diff -uNr gdc-0.23/d/asmstmt.cc gdc-0.24/d/asmstmt.cc --- gdc-0.23/d/asmstmt.cc 2007-03-04 18:29:17.000000000 +0100 +++ gdc-0.24/d/asmstmt.cc 2007-03-10 15:58:53.000000000 +0100 @@ -468,9 +468,7 @@ //printf("final: %.*s\n", code->insnTemplateLen, code->insnTemplate); tree insnt = build_string(code->insnTemplateLen, code->insnTemplate); -#if D_GCC_VER == 33 - expand_asm_operands(insnt, outputs.head, inputs.head, clobbers.head, 1, loc.filename, loc.linnum); -#elif D_GCC_VER == 34 +#if D_GCC_VER == 34 location_t gcc_loc = { loc.filename, loc.linnum }; expand_asm_operands(insnt, outputs.head, inputs.head, clobbers.head, 1, gcc_loc); #else diff -uNr gdc-0.23/d/ChangeLog gdc-0.24/d/ChangeLog --- gdc-0.23/d/ChangeLog 2007-03-06 05:15:06.000000000 +0100 +++ gdc-0.24/d/ChangeLog 2007-08-22 07:56:51.000000000 +0200 @@ -1,5 +1,413 @@ +2007-08-22 David Friedman + + Release GDC 0.24 + + --- + + * rdmd.d: Fix for Windows + +2007-08-21 David Friedman + + * GDC.html, History, README, gcc-mars.cc, gdc-version: + Update for 0.24 + + * rdmd.d, rdmd.1: New files. (Bugzilla 1152) + + * patch-build_gcc-4.0: Build universal rdmd. (Bugzilla 1152) + + * package/simple.sh: Install rdmd. (Bugzilla 1152) + Install man pages for MacOS build. + + * dmd-script: Apply Ander's patch to make -op apply + to interface files. (Bugzilla 1137) + + * d-lang.cc (d_parse_file): In -fall-sources mode, + only generate an interface file for the -fonly module. + + * phobos/internal/adi.d (_adReverseChar, _adReverseWchar): + Make sure stride difference is signed. + +2007-08-20 David Friedman + + * patch-gcc-4.1.x, patch-gcc-4.0.x: Fix botched patches. + +2007-08-05 David Friedman + + * d-codegen.cc (convertForArgument): Recognize + pointer arithmetic expression as reference. + (Bugzilla 1400) + + * d-glue.cc (DotVarExp::toElem): Do not NOP_EXPR + the result. (Bugzilla 1398) + +2007-07-27 David Friedman + + * phobos/std/stdio: Fix breakage from last commit. + (SF 1761989) + +2007-07-26 David Friedman + + * phobos/std/c/stdio.d: Change import for gcc.config + + * d-lang.cc: add flag_iso for target macros + + * patch-gcc-4.0.x: (gcc/tree-sra.c): Do not use SRA + on structs with aliased fields created for anonymous + unions. (Followup to Bugzilla 1034) + +2007-07-25 David Friedman + + * d-lang.cc: implement d_gcc_is_target_win32 + + * dmd/parse.c (parseLinkage): use d_gcc_is_target_win32 + + * d-dmd-gcc.h (d_gcc_is_target_win32): added + +2007-07-24 David Friedman + + Merge DMD 1.019 - 1.020 + + * dmd/attrib.c, dmd/cast.c, dmd/constfold.c, dmd/declaration.h, + dmd/expression.c, dmd/expression.h, dmd/func.c, dmd/idgen.c, + dmd/inline.c, dmd/interpret.c, dmd/mars.c, dmd/mars.h, + dmd/mtype.c, dmd/mtype.h, dmd/opover.c, dmd/parse.c, + dmd/template.c, dmd/template.h, dmd/tocsym.c, dmd/toir.c: Merge + + * phobos/internal/gc/gc.d, phobos/linux.mak, + phobos/std/demangle.d, phobos/std/format.d, phobos/std/loader.d, + phobos/std/socket.d, phobos/std/uni.d: Merge + +2007-07-22 David Friedman + + Merge DMD 1.015 - 1.018: + + * dmd/lexer.c (escapeSequence): Change vendor string. + + * dmd-script: Update documentation link + + * dmd/attrib.c, dmd/cast.c, dmd/class.c, dmd/declaration.c, + dmd/dsymbol.c, dmd/expression.c, dmd/expression.h, dmd/func.c, + dmd/hdrgen.h, dmd/idgen.c, dmd/init.c, dmd/init.h, dmd/inline.c, + dmd/interpret.c, dmd/lexer.c, dmd/mars.c, dmd/mars.h, + dmd/module.c, dmd/mtype.c, dmd/mtype.h, dmd/optimize.c, + dmd/parse.c, dmd/scope.c, dmd/scope.h, dmd/statement.c, + dmd/statement.h, dmd/staticassert.c, dmd/template.c: Merge + + * phobos/internal/dmain2.d, phobos/internal/gc/gcx.d, + phobos/internal/object.d, phobos/object.d, phobos/std/bind.d, + phobos/std/compiler.d, phobos/std/date.d, phobos/std/dateparse.d, + phobos/std/format.d, phobos/std/intrinsic.d, phobos/std/loader.d, + phobos/std/math2.d, phobos/std/metastrings.d, phobos/std/mmfile.d, + phobos/std/outbuffer.d, phobos/std/string.d, + phobos/std/windows/registry.d, phobos/win32.mak: Merge + + ---- + + * gdc_alloca.h: Support OpenBSD. (Bugzilla 1065) + + * patch-gcc-4.1.x (gcc/tree-sra.c): Do not use SRA + on structs with aliased fields created for anonymous + unions. (Bugzilla 1034) + +2007-07-19 David Friedman + + * patch-gcc-4.1.x (gcc/predict.c): Add null-pointer check. + (Bugzilla 1035) + + --- + + * phobos/std/format.d (doFormatPtr): Fix accidental + reversion from DMD merge. + + * d-codegen.cc (maybeSetUpBuiltin): Add some missing + instrinsics. + + * phobos/Makefile.am (MAIN_OBJS): Add gcc.builtins + module to get built-instruct initializers. + + * phobos/Makefile.in: Regenerated + + * d-lang.cc (d_parse_file): Call d_gcc_magic_module + for each module on the command line. + + * d-builtins2.cc (d_gcc_magic_builtins_module): output + declaration other than funcs + +2007-07-16 David Friedman + + * dmd/todt.c (StructLiteralExp::toDt): Use target_size_t + as in StructInitializer::toDt. + + Bugzilla 1032: + + * dmd/todt.c: Use DT_container for arrays, array elements, + and structs + + * dt.h, d-objfile.cc: Add DT_container / dtcontainer + +2007-07-14 David Friedman + + * d-codegen.cc (ArrayScope::setArrayExp, finish): Handle + constant lengths. (Bugzilla 1031) + +2007-07-13 David Friedman + + * d-codegen.cc (toElemLvalue): Use toElemLvalue recursively. + (Bugzilla 1191) + + * d-codegen.cc (twoFieldCtor): Only set TREE_READONLY if + TREE_CONSTANT + + * d-glue.cc (array_set_expr, AssocArrayLiteralExp::toElem, + (StructLiteralExp::toElem, NullExp::toElem): + Do not set TREE_READONLY. + + * d-glue.cc (NewExp::toElem): Do not set TREE_READONLY on + new array dimensions. + + * d-codegen.cc (darrayVal): Do not set TREE_READONLY. + (Bugzilla 1329) + + (delegateVal): ditto + + * d-codegen.cc (FieldVisitor::visit): Handle classes that + are forward references. (Bugzilla 1325) + + * dmd-script: Pass -J option correctly. (SF 1721435) + + * d-glue.cc (DeleteExp::toElem): Handle interfaces. + (SF 1721496) + + * d-decls.cc (VarDeclaration::toSymbol): Handle void initializer. + (SF 1749622) + + * d-glue.cc (AndAndExp, OrOrExp): Handle void second expression. + (SF 1689634) + + * phobos/gcc/cbridge_time.c (_d_gnu_cbridge_tza): Remove + daylight saving time offset from tm_gmtoff (Bugzilla 1208) + + * phobos/std/format.d (doFormat): Use original signature. Actual + work is done by new doFormatPtr. (Bugzilla 1109) + + * phobos/std/boxer.d: Use doFormatPtr + +2007-07-11 David Friedman + + * d-convert.cc (default_conversion): make public + (SF 1711324 and 1709602) + + * d-apple-gcc.c (build_function_call): re-enable some code + +2007-05-08 David Friedman + + * d-apple-gcc.c: Remove a variable that is now defined in d-lang.c + + * d-lang.cc: Fix for other GCC versions. + + * d-c-stubs.c: New file. + + * Make-lang.in (D_BORROWED_C_OBJS): Always use C_TARGET_OBJS. Add + stubs for C compiler to allow linking target-specific preprocessor + defines. + +2007-05-05 David Friedman + + * d-codegen.cc (hwi2toli, getTargetSizeConst): Fix 2x wide int to + long int conversion. + + * dmd/cast.c (implicitConvTo): Use GCC floating point + routines instead of native. + + * d-gcc-real.cc (toInt): Correctly convert to long integer + + * Make-lang.in (D_DMD_H): Add d/d-gcc-real.h + + * phobos/internal/dgccmain2.d: Print newline after error message + +2007-04-29 David Friedman + + Merge DMD 1.014: + + * dmd/aggregate.h, dmd/constfold.c, dmd/delegatize.c, dmd/enum.c, + dmd/enum.h, dmd/expression.c, dmd/expression.h, dmd/idgen.c, + dmd/inline.c, dmd/interpret.c, dmd/lexer.c, dmd/lexer.h, + dmd/mars.c, dmd/mtype.c, dmd/optimize.c, dmd/struct.c, + dmd/template.c, dmd/tocsym.c, dmd/todt.c, dmd/toobj.c, + dmd/typinf.c: Merge. + + * phobos/internal/gc/gc.d, phobos/internal/gc/gcx.d, + phobos/std/format.d, phobos/std.ddoc: Merge. + + * d-glue.d (StructLiteralExp::toElem): implement + * d-decls.d (EnumDeclaration::toInitializer): copy from tocsym.c + + ------------ + + Merge DMD 1.013: + + * dmd/cast.c, dmd/constfold.c, dmd/declaration.c, + dmd/expression.c, dmd/expression.h, dmd/interpret.c, dmd/link.c, + dmd/mars.c, dmd/mtype.c, dmd/opover.c, dmd/optimize.c, + dmd/parse.c, dmd/port.h, dmd/statement.c: Merge. + + * phobos/internal/aaA.d, phobos/internal/switch.d, + phobos/std/date.d, phobos/std/file.d, phobos/std/format: Merge. + + * d-codegen.h, d-codegen.cc: add _d_assocarrayliteralTp + * d-glue.cc (AssocArrayLiteralExp::toElem): Implement. + + * phobos/internal/aaA.d (_d_assocarrayliteralT): modified + to use pointers to keys, values. + + -------------- + + Merge DMD 1.012: + + * arraytypes.h, dmd/declaration.c, dmd/delegatize.c, + dmd/expression.c, dmd/expression.h, dmd/init.c, dmd/init.h, + dmd/inline.c, dmd/interpret.c, dmd/lexer.c, dmd/lexer.h, + dmd/mangle.c, dmd/mars.c, dmd/optimize.c, dmd/template.c, + dmd/template.h: Merge + + * phobos/internal/object.d: Merge + + * dmd/template.c (TemplateInstance::mangle): printf portability + + * d-glue.cc (AssocArrayLiteralExp::toElem): non-working implementation + +2007-04-28 David Friedman + + Merge DMD 1.011: + + * dmd/access.c, dmd/aggregate.h, dmd/arraytypes.h, dmd/attrib.c, + dmd/attrib.h, dmd/bit.c, dmd/cast.c, dmd/class.c, dmd/complex_t.h, + dmd/cond.c, dmd/cond.h, dmd/constfold.c, dmd/declaration.c, + dmd/declaration.h, dmd/delegatize.c, dmd/doc.c, dmd/doc.h, + dmd/dsymbol.c, dmd/dsymbol.h, dmd/dump.c, dmd/entity.c, + dmd/enum.c, dmd/enum.h, dmd/expression.c, dmd/expression.h, + dmd/func.c, dmd/hdrgen.c, dmd/hdrgen.h, dmd/html.c, dmd/html.h, + dmd/identifier.c, dmd/identifier.h, dmd/idgen.c, dmd/impcnvgen.c, + dmd/import.c, dmd/import.h, dmd/inifile.c, dmd/init.c, dmd/init.h, + dmd/inline.c, dmd/interpret.c, dmd/lexer.c, dmd/lexer.h, + dmd/link.c, dmd/macro.c, dmd/macro.h, dmd/mangle.c, dmd/mars.c, + dmd/mars.h, dmd/module.c, dmd/module.h, dmd/mtype.c, dmd/mtype.h, + dmd/opover.c, dmd/optimize.c, dmd/parse.c, dmd/parse.h, + dmd/scope.c, dmd/scope.h, dmd/statement.c, dmd/statement.h, + dmd/staticassert.c, dmd/staticassert.h, dmd/struct.c, + dmd/template.c, dmd/template.h, dmd/tocsym.c, dmd/todt.c, + dmd/toir.c, dmd/toir.h, dmd/toobj.c, dmd/total.h, dmd/typinf.c, + dmd/unialpha.c, dmd/utf.c, dmd/utf.h, dmd/version.c, dmd/version.h: + Merge + + * phobos/internal/gc/gc.d, phobos/internal/gc/gcx.d, + phobos/internal/object.d, phobos/std/c/locale.d, + phobos/std/stdio.d, phobos/std/windows/registry.d: Merge + + * dmd/expression.c: Comment out some logging code. + * d-builtins2.cc: Update and fix handling of built-in structs. + * d-codegen.cc, d-glue.cc: Update + + ---------------- + + Merge DMD 1.010: + + * dmd/aggregate.h, dmd/class.c, dmd/declaration.c, dmd/doc.c, + dmd/dsymbol.c, dmd/expression.c, dmd/expression.h, dmd/func.c, + dmd/interpret.c, dmd/mars.c, dmd/scope.c, dmd/statement.c, + dmd/template.c, dmd/template.h, dmd/todt.c: Merge. + + * phobos/internal/dmain2.d, phobos/internal/gc/gc.d, + phobos/internal/gc/gcx.d, phobos/internal/gc/testgc.d, + phobos/internal/object.d, phobos/object.d, + phobos/std/c/linux/linux.d, phobos/std/c/stdio.d, + phobos/std/file.d, phobos/std/gc.d, phobos/std/moduleinit.d, + phobos/std/regexp.d, phobos/std/stdio.d, phobos/std/string.d, + phobos/std.ddoc, phobos/win32.mak: Merge + + * dmd/mtype.c, phobos/internal/dgccmain2.d: Update. + * d-glue.cc (gcc_d_backend_init): Update. + + * phobos/config/unix-mid, phobos/std/c/unix/unix.d: Moved dirent + and stdio definitions out of configunix to std.c.unix.unix because + of compilation problems. + + * phobos/internal/gc/gcx.d (GC.realloc, GC.extend, GC.free): Clear + gcx.p_cache + + * phobos/std/stdio.d, phobos/frag-ac.in, phobos/configure.in: + Account for various configurations. + + * phobos/phobos-ver-syms.in: Remove GNU_Have_fwide + * phobos/configure: Regenerate + +2007-04-22 David Friedman + + * d-gcc-includes.h, d-lang.cc: Add target-specific preprocessor + symbols to the list of D version symbols. + + * d-glue.cc (NewExp::toElem): Use NewExp::newtype (Bugzilla 1038) + +2007-04-16 David Friedman + + Merge DMD 1.009 (from 1.007): + + * d-decls.c: Merge changes from dmd/tocsym.c + + * dmd/constfold.c, dmd/declaration.c, dmd/declaration.h, + dmd/expression.c, dmd/expression.h, dmd/init.c, dmd/interpret.c, + dmd/mangle.c, dmd/mars.c, dmd/mars.h, dmd/mtype.c, + dmd/optimize.c, dmd/statement.c, dmd/staticassert.c, + dmd/tocsym.c, dmd/todt.c: Merge changes. + + * phobos/std/path.d, phobos/std/string.d: Merge changes. + + ---- + + * d-builtins.c, d-builtins2.cc, d-lang.h: Reworked code to only + convert built-in functions when the gcc.builtins module is + imported. RECORD_TYPE is now converted to a TypeStruct. Fixed + problem that caused some functions to not be available. Support + targets builtins. + +2007-03-11 David Friedman + + * d-decls.cc (ClassDeclaration::toSymbol): Do not set TREE_READONLY. + (Bugzilla 1037) + +2007-03-10 David Friedman + + * d-codegen.cc (call): Handle CommaExp form of a delegate call + (Bugzilla 1043) + + * d-decls.cc (VarDeclaration::toSymbol): Partial fix for Bugzilla 1044 + + * dt.h, d-objfile.cc, dmd/typeinf.c: Only pad 32-bit words in RTTI if + needed. (Bugzilla 1045, 1046) + * dmd/toobj.c: update + + * d-glue.cc, d-objfile.cc: Additional GCC 3.3.x cleanup + + ---- + + * ChangeLog, History, Make-lang.in, asmstmt.cc, d-builtins.c, + d-codegen.cc, d-convert.cc, d-decls.cc, d-gcc-includes.h, + d-gcc-real.cc, d-glue.cc, d-gt.c, d-irstate.cc, d-lang.cc, + d-lang.h, d-misc.c, d-objfile.cc, d-spec.c, phobos/configure.in, + setup-gcc.sh: Remove support for GCC 3.3.x + + * phobos/configure: Regenerated + + * gcc-3.3.5-framework-headers.patch, + gcc-3.3.5-framework-linker.patch, patch-gcc-3.3.x, + patch-gcc-darwin-eh-3.3.x, patch-toplev-3.3.x, + phobos/config/ldfuncs33, phobos/config/noldfuncs33, + d-bi-attrs-33.h: Removed. + 2007-03-05 David Friedman + Release GDC 0.23 + * phobos/Makefile.am: Add all-local target to build libgphobos.a * phobos/Makefile.in: Regenrated diff -uNr gdc-0.23/d/d-apple-gcc.c gdc-0.24/d/d-apple-gcc.c --- gdc-0.23/d/d-apple-gcc.c 2006-06-24 02:52:45.000000000 +0200 +++ gdc-0.24/d/d-apple-gcc.c 2007-07-12 02:02:27.000000000 +0200 @@ -17,7 +17,7 @@ int flag_next_runtime; int flag_iasm_blocks; int flag_weak; -struct cpp_reader* parse_in; + int disable_typechecking_for_spec_flag; add_cpp_dir_path (cpp_dir *p, int chain) @@ -47,7 +47,7 @@ STRIP_TYPE_NOPS (function); /* Convert anything with function type to a pointer-to-function. */ gcc_assert(TREE_CODE (function) == FUNCTION_DECL); - /*if (TREE_CODE (function) == FUNCTION_DECL)*/ + if (TREE_CODE (function) == FUNCTION_DECL) { name = DECL_NAME (function); @@ -60,8 +60,8 @@ fundecl = function; function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); } - /*else - function = default_conversion (function);*/ + else + function = default_conversion (function); /* APPLE LOCAL begin mainline */ /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF expressions, like those used for ObjC messenger dispatches. */ diff -uNr gdc-0.23/d/d-bi-attrs-33.h gdc-0.24/d/d-bi-attrs-33.h --- gdc-0.23/d/d-bi-attrs-33.h 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/d-bi-attrs-33.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,1624 +0,0 @@ -static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_common_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_used_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_const_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree, - int, bool *)); -static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_section_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_tls_model_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, - tree, int, - bool *)); -static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_nonnull_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -static tree handle_nothrow_attribute PARAMS ((tree *, tree, tree, int, - bool *)); -/*not in gdc//static tree handle_cleanup_attribute PARAMS ((tree *, tree, tree, int, - bool *));*/ -static tree vector_size_helper PARAMS ((tree, tree)); - -/*not in gdc//static void check_function_nonnull PARAMS ((tree, tree));*/ -static void check_nonnull_arg PARAMS ((void *, tree, - unsigned HOST_WIDE_INT)); -static bool nonnull_check_p PARAMS ((tree, unsigned HOST_WIDE_INT)); -static bool get_nonnull_operand PARAMS ((tree, - unsigned HOST_WIDE_INT *)); - - -/* extra for gdc copy: */ -extern void check_function_arguments_recurse PARAMS ((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 },*/ - { NULL, 0, 0, false, false, false, NULL } -}; - -/* Give the specifications for the format attributes, used by C and all - descendents. */ - -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 (node, name, args, flags, no_add_attrs) - tree *node; - tree name; - tree args ATTRIBUTE_UNUSED; - int flags; - bool *no_add_attrs; -{ - tree *type = NULL; - if (DECL_P (*node)) - { - if (TREE_CODE (*node) == TYPE_DECL) - type = &TREE_TYPE (*node); - } - else - type = node; - - if (type) - { - if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *type = build_type_copy (*type); - TYPE_PACKED (*type) = 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. */ - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (pnode, name, args, flags, no_add_attrs) - 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_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (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 (node, name, args, flags, no_add_attrs) - tree *node; - tree name; - tree args ATTRIBUTE_UNUSED; - int flags; - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - tree *node; - tree name; - tree args; - 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; - - if (len > 4 && p[0] == '_' && p[1] == '_' - && p[len - 1] == '_' && p[len - 2] == '_') - { - char *newp = (char *) 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 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; - } - - *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 (node, name, args, flags, no_add_attrs) - 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_with_decl (decl, - "section attribute cannot be specified for local variables"); - *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_with_decl (*node, - "section of `%s' conflicts with previous declaration"); - *no_add_attrs = true; - } - else - DECL_SECTION_NAME (decl) = TREE_VALUE (args); - } - else - { - error_with_decl (*node, - "section attribute not allowed for `%s'"); - *no_add_attrs = true; - } - } - else - { - error_with_decl (*node, - "section attributes are not supported for this target"); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "aligned" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_aligned_attribute (node, name, args, flags, no_add_attrs) - 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_with_decl (decl, - "alignment may not be specified for `%s'"); - *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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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_with_decl (decl, - "`%s' defined both normally and as an alias"); - *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 (node, name, args, flags, no_add_attrs) - tree *node; - tree name; - tree args; - int flags ATTRIBUTE_UNUSED; - bool *no_add_attrs; -{ - tree decl = *node; - - if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (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 ("visibility arg not a string"); - *no_add_attrs = true; - return NULL_TREE; - } - if (strcmp (TREE_STRING_POINTER (id), "hidden") - && strcmp (TREE_STRING_POINTER (id), "protected") - && strcmp (TREE_STRING_POINTER (id), "internal") - && strcmp (TREE_STRING_POINTER (id), "default")) - { - error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); - *no_add_attrs = true; - return NULL_TREE; - } - } - - return NULL_TREE; -} - -/* Handle an "tls_model" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_tls_model_attribute (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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_with_decl (decl, - "`%s' attribute applies only to functions", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - else if (DECL_INITIAL (decl)) - { - error_with_decl (decl, - "can't set `%s' attribute after definition", - IDENTIFIER_POINTER (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 (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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_with_decl (decl, - "`%s' attribute applies only to functions", - IDENTIFIER_POINTER (name)); - *no_add_attrs = true; - } - else if (DECL_INITIAL (decl)) - { - error_with_decl (decl, - "can't set `%s' attribute after definition", - IDENTIFIER_POINTER (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 (node, name, args, flags, no_add_attrs) - 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; -} - -#if 0 -/* not in gdc */ -/* Handle a "cleanup" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_cleanup_attribute (node, name, args, flags, no_add_attrs) - 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 "deprecated" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_deprecated_attribute (node, name, args, flags, no_add_attrs) - 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 (node, name, args, flags, no_add_attrs) - 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) == 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 (type, bottom) - tree type, 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_VALUES (type)); - } - else if (TREE_CODE (type) == FUNCTION_TYPE) - { - inner = vector_size_helper (TREE_TYPE (type), bottom); - outer = build_function_type (inner, TYPE_VALUES (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 (node, name, args, flags, no_add_attrs) - 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. Veryify 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 (attrs, params) - 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 (args, param_num) - 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 (ctx, param, param_num) - 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 (arg_num_expr, valp) - 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 (node, name, args, flags, no_add_attrs) - 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 */ -/* Check for valid arguments being passed to a function. */ -void -check_function_arguments (attrs, params) - 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 (callback, ctx, param, param_num) - void (*callback) PARAMS ((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.23/d/d-builtins2.cc gdc-0.24/d/d-builtins2.cc --- gdc-0.23/d/d-builtins2.cc 2007-02-17 04:47:23.000000000 +0100 +++ gdc-0.24/d/d-builtins2.cc 2007-07-20 04:27:39.000000000 +0200 @@ -24,8 +24,11 @@ #include "symbol.h" #include "d-codegen.h" -Array d_bi_types; -Array d_bi_funcs; +static ListMaker bi_fn_list; + +// Necessary for built-in struct types +static Array builtin_converted_types; +static Array builtin_converted_decls; static Type * gcc_type_to_d_type(tree t); @@ -34,11 +37,6 @@ void d_bi_init(int nt, int nb) { - d_bi_types.setDim(nt); - d_bi_types.zero(); - d_bi_funcs.setDim(nb); - d_bi_funcs.zero(); - // assumes va_list_type_node already built d_gcc_builtin_va_list_d_type = gcc_type_to_d_type(va_list_type_node); if (! d_gcc_builtin_va_list_d_type) { @@ -153,83 +151,100 @@ } break; case RECORD_TYPE: - // cheat by making a bye array of the same size -- this should - // be okay for the builtin functions. - d = new TypeSArray(Type::tuns8, - new IntegerExp(0, gen.getTargetSizeConst( TYPE_SIZE_UNIT( t )), - Type::tindex)); - d->ctype = t; + { + for (unsigned i = 0; i < builtin_converted_types.dim; i += 2) + { + tree ti = (tree) builtin_converted_types.data[i]; + if (ti == t) + return (Type *) builtin_converted_types.data[i + 1]; + } + + const char * name; + char name_buf[64]; + static int serial; + + if ( TYPE_NAME(t) ) + name = IDENTIFIER_POINTER( DECL_NAME( TYPE_NAME( t ))); + else + { + snprintf(name_buf, sizeof(name_buf), "__bi_type_%d", ++serial); + name = name_buf; + } + + StructDeclaration * sd = new StructDeclaration(0, Lexer::idPool(name)); + /* The gcc.builtins module may not exist yet, so cannot set + sd->parent here. */ + sd->structsize = int_size_in_bytes( t ); + sd->alignsize = TYPE_ALIGN_UNIT( t ); + sd->sizeok = 1; + + d = new TypeStruct(sd); + sd->type = d; + sd->handle = d->pointerTo(); + + /* Does not seem necessary to convert fields, but the + members field must be non-null for the above size + setting to stick. */ + sd->members = new Array; + + d->ctype = t; + + builtin_converted_types.push(t); + builtin_converted_types.push(d); + builtin_converted_decls.push(sd); + } return d; + case FUNCTION_TYPE: + { + int varargs = 1; + Type * ret = gcc_type_to_d_type(TREE_TYPE(t)); + if (! ret) + return NULL; + + tree t_arg_types = TYPE_ARG_TYPES(t); + Arguments * args = new Arguments; + args->reserve(list_length(t_arg_types)); + for (tree tl = t_arg_types; tl != NULL_TREE; tl = TREE_CHAIN(tl)) + { + tree ta = TREE_VALUE(tl); + if (ta != void_type_node) + { + unsigned io = STCin; + + if ( TREE_CODE( ta ) == REFERENCE_TYPE ) + { + ta = TREE_TYPE( ta ); + io = STCref; + } + + Type * d_arg_type = gcc_type_to_d_type(ta); + if (! d_arg_type) + return NULL; + args->push(new Argument(io, d_arg_type, NULL, NULL)); + } + else + varargs = 0; + } + d = new TypeFunction(args, ret, varargs, LINKc); + return d; + Lfail: + delete args; + } + break; default: break; } return NULL; } -void -d_bi_builtin_type(int ti, tree t) -{ - Type * d = gcc_type_to_d_type(t); - if (d) { - d_bi_types.data[ti] = d; - } else { - // warning("cannot create builtin type %d\n", ti); - } -} - void -d_bi_builtin_func_type(int ti, tree t, int ri, int ai1, int ai2, int ai3, int ai4, int ai5, int ai6, int va) +d_bi_builtin_func(tree decl) { - Arguments * args = new Arguments; - Type * rd = (Type *) d_bi_types.data[ri]; - if (! rd) - return; - - int aia[6] = { ai1, ai2, ai3, ai4, ai5, ai6 }; - for (int i = 0; i < 6; i++) { - Type * ad; - int ai = aia[i]; - enum InOut io = In; - - if (ai == -1) - break; - - ad = (Type *) d_bi_types.data[ai]; - if (! ad) - return; - - if ( TREE_CODE( ad->toCtype() ) == REFERENCE_TYPE ) { - ad = ad->next; - io = InOut; - } - - args->push( new Argument(io, ad, NULL, NULL) ); - } - - // DMD doesn't like this. Nothing usable actually uses it, though - if (args->dim == 0 && va) - return; - - TypeFunction * dtf = new TypeFunction(args, rd, va, LINKc); - dtf->ctype = t; - d_bi_types.data[ti] = dtf; + bi_fn_list.cons(NULL_TREE, decl); } -void -d_bi_builtin_func(int bi, const char *name, int ti, tree decl) -{ - TypeFunction * df = (TypeFunction *) d_bi_types.data[ti]; - if (! df) { - // warning("cannot create builtin %s\n", name); - return; - } - FuncDeclaration * func = new FuncDeclaration(0, 0, - Lexer::idPool(name), STCextern, df); - func->isym = new Symbol; - func->isym->Stree = decl; - d_bi_funcs.data[bi] = func; -} + // std.stdarg is different: it expects pointer types (i.e. _argptr) /* @@ -274,7 +289,8 @@ tf = (TypeFunction *) fd->type; assert( tf->ty == Tfunction && tf->parameters && tf->parameters->dim >= 1 ); - ((Argument*) tf->parameters->data[0])->inout = In; + ((Argument*) tf->parameters->data[0])->storageClass &= ~(STCin|STCout|STCref); + ((Argument*) tf->parameters->data[0])->storageClass |= STCin; } } } @@ -287,10 +303,36 @@ { Array * funcs = new Array; - for (unsigned i = 0; i < d_bi_funcs.dim; i++) { - void * p = d_bi_funcs.data[i]; - if (p) - funcs->push( p ); + for (unsigned i = 0; i < builtin_converted_decls.dim ; ++i) + { + Dsymbol * sym = (Dsymbol *) builtin_converted_decls.data[i]; + sym->parent = m; + // Currently, there is no need to run semantic, but we do + // want to output inits, etc. + funcs->push( sym ); + } + + for (tree n = bi_fn_list.head; n; n = TREE_CHAIN(n)) + { + tree decl = TREE_VALUE(n); + const char * name = IDENTIFIER_POINTER(DECL_NAME(decl)); + TypeFunction * dtf = (TypeFunction *) gcc_type_to_d_type(TREE_TYPE(decl)); + if (! dtf) + { + //warning("cannot create built in function type for %s", name); + continue; + } + if (dtf->parameters && dtf->parameters->dim == 0 && dtf->varargs) + { + //warning("one-arg va problem: %s", name); + continue; + } + FuncDeclaration * func = new FuncDeclaration(0, 0, + Lexer::idPool(name), STCextern, dtf); + func->isym = new Symbol; + func->isym->Stree = decl; + + funcs->push( func ); } Type * d = gcc_type_to_d_type(va_list_type_node); diff -uNr gdc-0.23/d/d-builtins.c gdc-0.24/d/d-builtins.c --- gdc-0.23/d/d-builtins.c 2007-01-31 01:18:31.000000000 +0100 +++ gdc-0.24/d/d-builtins.c 2007-04-21 22:34:31.000000000 +0200 @@ -20,10 +20,8 @@ #include "config.h" #include "system.h" -#if D_GCC_VER >= 34 #include "coretypes.h" #include "tm.h" -#endif #include "intl.h" #include "tree.h" #include "flags.h" @@ -57,9 +55,7 @@ #endif -#if D_GCC_VER < 34 -#include "d-bi-attrs-33.h" -#elif D_GCC_VER < 40 +#if D_GCC_VER < 40 # ifdef D_GCC_VER341 # include "d-bi-attrs-341.h" # else @@ -99,9 +95,6 @@ #define DEF_ATTR_INT(ENUM, VALUE) ENUM, #define DEF_ATTR_IDENT(ENUM, STRING) ENUM, #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM, -#if D_GCC_VER == 33 -#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum. */ -#endif #include "builtin-attrs.def" #undef DEF_ATTR_NULL_TREE #undef DEF_ATTR_INT @@ -193,7 +186,6 @@ fnattrs); built_in_decls[(int) fncode] = decl; - d_bi_builtin_func((int) fncode, name, (int) fntype_index, decl); if (implicit_p) implicit_built_in_decls[(int) fncode] = decl; } @@ -267,6 +259,8 @@ const_string_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); + void_list_node = tree_cons(NULL_TREE, void_type_node, NULL_TREE); + #if D_GCC_VER >= 40 /* WINT_TYPE is a C type name, not an itk_ constant or something useful like that... */ @@ -274,22 +268,18 @@ pid_type_node = lookup_C_type_name(PID_TYPE); #endif -#define DDI(ENUM) d_bi_builtin_type((int) ENUM, builtin_types[ENUM]); - #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ - builtin_types[(int) ENUM] = VALUE; DDI(ENUM); + builtin_types[(int) ENUM] = VALUE; #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ builtin_types[(int) ENUM] \ = build_function_type (builtin_types[(int) RETURN], \ - void_list_node); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, -1,-1,-1,-1,-1,-1, 0); + void_list_node); #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \ builtin_types[(int) ENUM] \ = build_function_type (builtin_types[(int) RETURN], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG1], \ - void_list_node)); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1,-1,-1,-1,-1,-1, 0); + void_list_node)); #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \ builtin_types[(int) ENUM] \ = build_function_type \ @@ -298,8 +288,7 @@ builtin_types[(int) ARG1], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG2], \ - void_list_node))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2,-1,-1,-1,-1, 0); + void_list_node))); #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ builtin_types[(int) ENUM] \ = build_function_type \ @@ -310,8 +299,7 @@ builtin_types[(int) ARG2], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG3], \ - void_list_node)))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3,-1,-1,-1, 0); + void_list_node)))); #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ builtin_types[(int) ENUM] \ = build_function_type \ @@ -325,8 +313,7 @@ builtin_types[(int) ARG3], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG4], \ - void_list_node))))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, ARG4,-1,-1, 0); + void_list_node))))); #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \ builtin_types[(int) ENUM] \ = build_function_type \ @@ -342,8 +329,7 @@ builtin_types[(int) ARG4], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG5],\ - void_list_node)))))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, ARG4, ARG5,-1, 0); + void_list_node)))))); #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ ARG6) \ builtin_types[(int) ENUM] \ @@ -363,19 +349,16 @@ builtin_types[(int) ARG5], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG6],\ - void_list_node))))))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, 0); + void_list_node))))))); #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ builtin_types[(int) ENUM] \ - = build_function_type (builtin_types[(int) RETURN], NULL_TREE); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, -1, -1, -1, -1, -1, -1, 1); + = build_function_type (builtin_types[(int) RETURN], NULL_TREE); #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ builtin_types[(int) ENUM] \ = build_function_type (builtin_types[(int) RETURN], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG1], \ - NULL_TREE)); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, -1, -1, -1, -1, -1, 1); + NULL_TREE)); #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \ builtin_types[(int) ENUM] \ @@ -385,8 +368,7 @@ builtin_types[(int) ARG1], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG2], \ - NULL_TREE))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, -1, -1, -1, -1, 1); + NULL_TREE))); #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \ builtin_types[(int) ENUM] \ @@ -398,8 +380,7 @@ builtin_types[(int) ARG2], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG3], \ - NULL_TREE)))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, -1, -1, -1, 1); + NULL_TREE)))); #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \ builtin_types[(int) ENUM] \ = build_function_type \ @@ -412,8 +393,7 @@ builtin_types[(int) ARG3], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG4],\ - NULL_TREE))))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, ARG4, -1, -1, 1); + NULL_TREE))))); #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, \ ARG5) \ @@ -431,13 +411,12 @@ builtin_types[(int) ARG4], \ tree_cons (NULL_TREE, \ builtin_types[(int) ARG5],\ - NULL_TREE)))))); \ - d_bi_builtin_func_type((int) ENUM, builtin_types[(int) ENUM], (int) RETURN, (int) ARG1, ARG2, ARG3, ARG4, ARG5, -1, 1); + NULL_TREE)))))); #define DEF_POINTER_TYPE(ENUM, TYPE) \ builtin_types[(int) ENUM] \ - = build_pointer_type (builtin_types[(int) TYPE]); DDI(ENUM) + = build_pointer_type (builtin_types[(int) TYPE]); #include "builtin-types.def" #undef DEF_PRIMITIVE_TYPE #undef DEF_FUNCTION_TYPE_1 @@ -456,38 +435,7 @@ d_init_attributes (); -#if D_GCC_VER == 33 -#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \ - BOTH_P, FALLBACK_P, NONANSI_P, ATTRS) \ - if (NAME) \ - { \ - tree decl; \ - \ - if (strncmp (NAME, "__builtin_", strlen ("__builtin_")) != 0) \ - abort (); \ - \ - /*if (!BOTH_P)*/ \ - decl = builtin_function (NAME, builtin_types[TYPE], ENUM, \ - CLASS, \ - (FALLBACK_P \ - ? (NAME + strlen ("__builtin_")) \ - : NULL), \ - built_in_attributes[(int) ATTRS]); \ - /*else*/ \ - /*decl = builtin_function_2 (NAME,*/ \ - /* NAME + strlen ("__builtin_"),*/ \ - /* builtin_types[TYPE],*/ \ - /* builtin_types[LIBTYPE],*/ \ - /* ENUM,*/ \ - /* CLASS,*/ \ - /* FALLBACK_P,*/ \ - /* NONANSI_P,*/ \ - /* built_in_attributes[(int) ATTRS]);*/ \ - \ - built_in_decls[(int) ENUM] = decl; \ - d_bi_builtin_func((int) ENUM, NAME, (int) TYPE, decl); \ - } -#elif D_GCC_VER == 34 +#if D_GCC_VER == 34 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, \ BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT) \ if (NAME) \ @@ -516,7 +464,6 @@ /* built_in_attributes[(int) ATTRS]);*/ \ \ built_in_decls[(int) ENUM] = decl; \ - d_bi_builtin_func((int) ENUM, NAME, (int) TYPE, decl); \ if (IMPLICIT) \ implicit_built_in_decls[(int) ENUM] = decl; \ } @@ -550,7 +497,6 @@ /* built_in_attributes[(int) ATTRS]);*/ \ \ built_in_decls[(int) ENUM] = decl; \ - d_bi_builtin_func((int) ENUM, NAME, (int) TYPE, decl); \ if (IMPLICIT) \ implicit_built_in_decls[(int) ENUM] = decl; \ } @@ -625,6 +571,8 @@ else decl_attributes (&decl, NULL_TREE, 0); + d_bi_builtin_func(decl); + return decl; } diff -uNr gdc-0.23/d/d-codegen.cc gdc-0.24/d/d-codegen.cc --- gdc-0.23/d/d-codegen.cc 2007-03-04 18:29:00.000000000 +0100 +++ gdc-0.24/d/d-codegen.cc 2007-08-05 21:31:55.000000000 +0200 @@ -435,8 +435,8 @@ if ( isArgumentReferenceType(arg) ) { tree exp_tree = this->toElemLvalue(exp); // front-end already sometimes automatically takes the address - // TODO: find out why... and can this be confused by a non-zero SymOff - if (exp->op != TOKaddress && exp->op != TOKsymoff) + // TODO: Make this safer? Can this be confused by a non-zero SymOff? + if (exp->op != TOKaddress && exp->op != TOKsymoff && exp->op != TOKadd) return addressOf( exp_tree ); else return exp_tree; @@ -549,8 +549,8 @@ switch (exp_type->toBasetype()->ty) { case Taarray: - // should be... - //result = libCall(LIBCALL_AALEN, 1, & exp_tree); + // Shouldn't this be... + // result = libCall(LIBCALL_AALEN, 1, & exp_tree); result = component(exp_tree, TYPE_FIELDS(TREE_TYPE(exp_tree))); break; @@ -701,6 +701,22 @@ return build_real(type_node, converted_val); } +xdmd_integer_t +IRState::hwi2toli(HOST_WIDE_INT low, HOST_WIDE_INT high) +{ + uinteger_t result; + if (sizeof(HOST_WIDE_INT) < sizeof(xdmd_integer_t)) + { + gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(xdmd_integer_t)); + result = (unsigned HOST_WIDE_INT) low; + result += ((uinteger_t) (unsigned HOST_WIDE_INT) high) << HOST_BITS_PER_WIDE_INT; + } + else + result = low; + return result; +} + + #if D_GCC_VER >= 40 tree IRState::binding(tree var_chain, tree body) @@ -760,6 +776,16 @@ tree IRState::call(Expression * expr, /*TypeFunction * func_type, */ Array * arguments) { + // Calls to delegates can sometimes look like this: + if (expr->op == TOKcomma) + { + CommaExp * ce = (CommaExp *) expr; + VarExp * ve; + expr = ce->e1; + gcc_assert( ce->e2->op == TOKvar && + ((VarExp *) ce->e2)->var->isFuncDeclaration() ); + } + Type* t = expr->type->toBasetype(); TypeFunction* tf = NULL; tree callee = expr->toElem(this); @@ -928,7 +954,8 @@ "_d_monitorenter", "_d_monitorexit", "_d_criticalenter", "_d_criticalexit", "_d_throw", - "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring" + "_d_switch_string", "_d_switch_ustring", "_d_switch_dstring", + "_d_assocarrayliteralTp" }; static FuncDeclaration * libcall_decls[LIBCALL_count]; @@ -949,10 +976,6 @@ case LIBCALL_ARRAYCAST: // replace the function declaration break; -#if D_GCC_VER <= 33 - // may be safe for GCC 3.4, haven't tried it - case LIBCALL_ADCMPCHAR: -#endif default: // don't replace return; @@ -1160,6 +1183,13 @@ arg_types.push(t); return_type = Type::tint32; break; + case LIBCALL_ASSOCARRAYLITERALTP: + arg_types.push(Type::typeinfo->type); + arg_types.push(Type::tsize_t); + arg_types.push(Type::tvoid->pointerTo()); + arg_types.push(Type::tvoid->pointerTo()); + return_type = Type::tvoid->pointerTo(); + break; default: abort(); } @@ -1170,7 +1200,7 @@ Arguments * args = new Arguments; args->setDim( arg_types.dim ); for (unsigned i = 0; i < arg_types.dim; i++) - args->data[i] = new Argument( In, (Type *) arg_types.data[i], + args->data[i] = new Argument( STCin, (Type *) arg_types.data[i], NULL, NULL); tf->parameters = args; } @@ -1208,12 +1238,14 @@ case BUILT_IN_LABS: case BUILT_IN_LLABS: case BUILT_IN_IMAXABS: - /* The above are required for both gcc3.3 and 3.4. The below - are only needed for gcc3.3, but we might as well use it - for gcc3.4 as well. */ + /* The above are required for both 3.4. Not sure about later + versions. */ + /* OLDOLDOLD below supposedly for 3.3 only */ + /* case BUILT_IN_FABS: case BUILT_IN_FABSL: case BUILT_IN_FABSF: + */ op = TREE_VALUE( TREE_OPERAND( call_exp, 1 )); t = build1(ABS_EXPR, TREE_TYPE(op), op); return d_convert_basic(TREE_TYPE(call_exp), t); @@ -1326,6 +1358,7 @@ // %% types should be correct, but should still check.. // %% 64-bit.. return call_exp; + //YOWZA1 #if D_GCC_VER >= 34 return buildCall(TREE_TYPE(call_exp), built_in_decls[intrinsic == INTRINSIC_BSF ? BUILT_IN_CTZ : BUILT_IN_CLZ], @@ -1476,7 +1509,6 @@ CtorEltMaker ce; TREE_TYPE( ctor ) = type; - TREE_READONLY( ctor ) = 1; TREE_STATIC( ctor ) = 0; // can be set by caller if needed TREE_CONSTANT( ctor ) = 0; // " len_field = TYPE_FIELDS( TREE_TYPE( ctor )); @@ -1498,7 +1530,6 @@ CtorEltMaker ce; TREE_TYPE( ctor ) = type; - TREE_READONLY( ctor ) = 1; TREE_STATIC( ctor ) = 0; // can be set by caller if needed TREE_CONSTANT( ctor ) = 0; // " len_field = TYPE_FIELDS( TREE_TYPE( ctor )); @@ -1597,7 +1628,6 @@ tree IRState::floatMod(tree a, tree b, Type * d_type) { -#if D_GCC_VER >= 34 enum built_in_function fn; switch (d_type->toBasetype()->ty) { case Tfloat32: @@ -1628,56 +1658,6 @@ addressOf(decl), tree_cons(NULL_TREE, a, tree_cons(NULL_TREE, b, NULL_TREE))); -#else - // could move this to d-builtins.c - static tree float_mod_decls[3]; - static const char * decl_names[3] = { "fmodf", "fmod", "fmodl" }; - tree the_float_type; - int decl_idx; - switch (d_type->toBasetype()->ty) { - case Tfloat32: - case Timaginary32: - decl_idx = 0; - the_float_type = float_type_node; - break; - case Tfloat64: - case Timaginary64: - no_long_double: - decl_idx = 1; - the_float_type = double_type_node; - break; - case Tfloat80: - case Timaginary80: - if (! haveLongDouble()) - goto no_long_double; - decl_idx = 2; - the_float_type = long_double_type_node; - break; - default: - ::error("tried to perform floating-point modulo division on %s", - d_type->toChars()); - return error_mark_node; - } - - tree decl = float_mod_decls[decl_idx]; - if (! decl) { - tree func_type = build_function_type(the_float_type, - tree_cons(NULL_TREE, the_float_type, - tree_cons(NULL_TREE, the_float_type, - tree_cons(NULL_TREE, void_type_node, NULL_TREE)))); - decl = build_decl(FUNCTION_DECL, get_identifier(decl_names[decl_idx]), - func_type); - DECL_EXTERNAL(decl) = 1; - float_mod_decls[decl_idx] = decl; - } - // %% assuming no arg conversion needed - // %% bypassing buildCall since this shouldn't have - // side effects - return buildCall(TREE_TYPE(TREE_TYPE(decl)), - addressOf(decl), - tree_cons(NULL_TREE, a, - tree_cons(NULL_TREE, b, NULL_TREE))); -#endif } tree @@ -1694,8 +1674,9 @@ target_size_t result; if (sizeof(HOST_WIDE_INT) < sizeof(target_size_t)) { - result = TREE_INT_CST_LOW( t ); - result += ((target_size_t) TREE_INT_CST_HIGH( t )) + gcc_assert(sizeof(HOST_WIDE_INT) * 2 == sizeof(target_size_t)); + result = (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW( t ); + result += ((target_size_t) (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH( t )) << HOST_BITS_PER_WIDE_INT; } else @@ -1749,7 +1730,6 @@ tree func_field = NULL_TREE; CtorEltMaker ce; - TREE_READONLY( ctor ) = 1; if (type) { TREE_TYPE( ctor ) = type; obj_field = TYPE_FIELDS( type ); @@ -1897,9 +1877,9 @@ CtorEltMaker ce; TREE_TYPE( ctor ) = rec_type; - TREE_READONLY( ctor ) = 1; TREE_STATIC( ctor ) = (storage_class & STCstatic) != 0; - TREE_CONSTANT( ctor ) = (storage_class & STCconst) != 0; + TREE_CONSTANT( ctor ) = (storage_class & STCconst) != 0; + TREE_READONLY( ctor ) = (storage_class & STCconst) != 0; ft1 = TYPE_FIELDS( rec_type ); ft2 = TREE_CHAIN( ft1 ); @@ -2014,6 +1994,9 @@ //have_intrinsic = true; #endif break; + case INTRINSIC_INP: + case INTRINSIC_INPW: + case INTRINSIC_INPL: case INTRINSIC_OUTP: case INTRINSIC_OUTPW: case INTRINSIC_OUTPL: @@ -2064,7 +2047,7 @@ return true; } - if ( decl->isOut() || + if ( decl->isOut() || decl->isRef() || ( decl->isParameter() && base_type->ty == Tsarray ) ) { return true; } @@ -2100,7 +2083,7 @@ return true; } - if ( (arg->inout == Out) || (arg->inout == InOut) || base_type->ty == Tsarray ) { + if ( (arg->storageClass & (STCout | STCref)) || base_type->ty == Tsarray ) { return true; } @@ -2113,7 +2096,7 @@ tree arg_type = arg->type->toCtype(); if ( isArgumentReferenceType( arg )) { return build_reference_type( arg_type ); - } else if (arg->inout == Lazy) { + } else if (arg->storageClass & STClazy) { TypeFunction *tf = new TypeFunction(NULL, arg->type, 0, LINKd); TypeDelegate *t = new TypeDelegate(tf); return t->merge()->toCtype(); @@ -2399,7 +2382,7 @@ AddrOfExpr aoe; tree args[4]; - args[0] = this->addressOf( e1->toElem(this) ); + args[0] = this->addressOf( this->toElemLvalue(e1) ); args[1] = this->typeinfoReference(key_type); args[2] = this->integerConstant( array_type->next->size(), Type::tsize_t ); args[3] = aoe.set(this, this->convertTo( e2, key_type )); @@ -2799,11 +2782,9 @@ void IRState::doAsm(tree insn_tmpl, tree outputs, tree inputs, tree clobbers) { -#if D_GCC_VER == 33 - expand_asm_operands(insn_tmpl, outputs, inputs, clobbers, 1, input_filename, lineno); -#elif D_GCC_VER == 34 +#if D_GCC_VER < 40 expand_asm_operands(insn_tmpl, outputs, inputs, clobbers, 1, input_location); -#elif D_GCC_VER >= 40 +#else tree t = d_build_asm_stmt(insn_tmpl, outputs, inputs, clobbers); ASM_VOLATILE_P( t ) = 1; addExp( t ); @@ -2961,22 +2942,13 @@ tree ArrayScope::setArrayExp(tree e, Type * t) { - if ( v) { - /* Use STCconst to tell that we should use v->init instead - of the runtime length of the array expression. */ - if (v->init && (v->storage_class & STCconst)) - { - // This code only handles simple assignment. - Expression * init_exp = v->init->toExpression(); - assert(init_exp); - DECL_INITIAL(v->toSymbol()->Stree) = init_exp->toElem(irs); - } - else - { - if (t->toBasetype()->ty != Tsarray) // %% - e = irs->maybeMakeTemp(e); - DECL_INITIAL(v->toSymbol()->Stree) = irs->arrayLength(e, t); - } + /* If STCconst, the value will be assigned in d-decls.cc + of the runtime length of the array expression. */ + if (v && ! (v->storage_class & STCconst)) + { + if (t->toBasetype()->ty != Tsarray) // %% + e = irs->maybeMakeTemp(e); + DECL_INITIAL(v->toSymbol()->Stree) = irs->arrayLength(e, t); } return e; } @@ -2985,9 +2957,13 @@ ArrayScope::finish(tree e) { if (v) - return gen.binding(v->toSymbol()->Stree, e); - else - return e; + { + tree t = v->toSymbol()->Stree; + if (TREE_CODE(t) == VAR_DECL) + return gen.binding(v->toSymbol()->Stree, e); + } + + return e; } void @@ -3000,6 +2976,6 @@ doFields(& decl->fields, decl); - if (class_decl) + if (class_decl && class_decl->vtblInterfaces) doInterfaces(class_decl->vtblInterfaces, decl); } diff -uNr gdc-0.23/d/d-codegen.h gdc-0.24/d/d-codegen.h --- gdc-0.23/d/d-codegen.h 2007-02-20 01:36:58.000000000 +0100 +++ gdc-0.24/d/d-codegen.h 2007-05-05 15:23:21.000000000 +0200 @@ -73,6 +73,7 @@ LIBCALL_SWITCH_STRING, LIBCALL_SWITCH_USTRING, LIBCALL_SWITCH_DSTRING, + LIBCALL_ASSOCARRAYLITERALTP, LIBCALL_count } LibCall; @@ -170,6 +171,8 @@ static tree floatConstant(const real_t & value, TypeBasic * target_type ); + static xdmd_integer_t hwi2toli(HOST_WIDE_INT low, HOST_WIDE_INT high); + // ** Routines for built in structured types static tree realPart(tree c); diff -uNr gdc-0.23/d/d-convert.cc gdc-0.24/d/d-convert.cc --- gdc-0.23/d/d-convert.cc 2007-01-29 03:24:22.000000000 +0100 +++ gdc-0.24/d/d-convert.cc 2007-07-12 02:02:27.000000000 +0200 @@ -24,7 +24,7 @@ enumeral types or short or char, to int. In addition, manifest constants symbols are replaced by their values. */ -static tree +extern "C" tree default_conversion (tree exp) { #if 0 @@ -287,11 +287,7 @@ case NEGATE_EXPR: case ABS_EXPR: case FLOAT_EXPR: -#if D_GCC_VER == 33 - case FFS_EXPR: -#else - // nothing %% there may be other things wrong for gcc 3.4 -#endif + // %% there may be other things wrong... /* These don't change whether an object is nonzero or zero. */ return d_truthvalue_conversion (TREE_OPERAND (expr, 0)); diff -uNr gdc-0.23/d/d-c-stubs.c gdc-0.24/d/d-c-stubs.c --- gdc-0.23/d/d-c-stubs.c 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.24/d/d-c-stubs.c 2007-05-09 02:09:26.000000000 +0200 @@ -0,0 +1,37 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "flags.h" +#include "convert.h" +#include "cpplib.h" + +add_cpp_dir_path (cpp_dir *p, int chain) +{ + /* nothing */ +} + +void +add_path (char *path, int chain, int cxx_aware, bool user_supplied_p) +{ + /* nothing */ +} + +void +builtin_define_with_value (const char *macro, const char *expansion, int is_str) +{ + /* nothing */ +} + +enum { unused } c_language; + +enum cpp_ttype +c_lex (tree *value) +{ +#if D_GCC_VER >= 40 + gcc_assert(0); +#else + return 0; +#endif +} diff -uNr gdc-0.23/d/d-decls.cc gdc-0.24/d/d-decls.cc --- gdc-0.23/d/d-decls.cc 2007-02-18 18:22:58.000000000 +0100 +++ gdc-0.24/d/d-decls.cc 2007-07-13 20:40:28.000000000 +0200 @@ -202,6 +202,9 @@ var_decl = build_decl(decl_kind, get_identifier(ident_to_use), gen.trueDeclarationType( this )); + csym = new Symbol(); + csym->Stree = var_decl; + if (decl_kind != CONST_DECL) { if (isDataseg()) uniqueName(this, var_decl, ident_to_use); @@ -224,17 +227,21 @@ /* Not sure how much of an optimization this is... It is needed for foreach loops on tuples which 'declare' the index variable as a constant for each iteration. */ - Expression * e; + Expression * e = NULL; if (init) { - e = init->toExpression(); - assert(e != NULL); + if (! init->isVoidInitializer()) + { + e = init->toExpression(); + assert(e != NULL); + } } else e = type->defaultInit(); - - DECL_INITIAL( var_decl ) = e->toElem(g.irs); + + if (e) + DECL_INITIAL( var_decl ) = e->toElem(g.irs); } // Can't set TREE_STATIC, etc. until we get to toObjFile as this could be @@ -273,10 +280,6 @@ else if (isExport()) gen.addDeclAttribute( var_decl, "dllexport" ); #endif - - csym = new Symbol(); - csym->Stree = var_decl; - } return csym; } @@ -329,6 +332,14 @@ /************************************* */ +Symbol *FuncAliasDeclaration::toSymbol() +{ + return funcalias->toSymbol(); +} + +/************************************* + */ + // returns a FUNCTION_DECL tree Symbol *FuncDeclaration::toSymbol() { @@ -606,9 +617,7 @@ DECL_IGNORED_P(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 //needed on some targets to avoid "causes a section type conflict" D_DECL_ONE_ONLY(thunk_decl) = D_DECL_ONE_ONLY(target_func_decl); if ( D_DECL_ONE_ONLY(thunk_decl) ) @@ -677,7 +686,7 @@ g.ofile->setupStaticStorage(this, decl); TREE_CONSTANT( decl ) = 0; // DMD puts this into .data, not .rodata... - TREE_READONLY( decl ) = 1; // Non-constant data, but still won't be assigned to. + TREE_READONLY( decl ) = 0; } return csym; } @@ -840,7 +849,31 @@ } return sinit; } - + +Symbol *EnumDeclaration::toInitializer() +{ + Symbol *s; + Classsym *stag; + + if (!sinit) + { + Identifier *ident_save = ident; + if (!ident) + { static int num; + char name[6 + sizeof(num) * 3 + 1]; + snprintf(name, sizeof(name), "__enum%d", ++num); + ident = Lexer::idPool(name); + } + s = toSymbolX("__init", SCextern, 0, "Z"); + ident = ident_save; + s->Sfl = FLextern; + s->Sflags |= SFLnodebug; + slist_add(s); + sinit = s; + } + return sinit; +} + /****************************************** */ diff -uNr gdc-0.23/d/d-dmd-gcc.h gdc-0.24/d/d-dmd-gcc.h --- gdc-0.23/d/d-dmd-gcc.h 2006-11-11 15:25:27.000000000 +0100 +++ gdc-0.24/d/d-dmd-gcc.h 2007-07-27 02:07:14.000000000 +0200 @@ -33,6 +33,9 @@ struct Type; extern Type * d_gcc_builtin_va_list_d_type; +/* used in parse.c */ +extern bool d_gcc_is_target_win32(); + /* used in toobj.c */ struct VarDeclaration; struct Symbol; diff -uNr gdc-0.23/d/d-gcc-includes.h gdc-0.24/d/d-gcc-includes.h --- gdc-0.23/d/d-gcc-includes.h 2007-01-29 03:24:34.000000000 +0100 +++ gdc-0.24/d/d-gcc-includes.h 2007-04-23 00:42:42.000000000 +0200 @@ -39,15 +39,9 @@ #define bool unsigned char #endif -// coretypes.h and tm.h is not present in gcc < 3.4 -#if D_GCC_VER == 33 - /* nothing */ -#else - // gcc 3.4 #include "coretypes.h" #include "tm.h" -#endif - +#include "cpplib.h" #include "cppdefault.h" #include "tree.h" #include "real.h" @@ -66,10 +60,8 @@ #include "expr.h" #include "convert.h" #include "ggc.h" - -#if D_GCC_VER >= 34 #include "opts.h" -#endif +#include "tm_p.h" #if D_GCC_VER >= 40 #include "cgraph.h" diff -uNr gdc-0.23/d/d-gcc-real.cc gdc-0.24/d/d-gcc-real.cc --- gdc-0.23/d/d-gcc-real.cc 2007-01-28 19:47:28.000000000 +0100 +++ gdc-0.24/d/d-gcc-real.cc 2007-05-05 15:23:21.000000000 +0200 @@ -32,18 +32,6 @@ static enum machine_mode max_float_mode() { - /* -#if D_GCC_VER >= 34 - return MAX_MODE_FLOAT; -#else - static enum machine_mode max_mode = VOIDmode; - if (max_mode == VOIDmode) { - // %% not sure if using LONG_DOUBLE_TYPE_SIZE is right - max_mode = smallest_mode_for_size(LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT); - } - return max_mode; -#endif - */ return TYPE_MODE(long_double_type_node); } @@ -66,51 +54,6 @@ } } - -#if D_GCC_VER < 34 - -#define REAL_MODE_FORMAT(MODE) (real_format_for_mode[(MODE) - QFmode]) - -// Taken from GCC 3.4 -/* Fills R with the largest finite value representable in mode MODE. - If SIGN is nonzero, R is set to the most negative finite value. */ - -/* Clear bits 0..N-1 of the significand of R. */ - -static void -clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n) -{ - int i, w = n / HOST_BITS_PER_LONG; - - for (i = 0; i < w; ++i) - r->sig[i] = 0; - - r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1); -} - -static void -real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) -{ - const struct real_format *fmt; - int np2; - - fmt = REAL_MODE_FORMAT (mode); - if (fmt == NULL) - abort (); - - r->cl = rvc_normal; - r->sign = sign; - //r->signalling = 0; - //r->canonical = 0; - r->exp = fmt->emax * fmt->log2_b; - - np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b; - memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); - clear_significand_below (r, np2); -} - -#endif - real_t_Properties real_t_properties[real_t::NumModes]; #define M_LOG10_2 0.30102999566398119521 @@ -334,20 +277,28 @@ */ d_uns64 -real_t::toInt() +real_t::toInt() const { - // %% HOST_WIDE_INT - return real_to_integer(& rv()); + HOST_WIDE_INT low, high; + real_to_integer2(& low, & high, & rv()); + return gen.hwi2toli(low, high); } d_uns64 -real_t::toInt(Type * real_type, Type * int_type) +real_t::toInt(Type * real_type, Type * int_type) const { tree t = fold( build1(FIX_TRUNC_EXPR, int_type->toCtype(), gen.floatConstant(rv(), real_type->toBasetype()->isTypeBasic())) ); // can't use tree_low_cst as it asserts !TREE_OVERFLOW - // %% HOST_WIDE_INT - return TREE_INT_CST_LOW(t); + return gen.hwi2toli(TREE_INT_CST_LOW(t), TREE_INT_CST_HIGH(t)); +} + +real_t +real_t::convert(MyMode to_mode) const +{ + real_t result; + real_convert(& result.rv(), myMode_to_machineMode(to_mode), & rv()); + return result; } bool @@ -414,6 +365,12 @@ return REAL_VALUE_ISNAN(rv()); } +bool +real_t::isConversionExact(MyMode to_mode) const +{ + return exact_real_truncate(myMode_to_machineMode(to_mode), & rv()); +} + void real_t::toBytes(unsigned char * buf, unsigned buf_size) { diff -uNr gdc-0.23/d/d-gcc-real.h gdc-0.24/d/d-gcc-real.h --- gdc-0.23/d/d-gcc-real.h 2007-01-28 19:44:19.000000000 +0100 +++ gdc-0.24/d/d-gcc-real.h 2007-05-05 15:23:21.000000000 +0200 @@ -53,8 +53,9 @@ bool operator== (const real_t & r); bool operator!= (const real_t & r); //operator d_uns64(); // avoid bugs, but maybe allow operator bool() - d_uns64 toInt(); - d_uns64 toInt(Type * real_type, Type * int_type); + d_uns64 toInt() const; + d_uns64 toInt(Type * real_type, Type * int_type) const; + real_t convert(MyMode to_mode) const; bool isZero(); bool isNegative(); bool floatCompare(int op, const real_t & r); @@ -64,6 +65,7 @@ // for debugging: bool isInf(); bool isNan(); + bool isConversionExact(MyMode to_mode) const; void toBytes(unsigned char * buf, unsigned buf_size); void dump(); private: diff -uNr gdc-0.23/d/d-glue.cc gdc-0.24/d/d-glue.cc --- gdc-0.23/d/d-glue.cc 2007-03-06 05:07:47.000000000 +0100 +++ gdc-0.24/d/d-glue.cc 2007-08-05 19:20:57.000000000 +0200 @@ -46,13 +46,6 @@ return build(COND_EXPR, type->toCtype(), cn, t1, t2); } -#if D_GCC_VER < 34 -// Copied from GCC 3.4 -#define COMPLEX_FLOAT_TYPE_P(TYPE) \ - (TREE_CODE (TYPE) == COMPLEX_TYPE \ - && TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE) -#endif - static void signed_compare_check(tree * e1, tree * e2) { @@ -93,15 +86,9 @@ out_code = NE_EXPR; break; case TOKandand: - // %% check if these d_truthvalue_conversion calls are only needed - // for gcc3.3. Test case is regexp.d:trymatch:REwordboundary. - e1 = d_truthvalue_conversion(e1); - e2 = d_truthvalue_conversion(e2); out_code = TRUTH_ANDIF_EXPR; break; case TOKoror: - e1 = d_truthvalue_conversion(e1); - e2 = d_truthvalue_conversion(e2); out_code = TRUTH_ORIF_EXPR; break; default: @@ -566,9 +553,26 @@ elem * -AndAndExp::toElem(IRState * irs) { return make_bool_binop(this, irs); } +AndAndExp::toElem(IRState * irs) +{ + if (e2->type->toBasetype()->ty != Tvoid) + return make_bool_binop(this, irs); + else + return build(COND_EXPR, type->toCtype(), + e1->toElem(irs), e2->toElem(irs), d_void_zero_node); +} + elem * -OrOrExp::toElem(IRState * irs) { return make_bool_binop(this, irs); } +OrOrExp::toElem(IRState * irs) +{ + if (e2->type->toBasetype()->ty != Tvoid) + return make_bool_binop(this, irs); + else + return build(COND_EXPR, type->toCtype(), + build1(TRUTH_NOT_EXPR, boolean_type_node, e1->toElem(irs)), + e2->toElem(irs), d_void_zero_node); +} + elem * XorExp::toElem(IRState * irs) { return make_math_op(this, irs); } elem * @@ -861,7 +865,6 @@ tree exp = build( (enum tree_code) D_ARRAY_SET_EXPR, void_type_node, ptr, src, count); TREE_SIDE_EFFECTS( exp ) = 1; - TREE_READONLY( exp ) = 1; return exp; #else irs->pushStatementList(); @@ -1173,8 +1176,10 @@ // Otherwise, this is normal delete LibCall lib_call; + tree t = e1->toElem(irs); + Type * base_type = e1->type->toBasetype(); - switch (e1->type->toBasetype()->ty) { + switch (base_type->ty) { case Tclass: { VarDeclaration * v; @@ -1183,6 +1188,9 @@ lib_call = LIBCALL_CALLFINALIZER; else lib_call = LIBCALL_DELCLASS; + + if (((TypeClass*) base_type)->sym->isInterfaceDeclaration()) + t = irs->convertTo(t, base_type, irs->getObjectType()); } break; case Tarray: lib_call = LIBCALL_DELARRAY; break; @@ -1192,7 +1200,6 @@ return error_mark_node; } - tree t = e1->toElem(irs); if (lib_call != LIBCALL_CALLFINALIZER) t = irs->addressOf( t ); @@ -1385,10 +1392,7 @@ tree this_tree = e1->toElem(irs); if ( obj_basetype_ty != Tstruct ) this_tree = irs->indirect(this_tree); - - //return build(COMPONENT_REF, type->toCtype(), this_tree, var_decl->toSymbol()->Stree); - return irs->nop(irs->component(this_tree, var_decl->toSymbol()->Stree), - type->toCtype()); + return irs->component(this_tree, var_decl->toSymbol()->Stree); } else { return var_decl->toSymbol()->Stree; } @@ -1580,12 +1584,7 @@ HaltExp::toElem(IRState* irs) { // Needs improvement. Avoid library calls if possible.. - tree t_abort; -#if D_GCC_VER >= 34 - t_abort = built_in_decls[BUILT_IN_ABORT]; -#else - t_abort = built_in_decls[BUILT_IN_TRAP]; -#endif + tree t_abort = built_in_decls[BUILT_IN_ABORT]; return irs->buildCall( TREE_TYPE(TREE_TYPE(t_abort)), irs->addressOf(t_abort), NULL_TREE); } @@ -1707,7 +1706,7 @@ elem * NewExp::toElem(IRState * irs) { - Type * base_type = type->toBasetype(); + Type * base_type = newtype->toBasetype(); tree result; if (allocator) @@ -1797,7 +1796,7 @@ } else { result = new_call; } - return result; + return irs->convertTo(result, base_type, type); } case Tarray: { @@ -1806,7 +1805,7 @@ LibCall lib_call; - Type * elem_init_type = type; + Type * elem_init_type = newtype; /* First, skip past dynamic array dimensions/types that will be allocated by this call. */ @@ -1842,7 +1841,6 @@ //elms.cons(final_length); dims_init = make_node(CONSTRUCTOR); TREE_TYPE( dims_init ) = TREE_TYPE( dims_var); - TREE_READONLY( dims_init ) = 1; CONSTRUCTOR_ELTS( dims_init ) = elms.head; DECL_INITIAL(dims_var) = dims_init; } @@ -1856,12 +1854,13 @@ result = irs->binding(dims_var, result); } - return result; + return irs->convertTo(result, base_type, type); } break; - case Tpointer: + default: { - Type * object_type = base_type->next; + Type * object_type = newtype; + Type * handle_type = base_type->pointerTo(); tree new_call; tree t; bool need_init = true; @@ -1882,7 +1881,7 @@ new_call = irs->darrayPtrRef(new_call); need_init = false; } - new_call = irs->nop(new_call, base_type->toCtype()); + new_call = irs->nop(new_call, handle_type->toCtype()); if ( need_init ) { // Save the result allocation call. new_call = save_expr( new_call ); @@ -1891,11 +1890,9 @@ irs->convertForAssignment(object_type->defaultInit(), object_type) ); new_call = irs->compound(t, new_call); } - return new_call; + return irs->nop(new_call, type->toCtype()); } break; - default: - abort(); } } @@ -2020,6 +2017,82 @@ } elem * +AssocArrayLiteralExp::toElem(IRState * irs) +{ + TypeAArray * aa_type = (TypeAArray *)type->toBasetype(); + assert(aa_type->ty == Taarray); + assert(keys != NULL); + assert(values != NULL); + + tree keys_var = irs->exprVar(irs->arrayType(aa_type->index, keys->dim)); //? + tree vals_var = irs->exprVar(irs->arrayType(aa_type->next, keys->dim)); + tree keys_ptr = irs->nop(irs->addressOf(keys_var), + aa_type->index->pointerTo()->toCtype()); + tree vals_ptr = irs->nop(irs->addressOf(vals_var), + aa_type->next->pointerTo()->toCtype()); + tree keys_offset = size_int(0); + tree vals_offset = size_int(0); + tree keys_size = size_int( aa_type->index->size() ); + tree vals_size = size_int( aa_type->next->size() ); + tree result = NULL_TREE; + + for (unsigned i = 0; i < keys->dim; i++) + { + Expression * e; + tree elemp_e, assgn_e; + + e = (Expression *) keys->data[i]; + elemp_e = build2(PLUS_EXPR, TREE_TYPE(keys_ptr), keys_ptr, keys_offset); + assgn_e = irs->vmodify( irs->indirect(elemp_e), e->toElem(irs) ); + keys_offset = size_binop(PLUS_EXPR, keys_offset, keys_size); + result = irs->maybeCompound(result, assgn_e); + + e = (Expression *) values->data[i]; + elemp_e = build2(PLUS_EXPR, TREE_TYPE(vals_ptr), vals_ptr, vals_offset); + assgn_e = irs->vmodify( irs->indirect(elemp_e), e->toElem(irs) ); + vals_offset = size_binop(PLUS_EXPR, vals_offset, vals_size); + result = irs->maybeCompound(result, assgn_e); + } + + tree args[4] = { irs->typeinfoReference(aa_type), + irs->integerConstant(keys->dim, Type::tsize_t), + keys_ptr, vals_ptr }; + result = irs->maybeCompound(result, + irs->libCall(LIBCALL_ASSOCARRAYLITERALTP, 4, args)); + + result = irs->binding(keys_var, irs->binding(vals_var, result)); + + tree ctor = make_node( CONSTRUCTOR ); + CtorEltMaker ce; + TREE_TYPE( ctor ) = aa_type->toCtype(); + ce.cons(TYPE_FIELDS(TREE_TYPE( ctor )), result); + CONSTRUCTOR_ELTS( ctor ) = ce.head; + + return irs->nop(ctor, type->toCtype()); +} + +elem * +StructLiteralExp::toElem(IRState *irs) +{ + assert(type->toBasetype()->equals(sd->type->toBasetype())); + + tree ctor = make_node( CONSTRUCTOR ); + CtorEltMaker ce; + TREE_TYPE( ctor ) = type->toCtype(); + + if (elements) + for (unsigned i = 0; i < elements->dim; ++i) + { + Expression * e = (Expression *) elements->data[i]; + VarDeclaration * fld = (VarDeclaration *) sd->fields.data[i]; + ce.cons(fld->csym->Stree, irs->convertTo(e, fld->type)); + } + + CONSTRUCTOR_ELTS( ctor ) = ce.head; + return ctor; +} + +elem * NullExp::toElem(IRState * irs) { TY base_ty = type->toBasetype()->ty; @@ -2035,7 +2108,6 @@ CtorEltMaker ce; TREE_TYPE(ctor) = type->toCtype(); - TREE_READONLY(ctor)=1; fa = TYPE_FIELDS(TREE_TYPE(ctor)); ce.cons(fa, convert(TREE_TYPE(fa), integer_zero_node)); CONSTRUCTOR_ELTS(ctor) = ce.head; @@ -2326,11 +2398,7 @@ if (linkage == LINKc && DECL_ASSEMBLER_NAME (fn_decl) && MAIN_NAME_P (DECL_ASSEMBLER_NAME (fn_decl)) // other langs use DECL_NAME.. -#if D_GCC_VER >= 34 && DECL_FILE_SCOPE_P (fn_decl) -#else - && ! DECL_CONTEXT (fn_decl) -#endif ) expand_main_function (); @@ -2476,14 +2544,7 @@ irs->endScope(); #if D_GCC_VER < 40 -#ifdef D_GCC_VER330 - expand_function_end (input_filename, loc.linnum, 0, fn_decl); -#elif D_GCC_VER == 33 - expand_function_end (input_filename, loc.linnum, 0/*1?*/); -#else expand_function_end (); -#endif - block = (*lang_hooks.decls.poplevel) (1, 0, 1); #else DECL_SAVED_TREE(fn_decl) = irs->popStatementList(); @@ -2920,6 +2981,13 @@ type * TypeAArray::toCtype() { + /* Dependencies: + + IRState::convertForCondition + more... + + */ + if (! ctype) { /* Library functions expect a struct-of-pointer which could be passed @@ -2960,10 +3028,6 @@ return ctype; } -#if D_GCC_VER < 34 -#define BINFO_ELTS 8 -#endif - /* Create debug information for a ClassDeclaration's inheritance tree. Interfaces are not included. */ static tree @@ -3617,7 +3681,7 @@ irs->emitLocalVar(key); // %% getExpInitializer causes uneeded initialization } - if (value->isOut()) { + if (value->isRef() || value->isOut()) { iter_decl = value->toSymbol()->Stree; } else { iter_decl = irs->localVar(elem_type->pointerTo()); @@ -3823,11 +3887,7 @@ #if D_GCC_VER < 40 rtx -#if D_GCC_VER == 33 -d_expand_expr(tree exp, rtx target , enum machine_mode tmode, int modifier) -#else d_expand_expr(tree exp, rtx target , enum machine_mode tmode, int modifier, rtx *) -#endif { if ( TREE_CODE(exp) == (enum tree_code) D_STMT_EXPR ) { IRState * irs; @@ -3892,11 +3952,6 @@ } tree d_void_zero_node; -#if D_GCC_VER == 33 -tree boolean_type_node; -tree boolean_true_node; -tree boolean_false_node; -#endif tree d_null_pointer; tree d_vtbl_ptr_type_node; @@ -3940,27 +3995,9 @@ #else d_void_zero_node = build_int_cst (void_type_node, 0); #endif -#if D_GCC_VER == 33 - /* For GCC 3.3.x, the C front end uses integer_type_node, but this conflicts - with bit.size==1. GCC 3.4 uses an 8bit value like this. The GCC 3.4 code - is copied here. */ - boolean_type_node = make_unsigned_type(BOOL_TYPE_SIZE); - TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE); - TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0); - TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node; - TYPE_PRECISION (boolean_type_node) = 1; - - boolean_false_node = TYPE_MIN_VALUE(boolean_type_node);// convert(boolean_type_node, integer_zero_node); - boolean_true_node = TYPE_MAX_VALUE(boolean_type_node); //convert(boolean_type_node, integer_one_node); - // * / -#endif - // (else) %%TODO: we are relying on default boolean_type_node being 8bit / same as Tbit + // %%TODO: we are relying on default boolean_type_node being 8bit / same as Tbit d_null_pointer = convert(ptr_type_node, integer_zero_node); - - //%% fix dbxout_init expects integer_type_node and others to have a TYPE_NAME.. - // and it must be a TYPE_DECL, not an IDENTIFIER_NODE - // GCC 3.3 only? TYPE_NAME( integer_type_node ) = build_decl(TYPE_DECL, get_identifier("int"), integer_type_node); TYPE_NAME( char_type_node ) = build_decl(TYPE_DECL, get_identifier("cchar"), char_type_node); // "char?" @@ -3992,7 +4029,7 @@ default: abort(); } - CLASSINFO_SIZE = 17 * PTRSIZE; + CLASSINFO_SIZE = 18 * PTRSIZE; d_init_builtins(); diff -uNr gdc-0.23/d/d-gt.c gdc-0.24/d/d-gt.c --- gdc-0.23/d/d-gt.c 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/d-gt.c 2007-03-10 15:58:53.000000000 +0100 @@ -20,15 +20,8 @@ #include "config.h" #include "system.h" -/* coretypes.h and tm.h is not present in gcc < 3.4 (so it seems) */ -#if D_GCC_VER == 33 - /* nothing*/ -#else - /* gcc 3.4 */ #include "coretypes.h" #include "tm.h" -#endif - #include "tree.h" #include "ggc.h" #include "debug.h" diff -uNr gdc-0.23/d/d-irstate.cc gdc-0.24/d/d-irstate.cc --- gdc-0.23/d/d-irstate.cc 2006-12-21 03:04:11.000000000 +0100 +++ gdc-0.24/d/d-irstate.cc 2007-03-10 15:58:53.000000000 +0100 @@ -127,11 +127,7 @@ void IRBase::initFunctionStart(tree fn_decl, const Loc & loc) { -#if D_GCC_VER >= 34 init_function_start (fn_decl); -#else - init_function_start (fn_decl, loc.filename, loc.linnum); // %% loc of the f. or 1st stmt.? -#endif } #if D_GCC_VER < 40 diff -uNr gdc-0.23/d/d-lang.cc gdc-0.24/d/d-lang.cc --- gdc-0.23/d/d-lang.cc 2007-03-04 19:20:57.000000000 +0100 +++ gdc-0.24/d/d-lang.cc 2007-08-22 02:16:39.000000000 +0200 @@ -28,9 +28,7 @@ #include #include "d-gcc-includes.h" -#if D_GCC_VER >= 34 #include "options.h" -#endif #include "d-lang.h" #include "d-codegen.h" #include "d-gcc-real.h" @@ -47,16 +45,10 @@ #undef LANG_HOOKS_INIT_OPTIONS #define LANG_HOOKS_INIT_OPTIONS d_init_options -#if D_GCC_VER == 33 -#undef LANG_HOOKS_DECODE_OPTION -#define LANG_HOOKS_DECODE_OPTION d_decode_option -#else -// gcc3.4 #undef LANG_HOOKS_HANDLE_OPTION #define LANG_HOOKS_HANDLE_OPTION d_handle_option #undef LANG_HOOKS_POST_OPTIONS #define LANG_HOOKS_POST_OPTIONS d_post_options -#endif #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE d_parse_file @@ -139,22 +131,10 @@ static const char * fonly_arg; static const char * multilib_dir; -#if D_GCC_VER == 33 - -static Array * all_input_files = 0; - -static void -d_init_options () -#else static unsigned int d_init_options (unsigned int, const char **) -#endif { // Set default values -#if D_GCC_VER == 33 - all_input_files = new Array; -#endif - global.params.argv0 = (char *) progname; global.params.link = 1; global.params.useAssert = 1; @@ -186,9 +166,7 @@ gen.useBuiltins = true; std_inc = true; -#if D_GCC_VER >= 34 return CL_D; -#endif } // support for the -mno-cygwin switch @@ -207,7 +185,7 @@ #undef D_PHOBOS_TARGET_DIR #define D_PHOBOS_TARGET_DIR (cygwin_d_target_dir) -char * cygwin_d_os_versym = D_OS_VERSYM; +const char * cygwin_d_os_versym = D_OS_VERSYM; #undef D_OS_VERSYM #define D_OS_VERSYM cygwin_d_os_versym @@ -245,6 +223,14 @@ } } +static bool is_target_win32 = false; + +bool +d_gcc_is_target_win32() +{ + return is_target_win32; +} + static char * prefixed_path(const char * path) { @@ -256,13 +242,35 @@ return xstrdup(path); } -#if D_GCC_VER == 33 -static const char * -d_init (const char * filename) -#else +static int +d_cpp_forall_callback(cpp_reader *, cpp_hashnode * hn, void *) +{ + const char * str = (const char *) hn->ident.str; + unsigned int len = hn->ident.len; + char * d_ident = new char[4 + len + 1]; + if (len > 4 && str[0] == '_' && str[1] == '_' && + str[len - 1] == '_' && str[len - 2] == '_') + { + str += 2; + len -= 4; + } + strcpy(d_ident, "GNU_"); + strncpy(d_ident + 4, str, len); + d_ident[len + 4] = '\0'; + VersionCondition::addPredefinedGlobalIdent(d_ident); + return 1; +} + +/* Supports CPP builtins. */ +cpp_reader * parse_in; +void +builtin_define_std (const char *macro) +{ + // Do nothing. No need for these (yet). +} + static bool d_init () -#endif { const char * cpu_versym = NULL; @@ -294,10 +302,14 @@ if (cpu_versym) VersionCondition::addPredefinedGlobalIdent((char*) cpu_versym); #ifdef D_OS_VERSYM - VersionCondition::addPredefinedGlobalIdent(D_OS_VERSYM); + VersionCondition::addPredefinedGlobalIdent((char*) D_OS_VERSYM); + if (strcmp(D_OS_VERSYM, "Win32") == 0) + is_target_win32 = true; #endif #ifdef D_OS_VERSYM2 - VersionCondition::addPredefinedGlobalIdent(D_OS_VERSYM2); + VersionCondition::addPredefinedGlobalIdent((char*) D_OS_VERSYM2); + if (strcmp(D_OS_VERSYM2, "Win32") == 0) + is_target_win32 = true; #endif if (BYTES_BIG_ENDIAN) @@ -326,6 +338,43 @@ if (flag_test_coverage) VersionCondition::addPredefinedGlobalIdent("D_Coverage"); + { + line_maps lm; + cpp_reader * pfile; // Target macros below expect this identifier. + int flag_iso = 0; // ditto + + linemap_init(& lm); + parse_in = pfile = cpp_create_reader(CLK_STDC89, NULL +#if D_GCC_VER >= 40 + , & lm +#endif + ); + cpp_change_file(pfile, LC_ENTER, ""); + + // from c-cppbuiltin.c +#ifndef TARGET_OS_CPP_BUILTINS +# define TARGET_OS_CPP_BUILTINS() +#endif +#ifndef TARGET_OBJFMT_CPP_BUILTINS +# define TARGET_OBJFMT_CPP_BUILTINS() +#endif + +# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM) +# define preprocessing_trad_p() (cpp_get_options (pfile)->traditional) +# define preprocessing_asm_p() (0) +# define preprocessing_trad_p() (0) +# define builtin_define(TXT) (cpp_define (pfile, TXT)) +# define builtin_assert(TXT) (cpp_assert (pfile, TXT)) + TARGET_CPU_CPP_BUILTINS (); + TARGET_OS_CPP_BUILTINS (); + TARGET_OBJFMT_CPP_BUILTINS (); + + cpp_forall_identifiers(pfile, & d_cpp_forall_callback, NULL); + + cpp_destroy(pfile); + linemap_free(& lm); + } + VersionCondition::addPredefinedGlobalIdent("all"); @@ -403,55 +452,9 @@ } } -#if D_GCC_VER == 33 - if (all_input_files && all_input_files->dim) - return (char *) all_input_files->data[0]; - else - return filename; -#else return 1; -#endif } -#if D_GCC_VER == 33 - -typedef enum opt_code { - Wrong, - OPT_I, - OPT_J, - OPT_fdeprecated, - OPT_fassert, - OPT_frelease, - OPT_funittest, - OPT_fversion_, - OPT_fdebug, - OPT_fdebug_, - OPT_fdebug_c, - OPT_fintfc, - OPT_fintfc_dir_, - OPT_fintfc_file_, - OPT_fdoc, - OPT_fdoc_dir_, - OPT_fdoc_file_, - OPT_fdoc_inc_, - OPT_fd_verbose, - OPT_fd_version_1, - OPT_femit_templates, - OPT_femit_templates_, - OPT_fmultilib_dir_, - OPT_fonly_, - OPT_nostdinc, - OPT_fdump_source, - OPT_fbuiltin, - OPT_fsigned_char, - OPT_funsigned_char, - OPT_iprefix, - OPT_Wall, - OPT_Wsign_compare -}; - -#endif - static bool parse_int (const char * arg, int * value_ret) { @@ -465,7 +468,6 @@ return true; } -// gcc 3.4, but also called by gcc3 static int d_handle_option (size_t scode, const char *arg, int value) { @@ -615,128 +617,6 @@ return 1; } - -#if D_GCC_VER == 33 - -static int -d_decode_option (int argc, char **argv) -{ - const char * p_arg = argv[0]; - - //printf("d_decode_option %d, \"%s\"\n", argc, p_arg); - - if (strncmp(p_arg, "-I", 2) == 0) { - if (p_arg[2] == '\0') { - d_handle_option(OPT_I, argv[1], 0); - return 2; - } else { - d_handle_option(OPT_I, p_arg + 2, 0); - return 1; - } - if (strncmp(p_arg, "-J", 2) == 0) { - if (p_arg[2] == '\0') { - d_handle_option(OPT_J, argv[1], 0); - return 2; - } else { - d_handle_option(OPT_J, p_arg + 2, 0); - return 1; - } - } else if (strncmp(p_arg, "-f", 2) == 0) { - int value = 1; - p_arg += 2; - if (strncmp(p_arg, "no-", 3) == 0) { - value = 0; - p_arg += 3; - } - if (strcmp(p_arg, "deprecated") == 0) - d_handle_option(OPT_fdeprecated, NULL, value); - else if (strcmp(p_arg, "assert") == 0) - d_handle_option(OPT_fassert, NULL, value); - else if (strcmp(p_arg, "release") == 0) - d_handle_option(OPT_frelease, NULL, value); - else if (strcmp(p_arg, "unittest") == 0) - d_handle_option(OPT_funittest, NULL, value); - else if (value && strncmp(p_arg, "version=", 8) == 0) - // %% better error handling - d_handle_option(OPT_fversion_, p_arg + 8, value); - else if (strcmp(p_arg, "debug-c") == 0) - d_handle_option(OPT_fdebug_c, NULL, value); - else if (value && strncmp(p_arg, "debug=", 6) == 0) - d_handle_option(OPT_fdebug_, p_arg + 6, value); - else if (strcmp(p_arg, "debug") == 0) - d_handle_option(OPT_fdebug, p_arg + 5, value); - else if (strcmp(p_arg, "intfc") == 0) - d_handle_option(OPT_fintfc, NULL, value); - else if (strncmp(p_arg, "intfc-dir=", 10) == 0) - d_handle_option(OPT_fintfc_dir_, p_arg + 10, value); - else if (strncmp(p_arg, "intfc-file=", 11) == 0) - d_handle_option(OPT_fintfc_file_, p_arg + 11, value); - else if (strcmp(p_arg, "doc") == 0) - d_handle_option(OPT_fdoc, NULL, value); - else if (strncmp(p_arg, "doc-dir=", 8) == 0) - d_handle_option(OPT_fdoc_dir_, p_arg + 8, value); - else if (strncmp(p_arg, "doc-file=", 9) == 0) - d_handle_option(OPT_fdoc_file_, p_arg + 9, value); - else if (strncmp(p_arg, "doc-inc=", 8) == 0) - d_handle_option(OPT_fdoc_inc_, p_arg + 8, value); - else if (strcmp(p_arg, "d-verbose") == 0) - d_handle_option(OPT_fd_verbose, NULL, value); - else if (strcmp(p_arg, "d-version=1") == 0) - d_handle_option(OPT_fd_version_1_, NULL, value); - else if (strncmp(p_arg, "emit-templates", 14) == 0 && - p_arg[14] == '\0' || (value && p_arg[14] == '=')) { - if (p_arg[14] == '=') { - if (! value) { - return 0; - } - p_arg += 15; - d_handle_option(OPT_femit_templates_, p_arg, value); - } else { - d_handle_option(OPT_femit_templates, NULL, value); - } - } else if (strncmp(p_arg, "multilib-dir=", x) == 0) - d_handle_option(OPT_fmultilib_dir, p_arg + 13, value); - } else if (strncmp(p_arg, "only=", 5) == 0) - d_handle_option(OPT_fonly_, p_arg + 5, value); - else if (strcmp(p_arg, "dump-source") == 0) - d_handle_option(OPT_fdump_source, NULL, value); - else if (strcmp(p_arg, "builtin") == 0) - d_handle_option(OPT_fbuiltin, NULL, value); - else - return 0; - return 1; - } else if (strcmp(p_arg, "-iprefix") == 0) { - d_handle_option(OPT_iprefix, argv[1], 0); - return 2; - } else if (strcmp(p_arg, "-isystem") == 0) { - /* ignored */ - return 2; - } else if (strcmp(p_arg, "-nostdinc") == 0) { - d_handle_option(OPT_nostdinc, NULL, 0); - return 1; - } else if (strncmp(p_arg, "-W", 2) == 0) { - int value = 1; - p_arg += 2; - if (strncmp(p_arg, "no-", 3) == 0) { - value = 0; - p_arg += 3; - } - if (strcmp(p_arg, "all") == 0) - 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; - } else { - return 0; - } -} -#endif - -#if D_GCC_VER >= 34 - bool d_post_options(const char ** fn) { // The front end considers the first input file to be the main one. @@ -761,10 +641,8 @@ return false; } -#endif - -// %% In gcc 3.4 (not sure about 3.3), wrapup_global_declaration needs -// to be called or functions will not be emitted. +/* wrapup_global_declaration needs to be called or functions will not + be emitted. */ Array globalFunctions; // Array of tree (for easy passing to wrapup_global_declarations) void @@ -808,7 +686,6 @@ return an_output_module; } - static void nametype(tree type, const char * name) { @@ -852,21 +729,9 @@ global.params.pic = flag_pic != 0; // Has no effect yet. gen.originalOmitFramePointer = flag_omit_frame_pointer; -#if D_GCC_VER == 33 - (*debug_hooks->start_source_file) (lineno, input_filename); - - unsigned num_in_fnames = all_input_files->dim; - char ** in_fnames = (char **) all_input_files->data; - /* - for (unsigned i = 0; i < all_input_files->dim; i++) { - printf("%2d: '%s'\n", i, all_input_files->data[i]); - } - */ - -#else // elif >= 34 // better to use input_location.xxx ? (*debug_hooks->start_source_file) (input_line, input_filename); -#endif + /* printf("input_filename = '%s'\n", input_filename); printf("main_input_filename = '%s'\n", main_input_filename); @@ -990,6 +855,7 @@ //m->deleteObjFile(); // %% driver does this m->read(0); m->parse(global.params.dump_source); + d_gcc_magic_module(m); if (m->isDocFile) { m->gendocfile(); @@ -1013,6 +879,8 @@ for (i = 0; i < modules.dim; i++) { m = (Module *)modules.data[i]; + if (fonly_arg && m != an_output_module) + continue; if (global.params.verbose) printf("import %s\n", m->toChars()); m->genhdrfile(); @@ -1093,12 +961,8 @@ } } -#if D_GCC_VER == 33 - (*debug_hooks->end_source_file) (lineno); -#else // better to use input_location.xxx ? (*debug_hooks->end_source_file) (input_line); -#endif had_errors: // Add DMD error count to GCC error count to to exit with error status errorcount += global.errors; @@ -1201,13 +1065,7 @@ case RESULT_DECL: #if D_GCC_VER < 40 if ( ! TREE_STATIC(x) ) // %% C doesn't do this check - put_var_into_stack(x -// Hack: Apple gcc-1495 differs from gcc-3.3 on this point. This macro is -// used to distinguish from the true 3.3 release. -#ifndef APPLE_WEAK_ASSEMBLER_DIRECTIVE - , 1 -#endif - ); + put_var_into_stack(x, 1); #endif // drop through case FUNCTION_DECL: diff -uNr gdc-0.23/d/d-lang.h gdc-0.24/d/d-lang.h --- gdc-0.23/d/d-lang.h 2007-03-04 18:28:07.000000000 +0100 +++ gdc-0.24/d/d-lang.h 2007-04-21 22:34:31.000000000 +0200 @@ -117,12 +117,6 @@ extern GTY(()) struct binding_level * current_binding_level; extern GTY(()) struct binding_level * global_binding_level; -#if D_GCC_VER == 33 -extern GTY(()) tree boolean_type_node; -extern GTY(()) tree boolean_true_node; -extern GTY(()) tree boolean_false_node; -#endif - extern GTY(()) tree intmax_type_node; extern GTY(()) tree uintmax_type_node; extern GTY(()) tree signed_size_type_node; @@ -155,11 +149,7 @@ extern tree d_type_promotes_to(tree); -#if D_GCC_VER == 33 -extern rtx d_expand_expr(tree, rtx, enum machine_mode, int); -#else extern rtx d_expand_expr(tree, rtx, enum machine_mode, int, rtx *); -#endif extern void gcc_d_backend_init(); extern void gcc_d_backend_term(); @@ -200,9 +190,7 @@ /* In d-builtins2.cc */ extern void d_bi_init(int nt, int nb); -extern void d_bi_builtin_type(int ti, tree t); -extern void d_bi_builtin_func_type(int ti, tree t, int ri, int ai1, int ai2, int ai3, int ai4, int ai5, int ai6, int va); -extern void d_bi_builtin_func(int bi, const char *name, int ti, tree decl); +extern void d_bi_builtin_func(tree decl); #ifdef __cplusplus } diff -uNr gdc-0.23/d/dmd/access.c gdc-0.24/d/dmd/access.c --- gdc-0.23/d/dmd/access.c 2006-07-22 16:16:08.000000000 +0200 +++ gdc-0.24/d/dmd/access.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/aggregate.h gdc-0.24/d/dmd/aggregate.h --- gdc-0.23/d/dmd/aggregate.h 2007-02-18 17:24:46.000000000 +0100 +++ gdc-0.24/d/dmd/aggregate.h 2007-04-29 20:05:44.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -49,6 +49,7 @@ target_size_t structsize; // size of struct target_size_t alignsize; // size of struct for alignment purposes target_size_t structalign; // struct member alignment in effect + int hasUnions; // set if aggregate has overlapping fields Array fields; // VarDeclaration fields unsigned sizeok; // set when structsize contains valid data // 0: no size @@ -166,6 +167,7 @@ ClassDeclaration *baseClass; // NULL only if this is Object CtorDeclaration *ctor; + CtorDeclaration *defaultCtor; // default constructor FuncDeclarations dtors; // Array of destructors FuncDeclaration *staticCtor; FuncDeclaration *staticDtor; diff -uNr gdc-0.23/d/dmd/arraytypes.h gdc-0.24/d/dmd/arraytypes.h --- gdc-0.23/d/dmd/arraytypes.h 2007-03-04 14:27:08.000000000 +0100 +++ gdc-0.24/d/dmd/arraytypes.h 2007-04-29 14:03:30.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 2006-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -23,6 +23,8 @@ struct BaseClass; struct TemplateParameter; struct FuncDeclaration; +struct Identifier; +struct Initializer; struct TemplateParameters : Array { }; @@ -42,4 +44,8 @@ struct Arguments : Array { }; +struct Identifiers : Array { }; + +struct Initializers : Array { }; + #endif diff -uNr gdc-0.23/d/dmd/attrib.c gdc-0.24/d/dmd/attrib.c --- gdc-0.23/d/dmd/attrib.c 2007-03-04 14:27:19.000000000 +0100 +++ gdc-0.24/d/dmd/attrib.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -298,7 +298,7 @@ buf->writeByte('}'); } else - buf->writeByte(':'); + buf->writeByte(';'); buf->writenl(); } @@ -1265,6 +1265,7 @@ se = se->toUTF8(sc); Parser p(sc->module, (unsigned char *)se->string, se->len, 0); p.loc = loc; + p.nextToken(); decl = p.parseDeclDefs(0); if (p.token.value != TOKeof) { diff -uNr gdc-0.23/d/dmd/attrib.h gdc-0.24/d/dmd/attrib.h --- gdc-0.23/d/dmd/attrib.h 2007-02-08 18:58:10.000000000 +0100 +++ gdc-0.24/d/dmd/attrib.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/bit.c gdc-0.24/d/dmd/bit.c --- gdc-0.23/d/dmd/bit.c 2006-06-03 04:57:44.000000000 +0200 +++ gdc-0.24/d/dmd/bit.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2002 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/cast.c gdc-0.24/d/dmd/cast.c --- gdc-0.23/d/dmd/cast.c 2007-02-18 16:24:29.000000000 +0100 +++ gdc-0.24/d/dmd/cast.c 2007-07-27 02:07:14.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -87,7 +87,7 @@ * Don't do the actual cast. */ -int Expression::implicitConvTo(Type *t) +MATCH Expression::implicitConvTo(Type *t) { #if 0 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", @@ -104,7 +104,7 @@ { //printf("optimzed to %s\n", e->toChars()); return e->implicitConvTo(t); } - int match = type->implicitConvTo(t); + MATCH match = type->implicitConvTo(t); if (match) return match; #if 0 @@ -129,7 +129,7 @@ } -int IntegerExp::implicitConvTo(Type *t) +MATCH IntegerExp::implicitConvTo(Type *t) { #if 0 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", @@ -142,7 +142,9 @@ enum TY toty = t->toBasetype()->ty; if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum) + { return MATCHnomatch; + } switch (ty) { @@ -245,6 +247,36 @@ goto Lno; goto Lyes; +#if IN_GCC + case Tfloat32: + case Tfloat64: + case Tfloat80: + { + real_t::MyMode mode; + real_t f; + switch (toty) + { + case Tfloat32: mode = real_t::Float; break; + case Tfloat64: mode = real_t::Double; break; + case Tfloat80: mode = real_t::LongDouble; break; + } + if (type->isunsigned()) + { + f = real_t((d_uns64) value); + f = f.convert(mode); + if ((d_uns64) f.toInt() != (d_uns64) value) + goto Lno; + } + else + { + f = real_t((d_int64) value); + f = f.convert(mode); + if ((d_int64) f.toInt() != (d_int64) value) + goto Lno; + } + goto Lyes; + } +#else case Tfloat32: { volatile float f; @@ -298,17 +330,20 @@ } goto Lyes; } +#endif } return Expression::implicitConvTo(t); Lyes: + //printf("MATCHconvert\n"); return MATCHconvert; Lno: + //printf("MATCHnomatch\n"); return MATCHnomatch; } -int NullExp::implicitConvTo(Type *t) +MATCH NullExp::implicitConvTo(Type *t) { #if 0 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", @@ -329,10 +364,13 @@ return Expression::implicitConvTo(t); } -int StringExp::implicitConvTo(Type *t) +MATCH StringExp::implicitConvTo(Type *t) { MATCH m; - //printf("StringExp::implicitConvTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed); +#if 0 + printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", + toChars(), committed, type->toChars(), t->toChars()); +#endif if (!committed) { if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) @@ -350,8 +388,11 @@ ((TypeSArray *)type)->dim->toInteger() != ((TypeSArray *)t)->dim->toInteger()) return MATCHnomatch; + goto L1; case Tarray: + goto L1; case Tpointer: + L1: if (t->next->ty == Tchar) return MATCHexact; else if (t->next->ty == Twchar) @@ -375,7 +416,7 @@ #endif } -int ArrayLiteralExp::implicitConvTo(Type *t) +MATCH ArrayLiteralExp::implicitConvTo(Type *t) { MATCH result = MATCHexact; Type *typeb = type->toBasetype(); @@ -403,13 +444,40 @@ return Expression::implicitConvTo(t); } -int AddrExp::implicitConvTo(Type *t) +MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) +{ MATCH result = MATCHexact; + + Type *typeb = type->toBasetype(); + Type *tb = t->toBasetype(); + if (tb->ty == Taarray && typeb->ty == Taarray) + { + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (Expression *)keys->data[i]; + MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->key); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + e = (Expression *)values->data[i]; + m = (MATCH)e->implicitConvTo(tb->next); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + } + return result; + } + else + return Expression::implicitConvTo(t); +} + +MATCH AddrExp::implicitConvTo(Type *t) { #if 0 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif - int result; + MATCH result; result = type->implicitConvTo(t); //printf("\tresult = %d\n", result); @@ -435,13 +503,13 @@ return result; } -int SymOffExp::implicitConvTo(Type *t) +MATCH SymOffExp::implicitConvTo(Type *t) { #if 0 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif - int result; + MATCH result; result = type->implicitConvTo(t); //printf("\tresult = %d\n", result); @@ -464,13 +532,13 @@ return result; } -int DelegateExp::implicitConvTo(Type *t) +MATCH DelegateExp::implicitConvTo(Type *t) { #if 0 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif - int result; + MATCH result; result = type->implicitConvTo(t); @@ -484,16 +552,16 @@ t->ty == Tdelegate && t->next->ty == Tfunction) { if (func && func->overloadExactMatch(t->next)) - result = 2; + result = MATCHexact; } } return result; } -int CondExp::implicitConvTo(Type *t) +MATCH CondExp::implicitConvTo(Type *t) { - int m1; - int m2; + MATCH m1; + MATCH m2; m1 = e1->implicitConvTo(t); m2 = e2->implicitConvTo(t); @@ -898,7 +966,8 @@ Type *typeb = type->toBasetype(); Type *tb = t->toBasetype(); if ((tb->ty == Tarray || tb->ty == Tsarray) && - (typeb->ty == Tarray || typeb->ty == Tsarray)) + (typeb->ty == Tarray || typeb->ty == Tsarray) && + tb->next->toBasetype()->ty != Tvoid) { if (tb->ty == Tsarray) { TypeSArray *tsa = (TypeSArray *)tb; @@ -922,6 +991,30 @@ return Expression::castTo(sc, t); } +Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t) +{ + Type *typeb = type->toBasetype(); + Type *tb = t->toBasetype(); + if (tb->ty == Taarray && typeb->ty == Taarray && + tb->next->toBasetype()->ty != Tvoid) + { + assert(keys->dim == values->dim); + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (Expression *)values->data[i]; + e = e->castTo(sc, tb->next); + values->data[i] = (void *)e; + + e = (Expression *)keys->data[i]; + e = e->castTo(sc, ((TypeAArray *)tb)->key); + keys->data[i] = (void *)e; + } + type = t; + return this; + } +L1: + return Expression::castTo(sc, t); +} + Expression *SymOffExp::castTo(Scope *sc, Type *t) { Type *tb; diff -uNr gdc-0.23/d/dmd/class.c gdc-0.24/d/dmd/class.c --- gdc-0.23/d/dmd/class.c 2007-02-18 16:25:35.000000000 +0100 +++ gdc-0.24/d/dmd/class.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -59,6 +59,7 @@ handle = type; ctor = NULL; + defaultCtor = NULL; staticCtor = NULL; staticDtor = NULL; @@ -402,6 +403,9 @@ if (baseClass) { + if (baseClass->storage_class & STCfinal) + error("cannot inherit from final class %s", baseClass->toChars()); + interfaces_dim--; interfaces++; @@ -489,7 +493,8 @@ isdeprecated = 1; sc = sc->push(this); - sc->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated); + sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | + STCabstract | STCdeprecated); sc->attributes = NULL; sc->parent = this; sc->inunion = 0; @@ -528,7 +533,7 @@ alignsize = 0; structalign = 0; - sc->pop(); + sc = sc->pop(); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); @@ -575,6 +580,7 @@ *sc = scsave; sc->offset = structsize; ctor->semantic(sc); + defaultCtor = ctor; } #if 0 diff -uNr gdc-0.23/d/dmd/complex_t.h gdc-0.24/d/dmd/complex_t.h --- gdc-0.23/d/dmd/complex_t.h 2006-11-12 19:30:18.000000000 +0100 +++ gdc-0.24/d/dmd/complex_t.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright and Burton Radons -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/cond.c gdc-0.24/d/dmd/cond.c --- gdc-0.23/d/dmd/cond.c 2007-03-04 14:27:25.000000000 +0100 +++ gdc-0.24/d/dmd/cond.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/cond.h gdc-0.24/d/dmd/cond.h --- gdc-0.23/d/dmd/cond.h 2006-12-16 18:22:50.000000000 +0100 +++ gdc-0.24/d/dmd/cond.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/constfold.c gdc-0.24/d/dmd/constfold.c --- gdc-0.23/d/dmd/constfold.c 2007-03-05 00:35:22.000000000 +0100 +++ gdc-0.24/d/dmd/constfold.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -28,6 +28,8 @@ #include "mtype.h" #include "expression.h" +#include "aggregate.h" +#include "declaration.h" #ifdef IN_GCC #include "d-gcc-real.h" @@ -460,7 +462,7 @@ n1 = e1->toInteger(); n2 = e2->toInteger(); if (n2 == 0) - { error("divide by 0"); + { e2->error("divide by 0"); e2 = new IntegerExp(0, 1, e2->type); n2 = 1; } @@ -523,7 +525,7 @@ n1 = e1->toInteger(); n2 = e2->toInteger(); if (n2 == 0) - { error("divide by 0"); + { e2->error("divide by 0"); e2 = new IntegerExp(0, 1, e2->type); n2 = 1; } @@ -665,6 +667,8 @@ real_t r1; real_t r2; + //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); + assert(op == TOKequal || op == TOKnotequal); if (e1->op == TOKstring && e2->op == TOKstring) @@ -704,6 +708,41 @@ } } } + else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral) + { StructLiteralExp *es1 = (StructLiteralExp *)e1; + StructLiteralExp *es2 = (StructLiteralExp *)e2; + + if (es1->sd != es2->sd) + cmp = 0; + else if ((!es1->elements || !es1->elements->dim) && + (!es2->elements || !es2->elements->dim)) + cmp = 1; // both arrays are empty + else if (!es1->elements || !es2->elements) + cmp = 0; + else if (es1->elements->dim != es2->elements->dim) + cmp = 0; + else + { + cmp = 1; + for (size_t i = 0; i < es1->elements->dim; i++) + { Expression *ee1 = (Expression *)es1->elements->data[i]; + Expression *ee2 = (Expression *)es2->elements->data[i]; + + if (ee1 == ee2) + continue; + if (!ee1 || !ee2) + { cmp = 0; + break; + } + Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); + if (v == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + cmp = v->toInteger(); + if (cmp == 0) + break; + } + } + } #if 0 // Should handle this else if (e1->op == TOKarrayliteral && e2->op == TOKstring) { @@ -1011,14 +1050,31 @@ } else if (tb->isscalar()) e = new IntegerExp(loc, e1->toInteger(), type); + else if (tb->ty == Tvoid) + e = EXP_CANT_INTERPRET; + else if (tb->ty == Tstruct && e1->op == TOKint64) + { // Struct = 0; + StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration(); + assert(sd); + Expressions *elements = new Expressions; + for (size_t i = 0; i < sd->fields.dim; i++) + { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + + Expression *exp = new IntegerExp(0); + exp = Cast(v->type, v->type, exp); + if (exp == EXP_CANT_INTERPRET) + return exp; + elements->push(exp); + } + e = new StructLiteralExp(loc, sd, elements); + e->type = type; + } else { - if (tb->ty == Tvoid) - e = EXP_CANT_INTERPRET; - else - { error("cannot cast %s to %s", e1->type->toChars(), type->toChars()); - e = new IntegerExp(loc, 0, type); - } + error("cannot cast %s to %s", e1->type->toChars(), type->toChars()); + e = new IntegerExp(loc, 0, type); } return e; } @@ -1040,6 +1096,12 @@ dim = ale->elements ? ale->elements->dim : 0; e = new IntegerExp(loc, dim, type); } + else if (e1->op == TOKassocarrayliteral) + { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1; + size_t dim = ale->keys->dim; + + e = new IntegerExp(loc, dim, type); + } else e = EXP_CANT_INTERPRET; return e; @@ -1051,7 +1113,8 @@ { Expression *e = EXP_CANT_INTERPRET; Loc loc = e1->loc; - //printf("Index(e1->type = %p)\n", e1->type); + //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); + assert(e1->type); if (e1->op == TOKstring && e2->op == TOKint64) { StringExp *es1 = (StringExp *)e1; uinteger_t i = e2->toInteger(); @@ -1088,7 +1151,7 @@ uinteger_t i = e2->toInteger(); if (i >= length) - { error("array index %"PRIuMAX" is out of bounds [0 .. %"PRIuMAX"]", i, length); + { e2->error("array index %"PRIuMAX" is out of bounds %s[0 .. %"PRIuMAX"]", i, e1->toChars(), length); } else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; @@ -1096,6 +1159,40 @@ e->type = type; } } + else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64) + { + uinteger_t i = e2->toInteger(); + + if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) + { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; + if (i >= ale->elements->dim) + { e2->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); + } + else + { e = (Expression *)ale->elements->data[i]; + e->type = type; + } + } + } + else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2)) + { + AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1; + /* Search the keys backwards, in case there are duplicate keys + */ + for (size_t i = ae->keys->dim; i;) + { + i--; + Expression *ekey = (Expression *)ae->keys->data[i]; + Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); + if (ex == EXP_CANT_INTERPRET) + return ex; + if (ex->isBool(TRUE)) + { e = (Expression *)ae->values->data[i]; + e->type = type; + break; + } + } + } return e; } @@ -1166,6 +1263,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2) { Expression *e = EXP_CANT_INTERPRET; Loc loc = e1->loc; + Type *t; //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); @@ -1212,8 +1310,7 @@ e->type = type; return e; } - - if (e1->op == TOKstring && e2->op == TOKstring) + else if (e1->op == TOKstring && e2->op == TOKstring) { // Concatenate the strings void *s; @@ -1361,12 +1458,21 @@ } else if (e1->op == TOKnull && e2->op == TOKstring) { + t = e1->type; e = e2; goto L1; } else if (e1->op == TOKstring && e2->op == TOKnull) { e = e1; + t = e2->type; L1: + Type *tb = t->toBasetype(); + if (tb->ty == Tarray && tb->next->equals(e->type)) + { Expressions *expressions = new Expressions(); + expressions->push(e); + e = new ArrayLiteralExp(loc, expressions); + e->type = t; + } if (!e->type->equals(type)) { StringExp *se = (StringExp *)e->copy(); e = se->castTo(NULL, type); @@ -1375,4 +1481,23 @@ return e; } +Expression *Ptr(Type *type, Expression *e1) +{ + //printf("Ptr(e1 = %s)\n", e1->toChars()); + if (e1->op == TOKadd) + { AddExp *ae = (AddExp *)e1; + if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) + { AddrExp *ade = (AddrExp *)ae->e1; + if (ade->e1->op == TOKstructliteral) + { StructLiteralExp *se = (StructLiteralExp *)ade->e1; + unsigned offset = ae->e2->toInteger(); + Expression *e = se->getField(type, offset); + if (!e) + e = EXP_CANT_INTERPRET; + return e; + } + } + } + return EXP_CANT_INTERPRET; +} diff -uNr gdc-0.23/d/dmd/declaration.c gdc-0.24/d/dmd/declaration.c --- gdc-0.23/d/dmd/declaration.c 2007-03-04 14:46:20.000000000 +0100 +++ gdc-0.24/d/dmd/declaration.c 2007-07-23 02:23:26.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -143,9 +143,9 @@ buf.printf("_%s_%d", ident->toChars(), i); char *name = (char *)buf.extractData(); Identifier *id = new Identifier(name, TOKidentifier); - Argument *arg = new Argument(In, t, id, NULL); + Argument *arg = new Argument(STCin, t, id, NULL); #else - Argument *arg = new Argument(In, t, NULL, NULL); + Argument *arg = new Argument(STCin, t, NULL, NULL); #endif args->data[i] = (void *)arg; } @@ -156,6 +156,26 @@ return tupletype; } +int TupleDeclaration::needThis() +{ + //printf("TupleDeclaration::needThis(%s)\n", toChars()); + for (size_t i = 0; i < objects->dim; i++) + { Object *o = (Object *)objects->data[i]; + if (o->dyncast() == DYNCAST_EXPRESSION) + { Expression *e = (Expression *)o; + if (e->op == TOKdsymbol) + { DsymbolExp *ve = (DsymbolExp *)e; + Declaration *d = ve->s->isDeclaration(); + if (d && d->needThis()) + { + return 1; + } + } + } + } + return 0; +} + /********************************* TypedefDeclaration ****************************/ TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) @@ -362,50 +382,49 @@ // toAlias() will return aliasssym. Dsymbol *s; + Type *t; + Expression *e; - if (type->ty == Tident) - { - TypeIdentifier *ti = (TypeIdentifier *)type; + /* This section is needed because resolve() will: + * const x = 3; + * alias x y; + * try to alias y to 3. + */ + s = type->toDsymbol(sc); + if (s) + goto L2; // it's a symbolic alias - s = ti->toDsymbol(sc); - if (s) - goto L2; // it's a symbolic alias + //printf("alias type is %s\n", type->toChars()); + type->resolve(loc, sc, &e, &t, &s); + if (s) + { + goto L2; } - else if (type->ty == Tinstance) + else if (e) { - // 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(loc, id, 0); - if (!s) // failed to find a symbol - goto L1; // it must be a type - s = s->toAlias(); - } + // Try to convert Expression to Dsymbol + if (e->op == TOKvar) + { s = ((VarExp *)e)->var; goto L2; } + else if (e->op == TOKfunction) + { s = ((FuncExp *)e)->fd; + goto L2; + } + else + { error("cannot alias an expression %s", e->toChars()); + t = e->type; + } } - L1: + else if (t) + type = t; if (overnext) ScopeDsymbol::multiplyDefined(0, this, overnext); - type = type->semantic(loc, sc); this->inSemantic = 0; return; L2: + //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); type = NULL; VarDeclaration *v = s->isVarDeclaration(); if (v && v->linkage == LINKdefault) @@ -415,7 +434,7 @@ } else { - FuncDeclaration *f = s->isFuncDeclaration(); + FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); if (f) { if (overnext) @@ -469,7 +488,7 @@ Dsymbol *AliasDeclaration::toAlias() { - //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym->kind()); + //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); assert(this != aliassym); //static int count; if (++count == 10) *(char*)0=0; if (inSemantic) @@ -538,6 +557,7 @@ ctorinit = 0; aliassym = NULL; onstack = 0; + canassign = 0; value = NULL; } @@ -586,6 +606,8 @@ void VarDeclaration::semantic(Scope *sc) { //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); + //printf("type = %s\n", type->toChars()); + //printf("linkage = %d\n", sc->linkage); //if (strcmp(toChars(), "mul") == 0) halt(); storage_class |= sc->stc; @@ -745,15 +767,15 @@ if (type->isauto() && !noauto) { - if (storage_class & (STCfield | STCout | STCstatic) || !fd) + if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) { - error("globals, statics, fields, inout and out parameters cannot be auto"); + error("globals, statics, fields, ref and out parameters cannot be auto"); } if (!(storage_class & (STCauto | STCscope))) { if (!(storage_class & STCparameter) && ident != Id::withSym) - error("reference to auto class must be auto"); + error("reference to scope class must be scope"); } } @@ -793,6 +815,12 @@ if (init) { + ArrayInitializer *ai = init->isArrayInitializer(); + if (ai && type->toBasetype()->ty == Taarray) + { + init = ai->toAssocArrayInitializer(); + } + ExpInitializer *ei = init->isExpInitializer(); // See if we can allocate on the stack @@ -862,7 +890,10 @@ ei->exp = new CastExp(loc, ei->exp, type); } ei->exp = new AssignExp(loc, e1, ei->exp); + ei->exp->op = TOKconstruct; + canassign++; ei->exp = ei->exp->semantic(sc); + canassign--; ei->exp->optimize(WANTvalue); } else @@ -874,7 +905,7 @@ } } } - else if (isConst()) + else if (isConst() || isFinal()) { /* Because we may need the results of a const declaration in a * subsequent type, such as an array dimension, before semantic2() @@ -980,6 +1011,7 @@ int VarDeclaration::needThis() { + //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); return storage_class & STCfield; } diff -uNr gdc-0.23/d/dmd/declaration.h gdc-0.24/d/dmd/declaration.h --- gdc-0.23/d/dmd/declaration.h 2007-03-04 16:21:12.000000000 +0100 +++ gdc-0.24/d/dmd/declaration.h 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -66,6 +66,8 @@ STCctorinit = 0x20000, // can only be set inside constructor STCtemplateparameter = 0x40000, // template parameter STCscope = 0x80000, // template parameter + STCinvariant = 0x100000, + STCref = 0x200000, }; struct Match @@ -78,6 +80,9 @@ }; void overloadResolveX(Match *m, FuncDeclaration *f, Expressions *arguments); +int overloadApply(FuncDeclaration *fstart, + int (*fp)(void *, FuncDeclaration *), + void *param); /**************************************************************/ @@ -117,7 +122,7 @@ int isIn() { return storage_class & STCin; } int isOut() { return storage_class & STCout; } - int isInOut() { return (storage_class & (STCin | STCout)) == (STCin | STCout); } + int isRef() { return storage_class & STCref; } enum PROT prot(); @@ -137,6 +142,7 @@ Dsymbol *syntaxCopy(Dsymbol *); char *kind(); Type *getType(); + int needThis(); TupleDeclaration *isTupleDeclaration() { return this; } }; @@ -217,6 +223,7 @@ int ctorinit; // it has been initialized in a ctor int onstack; // 1: it has been allocated on the stack // 2: on stack, run destructor anyway + int canassign; // it can be assigned to Dsymbol *aliassym; // if redone as alias to another symbol Expression *value; // when interpreting, this is the value // (NULL if value not determinable) @@ -514,6 +521,7 @@ FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } char *kind(); + Symbol *toSymbol(); }; struct FuncLiteralDeclaration : FuncDeclaration diff -uNr gdc-0.23/d/dmd/delegatize.c gdc-0.24/d/dmd/delegatize.c --- gdc-0.23/d/dmd/delegatize.c 2007-01-03 06:28:37.000000000 +0100 +++ gdc-0.24/d/dmd/delegatize.c 2007-04-29 20:05:44.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -177,6 +177,19 @@ } +void AssocArrayLiteralExp::scanForNestedRef(Scope *sc) +{ + arrayExpressionScanForNestedRef(sc, keys); + arrayExpressionScanForNestedRef(sc, values); +} + + +void StructLiteralExp::scanForNestedRef(Scope *sc) +{ + arrayExpressionScanForNestedRef(sc, elements); +} + + void TupleExp::scanForNestedRef(Scope *sc) { arrayExpressionScanForNestedRef(sc, exps); diff -uNr gdc-0.23/d/dmd/doc.c gdc-0.24/d/dmd/doc.c --- gdc-0.23/d/dmd/doc.c 2006-12-26 21:57:51.000000000 +0100 +++ gdc-0.24/d/dmd/doc.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -259,6 +259,8 @@ Macro::define(¯otable, (unsigned char *)"DATETIME", 8, (unsigned char *)p, strlen(p)); Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); + char *docfilename = docfile->toChars(); + Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); if (dc->copyright) { diff -uNr gdc-0.23/d/dmd/doc.h gdc-0.24/d/dmd/doc.h --- gdc-0.23/d/dmd/doc.h 2006-11-11 21:41:32.000000000 +0100 +++ gdc-0.24/d/dmd/doc.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/dsymbol.c gdc-0.24/d/dmd/dsymbol.c --- gdc-0.23/d/dmd/dsymbol.c 2007-02-15 13:38:36.000000000 +0100 +++ gdc-0.24/d/dmd/dsymbol.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -27,6 +27,7 @@ #include "scope.h" #include "init.h" #include "import.h" +#include "template.h" /****************************** Dsymbol ******************************/ @@ -263,8 +264,57 @@ { //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; +} + +/*************************************** + * Search for identifier id as a member of 'this'. + * id may be a template instance. + * Returns: + * symbol found, NULL if not + */ + +Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) +{ + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident->toChars()); + Dsymbol *s = toAlias(); + Dsymbol *sm; + + switch (id->dyncast()) + { + case DYNCAST_IDENTIFIER: + sm = s->search(loc, id, 0); + break; + + case DYNCAST_DSYMBOL: + { // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol *st = (Dsymbol *)id; + TemplateInstance *ti = st->isTemplateInstance(); + id = ti->name; + sm = s->search(loc, id, 0); + if (!sm) + { error("template identifier %s is not a member of %s %s", + id->toChars(), s->kind(), s->toChars()); + return NULL; + } + sm = sm->toAlias(); + TemplateDeclaration *td = sm->isTemplateDeclaration(); + if (!td) + { + error("%s is not a template, it is a %s", id->toChars(), sm->kind()); + return NULL; + } + ti->tempdecl = td; + if (!ti->semanticdone) + ti->semantic(sc); + sm = ti->toAlias(); + break; + } + + default: + assert(0); + } + return sm; } int Dsymbol::overloadInsert(Dsymbol *s) @@ -679,11 +729,11 @@ } else { - s1->error(loc, "conflicts with %s at %s", + s1->error(loc, "conflicts with %s %s at %s", + s2->kind(), s2->toPrettyChars(), s2->locToChars()); } -//*(char*)0=0; } Dsymbol *ScopeDsymbol::nameCollision(Dsymbol *s) @@ -766,7 +816,7 @@ if (td) { - VarDeclaration *v = new VarDeclaration(0, Type::tsize_t, Id::dollar, NULL); + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCconst; @@ -775,7 +825,7 @@ if (type) { - VarDeclaration *v = new VarDeclaration(0, Type::tsize_t, Id::dollar, NULL); + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCconst; @@ -810,7 +860,7 @@ if (!*pvar) { - VarDeclaration *v = new VarDeclaration(0, Type::tsize_t, Id::dollar, NULL); + VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); if (ce->op == TOKstring) { /* It is for a string literal, so the @@ -820,6 +870,14 @@ v->init = new ExpInitializer(0, e); v->storage_class |= STCconst; } + else if (ce->op == TOKarrayliteral) + { /* It is for an array literal, so the + * length will be a const. + */ + Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); + v->init = new ExpInitializer(0, e); + v->storage_class |= STCconst; + } else if (ce->op == TOKtuple) { /* It is for an expression tuple, so the * length will be a const. diff -uNr gdc-0.23/d/dmd/dsymbol.h gdc-0.24/d/dmd/dsymbol.h --- gdc-0.23/d/dmd/dsymbol.h 2007-02-15 13:36:30.000000000 +0100 +++ gdc-0.24/d/dmd/dsymbol.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -123,6 +123,7 @@ virtual void semantic3(Scope *sc); virtual void inlineScan(); virtual Dsymbol *search(Loc loc, Identifier *ident, int flags); + Dsymbol *searchX(Loc loc, Scope *sc, Identifier *id); virtual int overloadInsert(Dsymbol *s); #ifdef _DH char *toHChars(); diff -uNr gdc-0.23/d/dmd/dump.c gdc-0.24/d/dmd/dump.c --- gdc-0.23/d/dmd/dump.c 2006-12-06 09:20:33.000000000 +0100 +++ gdc-0.24/d/dmd/dump.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/entity.c gdc-0.24/d/dmd/entity.c --- gdc-0.23/d/dmd/entity.c 2006-06-03 04:57:43.000000000 +0200 +++ gdc-0.24/d/dmd/entity.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/enum.c gdc-0.24/d/dmd/enum.c --- gdc-0.23/d/dmd/enum.c 2007-01-03 06:28:37.000000000 +0100 +++ gdc-0.24/d/dmd/enum.c 2007-04-29 20:05:44.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -32,6 +32,7 @@ maxval = 0; minval = 0; defaultval = 0; + sinit = NULL; attributes = NULL; } diff -uNr gdc-0.23/d/dmd/enum.h gdc-0.24/d/dmd/enum.h --- gdc-0.23/d/dmd/enum.h 2006-12-26 00:25:25.000000000 +0100 +++ gdc-0.24/d/dmd/enum.h 2007-04-29 20:05:44.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -31,6 +31,7 @@ struct HdrGenState; #endif + struct EnumDeclaration : ScopeDsymbol { Type *type; // the TypeEnum @@ -56,6 +57,9 @@ void toObjFile(); // compile to .obj file void toDebug(); int cvMember(unsigned char *p); + + Symbol *sinit; + Symbol *toInitializer(); }; diff -uNr gdc-0.23/d/dmd/expression.c gdc-0.24/d/dmd/expression.c --- gdc-0.23/d/dmd/expression.c 2007-03-04 14:47:46.000000000 +0100 +++ gdc-0.24/d/dmd/expression.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -39,7 +39,7 @@ #elif linux #include "../root/mem.h" #endif -#include "port.h" +//#include "port.h" #include "mtype.h" #include "init.h" #include "expression.h" @@ -299,10 +299,30 @@ void expandTuples(Expressions *exps) { + //printf("expandTuples()\n"); if (exps) { for (size_t i = 0; i < exps->dim; i++) { Expression *arg = (Expression *)exps->data[i]; + if (!arg) + continue; + + // Look for tuple with 0 members + if (arg->op == TOKtype) + { TypeExp *e = (TypeExp *)arg; + if (e->type->toBasetype()->ty == Ttuple) + { TypeTuple *tt = (TypeTuple *)e->type->toBasetype(); + + if (!tt->arguments || tt->arguments->dim == 0) + { + exps->remove(i); + if (i == exps->dim) + return; + i--; + continue; + } + } + } // Inline expand all the tuples while (arg->op == TOKtuple) @@ -495,21 +515,16 @@ } L1: - if (!(p->inout == Lazy && p->type->ty == Tvoid)) + if (!(p->storageClass & STClazy && p->type->ty == Tvoid)) arg = arg->implicitCastTo(sc, p->type); - if (p->inout == Out || p->inout == InOut) + if (p->storageClass & (STCout | STCref)) { - // BUG: should check that argument to inout is type 'invariant' - // BUG: assignments to inout should also be type 'invariant' + // BUG: should check that argument to ref is type 'invariant' + // BUG: assignments to ref 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 @@ -520,7 +535,7 @@ } // Convert lazy argument to a delegate - if (p->inout == Lazy) + if (p->storageClass & STClazy) { arg = arg->toDelegate(sc, p->type); } @@ -661,7 +676,14 @@ { Expression *e; if (!size) + { +#ifdef DEBUG fprintf(stdmsg, "No expression copy for: %s\n", toChars()); + printf("op = %d\n", op); + dump(0); +#endif + assert(0); + } e = (Expression *)mem.malloc(size); return (Expression *)memcpy(e, this, size); } @@ -854,8 +876,14 @@ int Expression::checkSideEffect(int flag) { if (flag == 0) - error("%s has no effect in expression (%s)", + { if (op == TOKimport) + { + error("%s has no effect", toChars()); + } + else + error("%s has no effect in expression (%s)", Token::toChars(op), toChars()); + } return 0; } @@ -1005,10 +1033,14 @@ char *IntegerExp::toChars() { +#if 1 + return Expression::toChars(); +#else static char buffer[sizeof(value) * 3 + 1]; sprintf(buffer, "%"PRIdMAX, value); return buffer; +#endif } integer_t IntegerExp::toInteger() @@ -1148,7 +1180,9 @@ break; } case Tchar: - if (isprint(v) && v != '\\') + if (v == '\'') + buf->writestring("'\\''"); + else if (isprint(v) && v != '\\') buf->printf("'%c'", (int)v); else buf->printf("'\\x%02x'", (int)v); @@ -1248,7 +1282,7 @@ integer_t RealExp::toInteger() { #ifdef IN_GCC - return toReal().toInt(); + return (d_int64) toReal().toInt(); #else return (sinteger_t) toReal(); #endif @@ -1495,7 +1529,7 @@ integer_t ComplexExp::toInteger() { #ifdef IN_GCC - return (sinteger_t) toReal().toInt(); + return (d_int64) toReal().toInt(); #else return (sinteger_t) toReal(); #endif @@ -1645,7 +1679,7 @@ if (ti && !ti->isTemplateMixin() && - (ti->idents.data[ti->idents.dim - 1] == f->ident || + (ti->name == f->ident || ti->toAlias()->ident == f->ident) && ti->tempdecl && ti->tempdecl->onemember) @@ -1859,23 +1893,8 @@ TupleDeclaration *tup = s->isTupleDeclaration(); if (tup) - { Expressions *exps = new Expressions(); - - exps->reserve(tup->objects->dim); - for (size_t i = 0; i < tup->objects->dim; i++) - { Object *o = (Object *)tup->objects->data[i]; - if (o->dyncast() != DYNCAST_EXPRESSION) - { - error("%s is not an expression", o->toChars()); - } - else - { - Expression *e = (Expression *)o; - e = e->syntaxCopy(); - exps->push(e); - } - } - e = new TupleExp(loc, exps); + { + e = new TupleExp(loc, tup); e = e->semantic(sc); return e; } @@ -2396,10 +2415,11 @@ { case '"': case '\\': - buf->writeByte('\\'); + if (!hgs->console) + buf->writeByte('\\'); default: if (c <= 0xFF) - { if (c <= 0x7F && isprint(c)) + { if (c <= 0x7F && (isprint(c) || hgs->console)) buf->writeByte(c); else buf->printf("\\x%02x", c); @@ -2479,6 +2499,13 @@ this->elements = elements; } +ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e) + : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp)) +{ + elements = new Expressions; + elements->push(e); +} + Expression *ArrayLiteralExp::syntaxCopy() { return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); @@ -2505,6 +2532,11 @@ if (!e->type) error("%s has no value", e->toChars()); e = resolveProperties(sc, e); + + unsigned char committed = 1; + if (e->op == TOKstring) + committed = ((StringExp *)e)->committed; + if (!t0) { t0 = e->type; // Convert any static arrays to dynamic arrays @@ -2516,6 +2548,10 @@ } else e = e->implicitCastTo(sc, t0); + if (!committed && e->op == TOKstring) + { StringExp *se = (StringExp *)e; + se->committed = 0; + } elements->data[i] = (void *)e; } @@ -2562,6 +2598,326 @@ } } +/************************ AssocArrayLiteralExp ************************************/ + +// [ key0 : value0, key1 : value1, ... ] + +AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc, + Expressions *keys, Expressions *values) + : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp)) +{ + assert(keys->dim == values->dim); + this->keys = keys; + this->values = values; +} + +Expression *AssocArrayLiteralExp::syntaxCopy() +{ + return new AssocArrayLiteralExp(loc, + arraySyntaxCopy(keys), arraySyntaxCopy(values)); +} + +Expression *AssocArrayLiteralExp::semantic(Scope *sc) +{ Expression *e; + Type *tkey = NULL; + Type *tvalue = NULL; + +#if LOGSEMANTIC + printf("AssocArrayLiteralExp::semantic('%s')\n", toChars()); +#endif + + // Run semantic() on each element + for (size_t i = 0; i < keys->dim; i++) + { Expression *key = (Expression *)keys->data[i]; + Expression *value = (Expression *)values->data[i]; + + key = key->semantic(sc); + value = value->semantic(sc); + + keys->data[i] = (void *)key; + values->data[i] = (void *)value; + } + expandTuples(keys); + expandTuples(values); + if (keys->dim != values->dim) + { + error("number of keys is %u, must match number of values %u", keys->dim, values->dim); + keys->setDim(0); + values->setDim(0); + } + for (size_t i = 0; i < keys->dim; i++) + { Expression *key = (Expression *)keys->data[i]; + Expression *value = (Expression *)values->data[i]; + + if (!key->type) + error("%s has no value", key->toChars()); + if (!value->type) + error("%s has no value", value->toChars()); + key = resolveProperties(sc, key); + value = resolveProperties(sc, value); + + if (!tkey) + tkey = key->type; + else + key = key->implicitCastTo(sc, tkey); + keys->data[i] = (void *)key; + + if (!tvalue) + tvalue = value->type; + else + value = value->implicitCastTo(sc, tvalue); + values->data[i] = (void *)value; + } + + if (!tkey) + tkey = Type::tvoid; + if (!tvalue) + tvalue = Type::tvoid; + type = new TypeAArray(tvalue, tkey); + type = type->semantic(loc, sc); + return this; +} + +int AssocArrayLiteralExp::checkSideEffect(int flag) +{ int f = 0; + + for (size_t i = 0; i < keys->dim; i++) + { Expression *key = (Expression *)keys->data[i]; + Expression *value = (Expression *)values->data[i]; + + f |= key->checkSideEffect(2); + f |= value->checkSideEffect(2); + } + if (flag == 0 && f == 0) + Expression::checkSideEffect(0); + return f; +} + +int AssocArrayLiteralExp::isBool(int result) +{ + size_t dim = keys->dim; + return result ? (dim != 0) : (dim == 0); +} + +void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writeByte('['); + for (size_t i = 0; i < keys->dim; i++) + { Expression *key = (Expression *)keys->data[i]; + Expression *value = (Expression *)values->data[i]; + + if (i) + buf->writeByte(','); + expToCBuffer(buf, hgs, key, PREC_assign); + buf->writeByte(':'); + expToCBuffer(buf, hgs, value, PREC_assign); + } + buf->writeByte(']'); +} + +void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf) +{ + size_t dim = keys->dim; + buf->printf("A%u", dim); + for (size_t i = 0; i < dim; i++) + { Expression *key = (Expression *)keys->data[i]; + Expression *value = (Expression *)values->data[i]; + + key->toMangleBuffer(buf); + value->toMangleBuffer(buf); + } +} + +/************************ StructLiteralExp ************************************/ + +// sd( e1, e2, e3, ... ) + +StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements) + : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp)) +{ + this->sd = sd; + this->elements = elements; + this->sym = NULL; + this->soffset = 0; + this->fillHoles = 1; +} + +Expression *StructLiteralExp::syntaxCopy() +{ + return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); +} + +Expression *StructLiteralExp::semantic(Scope *sc) +{ Expression *e; + +#if LOGSEMANTIC + printf("StructLiteralExp::semantic('%s')\n", toChars()); +#endif + + // Run semantic() on each element + for (size_t i = 0; i < elements->dim; i++) + { e = (Expression *)elements->data[i]; + if (!e) + continue; + e = e->semantic(sc); + elements->data[i] = (void *)e; + } + expandTuples(elements); + size_t offset = 0; + for (size_t i = 0; i < elements->dim; i++) + { e = (Expression *)elements->data[i]; + if (!e) + continue; + + if (!e->type) + error("%s has no value", e->toChars()); + e = resolveProperties(sc, e); + if (i >= sd->fields.dim) + { error("more initializers than fields of %s", sd->toChars()); + break; + } + Dsymbol *s = (Dsymbol *)sd->fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + if (v->offset < offset) + error("overlapping initialization for %s", v->toChars()); + offset = v->offset + v->type->size(); + + Type *telem = v->type; + while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray) + { /* Static array initialization, as in: + * T[3][5] = e; + */ + telem = telem->toBasetype()->nextOf(); + } + + e = e->implicitCastTo(sc, telem); + + elements->data[i] = (void *)e; + } + + /* Fill out remainder of elements[] with default initializers for fields[] + */ + for (size_t i = elements->dim; i < sd->fields.dim; i++) + { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + + if (v->offset < offset) + { e = NULL; + sd->hasUnions = 1; + } + else + { + if (v->init) + { e = v->init->toExpression(); + if (!e) + error("cannot make expression out of initializer for %s", v->toChars()); + } + else + { e = v->type->defaultInit(); + e->loc = loc; + } + offset = v->offset + v->type->size(); + } + elements->push(e); + } + + type = sd->type; + return this; +} + +/************************************** + * Gets expression at offset of type. + * Returns NULL if not found. + */ + +Expression *StructLiteralExp::getField(Type *type, unsigned offset) +{ Expression *e = NULL; + int i = getFieldIndex(type, offset); + + if (i != -1) + { e = (Expression *)elements->data[i]; + if (e) + { + e = e->copy(); + e->type = type; + } + } + return e; +} + +/************************************ + * Get index of field. + * Returns -1 if not found. + */ + +int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) +{ + /* Find which field offset is by looking at the field offsets + */ + for (size_t i = 0; i < sd->fields.dim; i++) + { + Dsymbol *s = (Dsymbol *)sd->fields.data[i]; + VarDeclaration *v = s->isVarDeclaration(); + assert(v); + + if (offset == v->offset && + type->size() == v->type->size()) + { Expression *e = (Expression *)elements->data[i]; + if (e) + { + return i; + } + break; + } + } + return -1; +} + + +Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) +{ + return this; +} + + +int StructLiteralExp::checkSideEffect(int flag) +{ int f = 0; + + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + if (!e) + continue; + + f |= e->checkSideEffect(2); + } + if (flag == 0 && f == 0) + Expression::checkSideEffect(0); + return f; +} + +void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) +{ + buf->writestring(sd->toChars()); + buf->writeByte('('); + argsToCBuffer(buf, elements, hgs); + buf->writeByte(')'); +} + +void StructLiteralExp::toMangleBuffer(OutBuffer *buf) +{ + size_t dim = elements ? elements->dim : 0; + buf->printf("S%u", dim); + for (size_t i = 0; i < dim; i++) + { Expression *e = (Expression *)elements->data[i]; + if (e) + e->toMangleBuffer(buf); + else + buf->writeByte('v'); // 'v' for void + } +} + /************************ TypeDotIdExp ************************************/ /* Things like: @@ -2786,6 +3142,7 @@ } else type = newtype->semantic(loc, sc); + newtype = type; // in case type gets cast to something else tb = type->toBasetype(); //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco); @@ -2804,7 +3161,7 @@ ClassDeclaration *cd = tc->sym->isClassDeclaration(); if (cd->isInterfaceDeclaration()) error("cannot create instance of interface %s", cd->toChars()); - if (cd->isAbstract()) + else if (cd->isAbstract()) error("cannot create instance of abstract class %s", cd->toChars()); checkDeprecated(sc, cd); if (cd->isNested()) @@ -3128,7 +3485,7 @@ if (v) { if (!v->isDataseg()) - error("escaping reference to local %s", v->toChars()); + error("escaping reference to local variable %s", v->toChars()); } } @@ -3253,8 +3610,10 @@ 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()); + VarDeclaration *v = var->isVarDeclaration(); + if (v && v->canassign == 0 && + (var->isConst() || (global.params.Dversion > 1 && var->isFinal()))) + error("cannot modify final variable '%s'", var->toChars()); if (var->isCtorinit()) { // It's only modifiable if inside the right constructor @@ -3307,6 +3666,41 @@ this->type = NULL; } + +TupleExp::TupleExp(Loc loc, TupleDeclaration *tup) + : Expression(loc, TOKtuple, sizeof(TupleExp)) +{ + exps = new Expressions(); + type = NULL; + + exps->reserve(tup->objects->dim); + for (size_t i = 0; i < tup->objects->dim; i++) + { Object *o = (Object *)tup->objects->data[i]; + if (o->dyncast() == DYNCAST_EXPRESSION) + { + Expression *e = (Expression *)o; + e = e->syntaxCopy(); + exps->push(e); + } + else if (o->dyncast() == DYNCAST_DSYMBOL) + { + Dsymbol *s = (Dsymbol *)o; + Expression *e = new DsymbolExp(loc, s); + exps->push(e); + } + else if (o->dyncast() == DYNCAST_TYPE) + { + Type *t = (Type *)o; + Expression *e = new TypeExp(loc, t); + exps->push(e); + } + else + { + error("%s is not an expression", o->toChars()); + } + } +} + int TupleExp::equals(Object *o) { TupleExp *ne; @@ -3716,7 +4110,7 @@ args->reserve(cd->baseclasses.dim); for (size_t i = 0; i < cd->baseclasses.dim; i++) { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; - args->push(new Argument(In, b->type, NULL, NULL)); + args->push(new Argument(STCin, b->type, NULL, NULL)); } tded = new TypeTuple(args); } @@ -3749,7 +4143,7 @@ for (size_t i = 0; i < dim; i++) { Argument *arg = Argument::getNth(params, i); assert(arg && arg->type); - args->push(new Argument(arg->inout, arg->type, NULL, NULL)); + args->push(new Argument(arg->storageClass, arg->type, NULL, NULL)); } tded = new TypeTuple(args); break; @@ -4067,12 +4461,14 @@ e1 = e1->optimize(WANTvalue | WANTinterpret); if (e1->op != TOKstring) { error("argument to mixin must be a string, not (%s)", e1->toChars()); + type = Type::terror; return this; } StringExp *se = (StringExp *)e1; se = se->toUTF8(sc); Parser p(sc->module, (unsigned char *)se->string, se->len, 0); p.loc = loc; + p.nextToken(); Expression *e = p.parseExpression(); if (p.token.value != TOKeof) error("incomplete mixin expression (%s)", se->toChars()); @@ -4441,6 +4837,12 @@ #endif assert(0); } + else if (ident == Id::stringof) + { char *s = ie->toChars(); + e = new StringExp(loc, s, strlen(s), 'c'); + e = e->semantic(sc); + return e; + } error("undefined identifier %s", toChars()); type = Type::tvoid; return this; @@ -4747,10 +5149,10 @@ } assert(s); - id = (Identifier *)ti->idents.data[0]; + id = ti->name; s2 = s->search(loc, id, 0); if (!s2) - { error("template identifier %s is not a member of %s", id->toChars(), s->ident->toChars()); + { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars()); goto Lerr; } s = s2; @@ -5036,6 +5438,24 @@ e1 = new DsymbolExp(loc, se->sds); e1 = e1->semantic(sc); } +#if 1 // patch for #540 by Oskar Linde + else if (e1->op == TOKdotexp) + { + DotExp *de = (DotExp *) e1; + + if (de->e2->op == TOKimport) + { // This should *really* be moved to ScopeExp::semantic() + ScopeExp *se = (ScopeExp *)de->e2; + de->e2 = new DsymbolExp(loc, se->sds); + de->e2 = de->e2->semantic(sc); + } + + if (de->e2->op == TOKtemplate) + { TemplateExp *te = (TemplateExp *) de->e2; + e1 = new DotTemplateExp(loc,de->e1,te->td); + } + } +#endif } if (e1->op == TOKcomma) @@ -5057,14 +5477,21 @@ if (t1) { AggregateDeclaration *ad; - if (t1->ty == Tclass) + if (t1->ty == Tstruct) { - ad = ((TypeClass *)t1)->sym; - goto L1; + ad = ((TypeStruct *)t1)->sym; + if (search_function(ad, Id::call)) + goto L1; // overload of opCall, therefore it's a call + /* It's a struct literal + */ + Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments); + e = e->semantic(sc); + return e; } - else if (t1->ty == Tstruct) + else if (t1->ty == Tclass) { - ad = ((TypeStruct *)t1)->sym; + ad = ((TypeClass *)t1)->sym; + goto L1; L1: // Rewrite as e1.call(arguments) Expression *e = new DotIdExp(loc, e1, Id::call); @@ -5313,7 +5740,7 @@ { TemplateInstance *ti = f->parent->isTemplateInstance(); if (ti && - (ti->idents.data[ti->idents.dim - 1] == f->ident || + (ti->name == f->ident || ti->toAlias()->ident == f->ident) && ti->tempdecl) @@ -5807,7 +6234,8 @@ return e; } } - return e1->castTo(sc, to); + e = e1->castTo(sc, to); + return e; } int CastExp::checkSideEffect(int flag) @@ -5830,7 +6258,7 @@ VarDeclaration *v = ve->var->isVarDeclaration(); if (v) { - if (!v->isDataseg()) + if (!v->isDataseg() && !v->isParameter()) error("escaping reference to local %s", v->toChars()); } } @@ -5941,6 +6369,7 @@ if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple) { sym = new ArrayScopeSymbol(this); + sym->loc = loc; sym->parent = sc->scopesym; sc = sc->push(sym); } @@ -6251,6 +6680,7 @@ IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2) : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2) { + //printf("IndexExp::IndexExp('%s')\n", toChars()); lengthVar = NULL; modifiable = 0; // assume it is an rvalue } @@ -6267,6 +6697,8 @@ #endif if (type) return this; + if (!e1->type) + e1 = e1->semantic(sc); assert(e1->type); // semantic() should already be run on it e = this; @@ -6277,6 +6709,7 @@ if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple) { // Create scope for 'length' variable sym = new ArrayScopeSymbol(this); + sym->loc = loc; sym->parent = sc->scopesym; sc = sc->push(sym); } @@ -6451,6 +6884,7 @@ AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2) : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2) { + ismemset = 0; } Expression *AssignExp::semantic(Scope *sc) @@ -6825,7 +7259,7 @@ } else { - error("Can only append to dynamic arrays, not %s ~= %s", tb1->toChars(), tb2->toChars()); + error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); type = Type::tint32; e = this; } @@ -7252,7 +7686,7 @@ Expression *CatExp::semantic(Scope *sc) { Expression *e; - //printf("CatExp::semantic()\n"); + //printf("CatExp::semantic() %s\n", toChars()); if (!type) { BinExp::semanticp(sc); @@ -7278,12 +7712,22 @@ e2->type->equals(tb1->next)) { type = tb1->next->arrayOf(); + if (tb2->ty == Tarray) + { // Make e2 into [e2] + e2 = new ArrayLiteralExp(e2->loc, e2); + e2->type = type; + } return this; } else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && e1->type->equals(tb2->next)) { type = tb2->next->arrayOf(); + if (tb1->ty == Tarray) + { // Make e1 into [e1] + e1 = new ArrayLiteralExp(e1->loc, e1); + e1->type = type; + } return this; } @@ -7328,8 +7772,13 @@ Expression *MulExp::semantic(Scope *sc) { Expression *e; +#if 0 + printf("MulExp::semantic() %s\n", toChars()); +#endif if (type) + { return this; + } BinExp::semanticp(sc); e = op_overload(sc); @@ -8032,6 +8481,9 @@ unsigned cs0; unsigned cs1; +#if LOGSEMANTIC + printf("CondExp::semantic('%s')\n", toChars()); +#endif if (type) return this; @@ -8084,6 +8536,22 @@ else { typeCombine(sc); + switch (e1->type->toBasetype()->ty) + { + case Tcomplex32: + case Tcomplex64: + case Tcomplex80: + e2 = e2->castTo(sc, e1->type); + break; + } + switch (e2->type->toBasetype()->ty) + { + case Tcomplex32: + case Tcomplex64: + case Tcomplex80: + e1 = e1->castTo(sc, e2->type); + break; + } } return this; } diff -uNr gdc-0.23/d/dmd/expression.h gdc-0.24/d/dmd/expression.h --- gdc-0.23/d/dmd/expression.h 2007-03-04 14:49:16.000000000 +0100 +++ gdc-0.24/d/dmd/expression.h 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -24,6 +24,7 @@ struct Type; struct Scope; +struct TupleDeclaration; struct VarDeclaration; struct FuncDeclaration; struct FuncLiteralDeclaration; @@ -40,12 +41,14 @@ struct Expression; struct Declaration; struct AggregateDeclaration; +struct StructDeclaration; struct TemplateInstance; struct TemplateDeclaration; struct ClassDeclaration; struct HdrGenState; struct BinExp; struct InterState; +struct Symbol; // back end symbol enum TOK; @@ -102,7 +105,7 @@ virtual Expression *toLvalue(Scope *sc, Expression *e); virtual Expression *modifiableLvalue(Scope *sc, Expression *e); Expression *implicitCastTo(Scope *sc, Type *t); - virtual int implicitConvTo(Type *t); + virtual MATCH implicitConvTo(Type *t); virtual Expression *castTo(Scope *sc, Type *t); virtual void checkEscape(); void checkScalar(); @@ -162,7 +165,7 @@ complex_t toComplex(); int isConst(); int isBool(int result); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); Expression *toLvalue(Scope *sc, Expression *e); @@ -289,7 +292,7 @@ int isBool(int result); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toMangleBuffer(OutBuffer *buf); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); Expression *interpret(InterState *istate); elem *toElem(IRState *irs); @@ -313,7 +316,7 @@ Expression *semantic(Scope *sc); Expression *interpret(InterState *istate); StringExp *toUTF8(Scope *sc); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); int compare(Object *obj); int isBool(int result); @@ -330,6 +333,7 @@ Expressions *exps; TupleExp(Loc loc, Expressions *exps); + TupleExp(Loc loc, TupleDeclaration *tup); Expression *syntaxCopy(); int equals(Object *o); Expression *semantic(Scope *sc); @@ -351,6 +355,7 @@ Expressions *elements; ArrayLiteralExp(Loc loc, Expressions *elements); + ArrayLiteralExp(Loc loc, Expression *e); Expression *syntaxCopy(); Expression *semantic(Scope *sc); @@ -362,8 +367,65 @@ void scanForNestedRef(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + dt_t **toDt(dt_t **pdt); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Expression *inlineScan(InlineScanState *iss); +}; + +struct AssocArrayLiteralExp : Expression +{ + Expressions *keys; + Expressions *values; + + AssocArrayLiteralExp(Loc loc, Expressions *keys, Expressions *values); + + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + int isBool(int result); + elem *toElem(IRState *irs); + int checkSideEffect(int flag); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void toMangleBuffer(OutBuffer *buf); + void scanForNestedRef(Scope *sc); + Expression *optimize(int result); + Expression *interpret(InterState *istate); + MATCH implicitConvTo(Type *t); + Expression *castTo(Scope *sc, Type *t); + + int inlineCost(InlineCostState *ics); + Expression *doInline(InlineDoState *ids); + Expression *inlineScan(InlineScanState *iss); +}; + +struct StructLiteralExp : Expression +{ + StructDeclaration *sd; // which aggregate this is for + Expressions *elements; // parallels sd->fields[] with + // NULL entries for fields to skip + + Symbol *sym; // back end symbol to initialize with literal + size_t soffset; // offset from start of s + int fillHoles; // fill alignment 'holes' with zero + + StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements); + + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + Expression *getField(Type *type, unsigned offset); + int getFieldIndex(Type *type, unsigned offset); + elem *toElem(IRState *irs); + int checkSideEffect(int flag); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); + void toMangleBuffer(OutBuffer *buf); + void scanForNestedRef(Scope *sc); + Expression *optimize(int result); + Expression *interpret(InterState *istate); + dt_t **toDt(dt_t **pdt); + Expression *toLvalue(Scope *sc, Expression *e); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -468,7 +530,7 @@ int isConst(); int isBool(int result); Expression *doInline(InlineDoState *ids); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void scanForNestedRef(Scope *sc); @@ -485,6 +547,7 @@ VarExp(Loc loc, Declaration *var); int equals(Object *o); Expression *semantic(Scope *sc); + Expression *optimize(int result); Expression *interpret(InterState *istate); void dump(int indent); char *toChars(); @@ -621,7 +684,7 @@ void scanForNestedRef(Scope *sc); Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *)); - Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); + Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -720,7 +783,7 @@ DelegateExp(Loc loc, Expression *e, FuncDeclaration *func); Expression *semantic(Scope *sc); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); @@ -769,7 +832,7 @@ AddrExp(Loc loc, Expression *e); Expression *semantic(Scope *sc); elem *toElem(IRState *irs); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); Expression *optimize(int result); }; @@ -783,6 +846,7 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); Expression *optimize(int result); + Expression *interpret(InterState *istate); }; struct NegExp : UnaExp @@ -978,7 +1042,8 @@ }; struct AssignExp : BinExp -{ +{ int ismemset; // !=0 if setting the contents of an array + AssignExp(Loc loc, Expression *e1, Expression *e2); Expression *semantic(Scope *sc); Expression *checkToBoolean(); @@ -1291,7 +1356,7 @@ Expression *checkToBoolean(); int checkSideEffect(int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); - int implicitConvTo(Type *t); + MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); void scanForNestedRef(Scope *sc); @@ -1311,6 +1376,7 @@ #define EXP_CONTINUE_INTERPRET ((Expression *)2) #define EXP_BREAK_INTERPRET ((Expression *)3) #define EXP_GOTO_INTERPRET ((Expression *)4) +#define EXP_VOID_INTERPRET ((Expression *)5) Expression *expType(Type *type, Expression *e); @@ -1320,6 +1386,7 @@ Expression *Bool(Type *type, Expression *e1); Expression *Cast(Type *type, Type *to, Expression *e1); Expression *ArrayLength(Type *type, Expression *e1); +Expression *Ptr(Type *type, Expression *e1); Expression *Add(Type *type, Expression *e1, Expression *e2); Expression *Min(Type *type, Expression *e1, Expression *e2); diff -uNr gdc-0.23/d/dmd/func.c gdc-0.24/d/dmd/func.c --- gdc-0.23/d/dmd/func.c 2007-03-04 16:21:36.000000000 +0100 +++ gdc-0.24/d/dmd/func.c 2007-07-27 02:07:14.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -74,7 +74,7 @@ fes = NULL; introducing = 0; tintro = NULL; - inferRetType = (type && type->next == NULL); + inferRetType = (type && type->nextOf() == NULL); scope = NULL; hasReturnExp = 0; nrvo_can = 1; @@ -116,7 +116,7 @@ printf("type: %s\n", type->toChars()); #endif - if (type->next) + if (type->nextOf()) type = type->semantic(loc, sc); //type->print(); if (type->ty != Tfunction) @@ -155,7 +155,7 @@ #if 0 if (isStaticConstructor() || isStaticDestructor()) { - if (!isStatic() || type->next->ty != Tvoid) + if (!isStatic() || type->nextOf()->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"); @@ -327,7 +327,7 @@ * offsets differ */ target_ptrdiff_t offset; - if (fdv->type->next->isBaseOf(type->next, &offset)) + if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) { tintro = fdv->type; } @@ -344,19 +344,21 @@ } // This is an 'introducing' function. + + // Verify this doesn't override previous final function + if (cd->baseClass) + { Dsymbol *s = cd->baseClass->search(loc, ident, 0); + if (s) + { + FuncDeclaration *f = s->isFuncDeclaration(); + f = f->overloadExactMatch(type); + if (f && f->isFinal() && f->prot() != PROTprivate) + error("cannot override final function %s", f->toPrettyChars()); + } + } + if (isFinal()) { - // Verify this doesn't override previous final function - if (cd->baseClass) - { Dsymbol *s = cd->baseClass->search(loc, ident, 0); - if (s) - { - FuncDeclaration *f = s->isFuncDeclaration(); - f = f->overloadExactMatch(type); - if (f && f->isFinal()) - error("cannot override final function %s", f->toPrettyChars()); - } - } cd->vtblFinal.push(this); } else @@ -406,7 +408,7 @@ * offsets differ */ target_ptrdiff_t offset; - if (fdv->type->next->isBaseOf(type->next, &offset)) + if (fdv->type->nextOf()->isBaseOf(type->nextOf(), &offset)) { ti = fdv->type; #if 0 @@ -489,7 +491,7 @@ if (arg0->type->ty != Tarray || arg0->type->next->ty != Tarray || arg0->type->next->next->ty != Tchar || - (arg0->inout != None && arg0->inout != In)) + arg0->storageClass & (STCout | STCref | STClazy)) goto Lmainerr; break; } @@ -498,8 +500,8 @@ goto Lmainerr; } - if (f->next->ty != Tint32 && f->next->ty != Tvoid) - error("must return int or void, not %s", f->next->toChars()); + if (f->nextOf()->ty != Tint32 && f->nextOf()->ty != Tvoid) + error("must return int or void, not %s", f->nextOf()->toChars()); if (f->varargs) { Lmainerr: @@ -521,7 +523,7 @@ Type *t0 = arg0->type->toBasetype(); Type *tb = sd ? sd->type : cd->type; if (arg0->type->implicitConvTo(tb) || - (sd && t0->ty == Tpointer && t0->next->implicitConvTo(tb)) + (sd && t0->ty == Tpointer && t0->nextOf()->implicitConvTo(tb)) ) { if (nparams == 1) @@ -616,6 +618,7 @@ sc2->structalign = 8; sc2->incontract = 0; sc2->tf = NULL; + sc2->noctor = 0; // Declare 'this' ad = isThis(); @@ -705,7 +708,7 @@ size_t dim = Argument::dim(t->arguments); for (size_t j = 0; j < dim; j++) { Argument *narg = Argument::getNth(t->arguments, j); - narg->inout = arg->inout; + narg->storageClass = arg->storageClass; } } } @@ -735,13 +738,9 @@ v->storage_class |= STCparameter; if (f->varargs == 2 && i + 1 == nparams) v->storage_class |= STCvariadic; - 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; - case Lazy: v->storage_class |= STCin | STClazy; break; - default: assert(0); - } + v->storage_class |= arg->storageClass & (STCin | STCout | STCref | STClazy); + if (v->storage_class & STClazy) + v->storage_class |= STCin; v->semantic(sc2); if (!sc2->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars()); @@ -793,7 +792,7 @@ // 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 + // BUG: verify that all in and ref parameters are read frequire = frequire->semantic(sc2); labtab = NULL; // so body can't refer to labels } @@ -806,8 +805,8 @@ sym->parent = sc2->scopesym; sc2 = sc2->push(sym); - assert(type->next); - if (type->next->ty == Tvoid) + assert(type->nextOf()); + if (type->nextOf()->ty == Tvoid) { if (outId) error("void functions have no result"); @@ -826,7 +825,7 @@ if (fensure) loc = fensure->loc; - v = new VarDeclaration(loc, type->next, outId, NULL); + v = new VarDeclaration(loc, type->nextOf(), outId, NULL); v->noauto = 1; sc2->incontract--; v->semantic(sc2); @@ -922,7 +921,7 @@ if (inferRetType) { // If no return type inferred yet, then infer a void - if (!type->next) + if (!type->nextOf()) { type->next = Type::tvoid; type = type->semantic(loc, sc); @@ -988,11 +987,11 @@ 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 (!hasReturnExp && type->nextOf()->ty != Tvoid) + error("expected to return a value of type %s", type->nextOf()->toChars()); else if (!inlineAsm) { - if (type->next->ty == Tvoid) + if (type->nextOf()->ty == Tvoid) { if (offend && isMain()) { // Add a return 0; statement @@ -1018,12 +1017,12 @@ e = new AssertExp( endloc, new IntegerExp(0), - new StringExp(0, "missing return expression") + new StringExp(loc, "missing return expression") ); } else e = new HaltExp(endloc); - e = new CommaExp(0, e, type->next->defaultInit()); + e = new CommaExp(0, e, type->nextOf()->defaultInit()); e = e->semantic(sc2); Statement *s = new ExpStatement(0, e); fbody = new CompoundStatement(0, fbody, s); @@ -1041,7 +1040,7 @@ { VarDeclaration *v; v = (VarDeclaration *)parameters->data[i]; - if ((v->storage_class & (STCout | STCin)) == STCout) + if (v->storage_class & STCout) { assert(v->init); ExpInitializer *ie = v->init->isExpInitializer(); @@ -1154,13 +1153,13 @@ { a->push(returnLabel->statement); - if (type->next->ty != Tvoid) + if (type->nextOf()->ty != Tvoid) { // Create: return vresult; assert(vresult); Expression *e = new VarExp(0, vresult); if (tintro) - { e = e->implicitCastTo(sc, tintro->next); + { e = e->implicitCastTo(sc, tintro->nextOf()); e = e->semantic(sc); } ReturnStatement *s = new ReturnStatement(0, e); @@ -1299,6 +1298,108 @@ * Find function in overload list that exactly matches t. */ +/*************************************************** + * Visit each overloaded function in turn, and call + * (*fp)(param, f) on it. + * Exit when no more, or (*fp)(param, f) returns 1. + * Returns: + * 0 continue + * 1 done + */ + +int overloadApply(FuncDeclaration *fstart, + int (*fp)(void *, FuncDeclaration *), + void *param) +{ + FuncDeclaration *f; + Declaration *d; + Declaration *next; + + for (d = fstart; d; d = next) + { FuncAliasDeclaration *fa = d->isFuncAliasDeclaration(); + + if (fa) + { + if (overloadApply(fa->funcalias, fp, param)) + return 1; + next = fa->overnext; + } + else + { + AliasDeclaration *a = d->isAliasDeclaration(); + + if (a) + { + Dsymbol *s = a->toAlias(); + next = s->isDeclaration(); + if (next == a) + break; + if (next == fstart) + break; + } + else + { + f = d->isFuncDeclaration(); + if (!f) + { d->error("is aliased to a function"); + break; // BUG: should print error message? + } + if ((*fp)(param, f)) + return 1; + + next = f->overnext; + } + } + } + return 0; +} + +/******************************************** + * Find function in overload list that exactly matches t. + */ + +struct Param1 +{ + Type *t; // type to match + FuncDeclaration *f; // return value +}; + +int fp1(void *param, FuncDeclaration *f) +{ Param1 *p = (Param1 *)param; + Type *t = p->t; + + if (t->equals(f->type)) + { p->f = f; + return 1; + } + +#if V2 + /* Allow covariant matches, if it's just a const conversion + * of the return type + */ + if (t->ty == Tfunction) + { TypeFunction *tf = (TypeFunction *)f->type; + if (tf->covariant(t) == 1 && + tf->nextOf()->implicitConvTo(t->nextOf()) >= MATCHconst) + { + p->f = f; + return 1; + } + } +#endif + return 0; +} + +FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) +{ + Param1 p; + p.t = t; + p.f = NULL; + overloadApply(this, &fp1, &p); + return p.f; +} + +#if 0 FuncDeclaration *FuncDeclaration::overloadExactMatch(Type *t) { FuncDeclaration *f; @@ -1339,11 +1440,75 @@ } return NULL; } +#endif /******************************************** * Decide which function matches the arguments best. */ +struct Param2 +{ + Match *m; + Expressions *arguments; +}; + +int fp2(void *param, FuncDeclaration *f) +{ Param2 *p = (Param2 *)param; + Match *m = p->m; + Expressions *arguments = p->arguments; + MATCH match; + + if (f != m->lastf) // skip duplicates + { + 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++; + return 0; + + LfIsBetter: + m->last = match; + m->lastf = f; + m->count = 1; + return 0; + + LlastIsBetter: + return 0; + } + } + return 0; +} + + +void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments) +{ + Param2 p; + p.m = m; + p.arguments = arguments; + overloadApply(fstart, &fp2, &p); +} + +#if 0 // Recursive helper function void overloadResolveX(Match *m, FuncDeclaration *fstart, Expressions *arguments) @@ -1423,6 +1588,7 @@ } } } +#endif FuncDeclaration *FuncDeclaration::overloadResolve(Loc loc, Expressions *arguments) { @@ -1750,19 +1916,19 @@ { fd = s->isFuncDeclaration(); assert(fd); - assert(fd->type->next->equals(treturn)); + assert(fd->type->nextOf()->equals(treturn)); } else { Arguments * args = 0; if (t1) { args = new Arguments; - args->push(new Argument(In,t1,0,0)); + args->push(new Argument(STCin,t1,0,0)); if (t2) { - args->push(new Argument(In,t2,0,0)); + args->push(new Argument(STCin,t2,0,0)); if (t3) - args->push(new Argument(In,t3,0,0)); + args->push(new Argument(STCin,t3,0,0)); } } @@ -1927,6 +2093,10 @@ FuncDeclaration::semantic(sc); sc->pop(); + + // See if it's the default constructor + if (cd && varargs == 0 && Argument::dim(arguments) == 0) + cd->defaultCtor = this; } char *CtorDeclaration::kind() @@ -2103,7 +2273,9 @@ void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (hgs->hdrgen) + { buf->writestring("static this(){}\n"); return; + } buf->writestring("static this()"); bodyToCBuffer(buf, hgs); } diff -uNr gdc-0.23/d/dmd/hdrgen.c gdc-0.24/d/dmd/hdrgen.c --- gdc-0.23/d/dmd/hdrgen.c 2006-11-18 16:06:05.000000000 +0100 +++ gdc-0.24/d/dmd/hdrgen.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // Initial header generation implementation by Dave Fladebo -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/hdrgen.h gdc-0.24/d/dmd/hdrgen.h --- gdc-0.23/d/dmd/hdrgen.h 2006-11-11 21:42:37.000000000 +0100 +++ gdc-0.24/d/dmd/hdrgen.h 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // initial header generation implementation by Dave Fladebo -// www.digitalmars.com +// http://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. @@ -13,6 +13,7 @@ { int hdrgen; // 1 if generating header file int ddoc; // 1 if generating Ddoc file + int console; // 1 if writing to console int tpltMember; int inCallExp; int inPtrExp; diff -uNr gdc-0.23/d/dmd/html.c gdc-0.24/d/dmd/html.c --- gdc-0.23/d/dmd/html.c 2006-11-12 19:30:57.000000000 +0100 +++ gdc-0.24/d/dmd/html.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/html.h gdc-0.24/d/dmd/html.h --- gdc-0.23/d/dmd/html.h 2006-11-12 19:30:18.000000000 +0100 +++ gdc-0.24/d/dmd/html.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/identifier.c gdc-0.24/d/dmd/identifier.c --- gdc-0.23/d/dmd/identifier.c 2006-12-03 16:19:10.000000000 +0100 +++ gdc-0.24/d/dmd/identifier.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/identifier.h gdc-0.24/d/dmd/identifier.h --- gdc-0.23/d/dmd/identifier.h 2006-12-03 16:19:11.000000000 +0100 +++ gdc-0.24/d/dmd/identifier.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/idgen.c gdc-0.24/d/dmd/idgen.c --- gdc-0.23/d/dmd/idgen.c 2007-03-04 14:55:11.000000000 +0100 +++ gdc-0.24/d/dmd/idgen.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -88,6 +88,8 @@ { "TypeInfo_Function" }, { "TypeInfo_Delegate" }, { "TypeInfo_Tuple" }, + { "TypeInfo_Const" }, + { "TypeInfo_Invariant" }, { "elements" }, { "_arguments_typeinfo" }, { "_arguments" }, @@ -99,6 +101,8 @@ { "DATE", "__DATE__" }, { "TIME", "__TIME__" }, { "TIMESTAMP", "__TIMESTAMP__" }, + { "VENDOR", "__VENDOR__" }, + { "VERSIONX", "__VERSION__" }, { "nan" }, { "infinity" }, @@ -116,6 +120,7 @@ { "D" }, { "Windows" }, { "Pascal" }, + { "System" }, { "exit" }, { "success" }, @@ -128,6 +133,7 @@ { "sort" }, { "reverse" }, { "dup" }, + { "idup" }, // For inline assembler { "___out", "out" }, @@ -202,6 +208,12 @@ { "adDup", "_adDupT" }, { "adReverse", "_adReverse" }, + // For internal functions + { "aaLen", "_aaLen" }, + { "aaKeys", "_aaKeys" }, + { "aaValues", "_aaValues" }, + { "aaRehash", "_aaRehash" }, + // For pragma's { "lib" }, { "msg" }, diff -uNr gdc-0.23/d/dmd/impcnvgen.c gdc-0.24/d/dmd/impcnvgen.c --- gdc-0.23/d/dmd/impcnvgen.c 2007-01-31 01:02:30.000000000 +0100 +++ gdc-0.24/d/dmd/impcnvgen.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/import.c gdc-0.24/d/dmd/import.c --- gdc-0.23/d/dmd/import.c 2007-02-02 16:24:24.000000000 +0100 +++ gdc-0.24/d/dmd/import.c 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/import.h gdc-0.24/d/dmd/import.h --- gdc-0.23/d/dmd/import.h 2007-02-02 16:24:31.000000000 +0100 +++ gdc-0.24/d/dmd/import.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/inifile.c gdc-0.24/d/dmd/inifile.c --- gdc-0.23/d/dmd/inifile.c 2006-12-03 16:19:11.000000000 +0100 +++ gdc-0.24/d/dmd/inifile.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://www.digitalmars.com #include diff -uNr gdc-0.23/d/dmd/init.c gdc-0.24/d/dmd/init.c --- gdc-0.23/d/dmd/init.c 2007-03-04 14:55:17.000000000 +0100 +++ gdc-0.24/d/dmd/init.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -51,12 +51,12 @@ return Type::terror; } -Array *Initializer::arraySyntaxCopy(Array *ai) -{ Array *a = NULL; +Initializers *Initializer::arraySyntaxCopy(Initializers *ai) +{ Initializers *a = NULL; if (ai) { - a = new Array(); + a = new Initializers(); a->setDim(ai->dim); for (int i = 0; i < a->dim; i++) { Initializer *e = (Initializer *)ai->data[i]; @@ -364,7 +364,10 @@ Expression *ArrayInitializer::toExpression() { Expressions *elements; + Expression *e; + //printf("ArrayInitializer::toExpression()\n"); + //static int i; if (++i == 2) halt(); elements = new Expressions(); for (size_t i = 0; i < value.dim; i++) { @@ -378,7 +381,9 @@ goto Lno; elements->push(ex); } - return new ArrayLiteralExp(loc, elements); + e = new ArrayLiteralExp(loc, elements); + e->type = type; + return e; Lno: delete elements; @@ -387,6 +392,48 @@ } +/******************************** + * If possible, convert array initializer to associative array initializer. + */ + +Initializer *ArrayInitializer::toAssocArrayInitializer() +{ Expressions *keys; + Expressions *values; + Expression *e; + + //printf("ArrayInitializer::toAssocArrayInitializer()\n"); + //static int i; if (++i == 2) halt(); + keys = new Expressions(); + keys->setDim(value.dim); + values = new Expressions(); + values->setDim(value.dim); + + for (size_t i = 0; i < value.dim; i++) + { + e = (Expression *)index.data[i]; + if (!e) + goto Lno; + keys->data[i] = (void *)e; + + Initializer *iz = (Initializer *)value.data[i]; + if (!iz) + goto Lno; + e = iz->toExpression(); + if (!e) + goto Lno; + values->data[i] = (void *)e; + } + e = new AssocArrayLiteralExp(loc, keys, values); + return new ExpInitializer(loc, e); + +Lno: + delete keys; + delete values; + error(loc, "not an associative array initializer"); + return this; +} + + Type *ArrayInitializer::inferType(Scope *sc) { for (size_t i = 0; i < value.dim; i++) diff -uNr gdc-0.23/d/dmd/init.h gdc-0.24/d/dmd/init.h --- gdc-0.23/d/dmd/init.h 2007-02-18 17:11:07.000000000 +0100 +++ gdc-0.24/d/dmd/init.h 2007-07-23 02:23:26.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -14,6 +14,7 @@ #include "root.h" #include "mars.h" +#include "arraytypes.h" struct Identifier; struct Expression; @@ -22,6 +23,7 @@ struct dt_t; struct AggregateDeclaration; struct VoidInitializer; +struct ArrayInitializer; struct ExpInitializer; #ifdef _DH struct HdrGenState; @@ -39,11 +41,12 @@ virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; char *toChars(); - static Array *arraySyntaxCopy(Array *ai); + static Initializers *arraySyntaxCopy(Initializers *ai); virtual dt_t *toDt(); virtual VoidInitializer *isVoidInitializer() { return NULL; } + virtual ArrayInitializer *isArrayInitializer() { return NULL; } virtual ExpInitializer *isExpInitializer() { return NULL; } }; @@ -64,8 +67,8 @@ struct StructInitializer : Initializer { - Array field; // of Identifier *'s - Array value; // parallel array of Initializer *'s + Identifiers field; // of Identifier *'s + Initializers value; // parallel array of Initializer *'s Array vars; // parallel array of VarDeclaration *'s AggregateDeclaration *ad; // which aggregate this is for @@ -82,8 +85,8 @@ struct ArrayInitializer : Initializer { - Array index; // of Expression *'s - Array value; // of Initializer *'s + Expressions index; // indices + Initializers value; // of Initializer *'s target_size_t dim; // length of array being initialized Type *type; // type that array will be used to initialize int sem; // !=0 if semantic() is run @@ -94,10 +97,13 @@ Initializer *semantic(Scope *sc, Type *t); Type *inferType(Scope *sc); Expression *toExpression(); + Initializer *toAssocArrayInitializer(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); dt_t *toDt(); dt_t *toDtBit(); // for bit arrays + + ArrayInitializer *isArrayInitializer() { return this; } }; struct ExpInitializer : Initializer diff -uNr gdc-0.23/d/dmd/inline.c gdc-0.24/d/dmd/inline.c --- gdc-0.23/d/dmd/inline.c 2007-02-08 18:58:10.000000000 +0100 +++ gdc-0.24/d/dmd/inline.c 2007-07-27 02:07:14.000000000 +0200 @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -183,6 +183,16 @@ return 1 + arrayInlineCost(ics, elements); } +int AssocArrayLiteralExp::inlineCost(InlineCostState *ics) +{ + return 1 + arrayInlineCost(ics, keys) + arrayInlineCost(ics, values); +} + +int StructLiteralExp::inlineCost(InlineCostState *ics) +{ + return 1 + arrayInlineCost(ics, elements); +} + int FuncExp::inlineCost(InlineCostState *ics) { // Right now, this makes the function be output to the .obj file twice. @@ -336,6 +346,20 @@ e = Expression::combine(e, e2); if (s->isReturnStatement()) break; + + /* Check for: + * if (condition) + * return exp1; + * else + * return exp2; + */ + IfStatement *ifs = s->isIfStatement(); + if (ifs && ifs->elsebody && ifs->ifbody && + ifs->ifbody->isReturnStatement() && + ifs->elsebody->isReturnStatement() + ) + break; + } } return e; @@ -478,7 +502,10 @@ { //if (!ids->vthis) //error("no 'this' when inlining %s", ids->parent->toChars()); - assert(ids->vthis); + if (!ids->vthis) + { + return this; + } VarExp *ve = new VarExp(loc, ids->vthis); ve->type = type; @@ -699,6 +726,27 @@ } +Expression *AssocArrayLiteralExp::doInline(InlineDoState *ids) +{ + AssocArrayLiteralExp *ce; + + ce = (AssocArrayLiteralExp *)copy(); + ce->keys = arrayExpressiondoInline(keys, ids); + ce->values = arrayExpressiondoInline(values, ids); + return ce; +} + + +Expression *StructLiteralExp::doInline(InlineDoState *ids) +{ + StructLiteralExp *ce; + + ce = (StructLiteralExp *)copy(); + ce->elements = arrayExpressiondoInline(elements, ids); + return ce; +} + + Expression *ArrayExp::doInline(InlineDoState *ids) { ArrayExp *ce; @@ -777,14 +825,14 @@ Statement *WhileStatement::inlineScan(InlineScanState *iss) { condition = condition->inlineScan(iss); - body = body->inlineScan(iss); + body = body ? body->inlineScan(iss) : NULL; return this; } Statement *DoStatement::inlineScan(InlineScanState *iss) { - body = body->inlineScan(iss); + body = body ? body->inlineScan(iss) : NULL; condition = condition->inlineScan(iss); return this; } @@ -811,6 +859,17 @@ } +#if V2 +Statement *ForeachRangeStatement::inlineScan(InlineScanState *iss) +{ + lwr = lwr->inlineScan(iss); + upr = upr->inlineScan(iss); + body = body->inlineScan(iss); + return this; +} +#endif + + Statement *IfStatement::inlineScan(InlineScanState *iss) { condition = condition->inlineScan(iss); @@ -826,7 +885,7 @@ { //printf("SwitchStatement::inlineScan()\n"); condition = condition->inlineScan(iss); - body = body->inlineScan(iss); + body = body ? body->inlineScan(iss) : NULL; if (sdefault) sdefault = (DefaultStatement *)sdefault->inlineScan(iss); if (cases) @@ -1093,6 +1152,27 @@ } +Expression *AssocArrayLiteralExp::inlineScan(InlineScanState *iss) +{ Expression *e = this; + + //printf("AssocArrayLiteralExp::inlineScan()\n"); + arrayInlineScan(iss, keys); + arrayInlineScan(iss, values); + + return e; +} + + +Expression *StructLiteralExp::inlineScan(InlineScanState *iss) +{ Expression *e = this; + + //printf("StructLiteralExp::inlineScan()\n"); + arrayInlineScan(iss, elements); + + return e; +} + + Expression *ArrayExp::inlineScan(InlineScanState *iss) { Expression *e = this; @@ -1184,7 +1264,7 @@ /* Don't inline a function that returns non-void, but has * no return expression. */ - if (type->next && type->next->ty != Tvoid && + if (tf->next && tf->next->ty != Tvoid && !(hasReturnExp & 1) && !hdrscan) goto Lno; @@ -1223,7 +1303,7 @@ for (int i = 0; i < parameters->dim; i++) { VarDeclaration *v = (VarDeclaration *)parameters->data[i]; - if (v->isOut() || v->type->toBasetype()->ty == Tsarray) + if (v->isOut() || v->isRef() || v->type->toBasetype()->ty == Tsarray) goto Lno; } } @@ -1322,7 +1402,7 @@ ei = new ExpInitializer(arg->loc, arg); vto = new VarDeclaration(vfrom->loc, vfrom->type, vfrom->ident, ei); - vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy); + vto->storage_class |= vfrom->storage_class & (STCin | STCout | STClazy | STCref); vto->linkage = vfrom->linkage; vto->parent = iss->fd; //printf("vto = '%s', vto->storage_class = x%x\n", vto->toChars(), vto->storage_class); diff -uNr gdc-0.23/d/dmd/interpret.c gdc-0.24/d/dmd/interpret.c --- gdc-0.23/d/dmd/interpret.c 2007-02-20 22:07:00.000000000 +0100 +++ gdc-0.24/d/dmd/interpret.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -43,6 +43,10 @@ memset(this, 0, sizeof(InterState)); } +Expression *interpret_aaLen(InterState *istate, Expressions *arguments); +Expression *interpret_aaKeys(InterState *istate, Expressions *arguments); +Expression *interpret_aaValues(InterState *istate, Expressions *arguments); + /************************************* * Attempt to interpret a function given the arguments. * Input: @@ -56,6 +60,15 @@ printf("FuncDeclaration::interpret() %s\n", toChars()); printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); #endif + if (global.errors) + return NULL; + if (ident == Id::aaLen) + return interpret_aaLen(istate, arguments); + else if (ident == Id::aaKeys) + return interpret_aaKeys(istate, arguments); + else if (ident == Id::aaValues) + return interpret_aaValues(istate, arguments); + if (cantInterpret || semanticRun == 1) return NULL; @@ -75,7 +88,7 @@ assert(tb->ty == Tfunction); TypeFunction *tf = (TypeFunction *)tb; Type *tret = tf->next->toBasetype(); - if (tf->varargs || tret->ty == Tvoid) + if (tf->varargs /*|| tret->ty == Tvoid*/) { cantInterpret = 1; return NULL; } @@ -84,28 +97,13 @@ { size_t dim = Argument::dim(tf->parameters); for (size_t i = 0; i < dim; i++) { Argument *arg = Argument::getNth(tf->parameters, i); - if (arg->inout == Lazy) + if (arg->storageClass & STClazy) { cantInterpret = 1; return NULL; } } } - /* Save the values of the local variables used - */ - Expressions valueSaves; - if (istate) - { - valueSaves.setDim(istate->vars.dim); - for (size_t i = 0; i < istate->vars.dim; i++) - { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; - if (v) - { valueSaves.data[i] = v->value; - v->value = NULL; - } - } - } - InterState istatex; istatex.caller = istate; istatex.fd = this; @@ -126,9 +124,9 @@ #if LOG printf("arg[%d] = %s\n", i, earg->toChars()); #endif - if (arg->inout == Out || arg->inout == InOut) + if (arg->storageClass & (STCout | STCref)) { - /* Bind out or inout parameter to the corresponding + /* Bind out or ref parameter to the corresponding * variable v2 */ if (!istate || earg->op != TOKvar) @@ -173,6 +171,24 @@ } } + /* Save the values of the local variables used + */ + Expressions valueSaves; + if (istate) + { + //printf("saving state...\n"); + valueSaves.setDim(istate->vars.dim); + for (size_t i = 0; i < istate->vars.dim; i++) + { VarDeclaration *v = (VarDeclaration *)istate->vars.data[i]; + if (v) + { + //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value->toChars()); + valueSaves.data[i] = v->value; + v->value = NULL; + } + } + } + Expression *e = NULL; while (1) @@ -252,7 +268,7 @@ Expression *ExpStatement::interpret(InterState *istate) { #if LOG - printf("ExpStatement::interpret()\n"); + printf("ExpStatement::interpret(%s)\n", exp ? exp->toChars() : ""); #endif START() if (exp) @@ -280,11 +296,17 @@ for (size_t i = 0; i < statements->dim; i++) { Statement *s = (Statement *)statements->data[i]; - e = s->interpret(istate); - if (e) - break; + if (s) + { + e = s->interpret(istate); + if (e) + break; + } } } +#if LOG + printf("-CompoundStatement::interpret() %p\n", e); +#endif return e; } @@ -374,11 +396,18 @@ Expression *ReturnStatement::interpret(InterState *istate) { #if LOG - printf("ReturnStatement::interpret()\n"); + printf("ReturnStatement::interpret(%s)\n", exp ? exp->toChars() : ""); #endif START() - assert(exp); + if (!exp) + return EXP_VOID_INTERPRET; +#if LOG + Expression *e = exp->interpret(istate); + printf("e = %p\n", e); + return e; +#else return exp->interpret(istate); +#endif } Expression *BreakStatement::interpret(InterState *istate) @@ -595,7 +624,7 @@ Expression *e = NULL; Expression *eaggr; - if (value->isOut()) + if (value->isOut() || value->isRef()) return EXP_CANT_INTERPRET; eaggr = aggr->interpret(istate); @@ -606,6 +635,9 @@ if (dim == EXP_CANT_INTERPRET) return EXP_CANT_INTERPRET; + Expression *keysave = key ? key->value : NULL; + Expression *valuesave = value->value; + uinteger_t d = dim->toUInteger(); uinteger_t index; @@ -616,9 +648,10 @@ Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); if (key) key->value = ekey; - value->value = Index(value->type, eaggr, ekey); - if (value->value == EXP_CANT_INTERPRET) - return EXP_CANT_INTERPRET; + e = Index(value->type, eaggr, ekey); + if (e == EXP_CANT_INTERPRET) + break; + value->value = e; e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) @@ -640,9 +673,10 @@ Expression *ekey = new IntegerExp(loc, index, Type::tsize_t); if (key) key->value = ekey; - value->value = Index(value->type, eaggr, ekey); - if (value->value == EXP_CANT_INTERPRET) - return EXP_CANT_INTERPRET; + e = Index(value->type, eaggr, ekey); + if (e == EXP_CANT_INTERPRET) + break; + value->value = e; e = body ? body->interpret(istate) : NULL; if (e == EXP_CANT_INTERPRET) @@ -657,8 +691,93 @@ break; } } + value->value = valuesave; + if (key) + key->value = keysave; + return e; +} + +#if V2 +Expression *ForeachRangeStatement::interpret(InterState *istate) +{ +#if LOG + printf("ForeachRangeStatement::interpret()\n"); +#endif + if (istate->start == this) + istate->start = NULL; + if (istate->start) + return NULL; + + Expression *e = NULL; + Expression *elwr = lwr->interpret(istate); + if (elwr == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + Expression *eupr = upr->interpret(istate); + if (eupr == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + + Expression *keysave = key->value; + + if (op == TOKforeach) + { + key->value = elwr; + + while (1) + { + e = Cmp(TOKlt, key->value->type, key->value, upr); + if (e == EXP_CANT_INTERPRET) + break; + if (e->isBool(TRUE) == FALSE) + { e = NULL; + break; + } + + e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); + if (e == EXP_CANT_INTERPRET) + break; + key->value = e; + } + } + else // TOKforeach_reverse + { + key->value = eupr; + + while (1) + { + e = Cmp(TOKgt, key->value->type, key->value, lwr); + if (e == EXP_CANT_INTERPRET) + break; + if (e->isBool(TRUE) == FALSE) + { e = NULL; + break; + } + + e = Min(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type)); + if (e == EXP_CANT_INTERPRET) + break; + key->value = e; + + e = body ? body->interpret(istate) : NULL; + if (e == EXP_CANT_INTERPRET) + break; + if (e == EXP_BREAK_INTERPRET) + { e = NULL; + break; + } + } + } + key->value = keysave; return e; } +#endif Expression *SwitchStatement::interpret(InterState *istate) { @@ -810,6 +929,9 @@ Expression *RealExp::interpret(InterState *istate) { +#if LOG + printf("RealExp::interpret() %s\n", toChars()); +#endif return this; } @@ -826,32 +948,53 @@ return this; } -Expression *VarExp::interpret(InterState *istate) +Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) { -#if LOG - printf("VarExp::interpret() %s\n", toChars()); -#endif Expression *e = EXP_CANT_INTERPRET; - VarDeclaration *v = var->isVarDeclaration(); + VarDeclaration *v = d->isVarDeclaration(); + SymbolDeclaration *s = d->isSymbolDeclaration(); if (v) { if (v->isConst() && v->init) - e = v->init->toExpression(); + { e = v->init->toExpression(); + if (!e->type) + e->type = v->type; + } else { e = v->value; if (!e) - error("variable %s is used before initialization", v->toChars()); + error(loc, "variable %s is used before initialization", v->toChars()); else if (e != EXP_CANT_INTERPRET) e = e->interpret(istate); } if (!e) e = EXP_CANT_INTERPRET; } + else if (s) + { + if (s->dsym->toInitializer() == s->sym) + { Expressions *exps = new Expressions(); + e = new StructLiteralExp(0, s->dsym, exps); + e = e->semantic(NULL); + } + } return e; } +Expression *VarExp::interpret(InterState *istate) +{ +#if LOG + printf("VarExp::interpret() %s\n", toChars()); +#endif + return getVarExp(loc, istate, var); +} + Expression *DeclarationExp::interpret(InterState *istate) -{ Expression *e = EXP_CANT_INTERPRET; +{ +#if LOG + printf("DeclarationExp::interpret() %s\n", toChars()); +#endif + Expression *e = EXP_CANT_INTERPRET; VarDeclaration *v = declaration->isVarDeclaration(); if (v) { @@ -864,12 +1007,23 @@ else if (v->init->isVoidInitializer()) e = NULL; } + else if (s == v && v->isConst() && v->init) + { e = v->init->toExpression(); + if (!e) + e = EXP_CANT_INTERPRET; + else if (!e->type) + e->type = v->type; + } } return e; } Expression *TupleExp::interpret(InterState *istate) -{ Expressions *expsx = NULL; +{ +#if LOG + printf("TupleExp::interpret() %s\n", toChars()); +#endif + Expressions *expsx = NULL; for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; @@ -908,6 +1062,9 @@ Expression *ArrayLiteralExp::interpret(InterState *istate) { Expressions *expsx = NULL; +#if LOG + printf("ArrayLiteralExp::interpret() %s\n", toChars()); +#endif if (elements) { for (size_t i = 0; i < elements->dim; i++) @@ -950,10 +1107,154 @@ return this; } +Expression *AssocArrayLiteralExp::interpret(InterState *istate) +{ Expressions *keysx = keys; + Expressions *valuesx = values; + +#if LOG + printf("AssocArrayLiteralExp::interpret() %s\n", toChars()); +#endif + for (size_t i = 0; i < keys->dim; i++) + { Expression *ekey = (Expression *)keys->data[i]; + Expression *evalue = (Expression *)values->data[i]; + Expression *ex; + + ex = ekey->interpret(istate); + if (ex == EXP_CANT_INTERPRET) + goto Lerr; + + /* If any changes, do Copy On Write + */ + if (ex != ekey) + { + if (keysx == keys) + keysx = (Expressions *)keys->copy(); + keysx->data[i] = (void *)ex; + } + + ex = evalue->interpret(istate); + if (ex == EXP_CANT_INTERPRET) + goto Lerr; + + /* If any changes, do Copy On Write + */ + if (ex != evalue) + { + if (valuesx == values) + valuesx = (Expressions *)values->copy(); + valuesx->data[i] = (void *)ex; + } + } + if (keysx != keys) + expandTuples(keysx); + if (valuesx != values) + expandTuples(valuesx); + if (keysx->dim != valuesx->dim) + goto Lerr; + + /* Remove duplicate keys + */ + for (size_t i = 1; i < keysx->dim; i++) + { Expression *ekey = (Expression *)keysx->data[i - 1]; + + for (size_t j = i; j < keysx->dim; j++) + { Expression *ekey2 = (Expression *)keysx->data[j]; + Expression *ex = Equal(TOKequal, Type::tbool, ekey, ekey2); + if (ex == EXP_CANT_INTERPRET) + goto Lerr; + if (ex->isBool(TRUE)) // if a match + { + // Remove ekey + if (keysx == keys) + keysx = (Expressions *)keys->copy(); + if (valuesx == values) + valuesx = (Expressions *)values->copy(); + keysx->remove(i - 1); + valuesx->remove(i - 1); + i -= 1; // redo the i'th iteration + break; + } + } + } + + if (keysx != keys || valuesx != values) + { + AssocArrayLiteralExp *ae; + ae = new AssocArrayLiteralExp(loc, keysx, valuesx); + ae->type = type; + return ae; + } + return this; + +Lerr: + if (keysx != keys) + delete keysx; + if (valuesx != values) + delete values; + return EXP_CANT_INTERPRET; +} + +Expression *StructLiteralExp::interpret(InterState *istate) +{ Expressions *expsx = NULL; + +#if LOG + printf("StructLiteralExp::interpret() %s\n", toChars()); +#endif + /* We don't know how to deal with overlapping fields + */ + if (sd->hasUnions) + return EXP_CANT_INTERPRET; + + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + if (!e) + continue; + + Expression *ex = e->interpret(istate); + if (ex == EXP_CANT_INTERPRET) + { delete expsx; + return EXP_CANT_INTERPRET; + } + + /* If any changes, do Copy On Write + */ + if (ex != e) + { + if (!expsx) + { expsx = new Expressions(); + expsx->setDim(elements->dim); + for (size_t j = 0; j < elements->dim; j++) + { + expsx->data[j] = elements->data[j]; + } + } + expsx->data[i] = (void *)ex; + } + } + } + if (elements && expsx) + { + expandTuples(expsx); + if (expsx->dim != elements->dim) + { delete expsx; + return EXP_CANT_INTERPRET; + } + StructLiteralExp *se = new StructLiteralExp(loc, sd, expsx); + se->type = type; + return se; + } + return this; +} + Expression *UnaExp::interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *)) { Expression *e; Expression *e1; +#if LOG + printf("UnaExp::interpretCommon() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; @@ -986,6 +1287,9 @@ Expression *e1; Expression *e2; +#if LOG + printf("BinExp::interpretCommon() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; @@ -1031,16 +1335,25 @@ Expression *e1; Expression *e2; +#if LOG + printf("BinExp::interpretCommon2() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; - if (e1->isConst() != 1) + if (e1->isConst() != 1 && + e1->op != TOKstring && + e1->op != TOKarrayliteral && + e1->op != TOKstructliteral) goto Lcant; e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) goto Lcant; - if (e2->isConst() != 1) + if (e2->isConst() != 1 && + e2->op != TOKstring && + e2->op != TOKarrayliteral && + e2->op != TOKstructliteral) goto Lcant; e = (*fp)(op, type, e1, e2); @@ -1060,7 +1373,7 @@ BIN_INTERPRET2(Identity) BIN_INTERPRET2(Cmp) -Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp) +Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) { #if LOG printf("BinExp::interpretAssignCommon() %s\n", toChars()); @@ -1075,13 +1388,22 @@ e1 = ce->e1; } } - if (e1 != EXP_CANT_INTERPRET && e1->op == TOKvar) + if (e1 == EXP_CANT_INTERPRET) + return e1; + Expression *e2 = this->e2->interpret(istate); + if (e2 == EXP_CANT_INTERPRET) + return e2; + + /* Assignment to variable of the form: + * v = e2 + */ + if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); if (v && !v->isDataseg()) { - /* Chase down rebinding of out and inout + /* Chase down rebinding of out and ref */ if (v->value && v->value->op == TOKvar) { @@ -1090,36 +1412,255 @@ assert(v); } - if (fp && !v->value) + Expression *ev = v->value; + if (fp && !ev) { error("variable %s is used before initialization", v->toChars()); return e; } - Expression *e2 = this->e2->interpret(istate); + if (fp) + e2 = (*fp)(v->type, ev, e2); + else + e2 = Cast(v->type, v->type, e2); if (e2 != EXP_CANT_INTERPRET) { - if (fp) - e2 = (*fp)(v->type, v->value, e2); - else - e2 = Cast(v->type, v->type, e2); - if (e2 != EXP_CANT_INTERPRET) + if (!v->isParameter()) { - if (v->isAuto()) + for (size_t i = 0; 1; i++) { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; + if (i == istate->vars.dim) + { istate->vars.push(v); + break; } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; } - v->value = e2; - e = Cast(type, type, e2); } + v->value = e2; + e = Cast(type, type, post ? ev : e2); + } + } + } + /* Assignment to struct member of the form: + * *(symoffexp) = e2 + */ + else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) + { SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; + VarDeclaration *v = soe->var->isVarDeclaration(); + + if (v->isDataseg()) + return EXP_CANT_INTERPRET; + if (fp && !v->value) + { error("variable %s is used before initialization", v->toChars()); + return e; + } + if (v->value->op != TOKstructliteral) + return EXP_CANT_INTERPRET; + StructLiteralExp *se = (StructLiteralExp *)v->value; + int fieldi = se->getFieldIndex(type, soe->offset); + if (fieldi == -1) + return EXP_CANT_INTERPRET; + Expression *ev = se->getField(type, soe->offset); + if (fp) + e2 = (*fp)(type, ev, e2); + else + e2 = Cast(type, type, e2); + if (e2 == EXP_CANT_INTERPRET) + return e2; + + if (!v->isParameter()) + { + for (size_t i = 0; 1; i++) + { + if (i == istate->vars.dim) + { istate->vars.push(v); + break; + } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; } } + + /* Create new struct literal reflecting updated fieldi + */ + Expressions *expsx = new Expressions(); + expsx->setDim(se->elements->dim); + for (size_t j = 0; j < expsx->dim; j++) + { + if (j == fieldi) + expsx->data[j] = (void *)e2; + else + expsx->data[j] = se->elements->data[j]; + } + v->value = new StructLiteralExp(se->loc, se->sd, expsx); + v->value->type = se->type; + + e = Cast(type, type, post ? ev : e2); + } + /* Assignment to array element of the form: + * a[i] = e2 + */ + else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) + { IndexExp *ie = (IndexExp *)e1; + VarExp *ve = (VarExp *)ie->e1; + VarDeclaration *v = ve->var->isVarDeclaration(); + + if (!v || v->isDataseg()) + return EXP_CANT_INTERPRET; + if (!v->value) + { + if (fp) + { error("variable %s is used before initialization", v->toChars()); + return e; + } + + Type *t = v->type->toBasetype(); + if (t->ty == Tsarray) + { + /* This array was void initialized. Create a + * default initializer for it. + * What we should do is fill the array literal with + * NULL data, so use-before-initialized can be detected. + * But we're too lazy at the moment to do it, as that + * involves redoing Index() and whoever calls it. + */ + Expression *ev = v->type->defaultInit(); + size_t dim = ((TypeSArray *)t)->dim->toInteger(); + Expressions *elements = new Expressions(); + elements->setDim(dim); + for (size_t i = 0; i < dim; i++) + elements->data[i] = (void *)ev; + ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements); + ae->type = v->type; + v->value = ae; + } + else + return EXP_CANT_INTERPRET; + } + + ArrayLiteralExp *ae = NULL; + AssocArrayLiteralExp *aae = NULL; + StringExp *se = NULL; + if (v->value->op == TOKarrayliteral) + ae = (ArrayLiteralExp *)v->value; + else if (v->value->op == TOKassocarrayliteral) + aae = (AssocArrayLiteralExp *)v->value; + else if (v->value->op == TOKstring) + se = (StringExp *)v->value; + else + return EXP_CANT_INTERPRET; + + Expression *index = ie->e2->interpret(istate); + if (index == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + Expression *ev; + if (fp || ae || se) // not for aae, because key might not be there + { + ev = Index(type, v->value, index); + if (ev == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + } + + if (fp) + e2 = (*fp)(type, ev, e2); + else + e2 = Cast(type, type, e2); + if (e2 == EXP_CANT_INTERPRET) + return e2; + + if (!v->isParameter()) + { + for (size_t i = 0; 1; i++) + { + if (i == istate->vars.dim) + { istate->vars.push(v); + break; + } + if (v == (VarDeclaration *)istate->vars.data[i]) + break; + } + } + + if (ae) + { + /* Create new array literal reflecting updated elem + */ + int elemi = index->toInteger(); + Expressions *expsx = new Expressions(); + expsx->setDim(ae->elements->dim); + for (size_t j = 0; j < expsx->dim; j++) + { + if (j == elemi) + expsx->data[j] = (void *)e2; + else + expsx->data[j] = ae->elements->data[j]; + } + v->value = new ArrayLiteralExp(ae->loc, expsx); + v->value->type = ae->type; + } + else if (aae) + { + /* Create new associative array literal reflecting updated key/value + */ + Expressions *keysx = aae->keys; + Expressions *valuesx = new Expressions(); + valuesx->setDim(aae->values->dim); + int updated = 0; + for (size_t j = valuesx->dim; j; ) + { j--; + Expression *ekey = (Expression *)aae->keys->data[j]; + Expression *ex = Equal(TOKequal, Type::tbool, ekey, index); + if (ex == EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + if (ex->isBool(TRUE)) + { valuesx->data[j] = (void *)e2; + updated = 1; + } + else + valuesx->data[j] = aae->values->data[j]; + } + if (!updated) + { // Append index/e2 to keysx[]/valuesx[] + valuesx->push(e2); + keysx = (Expressions *)keysx->copy(); + keysx->push(index); + } + v->value = new AssocArrayLiteralExp(aae->loc, keysx, valuesx); + v->value->type = aae->type; + } + else if (se) + { + /* Create new string literal reflecting updated elem + */ + int elemi = index->toInteger(); + unsigned char *s; + s = (unsigned char *)mem.calloc(se->len + 1, se->sz); + memcpy(s, se->string, se->len * se->sz); + unsigned value = e2->toInteger(); + switch (se->sz) + { + case 1: s[elemi] = value; break; + case 2: ((unsigned short *)s)[elemi] = value; break; + case 4: ((unsigned *)s)[elemi] = value; break; + default: + assert(0); + break; + } + StringExp *se2 = new StringExp(se->loc, s, se->len); + se2->committed = se->committed; + se2->postfix = se->postfix; + se2->type = se->type; + v->value = se2; + } + else + assert(0); + + e = Cast(type, type, post ? ev : e2); + } + else + { +#ifdef DEBUG + dump(0); +#endif } return e; } @@ -1150,56 +1691,26 @@ Expression *PostExp::interpret(InterState *istate) { - Expression *e = EXP_CANT_INTERPRET; - - if (e1->op == TOKvar) - { - VarExp *ve = (VarExp *)e1; - VarDeclaration *v = ve->var->isVarDeclaration(); - if (v && !v->isDataseg()) - { - /* Chase down rebinding of out and inout - */ - if (v->value && v->value->op == TOKvar) - { - ve = (VarExp *)v->value; - v = ve->var->isVarDeclaration(); - assert(v); - } - - if (!v->value) - { error("variable %s is used before initialization", v->toChars()); - return e; - } - Expression *e2 = this->e2->interpret(istate); - if (e2 != EXP_CANT_INTERPRET) - { - e = ((op == TOKplusplus) ? &Add : &Min)(v->type, v->value, e2); - if (e != EXP_CANT_INTERPRET) - { - if (v->isAuto()) - { - for (size_t i = 0; 1; i++) - { - if (i == istate->vars.dim) - { istate->vars.push(v); - break; - } - if (v == (VarDeclaration *)istate->vars.data[i]) - break; - } - } - v->value = e; - e = Cast(type, type, e2); - } - } - } - } +#if LOG + printf("PostExp::interpret() %s\n", toChars()); +#endif + Expression *e; + if (op == TOKplusplus) + e = interpretAssignCommon(istate, &Add, 1); + else + e = interpretAssignCommon(istate, &Min, 1); +#if LOG + if (e == EXP_CANT_INTERPRET) + printf("PostExp::interpret() CANT\n"); +#endif return e; } Expression *AndAndExp::interpret(InterState *istate) { +#if LOG + printf("AndAndExp::interpret() %s\n", toChars()); +#endif Expression *e = e1->interpret(istate); if (e != EXP_CANT_INTERPRET) { @@ -1226,6 +1737,9 @@ Expression *OrOrExp::interpret(InterState *istate) { +#if LOG + printf("OrOrExp::interpret() %s\n", toChars()); +#endif Expression *e = e1->interpret(istate); if (e != EXP_CANT_INTERPRET) { @@ -1276,6 +1790,8 @@ Expression *eresult = fd->interpret(istate, arguments); if (eresult) e = eresult; + else if (fd->type->toBasetype()->nextOf()->ty == Tvoid) + e = EXP_VOID_INTERPRET; else error("cannot evaluate %s at compile time", toChars()); } @@ -1286,6 +1802,9 @@ Expression *CommaExp::interpret(InterState *istate) { +#if LOG + printf("CommaExp::interpret() %s\n", toChars()); +#endif Expression *e = e1->interpret(istate); if (e != EXP_CANT_INTERPRET) e = e2->interpret(istate); @@ -1294,6 +1813,9 @@ Expression *CondExp::interpret(InterState *istate) { +#if LOG + printf("CondExp::interpret() %s\n", toChars()); +#endif Expression *e = econd->interpret(istate); if (e != EXP_CANT_INTERPRET) { @@ -1317,7 +1839,7 @@ e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; - if (e1->op == TOKstring || e1->op == TOKarrayliteral) + if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) { e = ArrayLength(type, e1); } @@ -1334,17 +1856,23 @@ Expression *e1; Expression *e2; +#if LOG + printf("IndexExp::interpret() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; - /* Set the $ variable - */ - e = ArrayLength(Type::tsize_t, e1); - if (e == EXP_CANT_INTERPRET) - goto Lcant; - if (lengthVar) - lengthVar->value = e; + if (e1->op == TOKstring || e1->op == TOKarrayliteral) + { + /* Set the $ variable + */ + e = ArrayLength(Type::tsize_t, e1); + if (e == EXP_CANT_INTERPRET) + goto Lcant; + if (lengthVar) + lengthVar->value = e; + } e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) @@ -1408,13 +1936,18 @@ #endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) + { goto Lcant; + } e2 = this->e2->interpret(istate); if (e2 == EXP_CANT_INTERPRET) goto Lcant; return Cat(type, e1, e2); Lcant: +#if LOG + printf("CatExp::interpret() %s CANT\n", toChars()); +#endif return EXP_CANT_INTERPRET; } @@ -1423,12 +1956,18 @@ { Expression *e; Expression *e1; +#if LOG + printf("CastExp::interpret() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; return Cast(type, to, e1); Lcant: +#if LOG + printf("CastExp::interpret() %s CANT\n", toChars()); +#endif return EXP_CANT_INTERPRET; } @@ -1437,6 +1976,9 @@ { Expression *e; Expression *e1; +#if LOG + printf("AssertExp::interpret() %s\n", toChars()); +#endif e1 = this->e1->interpret(istate); if (e1 == EXP_CANT_INTERPRET) goto Lcant; @@ -1454,6 +1996,7 @@ } else error("%s failed", toChars()); + goto Lcant; } else goto Lcant; @@ -1463,4 +2006,101 @@ return EXP_CANT_INTERPRET; } +Expression *PtrExp::interpret(InterState *istate) +{ Expression *e = EXP_CANT_INTERPRET; + +#if LOG + printf("PtrExp::interpret() %s\n", toChars()); +#endif + + // Constant fold *(&structliteral + offset) + if (e1->op == TOKadd) + { AddExp *ae = (AddExp *)e1; + if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) + { AddrExp *ade = (AddrExp *)ae->e1; + Expression *ex = ade->e1; + ex = ex->interpret(istate); + if (ex != EXP_CANT_INTERPRET) + { + if (ex->op == TOKstructliteral) + { StructLiteralExp *se = (StructLiteralExp *)ex; + unsigned offset = ae->e2->toInteger(); + e = se->getField(type, offset); + if (!e) + e = EXP_CANT_INTERPRET; + return e; + } + } + } + e = Ptr(type, e1); + } + else if (e1->op == TOKsymoff) + { SymOffExp *soe = (SymOffExp *)e1; + VarDeclaration *v = soe->var->isVarDeclaration(); + if (v) + { Expression *ev = getVarExp(loc, istate, v); + if (ev != EXP_CANT_INTERPRET && ev->op == TOKstructliteral) + { StructLiteralExp *se = (StructLiteralExp *)ev; + e = se->getField(type, soe->offset); + if (!e) + e = EXP_CANT_INTERPRET; + } + } + } +#if LOG + if (e == EXP_CANT_INTERPRET) + printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); +#endif + return e; +} + +/******************************* Special Functions ***************************/ + +Expression *interpret_aaLen(InterState *istate, Expressions *arguments) +{ + if (!arguments || arguments->dim != 1) + return NULL; + Expression *earg = (Expression *)arguments->data[0]; + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); + return e; +} + +Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) +{ + //printf("interpret_aaKeys()\n"); + if (!arguments || arguments->dim != 2) + return NULL; + Expression *earg = (Expression *)arguments->data[0]; + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); + return e; +} + +Expression *interpret_aaValues(InterState *istate, Expressions *arguments) +{ + //printf("interpret_aaValues()\n"); + if (!arguments || arguments->dim != 3) + return NULL; + Expression *earg = (Expression *)arguments->data[0]; + earg = earg->interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return NULL; + if (earg->op != TOKassocarrayliteral) + return NULL; + AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; + Expression *e = new ArrayLiteralExp(aae->loc, aae->values); + //printf("result is %s\n", e->toChars()); + return e; +} diff -uNr gdc-0.23/d/dmd/lexer.c gdc-0.24/d/dmd/lexer.c --- gdc-0.23/d/dmd/lexer.c 2007-03-04 14:56:31.000000000 +0100 +++ gdc-0.24/d/dmd/lexer.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -407,6 +407,7 @@ { //printf("peekPastParen()\n"); int parens = 1; + int curlynest = 0; while (1) { tk = peek(tk); @@ -424,6 +425,20 @@ tk = peek(tk); break; + case TOKlcurly: + curlynest++; + continue; + + case TOKrcurly: + if (--curlynest >= 0) + continue; + break; + + case TOKsemicolon: + if (curlynest) + continue; + break; + case TOKeof: break; @@ -636,9 +651,8 @@ if (mod && id == Id::FILE) { - t->value = TOKstring; t->ustring = (unsigned char *)(loc.filename ? loc.filename : mod->ident->toChars()); - goto Llen; + goto Lstring; } else if (mod && id == Id::LINE) { @@ -647,24 +661,51 @@ } else if (id == Id::DATE) { - t->value = TOKstring; t->ustring = (unsigned char *)date; - goto Llen; + goto Lstring; } else if (id == Id::TIME) { - t->value = TOKstring; t->ustring = (unsigned char *)time; - goto Llen; + goto Lstring; + } + else if (id == Id::VENDOR) + { +#ifdef IN_GCC + t->ustring = (unsigned char *)"GDC"; +#else + t->ustring = (unsigned char *)"Digital Mars D"; +#endif + goto Lstring; } else if (id == Id::TIMESTAMP) { - t->value = TOKstring; t->ustring = (unsigned char *)timestamp; + Lstring: + t->value = TOKstring; Llen: t->postfix = 0; t->len = strlen((char *)t->ustring); } + else if (id == Id::VERSIONX) + { unsigned major = 0; + unsigned minor = 0; + + for (char *p = global.version + 1; 1; p++) + { + char c = *p; + if (isdigit(c)) + minor = minor * 10 + c - '0'; + else if (c == '.') + { major = minor; + minor = 0; + } + else + break; + } + t->value = TOKint64v; + t->uns64value = major * 1000 + minor; + } } //printf("t->value = %d\n",t->value); return; @@ -2605,6 +2646,10 @@ { "invariant", TOKinvariant }, { "unittest", TOKunittest }, { "version", TOKversion }, + + // Added after 1.0 + { "ref", TOKref }, + { "macro", TOKmacro }, }; int Token::isKeyword() @@ -2621,10 +2666,14 @@ { StringValue *sv; unsigned u; enum TOK v; + unsigned nkeywords = sizeof(keywords) / sizeof(keywords[0]); + + if (global.params.Dversion == 1) + nkeywords -= 2; cmtable_init(); - for (u = 0; u < sizeof(keywords) / sizeof(keywords[0]); u++) + for (u = 0; u < nkeywords; u++) { char *s; //printf("keyword[%d] = '%s'\n",u, keywords[u].name); @@ -2728,6 +2777,8 @@ Token::tochars[TOKtypedot] = "typedot"; Token::tochars[TOKarraylength] = "arraylength"; Token::tochars[TOKarrayliteral] = "arrayliteral"; + Token::tochars[TOKassocarrayliteral] = "assocarrayliteral"; + Token::tochars[TOKstructliteral] = "structliteral"; Token::tochars[TOKstring] = "string"; Token::tochars[TOKdsymbol] = "symbol"; Token::tochars[TOKtuple] = "tuple"; diff -uNr gdc-0.23/d/dmd/lexer.h gdc-0.24/d/dmd/lexer.h --- gdc-0.23/d/dmd/lexer.h 2007-03-04 14:56:32.000000000 +0100 +++ gdc-0.24/d/dmd/lexer.h 2007-04-29 20:05:44.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -66,7 +66,8 @@ TOKtypeid, TOKuadd, TOKremove, TOKnewanonclass, TOKcomment, - TOKarrayliteral, + TOKarrayliteral, TOKassocarrayliteral, + TOKstructliteral, // Operators TOKlt, TOKgt, @@ -146,6 +147,10 @@ // Testing TOKunittest, + // Added after 1.0 + TOKref, + TOKmacro, + TOKMAX }; diff -uNr gdc-0.23/d/dmd/link.c gdc-0.24/d/dmd/link.c --- gdc-0.23/d/dmd/link.c 2006-12-04 02:30:56.000000000 +0100 +++ gdc-0.24/d/dmd/link.c 2007-04-29 18:39:02.000000000 +0200 @@ -1,9 +1,9 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -139,10 +139,29 @@ p = cmdbuf.toChars(); + FileName *lnkfilename = NULL; + size_t plen = strlen(p); + if (plen > 7000) + { + lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); + File flnk(lnkfilename); + flnk.setbuffer(p, plen); + flnk.ref = 1; + if (flnk.write()) + error("error writing file %s", lnkfilename); + if (lnkfilename->len() < plen) + sprintf(p, "@%s", lnkfilename->toChars()); + } + char *linkcmd = getenv("LINKCMD"); if (!linkcmd) linkcmd = "link"; status = executecmd(linkcmd, p, 1); + if (lnkfilename) + { + remove(lnkfilename->toChars()); + delete lnkfilename; + } return status; #elif linux pid_t childpid; @@ -199,10 +218,6 @@ argv.push((void *)"-m32"); - argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a - argv.push((void *)"-lpthread"); - argv.push((void *)"-lm"); - if (0 && global.params.exefile) { /* This switch enables what is known as 'smart linking' @@ -219,11 +234,20 @@ } for (i = 0; i < global.params.linkswitches->dim; i++) - { - argv.push((void *)"-Xlinker"); - argv.push((void *) global.params.linkswitches->data[i]); + { char *p = (char *)global.params.linkswitches->data[i]; + if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) + // Don't need -Xlinker if switch starts with -l + argv.push((void *)"-Xlinker"); + argv.push((void *) p); } + /* Standard libraries must go after user specified libraries + * passed with -l. + */ + argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a + argv.push((void *)"-lpthread"); + argv.push((void *)"-lm"); + if (!global.params.quiet) { // Print it diff -uNr gdc-0.23/d/dmd/macro.c gdc-0.24/d/dmd/macro.c --- gdc-0.23/d/dmd/macro.c 2006-06-03 04:57:43.000000000 +0200 +++ gdc-0.24/d/dmd/macro.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/macro.h gdc-0.24/d/dmd/macro.h --- gdc-0.23/d/dmd/macro.h 2006-11-11 21:43:57.000000000 +0100 +++ gdc-0.24/d/dmd/macro.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/mangle.c gdc-0.24/d/dmd/mangle.c --- gdc-0.23/d/dmd/mangle.c 2006-12-26 21:57:51.000000000 +0100 +++ gdc-0.24/d/dmd/mangle.c 2007-04-29 14:03:30.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -36,10 +36,11 @@ char *id; Dsymbol *s; + //printf("::mangle(%s)\n", sthis->toChars()); s = sthis; do { - //printf("s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent); + //printf("mangle: s = %p, '%s', parent = %p\n", s, s->toChars(), s->parent); if (s->ident) { FuncDeclaration *fd = s->isFuncDeclaration(); @@ -66,11 +67,16 @@ // buf.prependstring("_D"); L1: - //printf("deco = '%s'\n", sthis->type->deco); + //printf("deco = '%s'\n", sthis->type->deco ? sthis->type->deco : "null"); + //printf("sthis->type = %s\n", sthis->type->toChars()); FuncDeclaration *fd = sthis->isFuncDeclaration(); if (fd && (fd->needThis() || fd->isNested())) buf.writeByte(Type::needThisPrefix()); - buf.writestring(sthis->type->deco); + if (sthis->type->deco) + buf.writestring(sthis->type->deco); + else + { assert(fd->inferRetType); + } id = buf.toChars(); buf.data = NULL; @@ -125,6 +131,7 @@ buf.writestring(p); p = buf.toChars(); buf.data = NULL; + //printf("Declaration::mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent->toChars() : "null", linkage, p); return p; } @@ -140,6 +147,7 @@ if (isMain()) return "_Dmain"; + assert(this); return Declaration::mangle(); } @@ -191,8 +199,28 @@ char *TemplateInstance::mangle() { - //printf("TemplateInstance::mangle() '%s'\n", toChars()); - return Dsymbol::mangle(); + OutBuffer buf; + char *id; + +#if 0 + printf("TemplateInstance::mangle() %s", toChars()); + if (parent) + printf(" parent = %s %s", parent->kind(), parent->toChars()); + printf("\n"); +#endif + id = ident ? ident->toChars() : toChars(); + if (tempdecl->parent) + { + char *p = tempdecl->parent->mangle(); + if (p[0] == '_' && p[1] == 'D') + p += 2; + buf.writestring(p); + } + buf.printf("%"PRIuSIZE"%s", strlen(id), id); + id = buf.toChars(); + buf.data = NULL; + //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id); + return id; } @@ -202,11 +230,15 @@ OutBuffer buf; char *id; - //printf("Dsymbol::mangle() '%s'\n", toChars()); +#if 0 + printf("Dsymbol::mangle() '%s'", toChars()); + if (parent) + printf(" parent = %s %s", parent->kind(), parent->toChars()); + printf("\n"); +#endif id = ident ? ident->toChars() : toChars(); if (parent) { - //printf(" parent = '%s', kind = '%s'\n", parent->mangle(), parent->kind()); char *p = parent->mangle(); if (p[0] == '_' && p[1] == 'D') p += 2; @@ -215,6 +247,7 @@ buf.printf("%"PRIuSIZE"%s", strlen(id), id); id = buf.toChars(); buf.data = NULL; + //printf("Dsymbol::mangle() %s = %s\n", toChars(), id); return id; } diff -uNr gdc-0.23/d/dmd/mars.c gdc-0.24/d/dmd/mars.c --- gdc-0.23/d/dmd/mars.c 2007-03-04 14:56:40.000000000 +0100 +++ gdc-0.24/d/dmd/mars.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -60,7 +60,7 @@ copyright = "Copyright (c) 1999-2007 by Digital Mars"; written = "written by Walter Bright"; - version = "v1.007"; + version = "v1.020"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -150,7 +150,7 @@ 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\ +Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ Usage:\n\ dmd files.d ... { -switch }\n\ \n\ @@ -221,14 +221,6 @@ goto Largs; } - // Initialization - Type::init(); - Id::initialize(); - Module::init(); - initPrecedence(); - - backend_init(); - #if __DMC__ // DMC unique support for response files if (response_expand(&argc,&argv)) // expand response files error("can't open response file"); @@ -569,6 +561,13 @@ if (global.params.cov) VersionCondition::addPredefinedGlobalIdent("D_Coverage"); + // Initialization + Type::init(); + Id::initialize(); + Module::init(); + initPrecedence(); + + backend_init(); //printf("%d source files\n",files.dim); diff -uNr gdc-0.23/d/dmd/mars.h gdc-0.24/d/dmd/mars.h --- gdc-0.23/d/dmd/mars.h 2007-03-04 14:56:50.000000000 +0100 +++ gdc-0.24/d/dmd/mars.h 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -27,11 +27,19 @@ #include #include +#ifdef __DMC__ +#ifdef DEBUG +#undef assert +#define assert(e) (static_cast((e) || (printf("assert %s(%d) %s\n", __FILE__, __LINE__, #e), halt()))) +#endif +#endif + #ifdef IN_GCC /* Changes for the GDC compiler by David Friedman */ #endif -#define BREAKABI 1 // not ready to break the ABI just yet +#define V2 0 // Version 2.0 features +#define BREAKABI 1 // 0 if not ready to break the ABI just yet struct Array; @@ -268,6 +276,16 @@ DYNCAST_TUPLE, }; +enum MATCH +{ + MATCHnomatch, // no match + MATCHconvert, // match with conversions +#if V2 + MATCHconst, // match with conversion to const +#endif + MATCHexact // exact match +}; + void error(Loc loc, const char *format, ...); void verror(Loc loc, const char *format, va_list); void fatal(); diff -uNr gdc-0.23/d/dmd/module.c gdc-0.24/d/dmd/module.c --- gdc-0.23/d/dmd/module.c 2007-03-04 14:57:18.000000000 +0100 +++ gdc-0.24/d/dmd/module.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -577,6 +577,7 @@ #endif } Parser p(this, buf, buflen, docfile != NULL); + p.nextToken(); members = p.parseModule(); md = p.md; numlines = p.loc.linnum; diff -uNr gdc-0.23/d/dmd/module.h gdc-0.24/d/dmd/module.h --- gdc-0.23/d/dmd/module.h 2007-02-02 16:25:51.000000000 +0100 +++ gdc-0.24/d/dmd/module.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/mtype.c gdc-0.24/d/dmd/mtype.c --- gdc-0.23/d/dmd/mtype.c 2007-03-04 15:01:34.000000000 +0100 +++ gdc-0.24/d/dmd/mtype.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -109,7 +109,7 @@ int Tsize_t = Tuns32; int Tptrdiff_t = Tint32; int Tindex = Tint32; -int CLASSINFO_SIZE = 0x3c+8; +int CLASSINFO_SIZE = 0x3c+12; /***************************** Type *****************************/ @@ -271,7 +271,7 @@ Tsize_t = Tuns32; Tptrdiff_t = Tint32; } - CLASSINFO_SIZE = 17 * PTRSIZE; + CLASSINFO_SIZE = 18 * PTRSIZE; } d_uns64 Type::size() @@ -538,7 +538,7 @@ * 2 this and to are the same type */ -int Type::implicitConvTo(Type *to) +MATCH 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); @@ -546,7 +546,7 @@ return MATCHexact; // if (to->ty == Tvoid) // return 1; - return 0; + return MATCHnomatch; } Expression *Type::getProperty(Loc loc, Identifier *ident) @@ -635,12 +635,14 @@ } else if (ident == Id::init) { +#if 0 if (v->init) { if (v->init->isVoidInitializer()) error(e->loc, "%s.init is void", v->toChars()); else - { e = v->init->toExpression(); + { Loc loc = e->loc; + e = v->init->toExpression(); if (e->op == TOKassign || e->op == TOKconstruct) { e = ((AssignExp *)e)->e2; @@ -655,9 +657,14 @@ e = v->type->defaultInit(); } } + e = e->optimize(WANTvalue | WANTinterpret); +// if (!e->isConst()) +// error(loc, ".init cannot be evaluated at compile time"); } return e; } +#endif + return defaultInit(); } } if (ident == Id::typeinfo) @@ -1463,7 +1470,7 @@ return flags & (TFLAGSintegral | TFLAGSfloating); } -int TypeBasic::implicitConvTo(Type *to) +MATCH TypeBasic::implicitConvTo(Type *to) { //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars()); if (this == to) @@ -1761,9 +1768,23 @@ return exp; } +Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp) +{ + ScopeDsymbol *sym = new ArrayScopeSymbol(s); + sym->parent = sc->scopesym; + sc = sc->push(sym); + + exp = exp->semantic(sc); + + sc->pop(); + return exp; +} + void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) { + //printf("TypeSArray::resolve() %s\n", toChars()); next->resolve(loc, sc, pe, pt, ps); + //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); if (*pe) { // It's really an index expression Expression *e; @@ -1789,6 +1810,18 @@ { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, td->objects->dim); goto Ldefault; } + Object *o = (Object *)td->objects->data[(size_t)d]; + if (o->dyncast() == DYNCAST_DSYMBOL) + { + *ps = (Dsymbol *)o; + return; + } + if (o->dyncast() == DYNCAST_EXPRESSION) + { + *ps = NULL; + *pe = (Expression *)o; + return; + } /* Create a new TupleDeclaration which * is a slice [d..d+1] out of the old one. @@ -1797,7 +1830,7 @@ */ Objects *objects = new Objects; objects->setDim(1); - objects->data[0] = td->objects->data[(size_t)d]; + objects->data[0] = o; TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects); *ps = tds; @@ -1815,6 +1848,31 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) { //printf("TypeSArray::semantic() %s\n", toChars()); + + Type *t; + Expression *e; + Dsymbol *s; + next->resolve(loc, sc, &e, &t, &s); + if (dim && s && s->isTupleDeclaration()) + { TupleDeclaration *sd = s->isTupleDeclaration(); + + dim = semanticLength(sc, sd, dim); + dim = dim->optimize(WANTvalue | WANTinterpret); + uinteger_t d = dim->toUInteger(); + + if (d >= sd->objects->dim) + { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); + return Type::terror; + } + Object *o = (Object *)sd->objects->data[(size_t)d]; + if (o->dyncast() != DYNCAST_TYPE) + { error(loc, "%s is not a type", toChars()); + return Type::terror; + } + t = (Type *)o; + return t; + } + next = next->semantic(loc,sc); Type *tbn = next->toBasetype(); @@ -1823,7 +1881,7 @@ dim = semanticLength(sc, tbn, dim); - dim = dim->optimize(WANTvalue); + dim = dim->optimize(WANTvalue | WANTinterpret); integer_t d1 = dim->toInteger(); dim = dim->castTo(sc, tsize_t); dim = dim->optimize(WANTvalue); @@ -1832,9 +1890,7 @@ if (d1 != d2) goto Loverflow; - if (tbn->ty == Tbit && (d2 + 31) < d2) - goto Loverflow; - else if (tbn->isintegral() || + if (tbn->isintegral() || tbn->isfloating() || tbn->ty == Tpointer || tbn->ty == Tarray || @@ -1937,7 +1993,7 @@ return next->memalign(salign); } -int TypeSArray::implicitConvTo(Type *to) +MATCH TypeSArray::implicitConvTo(Type *to) { //printf("TypeSArray::implicitConvTo()\n"); @@ -1946,7 +2002,7 @@ (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/)) { - return 1; + return MATCHconvert; } if (to->ty == Tarray) { target_ptrdiff_t offset = 0; @@ -1963,7 +2019,7 @@ if (next->equals(tsa->next) && dim->equals(tsa->dim)) { - return 1; + return MATCHconvert; } } #endif @@ -2040,6 +2096,7 @@ { case Tfunction: case Tnone: + case Ttuple: error(loc, "can't have array of %s", tbn->toChars()); tn = next = tint32; break; @@ -2105,7 +2162,7 @@ return nty == Tchar || nty == Twchar || nty == Tdchar; } -int TypeDArray::implicitConvTo(Type *to) +MATCH TypeDArray::implicitConvTo(Type *to) { //printf("TypeDArray::implicitConvTo()\n"); @@ -2181,7 +2238,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc) { - //printf("TypeAArray::semantic() index->ty = %d\n", index->ty); + //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty); // Deal with the case where we thought the index was a type, but // in reality it was an expression. @@ -2227,8 +2284,8 @@ #if 0 // Convert to Tarray key = key->next->arrayOf(); - break; #endif + break; case Tbit: case Tbool: case Tfunction: @@ -2262,7 +2319,7 @@ FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tsize_t, "_aaLen", Type::tvoid->arrayOf()); + fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen, Type::tvoid->arrayOf()); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e); @@ -2274,26 +2331,15 @@ Expression *ec; FuncDeclaration *fd; Expressions *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, + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaKeys, Type::tvoid->arrayOf(), Type::tsize_t); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e); - if (size) - arguments->push(new IntegerExp(0, size, Type::tsize_t)); + arguments->push(new IntegerExp(0, size, Type::tsize_t)); e = new CallExp(e->loc, ec, arguments); e->type = index->arrayOf(); } @@ -2303,7 +2349,7 @@ FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaValues", + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaValues, Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t); ec = new VarExp(0, fd); arguments = new Expressions(); @@ -2321,7 +2367,7 @@ FuncDeclaration *fd; Expressions *arguments; - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), "_aaRehash"); + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaRehash); ec = new VarExp(0, fd); arguments = new Expressions(); arguments->push(e->addressOf(sc)); @@ -2396,6 +2442,13 @@ { //printf("TypePointer::semantic()\n"); Type *n = next->semantic(loc, sc); + switch (n->toBasetype()->ty) + { + case Ttuple: + error(loc, "can't have pointer to %s", n->toChars()); + n = tint32; + break; + } if (n != next) deco = NULL; next = n; @@ -2420,7 +2473,7 @@ next->toCBuffer2(buf, NULL, hgs); } -int TypePointer::implicitConvTo(Type *to) +MATCH TypePointer::implicitConvTo(Type *to) { //printf("TypePointer::implicitConvTo()\n"); @@ -2603,7 +2656,7 @@ if (!arg1->type->equals(arg2->type)) goto Ldistinct; - if (arg1->inout != arg2->inout) + if (arg1->storageClass != arg2->storageClass) inoutmismatch = 1; } } @@ -2766,18 +2819,12 @@ if (inuse == 1) inuse--; t = arg->type->toBasetype(); - /* If arg turns out to be a tuple, the number of parameters may - * change. - */ - if (t->ty == Ttuple) - dim = Argument::dim(parameters); - - if (arg->inout != In) + if (arg->storageClass & (STCout | STCref | STClazy)) { if (t->ty == Tsarray) - error(loc, "cannot have out or inout parameter of type %s", t->toChars()); + error(loc, "cannot have out or ref parameter of type %s", t->toChars()); } - if (arg->inout != Lazy && t->ty == Tvoid) + if (!(arg->storageClass & STClazy) && t->ty == Tvoid) error(loc, "cannot have parameter of type %s", arg->type->toChars()); if (arg->defaultArg) @@ -2786,6 +2833,14 @@ arg->defaultArg = resolveProperties(sc, arg->defaultArg); arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type); } + + /* If arg turns out to be a tuple, the number of parameters may + * change. + */ + if (t->ty == Ttuple) + { dim = Argument::dim(parameters); + i--; + } } } deco = merge()->deco; @@ -2833,7 +2888,7 @@ { int m; Expression *arg; - // BUG: what about out and inout? + // BUG: what about out and ref? Argument *p = Argument::getNth(parameters, u); assert(p); @@ -2847,7 +2902,7 @@ } arg = (Expression *)args->data[u]; assert(arg); - if (p->inout == Lazy && p->type->ty == Tvoid && arg->type->ty != Tvoid) + if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid) m = MATCHconvert; else m = arg->implicitConvTo(p->type); @@ -3077,11 +3132,12 @@ void TypeQualified::syntaxCopyHelper(TypeQualified *t) { + //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars()); 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) + if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; @@ -3107,7 +3163,7 @@ buf->writeByte('.'); - if (id->dyncast() != DYNCAST_IDENTIFIER) + if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; ti->toCBuffer(buf, hgs); @@ -3160,43 +3216,11 @@ { 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(loc, 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; - if (!ti->semanticdone) - ti->semantic(sc); - sm = ti->toAlias(); - } - else - sm = s->search(loc, id, 0); + sm = s->searchX(loc, sc, id); //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind()); //printf("getType = '%s'\n", s->getType()->toChars()); if (!sm) { -#if 0 - if (s->isAliasDeclaration() && this->ty == Tident) - { - *pt = this; - return; - } -#endif v = s->isVarDeclaration(); if (v && id == Id::length) { @@ -3221,7 +3245,9 @@ if (sm) goto L2; } - e = t->getProperty(loc, id); + //e = t->getProperty(loc, id); + e = new TypeExp(loc, t); + e = t->dotExp(sc, e, id); i++; L3: for (; i < idents.dim; i++) @@ -3395,56 +3421,23 @@ 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(loc, ident, &scopesym); + + Dsymbol *scopesym; + Dsymbol *s = sc->search(loc, 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(loc, 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; - if (!ti->semanticdone) - ti->semantic(sc); - sm = ti->toAlias(); - } - else - sm = s->search(loc, id, 0); - s = sm; - + { + Identifier *id = (Identifier *)idents.data[i]; + s = s->searchX(loc, sc, id); if (!s) // failed to find a symbol { //printf("\tdidn't find a symbol\n"); break; } - s = s->toAlias(); } } return s; @@ -3514,6 +3507,7 @@ Type *TypeInstance::syntaxCopy() { + //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim); TypeInstance *t; t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL)); @@ -3568,7 +3562,24 @@ Dsymbol *s; //printf("TypeInstance::semantic(%s)\n", toChars()); - resolve(loc, sc, &e, &t, &s); + + if (sc->parameterSpecialization) + { + unsigned errors = global.errors; + global.gag++; + + resolve(loc, sc, &e, &t, &s); + + global.gag--; + if (errors != global.errors) + { if (global.gag == 0) + global.errors = errors; + return this; + } + } + else + resolve(loc, sc, &e, &t, &s); + if (!t) { #ifdef DEBUG @@ -3691,8 +3702,26 @@ if (idents.dim) { - error(loc, ".property not implemented for typeof"); - goto Lerr; + Dsymbol *s = t->toDsymbol(sc); + for (size_t i = 0; i < idents.dim; i++) + { + if (!s) + break; + Identifier *id = (Identifier *)idents.data[i]; + s = s->searchX(loc, sc, id); + } + if (s) + { + t = s->getType(); + if (!t) + { error(loc, "%s is not a type", s->toChars()); + goto Lerr; + } + } + else + { error(loc, "cannot resolve .property for %s", toChars()); + goto Lerr; + } } return t; @@ -3868,16 +3897,16 @@ //return sym->memtype->isscalar(); } -int TypeEnum::implicitConvTo(Type *to) -{ int m; +MATCH TypeEnum::implicitConvTo(Type *to) +{ MATCH m; //printf("TypeEnum::implicitConvTo()\n"); if (this->equals(to)) - m = 2; // exact match + m = MATCHexact; // exact match else if (sym->memtype->implicitConvTo(to)) - m = 1; // match with conversions + m = MATCHconvert; // match with conversions else - m = 0; // no match + m = MATCHnomatch; // no match return m; } @@ -3976,20 +4005,7 @@ #endif if (ident == Id::init) { - if (e->op == TOKvar) - { - VarExp *ve = (VarExp *)e; - VarDeclaration *v = ve->var->isVarDeclaration(); - - assert(v); - if (v->init) - { if (v->init->isVoidInitializer()) - error(e->loc, "%s.init is void", v->toChars()); - else - return v->init->toExpression(); - } - } - return defaultInit(); + return Type::dotExp(sc, e, ident); } return sym->basetype->dotExp(sc, e, ident); } @@ -4056,16 +4072,16 @@ return t; } -int TypeTypedef::implicitConvTo(Type *to) -{ int m; +MATCH TypeTypedef::implicitConvTo(Type *to) +{ MATCH m; //printf("TypeTypedef::implicitConvTo()\n"); if (this->equals(to)) - m = 2; // exact match + m = MATCHexact; // exact match else if (sym->basetype->implicitConvTo(to)) - m = 1; // match with conversions + m = MATCHconvert; // match with conversions else - m = 0; // no match + m = MATCHnomatch; // no match return m; } @@ -4313,6 +4329,12 @@ e = e->semantic(sc); return e; } + if (d->isTupleDeclaration()) + { + e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = e->semantic(sc); + return e; + } return new VarExp(e->loc, d); } @@ -4641,6 +4663,12 @@ e = de->semantic(sc); return e; } + else if (d->isTupleDeclaration()) + { + e = new TupleExp(e->loc, d->isTupleDeclaration()); + e = e->semantic(sc); + return e; + } else ve = new VarExp(e->loc, d); return ve; @@ -4695,26 +4723,26 @@ return 0; } -int TypeClass::implicitConvTo(Type *to) +MATCH TypeClass::implicitConvTo(Type *to) { //printf("TypeClass::implicitConvTo('%s')\n", to->toChars()); if (this == to) - return 2; + return MATCHexact; ClassDeclaration *cdto = to->isClassHandle(); if (cdto && cdto->isBaseOf(sym, NULL)) { //printf("is base\n"); - return 1; + return MATCHconvert; } if (global.params.Dversion == 1) { // Allow conversion to (void *) if (to->ty == Tpointer && to->next->ty == Tvoid) - return 1; + return MATCHconvert; } - return 0; + return MATCHnomatch; } Expression *TypeClass::defaultInit() @@ -4778,7 +4806,7 @@ { Expression *e = (Expression *)exps->data[i]; if (e->type->ty == Ttuple) e->error("cannot form tuple of tuples"); - Argument *arg = new Argument(In, e->type, NULL, NULL); + Argument *arg = new Argument(STCin, e->type, NULL, NULL); arguments->data[i] = (void *)arg; } } @@ -5026,17 +5054,17 @@ /***************************** Argument *****************************/ -Argument::Argument(enum InOut inout, Type *type, Identifier *ident, Expression *defaultArg) +Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg) { this->type = type; this->ident = ident; - this->inout = inout; + this->storageClass = storageClass; this->defaultArg = defaultArg; } Argument *Argument::syntaxCopy() { - Argument *a = new Argument(inout, + Argument *a = new Argument(storageClass, type ? type->syntaxCopy() : NULL, ident, defaultArg ? defaultArg->syntaxCopy() : NULL); @@ -5106,11 +5134,12 @@ if (i) buf->writestring(", "); arg = (Argument *)arguments->data[i]; - if (arg->inout == Out) + if (arg->storageClass & STCout) buf->writestring("out "); - else if (arg->inout == InOut) - buf->writestring("inout "); - else if (arg->inout == Lazy) + else if (arg->storageClass & STCref) + buf->writestring((global.params.Dversion == 1) + ? (char *)"inout " : (char *)"ref "); + else if (arg->storageClass & STClazy) buf->writestring("lazy "); argbuf.reset(); arg->type->toCBuffer2(&argbuf, arg->ident, hgs); @@ -5179,16 +5208,17 @@ void Argument::toDecoBuffer(OutBuffer *buf) { - switch (inout) - { case In: + switch (storageClass & (STCin | STCout | STCref | STClazy)) + { case 0: + case STCin: break; - case Out: + case STCout: buf->writeByte('J'); break; - case InOut: + case STCref: buf->writeByte('K'); break; - case Lazy: + case STClazy: buf->writeByte('L'); break; default: diff -uNr gdc-0.23/d/dmd/mtype.h gdc-0.24/d/dmd/mtype.h --- gdc-0.23/d/dmd/mtype.h 2007-02-18 16:28:49.000000000 +0100 +++ gdc-0.24/d/dmd/mtype.h 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -115,14 +115,6 @@ extern int Tptrdiff_t; extern int Tindex; -enum MATCH -{ - MATCHnomatch, // no match - MATCHconvert, // match with conversions - MATCHexact // exact match -}; - - struct Type : Object { TY ty; @@ -236,7 +228,7 @@ virtual Dsymbol *toDsymbol(Scope *sc); virtual Type *toBasetype(); virtual int isBaseOf(Type *t, target_ptrdiff_t *poffset); - virtual int implicitConvTo(Type *to); + virtual MATCH implicitConvTo(Type *to); virtual ClassDeclaration *isClassHandle(); virtual Expression *getProperty(Loc loc, Identifier *ident); virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); @@ -254,6 +246,7 @@ virtual Type *reliesOnTident(); virtual Expression *toExpression(); virtual int hasPointers(); + Type *nextOf() { return next; } static void error(Loc loc, const char *format, ...); @@ -289,7 +282,7 @@ int iscomplex(); int isscalar(); int isunsigned(); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Expression *defaultInit(); int isZeroInit(); int builtinTypeInfo(); @@ -324,7 +317,7 @@ int isString(); int isZeroInit(); unsigned memalign(unsigned salign); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Expression *defaultInit(); dt_t **toDt(dt_t **pdt); dt_t **toDtElem(dt_t **pdt, Expression *e); @@ -352,7 +345,7 @@ int isString(); int isZeroInit(); int checkBoolean(); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Expression *defaultInit(); int builtinTypeInfo(); TypeInfoDeclaration *getTypeInfoDeclaration(); @@ -392,7 +385,7 @@ Type *semantic(Loc loc, Scope *sc); d_uns64 size(Loc loc); void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); int isscalar(); Expression *defaultInit(); int isZeroInit(); @@ -566,7 +559,7 @@ int isfloating(); int isscalar(); int isunsigned(); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Type *toBasetype(); Expression *defaultInit(); int isZeroInit(); @@ -602,7 +595,7 @@ int isunsigned(); int checkBoolean(); Type *toBasetype(); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Expression *defaultInit(); int isZeroInit(); dt_t **toDt(dt_t **pdt); @@ -629,7 +622,7 @@ Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); ClassDeclaration *isClassHandle(); int isBaseOf(Type *t, target_ptrdiff_t *poffset); - int implicitConvTo(Type *to); + MATCH implicitConvTo(Type *to); Expression *defaultInit(); int isZeroInit(); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes); @@ -673,16 +666,17 @@ /**************************************************************/ -enum InOut { None, In, Out, InOut, Lazy }; +//enum InOut { None, In, Out, InOut, Lazy }; struct Argument : Object { - enum InOut inout; + //enum InOut inout; + unsigned storageClass; Type *type; Identifier *ident; Expression *defaultArg; - Argument(enum InOut inout, Type *type, Identifier *ident, Expression *defaultArg); + Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg); Argument *syntaxCopy(); Type *isLazyArray(); void toDecoBuffer(OutBuffer *buf); diff -uNr gdc-0.23/d/dmd/opover.c gdc-0.24/d/dmd/opover.c --- gdc-0.23/d/dmd/opover.c 2007-03-04 15:02:01.000000000 +0100 +++ gdc-0.24/d/dmd/opover.c 2007-07-27 02:07:14.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -36,7 +36,7 @@ #include "..\root\mem.h" #endif -#include "port.h" +//#include "port.h" #include "mtype.h" #include "init.h" #include "expression.h" @@ -533,7 +533,7 @@ arg = (Argument *)arguments->data[1]; } if (!arg->type && tab->ty != Ttuple) - arg->type = tab->next; // value type + arg->type = tab->nextOf(); // value type break; case Taarray: @@ -577,7 +577,7 @@ #endif Lapply: { /* Look for an - * int opApply(int delegate(inout Type [, ...]) dg); + * int opApply(int delegate(ref Type [, ...]) dg); * overload */ Dsymbol *s = search_function(ad, @@ -603,7 +603,7 @@ } else { - inferApplyArgTypesY((TypeFunction *)tab->next, arguments); + inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments); } break; } @@ -618,6 +618,23 @@ * analogous to func.overloadResolveX(). */ +int fp3(void *param, FuncDeclaration *f) +{ + Arguments *arguments = (Arguments *)param; + TypeFunction *tf = (TypeFunction *)f->type; + if (inferApplyArgTypesY(tf, arguments) == 1) + return 0; + if (arguments->dim == 0) + return 1; + return 0; +} + +static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments) +{ + overloadApply(fstart, &fp3, arguments); +} + +#if 0 static void inferApplyArgTypesX(FuncDeclaration *fstart, Arguments *arguments) { Declaration *d; @@ -660,6 +677,7 @@ } } } +#endif /****************************** * Infer arguments from type of function. @@ -677,7 +695,7 @@ p = Argument::getNth(tf->parameters, 0); if (p->type->ty != Tdelegate) goto Lnomatch; - tf = (TypeFunction *)p->type->next; + tf = (TypeFunction *)p->type->nextOf(); assert(tf->ty == Tfunction); /* We now have tf, the type of the delegate. Match it against diff -uNr gdc-0.23/d/dmd/optimize.c gdc-0.24/d/dmd/optimize.c --- gdc-0.23/d/dmd/optimize.c 2007-03-04 15:17:21.000000000 +0100 +++ gdc-0.24/d/dmd/optimize.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -48,16 +48,14 @@ Expression *fromConstInitializer(Expression *e1) { + //printf("fromConstInitializer(%s)\n", e1->toChars()); if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); if (v && v->isConst() && v->init) { Expression *ei = v->init->toExpression(); - if (ei) - { e1 = ei; - if (!e1->type) - e1->type = v->type; - } + if (ei && ei->type) + e1 = ei; } } return e1; @@ -70,6 +68,15 @@ return this; } +Expression *VarExp::optimize(int result) +{ + if (result & WANTinterpret) + { + return fromConstInitializer(this); + } + return this; +} + Expression *TupleExp::optimize(int result) { for (size_t i = 0; i < exps->dim; i++) @@ -95,6 +102,37 @@ return this; } +Expression *AssocArrayLiteralExp::optimize(int result) +{ + assert(keys->dim == values->dim); + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (Expression *)keys->data[i]; + + e = e->optimize(WANTvalue | (result & WANTinterpret)); + keys->data[i] = (void *)e; + + e = (Expression *)values->data[i]; + e = e->optimize(WANTvalue | (result & WANTinterpret)); + values->data[i] = (void *)e; + } + return this; +} + +Expression *StructLiteralExp::optimize(int result) +{ + if (elements) + { + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + if (!e) + continue; + e = e->optimize(WANTvalue | (result & WANTinterpret)); + elements->data[i] = (void *)e; + } + } + return this; +} + Expression *TypeExp::optimize(int result) { return this; @@ -179,7 +217,8 @@ } if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; - if (!ve->var->isOut() && !ve->var->isImportedSymbol()) + if (!ve->var->isOut() && !ve->var->isRef() && + !ve->var->isImportedSymbol()) { e = new SymOffExp(loc, ve->var, 0); e->type = type; @@ -212,6 +251,7 @@ Expression *PtrExp::optimize(int result) { + //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); e1 = e1->optimize(result); // Convert *&ex to ex if (e1->op == TOKaddress) @@ -233,6 +273,15 @@ } return e; } + // Constant fold *(&structliteral + offset) + if (e1->op == TOKadd) + { + Expression *e; + e = Ptr(type, e1); + if (e != EXP_CANT_INTERPRET) + return e; + } + return this; } @@ -260,10 +309,15 @@ { //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); //printf("from %s to %s\n", type->toChars(), to->toChars()); + //printf("from %s\n", type->toChars()); //printf("type = %p\n", type); assert(type); + enum TOK op1 = e1->op; e1 = e1->optimize(result); + if (result & WANTinterpret) + e1 = fromConstInitializer(e1); + if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && type->next->equals(e1->type->next) @@ -272,6 +326,10 @@ e1->type = type; return e1; } + /* The first test here is to prevent infinite loops + */ + if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) + return e1->castTo(NULL, to); if (e1->op == TOKnull && (type->ty == Tpointer || type->ty == Tclass)) { @@ -515,7 +573,7 @@ //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e = this; - if (e1->op == TOKstring || e1->op == TOKarrayliteral) + if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) { e = ArrayLength(type, e1); } diff -uNr gdc-0.23/d/dmd/parse.c gdc-0.24/d/dmd/parse.c --- gdc-0.23/d/dmd/parse.c 2007-03-04 15:17:41.000000000 +0100 +++ gdc-0.24/d/dmd/parse.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -36,6 +36,9 @@ #include "enum.h" #include "id.h" #include "version.h" +#ifdef IN_GCC +#include "d-dmd-gcc.h" +#endif // How multiple declarations are parsed. // If 1, treat as C. @@ -66,7 +69,7 @@ linkage = LINKd; endloc = 0; inBrackets = 0; - nextToken(); // start up the scanner + //nextToken(); // start up the scanner } Array *Parser::parseModule() @@ -197,7 +200,17 @@ break; case TOKinvariant: +#if 1 s = parseInvariant(); +#else + if (peek(&token)->value == TOKlcurly) + s = parseInvariant(); + else + { + stc = STCinvariant; + goto Lstc; + } +#endif break; case TOKunittest: @@ -267,6 +280,7 @@ case TOKabstract: stc |= STCabstract; goto Lstc; case TOKsynchronized: stc |= STCsynchronized; goto Lstc; case TOKdeprecated: stc |= STCdeprecated; goto Lstc; + //case TOKinvariant: stc |= STCinvariant; goto Lstc; default: break; } @@ -277,17 +291,36 @@ if (token.value == TOKidentifier && peek(&token)->value == TOKassign) { - Identifier *ident = token.ident; - nextToken(); - nextToken(); - Initializer *init = parseInitializer(); - VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init); - v->storage_class = stc; - s = v; - if (token.value != TOKsemicolon) - error("semicolon expected following auto declaration, not '%s'", token.toChars()); - else + while (1) + { + Identifier *ident = token.ident; + nextToken(); nextToken(); + Initializer *init = parseInitializer(); + VarDeclaration *v = new VarDeclaration(loc, NULL, ident, init); + v->storage_class = stc; + s = v; + if (token.value == TOKsemicolon) + { + nextToken(); + } + else if (token.value == TOKcomma) + { + nextToken(); + if (token.value == TOKidentifier && + peek(&token)->value == TOKassign) + { + decldefs->push(s); + addComment(s, comment); + continue; + } + else + error("Identifier expected following comma"); + } + else + error("semicolon expected following auto declaration, not '%s'", token.toChars()); + break; + } } else { a = parseBlock(); @@ -477,7 +510,7 @@ case TOKcolon: nextToken(); -#if 1 +#if 0 a = NULL; #else a = parseDeclDefs(0); // grab declarations up to closing curly bracket @@ -544,9 +577,21 @@ nextToken(); } } + else if (id == Id::System) + { +#ifdef IN_GCC + link = d_gcc_is_target_win32() ? LINKwindows : LINKc; +#else +#if _WIN32 + link = LINKwindows; +#else + link = LINKc; +#endif +#endif + } else { - error("valid linkage identifiers are D, C, C++, Pascal, Windows"); + error("valid linkage identifiers are D, C, C++, Pascal, Windows, System"); link = LINKd; } } @@ -742,8 +787,11 @@ Loc loc = this->loc; nextToken(); - //check(TOKlparen); // don't require () - //check(TOKrparen); + if (token.value == TOKlparen) // optional () + { + nextToken(); + check(TOKrparen); + } f = new InvariantDeclaration(loc, 0); f->fbody = parseStatement(PScurly); @@ -829,11 +877,11 @@ Identifier *ai; Type *at; Argument *a; - enum InOut inout; + unsigned storageClass; Expression *ae; ai = NULL; - inout = In; // parameter is "in" by default + storageClass = STCin; // parameter is "in" by default switch (token.value) { case TOKrparen: @@ -845,22 +893,23 @@ break; case TOKin: - inout = In; + storageClass = STCin; nextToken(); goto L1; case TOKout: - inout = Out; + storageClass = STCout; nextToken(); goto L1; case TOKinout: - inout = InOut; + case TOKref: + storageClass = STCref; nextToken(); goto L1; case TOKlazy: - inout = Lazy; + storageClass = STClazy; nextToken(); goto L1; @@ -884,15 +933,15 @@ * at ai ... */ - if (inout == Out || inout == InOut) - error("variadic argument cannot be out or inout"); + if (storageClass & (STCout | STCref)) + error("variadic argument cannot be out or ref"); varargs = 2; - a = new Argument(inout, at, ai, ae); + a = new Argument(storageClass, at, ai, ae); arguments->push(a); nextToken(); break; } - a = new Argument(inout, at, ai, ae); + a = new Argument(storageClass, at, ai, ae); arguments->push(a); if (token.value == TOKcomma) { nextToken(); @@ -1300,69 +1349,25 @@ 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 (1 || !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; + * mixin typeof(expr).identifier!(args); */ Dsymbol *Parser::parseMixin() { TemplateMixin *tm; Identifier *id; - TypeTypeof *tqual; + Type *tqual; Objects *tiargs; Array *idents; //printf("parseMixin()\n"); nextToken(); - tqual = NULL; if (token.value == TOKdot) { @@ -1945,7 +1950,7 @@ /* Look for auto initializers: * storage_class identifier = initializer; */ - if (storage_class && + while (storage_class && token.value == TOKidentifier && peek(&token)->value == TOKassign) { @@ -1961,6 +1966,16 @@ nextToken(); addComment(v, comment); } + else if (token.value == TOKcomma) + { + nextToken(); + if (!(token.value == TOKidentifier && peek(&token)->value == TOKassign)) + { + error("Identifier expected following comma"); + } + else + continue; + } else error("semicolon expected following auto declaration, not '%s'", token.toChars()); return a; @@ -2014,7 +2029,15 @@ v = new AliasDeclaration(loc, ident, t); } v->storage_class = storage_class; - a->push(v); + if (link == linkage) + a->push(v); + else + { + Array *ax = new Array(); + ax->push(v); + Dsymbol *s = new LinkDeclaration(link, ax); + a->push(s); + } switch (token.value) { case TOKsemicolon: nextToken(); @@ -2074,7 +2097,15 @@ } v = new VarDeclaration(loc, t, ident, init); v->storage_class = storage_class; - a->push(v); + if (link == linkage) + a->push(v); + else + { + Array *ax = new Array(); + ax->push(v); + Dsymbol *s = new LinkDeclaration(link, ax); + a->push(s); + } switch (token.value) { case TOKsemicolon: nextToken(); @@ -2340,7 +2371,7 @@ case TOKvoid: t = peek(&token); - if (t->value == TOKsemicolon) + if (t->value == TOKsemicolon || t->value == TOKcomma) { nextToken(); return new VoidInitializer(loc); @@ -2468,6 +2499,8 @@ case TOKconst: case TOKauto: case TOKextern: + case TOKfinal: + case TOKinvariant: // case TOKtypeof: Ldeclaration: { Array *a; @@ -2645,12 +2678,12 @@ Type *tb; Identifier *ai = NULL; Type *at; - enum InOut inout; + unsigned storageClass; Argument *a; - inout = In; - if (token.value == TOKinout) - { inout = InOut; + storageClass = STCin; + if (token.value == TOKinout || token.value == TOKref) + { storageClass = STCref; nextToken(); } if (token.value == TOKidentifier) @@ -2668,7 +2701,7 @@ if (!ai) error("no identifier for declarator %s", at->toChars()); Larg: - a = new Argument(inout, at, ai, NULL); + a = new Argument(storageClass, at, ai, NULL); arguments->push(a); if (token.value == TOKcomma) { nextToken(); @@ -2702,7 +2735,7 @@ Token *t = peek(&token); if (t->value == TOKassign) { - arg = new Argument(In, NULL, token.ident, NULL); + arg = new Argument(STCin, NULL, token.ident, NULL); nextToken(); nextToken(); } @@ -2725,7 +2758,7 @@ tb = parseBasicType(); at = parseDeclarator(tb, &ai); check(TOKassign); - arg = new Argument(In, at, ai, NULL); + arg = new Argument(STCin, at, ai, NULL); } // Check for " ident;" @@ -2734,7 +2767,7 @@ Token *t = peek(&token); if (t->value == TOKcomma || t->value == TOKsemicolon) { - arg = new Argument(In, NULL, token.ident, NULL); + arg = new Argument(STCin, NULL, token.ident, NULL); nextToken(); nextToken(); if (1 || !global.params.useDeprecated) @@ -3204,7 +3237,7 @@ Expressions * argConstraints = NULL; int nOutputArgs = 0; Expressions * clobbers = NULL; - enum InOut phase = Out; + bool isInputPhase = false; // Output operands first, then input. insnTemplate = parseExpression(); if (token.value == TOKrparen || token.value == TOKsemicolon) @@ -3253,7 +3286,7 @@ args->push(arg); argNames->push(name); argConstraints->push(constraint); - if (phase == Out) + if (! isInputPhase) nOutputArgs++; if (token.value == TOKcomma) @@ -3262,8 +3295,8 @@ } continue; LnextPhase: - if (phase == Out) - phase = In; + if (! isInputPhase) + isInputPhase = true; else break; } @@ -3306,8 +3339,13 @@ void Parser::check(enum TOK value) { + check(loc, value); +} + +void Parser::check(Loc loc, enum TOK value) +{ if (token.value != value) - error("found '%s' when expecting '%s'", token.toChars(), Token::toChars(value)); + error(loc, "found '%s' when expecting '%s'", token.toChars(), Token::toChars(value)); nextToken(); } @@ -3584,6 +3622,8 @@ case TOKin: case TOKout: case TOKinout: + case TOKref: + case TOKlazy: t = peek(t); default: if (!isBasicType(&t)) @@ -4088,13 +4128,47 @@ // ( expression ) nextToken(); e = parseExpression(); - check(TOKrparen); + check(loc, TOKrparen); break; case TOKlbracket: - { Expressions *elements = parseArguments(); + { /* Parse array literals and associative array literals: + * [ value, value, value ... ] + * [ key:value, key:value, key:value ... ] + */ + Expressions *values = new Expressions(); + Expressions *keys = NULL; - e = new ArrayLiteralExp(loc, elements); + nextToken(); + if (token.value != TOKrbracket) + { + while (1) + { + Expression *e = parseAssignExp(); + if (token.value == TOKcolon && (keys || values->dim == 0)) + { nextToken(); + if (!keys) + keys = new Expressions(); + keys->push(e); + e = parseAssignExp(); + } + else if (keys) + { error("'key:value' expected for associative array literal"); + delete keys; + keys = NULL; + } + values->push(e); + if (token.value == TOKrbracket) + break; + check(TOKcomma); + } + } + check(TOKrbracket); + + if (keys) + e = new AssocArrayLiteralExp(loc, keys, values); + else + e = new ArrayLiteralExp(loc, values); break; } diff -uNr gdc-0.23/d/dmd/parse.h gdc-0.24/d/dmd/parse.h --- gdc-0.23/d/dmd/parse.h 2007-03-04 15:17:46.000000000 +0100 +++ gdc-0.24/d/dmd/parse.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -69,7 +69,6 @@ Array *parseBlock(); TemplateDeclaration *parseTemplateDeclaration(); TemplateParameters *parseTemplateParameterList(); - TemplateInstance *parseTemplateInstance(); Dsymbol *parseMixin(); Objects *parseTemplateArgumentList(); StaticAssert *parseStaticAssert(); @@ -98,6 +97,7 @@ Statement *parseStatement(int flags); Statement *parseExtAsm(int expect_rparen); Initializer *parseInitializer(); + void check(Loc loc, enum TOK value); void check(enum TOK value); void check(enum TOK value, char *string); int isDeclaration(Token *t, int needId, enum TOK endtok, Token **pt); diff -uNr gdc-0.23/d/dmd/port.h gdc-0.24/d/dmd/port.h --- gdc-0.23/d/dmd/port.h 2006-06-03 04:57:44.000000000 +0200 +++ gdc-0.24/d/dmd/port.h 2007-04-29 18:39:02.000000000 +0200 @@ -34,10 +34,17 @@ static double dbl_max; static double dbl_min; - static int isnan(double); - static int isfinite(double); - static int isinfinity(double); - static int signbit(double); +#if __GNUC__ + // These conflict with macros in math.h, should rename them + #undef isnan + #undef isfinite + #undef isinfinity + #undef signbit +#endif + 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); diff -uNr gdc-0.23/d/dmd/scope.c gdc-0.24/d/dmd/scope.c --- gdc-0.23/d/dmd/scope.c 2007-02-08 18:58:10.000000000 +0100 +++ gdc-0.24/d/dmd/scope.c 2007-07-23 02:23:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -32,21 +32,26 @@ Scope *Scope::freelist = NULL; void *Scope::operator new(size_t size) -{ Scope *s; - +{ if (freelist) { - s = freelist; + Scope *s = freelist; freelist = s->enclosing; + //printf("freelist %p\n", s); + assert(s->flags & SCOPEfree); + s->flags &= ~SCOPEfree; return s; } - return ::operator new(size); + void *p = ::operator new(size); + //printf("new %p\n", p); + return p; } Scope::Scope() { // Create root scope + //printf("Scope::Scope() %p\n", this); this->module = NULL; this->scopesym = NULL; this->sd = NULL; @@ -71,6 +76,7 @@ this->nofree = 0; this->noctor = 0; this->intypeof = 0; + this->parameterSpecialization = 0; this->callSuper = 0; this->flags = 0; this->anonAgg = NULL; @@ -81,6 +87,8 @@ Scope::Scope(Scope *enclosing) { + //printf("Scope::Scope(enclosing = %p) %p\n", enclosing, this); + assert(!(enclosing->flags & SCOPEfree)); this->module = enclosing->module; this->func = enclosing->func; this->parent = enclosing->parent; @@ -93,6 +101,15 @@ this->fes = enclosing->fes; this->structalign = enclosing->structalign; this->enclosing = enclosing; +#ifdef DEBUG + if (enclosing->enclosing) + assert(!(enclosing->enclosing->flags & SCOPEfree)); + if (this == enclosing->enclosing) + { + printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", this, enclosing, enclosing->enclosing); + } + assert(this != enclosing->enclosing); +#endif this->slabel = NULL; this->linkage = enclosing->linkage; this->protection = enclosing->protection; @@ -105,6 +122,7 @@ this->nofree = 0; this->noctor = enclosing->noctor; this->intypeof = enclosing->intypeof; + this->parameterSpecialization = enclosing->parameterSpecialization; this->callSuper = enclosing->callSuper; this->flags = 0; this->anonAgg = NULL; @@ -154,7 +172,7 @@ Scope *Scope::pop() { - //printf("Scope::pop()\n"); + //printf("Scope::pop() %p nofree = %d\n", this, nofree); Scope *enc = enclosing; if (enclosing) @@ -163,6 +181,7 @@ if (!nofree) { enclosing = freelist; freelist = this; + flags |= SCOPEfree; } return enc; @@ -242,7 +261,7 @@ { if (global.params.warnings) fprintf(stdmsg, "warning - "); - error("array 'length' hides other 'length' name in outer scope"); + error(s->loc, "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()); @@ -329,9 +348,18 @@ void Scope::setNoFree() { Scope *sc; + //int i = 0; + //printf("Scope::setNoFree(this = %p)\n", this); for (sc = this; sc; sc = sc->enclosing) { + //printf("\tsc = %p\n", sc); sc->nofree = 1; + + assert(!(flags & SCOPEfree)); + //assert(sc != sc->enclosing); + //assert(!sc->enclosing || sc != sc->enclosing->enclosing); + //if (++i == 10) + //assert(0); } } diff -uNr gdc-0.23/d/dmd/scope.h gdc-0.24/d/dmd/scope.h --- gdc-0.23/d/dmd/scope.h 2007-02-15 01:45:25.000000000 +0100 +++ gdc-0.24/d/dmd/scope.h 2007-07-23 02:23:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -60,6 +60,7 @@ int nofree; // set if shouldn't free it int noctor; // set if constructor calls aren't allowed int intypeof; // in typeof(exp) + int parameterSpecialization; // if in template parameter specialization unsigned callSuper; // primitive flow analysis for constructors #define CSXthis_ctor 1 // called this() @@ -82,6 +83,7 @@ unsigned flags; #define SCOPEctor 1 // constructor type #define SCOPEstaticif 2 // inside static if +#define SCOPEfree 4 // is on free list AnonymousAggregateDeclaration *anonAgg; // for temporary analysis diff -uNr gdc-0.23/d/dmd/statement.c gdc-0.24/d/dmd/statement.c --- gdc-0.23/d/dmd/statement.c 2007-03-04 15:18:00.000000000 +0100 +++ gdc-0.24/d/dmd/statement.c 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -257,6 +257,7 @@ se = se->toUTF8(sc); Parser p(sc->module, (unsigned char *)se->string, se->len, 0); p.loc = loc; + p.nextToken(); Statements *statements = new Statements(); while (p.token.value != TOKeof) @@ -787,7 +788,7 @@ Statement *WhileStatement::syntaxCopy() { - WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body->syntaxCopy()); + WhileStatement *s = new WhileStatement(loc, condition->syntaxCopy(), body ? body->syntaxCopy() : NULL); return s; } @@ -819,6 +820,7 @@ condition = condition->semantic(sc); condition = resolveProperties(sc, condition); + condition = condition->optimize(WANTvalue); condition = condition->checkToBoolean(); sc->noctor++; @@ -826,7 +828,8 @@ Scope *scd = sc->push(); scd->sbreak = this; scd->scontinue = this; - body = body->semantic(scd); + if (body) + body = body->semantic(scd); scd->pop(); sc->noctor--; @@ -846,12 +849,13 @@ int WhileStatement::usesEH() { - return body->usesEH(); + return body ? body->usesEH() : 0; } int WhileStatement::fallOffEnd() { - body->fallOffEnd(); + if (body) + body->fallOffEnd(); return TRUE; } @@ -868,7 +872,8 @@ condition->toCBuffer(buf, hgs); buf->writebyte(')'); buf->writenl(); - body->toCBuffer(buf, hgs); + if (body) + body->toCBuffer(buf, hgs); } /******************************** DoStatement ***************************/ @@ -882,7 +887,7 @@ Statement *DoStatement::syntaxCopy() { - DoStatement *s = new DoStatement(loc, body->syntaxCopy(), condition->syntaxCopy()); + DoStatement *s = new DoStatement(loc, body ? body->syntaxCopy() : NULL, condition->syntaxCopy()); return s; } @@ -890,7 +895,8 @@ Statement *DoStatement::semantic(Scope *sc) { sc->noctor++; - body = body->semanticScope(sc, this, this); + if (body) + body = body->semanticScope(sc, this, this); sc->noctor--; condition = condition->semantic(sc); condition = resolveProperties(sc, condition); @@ -912,12 +918,13 @@ int DoStatement::usesEH() { - return body->usesEH(); + return body ? body->usesEH() : 0; } int DoStatement::fallOffEnd() { - body->fallOffEnd(); + if (body) + body->fallOffEnd(); return TRUE; } @@ -932,7 +939,8 @@ { buf->writestring("do"); buf->writenl(); - body->toCBuffer(buf, hgs); + if (body) + body->toCBuffer(buf, hgs); buf->writestring("while ("); condition->toCBuffer(buf, hgs); buf->writebyte(')'); @@ -1142,11 +1150,11 @@ //printf("aggr: op = %d, %s\n", aggr->op, aggr->toChars()); size_t n; TupleExp *te = NULL; - if (aggr->op == TOKtuple) + if (aggr->op == TOKtuple) // expression tuple { te = (TupleExp *)aggr; n = te->exps->dim; } - else if (aggr->op == TOKtype) + else if (aggr->op == TOKtype) // type tuple { n = Argument::dim(tuple->arguments); } @@ -1165,8 +1173,8 @@ if (dim == 2) { // Declare key - if (arg->inout != In) - error("no storage class for %s", arg->ident->toChars()); + if (arg->storageClass & (STCout | STCref | STClazy)) + error("no storage class for key %s", arg->ident->toChars()); TY keyty = arg->type->ty; if ((keyty != Tint32 && keyty != Tuns32) && (! global.params.isX86_64 || @@ -1183,14 +1191,29 @@ arg = (Argument *)arguments->data[1]; // value } // Declare value - if (arg->inout != In) - error("no storage class for %s", arg->ident->toChars()); + if (arg->storageClass & (STCout | STCref | STClazy)) + error("no storage class for value %s", arg->ident->toChars()); Dsymbol *var; if (te) { - arg->type = e->type; - Initializer *ie = new ExpInitializer(0, e); - var = new VarDeclaration(loc, arg->type, arg->ident, ie); + if (e->type->toBasetype()->ty == Tfunction && + e->op == TOKvar) + { VarExp *ve = (VarExp *)e; + var = new AliasDeclaration(loc, arg->ident, ve->var); + } + else + { + arg->type = e->type; + Initializer *ie = new ExpInitializer(0, e); + VarDeclaration *v = new VarDeclaration(loc, arg->type, arg->ident, ie); + if (e->isConst()) + v->storage_class |= STCconst; +#if V2 + else + v->storage_class |= STCfinal; +#endif + var = v; + } } else { @@ -1249,12 +1272,12 @@ 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 (arg->storageClass & STCref) + error("foreach: value of UTF conversion cannot be ref"); if (dim == 2) { arg = (Argument *)arguments->data[0]; - if (arg->inout == InOut) - error("foreach: key cannot be inout"); + if (arg->storageClass & STCref) + error("foreach: key cannot be ref"); } goto Lapply; } @@ -1267,12 +1290,7 @@ var = new VarDeclaration(loc, 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; - default: assert(0); - } + var->storage_class |= arg->storageClass & (STCin | STCout | STCref); #if 1 DeclarationExp *de = new DeclarationExp(loc, var); de->semantic(sc); @@ -1312,8 +1330,8 @@ 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"); + if (key && key->storage_class & (STCout | STCref)) + error("foreach: key cannot be out or ref"); break; case Taarray: @@ -1360,17 +1378,17 @@ } /* Turn body into the function literal: - * int delegate(inout T arg) { body } + * int delegate(ref T arg) { body } */ args = new Arguments(); for (i = 0; i < dim; i++) { Argument *arg = (Argument *)arguments->data[i]; arg->type = arg->type->semantic(loc, sc); - if (arg->inout == InOut) + if (arg->storageClass & STCref) id = arg->ident; else - { // Make a copy of the inout argument so it isn't + { // Make a copy of the ref argument so it isn't // a reference. VarDeclaration *v; Initializer *ie; @@ -1384,7 +1402,7 @@ s = new DeclarationStatement(0, v); body = new CompoundStatement(loc, s, body); } - a = new Argument(InOut, arg->type, id, NULL); + a = new Argument(STCref, arg->type, id, NULL); args->push(a); } t = new TypeFunction(args, Type::tint32, 0, LINKd); @@ -1412,8 +1430,8 @@ Argument *arg = (Argument *)arguments->data[0]; if (dim == 2) { - if (arg->inout == InOut) - error("foreach: index cannot be inout"); + if (arg->storageClass & STCref) + error("foreach: index cannot be ref"); 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]; @@ -1586,8 +1604,9 @@ Argument *a = (Argument *)arguments->data[i]; if (i) buf->writestring(", "); - if (a->inout == InOut) - buf->writestring("inout "); + if (a->storageClass & STCref) + buf->writestring((global.params.Dversion == 1) + ? (char*)"inout " : (char*)"ref "); if (a->type) a->type->toCBuffer(buf, a->ident, hgs); else @@ -2061,12 +2080,13 @@ int SwitchStatement::usesEH() { - return body->usesEH(); + return body ? body->usesEH() : 0; } int SwitchStatement::fallOffEnd() { - body->fallOffEnd(); + if (body) + body->fallOffEnd(); return TRUE; // need to do this better } @@ -2116,7 +2136,7 @@ { int i; exp = exp->implicitCastTo(sc, sw->condition->type); - exp = exp->optimize(WANTvalue); + exp = exp->optimize(WANTvalue | WANTinterpret); if (exp->op != TOKstring && exp->op != TOKint64) { error("case must be a string or an integral constant, not %s", exp->toChars()); @@ -2422,7 +2442,7 @@ { VarExp *ve = (VarExp *)exp; VarDeclaration *v = ve->var->isVarDeclaration(); - if (!v || v->isOut()) + if (!v || v->isOut() || v->isRef()) fd->nrvo_can = 0; else if (fd->nrvo_var == NULL) { if (!v->isDataseg() && !v->isParameter() && v->toParent2() == fd) @@ -2433,6 +2453,8 @@ else if (fd->nrvo_var != v) fd->nrvo_can = 0; } + else + fd->nrvo_can = 0; if (fd->returnLabel && tbret->ty != Tvoid) { @@ -2823,7 +2845,7 @@ Statement *SynchronizedStatement::syntaxCopy() { Expression *e = exp ? exp->syntaxCopy() : NULL; - SynchronizedStatement *s = new SynchronizedStatement(loc, e, body->syntaxCopy()); + SynchronizedStatement *s = new SynchronizedStatement(loc, e, body ? body->syntaxCopy() : NULL); return s; } @@ -2845,7 +2867,8 @@ exp = exp->semantic(sc); } } - body = body->semantic(sc); + if (body) + body = body->semantic(sc); return this; } @@ -2866,7 +2889,7 @@ int SynchronizedStatement::fallOffEnd() { - return body->fallOffEnd(); + return body ? body->fallOffEnd() : TRUE; } void SynchronizedStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -2896,7 +2919,7 @@ Statement *WithStatement::syntaxCopy() { - WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body->syntaxCopy()); + WithStatement *s = new WithStatement(loc, exp->syntaxCopy(), body ? body->syntaxCopy() : NULL); return s; } @@ -2912,6 +2935,16 @@ sym = es->sds; } + else if (exp->op == TOKtype) + { TypeExp *es = (TypeExp *)exp; + + sym = es->type->toDsymbol(sc)->isScopeDsymbol(); + if (!sym) + { error("%s has no members", es->toChars()); + body = body->semantic(sc); + return this; + } + } else { Type *t = exp->type; @@ -2942,7 +2975,8 @@ } sc = sc->push(sym); - body = body->semantic(sc); + if (body) + body = body->semantic(sc); sc->pop(); @@ -2954,17 +2988,18 @@ buf->writestring("with ("); exp->toCBuffer(buf, hgs); buf->writestring(")\n"); - body->toCBuffer(buf, hgs); + if (body) + body->toCBuffer(buf, hgs); } int WithStatement::usesEH() { - return body->usesEH(); + return body ? body->usesEH() : 0; } int WithStatement::fallOffEnd() { - return body->fallOffEnd(); + return body ? body->fallOffEnd() : TRUE; } /******************************** TryCatchStatement ***************************/ @@ -3007,7 +3042,7 @@ char *si = c->loc.toChars(); char *sj = cj->loc.toChars(); - if (c->type->implicitConvTo(cj->type)) + if (c->type->toBasetype()->implicitConvTo(cj->type->toBasetype())) error("catch at %s hides catch at %s", sj, si); } } @@ -3100,7 +3135,7 @@ if (!type) type = new TypeIdentifier(0, Id::Object); type = type->semantic(loc, sc); - if (!type->isClassHandle()) + if (!type->toBasetype()->isClassHandle()) error("can only catch class objects, not '%s'", type->toChars()); else if (ident) { @@ -3335,7 +3370,7 @@ Statement *VolatileStatement::semantic(Scope *sc) { - statement = statement->semantic(sc); + statement = statement ? statement->semantic(sc) : NULL; return this; } @@ -3343,7 +3378,7 @@ { Statements *a; - a = statement->flatten(sc); + a = statement ? statement->flatten(sc) : NULL; if (a) { for (int i = 0; i < a->dim; i++) { Statement *s = (Statement *)a->data[i]; @@ -3358,7 +3393,7 @@ int VolatileStatement::fallOffEnd() { - return statement->fallOffEnd(); + return statement ? statement->fallOffEnd() : TRUE; } void VolatileStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff -uNr gdc-0.23/d/dmd/statement.h gdc-0.24/d/dmd/statement.h --- gdc-0.23/d/dmd/statement.h 2007-03-04 15:18:05.000000000 +0100 +++ gdc-0.24/d/dmd/statement.h 2007-07-23 02:23:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -25,6 +25,7 @@ struct Expression; struct LabelDsymbol; struct Identifier; +struct IfStatement; struct DeclarationStatement; struct DefaultStatement; struct VarDeclaration; @@ -100,6 +101,7 @@ virtual DeclarationStatement *isDeclarationStatement() { return NULL; } virtual CompoundStatement *isCompoundStatement() { return NULL; } virtual ReturnStatement *isReturnStatement() { return NULL; } + virtual IfStatement *isIfStatement() { return NULL; } }; struct ExpStatement : Statement @@ -328,6 +330,7 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); int usesEH(); int fallOffEnd(); + IfStatement *isIfStatement() { return this; } int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); diff -uNr gdc-0.23/d/dmd/staticassert.c gdc-0.24/d/dmd/staticassert.c --- gdc-0.23/d/dmd/staticassert.c 2006-06-06 00:18:18.000000000 +0200 +++ gdc-0.24/d/dmd/staticassert.c 2007-07-23 02:23:26.000000000 +0200 @@ -1,8 +1,8 @@ -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -15,6 +15,7 @@ #include "staticassert.h" #include "expression.h" #include "id.h" +#include "hdrgen.h" /********************************* AttribDeclaration ****************************/ @@ -49,20 +50,21 @@ Expression *e; e = exp->semantic(sc); - e = e->optimize(WANTvalue); + e = e->optimize(WANTvalue | WANTinterpret); if (e->isBool(FALSE)) { if (msg) - { + { HdrGenState hgs; + OutBuffer buf; + msg = msg->semantic(sc); - msg = msg->optimize(WANTvalue); - char *p = msg->toChars(); - p = strdup(p); - error("(%s) is false, %s", exp->toChars(), p); - free(p); + msg = msg->optimize(WANTvalue | WANTinterpret); + hgs.console = 1; + msg->toCBuffer(&buf, &hgs); + error("%s", buf.toChars()); } else - error("(%s) is false", exp->toChars()); + error("is false"); if (!global.gag) fatal(); } diff -uNr gdc-0.23/d/dmd/staticassert.h gdc-0.24/d/dmd/staticassert.h --- gdc-0.23/d/dmd/staticassert.h 2006-11-11 21:49:55.000000000 +0100 +++ gdc-0.24/d/dmd/staticassert.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/struct.c gdc-0.24/d/dmd/struct.c --- gdc-0.23/d/dmd/struct.c 2007-02-15 14:03:29.000000000 +0100 +++ gdc-0.24/d/dmd/struct.c 2007-04-29 20:05:44.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -40,6 +40,7 @@ structsize = 0; // size of struct alignsize = 0; // size of struct for alignment purposes structalign = 0; // struct member alignment in effect + hasUnions = 0; sizeok = 0; // size not determined yet isdeprecated = 0; inv = NULL; @@ -317,7 +318,7 @@ TypeFunction *tfeqptr; { Arguments *arguments = new Arguments; - Argument *arg = new Argument(In, handle, Id::p, NULL); + Argument *arg = new Argument(STCin, handle, Id::p, NULL); arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); @@ -327,7 +328,7 @@ TypeFunction *tfeq; { Arguments *arguments = new Arguments; - Argument *arg = new Argument(In, type, NULL, NULL); + Argument *arg = new Argument(STCin, type, NULL, NULL); arguments->push(arg); tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); diff -uNr gdc-0.23/d/dmd/template.c gdc-0.24/d/dmd/template.c --- gdc-0.23/d/dmd/template.c 2007-03-04 15:18:12.000000000 +0100 +++ gdc-0.24/d/dmd/template.c 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -81,6 +81,45 @@ return (Tuple *)o; } +/*********************** + * Try to get arg as a type. + */ + +Type *getType(Object *o) +{ + Type *t = isType(o); + if (!t) + { Expression *e = isExpression(o); + if (e) + t = e->type; + } + return t; +} + +Dsymbol *getDsymbol(Object *oarg) +{ + Dsymbol *sa; + 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 + sa = NULL; + } + 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 + } + return sa; +} + /****************************** * If o1 matches o2, return 1. * Else, return 0. @@ -164,6 +203,50 @@ return 0; // nomatch; } +/**************************************** + */ + +void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg) +{ + Type *t = isType(oarg); + Expression *e = isExpression(oarg); + Dsymbol *s = isDsymbol(oarg); + Tuple *v = isTuple(oarg); + if (t) + t->toCBuffer(buf, NULL, hgs); + else if (e) + e->toCBuffer(buf, hgs); + else if (s) + { + char *p = s->ident ? s->ident->toChars() : s->toChars(); + buf->writestring(p); + } + else if (v) + { + Objects *args = &v->objects; + for (size_t i = 0; i < args->dim; i++) + { + if (i) + buf->writeByte(','); + Object *o = (Object *)args->data[i]; + ObjectToCBuffer(buf, hgs, o); + } + } + else if (!oarg) + { + buf->writestring("NULL"); + } + else + { +#ifdef DEBUG + printf("bad Object = %p\n", oarg); +#endif + assert(0); + } +} + + + /* ======================== TemplateDeclaration ============================= */ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Array *decldefs) @@ -253,6 +336,14 @@ ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = sc->parent; Scope *paramscope = sc->push(paramsym); + paramscope->parameterSpecialization = 1; + + for (int i = 0; i < parameters->dim; i++) + { + TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; + + tp->declareParameter(paramscope); + } for (int i = 0; i < parameters->dim; i++) { @@ -307,6 +398,7 @@ TemplateDeclaration *pthis = this; for (pf = &pthis; *pf; pf = &(*pf)->overnext) { +#if 0 // Conflict if TemplateParameter's match // Will get caught anyway later with TemplateInstance, but // should check it now. @@ -330,6 +422,7 @@ Lcontinue: ; +#endif } f->overroot = this; @@ -346,6 +439,8 @@ * those deduced types in dedtypes[]. * Input: * flag 1: don't do semantic() because of dummy types + * Output: + * dedtypes deduced arguments * Return match level. */ @@ -372,7 +467,12 @@ // If more arguments than parameters, no match if (ti->tiargs->dim > parameters_dim && !variadic) + { +#if LOG + printf(" no match: more arguments than parameters\n"); +#endif return MATCHnomatch; + } assert(dedtypes_dim == parameters_dim); assert(dedtypes_dim >= ti->tiargs->dim || variadic); @@ -390,6 +490,7 @@ TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; Declaration *sparam; + //printf("\targument [%d]\n", i); #if 0 printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null"); TemplateTypeParameter *ttp = tp->isTemplateTypeParameter(); @@ -400,7 +501,10 @@ m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam); if (m2 == MATCHnomatch) - { //printf("\tmatchArg() for parameter %i failed\n", i); + { +#if 0 + printf("\tmatchArg() for parameter %i failed\n", i); +#endif goto Lnomatch; } @@ -562,7 +666,7 @@ printf("\nTemplateDeclaration::deduceMatch() %s\n", toChars()); for (i = 0; i < fargs->dim; i++) { Expression *e = (Expression *)fargs->data[i]; - printf("\tfarg[%d] = %s\n", i, e->toChars()); + printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars()); } #endif @@ -692,20 +796,25 @@ } else { farg = (Expression *)fargs->data[i]; +#if 0 + printf("\tfarg->type = %s\n", farg->type->toChars()); + printf("\tfparam->type = %s\n", fparam->type->toChars()); +#endif + m = farg->type->deduceType(scope, fparam->type, parameters, &dedtypes); - //printf("\tm = %d\n", m); + //printf("\tdeduceType m = %d\n", m); /* If no match, see if there's a conversion to a delegate */ if (!m && fparam->type->toBasetype()->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype(); - TypeFunction *tf = (TypeFunction *)td->next; + TypeFunction *tf = (TypeFunction *)td->nextOf(); if (!tf->varargs && Argument::dim(tf->parameters) == 0) { - m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes); - if (!m && tf->next->toBasetype()->ty == Tvoid) + m = farg->type->deduceType(scope, tf->nextOf(), parameters, &dedtypes); + if (!m && tf->nextOf()->toBasetype()->ty == Tvoid) m = MATCHconvert; } //printf("\tm2 = %d\n", m); @@ -758,6 +867,13 @@ { o = tp->defaultArg(paramscope); if (!o) goto Lnomatch; +#if 0 + Match m; + Declaration *sparam; + m = tp->matchArg(paramscope, dedargs, i, parameters, &sparam); + if (!m) + goto Lnomatch; +#endif } declareParameter(paramscope, tp, o); dedargs->data[i] = (void *)o; @@ -787,7 +903,7 @@ void TemplateDeclaration::declareParameter(Scope *sc, TemplateParameter *tp, Object *o) { - //printf("TemplateDeclaration::declareParameter('%s')\n", tp->ident->toChars()); + //printf("TemplateDeclaration::declareParameter('%s', o = %p)\n", tp->ident->toChars(), o); Type *targ = isType(o); Expression *ea = isExpression(o); @@ -952,7 +1068,7 @@ } if (td_ambig) { - error(loc, "%s matches more than one template declaration, %s and %s", + error(loc, "%s matches more than one function template declaration, %s and %s", toChars(), td_best->toChars(), td_ambig->toChars()); } @@ -1085,7 +1201,6 @@ if (!tparam) goto Lnomatch; - Lagain: if (this == tparam) goto Lexact; @@ -1102,7 +1217,7 @@ */ tparam = tparam->semantic(0, sc); assert(tparam->ty != Tident); - goto Lagain; + return deduceType(sc, tparam, parameters, dedtypes); } TemplateParameter *tp = (TemplateParameter *)parameters->data[i]; @@ -1118,8 +1233,12 @@ } if (equals(at)) goto Lexact; + else if (ty == Tclass && at->ty == Tclass) + { + return (MATCH) implicitConvTo(at); + } else if (ty == Tsarray && at->ty == Tarray && - next->equals(at->next)) + next->equals(at->nextOf())) { goto Lexact; } @@ -1130,8 +1249,8 @@ if (ty != tparam->ty) goto Lnomatch; - if (next) - return next->deduceType(sc, tparam->next, parameters, dedtypes); + if (nextOf()) + return nextOf()->deduceType(sc, tparam->nextOf(), parameters, dedtypes); Lexact: return MATCHexact; @@ -1185,7 +1304,7 @@ else { dedtypes->data[i] = (void *)dim; } - return next->deduceType(sc, tparam->next, parameters, dedtypes); + return next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); } } } @@ -1194,7 +1313,7 @@ else if (tparam->ty == Tarray) { MATCH m; - m = next->deduceType(sc, tparam->next, parameters, dedtypes); + m = next->deduceType(sc, tparam->nextOf(), parameters, dedtypes); if (m == MATCHexact) m = MATCHconvert; return m; @@ -1308,7 +1427,7 @@ { Argument *a = Argument::getNth(this->parameters, i); Argument *ap = Argument::getNth(tp->parameters, i); - if (a->inout != ap->inout || + if (a->storageClass != ap->storageClass || !a->type->deduceType(sc, ap->type, parameters, dedtypes)) return MATCHnomatch; } @@ -1339,7 +1458,7 @@ Type *tparam, TemplateParameters *parameters, Objects *dedtypes) { - //printf("TypeInstance::deduceType()\n"); + //printf("TypeInstance::deduceType(tparam = %s) %s\n", tparam->toChars(), toChars()); //printf("\ttparam = %d, ", tparam->ty); tparam->print(); // Extra check @@ -1347,18 +1466,18 @@ { 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)) + //printf("tempinst->tempdecl = %p\n", tempinst->tempdecl); + //printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl); + if (!tp->tempinst->tempdecl) + { if (!tp->tempinst->name->equals(tempinst->name)) goto Lnomatch; } + else if (tempinst->tempdecl != tp->tempinst->tempdecl) + goto Lnomatch; for (int i = 0; i < tempinst->tiargs->dim; i++) { - //printf("test1: [%d]\n", i); + //printf("test: [%d]\n", i); Object *o1 = (Object *)tempinst->tiargs->data[i]; Object *o2 = (Object *)tp->tempinst->tiargs->data[i]; @@ -1430,11 +1549,35 @@ * to a template instance, too, and try again. */ TemplateInstance *ti = sym->parent->isTemplateInstance(); - if (ti && ti->toAlias() == sym && - tparam && tparam->ty == Tinstance) + + if (tparam && tparam->ty == Tinstance) { - TypeInstance *t = new TypeInstance(0, ti); - return t->deduceType(sc, tparam, parameters, dedtypes); + if (ti && ti->toAlias() == sym) + { + TypeInstance *t = new TypeInstance(0, ti); + return t->deduceType(sc, tparam, parameters, dedtypes); + } + + /* Match things like: + * S!(T).foo + */ + TypeInstance *tpi = (TypeInstance *)tparam; + if (tpi->idents.dim) + { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1]; + if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) + { + Type *tparent = sym->parent->getType(); + if (tparent) + { + /* Slice off the .foo in S!(T).foo + */ + tpi->idents.dim--; + MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes); + tpi->idents.dim++; + return m; + } + } + } } // Extra check @@ -1476,18 +1619,42 @@ MATCH TypeClass::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes) { - //printf("TypeClass::deduceType()\n"); + //printf("TypeClass::deduceType(this = %s)\n", toChars()); /* If this class is a template class, and we're matching * it against a template instance, convert the class type * to a template instance, too, and try again. */ TemplateInstance *ti = sym->parent->isTemplateInstance(); - if (ti && ti->toAlias() == sym && - tparam && tparam->ty == Tinstance) + + if (tparam && tparam->ty == Tinstance) { - TypeInstance *t = new TypeInstance(0, ti); - return t->deduceType(sc, tparam, parameters, dedtypes); + if (ti && ti->toAlias() == sym) + { + TypeInstance *t = new TypeInstance(0, ti); + return t->deduceType(sc, tparam, parameters, dedtypes); + } + + /* Match things like: + * S!(T).foo + */ + TypeInstance *tpi = (TypeInstance *)tparam; + if (tpi->idents.dim) + { Identifier *id = (Identifier *)tpi->idents.data[tpi->idents.dim - 1]; + if (id->dyncast() == DYNCAST_IDENTIFIER && sym->ident->equals(id)) + { + Type *tparent = sym->parent->getType(); + if (tparent) + { + /* Slice off the .foo in S!(T).foo + */ + tpi->idents.dim--; + MATCH m = tparent->deduceType(sc, tpi, parameters, dedtypes); + tpi->idents.dim++; + return m; + } + } + } } // Extra check @@ -1507,6 +1674,7 @@ { this->loc = loc; this->ident = ident; + this->sparam = NULL; } TemplateTypeParameter *TemplateParameter::isTemplateTypeParameter() @@ -1557,14 +1725,18 @@ return tp; } -void TemplateTypeParameter::semantic(Scope *sc) +void TemplateTypeParameter::declareParameter(Scope *sc) { - //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars()); + //printf("TemplateTypeParameter::declareParameter('%s')\n", ident->toChars()); TypeIdentifier *ti = new TypeIdentifier(loc, ident); - Declaration *sparam = new AliasDeclaration(loc, ident, ti); + sparam = new AliasDeclaration(loc, ident, ti); if (!sc->insert(sparam)) error(loc, "parameter '%s' multiply defined", ident->toChars()); +} +void TemplateTypeParameter::semantic(Scope *sc) +{ + //printf("TemplateTypeParameter::semantic('%s')\n", ident->toChars()); if (specType) { specType = specType->semantic(loc, sc); @@ -1607,6 +1779,7 @@ /******************************************* * Match to a particular TemplateParameter. * Input: + * i i'th argument * tiargs[] actual arguments to template instance * parameters[] template parameters * dedtypes[] deduced arguments to template instance @@ -1629,12 +1802,18 @@ { // Get default argument instead oarg = defaultArg(sc); if (!oarg) - goto Lnomatch; + { assert(i < dedtypes->dim); + // It might have already been deduced + oarg = (Object *)dedtypes->data[i]; + if (!oarg) + goto Lnomatch; + } } ta = isType(oarg); if (!ta) goto Lnomatch; + //printf("ta is %s\n", ta->toChars()); t = (Type *)dedtypes->data[i]; @@ -1775,13 +1954,16 @@ return tp; } -void TemplateAliasParameter::semantic(Scope *sc) +void TemplateAliasParameter::declareParameter(Scope *sc) { TypeIdentifier *ti = new TypeIdentifier(loc, ident); - Declaration *sparam = new AliasDeclaration(loc, ident, ti); + sparam = new AliasDeclaration(loc, ident, ti); if (!sc->insert(sparam)) error(loc, "parameter '%s' multiply defined", ident->toChars()); +} +void TemplateAliasParameter::semantic(Scope *sc) +{ if (specAliasT) { specAlias = specAliasT->toDsymbol(sc); @@ -1826,28 +2008,15 @@ { // Get default argument instead oarg = defaultArg(sc); if (!oarg) - goto Lnomatch; - } - - 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 + { assert(i < dedtypes->dim); + // It might have already been deduced + oarg = (Object *)dedtypes->data[i]; + if (!oarg) + goto Lnomatch; + } } + sa = getDsymbol(oarg); if (!sa) goto Lnomatch; @@ -1969,13 +2138,17 @@ return tp; } -void TemplateValueParameter::semantic(Scope *sc) +void TemplateValueParameter::declareParameter(Scope *sc) { - VarDeclaration *sparam = new VarDeclaration(loc, valType, ident, NULL); - sparam->storage_class = STCtemplateparameter; - if (!sc->insert(sparam)) + VarDeclaration *v = new VarDeclaration(loc, valType, ident, NULL); + v->storage_class = STCtemplateparameter; + if (!sc->insert(v)) error(loc, "parameter '%s' multiply defined", ident->toChars()); + sparam = v; +} +void TemplateValueParameter::semantic(Scope *sc) +{ sparam->semantic(sc); valType = valType->semantic(loc, sc); if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && @@ -2049,7 +2222,12 @@ { // Get default argument instead oarg = defaultArg(sc); if (!oarg) - goto Lnomatch; + { assert(i < dedtypes->dim); + // It might have already been deduced + oarg = (Object *)dedtypes->data[i]; + if (!oarg) + goto Lnomatch; + } } ei = isExpression(oarg); @@ -2192,14 +2370,18 @@ return tp; } -void TemplateTupleParameter::semantic(Scope *sc) +void TemplateTupleParameter::declareParameter(Scope *sc) { TypeIdentifier *ti = new TypeIdentifier(loc, ident); - Declaration *sparam = new AliasDeclaration(loc, ident, ti); + sparam = new AliasDeclaration(loc, ident, ti); if (!sc->insert(sparam)) error(loc, "parameter '%s' multiply defined", ident->toChars()); } +void TemplateTupleParameter::semantic(Scope *sc) +{ +} + int TemplateTupleParameter::overloadMatch(TemplateParameter *tp) { TemplateTupleParameter *tvp = tp->isTemplateTupleParameter(); @@ -2230,7 +2412,7 @@ else { ovar = new Tuple(); - //printf("test3: ovar = %p\n", ovar); + //printf("ovar = %p\n", ovar); if (i < tiargs->dim) { //printf("i = %d, tiargs->dim = %d\n", i, tiargs->dim); @@ -2310,7 +2492,7 @@ printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident->toChars() : "null"); #endif this->loc = loc; - this->idents.push(ident); + this->name = ident; this->tiargs = NULL; this->tempdecl = NULL; this->inst = NULL; @@ -2323,7 +2505,7 @@ this->objFileModule = NULL; #endif this->havetempdecl = 0; - this->isnested = 0; + this->isnested = NULL; this->errors = 0; } @@ -2335,7 +2517,7 @@ printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td->toChars()); #endif this->loc = loc; - this->idents.push(td->ident); + this->name = td->ident; this->tiargs = tiargs; this->tempdecl = td; this->inst = NULL; @@ -2348,13 +2530,35 @@ this->objFileModule = NULL; #endif this->havetempdecl = 1; - this->isnested = 0; + this->isnested = NULL; this->errors = 0; assert((size_t)tempdecl->scope > 0x10000); } +Objects *TemplateInstance::arraySyntaxCopy(Objects *objs) +{ + Objects *a = NULL; + if (objs) + { a = new Objects(); + a->setDim(objs->dim); + for (size_t i = 0; i < objs->dim; i++) + { + Type *ta = isType((Object *)objs->data[i]); + if (ta) + a->data[i] = ta->syntaxCopy(); + else + { + Expression *ea = isExpression((Object *)objs->data[i]); + assert(ea); + a->data[i] = ea->syntaxCopy(); + } + } + } + return a; +} + Dsymbol *TemplateInstance::syntaxCopy(Dsymbol *s) { TemplateInstance *ti; @@ -2363,37 +2567,15 @@ if (s) ti = (TemplateInstance *)s; else - ti = new TemplateInstance(loc, (Identifier *)idents.data[0]); + ti = new TemplateInstance(loc, name); - ti->idents.setDim(idents.dim); - for (i = 1; i < idents.dim; i++) - ti->idents.data[i] = idents.data[i]; - - ti->tiargs = new Objects(); - 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(); - } - } + ti->tiargs = arraySyntaxCopy(tiargs); ScopeDsymbol::syntaxCopy(ti); return ti; } -void TemplateInstance::addIdent(Identifier *ident) -{ - idents.push(ident); -} - #ifdef IN_GCC #include "d-dmd-gcc.h" #endif @@ -2449,7 +2631,12 @@ assert((size_t)tempdecl->scope > 0x10000); // Deduce tdtypes tdtypes.setDim(tempdecl->parameters->dim); - tempdecl->matchWithInstance(this, &tdtypes, 0); + if (!tempdecl->matchWithInstance(this, &tdtypes, 0)) + { + error("incompatible arguments for template instantiation"); + inst = this; + return; + } } else { @@ -2457,6 +2644,8 @@ semanticTiargs(sc); tempdecl = findTemplateDeclaration(sc); + if (tempdecl) + tempdecl = findBestMatch(sc); if (!tempdecl || global.errors) { inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); @@ -2481,9 +2670,10 @@ // Nesting must match if (isnested != ti->isnested) continue; +#if 0 if (isnested && sc->parent != ti->parent) continue; - +#endif for (size_t j = 0; j < tdtypes.dim; j++) { Object *o1 = (Object *)tdtypes.data[j]; Object *o2 = (Object *)ti->tdtypes.data[j]; @@ -2517,8 +2707,10 @@ ident = genIdent(); // need an identifier for name mangling purposes. +#if 1 if (isnested) - parent = sc->parent; + parent = isnested; +#endif //printf("parent = '%s'\n", parent->kind()); // Add 'this' to the enclosing scope's members[] so the semantic routines @@ -2667,7 +2859,7 @@ { Dsymbol *s = (Dsymbol *)members->data[i]; //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->toChars()); - //printf("test2: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); + //printf("test: isnested = %d, sc2->parent = %s\n", isnested, sc2->parent->toChars()); // if (isnested) // s->parent = sc->parent; //printf("test3: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); @@ -2737,8 +2929,16 @@ void TemplateInstance::semanticTiargs(Scope *sc) { + //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); + semanticTiargs(loc, sc, tiargs); +} + +void TemplateInstance::semanticTiargs(Loc loc, Scope *sc, Objects *tiargs) +{ // Run semantic on each argument, place results in tiargs[] //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); + if (!tiargs) + return; for (size_t j = 0; j < tiargs->dim; j++) { Object *o = (Object *)tiargs->data[j]; @@ -2839,66 +3039,51 @@ if (!tempdecl) { /* Given: - * instance foo.bar.abc( ... ) - * figure out which TemplateDeclaration foo.bar.abc refers to. + * foo!( ... ) + * figure out which TemplateDeclaration foo refers to. */ Dsymbol *s; Dsymbol *scopesym; Identifier *id; int i; - id = (Identifier *)idents.data[0]; + id = name; s = sc->search(loc, id, &scopesym); - if (s) - { + if (!s) + { error("identifier '%s' is not defined", id->toChars()); + return NULL; + } #if LOG - printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind()); - printf("s->parent = '%s'\n", s->parent->toChars()); + printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind()); + printf("s->parent = '%s'\n", s->parent->toChars()); #endif - withsym = scopesym->isWithScopeSymbol(); - - /* We might have found an alias within a template when - * we really want the template. - */ - TemplateInstance *ti; - if (idents.dim == 1 && s->parent && - (ti = s->parent->isTemplateInstance()) != NULL) - { - if ( - (ti->idents.data[ti->idents.dim - 1] == id || - ti->toAlias()->ident == id) - && - ti->tempdecl) - { - /* This is so that one can refer to the enclosing - * template, even if it has the same name as a member - * of the template, if it has a !(arguments) - */ - tempdecl = ti->tempdecl; - if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's - tempdecl = tempdecl->overroot; // then get the start - s = tempdecl; - } - } + withsym = scopesym->isWithScopeSymbol(); - s = s->toAlias(); - for (i = 1; i < idents.dim; i++) - { Dsymbol *sm; - - id = (Identifier *)idents.data[i]; - sm = s->search(loc, id, 0); - if (!sm) - { - s = NULL; - break; - } - s = sm->toAlias(); + /* We might have found an alias within a template when + * we really want the template. + */ + TemplateInstance *ti; + if (s->parent && + (ti = s->parent->isTemplateInstance()) != NULL) + { + if ( + (ti->name == id || + ti->toAlias()->ident == id) + && + ti->tempdecl) + { + /* This is so that one can refer to the enclosing + * template, even if it has the same name as a member + * of the template, if it has a !(arguments) + */ + tempdecl = ti->tempdecl; + if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's + tempdecl = tempdecl->overroot; // then get the start + s = tempdecl; } } - if (!s) - { error("identifier '%s' is not defined", id->toChars()); - return NULL; - } + + s = s->toAlias(); /* It should be a TemplateDeclaration, not some other symbol */ @@ -2916,13 +3101,15 @@ } s = s2; } - assert(s->parent); - TemplateInstance *ti = s->parent->isTemplateInstance(); +#ifdef DEBUG + //if (!s->parent) printf("s = %s %s\n", s->kind(), s->toChars()); +#endif + //assert(s->parent); + TemplateInstance *ti = s->parent ? s->parent->isTemplateInstance() : NULL; if (ti && - (ti->idents.data[ti->idents.dim - 1] == id || + (ti->name == id || ti->toAlias()->ident == id) && - idents.dim == 1 && ti->tempdecl) { /* This is so that one can refer to the enclosing @@ -2942,7 +3129,11 @@ } else assert(tempdecl->isTemplateDeclaration()); + return tempdecl; +} +TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc) +{ /* Since there can be multiple TemplateDeclaration's with the same * name, look for the best match. */ @@ -2951,6 +3142,9 @@ MATCH m_best = MATCHnomatch; Objects dedtypes; +#if LOG + printf("TemplateInstance::findBestMatch()\n"); +#endif for (TemplateDeclaration *td = tempdecl; td; td = td->overnext) { MATCH m; @@ -3062,7 +3256,7 @@ */ int TemplateInstance::isNested(Objects *args) -{ +{ int nested = 0; //printf("TemplateInstance::isNested('%s')\n", tempdecl->ident->toChars()); /* A nested instance happens when an argument references a local @@ -3096,8 +3290,11 @@ { // if module level template if (tempdecl->toParent()->isModule()) - { isnested = 1; - return 1; + { + if (isnested && isnested != d->toParent()) + error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars()); + isnested = d->toParent(); + nested |= 1; } else error("cannot use local '%s' as template parameter", d->toChars()); @@ -3105,11 +3302,10 @@ } else if (va) { - if (isNested(&va->objects)) - return 1; + nested |= isNested(&va->objects); } } - return 0; + return nested; } /**************************************** @@ -3322,13 +3518,8 @@ { int i; - for (i = 0; i < idents.dim; i++) - { Identifier *id = (Identifier *)idents.data[i]; - - if (i) - buf->writeByte('.'); - buf->writestring(id->toChars()); - } + Identifier *id = name; + buf->writestring(id->toChars()); buf->writestring("!("); if (nest) buf->writestring("..."); @@ -3341,35 +3532,7 @@ if (i) buf->writeByte(','); Object *oarg = (Object *)args->data[i]; - Type *t = isType(oarg); - Expression *e = isExpression(oarg); - Dsymbol *s = isDsymbol(oarg); - Tuple *v = isTuple(oarg); - if (t) - t->toCBuffer(buf, NULL, hgs); - else if (e) - e->toCBuffer(buf, hgs); - else if (s) - { - char *p = s->ident ? s->ident->toChars() : s->toChars(); - buf->writestring(p); - } - else if (v) - { assert(i + 1 == args->dim); - args = &v->objects; - i = -1; - } - else if (!oarg) - { - buf->writestring("NULL"); - } - else - { -#ifdef DEBUG - printf("tiargs[%d] = %p\n", i, oarg); -#endif - assert(0); - } + ObjectToCBuffer(buf, hgs, oarg); } nest--; } @@ -3426,7 +3589,7 @@ /* ======================== TemplateMixin ================================ */ -TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, TypeTypeof *tqual, +TemplateMixin::TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs) : TemplateInstance(loc, (Identifier *)idents->data[idents->dim - 1]) { @@ -3446,7 +3609,7 @@ for (int i = 0; i < idents->dim; i++) { // Matches TypeQualified::syntaxCopyHelper() Identifier *id = (Identifier *)idents->data[i]; - if (id->dyncast() != DYNCAST_IDENTIFIER) + if (id->dyncast() == DYNCAST_DSYMBOL) { TemplateInstance *ti = (TemplateInstance *)id; @@ -3457,7 +3620,7 @@ } tm = new TemplateMixin(loc, ident, - (TypeTypeof *)(tqual ? tqual->syntaxCopy() : NULL), + (Type *)(tqual ? tqual->syntaxCopy() : NULL), ids, tiargs); TemplateInstance::syntaxCopy(tm); return tm; @@ -3467,11 +3630,12 @@ { #if LOG printf("+TemplateMixin::semantic('%s', this=%p)\n", toChars(), this); + fflush(stdout); #endif if (semanticdone && // This for when a class/struct contains mixin members, and // is done over because of forward references - parent && !toParent()->isAggregateDeclaration()) + (!parent || !toParent()->isAggregateDeclaration())) { #if LOG printf("\tsemantic done\n"); @@ -3505,54 +3669,30 @@ { i = 1; id = (Identifier *)idents->data[0]; - if (id->dyncast() == DYNCAST_IDENTIFIER) - { - s = sc->search(loc, id, NULL); - } - else + switch (id->dyncast()) { - TemplateInstance *ti = (TemplateInstance *)id; - ti->semantic(sc); - s = ti; + case DYNCAST_IDENTIFIER: + s = sc->search(loc, id, NULL); + break; + + case DYNCAST_DSYMBOL: + { + TemplateInstance *ti = (TemplateInstance *)id; + ti->semantic(sc); + s = ti; + break; + } + default: + assert(0); } } 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(loc, 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(loc, 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; + s = s->searchX(loc, sc, id); } if (!s) { @@ -3563,7 +3703,7 @@ tempdecl = s->toAlias()->isTemplateDeclaration(); if (!tempdecl) { - error("%s is not a template", s->toChars()); + error("%s isn't a template", s->toChars()); inst = this; return; } @@ -3600,7 +3740,7 @@ // Run semantic on each argument, place results in tiargs[] semanticTiargs(sc); - tempdecl = findTemplateDeclaration(sc); + tempdecl = findBestMatch(sc); if (!tempdecl) { inst = this; return; // error recovery diff -uNr gdc-0.23/d/dmd/template.h gdc-0.24/d/dmd/template.h --- gdc-0.23/d/dmd/template.h 2007-02-08 18:58:10.000000000 +0100 +++ gdc-0.24/d/dmd/template.h 2007-07-27 02:07:14.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -94,6 +94,8 @@ Loc loc; Identifier *ident; + Declaration *sparam; + TemplateParameter(Loc loc, Identifier *ident); virtual TemplateTypeParameter *isTemplateTypeParameter(); @@ -102,6 +104,7 @@ virtual TemplateTupleParameter *isTemplateTupleParameter(); virtual TemplateParameter *syntaxCopy() = 0; + virtual void declareParameter(Scope *sc) = 0; virtual void semantic(Scope *) = 0; virtual void print(Object *oarg, Object *oded) = 0; virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; @@ -133,6 +136,7 @@ TemplateTypeParameter *isTemplateTypeParameter(); TemplateParameter *syntaxCopy(); + void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -159,6 +163,7 @@ TemplateValueParameter *isTemplateValueParameter(); TemplateParameter *syntaxCopy(); + void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -186,6 +191,7 @@ TemplateAliasParameter *isTemplateAliasParameter(); TemplateParameter *syntaxCopy(); + void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -206,6 +212,7 @@ TemplateTupleParameter *isTemplateTupleParameter(); TemplateParameter *syntaxCopy(); + void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -219,10 +226,12 @@ struct TemplateInstance : ScopeDsymbol { /* Given: - * template abc(T:T*, S, int V) - * instance foo.bar.abc(int*, char, 10*10) + * foo!(args) => + * name = foo + * tiargs = args */ - Array idents; // Array of Identifiers [foo, bar, abc] + Identifier *name; + //Array idents; Objects *tiargs; // Array of Types/Expressions of template // instance arguments [int*, char, 10*10] @@ -239,7 +248,7 @@ int semanticdone; // has semantic() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor - int isnested; // if referencing local symbols + Dsymbol *isnested; // if referencing local symbols, this is the context int errors; // 1 if compiled with errors #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol @@ -250,8 +259,8 @@ TemplateInstance(Loc loc, Identifier *temp_id); TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs); + static Objects *arraySyntaxCopy(Objects *objs); Dsymbol *syntaxCopy(Dsymbol *); - void addIdent(Identifier *ident); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); @@ -266,8 +275,10 @@ void toObjFile(); // compile to .obj file // Internal + static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs); void semanticTiargs(Scope *sc); TemplateDeclaration *findTemplateDeclaration(Scope *sc); + TemplateDeclaration *findBestMatch(Scope *sc); void declareParameters(Scope *sc); int isNested(Objects *tiargs); Identifier *genIdent(); @@ -279,11 +290,11 @@ struct TemplateMixin : TemplateInstance { Array *idents; - TypeTypeof *tqual; + Type *tqual; Scope *scope; // for forward referencing - TemplateMixin(Loc loc, Identifier *ident, TypeTypeof *tqual, Array *idents, Objects *tiargs); + TemplateMixin(Loc loc, Identifier *ident, Type *tqual, Array *idents, Objects *tiargs); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); @@ -304,5 +315,9 @@ Dsymbol *isDsymbol(Object *o); Type *isType(Object *o); Tuple *isTuple(Object *o); +Type *getType(Object *o); +Dsymbol *getDsymbol(Object *o); + +void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg); #endif /* DMD_TEMPLATE_H */ diff -uNr gdc-0.23/d/dmd/tocsym.c gdc-0.24/d/dmd/tocsym.c --- gdc-0.23/d/dmd/tocsym.c 2007-02-02 16:44:19.000000000 +0100 +++ gdc-0.24/d/dmd/tocsym.c 2007-07-27 02:07:14.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -25,6 +25,7 @@ #include "attrib.h" #include "lexer.h" #include "dsymbol.h" +#include "id.h" #include @@ -133,7 +134,7 @@ //printf("Dsymbol::toImport('%s')\n", sym->Sident); n = sym->Sident; id = (char *) alloca(6 + strlen(n) + 1 + sizeof(type_paramsize(sym->Stype))*3 + 1); - if (sym->Stype->Tmangle == mTYman_std) + if (sym->Stype->Tmangle == mTYman_std && tyfunc(sym->Stype->Tty)) { sprintf(id,"_imp__%s@%d",n,type_paramsize(sym->Stype)); } @@ -174,8 +175,17 @@ id = ident->toChars(); s = symbol_calloc(id); - if (storage_class & STCout) - t = type_fake(TYnptr); + if (storage_class & (STCout | STCref)) + { + if (global.params.symdebug && storage_class & STCparameter) + { + t = type_alloc(TYnptr); // should be TYref, but problems in back end + t->Tnext = type->toCtype(); + t->Tnext->Tcount++; + } + else + t = type_fake(TYnptr); + } else if (storage_class & STClazy) t = type_fake(TYullong); // Tdelegate as C type else if (isParameter()) @@ -277,6 +287,14 @@ /************************************* */ +Symbol *FuncAliasDeclaration::toSymbol() +{ + return funcalias->toSymbol(); +} + +/************************************* + */ + Symbol *FuncDeclaration::toSymbol() { if (!csym) @@ -289,7 +307,7 @@ #else id = mangle(); #endif - //printf("FuncDeclaration::toSymbol(%s)\n", toChars()); + //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars()); //printf("\tid = '%s'\n", id); //printf("\ttype = %s\n", type->toChars()); s = symbol_calloc(id); @@ -301,10 +319,15 @@ symbol_func(s); f = s->Sfunc; f->Fstartline.Slinnum = loc.linnum; + f->Fstartline.Sfilename = loc.filename; if (endloc.linnum) - f->Fendline.Slinnum = endloc.linnum; + { f->Fendline.Slinnum = endloc.linnum; + f->Fendline.Sfilename = endloc.filename; + } else - f->Fendline.Slinnum = loc.linnum; + { f->Fendline.Slinnum = loc.linnum; + f->Fendline.Sfilename = loc.filename; + } t = type->toCtype(); } @@ -569,6 +592,31 @@ return sinit; } +Symbol *EnumDeclaration::toInitializer() +{ + Symbol *s; + Classsym *stag; + + if (!sinit) + { + stag = fake_classsym(NULL); + Identifier *ident_save = ident; + if (!ident) + { static int num; + char name[6 + sizeof(num) * 3 + 1]; + sprintf(name, "__enum%d", ++num); + ident = Lexer::idPool(name); + } + s = toSymbolX("__init", SCextern, stag->Stype, "Z"); + ident = ident_save; + s->Sfl = FLextern; + s->Sflags |= SFLnodebug; + slist_add(s); + sinit = s; + } + return sinit; +} + /****************************************** */ diff -uNr gdc-0.23/d/dmd/todt.c gdc-0.24/d/dmd/todt.c --- gdc-0.23/d/dmd/todt.c 2007-02-17 17:27:15.000000000 +0100 +++ gdc-0.24/d/dmd/todt.c 2007-07-17 03:01:54.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -11,7 +11,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, July 2007 */ /* A dt_t is a simple structure representing data to be added @@ -57,6 +57,43 @@ /* ================================================================ */ +#ifdef IN_GCC +static dt_t *createTsarrayDt(dt_t * elem_or_all, Type *t) +{ + assert(elem_or_all != NULL); + target_size_t eoa_size = dt_size(elem_or_all); + if (eoa_size == t->size()) + { + return elem_or_all; + } + else + { + TypeSArray * tsa = (TypeSArray *) t->toBasetype(); + assert(tsa->ty == Tsarray); + + target_size_t dim = tsa->dim->toInteger(); + dt_t * adt = NULL; + + if (eoa_size * dim == eoa_size) + { + for (target_size_t i = 0; i < dim; i++) + dtcontainer(& adt, NULL, elem_or_all); + } + else + { + assert(tsa->size(0) % eoa_size == 0); + for (target_size_t i = 0; i < dim; i++) + dtcontainer(& adt, NULL, + createTsarrayDt(elem_or_all, tsa->next)); + } + dt_t * fdt = NULL; + dtcontainer(& fdt, t, adt); + return fdt; + } +} +#endif + + dt_t *Initializer::toDt() { assert(0); @@ -158,6 +195,18 @@ target_size_t voffset = v->offset; assert(sz <= vsz); +#ifdef IN_GCC + if (offset < voffset) + pdtend = dtnzeros(pdtend, voffset - offset); + if (v->type->toBasetype()->ty == Tsarray) + { + d = createTsarrayDt(d, v->type); + sz = dt_size(d); + assert(sz <= vsz); + } + pdtend = dtcat(pdtend, d); + offset = voffset + sz; +#else target_size_t dim = 1; for (Type *vt = v->type->toBasetype(); vt->ty == Tsarray; @@ -184,12 +233,18 @@ if (sz == vsz) break; } +#endif } } } if (offset < ad->structsize) dtnzeros(pdtend, ad->structsize - offset); +#ifdef IN_GCC + dt_t * cdt = NULL; + dtcontainer(& cdt, ad->type, dt); + dt = cdt; +#endif return dt; } @@ -232,24 +287,37 @@ dt = val->toDt(); if (dts.data[length]) error(loc, "duplicate initializations for index %d", length); + if (tn->ty == Tsarray) + dt = createTsarrayDt(dt, tb->next); dts.data[length] = (void *)dt; length++; } Expression *edefault = tb->next->defaultInit(); +#ifdef IN_GCC + dt_t * sadefault = NULL; + if (tn->ty == Tsarray) + tn->toDt(& sadefault); + else + edefault->toDt(& sadefault); +#else unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->next->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } +#endif d = NULL; pdtend = &d; for (i = 0; i < dim; i++) { dt = (dt_t *)dts.data[i]; +#ifdef IN_GCC + pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault); +#else if (dt) pdtend = dtcat(pdtend, dt); else @@ -257,6 +325,7 @@ for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } +#endif } switch (tb->ty) { @@ -269,13 +338,18 @@ { if (edefault->isBool(FALSE)) // pad out end of array + // (ok for GDC as well) pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (i = dim; i < tadim; i++) +#ifdef IN_GCC + pdtend = dtcontainer(pdtend, NULL, sadefault); +#else { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } +#endif } } else if (dim > tadim) @@ -285,6 +359,11 @@ #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } +#ifdef IN_GCC + dt_t * cdt = NULL; + dtcontainer(& cdt, type, d); + d = cdt; +#endif break; } @@ -300,6 +379,13 @@ if (tb->ty == Tarray) dtdword(&d, dim); dtxoff(&d, s, 0, TYnptr); +#ifdef IN_GCC + dt_t * cdt; + cdt = NULL; + if (tb->ty == Tarray) + dtcontainer(& cdt, type, d); + d = cdt; +#endif break; default: @@ -440,6 +526,7 @@ { #ifdef DEBUG printf("Expression::toDt() %d\n", op); + dump(0); #endif error("non-constant expression %s", toChars()); pdt = dtnzeros(pdt, 1); @@ -556,12 +643,16 @@ switch (t->ty) { case Tarray: - dtdword(pdt, len); + dt_t * adt; adt = NULL; + dtdword(& adt, len); #ifndef IN_GCC - pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); + dtabytes(& adt, TYnptr, 0, (len + 1) * sz, (char *)string); + pdt = dcat(pdt, adt); #else - pdt = dtawords(pdt, len + 1, string, sz); + dtawords(& adt, len + 1, string, sz); + pdt = dtcontainer(pdt, type, adt); #endif + break; case Tsarray: @@ -599,6 +690,190 @@ return pdt; } +dt_t **ArrayLiteralExp::toDt(dt_t **pdt) +{ + //printf("ArrayLiteralExp::toDt() '%s', type = %s\n", toChars(), type->toChars()); + + dt_t *d; + dt_t **pdtend; + + d = NULL; + pdtend = &d; + for (int i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + + pdtend = e->toDt(pdtend); + } +#ifdef IN_GCC + dt_t * cdt = NULL; + dtcontainer(& cdt, type, d); + d = cdt; +#endif + Type *t = type->toBasetype(); + + switch (t->ty) + { + case Tsarray: + pdt = dtcat(pdt, d); + break; + + case Tpointer: + case Tarray: + dt_t * adt; adt = NULL; + if (t->ty == Tarray) + dtdword(& adt, elements->dim); + if (d) + { + // Create symbol, and then refer to it + Symbol *s; + s = static_sym(); + s->Sdt = d; + outdata(s); + + dtxoff(& adt, s, 0, TYnptr); + } + else + dtdword(& adt, 0); +#ifdef IN_GCC + if (t->ty == Tarray) + dtcontainer(pdt, type, adt); + else +#endif + dtcat(pdt, adt); + + break; + + default: + assert(0); + } + return pdt; +} + +dt_t **StructLiteralExp::toDt(dt_t **pdt) +{ + Array dts; + unsigned i; + unsigned j; + dt_t *dt; + dt_t *d; + dt_t *sdt = NULL; + target_size_t offset; + + //printf("StructLiteralExp::toDt() %s)\n", toChars()); + dts.setDim(sd->fields.dim); + dts.zero(); + assert(elements->dim <= sd->fields.dim); + + for (i = 0; i < elements->dim; i++) + { + Expression *e = (Expression *)elements->data[i]; + if (!e) + continue; + dt = NULL; + e->toDt(&dt); + dts.data[i] = (void *)dt; + } + + offset = 0; + for (j = 0; j < dts.dim; j++) + { + VarDeclaration *v = (VarDeclaration *)sd->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 *)sd->fields.data[j]; + + if (v->init) + { + d = v->init->toDt(); + } + else if (v->offset >= offset) + { + target_size_t k; + target_size_t offset2 = v->offset + v->type->size(); + // Make sure this field (v) 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); + break; + } + VarDeclaration *v2 = (VarDeclaration *)sd->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 + { target_size_t sz = dt_size(d); + target_size_t vsz = v->type->size(); + target_size_t voffset = v->offset; + assert(sz <= vsz); + +#ifdef IN_GCC + if (offset < voffset) + dtnzeros(& sdt, voffset - offset); + if (v->type->toBasetype()->ty == Tsarray) + { + d = createTsarrayDt(d, v->type); + sz = dt_size(d); + assert(sz <= vsz); + } + dtcat(& sdt, d); + offset = voffset + sz; +#else + target_size_t dim = 1; + for (Type *vt = v->type->toBasetype(); + vt->ty == Tsarray; + vt = vt->next->toBasetype()) + { TypeSArray *tsa = (TypeSArray *)vt; + dim *= tsa->dim->toInteger(); + } + + for (target_size_t i = 0; i < dim; i++) + { + if (offset < voffset) + dtnzeros(& sdt, voffset - offset); + if (!d) + { + if (v->init) + d = v->init->toDt(); + else + v->type->toDt(&d); + } + dtcat(& sdt, d); + d = NULL; + offset = voffset + sz; + voffset += vsz / dim; + if (sz == vsz) + break; + } +#endif + } + } + } + if (offset < sd->structsize) + dtnzeros(& sdt, sd->structsize - offset); +#ifdef IN_GCC + dtcontainer(pdt, type, sdt); +#else + pdt = dtcat(pdt, sdt); +#endif + + return pdt; +} + + dt_t **SymOffExp::toDt(dt_t **pdt) { Symbol *s; @@ -697,7 +972,14 @@ ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) + { +#ifdef IN_GCC + dt = init->toDt(); + dt = createTsarrayDt(dt, v->type); +#else ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); +#endif + } else dt = init->toDt(); } @@ -763,6 +1045,7 @@ unsigned offset; unsigned i; dt_t *dt; + dt_t *sdt = NULL; //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); offset = 0; @@ -781,7 +1064,14 @@ ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) + { +#ifdef IN_GCC + dt = init->toDt(); + dt = createTsarrayDt(dt, v->type); +#else ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); +#endif + } else dt = init->toDt(); } @@ -794,15 +1084,20 @@ else { if (offset < v->offset) - dtnzeros(pdt, v->offset - offset); - dtcat(pdt, dt); + dtnzeros(& sdt, v->offset - offset); + dtcat(& sdt, dt); offset = v->offset + v->type->size(); } } } if (offset < structsize) - dtnzeros(pdt, structsize - offset); + dtnzeros(& sdt, structsize - offset); +#ifdef IN_GCC + dtcontainer(pdt, type, sdt); +#else + dtcat(pdt, sdt); +#endif dt_optimize(*pdt); } @@ -860,34 +1155,46 @@ } else { + dt_t *adt = NULL; + dt_t **padt = & adt; + /* problem...? if (tbn->ty == Tstruct) tnext->toDt(pdt); else e->toDt(pdt); - dt_optimize(*pdt); - if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) + */ + e->toDt(padt); + dt_optimize(*padt); + + // These first two cases are okay for GDC too + if ((*padt)->dt == DT_azeros && !(*padt)->DTnext) { - (*pdt)->DTazeros *= len; - pdt = &((*pdt)->DTnext); + (*padt)->DTazeros *= len; + pdt = dtcat(pdt, adt); } - else if ((*pdt)->dt == DT_1byte && (*pdt)->DTonebyte == 0 && !(*pdt)->DTnext) + else if ((*padt)->dt == DT_1byte && (*padt)->DTonebyte == 0 && !(*padt)->DTnext) { - (*pdt)->dt = DT_azeros; - (*pdt)->DTazeros = len; - pdt = &((*pdt)->DTnext); + (*padt)->dt = DT_azeros; + (*padt)->DTazeros = len; + pdt = dtcat(pdt, adt); } else if (e->op != TOKstring) { +#ifdef IN_GCC + pdt = dtcat(pdt, createTsarrayDt(adt, this)); +#else for (i = 1; i < len; i++) { if (tbn->ty == Tstruct) - { pdt = tnext->toDt(pdt); - while (*pdt) - pdt = &((*pdt)->DTnext); + { padt = tnext->toDt(padt); + while (*padt) + adt = &((*padt)->DTnext); } else - pdt = e->toDt(pdt); + padt = e->toDt(padt); } + pdt = dtcat(pdt, adt); +#endif } } } diff -uNr gdc-0.23/d/dmd/toir.c gdc-0.24/d/dmd/toir.c --- gdc-0.23/d/dmd/toir.c 2006-12-04 03:32:03.000000000 +0100 +++ gdc-0.24/d/dmd/toir.c 2007-07-27 02:07:14.000000000 +0200 @@ -1,9 +1,9 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -179,7 +179,11 @@ fd->isClassDeclaration() && fd->isClassDeclaration()->isBaseOf(cd, NULL)) break; - assert(cd->isNested() && cd->vthis); + if (!cd->isNested() || !cd->vthis) + { + irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars()); + return el_long(TYnptr, 0); // error recovery + } ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, cd->vthis->offset)); ethis = el_una(OPind, TYnptr, ethis); if (fdparent == s->toParent2()) diff -uNr gdc-0.23/d/dmd/toir.h gdc-0.24/d/dmd/toir.h --- gdc-0.23/d/dmd/toir.h 2006-12-04 03:32:03.000000000 +0100 +++ gdc-0.24/d/dmd/toir.h 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/toobj.c gdc-0.24/d/dmd/toobj.c --- gdc-0.23/d/dmd/toobj.c 2007-02-13 17:16:49.000000000 +0100 +++ gdc-0.24/d/dmd/toobj.c 2007-04-29 20:05:44.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2004 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -129,7 +129,7 @@ dtdword(&dt, 0); // monitor // name[] - char *name = ident->toChars(); + char *name = toPrettyChars(); size_t namelen = strlen(name); dtdword(&dt, namelen); dtabytes(&dt, TYnptr, 0, namelen + 1, name); @@ -175,14 +175,14 @@ // localClasses[] dtdword(&dt, aclasses.dim); if (aclasses.dim) - dtxoff(&dt, csym, sizeof_ModuleInfo + aimports.dim * PTRSIZE, TYnptr); + dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr); else dtdword(&dt, 0); if (needmoduleinfo) - dti32(&dt, 0); // flags (4 means MIstandalone) + dti32(&dt, 0, true); // flags (4 means MIstandalone) else - dti32(&dt, 4); // flags (4 means MIstandalone) + dti32(&dt, 4, true); // flags (4 means MIstandalone) if (sctor) dtxoff(&dt, sctor, 0, TYnptr); @@ -408,13 +408,15 @@ uint flags; void *deallocator; OffsetTypeInfo[] offTi; + void *defaultConstructor; } */ dt_t *dt = NULL; offset = CLASSINFO_SIZE; // must be ClassInfo.size if (classinfo) { - assert(classinfo->structsize == CLASSINFO_SIZE); + if (classinfo->structsize != CLASSINFO_SIZE) + error("D compiler and phobos/object.d are mismatched"); } if (classinfo) @@ -469,6 +471,8 @@ // flags int flags = 4 | com; + if (ctor) + flags |= 8; for (ClassDeclaration *cd = this; cd; cd = cd->baseClass) { if (cd->members) @@ -484,7 +488,7 @@ } flags |= 2; // no pointers L2: - dti32(&dt, flags); + dti32(&dt, flags, true); // deallocator @@ -497,6 +501,12 @@ dtdword(&dt, 0); dtdword(&dt, 0); // null for now, fix later + // defaultConstructor + if (defaultCtor) + dtxoff(&dt, defaultCtor->toSymbol(), 0, TYnptr); + else + dtdword(&dt, 0); + ////////////////////////////////////////////// // Put out vtblInterfaces->data[]. Must immediately follow csym, because @@ -831,6 +841,8 @@ void *invariant; // class invariant uint flags; void *deallocator; + OffsetTypeInfo[] offTi; + void *defaultConstructor; } */ dt_t *dt = NULL; @@ -878,7 +890,7 @@ dtdword(&dt, 0); // flags - dti32(&dt, 4 | com); + dti32(&dt, 4 | com, true); // deallocator dtdword(&dt, 0); @@ -887,6 +899,9 @@ dtdword(&dt, 0); dtdword(&dt, 0); // null for now, fix later + // defaultConstructor + dtdword(&dt, 0); + ////////////////////////////////////////////// // Put out vtblInterfaces->data[]. Must immediately follow csym, because @@ -1204,6 +1219,33 @@ toDebug(); type->getTypeInfo(NULL); // generate TypeInfo + + TypeEnum *tc = (TypeEnum *)type; + if (type->isZeroInit() || !tc->sym->defaultval) + ; + else + { + enum_SC scclass = SCglobal; + for (Dsymbol *parent = this->parent; parent; parent = parent->parent) + { + if (parent->isTemplateInstance()) + { + scclass = SCcomdat; + break; + } + } + + // Generate static initializer + toInitializer(); + sinit->Sclass = scclass; + sinit->Sfl = FLdata; +#if ELFOBJ // Burton + sinit->Sseg = CDATA; +#endif /* ELFOBJ */ + dtnbytes(&sinit->Sdt, tc->size(0), (char *)&tc->sym->defaultval); + //sinit->Sdt = tc->sym->init->toDt(); + outdata(sinit); + } } diff -uNr gdc-0.23/d/dmd/total.h gdc-0.24/d/dmd/total.h --- gdc-0.23/d/dmd/total.h 2006-11-11 21:52:33.000000000 +0100 +++ gdc-0.24/d/dmd/total.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/typinf.c gdc-0.24/d/dmd/typinf.c --- gdc-0.23/d/dmd/typinf.c 2007-03-04 15:19:14.000000000 +0100 +++ gdc-0.24/d/dmd/typinf.c 2007-04-29 20:05:44.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. @@ -276,6 +276,7 @@ /* Put out: * TypeInfo base; * char[] name; + * void[] m_init; */ sd->memtype->getTypeInfo(NULL); @@ -285,6 +286,18 @@ size_t namelen = strlen(name); dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); + + // void[] init; + if (tinfo->isZeroInit() || !sd->defaultval) + { // 0 initializer, or the same as the base type + dtdword(pdt, 0); // init.length + dtdword(pdt, 0); // init.ptr + } + else + { + dtdword(pdt, sd->type->size()); // init.length + dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr + } } void TypeInfoPointerDeclaration::toDt(dt_t **pdt) @@ -440,7 +453,7 @@ { Scope sc; Arguments *arguments = new Arguments; - Argument *arg = new Argument(In, tc->pointerTo(), NULL, NULL); + Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); arguments->push(arg); tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); @@ -506,7 +519,7 @@ dtdword(pdt, 0); // uint m_flags; - dti32(pdt, tc->hasPointers()); + dti32(pdt, tc->hasPointers(), false); // name[] dtnbytes(pdt, namelen + 1, name); @@ -658,7 +671,7 @@ Arguments *args = new Arguments; args->setDim(dim); for (size_t i = 0; i < dim; i++) - { Argument *arg = new Argument(In, exps[i]->type, NULL, NULL); + { Argument *arg = new Argument(STCin, exps[i]->type, NULL, NULL); args->data[i] = (void *)arg; } TypeTuple *tup = new TypeTuple(args); diff -uNr gdc-0.23/d/dmd/unialpha.c gdc-0.24/d/dmd/unialpha.c --- gdc-0.23/d/dmd/unialpha.c 2006-06-03 04:57:43.000000000 +0200 +++ gdc-0.24/d/dmd/unialpha.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 2003 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/utf.c gdc-0.24/d/dmd/utf.c --- gdc-0.23/d/dmd/utf.c 2006-11-18 16:06:05.000000000 +0100 +++ gdc-0.24/d/dmd/utf.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 2003 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/utf.h gdc-0.24/d/dmd/utf.h --- gdc-0.23/d/dmd/utf.h 2006-11-18 16:06:05.000000000 +0100 +++ gdc-0.24/d/dmd/utf.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 2003-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/version.c gdc-0.24/d/dmd/version.c --- gdc-0.23/d/dmd/version.c 2006-06-03 04:57:43.000000000 +0200 +++ gdc-0.24/d/dmd/version.c 2007-04-29 02:47:26.000000000 +0200 @@ -2,7 +2,7 @@ // Copyright (c) 1999-2005 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd/version.h gdc-0.24/d/dmd/version.h --- gdc-0.23/d/dmd/version.h 2006-11-11 21:52:48.000000000 +0100 +++ gdc-0.24/d/dmd/version.h 2007-04-29 02:47:26.000000000 +0200 @@ -3,7 +3,7 @@ // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright -// www.digitalmars.com +// http://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. diff -uNr gdc-0.23/d/dmd-script gdc-0.24/d/dmd-script --- gdc-0.23/d/dmd-script 2007-03-04 16:24:14.000000000 +0100 +++ gdc-0.24/d/dmd-script 2007-08-22 02:16:39.000000000 +0200 @@ -33,7 +33,11 @@ my $output_directory; my $output_parents; my $output_file; +my $header_directory; +my $header_parents; +my $header_file; my $link = 1; +my $header = 0; my $run = 0; my $verbose = 0; my $show_commands = 0; @@ -74,7 +78,7 @@ sub printUsage() { print <catfile( @hdrbits ); + eval { mkpath($dir) }; + if ($@) { + errorExit "could not create $dir: $@"; + } + $hdrd = File::Spec->catfile( @hdrbits ); + } + push @outbits, basename( $srcf, '.d' ) . '.o'; # $outf .= basename( $srcf, '.d' ) . '.o'; $outf = File::Spec->catfile( @outbits ); @@ -356,8 +379,15 @@ $srcf = "-fonly=$srcf"; } + my @interface; + if ( $header ) { + push @interface, '-fintfc'; + push @interface, "-fintfc-dir=$hdrd" if $hdrd; + push @interface, "-fintfc-file=$header_file" if $header_file; + } + # Step 2: Run the compiler driver - my @cmd = ($gdc, @out, '-c', @all_sources_hack, $srcf, '-o', $outf ); + my @cmd = ($gdc, @out, '-c', @all_sources_hack, $srcf, '-o', $outf, @interface); if ( $show_commands ) { print join(' ', @cmd), "\n"; } diff -uNr gdc-0.23/d/d-misc.c gdc-0.24/d/d-misc.c --- gdc-0.23/d/d-misc.c 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/d-misc.c 2007-03-10 15:58:53.000000000 +0100 @@ -18,13 +18,8 @@ #include "config.h" #include "system.h" -#if D_GCC_VER == 33 - /* nothing */ -#else - // gcc 3.4 #include "coretypes.h" #include "tm.h" -#endif #include "except.h" #include "tree.h" diff -uNr gdc-0.23/d/d-objfile.cc gdc-0.24/d/d-objfile.cc --- gdc-0.23/d/d-objfile.cc 2007-02-28 01:47:22.000000000 +0100 +++ gdc-0.24/d/d-objfile.cc 2007-07-17 03:01:54.000000000 +0200 @@ -34,12 +34,8 @@ ObjectFile::ObjectFile() { -#if D_GCC_VER >= 34 fileContext = build_decl(TRANSLATION_UNIT_DECL, NULL, NULL); dkeep(fileContext); -#else - fileContext = NULL_TREE; -#endif } void @@ -97,13 +93,9 @@ { if (loc.filename) { setLoc(loc); -#if D_GCC_VER >= 40 - /* nothing */ -#elif D_GCC_VER >= 34 +#if D_GCC_VER < 40 location_t gcc_loc = { loc.filename, loc.linnum }; emit_line_note (gcc_loc); -#else - emit_line_note ((const char *)loc.filename, loc.linnum); #endif } else { // do nothing @@ -114,13 +106,8 @@ ObjectFile::setLoc(const Loc & loc) { if (loc.filename) { -#if D_GCC_VER >= 34 location_t gcc_loc = { loc.filename, loc.linnum }; input_location = gcc_loc; -#else - input_filename = loc.filename; - lineno = loc.linnum; -#endif } else { // do nothing } @@ -553,7 +540,7 @@ /* Thunk code is based on g++ */ -#if (D_GCC_VER >= 34) && defined(ASM_OUTPUT_DEF) +#ifdef ASM_OUTPUT_DEF static int thunk_labelno; /* Create a static alias to function. */ @@ -598,14 +585,13 @@ } #endif - void ObjectFile::outputThunk(tree thunk_decl, tree target_decl, target_ptrdiff_t offset) { target_ptrdiff_t delta = -offset; tree alias; -#if (D_GCC_VER >= 34) && defined(ASM_OUTPUT_DEF) +#ifdef ASM_OUTPUT_DEF alias = make_alias_for_thunk(target_decl); #else alias = target_decl; @@ -613,7 +599,6 @@ TREE_ADDRESSABLE(target_decl) = 1; TREE_USED(target_decl) = 1; -#if D_GCC_VER >= 34 DECL_VISIBILITY (thunk_decl) = DECL_VISIBILITY (target_decl); #if ASM_OUTPUT_DEF \ && !defined (TARGET_IS_PE_COFF) @@ -630,7 +615,6 @@ } } #endif -#endif // cp/method.c: /* The back-end expects DECL_INITIAL to contain a BLOCK, so we create one. */ @@ -685,10 +669,9 @@ func->protection = public_fn ? PROTpublic : PROTprivate; tree func_decl = func->toSymbol()->Stree; - if (static_ctor) { + if (static_ctor) 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? - } + // D static ctors, dtors, unittests, and the ModuleInfo chain function // are always private (see ObjectFile::setupSymbolStorage, default case) TREE_PUBLIC( func_decl ) = public_fn; @@ -748,13 +731,13 @@ gen.hostToTargetString((char*) pwords, word_count, word_size)); } -/* Add a 32-bit value to a dt. Adds any necessary padding so that the - next value is aligned to PTRSIZE. */ +/* Add a 32-bit value to a dt. If pad_to_word is true, adds any + necessary padding so that the next value is aligned to PTRSIZE. */ dt_t** -dti32(dt_t** pdt, unsigned val) +dti32(dt_t** pdt, unsigned val, int pad_to_word) { dt_t** result = dttree(pdt, gen.integerConstant(val, Type::tuns32)); - if (PTRSIZE == 4) + if (! pad_to_word || PTRSIZE == 4) return result; else if (PTRSIZE == 8) return dttree(result, gen.integerConstant(0, Type::tuns32)); @@ -762,6 +745,18 @@ gcc_unreachable(); } +dt_t** +dtcontainer(dt_t** pdt, Type * type, dt_t* values) +{ + dt_t * d = new dt_t; + d->dt = DT_container; + d->DTnext = 0; + d->DTtype = type; + d->DTvalues = values; + return dtcat(pdt, d); +} + + target_size_t dt_size(dt_t * dt) @@ -791,6 +786,9 @@ size += gen.getTargetSizeConst(t_size); } break; + case DT_container: + size += dt_size(dt->DTvalues); + break; default: assert(0); } @@ -860,6 +858,40 @@ gen.integerConstant(dt->DTint, Type::tsize_t) ); case DT_tree: return dt->DTtree; + case DT_container: + { + /* It is necessary to give static array data its + original type. Otherwise, the SRA pass will + not find the array elements. + + SRA accesses struct elements by field offset, + so the ad hoc type from dt2tree is fine. */ + Type *tb = NULL; + if (dt->DTtype) + tb = dt->DTtype->toBasetype(); + if (tb && tb->ty == Tsarray) + { + TypeSArray * tsa = (TypeSArray *) tb; + CtorEltMaker ctor_elts; + dt_t * dte = dt->DTvalues; + target_size_t i = 0; + ctor_elts.reserve(tsa->dim->toInteger()); + while (dte) + { + ctor_elts.cons(gen.integerConstant(i++, size_type_node), + dt2node(dte)); + dte = dte->DTnext; + } + tree ctor = make_node(CONSTRUCTOR); + TREE_TYPE(ctor) = dt->DTtype->toCtype(); + TREE_READONLY(ctor) = 1; + TREE_STATIC(ctor) = 1; + CONSTRUCTOR_ELTS(ctor) = ctor_elts.head; + return ctor; + } + else + return dt2tree(dt->DTvalues); + } default: abort(); } @@ -869,44 +901,50 @@ static tree dt2tree(dt_t * dt) { - CtorEltMaker elts; - ListMaker fields; - tree offset = size_zero_node; - - tree aggtype = make_node(RECORD_TYPE); - - while (dt) { - tree value = dt2node(dt); - tree field = build_decl(FIELD_DECL, NULL_TREE, TREE_TYPE(value)); - DECL_CONTEXT(field) = aggtype; - DECL_FIELD_OFFSET(field) = offset; - DECL_FIELD_BIT_OFFSET(field) = bitsize_zero_node; - DECL_ARTIFICIAL(field) = 1; - DECL_IGNORED_P(field) = 1; - layout_decl(field, 0); - - fields.chain(field); - elts.cons(field, value); - offset = size_binop(PLUS_EXPR, offset, TYPE_SIZE_UNIT( TREE_TYPE( value ))); + if (dt && /*dt->dt == DT_container || */dt->DTnext == NULL) + return dt2node(dt); + else + { + // Generate type on the fly + CtorEltMaker elts; + ListMaker fields; + tree offset = size_zero_node; + + tree aggtype = make_node(RECORD_TYPE); + + while (dt) { + tree value = dt2node(dt); + tree field = build_decl(FIELD_DECL, NULL_TREE, TREE_TYPE(value)); + DECL_CONTEXT(field) = aggtype; + DECL_FIELD_OFFSET(field) = offset; + DECL_FIELD_BIT_OFFSET(field) = bitsize_zero_node; + DECL_ARTIFICIAL(field) = 1; + DECL_IGNORED_P(field) = 1; + layout_decl(field, 0); + + fields.chain(field); + elts.cons(field, value); + offset = size_binop(PLUS_EXPR, offset, TYPE_SIZE_UNIT( TREE_TYPE( value ))); - dt = dt->DTnext; - } + dt = dt->DTnext; + } - TYPE_FIELDS(aggtype) = fields.head; // or finish_laout - TYPE_SIZE(aggtype) = convert( bitsizetype, - size_binop( MULT_EXPR, offset, size_int( BITS_PER_UNIT ))); - TYPE_SIZE_UNIT(aggtype) = offset; - // okay no alignment -- decl (which has the correct type) should take care of it.. - // align=bits per word? - compute_record_mode(aggtype); - - tree ctor = make_node(CONSTRUCTOR); - TREE_TYPE(ctor) = aggtype; - TREE_READONLY(ctor) = 1; - // dt created data is always static - TREE_STATIC(ctor) = 1; - CONSTRUCTOR_ELTS(ctor) = elts.head; - return ctor; + TYPE_FIELDS(aggtype) = fields.head; // or finish_laout + TYPE_SIZE(aggtype) = convert( bitsizetype, + size_binop( MULT_EXPR, offset, size_int( BITS_PER_UNIT ))); + TYPE_SIZE_UNIT(aggtype) = offset; + // okay no alignment -- decl (which has the correct type) should take care of it.. + // align=bits per word? + compute_record_mode(aggtype); + + tree ctor = make_node(CONSTRUCTOR); + TREE_TYPE(ctor) = aggtype; + TREE_READONLY(ctor) = 1; + // dt created data is always static + TREE_STATIC(ctor) = 1; + CONSTRUCTOR_ELTS(ctor) = elts.head; + return ctor; + } } void diff -uNr gdc-0.23/d/d-spec.c gdc-0.24/d/d-spec.c --- gdc-0.23/d/d-spec.c 2007-03-01 16:00:53.000000000 +0100 +++ gdc-0.24/d/d-spec.c 2007-03-10 15:58:53.000000000 +0100 @@ -23,11 +23,8 @@ #include "config.h" #include "system.h" - -#if D_GCC_VER >= 34 #include "coretypes.h" #include "tm.h" -#endif #include "gcc.h" diff -uNr gdc-0.23/d/dt.h gdc-0.24/d/dt.h --- gdc-0.23/d/dt.h 2007-02-13 15:34:38.000000000 +0100 +++ gdc-0.24/d/dt.h 2007-07-17 03:01:54.000000000 +0200 @@ -30,9 +30,12 @@ DT_word, DT_xoff, DT_1byte, - DT_tree + DT_tree, + DT_container }; +struct Type; + struct dt_t { enum DT dt; struct dt_t * DTnext; @@ -40,11 +43,13 @@ integer_t DTint; integer_t DTazeros; integer_t DTonebyte; + struct dt_t * DTvalues; }; union { Symbol * DTsym; tree DTtree; void * DTpointer; + Type * DTtype; }; }; @@ -86,6 +91,9 @@ extern dt_t** dtnbits(dt_t** pdt, size_t count, char * pbytes, unsigned unit_size); extern dt_t** dtnwords(dt_t** pdt, size_t word_count, void * pwords, unsigned word_size); extern dt_t** dtawords(dt_t** pdt, size_t word_count, void * pwords, unsigned word_size); -extern dt_t** dti32(dt_t** pdt, unsigned val); +extern dt_t** dti32(dt_t** pdt, unsigned val, int pad_to_word); + +// Added for GCC to match types for SRA pass +extern dt_t** dtcontainer(dt_t** pdt, Type * type, dt_t* values); #endif diff -uNr gdc-0.23/d/gcc-3.3.5-framework-headers.patch gdc-0.24/d/gcc-3.3.5-framework-headers.patch --- gdc-0.23/d/gcc-3.3.5-framework-headers.patch 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/gcc-3.3.5-framework-headers.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,662 +0,0 @@ -diff -uNr gcc-3.3.5.orig/gcc/config/darwin.h gcc-3.3.5/gcc/config/darwin.h ---- gcc-3.3.5.orig/gcc/config/darwin.h Tue Apr 6 20:48:47 2004 -+++ gcc-3.3.5/gcc/config/darwin.h Thu Nov 11 12:20:34 2004 -@@ -84,6 +84,10 @@ - #undef DEFAULT_PCC_STRUCT_RETURN - #define DEFAULT_PCC_STRUCT_RETURN 0 - -+/* APPLE LOCAL framework headers */ -+/* Need to look for framework headers. */ -+#define FRAMEWORK_HEADERS -+ - /* This table intercepts weirdo options whose names would interfere - with normal driver conventions, and either translates them into - standardly-named options, or adds a 'Z' so that they can get to -diff -uNr gcc-3.3.5.orig/gcc/cppfiles.c gcc-3.3.5/gcc/cppfiles.c ---- gcc-3.3.5.orig/gcc/cppfiles.c Wed Nov 20 20:49:53 2002 -+++ gcc-3.3.5/gcc/cppfiles.c Thu Nov 11 12:20:34 2004 -@@ -124,6 +124,24 @@ - struct search_path *)); - static struct search_path *search_from PARAMS ((cpp_reader *, - enum include_type)); -+ -+/* APPLE LOCAL framework headers */ -+#ifdef FRAMEWORK_HEADERS -+struct framework_header {const char * dirName; int dirNameLen; }; -+static struct framework_header framework_header_dirs[] = { -+ { "PrivateHeaders", 14 }, -+ { "Headers", 7 }, -+ { NULL, 0 } -+}; -+ -+static struct include_file * -+find_subframework_file PARAMS ((cpp_reader *, const cpp_token *, -+ struct search_path *)); -+static struct include_file * -+ find_framework_file PARAMS ((cpp_reader *, const cpp_token *, -+ enum include_type)); -+#endif /* FRAMEWORK_HEADERS */ -+ - static struct include_file * - find_include_file PARAMS ((cpp_reader *, const cpp_token *, - enum include_type)); -@@ -585,7 +603,15 @@ - if (type == IT_INCLUDE_NEXT && pfile->buffer->inc->foundhere) - path = pfile->buffer->inc->foundhere->next; - else if (header->type == CPP_HEADER_NAME) -- path = CPP_OPTION (pfile, bracket_include); -+ { -+ path = CPP_OPTION (pfile, bracket_include); -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ if (path == NULL) -+ path = CPP_OPTION (pfile, framework_include); -+#endif -+/* APPLE LOCAL end framework headers */ -+ } - else - path = search_from (pfile, type); - -@@ -624,6 +650,212 @@ - return 0; - } - -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+/* Search for HEADER frameworks. Return 0 if there is no such file -+ (or it's un-openable), in which case an error code will be in -+ errno. Translates the header file name suitable for frameworks from -+ "Foundation/Foundation.h" into -+ "Foundation.frameworks/PrivateHeaders/Foundation.h". */ -+ -+static struct include_file * -+find_framework_file (pfile, header, type) -+ cpp_reader *pfile; -+ const cpp_token *header; -+ enum include_type type ATTRIBUTE_UNUSED; -+{ -+ struct include_file *inc = NULL; -+ const char *fname = (const char *) header->val.str.text; -+ struct search_path *path; -+ struct include_file *file; -+ char *n, *frname; -+ unsigned char *bufptr; -+ unsigned position; -+ int frname_len, slash_position, index; -+ -+ if (fname == NULL) -+ return 0; -+ -+ /* For #include_next, skip in the search path past the dir in which -+ the current file was found, but if it was found via an absolute -+ path use the normal search logic. */ -+ -+ path = NULL; -+ path = CPP_OPTION (pfile, framework_include); -+ -+ if (path == NULL) -+ { -+ cpp_error (pfile, DL_ERROR, "No include path in which to find %s", fname); -+ return NO_INCLUDE_PATH; -+ } -+ -+ /* Framework header filename includes framework name and header name in the -+ "Foundation/Foundation.h" form. If it does not include slash it is not a -+ framework include. */ -+ bufptr = NULL; -+ slash_position = -1; -+ position = 0; -+ for (bufptr = (unsigned char *) fname; bufptr != NULL; bufptr++) -+ { -+ if (position > strlen(fname)) -+ break; -+ if (*bufptr == '/') -+ { -+ slash_position = position; -+ break; -+ } -+ position++; -+ } -+ if (slash_position == -1) -+ return 0; -+ -+ /* 25 = strlen(".framework/") + strlen("PrivateHeaders") */ -+ frname = (char *) alloca (strlen (fname) + pfile->max_include_len + 2 + 25); -+ -+ for (; path; path = path->next) -+ { -+ strncpy (&frname[0], path->name, path->len); -+ frname[path->len] = '/'; -+ frname_len = path->len + 1; -+ strncpy (&frname[frname_len], fname, slash_position); -+ frname_len += slash_position; -+ strncpy (&frname[frname_len], ".framework/", 11); -+ frname_len += 11; -+ -+ /* Append framework_header_dirs and header file name */ -+ for (index = 0; framework_header_dirs[index].dirName; index++) -+ { -+ strncpy (&frname[frname_len], -+ framework_header_dirs[index].dirName, -+ framework_header_dirs[index].dirNameLen); -+ strcpy (&frname[frname_len + framework_header_dirs[index].dirNameLen], -+ &fname[slash_position]); -+ -+ if (CPP_OPTION (pfile, remap)) -+ n = remap_filename (pfile, frname, path); -+ else -+ n = frname; -+ -+ -+ file = open_file (pfile, n); -+ if (file) -+ { -+ file->foundhere = path; -+ return file; -+ } -+ } -+ } -+ -+ path = CPP_OPTION (pfile, framework_include); -+ -+ /* Find in subframework */ -+ for (; path; path = path->next) -+ { -+ inc = find_subframework_file (pfile, header, path); -+ if (inc) -+ return inc; -+ } -+ -+ return 0; -+} -+ -+/* Search for HEADER in sub frameworks. Return 0 if there is no such -+ file (or it's un-openable), in which case an error code will be in -+ errno. */ -+ -+static struct include_file * -+find_subframework_file (pfile, header, path) -+ cpp_reader *pfile; -+ const cpp_token *header; -+ struct search_path *path; -+{ -+ const char *fname = (const char *) header->val.str.text; -+ const char *pname; /* Parent header name */ -+ struct include_file *file; -+ char *n, *sfrname; -+ const char *dot_framework = ".framework/"; -+ char *bufptr; -+ int sfrname_len, position, index; -+ struct cpp_buffer *b; -+ -+ for (b = pfile->buffer; b && b->inc && b->inc->name; b = b->prev) -+ { -+ pname = b->inc->name; -+ /* Sub framework header filename includes parent framework name and -+ header name in the "CarbonCore/OSUtils.h" form. If it does not -+ include slash it is not a sub framework include. */ -+ bufptr = NULL; -+ position = 0; -+ for (bufptr = (char *) fname; bufptr != NULL; bufptr++) -+ { -+ if (*bufptr == '/') -+ break; -+ position++; -+ } -+ if (position == 0) -+ return 0; -+ -+ bufptr = NULL; -+ bufptr = strstr (pname, dot_framework); -+ -+ /* If the parent header is not of any framework, then this header -+ can not be part of any subframework. */ -+ if (!bufptr) -+ return 0; -+ -+ /* Now translate. For example, +- bufptr -+ fname = CarbonCore/OSUtils.h | -+ pname = /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h into -+ sfrname = /System/Library/Frameworks/Foundation.framework/Frameworks/CarbonCore.framework/Headers/OSUtils.h -+ */ -+ -+ /* 36 = strlen ("Frameworks/") + strlen (".framework/") + strlen ("PrivateHeaders") */ -+ sfrname = (char *) alloca (strlen (pname) + strlen (fname) + 2 + 36); -+ -+ /* Advance bufptr */ -+ bufptr += strlen (dot_framework); -+ -+ sfrname_len = bufptr - pname; -+ -+ strncpy (&sfrname[0], pname, sfrname_len); -+ -+ strncpy (&sfrname[sfrname_len], "Frameworks/", 11); -+ sfrname_len += 11; -+ -+ strncpy (&sfrname[sfrname_len], fname, position); -+ sfrname_len += position; -+ -+ strncpy (&sfrname[sfrname_len], ".framework/", 11); -+ sfrname_len += 11; -+ -+ /* Append framework_header_dirs and header file name */ -+ for (index = 0; framework_header_dirs[index].dirName; index++) -+ { -+ strncpy (&sfrname[sfrname_len], -+ framework_header_dirs[index].dirName, -+ framework_header_dirs[index].dirNameLen); -+ strcpy (&sfrname[sfrname_len + framework_header_dirs[index].dirNameLen], -+ &fname[position]); -+ -+ if (CPP_OPTION (pfile, remap)) -+ n = remap_filename (pfile, sfrname, path); -+ else -+ n = sfrname; -+ -+ -+ file = open_file (pfile, n); -+ if (file) -+ { -+ file->foundhere = path; -+ return file; -+ } -+ } -+ } -+ return 0; -+} -+#endif /* FRAMEWORK_HEADERS */ -+/* APPLE LOCAL end framework headers */ -+ - /* Not everyone who wants to set system-header-ness on a buffer can - see the details of a buffer. This is an exported interface because - fix-header needs it. */ -@@ -709,6 +949,14 @@ - { - bool stacked = false; - struct include_file *inc = find_include_file (pfile, header, type); -+ -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ /* Search framework */ -+ if (inc == 0) -+ inc = find_framework_file (pfile, header, type); -+#endif -+ /* APPLE LOCAL end framework headers */ - - if (inc == 0) - handle_missing_header (pfile, (const char *) header->val.str.text, -diff -uNr gcc-3.3.5.orig/gcc/cppinit.c gcc-3.3.5/gcc/cppinit.c ---- gcc-3.3.5.orig/gcc/cppinit.c Tue Mar 2 21:09:15 2004 -+++ gcc-3.3.5/gcc/cppinit.c Thu Nov 11 12:20:34 2004 -@@ -28,6 +28,18 @@ - #include "mkdeps.h" - #include "cppdefault.h" - -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+struct { const char *path; int u1; } -+framework_paths_defaults_array [] = { -+ {"/System/Library/Frameworks", 0}, -+ {"/Library/Frameworks", 0}, -+ {"/Local/Library/Frameworks", 0}, -+ {NULL, 0} -+}; -+#endif /* FRAMEWORK_HEADERS */ -+/* APPLE LOCAL end framework headers */ -+ - /* Windows does not natively support inodes, and neither does MSDOS. - Cygwin's emulation can generate non-unique inodes, so don't use it. - VMS has non-numeric inodes. */ -@@ -67,6 +79,12 @@ - struct search_path *brack_head, *brack_tail; - struct search_path *systm_head, *systm_tail; - struct search_path *after_head, *after_tail; -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ struct search_path *framework_system_head, *framework_system_tail; -+ struct search_path *framework_head, *framework_tail; -+#endif -+ /* APPLE LOCAL end framework headers */ - - struct pending_option *imacros_head, *imacros_tail; - struct pending_option *include_head, *include_tail; -@@ -106,6 +124,11 @@ - struct pending_option *)); - static void free_chain PARAMS ((struct pending_option *)); - static void init_standard_includes PARAMS ((cpp_reader *)); -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+static void init_standard_frameworks PARAMS ((cpp_reader *)); -+#endif -+/* APPLE LOCAL end framework headers */ - static void read_original_filename PARAMS ((cpp_reader *)); - static void new_pending_directive PARAMS ((struct cpp_pending *, - const char *, -@@ -115,7 +138,8 @@ - - /* Fourth argument to append_include_chain: chain to use. - Note it's never asked to append to the quote chain. */ --enum { BRACKET = 0, SYSTEM, AFTER }; -+/* APPLE LOCAL framework headers */ -+enum { BRACKET = 0, SYSTEM, AFTER, FRAMEWORK, FRAMEWORK_SYSTEM }; - - /* If we have designated initializers (GCC >2.7) these tables can be - initialized, constant data. Otherwise, they have to be filled in at -@@ -245,7 +269,13 @@ - /* Both systm and after include file lists should be treated as system - include files since these two lists are really just a concatenation - of one "system" list. */ -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ if (path == SYSTEM || path == AFTER || path == FRAMEWORK_SYSTEM) -+#else - if (path == SYSTEM || path == AFTER) -+#endif -+/* APPLE LOCAL end framework headers */ - new->sysp = cxx_aware ? 1 : 2; - else - new->sysp = 0; -@@ -257,6 +287,12 @@ - case BRACKET: APPEND (pend, brack, new); break; - case SYSTEM: APPEND (pend, systm, new); break; - case AFTER: APPEND (pend, after, new); break; -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ case FRAMEWORK_SYSTEM: APPEND (pend, framework_system, new); break; -+ case FRAMEWORK: APPEND (pend, framework, new); break; -+#endif -+ /* APPLE LOCAL end framework headers */ - } - } - -@@ -366,6 +402,8 @@ - INO_T_EQ()). The system_include and after_include chains are never - referred to again after this function; all access is through the - bracket_include path. */ -+/* APPLE LOCAL framework headers -+ Merge System Framework and User Framework into framework_include chain. */ - static void - merge_include_chains (pfile) - cpp_reader *pfile; -@@ -423,6 +461,16 @@ - - CPP_OPTION (pfile, quote_include) = quote; - CPP_OPTION (pfile, bracket_include) = brack; -+ -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ if (pend->framework_head) -+ pend->framework_tail->next = pend->framework_system_head; -+ else -+ pend->framework_head = pend->framework_system_head; -+ CPP_OPTION (pfile, framework_include) = pend->framework_head; -+#endif -+ /* APPLE LOCAL end framework headers */ - } - - /* A set of booleans indicating what CPP features each source language -@@ -861,8 +909,45 @@ - append_include_chain (pfile, str, SYSTEM, p->cxx_aware); - } - } -+ -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ init_standard_frameworks (pfile); -+#endif -+/* APPLE LOCAL end framework headers */ - } - -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+static void -+init_standard_frameworks (pfile) -+ cpp_reader *pfile; -+{ -+ /* Setup default search path for frameworks. */ -+ int i = 0; -+ const char *path; -+ char *next_root = getenv ("NEXT_ROOT"); -+ if (next_root && *next_root && next_root[strlen (next_root) - 1] == '/') -+ next_root[strlen (next_root) - 1] = '\0'; -+ while ((path = framework_paths_defaults_array[i++].path)) -+ { -+ char *new_fname = NULL; -+ if (next_root && *next_root) -+ new_fname = (char *) xmalloc (strlen (next_root) + strlen (path) + 1); -+ if (new_fname) -+ sprintf (new_fname, "%s%s", next_root, path); -+ else -+ { -+ new_fname = (char *) xmalloc (strlen (path) + 1); -+ strcpy (new_fname, path); -+ } -+ /* System Framework headers are cxx aware. */ -+ append_include_chain (pfile, new_fname, FRAMEWORK_SYSTEM, 1); -+ } -+} -+#endif -+/* APPLE LOCAL end framework headers */ -+ - /* Pushes a command line -imacro and -include file indicated by P onto - the buffer stack. Returns nonzero if successful. */ - static bool -@@ -1001,6 +1087,16 @@ - fprintf (stderr, " %s\n", l->name); - } - fprintf (stderr, _("End of search list.\n")); -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ fprintf (stderr, _("Framework search starts here:\n")); -+ for (l = CPP_OPTION (pfile, framework_include); l; l = l->next) -+ { -+ fprintf (stderr, " %s\n", l->name); -+ } -+ fprintf (stderr, _("End of framework search list.\n")); -+#endif /* FRAMEWORK_HEADERS */ -+ /* APPLE LOCAL end framework headers */ - } - - if (CPP_OPTION (pfile, deps.style) != DEPS_NONE) -@@ -1196,9 +1292,13 @@ - #define COMMAND_LINE_OPTIONS \ - DEF_OPT("A", no_ass, OPT_A) \ - DEF_OPT("D", no_mac, OPT_D) \ -+ /* APPLE LOCAL framework headers */ \ -+ DEF_OPT("F", no_dir, OPT_F) \ - DEF_OPT("I", no_dir, OPT_I) \ - DEF_OPT("U", no_mac, OPT_U) \ - DEF_OPT("idirafter", no_dir, OPT_idirafter) \ -+ /* APPLE LOCAL framework headers */ \ -+ DEF_OPT("iframework", no_dir, OPT_iframework) \ - DEF_OPT("imacros", no_fil, OPT_imacros) \ - DEF_OPT("include", no_fil, OPT_include) \ - DEF_OPT("iprefix", no_pth, OPT_iprefix) \ -@@ -1391,6 +1491,16 @@ - include directory. */ - append_include_chain (pfile, xstrdup (arg), SYSTEM, 0); - break; -+ /* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ case OPT_F: -+ case OPT_iframework: -+ /* Add directory to beginning of system include path, as a system -+ include directory. */ -+ append_include_chain (pfile, xstrdup (arg), FRAMEWORK, 0); -+ break; -+#endif -+ /* APPLE LOCAL end framework headers */ - case OPT_include: - case OPT_imacros: - { -diff -uNr gcc-3.3.5.orig/gcc/cpplib.h gcc-3.3.5/gcc/cpplib.h ---- gcc-3.3.5.orig/gcc/cpplib.h Fri Nov 7 00:13:31 2003 -+++ gcc-3.3.5/gcc/cpplib.h Thu Nov 11 12:20:34 2004 -@@ -230,6 +230,10 @@ - /* Search paths for include files. */ - struct search_path *quote_include; /* "" */ - struct search_path *bracket_include; /* <> */ -+ /* APPLE LOCAL framework headers */ -+#ifdef FRAMEWORK_HEADERS -+ struct search_path *framework_include; -+#endif - - /* Map between header names and file names, used only on DOS where - file names are limited in length. */ -diff -uNr gcc-3.3.5.orig/gcc/doc/invoke.texi gcc-3.3.5/gcc/doc/invoke.texi ---- gcc-3.3.5.orig/gcc/doc/invoke.texi Fri Aug 27 00:42:53 2004 -+++ gcc-3.3.5/gcc/doc/invoke.texi Thu Nov 11 12:20:36 2004 -@@ -311,7 +311,11 @@ - - @item Directory Options - @xref{Directory Options,,Options for Directory Search}. --@gccoptlist{-B@var{prefix} -I@var{dir} -I- -L@var{dir} -specs=@var{file}} -+@gccoptlist{ -+-B@var{prefix} -I@var{dir} -I- @gol -+@c APPLE LOCAL framework headers -+-F@var{dir} (APPLE ONLY) @gol -+-L@var{dir} -specs=@var{file}} - - @item Target Options - @c I wrote this xref this way to avoid overfull hbox. -- rms -@@ -4768,6 +4772,23 @@ - @opindex L - Add directory @var{dir} to the list of directories to be searched - for @option{-l}. -+ -+@c APPLE LOCAL begin framework headers -+@item -F@var{dir} -+@opindex F -+In Apple's version of GCC only, add the directory @var{dir} to the head -+of the list of directories to be searched for frameworks. -+ -+The framework search algorithm is, for an inclusion of -+@samp{}, to look for files named -+@file{@var{path}/Fmwk.framework/Headers/Header.h} or -+@file{@var{path}/Fmwk.framework/PrivateHeaders/Header.h} where -+@var{path} includes @file{/System/Library/Frameworks/} -+@file{/Library/Frameworks/}, and @file{/Local/Library/Frameworks/}, plus -+any additional paths specified by @option{-F}. -+ -+All the @option{-F} options are also passed to the linker. -+@c APPLE LOCAL end framework headers - - @item -B@var{prefix} - @opindex B -diff -uNr gcc-3.3.5.orig/gcc/gcc.c gcc-3.3.5/gcc/gcc.c ---- gcc-3.3.5.orig/gcc/gcc.c Thu Apr 1 18:55:17 2004 -+++ gcc-3.3.5/gcc/gcc.c Thu Nov 11 12:20:36 2004 -@@ -288,6 +288,12 @@ - static char *build_search_list PARAMS ((struct path_prefix *, const char *, int)); - static void putenv_from_prefixes PARAMS ((struct path_prefix *, const char *)); - static int access_check PARAMS ((const char *, int)); -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+static void safe_add_prefix PARAMS ((struct path_prefix *, char *, -+ int, int, int *)); -+#endif -+/* APPLE LOCAL end framework headers */ - static char *find_a_file PARAMS ((struct path_prefix *, const char *, - int, int)); - static void add_prefix PARAMS ((struct path_prefix *, const char *, -@@ -432,6 +438,8 @@ - %I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot - (made from TARGET_SYSTEM_ROOT), and -isystem (made from COMPILER_PATH - and -B options) as necessary. -+ APPLE LOCAL framework headers -+ %Q Substitute -iframework default paths. - %s current argument is the name of a library or startup file of some sort. - Search for that file in a standard list of directories - and substitute the full name found. -@@ -704,6 +712,8 @@ - file that happens to exist is up-to-date. */ - static const char *cpp_unique_options = - "%{C:%{!E:%eGNU C does not support -C without using -E}}\ -+"/* APPLE LOCAL framework headers */"\ -+ %{!traditional:%{!ftraditional:%{!traditional-cpp:%Q}}} %{F*}\ - %{CC:%{!E:%eGNU C does not support -CC without using -E}}\ - %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*} %{P} %I\ - %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\ -@@ -1293,6 +1303,13 @@ - - static struct path_prefix include_prefixes = { 0, 0, "include" }; - -+/* APPLE LOCAL begin framework headers */ -+#ifdef FRAMEWORK_HEADERS -+/* A vector of the frameworks to search. */ -+static struct path_prefix default_framework_paths = {0, 0, "default_frameworks"}; -+#endif /* FRAMEWORK_HEADERS */ -+/* APPLE LOCAL end framework headers */ -+ - /* Suffix to attach to directories searched for commands. - This looks like `MACHINE/VERSION/'. */ - -@@ -2557,6 +2574,30 @@ - add_prefix (pprefix, prefix, component, priority, - require_machine_suffix, warn, os_multilib); - } -+ -+/* APPLE LOCAL framework headers */ -+#ifdef FRAMEWORK_HEADERS -+static void -+safe_add_prefix (pprefix, prefix, first, require_machine_suffix, warn) -+ struct path_prefix *pprefix; -+ char *prefix; -+ int first; -+ int require_machine_suffix; -+ int *warn; -+{ -+ int len = strlen (prefix); -+ char *temp = prefix; -+ if (prefix[len - 1] != '/') -+ { -+ temp = xmalloc (len+2); -+ strcpy (temp, prefix); -+ temp[len] = '/'; -+ temp[len+1] = 0; -+ } -+ add_prefix (pprefix, temp, "GCC", first, require_machine_suffix, warn, 0); -+} -+#endif /* FRAMEWORK_HEADERS */ -+ - - /* Execute the command specified by the arguments on the current line of spec. - When using pipes, this includes several piped-together commands -@@ -4657,6 +4698,25 @@ - } - } - break; -+ -+ /* APPLE LOCAL begin framework headers */ -+ case 'Q': -+#ifdef FRAMEWORK_HEADERS -+ { -+ struct prefix_list *dfpl = default_framework_paths.plist; -+ -+ for (; dfpl; dfpl = dfpl->next) -+ { -+ char *tmpstr = xmalloc (strlen (dfpl->prefix) + 5); -+ sprintf (tmpstr, "-F%s", dfpl->prefix); -+ do_spec_1 (tmpstr, 1, NULL); -+ do_spec_1 (" ", 0, NULL); /* fh */ -+ free (tmpstr); -+ } -+ } -+#endif /* FRAMEWORK_HEADERS */ -+ break; -+ /* APPLE LOCAL end framework headers */ - - case 'o': - { -diff -uNr gcc-3.3.5.orig/gcc/gcc.h gcc-3.3.5/gcc/gcc.h ---- gcc-3.3.5.orig/gcc/gcc.h Tue Mar 11 01:59:24 2003 -+++ gcc-3.3.5/gcc/gcc.h Thu Nov 11 12:20:36 2004 -@@ -37,6 +37,8 @@ - ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ - || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ - || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ -+ /* APPLE LOCAL framework headers */ \ -+ || (CHAR) == 'F' \ - || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \ - || (CHAR) == 'B' || (CHAR) == 'b') - diff -uNr gdc-0.23/d/gcc-3.3.5-framework-linker.patch gdc-0.24/d/gcc-3.3.5-framework-linker.patch --- gdc-0.23/d/gcc-3.3.5-framework-linker.patch 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/gcc-3.3.5-framework-linker.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,53 +0,0 @@ ---- gcc-3.3.5/gcc/gcc.c.linker Thu Nov 11 13:52:13 2004 -+++ gcc-3.3.5/gcc/gcc.c Thu Nov 11 15:43:33 2004 -@@ -3526,6 +3526,16 @@ - verbose_only_flag++; - verbose_flag++; - } -+ /* APPLE LOCAL begin framework */ -+ else if (strcmp (argv[i], "-framework") == 0) -+ { -+ if (i + 1 == argc) -+ fatal ("argument to `-framework' is missing"); -+ -+ n_infiles += 2; -+ i++; -+ } -+ /* APPLE LOCAL end framework */ - else if (argv[i][0] == '-' && argv[i][1] != 0) - { - const char *p = &argv[i][1]; -@@ -3916,6 +3926,15 @@ - } - else if (strcmp (argv[i], "-###") == 0) - ; -+ /* APPLE LOCAL begin framework */ -+ else if (strcmp (argv[i], "-framework") == 0) -+ { -+ infiles[n_infiles].language = "*"; -+ infiles[n_infiles++].name = argv[i]; -+ infiles[n_infiles].language = "*"; -+ infiles[n_infiles++].name = argv[++i]; -+ } -+ /* APPLE LOCAL end framework */ - else if (argv[i][0] == '-' && argv[i][1] != 0) - { - const char *p = &argv[i][1]; ---- gcc-3.3.5/gcc/doc/invoke.texi.linker Thu Nov 11 13:52:13 2004 -+++ gcc-3.3.5/gcc/doc/invoke.texi Thu Nov 11 15:33:54 2004 -@@ -4522,6 +4522,15 @@ - an executable output file. They are meaningless if the compiler is - not doing a link step. - -+@c APPLE LOCAL begin linker flags -+In addition to the options listed below, Apple's GCC also accepts and -+passes nearly all of the options defined by the linker @samp{ld} and by -+the library tool @samp{libtool}. Common options include -+@samp{-framework}, @samp{-dynamic}, @samp{-bundle}, -+@samp{-flat_namespace}, and so forth. See the ld and libtool man pages -+for further details. -+@c APPLE LOCAL end linker flags -+ - @table @gcctabopt - @cindex file names - @item @var{object-file-name} diff -uNr gdc-0.23/d/gcc-mars.cc gdc-0.24/d/gcc-mars.cc --- gdc-0.23/d/gcc-mars.cc 2007-03-04 16:38:00.000000000 +0100 +++ gdc-0.24/d/gcc-mars.cc 2007-08-22 05:21:08.000000000 +0200 @@ -35,7 +35,7 @@ copyright = "Copyright (c) 1999-2007 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.1007"; + version = "v1.020"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr gdc-0.23/d/gdc_alloca.h gdc-0.24/d/gdc_alloca.h --- gdc-0.23/d/gdc_alloca.h 2006-11-14 15:28:31.000000000 +0100 +++ gdc-0.24/d/gdc_alloca.h 2007-07-22 17:52:03.000000000 +0200 @@ -8,7 +8,7 @@ # include # elif SKYOS # define alloca __builtin_alloca -# elif defined(__APPLE__) && (GCC_VER <= 33) +# elif defined(__APPLE__) && (GCC_VER <= 33) || defined(__OpenBSD__) # include # else /* guess... */ diff -uNr gdc-0.23/d/GDC.html gdc-0.24/d/GDC.html --- gdc-0.23/d/GDC.html 2007-03-05 01:42:52.000000000 +0100 +++ gdc-0.24/d/GDC.html 2007-08-22 05:39:52.000000000 +0200 @@ -5,9 +5,9 @@ D Front End for GCC -

D Front End for GCC - Release 0.23
+

D Front End for GCC - Release 0.24

-Last update: March 4, 2007
+Last update: August 22, 2007

Supported Systems

  • GCC 3.4.x, 4.0.x, 4.1.x
    @@ -1500,1063 +1500,345 @@ for example) is not well defined.

    Changes

    - - - +0.24: +
      +
    • Removed support for GCC 3.3.x
    • +
    • Updated to DMD 1.020
    • +
    • Fixed Bugzilla 1037, 1038 (gdc specific), 1043, 1045, 1046,
    • + 1031, 1032, 1034, 1065, 1109, 1191, 1137, 1152, 1208, 1325, + 1329, 1898, 1400 +
    • Fixed SourceForge issues 1689634, 1749622, 1721496, 1721435
    • +
    +0.23: +
      +
    • Added support for 64-bit targets
    • +
    • Added multilib support
    • +
    • Updated to DMD 1.007
    • +
    • Fixed Bugzilla 984, 1013
    • +
    0.22:
      -
    • Added support for GCC 4.1.x
    • -
    • Support for GCC 3.3.x is deprecated
    • -
    • Updated to DMD 1.004
    • -
    • Fixed Bugzilla 836, 837, 838, 839, 841, 843, 844, 889, 896
    • -
    • Fixed problems with missing debug information
    • -
    • Added Rick Mann's -frameowrk patch for gdmd
    • -
    - 0.21:
      - - - -
    • Updated to DMD 1.00
    • - - -
    • Fixed Bugzilla 695, 696, 737, 738, 739, 742, 743, 745
    • - - - -
    • Implemented GCC extended assembler
    • - - - -
    • Implemented basic support for GCC attributes
    • - - - -
    - - - - 0.20:
      - - - -
    • Updated to DMD 0.177
    • - - - -
    • Fixes for synchronized code generation
    • - - - -
    • Better support for cross-hosted builds
    • - - - -
    • Fixed Bugzilla 307, 375, 403, 575, 578
    • - - - -
    • Applied Anders Björklund's MacOS X build patches
    • - - - -
    - - - - 0.19:
      - - - -
    • Fixed D Bugzilla bugs 141(gdc), 157, 162, 164, 171, 174, 175, 192, 229
    • - - - -
    • Applied Dave Fladebo's suggestion for -O3 in gdmd
    • - - - -
    • Updated to DMD 0.162
    • - - - -
    • The version symbol for FreeBSD is now "freebsd"
    • - - - -
    • Enabled std.loader for FreeBSD
    • - - - -
    • Implement offsetof in assembler
    • - - - -
    • Support building with Apple's GCC (4.0 only)
    • - - - -
    • Fix parallel builds
    • - - - -
    - - - - 0.18:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • ICE on assignment arithmetic
      • - - - -
      • Problems mixing D and assembler floating point operations
      • - - - -
      • Mac OS X 10.2 build problems
      • - - - -
      • The gdc driver no longer compiles C source as C++.
        - - - -
      • - - - -
      • Many others...
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.157.
      • - - - -
      • Added support for PowerPC Linux.
        - - - -
      • - - - -
      • Added partial support for SkyOS.
      • - - - -
      • Compiler can be relocated to another directory.
        - - - -
      • - - - -
      - - - -
    - - - - 0.17:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Mixed complex/float operations on GCC 4.0 (D.gnu/1485)
      • - - - -
      • Applied Thomas Kuhne's HTML line number fix
      • - - - -
      • Foreach/nested functions in templates (D.gnu/1514)
      • - - - -
      • Use correct default initializer when allocating arrays of typedef'd types
      • - - - -
      • Recursive calls to nested functions (D.gnu/1525)
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.140
        - - - -
      • - - - -
      - - - -
    - - - - 0.16:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Concatenating a array and single element
      • - - - -
      • "__arrayArg already defined"
      • - - - -
      • ICE on nested foreach statements (D.gnu/1393)
      • - - - -
      • Inline assembler
      • - - - -
          - - - -
        • Functions returning floating point types
        • - - - -
        - - - -
          - - - -
        • Spurious error on scaled register without a base register
        • - - - -
        • Access to locals by var+ofs[EBP] now works with optimization.
        • - - - -
        • Can now guess operand size from referenced variables.
        • - - - -
        - - - -
      • Thunks errors with reimplemented interfaces (e.g., Mango)
        - - - -
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Support GCC 4.0.x
      • - - - -
      • Updated to DMD 0.137
      • - - - -
      • Support DW_LANG_D for DWARF debugging
      • - - - -
      • Support compiling multiple sources to a single object with GCC 3.4.x.
        - - - -
      • - - - -
      - - - -
    - - - -
    - - - - 0.15:
    - - - -
        Updated to DMD 0.128
    - - - -
    - - - -
    - - - - 0.14:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Classes nested in functions actually work now.
      • - - - -
      • Fix for newest versions of the GNU assembler.
        - - - -
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.127
        - - - -
      • - - - -
      - - - -
    - - - -
    - - - - 0.13:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Cygwin/MinGW assembler problem
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.126.
      • - - - -
      • Calling nested functions with delegates is faster.
      • - - - -
      • The "check-target-libphobos" uses unit tests and runtime checks.
        - - - -
      • - - - -
      - - - -
    - - - - 0.12.1:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Compilation errors and crashes with -fpic
      • - - - -
      • Crashes with interfaces on Cygwin/MinGW
      • - - - -
      • Support the -mno-cygwin option
        - - - -
      • - - - -
      - - - -
    - - - - 0.12:
    - - - -
      - - - -
    • Fixes
    • - - - -
        - - - -
      • Various problems building MinGW in MSYS
      • - - - -
      • Mango "endless output"
      • - - - -
      • Build problems with gcc 3.4.1
      • - - - -
      • Various problems revealed by dmdscript
        - - - -
      • - - - -
      • Error message now go to standard error
      • - - - -
      • DStress catch_01, catch_02, new_04, switch_19, throw_02, and others.
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.125
      • - - - -
      • New target: AIX
      • - - - -
      • GDC and DMD versions are reported with "gcc --version"
      • - - - -
      • Take advantage of DMD template improvements on
        - - - -
      • - - - -
      - - - -
    • Changes
    • - - - -
        - - - -
      • std.c.unix is now std.c.unix.unix
      • - - - -
      • The runtime library is now "libgphobos" to avoid conflicts with DMD.
      • - - - -
      • 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
    • - - - -
        - - - -
      • Reversed structure compare
      • - - - -
      • Correct meaning of '-L' option in wrapper script
      • - - - -
      • Static data GC bug on Linux
      • - - - -
      - - - -
    • Improvements
    • - - - -
        - - - -
      • Updated to DMD 0.121
      • - - - -
      • New target: MingGW
      • - - - -
      • Included Anders F Björklund's man pages.
        - - - -
      • - - - -
      • It is now possible to build a cross-compiler.  Only MingGW is supported out-of-the-box, however.
      • - - - -
      - - - -
    diff -uNr gdc-0.23/d/gdc-version gdc-0.24/d/gdc-version --- gdc-0.23/d/gdc-version 2007-03-04 16:37:44.000000000 +0100 +++ gdc-0.24/d/gdc-version 2007-08-22 05:21:08.000000000 +0200 @@ -1 +1 @@ -gdc 0.23, using dmd 1.007 +gdc 0.24, using dmd 1.020 \ No newline at end of file diff -uNr gdc-0.23/d/History gdc-0.24/d/History --- gdc-0.23/d/History 2007-03-05 01:36:23.000000000 +0100 +++ gdc-0.24/d/History 2007-08-22 05:21:08.000000000 +0200 @@ -1,3 +1,11 @@ +0.24: + * Removed support for GCC 3.3.x + * Updated to DMD 1.020 + * Fixed Bugzilla 1037, 1038 (gdc specific), 1043, 1045, 1046, + 1031, 1032, 1034, 1065, 1109, 1191, 1137, 1152, 1208, 1325, + 1329, 1898, 1400 + * Fixed SourceForge issues 1689634, 1749622, 1721496, 1721435 + 0.23: * Added support for 64-bit targets * Added multilib support diff -uNr gdc-0.23/d/Make-lang.in gdc-0.24/d/Make-lang.in --- gdc-0.23/d/Make-lang.in 2007-03-04 17:08:23.000000000 +0100 +++ gdc-0.24/d/Make-lang.in 2007-05-09 02:09:26.000000000 +0200 @@ -64,11 +64,11 @@ d/dmd/parse.h d/dmd/port.h d/dmd/root.h d/dmd/scope.h \ d/dmd/statement.h d/dmd/staticassert.h d/dmd/stringtable.h \ d/dmd/template.h d/dmd/total.h d/dmd/utf.h d/dmd/version.h \ - d/id.h d/d-dmd-gcc.h + d/id.h d/d-dmd-gcc.h d/d-gcc-real.h D_TREE_H = $(TREE_H) d/d-tree.def d/d-lang.h d/d-codegen.h d/d-objfile.h \ d/d-irstate.h d/d-dmd-gcc.h d/d-gcc-includes.h d/d-gcc-real.h \ - d/symbol.h d/dt.h function.h varray.h \ + d/symbol.h d/dt.h coretypes.h function.h varray.h \ $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \ $(GGC_H) \ $(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h \ @@ -84,40 +84,23 @@ D_is_apple_ver:=$(shell grep version_string $(gcc_version_trigger) | grep 'Apple') endif -ifeq ($(D_gcc_main_ver),3.3) - D_target_alias=$(target_alias) - D_EXTRA_DEFINES += -DD_GCC_VER=33 - gcc_d_target_include_dir=$(gcc_d_include_dir)/$(target_alias) - - # Actual names to use when installing a cross-compiler. - # 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_target_alias=$(target_noncanonical) - gcc_d_target_include_dir=$(gcc_d_include_dir)/$(target_noncanonical) +gcc_d_target_include_dir=$(gcc_d_include_dir)/$(target_noncanonical) - ifeq ($(D_gcc_main_ver),3.4) +ifeq ($(D_gcc_main_ver),3.4) D_EXTRA_DEFINES += -DD_GCC_VER=34 - else +else ifeq ($(D_gcc_main_ver),4.0) D_EXTRA_DEFINES += -DD_GCC_VER=40 else D_EXTRA_DEFINES += -DD_GCC_VER=41 endif - endif - D_TREE_H += coretypes.h - - # 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 ($(version),3.3-fast) -D_EXTRA_DEFINES += -DD_GCC_VER330=1 endif +# 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) + ifeq ($(version),3.4.1) # need for Cygwin which does not have 3.4.x, x>1 yet... D_EXTRA_DEFINES += -DD_GCC_VER341=1 @@ -180,8 +163,21 @@ D_GLUE_OBJS += d/d-apple-gcc.cglue.o D_BORROWED_C_OBJS += stub-objc.o prefix.o $(C_TARGET_OBJS) endif +else + ifeq ($(D_gcc_main_ver),3.4) + D_GLUE_OBJS += d/d-c-stubs.cglue.o + D_BORROWED_C_OBJS += stub-objc.o prefix.o $(C_TARGET_OBJS) + D_EXTRA_LIBS += libcpp.a + else + ifeq ($(D_gcc_main_ver),4.1) + D_GLUE_OBJS += d/d-c-stubs.cglue.o + D_BORROWED_C_OBJS += stub-objc.o prefix.o $(C_TARGET_OBJS) + endif + endif endif +D_BORROWED_C_OBJS += + # The full path for -include ...total.h is only needed for g++ < 3.x # ALL_D_COMPILER_FLAGS causes issues -- c++ instead of C # Not all DMD sources depend on d-dmd-gcc.h @@ -235,7 +231,7 @@ d/symbol.glue.o: d/symbol.cc $(D_TREE_H) d/dt.glue.o: d/symbol.cc $(D_TREE_H) d/d-gt.cglue.o: d/d-gt.c $(D_TREE_H) -d/d-builtins.cglue.o: d/d-builtins.c $(D_TREE_H) d/d-bi-attrs-33.h d/d-bi-attrs-34.h d/d-bi-attrs-40.h d/d-bi-attrs-41.h +d/d-builtins.cglue.o: d/d-builtins.c $(D_TREE_H) d/d-bi-attrs-34.h d/d-bi-attrs-40.h d/d-bi-attrs-41.h d/d-builtins2.glue.o: d/d-builtins.c $(D_TREE_H) d/d-misc.cglue.o: d/d-misc.c $(D_TREE_H) @@ -264,7 +260,7 @@ $(D_COMPILER_NAME)$(exeext): $(D_ALL_OBJS) $(BACKEND) $(LIBDEPS) $(CXX) $(ALL_D_COMPILER_FLAGS) $(LDFLAGS) -o $@ \ - $(D_ALL_OBJS) $(BACKEND) $(LIBS) + $(D_ALL_OBJS) $(BACKEND) $(D_EXTRA_LIBS) $(LIBS) # Stage hooks: # The main makefile has already created stage?/cobol. @@ -365,7 +361,7 @@ @echo "build=$(build)" >> $@ @echo "host=$(host)" >> $@ @echo "target=$(target)" >> $@ - @echo "target_alias=$(D_target_alias)" >> $@ + @echo "target_alias=$(target_noncanonical)" >> $@ @echo "gcc_version=$(version)" >> $@ @echo "srcdir=$(srcdir)" >> $@ @echo "prefix=$(prefix)" >> $@ diff -uNr gdc-0.23/d/package/simple.sh gdc-0.24/d/package/simple.sh --- gdc-0.23/d/package/simple.sh 2007-03-05 01:48:26.000000000 +0100 +++ gdc-0.24/d/package/simple.sh 2007-08-22 04:20:58.000000000 +0200 @@ -88,6 +88,21 @@ pkg_name="gdc-$gdc_version-$target_alias" fi +# If this is a native compiler, try to build rdmd +# (This should be moved into the GCC build) +if test "$build" = "$host" && test "$host" = "$target"; then + if test ! -f "$inst_root/$prefix/bin/rdmd$exeext"; then + "$inst_root/$prefix/bin/gdc" -o "$inst_root/$prefix/bin/rdmd$exeext" \ + $srcdir/d/rdmd.d || exit 1 + fi + if test -d "$inst_root/$prefix/share/man/man1"; then + # Note: No ".1" extension -- assumes MacOS Universal build + cp $srcdir/d/rdmd.1 "$inst_root/$prefix/share/man/man1/rdmd" || exit 1 + else + cp $srcdir/d/rdmd.1 "$inst_root/$prefix/man/man1" || exit 1 + fi +fi + #pkg_root=/tmp/$pkg_name pkg_root=/tmp/gdc @@ -104,6 +119,7 @@ else ls bin/*gdc* >> "$file_list" ls bin/*gdmd* >> "$file_list" + ls bin/*rdmd* >> "$file_list" ls -d include/d >> "$file_list" find lib*/gcc -name '*.o' -o -name 'libgcc*.a' >> "$file_list" if test -z "$make_macos_package"; then @@ -114,12 +130,17 @@ find libexec -name '*collect2*' >> "$file_list" ls man/man1/*gdc* >> "$file_list" ls man/man1/*gdmd* >> "$file_list" + ls man/man1/*rdmd* >> "$file_list" + ls share/man/man1/*gdc* >> "$file_list" + ls share/man/man1/*gdmd* >> "$file_list" + ls share/man/man1/*rdmd* >> "$file_list" if test -n "$keep_gcov"; then ls bin/*gcov* >> "$file_list" # Don't need lib* here -- it's all buried under lib/gcc/ find lib -name 'libgcov*' >> "$file_list" ls man/man1/*gcov* >> "$file_list" + ls share/man/man1/*gcov* >> "$file_list" fi fi diff -uNr gdc-0.23/d/patch-build_gcc-4.0 gdc-0.24/d/patch-build_gcc-4.0 --- gdc-0.23/d/patch-build_gcc-4.0 2007-02-28 22:34:54.000000000 +0100 +++ gdc-0.24/d/patch-build_gcc-4.0 2007-08-22 04:20:58.000000000 +0200 @@ -1,5 +1,5 @@ ---- gcc-5341-orig/build_gcc 2006-03-15 20:30:20.000000000 -0500 -+++ gcc-5341/build_gcc 2007-02-28 16:33:04.000000000 -0500 +--- gcc-5363-orig/build_gcc 2006-06-27 03:29:34.000000000 -0400 ++++ gcc-5363/build_gcc 2007-08-21 22:04:22.000000000 -0400 @@ -106,11 +106,12 @@ CONFIGFLAGS="--disable-checking -enable-werror \ --prefix=$DEST_ROOT \ @@ -110,7 +110,7 @@ done lipo -output $DEST_DIR/$DEST_ROOT/bin/gcc-$MAJ_VERS -create \ -@@ -397,10 +441,14 @@ +@@ -397,11 +441,24 @@ lipo -output $DEST_DIR/$DEST_ROOT/bin/g++-$MAJ_VERS -create \ $DEST_DIR/$DEST_ROOT/bin/tmp-*-g++-$MAJ_VERS || exit 1 @@ -123,5 +123,15 @@ rm $DEST_DIR/$DEST_ROOT/bin/tmp-*-g++-$MAJ_VERS || exit 1 +rm $DEST_DIR/$DEST_ROOT/bin/tmp-*-gdc-$MAJ_VERS || exit 1 ++# Build rdmd ++for h in $HOSTS ; do ++ $DEST_DIR$DEST_ROOT/bin/$h-apple-darwin$DARWIN_VERS-gdc-$VERS \ ++ $ORIG_SRC_DIR/gcc/d/rdmd.d \ ++ -o $DEST_DIR/$DEST_ROOT/bin/tmp-$h-rdmd || exit 1 ++done ++lipo -output $DEST_DIR/$DEST_ROOT/bin/rdmd -create \ ++ $DEST_DIR/$DEST_ROOT/bin/tmp-*-rdmd || exit 1 ++rm $DEST_DIR/$DEST_ROOT/bin/tmp-*-rdmd || exit 1 ######################################## + # Save the source files and objects needed for debugging diff -uNr gdc-0.23/d/patch-gcc-3.3.x gdc-0.24/d/patch-gcc-3.3.x --- gdc-0.23/d/patch-gcc-3.3.x 2007-03-04 19:50:51.000000000 +0100 +++ gdc-0.24/d/patch-gcc-3.3.x 1970-01-01 01:00:00.000000000 +0100 @@ -1,370 +0,0 @@ -diff -c gcc-orig/gcc.c gcc/gcc.c -*** gcc-orig/gcc.c Thu Apr 1 11:55:17 2004 ---- gcc/gcc.c Thu Mar 1 10:58:13 2007 -*************** -*** 136,141 **** ---- 136,144 ---- - /* Flag set by cppspec.c to 1. */ - int is_cpp_driver; - -+ /* Flag set by drivers needing Pthreads. */ -+ int need_pthreads; -+ - /* Flag saying to pass the greatest exit code returned by a sub-process - to the calling program. */ - static int pass_exit_codes; -*************** -*** 455,460 **** ---- 458,464 ---- - assembler has done its job. - %D Dump out a -L option for each directory in startfile_prefixes. - If multilib_dir is set, extra entries are generated with it affixed. -+ %N Output the currently selected multilib directory name. - %l process LINK_SPEC as a spec. - %L process LIB_SPEC as a spec. - %G process LIBGCC_SPEC as a spec. -*************** -*** 3675,3680 **** ---- 3679,3687 ---- - } - } - -+ if (need_pthreads) -+ n_switches++; -+ - if (have_c && have_o && lang_n_infiles > 1) - fatal ("cannot specify -o with -c or -S and multiple compilations"); - -*************** -*** 4005,4010 **** ---- 4012,4029 ---- - } - } - -+ if (need_pthreads) -+ { -+ switches[n_switches].part1 = "pthread"; -+ switches[n_switches].args = 0; -+ switches[n_switches].live_cond = SWITCH_OK; -+ /* Do not print an error if there is not expansion for -pthread. */ -+ switches[n_switches].validated = 1; -+ switches[n_switches].ordering = 0; -+ -+ n_switches++; -+ } -+ - switches[n_switches].part1 = 0; - infiles[n_infiles].name = 0; - } -*************** -*** 5009,5014 **** ---- 5028,5044 ---- - return value; - break; - -+ case 'N': -+ if (multilib_dir) -+ { -+ arg_going = 1; -+ obstack_grow (&obstack, "-fmultilib-dir=", -+ strlen ("-fmultilib-dir=")); -+ obstack_grow (&obstack, multilib_dir, -+ strlen (multilib_dir)); -+ } -+ break; -+ - /* Here we define characters other than letters and digits. */ - - case '{': -diff -cr gcc-orig/gcc.c gcc/gcc.h -*** gcc-orig/gcc.h Fri Jun 24 22:02:01 2005 ---- gcc/gcc.h Sun Mar 4 13:44:05 2007 -*************** -*** 38,44 **** - || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ - || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ - || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \ -! || (CHAR) == 'B' || (CHAR) == 'b') - - /* This defines which multi-letter switches take arguments. */ - ---- 38,44 ---- - || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ - || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \ - || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \ -! || (CHAR) == 'B' || (CHAR) == 'b' || (CHAR) == 'J') - - /* This defines which multi-letter switches take arguments. */ - -diff -c gcc-3.3.2-orig-gcc/real.h gcc-3.3.2-patched-gcc/real.h -*** gcc-3.3.2-orig-gcc/real.h Tue Jul 1 21:28:45 2003 ---- gcc-3.3.2-patched-gcc/real.h Sat Feb 7 21:33:06 2004 -*************** -*** 40,52 **** - #define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG) - #define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1)) - - struct real_value GTY(()) - { -! ENUM_BITFIELD (real_value_class) class : 2; - unsigned int sign : 1; - signed int exp : EXP_BITS; - unsigned long sig[SIGSZ]; - }; - - /* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it - needs to be a macro. We do need to continue to have a structure tag ---- 40,62 ---- - #define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG) - #define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1)) - -+ /* Can't have "class" in C++, but gentype gets confused on #ifdefs -+ within the struct. */ -+ #ifndef __cplusplus -+ # define REAL_CLASSY class -+ #else -+ # define REAL_CLASSY cl -+ #endif -+ - struct real_value GTY(()) - { -! ENUM_BITFIELD (real_value_class) REAL_CLASSY : 2; - unsigned int sign : 1; - signed int exp : EXP_BITS; - unsigned long sig[SIGSZ]; - }; -+ -+ #undef REAL_CLASSY - - /* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it - needs to be a macro. We do need to continue to have a structure tag -diff -c gcc-3.3.2-orig-gcc/rtl.h gcc-3.3.2-patched-gcc/rtl.h -*** gcc-3.3.2-orig-gcc/rtl.h Thu May 1 21:21:07 2003 ---- gcc-3.3.2-patched-gcc/rtl.h Sat Feb 7 21:33:36 2004 -*************** -*** 111,118 **** ---- 111,123 ---- - int rtint; - unsigned int rtuint; - const char *rtstr; -+ #ifndef __cplusplus - rtx rtx; - rtvec rtvec; -+ #else -+ rtx rt_rtx; -+ rtvec rt_vec; -+ #endif - 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 -c gcc-orig/function.c gcc/function.c -*** gcc-orig/function.c Sat May 28 17:02:12 2005 ---- gcc/function.c Thu Jun 9 19:56:31 2005 -*************** -*** 6575,6585 **** - { - last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); - -! /* Delay copying static chain if it is not a register to avoid -! conflicts with regs used for parameters. */ -! if (! SMALL_REGISTER_CLASSES -! || GET_CODE (static_chain_incoming_rtx) == REG) -! emit_move_insn (last_ptr, static_chain_incoming_rtx); - } - - /* If the parameters of this function need cleaning up, get a label ---- 6575,6588 ---- - { - last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); - -! if (cfun->static_chain_expr == NULL_TREE) -! { -! /* Delay copying static chain if it is not a register to avoid -! conflicts with regs used for parameters. */ -! if (! SMALL_REGISTER_CLASSES -! || GET_CODE (static_chain_incoming_rtx) == REG) -! emit_move_insn (last_ptr, static_chain_incoming_rtx); -! } - } - - /* If the parameters of this function need cleaning up, get a label -*************** -*** 6666,6675 **** - - /* Copy the static chain now if it wasn't a register. The delay is to - avoid conflicts with the parameter passing registers. */ -! -! if (SMALL_REGISTER_CLASSES && current_function_needs_context) -! if (GET_CODE (static_chain_incoming_rtx) != REG) -! emit_move_insn (last_ptr, static_chain_incoming_rtx); - - /* The following was moved from init_function_start. - The move is supposed to make sdb output more accurate. */ ---- 6669,6680 ---- - - /* Copy the static chain now if it wasn't a register. The delay is to - avoid conflicts with the parameter passing registers. */ -! if (cfun->static_chain_expr == NULL_TREE) -! { -! if (SMALL_REGISTER_CLASSES && current_function_needs_context) -! if (GET_CODE (static_chain_incoming_rtx) != REG) -! emit_move_insn (last_ptr, static_chain_incoming_rtx); -! } - - /* The following was moved from init_function_start. - The move is supposed to make sdb output more accurate. */ -*************** -*** 6694,6703 **** - /* If the static chain originally came in a register, put it back - there, then move it out in the next insn. The reason for - this peculiar code is to satisfy function integration. */ -! if (SMALL_REGISTER_CLASSES -! && GET_CODE (static_chain_incoming_rtx) == REG) -! emit_move_insn (static_chain_incoming_rtx, last_ptr); -! last_ptr = copy_to_reg (static_chain_incoming_rtx); - } - - while (tem) ---- 6699,6719 ---- - /* If the static chain originally came in a register, put it back - there, then move it out in the next insn. The reason for - this peculiar code is to satisfy function integration. */ -! if (cfun->static_chain_expr == NULL_TREE) -! { -! if (SMALL_REGISTER_CLASSES -! && GET_CODE (static_chain_incoming_rtx) == REG) -! emit_move_insn (static_chain_incoming_rtx, last_ptr); -! last_ptr = copy_to_reg (static_chain_incoming_rtx); -! } -! else -! { -! rtx r = expand_expr (cfun->static_chain_expr, NULL_RTX, -! VOIDmode, EXPAND_NORMAL); -! r = copy_to_reg (r); -! emit_move_insn (last_ptr, r); -! last_ptr = r; -! } - } - - while (tem) -diff -c gcc-orig/function.h gcc/function.h -*** gcc-orig/function.h Fri Nov 14 01:46:09 2003 ---- gcc/function.h Wed Jun 8 19:03:37 2005 -*************** -*** 508,513 **** ---- 508,517 ---- - /* Maximal number of entities in the single jumptable. Used to estimate - final flowgraph size. */ - int max_jumptable_ents; -+ -+ /* Expression to be evaluated to get the static chain. If NULL, -+ the standard trampoline method is used. */ -+ tree static_chain_expr; - }; - - /* The function currently being compiled. */ -diff -cr gcc-orig/dwarf2.h gcc/dwarf2.h -*** gcc-orig/dwarf2.h Sun Sep 8 18:36:53 2002 ---- gcc/dwarf2.h Thu Sep 22 13:11:27 2005 -*************** -*** 588,593 **** ---- 588,594 ---- - DW_LANG_C99 = 0x000c, - DW_LANG_Ada95 = 0x000d, - DW_LANG_Fortran95 = 0x000e, -+ DW_LANG_D = 0x0013, - /* MIPS. */ - DW_LANG_Mips_Assembler = 0x8001 - }; -diff -cr gcc-orig/dwarf2out.c gcc/dwarf2out.c -*** gcc-orig/dwarf2out.c Wed Oct 1 16:58:30 2003 ---- gcc/dwarf2out.c Thu Sep 22 13:17:56 2005 -*************** -*** 4956,4962 **** - unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - - return (lang == DW_LANG_C || lang == DW_LANG_C89 -! || lang == DW_LANG_C_plus_plus); - } - - static inline int ---- 4956,4963 ---- - unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - - return (lang == DW_LANG_C || lang == DW_LANG_C89 -! || lang == DW_LANG_C_plus_plus -! || lang == DW_LANG_D); - } - - static inline int -*************** -*** 11235,11240 **** ---- 11236,11243 ---- - language = DW_LANG_Pascal83; - else if (strcmp (language_string, "GNU Java") == 0) - language = DW_LANG_Java; -+ else if (strcmp (language_string, "GNU D") == 0) -+ language = DW_LANG_D; - else - language = DW_LANG_C89; - -*************** -*** 12630,12636 **** - add_child_die (comp_unit_die, die); - else if (node->created_for - && ((DECL_P (node->created_for) -! && (context = DECL_CONTEXT (node->created_for))) - || (TYPE_P (node->created_for) - && (context = TYPE_CONTEXT (node->created_for)))) - && TREE_CODE (context) == FUNCTION_DECL) ---- 12633,12639 ---- - add_child_die (comp_unit_die, die); - else if (node->created_for - && ((DECL_P (node->created_for) -! && (context = decl_function_context (node->created_for))) - || (TYPE_P (node->created_for) - && (context = TYPE_CONTEXT (node->created_for)))) - && TREE_CODE (context) == FUNCTION_DECL) diff -uNr gdc-0.23/d/patch-gcc-4.0.x gdc-0.24/d/patch-gcc-4.0.x --- gdc-0.23/d/patch-gcc-4.0.x 2007-03-04 19:47:56.000000000 +0100 +++ gdc-0.24/d/patch-gcc-4.0.x 2007-08-22 02:15:43.000000000 +0200 @@ -625,6 +625,34 @@ case WITH_CLEANUP_EXPR: NIY; break; +diff -cr gcc-orig/tree-sra.c gcc/tree-sra.c +*** gcc-orig/tree-sra.c Fri Aug 5 16:39:04 2005 +--- gcc/tree-sra.c Thu Jul 26 18:45:59 2007 +*************** +*** 196,201 **** +--- 196,203 ---- + case RECORD_TYPE: + { + bool saw_one_field = false; ++ tree last_offset = size_zero_node; ++ tree cmp; + + for (t = TYPE_FIELDS (type); t ; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == FIELD_DECL) +*************** +*** 205,210 **** +--- 207,217 ---- + && (tree_low_cst (DECL_SIZE (t), 1) + != TYPE_PRECISION (TREE_TYPE (t)))) + goto fail; ++ /* Reject aliased fields created by GDC for anonymous unions. */ ++ cmp = fold_binary_to_constant (LE_EXPR, boolean_type_node, ++ DECL_FIELD_OFFSET (t), last_offset); ++ if (cmp == NULL_TREE || TREE_CODE (cmp) != INTEGER_CST || TREE_INT_CST_LOW (cmp)) ++ goto fail; + + saw_one_field = true; + } diff -cr gcc-orig/tree.def gcc/tree.def *** gcc-orig/tree.def Sun Jan 23 15:05:34 2005 --- gcc/tree.def Fri Nov 4 13:51:43 2005 diff -uNr gdc-0.23/d/patch-gcc-4.1.x gdc-0.24/d/patch-gcc-4.1.x --- gdc-0.23/d/patch-gcc-4.1.x 2007-03-04 19:45:26.000000000 +0100 +++ gdc-0.24/d/patch-gcc-4.1.x 2007-08-22 02:15:43.000000000 +0200 @@ -439,6 +439,19 @@ case TREE_LIST: gcc_unreachable (); +diff -cr gcc-orig/predict.c gcc/predict.c +*** gcc-orig/predict.c Thu Jul 19 20:05:21 2007 +--- gcc/predict.c Thu Jul 19 20:06:06 2007 +*************** +*** 1339,1344 **** +--- 1339,1345 ---- + care for error returns and other cases are often used for + fast paths trought function. */ + if (e->dest == EXIT_BLOCK_PTR ++ && last_stmt (bb) == NULL_TREE + && TREE_CODE (last_stmt (bb)) == RETURN_EXPR + && !single_pred_p (bb)) + { diff -cr gcc-orig/real.c gcc/real.c *** gcc-orig/real.c Mon Sep 19 13:01:40 2005 --- gcc/real.c Tue Jan 23 19:39:14 2007 @@ -686,6 +699,34 @@ case WITH_CLEANUP_EXPR: NIY; break; +diff -cr gcc-orig/tree-sra.c gcc/tree-sra.c +*** gcc-orig/tree-sra.c Sun Nov 20 19:55:57 2005 +--- gcc/tree-sra.c Sun Jul 22 11:32:36 2007 +*************** +*** 198,203 **** +--- 198,205 ---- + case RECORD_TYPE: + { + bool saw_one_field = false; ++ tree last_offset = size_zero_node; ++ tree cmp; + + for (t = TYPE_FIELDS (type); t ; t = TREE_CHAIN (t)) + if (TREE_CODE (t) == FIELD_DECL) +*************** +*** 207,212 **** +--- 209,219 ---- + && (tree_low_cst (DECL_SIZE (t), 1) + != TYPE_PRECISION (TREE_TYPE (t)))) + goto fail; ++ /* Reject aliased fields created by GDC for anonymous unions. */ ++ cmp = fold_binary_to_constant (LE_EXPR, boolean_type_node, ++ DECL_FIELD_OFFSET (t), last_offset); ++ if (cmp == NULL_TREE || tree_expr_nonzero_p (cmp)) ++ goto fail; + + saw_one_field = true; + } diff -cr gcc-orig/tree.def gcc/tree.def *** gcc-orig/tree.def Fri Feb 10 12:32:10 2006 --- gcc/tree.def Tue Jan 23 19:39:14 2007 diff -uNr gdc-0.23/d/patch-gcc-darwin-eh-3.3.x gdc-0.24/d/patch-gcc-darwin-eh-3.3.x --- gdc-0.23/d/patch-gcc-darwin-eh-3.3.x 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/patch-gcc-darwin-eh-3.3.x 1970-01-01 01:00:00.000000000 +0100 @@ -1,35 +0,0 @@ -*** gcc/config/darwin.h.orig Sun Feb 20 16:41:18 2005 ---- gcc/config/darwin.h Sun Feb 20 19:24:38 2005 -*************** -*** 635,641 **** - ".section __DATA,__gcc_except_tab", 0) \ - SECTION_FUNCTION (darwin_eh_frame_section, \ - in_darwin_eh_frame, \ -! ".section __TEXT,__eh_frame", 0) \ - \ - static void \ - objc_section_init () \ ---- 635,641 ---- - ".section __DATA,__gcc_except_tab", 0) \ - SECTION_FUNCTION (darwin_eh_frame_section, \ - in_darwin_eh_frame, \ -! ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms", 0)/*df*/ \ - \ - static void \ - objc_section_init () \ -*** 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 - -+ #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.23/d/patch-toplev-3.3.x gdc-0.24/d/patch-toplev-3.3.x --- gdc-0.23/d/patch-toplev-3.3.x 2006-06-03 04:57:50.000000000 +0200 +++ gdc-0.24/d/patch-toplev-3.3.x 1970-01-01 01:00:00.000000000 +0100 @@ -1,126 +0,0 @@ -diff -c gcc-3.3.2-orig/Makefile.def gcc-3.3.2/Makefile.def -*** gcc-3.3.2-orig/Makefile.def Tue Dec 31 15:07:33 2002 ---- gcc-3.3.2/Makefile.def Sun Apr 10 14:50:29 2005 -*************** -*** 78,80 **** ---- 78,81 ---- - target_modules = { module= boehm-gc; }; - target_modules = { module= qthreads; }; - target_modules = { module= rda; }; -+ target_modules = { module= libphobos; }; -diff -c gcc-3.3.2-orig/Makefile.in gcc-3.3.2/Makefile.in -*** gcc-3.3.2-orig/Makefile.in Fri Jul 4 22:37:08 2003 ---- gcc-3.3.2/Makefile.in Sun Apr 10 14:51:11 2005 -*************** -*** 765,771 **** - all-target-zlib \ - all-target-boehm-gc \ - all-target-qthreads \ -! all-target-rda - - # This is a list of the configure targets for all of the modules which - # are compiled using the target tools. ---- 765,772 ---- - all-target-zlib \ - all-target-boehm-gc \ - all-target-qthreads \ -! all-target-rda \ -! all-target-libphobos - - # This is a list of the configure targets for all of the modules which - # are compiled using the target tools. -*************** -*** 785,791 **** - configure-target-zlib \ - configure-target-boehm-gc \ - configure-target-qthreads \ -! configure-target-rda - - # This is a list of the check targets for all of the modules which are - # compiled using $(TARGET_FLAGS_TO_PASS). ---- 786,793 ---- - configure-target-zlib \ - configure-target-boehm-gc \ - configure-target-qthreads \ -! configure-target-rda \ -! configure-target-libphobos - - # This is a list of the check targets for all of the modules which are - # compiled using $(TARGET_FLAGS_TO_PASS). -*************** -*** 802,808 **** - check-target-zlib \ - check-target-boehm-gc \ - check-target-qthreads \ -! check-target-rda - - # This is a list of the install targets for all of the modules which are - # compiled using $(TARGET_FLAGS_TO_PASS). ---- 804,811 ---- - check-target-zlib \ - check-target-boehm-gc \ - check-target-qthreads \ -! check-target-rda \ -! check-target-libphobos - - # This is a list of the install targets for all of the modules which are - # compiled using $(TARGET_FLAGS_TO_PASS). -*************** -*** 821,827 **** - install-target-zlib \ - install-target-boehm-gc \ - install-target-qthreads \ -! install-target-rda - - # This is a list of the targets for which we can do a clean-{target}. - CLEAN_MODULES = \ ---- 824,831 ---- - install-target-zlib \ - install-target-boehm-gc \ - install-target-qthreads \ -! install-target-rda \ -! install-target-libphobos - - # This is a list of the targets for which we can do a clean-{target}. - CLEAN_MODULES = \ -*************** -*** 902,908 **** - clean-target-zlib \ - clean-target-boehm-gc \ - clean-target-qthreads \ -! clean-target-rda - - # All of the x11 modules that can be cleaned - CLEAN_X11_MODULES = \ ---- 906,913 ---- - clean-target-zlib \ - clean-target-boehm-gc \ - clean-target-qthreads \ -! clean-target-rda \ -! clean-target-libphobos - - # All of the x11 modules that can be cleaned - CLEAN_X11_MODULES = \ -*************** -*** 1777,1782 **** ---- 1782,1788 ---- - all-target-boehm-gc: configure-target-boehm-gc - all-target-qthreads: configure-target-qthreads - all-target-rda: configure-target-rda -+ all-target-libphobos: configure-target-libphobos - - - ### other supporting targets -diff -c gcc-3.3.2-orig/configure.in gcc-3.3.2/configure.in -*** gcc-3.3.2-orig/configure.in Sat Aug 9 02:57:21 2003 ---- gcc-3.3.2/configure.in Sun Apr 10 14:42:20 2005 -*************** -*** 66,71 **** ---- 66,72 ---- - target-newlib \ - ${libstdcxx_version} \ - target-libf2c \ -+ target-libphobos \ - ${libgcj} - target-libobjc" - diff -uNr gdc-0.23/d/phobos/frag-ac.in gdc-0.24/d/phobos/frag-ac.in --- gdc-0.23/d/phobos/frag-ac.in 2006-06-03 04:57:27.000000000 +0200 +++ gdc-0.24/d/phobos/frag-ac.in 2007-04-28 18:45:43.000000000 +0200 @@ -4,4 +4,12 @@ @DCFG_SQRTF@ +// C stdio config for std.stdio +const bool Have_fwide = @DCFG_FWIDE@; +const bool Have_getdelim = @DCFG_HAVE_GETDELIM@; +const bool Have_fgetln = @DCFG_HAVE_FGETLN@; +const bool Have_fgetline = @DCFG_HAVE_FGETLINE@; +const bool Have_Unlocked_Stdio = @DCFG_HAVE_UNLOCKED_STDIO@; +const bool Have_Unlocked_Wide_Stdio = @DCFG_HAVE_UNLOCKED_WIDE_STDIO@; + // ...frags-ac.in diff -uNr gdc-0.23/d/phobos/internal/aaA.d gdc-0.24/d/phobos/internal/aaA.d --- gdc-0.23/d/phobos/internal/aaA.d 2007-02-08 19:07:06.000000000 +0100 +++ gdc-0.24/d/phobos/internal/aaA.d 2007-04-29 18:39:02.000000000 +0200 @@ -34,10 +34,13 @@ Modified by David Friedman, September 2004 */ +//import std.stdio; +import std.c.stdarg; import std.c.stdio; import std.c.stdlib; import std.c.string; import std.string; + import std.outofmemory; // Auto-rehash and pre-allocate - Dave Fladebo @@ -87,15 +90,6 @@ struct AA { BB* a; - version (X86_64) - { - } - else - { - // This is here only to retain binary compatibility with the - // old way we did AA's. Should eventually be removed. - //int reserved; - } } /********************************** @@ -305,6 +299,7 @@ void *_aaGetRvaluep(AA aa, TypeInfo keyti, size_t valuesize, void *pkey) { + //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); if (!aa.a) return null; @@ -741,3 +736,93 @@ return result; } + +/*********************************** + * Construct an associative array of type ti from + * length pairs of key/value pairs. + */ + +extern (C) +BB* _d_assocarrayliteralTp(TypeInfo_AssociativeArray ti, size_t length, + void *keys, void *values) +{ + auto valuesize = ti.next.tsize(); // value size + auto keyti = ti.key; + auto keysize = keyti.tsize(); // key size + BB* result; + + //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length); + //writefln("tivalue = %s", ti.next.classinfo.name); + if (length == 0 || valuesize == 0 || keysize == 0) + { + ; + } + else + { + //va_list q; + //va_start!(size_t)(q, length); + void * qkey = keys; + void * qval = values; + + result = new BB(); + size_t i; + + for (i = 0; i < prime_list.length - 1; i++) + { + if (length <= prime_list[i]) + break; + } + auto len = prime_list[i]; + result.b = new aaA*[len]; + + size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1); + size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1); + + size_t keytsize = aligntsize(keysize); + + for (size_t j = 0; j < length; j++) + { void* pkey = qkey; + //q += keystacksize; + qkey += keysize; + void* pvalue = qval; + //q += valuestacksize; + qval += valuesize; + aaA* e; + + auto key_hash = keyti.getHash(pkey); + //printf("hash = %d\n", key_hash); + i = key_hash % len; + auto pe = &result.b[i]; + while (1) + { + e = *pe; + if (!e) + { + // Not found, create new elem + //printf("create new one\n"); + e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize]; + memcpy(e + 1, pkey, keysize); + e.hash = key_hash; + *pe = e; + result.nodes++; + break; + } + if (key_hash == e.hash) + { + auto c = keyti.compare(pkey, e + 1); + if (c == 0) + break; + pe = (c < 0) ? &e.left : &e.right; + } + else + pe = (key_hash < e.hash) ? &e.left : &e.right; + } + memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize); + } + + //va_end(q); + } + return result; +} + + diff -uNr gdc-0.23/d/phobos/internal/adi.d gdc-0.24/d/phobos/internal/adi.d --- gdc-0.23/d/phobos/internal/adi.d 2007-03-04 15:38:13.000000000 +0100 +++ gdc-0.24/d/phobos/internal/adi.d 2007-08-22 02:16:14.000000000 +0200 @@ -110,10 +110,10 @@ memcpy(tmplo.ptr, lo, stridelo); memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo); memcpy(lo, tmp.ptr, stridehi); - memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo); + memcpy(hi + cast(int) stridehi - cast(int) stridelo, tmplo.ptr, stridelo); lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); + hi = hi - 1 + (cast(int) stridehi - cast(int) stridelo); } } return *cast(Array*)(&a); @@ -202,12 +202,12 @@ /* Shift the whole array. This is woefully inefficient */ memcpy(tmp.ptr, hi, stridehi * wchar.sizeof); - memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof); + memcpy(hi + cast(int) stridehi - cast(int) stridelo, lo, stridelo * wchar.sizeof); memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof); memcpy(lo, tmp.ptr, stridehi * wchar.sizeof); lo += stridehi; - hi = hi - 1 + (stridehi - stridelo); + hi = hi - 1 + (cast(int) stridehi - cast(int) stridelo); } } return *cast(Array*)(&a); diff -uNr gdc-0.23/d/phobos/internal/dgccmain2.d gdc-0.24/d/phobos/internal/dgccmain2.d --- gdc-0.23/d/phobos/internal/dgccmain2.d 2006-11-18 16:17:14.000000000 +0100 +++ gdc-0.24/d/phobos/internal/dgccmain2.d 2007-05-05 15:24:02.000000000 +0200 @@ -93,8 +93,9 @@ go(); catch (Object o) { - printf("Error: "); - o.print(); + char[] msg = o.toString(); + fprintf(stderr, "Error: "); + fprintf(stderr, "%.*s\n", cast(int) msg.length, msg.ptr); exit(EXIT_FAILURE); } } diff -uNr gdc-0.23/d/phobos/internal/dmain2.d gdc-0.24/d/phobos/internal/dmain2.d --- gdc-0.23/d/phobos/internal/dmain2.d 2007-03-04 15:45:02.000000000 +0100 +++ gdc-0.24/d/phobos/internal/dmain2.d 2007-07-23 02:23:26.000000000 +0200 @@ -96,8 +96,15 @@ } catch (Object o) { - printf("Error: "); - o.print(); + version (none) + { + printf("Error: "); + o.print(); + } + else + { + fprintf(stderr, "Error: %.*s\n", o.toString()); + } exit(EXIT_FAILURE); } } diff -uNr gdc-0.23/d/phobos/internal/gc/gc.d gdc-0.24/d/phobos/internal/gc/gc.d --- gdc-0.23/d/phobos/internal/gc/gc.d 2007-03-04 15:45:25.000000000 +0100 +++ gdc-0.24/d/phobos/internal/gc/gc.d 2007-07-27 02:07:14.000000000 +0200 @@ -69,6 +69,28 @@ void hasNoPointers(void* p) { _gc.hasNoPointers(p); } void setV1_0() { _gc.setV1_0(); } +void[] malloc(size_t nbytes) +{ + void* p = _gc.malloc(nbytes); + return p[0 .. nbytes]; +} + +void[] realloc(void* p, size_t nbytes) +{ + void* q = _gc.realloc(p, nbytes); + return q[0 .. nbytes]; +} + +size_t extend(void* p, size_t minbytes, size_t maxbytes) +{ + return _gc.extend(p, minbytes, maxbytes); +} + +size_t capacity(void* p) +{ + return _gc.capacity(p); +} + void setTypeInfo(TypeInfo ti, void* p) { if (ti.flags() & 1) @@ -129,6 +151,7 @@ void gc_term() { _gc.fullCollectNoStack(); + _gc.Dtor(); } Object _d_newclass(ClassInfo ci) @@ -141,6 +164,7 @@ p = std.c.stdlib.malloc(ci.init.length); if (!p) _d_OutOfMemory(); + debug(PRINTF) printf(" COM object p = %p\n", p); } else { @@ -226,17 +250,31 @@ Array result; auto size = ti.next.tsize(); // array element size - debug(PRINTF) printf("_d_newT(length = %d, size = %d)\n", length, size); + debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size); if (length && size) { result.length = length; - size *= length; + /*version (D_InlineAsm_X86) + { + asm + { + mov EAX,size ; + mul EAX,length ; + mov size,EAX ; + jc Loverflow ; + } + } + else*/ + size *= length; result.data = cast(byte*) _gc.malloc(size + 1); if (!(ti.next.flags() & 1)) _gc.hasNoPointers(result.data); memset(result.data, 0, size); } return result; + +Loverflow: + _d_OutOfMemory(); } /* For when the array has a non-zero initializer. @@ -246,7 +284,8 @@ Array result; auto size = ti.next.tsize(); // array element size - //debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d, isize = %d)\n", length, size, isize); + debug(PRINTF) + printf("_d_newarrayiT(length = %d, size = %d)\n", length, size); if (length == 0 || size == 0) { } else @@ -254,7 +293,18 @@ auto initializer = ti.next.init(); auto isize = initializer.length; auto q = initializer.ptr; - size *= length; + /*version (D_InlineAsm_X86) + { + asm + { + mov EAX,size ; + mul EAX,length ; + mov size,EAX ; + jc Loverflow ; + } + } + else*/ + size *= length; auto p = _gc.malloc(size + 1); debug(PRINTF) printf(" p = %p\n", p); if (!(ti.next.flags() & 1)) @@ -281,6 +331,9 @@ result.data = cast(byte*) p ; } return result; + +Loverflow: + _d_OutOfMemory(); } void[] _d_newarraymTp(TypeInfo ti, int ndims, size_t* pdim) @@ -517,11 +570,20 @@ if (cap <= newsize) { + if (cap >= 4096) + { // Try to extend in-place + auto u = _gc.extend(p.data, (newsize + 1) - cap, (newsize + 1) - cap); + if (u) + { + goto L1; + } + } newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; if (!(ti.next.flags() & 1)) _gc.hasNoPointers(newdata); } + L1: newdata[size .. newsize] = 0; } } @@ -619,8 +681,17 @@ if (cap <= newsize) { + if (cap >= 4096) + { // Try to extend in-place + auto u = _gc.extend(p.data, (newsize + 1) - cap, (newsize + 1) - cap); + if (u) + { + goto L1; + } + } newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; + L1: ; } } } @@ -670,21 +741,32 @@ extern (C) Array _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) { - auto size = ti.next.tsize(); // array element size - size_t cap = _gc.capacity(px.data); - size_t length = px.length; - size_t newlength = length + y.length; - if (newlength * size > cap) + auto sizeelem = ti.next.tsize(); // array element size + auto cap = _gc.capacity(px.data); + auto length = px.length; + auto newlength = length + y.length; + auto newsize = newlength * sizeelem; + if (newsize > cap) { byte* newdata; - newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1); + if (cap >= 4096) + { // Try to extend in-place + auto u = _gc.extend(px.data, (newsize + 1) - cap, (newsize + 1) - cap); + if (u) + { + goto L1; + } + } + + newdata = cast(byte *)_gc.malloc(newCapacity(newlength, sizeelem) + 1); if (!(ti.next.flags() & 1)) _gc.hasNoPointers(newdata); - memcpy(newdata, px.data, length * size); + memcpy(newdata, px.data, length * sizeelem); px.data = newdata; } + L1: px.length = newlength; - memcpy(px.data + length * size, y.ptr, y.length * size); + memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); return *px; } @@ -702,7 +784,7 @@ * space for larger arrays. * - Arrays smaller than 4096 bytes are left as-is, so for the most * common cases, memory allocation is 1 to 1. The small overhead added - * doesn't effect small array perf. (it's virutally the same as + * doesn't effect small array perf. (it's virtually the same as * current). * - Larger arrays have some space pre-allocated. * - As the arrays grow, the relative pre-allocated space shrinks. @@ -756,34 +838,45 @@ } extern (C) -byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, void *argp) +byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, byte *argp) { - auto size = ti.next.tsize(); // array element size - size_t cap = _gc.capacity(x.ptr); - size_t length = x.length; - size_t newlength = length + 1; + auto sizeelem = ti.next.tsize(); // array element size + auto cap = _gc.capacity(x.ptr); + auto length = x.length; + auto newlength = length + 1; + auto newsize = newlength * sizeelem; - assert(cap == 0 || length * size <= cap); + assert(cap == 0 || length * sizeelem <= cap); - //printf("_d_arrayappendc(size = %d, ptr = %p, length = %d, cap = %d)\n", size, x.ptr, x.length, cap); + //printf("_d_arrayappendc(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, cap); - if (newlength * size >= cap) + if (newsize >= cap) { byte* newdata; - //printf("_d_arrayappendc(size = %d, newlength = %d, cap = %d)\n", size, newlength, cap); - cap = newCapacity(newlength, size); - assert(cap >= newlength * size); + if (cap >= 4096) + { // Try to extend in-place + auto u = _gc.extend(x.ptr, (newsize + 1) - cap, (newsize + 1) - cap); + if (u) + { + goto L1; + } + } + + //printf("_d_arrayappendc(sizeelem = %d, newlength = %d, cap = %d)\n", sizeelem, newlength, cap); + cap = newCapacity(newlength, sizeelem); + assert(cap >= newlength * sizeelem); newdata = cast(byte *)_gc.malloc(cap + 1); if (!(ti.next.flags() & 1)) _gc.hasNoPointers(newdata); - memcpy(newdata, x.ptr, length * size); + memcpy(newdata, x.ptr, length * sizeelem); (cast(void **)(&x))[1] = newdata; } + L1: *cast(size_t *)&x = newlength; - (cast(byte *)x)[length * size .. newlength * size] = (cast(byte*)argp)[0 .. size]; + x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem]; assert((cast(size_t)x.ptr & 15) == 0); - assert(_gc.capacity(x.ptr) > x.length * size); + assert(_gc.capacity(x.ptr) >= x.length * sizeelem); return x; } @@ -791,16 +884,16 @@ byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) out (result) { - auto size = ti.next.tsize(); // array element size - //printf("_d_arraycatT(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); + auto sizeelem = ti.next.tsize(); // array element size + //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr); assert(result.length == x.length + y.length); - for (size_t i = 0; i < x.length * size; i++) + for (size_t i = 0; i < x.length * sizeelem; i++) assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); - for (size_t i = 0; i < y.length * size; i++) - assert((cast(byte*)result)[x.length * size + i] == (cast(byte*)y)[i]); + for (size_t i = 0; i < y.length * sizeelem; i++) + assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]); size_t cap = _gc.capacity(result.ptr); - assert(!cap || cap > result.length * size); + assert(!cap || cap > result.length * sizeelem); } body { @@ -820,10 +913,10 @@ } //printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); - auto size = ti.next.tsize(); // array element size - //printf("_d_arraycatT(%d,%p ~ %d,%p size = %d)\n", x.length, x.ptr, y.length, y.ptr, size); - size_t xlen = x.length * size; - size_t ylen = y.length * size; + auto sizeelem = ti.next.tsize(); // array element size + //printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem); + size_t xlen = x.length * sizeelem; + size_t ylen = y.length * sizeelem; size_t len = xlen + ylen; if (!len) return null; @@ -841,13 +934,13 @@ extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) -{ byte[] a; +{ void* a; size_t length; byte[]* p; uint i; byte[] b; va_list va; - auto size = ti.next.tsize(); // array element size + auto sizeelem = ti.next.tsize(); // array element size va_start!(typeof(n))(va, n); @@ -859,9 +952,9 @@ if (!length) return null; - a = new byte[length * size]; + a = _gc.malloc(length * sizeelem); if (!(ti.next.flags() & 1)) - _gc.hasNoPointers(a.ptr); + _gc.hasNoPointers(a); va_start!(typeof(n))(va, n); uint j = 0; @@ -870,56 +963,53 @@ b = va_arg!(typeof(b))(va); if (b.length) { - memcpy(&a[j], b.ptr, b.length * size); - j += b.length * size; + memcpy(a + j, b.ptr, b.length * sizeelem); + j += b.length * sizeelem; } } - *cast(size_t *)&a = length; // jam length - //a.length = length; - return a; + return (cast(byte*)a)[0..length]; } version (GNU) { } else extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) { - auto size = ti.next.tsize(); // array element size - void[] result; + auto sizeelem = ti.next.tsize(); // array element size + void* result; - //printf("_d_arrayliteralT(size = %d, length = %d)\n", size, length); - if (length == 0 || size == 0) + //printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length); + if (length == 0 || sizeelem == 0) result = null; else { - result = new void[length * size]; + result = _gc.malloc(length * sizeelem); if (!(ti.next.flags() & 1)) { - _gc.hasNoPointers(result.ptr); + _gc.hasNoPointers(result); } - *cast(size_t *)&result = length; // jam length va_list q; va_start!(size_t)(q, length); - size_t stacksize = (size + int.sizeof - 1) & ~(int.sizeof - 1); + size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); - if (stacksize == size) + if (stacksize == sizeelem) { - memcpy(result.ptr, q, length * size); + memcpy(result, q, length * sizeelem); } else { for (size_t i = 0; i < length; i++) { - memcpy(result.ptr + i * size, q, size); + memcpy(result + i * sizeelem, q, sizeelem); q += stacksize; } } va_end(q); } - return result.ptr; + return result; } /********************************** @@ -936,8 +1026,8 @@ Array2 _adDupT(TypeInfo ti, Array2 a) out (result) { - auto szelem = ti.next.tsize(); // array element size - assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * szelem) == 0); + auto sizeelem = ti.next.tsize(); // array element size + assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * sizeelem) == 0); } body { @@ -945,9 +1035,9 @@ if (a.length) { - auto szelem = ti.next.tsize(); // array element size - auto size = a.length * szelem; - r.ptr = cast(void *) new void[size]; + auto sizeelem = ti.next.tsize(); // array element size + auto size = a.length * sizeelem; + r.ptr = _gc.malloc(size); if (!(ti.next.flags() & 1)) _gc.hasNoPointers(r.ptr); r.length = a.length; diff -uNr gdc-0.23/d/phobos/internal/gc/gcx.d gdc-0.24/d/phobos/internal/gc/gcx.d --- gdc-0.23/d/phobos/internal/gc/gcx.d 2007-03-04 15:45:52.000000000 +0100 +++ gdc-0.24/d/phobos/internal/gc/gcx.d 2007-07-23 02:23:26.000000000 +0200 @@ -124,17 +124,19 @@ if (!data) { data = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof); + if (!data && allocdim) + _d_OutOfMemory(); } else { Log *newdata; newdata = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof); - assert(newdata); + if (!newdata && allocdim) + _d_OutOfMemory(); memcpy(newdata, data, dim * Log.sizeof); std.c.stdlib.free(data); data = newdata; } - assert(!allocdim || data); } } @@ -198,6 +200,8 @@ { gcLock = GCLock.classinfo; gcx = cast(Gcx *)std.c.stdlib.calloc(1, Gcx.sizeof); + if (!gcx) + _d_OutOfMemory(); gcx.initialize(); version (Win32) { @@ -319,7 +323,7 @@ memset(p + size, 0, binsize[bin] - size); else // 'inline' memset - Dave Fladebo. - foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; } + //foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; } //debug(PRINTF) printf("\tmalloc => %x\n", p); debug (MEMSTOMP) memset(p, 0xF0, size); } @@ -355,6 +359,7 @@ void *realloc(void *p, size_t size) { + gcx.p_cache = null; if (!size) { if (p) { free(p); @@ -387,6 +392,53 @@ else { psize = gcx.findSize(p); // find allocated size + if (psize >= PAGESIZE && size >= PAGESIZE) + { + auto psz = psize / PAGESIZE; + auto newsz = (size + PAGESIZE - 1) / PAGESIZE; + if (newsz == psz) + return p; + + auto pool = gcx.findPool(p); + auto pagenum = (p - pool.baseAddr) / PAGESIZE; + + if (newsz < psz) + { // Shrink in place + synchronized (gcLock) + { + debug (MEMSTOMP) memset(p + size, 0xF2, psize - size); + pool.freePages(pagenum + newsz, psz - newsz); + } + return p; + } + else if (pagenum + newsz <= pool.npages) + { + // Attempt to expand in place + synchronized (gcLock) + { + for (size_t i = pagenum + psz; 1;) + { + if (i == pagenum + newsz) + { + debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize); + memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz); + return p; + } + if (i == pool.ncommitted) + { + auto u = pool.extendPages(pagenum + newsz - pool.ncommitted); + if (u == ~0u) + break; + i = pagenum + newsz; + continue; + } + if (pool.pagetable[i] != B_FREE) + break; + i++; + } + } + } + } if (psize < size || // if new size is bigger psize > size * 2) // or less than half { @@ -402,6 +454,66 @@ return p; } + /** + * Attempt to in-place enlarge the memory block pointed to by p + * by at least minbytes beyond its current capacity, + * up to a maximum of maxbytes. + * This does not attempt to move the memory block (like realloc() does). + * Returns: + * 0 if could not extend p, + * total size of entire memory block if successful. + */ + size_t extend(void* p, size_t minsize, size_t maxsize) + { + //debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize); + version (SENTINEL) + { + return 0; + } + auto psize = gcx.findSize(p); // find allocated size + if (psize < PAGESIZE) + return 0; // cannot extend buckets + + auto psz = psize / PAGESIZE; + auto minsz = (minsize + PAGESIZE - 1) / PAGESIZE; + auto maxsz = (maxsize + PAGESIZE - 1) / PAGESIZE; + + auto pool = gcx.findPool(p); + auto pagenum = (p - pool.baseAddr) / PAGESIZE; + + synchronized (gcLock) + { + size_t sz; + for (sz = 0; sz < maxsz; sz++) + { + auto i = pagenum + psz + sz; + if (i == pool.ncommitted) + break; + if (pool.pagetable[i] != B_FREE) + { if (sz < minsz) + return 0; + break; + } + } + if (sz >= minsz) + { + } + else if (pagenum + psz + sz == pool.ncommitted) + { + auto u = pool.extendPages(minsz - sz); + if (u == ~0u) + return 0; + sz = minsz; + } + else + return 0; + debug (MEMSTOMP) memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize); + memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz); + gcx.p_cache = null; + gcx.size_cache = 0; + return (psz + sz) * PAGESIZE; + } + } void free(void *p) { @@ -433,6 +545,7 @@ } } + gcx.p_cache = null; bin = cast(Bins)pool.pagetable[pagenum]; if (bin == B_PAGE) // if large alloc { int npages; @@ -483,7 +596,7 @@ } else { - if (p == gcx.p_cache) + if (p !is null && p == gcx.p_cache) return gcx.size_cache; size_t size = gcx.findSize(p); @@ -984,7 +1097,8 @@ void **newroots; newroots = cast(void **)std.c.stdlib.malloc(newdim * newroots[0].sizeof); - assert(newroots); + if (!newroots) + _d_OutOfMemory(); if (roots) { memcpy(newroots, roots, nroots * newroots[0].sizeof); std.c.stdlib.free(roots); @@ -1025,7 +1139,8 @@ Range *newranges; newranges = cast(Range *)std.c.stdlib.malloc(newdim * newranges[0].sizeof); - assert(newranges); + if (!newranges) + _d_OutOfMemory(); if (ranges) { memcpy(newranges, ranges, nranges * newranges[0].sizeof); std.c.stdlib.free(ranges); @@ -1252,7 +1367,7 @@ return p; Lnomemory: - assert(0); + _d_OutOfMemory(); return null; } @@ -1278,6 +1393,12 @@ // Minimum of POOLSIZE if (npages < POOLSIZE/PAGESIZE) npages = POOLSIZE/PAGESIZE; + else if (npages > POOLSIZE/PAGESIZE) + { // Give us 150% of requested size, so there's room to extend + auto n = npages + (npages >> 1); + if (n < size_t.max/PAGESIZE) + npages = n; + } // Allocate successively larger pools up to 8 megs if (npools) @@ -2046,6 +2167,8 @@ noptrs.alloc(poolsize / 16); pagetable = cast(ubyte*)std.c.stdlib.malloc(npages); + if (!pagetable) + _d_OutOfMemory(); memset(pagetable, B_UNCOMMITTED, npages); this.npages = npages; @@ -2132,6 +2255,17 @@ else n2 = n; } + return extendPages(n); + } + + /************************************** + * Extend Pool by n pages. + * Returns ~0u on failure. + */ + + uint extendPages(uint n) + { + //debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n); if (ncommitted + n <= npages) { uint tocommit; @@ -2144,7 +2278,7 @@ if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0) { memset(pagetable + ncommitted, B_FREE, tocommit); - i = ncommitted; + auto i = ncommitted; ncommitted += tocommit; while (i && pagetable[i - 1] == B_FREE) diff -uNr gdc-0.23/d/phobos/internal/gc/testgc.d gdc-0.24/d/phobos/internal/gc/testgc.d --- gdc-0.23/d/phobos/internal/gc/testgc.d 2006-12-09 17:40:20.000000000 +0100 +++ gdc-0.24/d/phobos/internal/gc/testgc.d 2007-04-28 18:45:43.000000000 +0200 @@ -472,6 +472,75 @@ /* ---------------------------- */ +void test6() +{ + printf("test6\n"); + + gc_t gc; + + gc = newGC(); + gc.initialize(); + + auto p = gc.malloc(4096); + assert(gc.capacity(p) == 4096); + memset(p, 3, 4096); + + auto q = gc.realloc(p, 4096*4); + assert(q == p); + assert(gc.capacity(p) == 4096*4); + memset(p, 4, 4096*4); + + q = gc.realloc(p, 4096*2); + assert(q == p); + assert(gc.capacity(p) == 4096*2); + memset(p, 5, 4096*2); + + q = gc.realloc(p, 4096*2 + 1000); + assert(q == p); + assert(gc.capacity(p) == 4096*3); + memset(p, 6, 4096*2 + 1000); + + q = gc.realloc(p, 4096*4); + assert(q == p); + assert(gc.capacity(p) == 4096*4); + memset(p, 7, 4096*4); + + q = gc.realloc(p, 0); + assert(q == null); + assert(gc.capacity(p) == 0); + + gc.fullCollect(); + deleteGC(gc); +} + +/* ---------------------------- */ + +void test7() +{ + printf("test7\n"); + + gc_t gc; + + gc = newGC(); + gc.initialize(); + + auto p = gc.malloc(4096); + assert(gc.capacity(p) == 4096); + memset(p, 3, 4096); + + auto q = gc.extend(p, 4096, 4096*2); + assert(q == 4096*2 || q == 4096*3); + + auto s = gc.malloc(4096); + q = gc.extend(p, 4096, 4096); + assert(q == 0); + + gc.fullCollect(); + deleteGC(gc); +} + +/* ---------------------------- */ + int main(char[][] args) { test1(); @@ -479,6 +548,8 @@ test3(); test4(); test5(); + test6(); + test7(); gc_t gc; diff -uNr gdc-0.23/d/phobos/internal/object.d gdc-0.24/d/phobos/internal/object.d --- gdc-0.23/d/phobos/internal/object.d 2007-03-04 15:48:12.000000000 +0100 +++ gdc-0.24/d/phobos/internal/object.d 2007-07-23 02:23:26.000000000 +0200 @@ -10,7 +10,7 @@ */ /* - * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -64,6 +64,10 @@ alias size_t hash_t; +alias char[] string; +alias wchar[] wstring; +alias dchar[] dstring; + extern (C) { /// C's printf function. int printf(char *, ...); @@ -73,6 +77,8 @@ void* calloc(size_t, size_t); void* realloc(void*, size_t); void free(void*); + + Object _d_newclass(ClassInfo ci); } /* ************************* @@ -202,6 +208,23 @@ } } } + + /****** + * Create instance of class specified by classname. + * The class must either have no constructors or have + * a default constructor. + * Returns: + * null if failed + */ + static Object factory(char[] classname) + { + auto ci = ClassInfo.find(classname); + if (ci) + { + return ci.create(); + } + return null; + } } extern (C) void _d_notify_release(Object o) @@ -241,6 +264,7 @@ ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' } +import std.moduleinit; /** * Runtime type information about a class. Can be retrieved for any class type * or instance by using the .classinfo property. @@ -261,8 +285,44 @@ // 1: // IUnknown // 2: // has no possible pointers into GC memory // 4: // has offTi[] member + // 8: // has constructors void *deallocator; OffsetTypeInfo[] offTi; + void function(Object) defaultConstructor; // default Constructor + + /************* + * Search all modules for ClassInfo corresponding to classname. + * Returns: null if not found + */ + static ClassInfo find(char[] classname) + { + foreach (m; ModuleInfo.modules()) + { + //writefln("module %s, %d", m.name, m.localClasses.length); + foreach (c; m.localClasses) + { + //writefln("\tclass %s", c.name); + if (c.name == classname) + return c; + } + } + return null; + } + + /******************** + * Create instance of Object represented by 'this'. + */ + Object create() + { + if (flags & 8 && !defaultConstructor) + return null; + Object o = _d_newclass(this); + if (flags & 8 && defaultConstructor) + { + defaultConstructor(o); + } + return o; + } } private import std.string; @@ -411,7 +471,12 @@ int compare(void *p1, void *p2) { - return *cast(void* *)p1 - *cast(void* *)p2; + if (*cast(void* *)p1 < *cast(void* *)p2) + return -1; + else if (*cast(void* *)p1 > *cast(void* *)p2) + return 1; + else + return 0; } size_t tsize() @@ -967,6 +1032,30 @@ } } +class TypeInfo_Const : TypeInfo +{ + char[] toString() { return "const " ~ base.toString(); } + + int opEquals(Object o) { return base.opEquals(o); } + hash_t getHash(void *p) { return base.getHash(p); } + int equals(void *p1, void *p2) { return base.equals(p1, p2); } + int compare(void *p1, void *p2) { return base.compare(p1, p2); } + size_t tsize() { return base.tsize(); } + void swap(void *p1, void *p2) { return base.swap(p1, p2); } + + TypeInfo next() { return base.next(); } + uint flags() { return base.flags(); } + void[] init() { return base.init(); } + + TypeInfo base; +} + +class TypeInfo_Invariant : TypeInfo_Const +{ + char[] toString() { return "invariant " ~ base.toString(); } +} + + /** * All recoverable exceptions should be derived from class Exception. */ diff -uNr gdc-0.23/d/phobos/internal/switch.d gdc-0.24/d/phobos/internal/switch.d --- gdc-0.23/d/phobos/internal/switch.d 2006-12-09 17:40:20.000000000 +0100 +++ gdc-0.24/d/phobos/internal/switch.d 2007-04-29 18:39:02.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -100,7 +100,7 @@ } body { - //printf("body _d_switch_string()\n"); + //printf("body _d_switch_string(%.*s)\n", ca); int low; int high; int mid; @@ -110,15 +110,16 @@ low = 0; high = table.length; - /* - // Print table - printf("ca[] = '%s'\n", (char *)ca); - for (mid = 0; mid < high; mid++) + version (none) { - pca = table[mid]; - printf("table[%d] = %d, '%s'\n", mid, pca.length, (char *)pca); + // Print table + printf("ca[] = '%s'\n", cast(char *)ca); + for (mid = 0; mid < high; mid++) + { + pca = table[mid]; + printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca); + } } - */ if (high && ca.length >= table[0].length && ca.length <= table[high - 1].length) @@ -137,7 +138,7 @@ c = ca.length - pca.length; if (c == 0) { - c = cast(byte)c1 - cast(byte)pca[0]; + c = cast(ubyte)c1 - cast(ubyte)pca[0]; if (c == 0) { c = memcmp(ca.ptr, pca.ptr, ca.length); diff -uNr gdc-0.23/d/phobos/linux.mak gdc-0.24/d/phobos/linux.mak --- gdc-0.23/d/phobos/linux.mak 2007-02-08 19:07:06.000000000 +0100 +++ gdc-0.24/d/phobos/linux.mak 2007-07-27 02:07:14.000000000 +0200 @@ -9,6 +9,8 @@ # make unittest # Build libphobos.a, build and run unit tests +LIB=libphobos.a + CFLAGS=-O -m32 #CFLAGS=-g -m32 @@ -36,11 +38,11 @@ test.o : test.d $(DMD) -c test -g -test : test.o libphobos.a - $(CC) -o $@ test.o libphobos.a -lpthread -lm -g +test : test.o $(LIB) + $(CC) -o $@ test.o $(LIB) -lpthread -lm -g -unittest : unittest.o libphobos.a - $(CC) -o $@ unittest.o libphobos.a -lpthread -lm -g +unittest : unittest.o $(LIB) + $(CC) -o $@ unittest.o $(LIB) -lpthread -lm -g unittest.o : unittest.d $(DMD) -c unittest @@ -58,7 +60,7 @@ socket.o socketstream.o stdarg.o stdio.o format.o \ perf.o openrj.o uni.o trace.o boxer.o \ demangle.o cover.o bitarray.o bind.o aApplyR.o \ - signals.o cpuid.o traits.o typetuple.o \ + signals.o cpuid.o traits.o typetuple.o loader.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 \ @@ -195,9 +197,9 @@ $(SRC_ZLIB) $(SRC_GC) -#libphobos.a : $(OBJS) internal/gc/dmgc.a linux.mak -libphobos.a : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) linux.mak - rm -f libphobos.a +#$(LIB) : $(OBJS) internal/gc/dmgc.a linux.mak +$(LIB) : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) linux.mak + rm -f $(LIB) ar -r $@ $(OBJS) $(ZLIB_OBJS) $(GC_OBJS) ########################################################### @@ -354,6 +356,9 @@ gc.o : std/gc.d $(DMD) -c $(DFLAGS) std/gc.d +loader.o : std/loader.d + $(DMD) -c $(DFLAGS) std/loader.d + math.o : std/math.d $(DMD) -c $(DFLAGS) std/math.d @@ -588,4 +593,4 @@ zip phobos $(ALLSRCS) linux.mak win32.mak phoboslicense.txt clean: - $(RM) libphobos.a $(OBJS) unittest unittest.o + $(RM) $(LIB) $(OBJS) unittest unittest.o diff -uNr gdc-0.23/d/phobos/Makefile.am gdc-0.24/d/phobos/Makefile.am --- gdc-0.23/d/phobos/Makefile.am 2007-03-06 05:11:55.000000000 +0100 +++ gdc-0.24/d/phobos/Makefile.am 2007-08-22 07:16:12.000000000 +0200 @@ -95,7 +95,8 @@ $(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 \ internal/dgccmain2.o internal/rundmain.o std/stdarg.o \ - std/signals.o std/cpuid.o std/traits.o std/typetuple.o std/bind.o + std/signals.o std/cpuid.o std/traits.o std/typetuple.o std/bind.o \ + gcc/builtins.o # This should not be linked into a shared library. CMAIN_OBJS=internal/cmain.o diff -uNr gdc-0.23/d/phobos/Makefile.in gdc-0.24/d/phobos/Makefile.in --- gdc-0.23/d/phobos/Makefile.in 2007-03-06 05:12:30.000000000 +0100 +++ gdc-0.24/d/phobos/Makefile.in 2007-08-22 07:16:23.000000000 +0200 @@ -126,6 +126,11 @@ DCFG_EXP2_LOG2 = @DCFG_EXP2_LOG2@ DCFG_FWIDE = @DCFG_FWIDE@ DCFG_GETPWNAM_R = @DCFG_GETPWNAM_R@ +DCFG_HAVE_FGETLINE = @DCFG_HAVE_FGETLINE@ +DCFG_HAVE_FGETLN = @DCFG_HAVE_FGETLN@ +DCFG_HAVE_GETDELIM = @DCFG_HAVE_GETDELIM@ +DCFG_HAVE_UNLOCKED_STDIO = @DCFG_HAVE_UNLOCKED_STDIO@ +DCFG_HAVE_UNLOCKED_WIDE_STDIO = @DCFG_HAVE_UNLOCKED_WIDE_STDIO@ DCFG_MMAP = @DCFG_MMAP@ DCFG_NAN = @DCFG_NAN@ DCFG_NEARBYINT = @DCFG_NEARBYINT@ @@ -260,7 +265,8 @@ $(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 \ internal/dgccmain2.o internal/rundmain.o std/stdarg.o \ - std/signals.o std/cpuid.o std/traits.o std/typetuple.o std/bind.o + std/signals.o std/cpuid.o std/traits.o std/typetuple.o std/bind.o \ + gcc/builtins.o # This should not be linked into a shared library. diff -uNr gdc-0.23/d/phobos/object.d gdc-0.24/d/phobos/object.d --- gdc-0.23/d/phobos/object.d 2007-02-13 14:37:13.000000000 +0100 +++ gdc-0.24/d/phobos/object.d 2007-07-23 02:23:26.000000000 +0200 @@ -10,6 +10,10 @@ alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; alias size_t hash_t; +alias char[] string; +alias wchar[] wstring; +alias dchar[] dstring; + extern (C) { int printf(char *, ...); } @@ -24,6 +28,8 @@ final void notifyRegister(void delegate(Object) dg); final void notifyUnRegister(void delegate(Object) dg); + + static Object factory(char[] classname); } struct Interface @@ -46,8 +52,13 @@ // 1: // IUnknown // 2: // has no possible pointers into GC memory // 4: // has offTi[] member + // 8: // has constructors void *deallocator; OffsetTypeInfo[] offTi; + void* defaultConstructor; // default Constructor + + static ClassInfo find(char[] classname); + Object create(); } struct OffsetTypeInfo @@ -141,6 +152,15 @@ TypeInfo[] elements; } +class TypeInfo_Const : TypeInfo +{ + TypeInfo next; +} + +class TypeInfo_Invariant : TypeInfo_Const +{ +} + // Recoverable errors class Exception : Object diff -uNr gdc-0.23/d/phobos/phobos-ver-syms.in gdc-0.24/d/phobos/phobos-ver-syms.in --- gdc-0.23/d/phobos/phobos-ver-syms.in 2006-06-03 04:57:27.000000000 +0200 +++ gdc-0.24/d/phobos/phobos-ver-syms.in 2007-04-28 18:45:43.000000000 +0200 @@ -9,7 +9,6 @@ @DCFG_EXP2_LOG2@ @DCFG_EXECVPE@ @DCFG_SPAWNVP@ -@DCFG_FWIDE@ @DCFG_STRTOLD@ @DCFG_SA_LEN@ @DCFG_CBRIDGE_STDIO@ diff -uNr gdc-0.23/d/phobos/std/bind.d gdc-0.24/d/phobos/std/bind.d --- gdc-0.23/d/phobos/std/bind.d 2006-12-04 03:33:54.000000000 +0100 +++ gdc-0.24/d/phobos/std/bind.d 2007-07-23 02:23:26.000000000 +0200 @@ -761,7 +761,7 @@ static if (is(T == void)) { // void means that we aren't adding anything alias tmp res; } else { - alias tmp.prependT!(T) res; + alias tmp.meta.prependT!(T) res; } } diff -uNr gdc-0.23/d/phobos/std/boxer.d gdc-0.24/d/phobos/std/boxer.d --- gdc-0.23/d/phobos/std/boxer.d 2006-12-09 17:52:48.000000000 +0100 +++ gdc-0.24/d/phobos/std/boxer.d 2007-07-13 17:30:19.000000000 +0200 @@ -294,7 +294,7 @@ version (GNU) { va_list dummy = void; - std.format.doFormat(&putc, arguments, dummy, args.ptr); + std.format.doFormatPtr(&putc, arguments, dummy, args.ptr); } else std.format.doFormat(&putc, arguments, args.ptr); diff -uNr gdc-0.23/d/phobos/std/c/dirent.d gdc-0.24/d/phobos/std/c/dirent.d --- gdc-0.23/d/phobos/std/c/dirent.d 2006-12-09 20:39:21.000000000 +0100 +++ gdc-0.24/d/phobos/std/c/dirent.d 2007-04-28 18:45:43.000000000 +0200 @@ -18,7 +18,6 @@ module std.c.dirent; -private import gcc.config; private import std.string; private import gcc.config; diff -uNr gdc-0.23/d/phobos/std/c/linux/linux.d.orig-dmd gdc-0.24/d/phobos/std/c/linux/linux.d.orig-dmd --- gdc-0.23/d/phobos/std/c/linux/linux.d.orig-dmd 2007-02-02 19:33:16.000000000 +0100 +++ gdc-0.24/d/phobos/std/c/linux/linux.d.orig-dmd 2007-04-28 18:45:43.000000000 +0200 @@ -20,6 +20,11 @@ alias uint uid_t; alias uint gid_t; +static if (size_t.sizeof == 4) + alias int ssize_t; +else + alias long ssize_t; + enum : int { SIGHUP = 1, diff -uNr gdc-0.23/d/phobos/std/c/locale.d gdc-0.24/d/phobos/std/c/locale.d --- gdc-0.23/d/phobos/std/c/locale.d 2006-11-12 20:01:14.000000000 +0100 +++ gdc-0.24/d/phobos/std/c/locale.d 2007-04-29 02:47:26.000000000 +0200 @@ -1,10 +1,10 @@ -/** +/** * C's <locale.h> * License: Public Domain * Standards: - * ISO/IEC 9899:1999 §7.11 + * ISO/IEC 9899:1999 7.11 * Macros: - * WIKI=Phobos/StdCCType + * WIKI=Phobos/StdCLocale */ module std.c.locale; @@ -26,8 +26,8 @@ char* grouping; /** The international currency symbol applicable to the current locale. - * The first three characters contain the alphabetic international - * currency symbol in accordance with those specified in ISO 4217. + * The first three characters contain the alphabetic international + * currency symbol in accordance with those specified in ISO 4217. * The fourth character (immediately preceding the null character) * is the character used to separate the international currency symbol * from the monetary quantity. @@ -135,11 +135,11 @@ **/ const LC_MONETARY = 4; -/// The program’s entire locale. +/// The program's entire locale. const LC_ALL = 6; /** The setlocale function selects the appropriate portion of the program's - * locale as specified by the category and locale arguments. + * locale as specified by the category and locale arguments. **/ char* setlocale(int category, char* locale); diff -uNr gdc-0.23/d/phobos/std/c/stdio.d gdc-0.24/d/phobos/std/c/stdio.d --- gdc-0.23/d/phobos/std/c/stdio.d 2007-02-26 15:01:16.000000000 +0100 +++ gdc-0.24/d/phobos/std/c/stdio.d 2007-04-28 18:45:43.000000000 +0200 @@ -125,6 +125,16 @@ } else { extern FILE _iob[_NFILE]; extern void function() _fcloseallp; + extern ubyte __fhnd_info[_NFILE]; + + enum + { + FHND_APPEND = 0x04, + FHND_DEVICE = 0x08, + FHND_TEXT = 0x10, + FHND_BYTE = 0x20, + FHND_WCHAR = 0x40, + } } } diff -uNr gdc-0.23/d/phobos/std/c/unix/unix.d gdc-0.24/d/phobos/std/c/unix/unix.d --- gdc-0.23/d/phobos/std/c/unix/unix.d 2006-07-22 16:36:37.000000000 +0200 +++ gdc-0.24/d/phobos/std/c/unix/unix.d 2007-04-28 18:45:43.000000000 +0200 @@ -26,3 +26,8 @@ // DMD linux.d has dirent.h declarations public import std.c.dirent; +int dirfd(DIR*); + +public import std.c.stdio; +int fseeko(FILE*, off_t, int); +off_t ftello(FILE*); diff -uNr gdc-0.23/d/phobos/std/compiler.d gdc-0.24/d/phobos/std/compiler.d --- gdc-0.23/d/phobos/std/compiler.d 2007-02-02 19:33:27.000000000 +0100 +++ gdc-0.24/d/phobos/std/compiler.d 2007-07-23 02:23:26.000000000 +0200 @@ -16,7 +16,7 @@ const { /// Vendor specific string naming the compiler, for example: "Digital Mars D". - char[] name = "Digital Mars D"; + string name = __VENDOR__; /// Master list of D compiler vendors. enum Vendor @@ -32,8 +32,8 @@ * The vendor specific version number, as in * version_major.version_minor */ - uint version_major = 1; - uint version_minor = 002; /// ditto + uint version_major = __VERSION__ / 1000; + uint version_minor = __VERSION__ % 1000; /// ditto /** diff -uNr gdc-0.23/d/phobos/std/date.d gdc-0.24/d/phobos/std/date.d --- gdc-0.23/d/phobos/std/date.d 2007-03-02 18:17:02.000000000 +0100 +++ gdc-0.24/d/phobos/std/date.d 2007-07-23 02:23:26.000000000 +0200 @@ -400,7 +400,9 @@ d_time UTCtoLocalTime(d_time t) { - return t + LocalTZA + DaylightSavingTA(t); + return (t == d_time_nan) + ? d_time_nan + : t + LocalTZA + DaylightSavingTA(t); } /*********************************** @@ -409,7 +411,9 @@ d_time LocalTimetoUTC(d_time t) { - return t - LocalTZA - DaylightSavingTA(t - LocalTZA); + return (t == d_time_nan) + ? d_time_nan + : t - LocalTZA - DaylightSavingTA(t - LocalTZA); } @@ -662,7 +666,7 @@ //writefln("weekday = %d, ampm = %d, tzcorrection = %d", dp.weekday, 1, dp.tzcorrection); time = MakeTime(dp.hour, dp.minute, dp.second, dp.ms); - if (dp.tzcorrection == Date.tzcorrection.init) + if (dp.tzcorrection == int.min) time -= LocalTZA; else { @@ -765,6 +769,7 @@ { case TIME_ZONE_ID_STANDARD: case TIME_ZONE_ID_DAYLIGHT: + case TIME_ZONE_ID_UNKNOWN: //printf("bias = %d\n", tzi.Bias); //printf("standardbias = %d\n", tzi.StandardBias); //printf("daylightbias = %d\n", tzi.DaylightBias); diff -uNr gdc-0.23/d/phobos/std/dateparse.d gdc-0.24/d/phobos/std/dateparse.d --- gdc-0.23/d/phobos/std/dateparse.d 2007-03-04 15:50:21.000000000 +0100 +++ gdc-0.24/d/phobos/std/dateparse.d 2007-07-23 02:23:26.000000000 +0200 @@ -76,7 +76,7 @@ (hours < 0 || hours > 23) || (minutes < 0 || minutes > 59) || (seconds < 0 || seconds > 59) || - (tzcorrection != tzcorrection.init && + (tzcorrection != int.min && ((tzcorrection < -2300 || tzcorrection > 2300) || (tzcorrection % 10))) ) diff -uNr gdc-0.23/d/phobos/std/demangle.d gdc-0.24/d/phobos/std/demangle.d --- gdc-0.23/d/phobos/std/demangle.d 2007-03-04 15:50:25.000000000 +0100 +++ gdc-0.24/d/phobos/std/demangle.d 2007-07-27 02:07:14.000000000 +0200 @@ -1,4 +1,3 @@ - // Written in the D programming language. /* @@ -19,6 +18,7 @@ /* Authors: * Walter Bright, Digital Mars, www.digitalmars.com * Thomas Kuehne + * Frits van Bommel */ module std.demangle; @@ -85,10 +85,10 @@ ------------------- */ -char[] demangle(char[] name) +string demangle(string name) { size_t ni = 2; - char[] delegate() fparseTemplateInstanceName; + string delegate() fparseTemplateInstanceName; static void error() { @@ -102,7 +102,7 @@ error(); return cast(ubyte) ( (c >= 'a') ? c - 'a' + 10 : - (c >= 'A') ? c - 'A' + 10 : + (c >= 'A') ? c - 'A' + 10 : c - '0' ); } @@ -122,13 +122,13 @@ return result; } - char[] parseSymbolName() + string parseSymbolName() { //writefln("parseSymbolName() %d", ni); size_t i = parseNumber(); if (ni + i > name.length) error(); - char[] result; + string result; if (i >= 5 && name[ni] == '_' && name[ni + 1] == '_' && @@ -159,10 +159,10 @@ return result; } - char[] parseQualifiedName() + string parseQualifiedName() { //writefln("parseQualifiedName() %d", ni); - char[] result; + string result; while (ni < name.length && isdigit(name[ni])) { @@ -173,19 +173,19 @@ return result; } - char[] parseType(char[] identifier = null) + string parseType(string identifier = null) { //writefln("parseType() %d", ni); int isdelegate = 0; + bool hasthisptr = false; /// For function/delegate types: expects a 'this' pointer as last argument Lagain: if (ni >= name.length) error(); - char[] p; + string p; switch (name[ni++]) { case 'v': p = "void"; goto L1; - case 'b': p = "bit"; goto L1; - case 'x': p = "bool"; goto L1; + case 'b': p = "bool"; goto L1; case 'g': p = "byte"; goto L1; case 'h': p = "ubyte"; goto L1; case 's': p = "short"; goto L1; @@ -232,13 +232,17 @@ isdelegate = 1; goto Lagain; + case 'M': + hasthisptr = true; + goto Lagain; + case 'F': // D function case 'U': // C function case 'W': // Windows function case 'V': // Pascal function case 'R': // C++ function { char mc = name[ni - 1]; - char[] args; + string args; while (1) { @@ -249,7 +253,8 @@ break; if (c == 'X') { - args ~= " ..."; + if (!args.length) error(); + args ~= " ..."; break; } if (args.length) @@ -281,6 +286,12 @@ } break; } + if (hasthisptr || isdelegate) { + // add implicit 'this'/context pointer + if (args.length) + args ~= ", "; + args ~= "void*"; + } ni++; if (!isdelegate && identifier.length) { @@ -327,9 +338,9 @@ assert(0); } - char[] parseTemplateInstanceName() + string parseTemplateInstanceName() { - char[] result = parseSymbolName() ~ "!("; + auto result = parseSymbolName() ~ "!("; int nargs; while (1) @@ -419,9 +430,8 @@ for (i = 0; i < n; i++) { char c; - c = cast(char) - ((ascii2hex(name[ni + i * 2]) << 4) + - ascii2hex(name[ni + i * 2 + 1])); + c = (ascii2hex(name[ni + i * 2]) << 4) + + ascii2hex(name[ni + i * 2 + 1]); result ~= c; } ni += n * 2; @@ -464,8 +474,12 @@ try { - char[] result = parseQualifiedName(); + auto result = parseQualifiedName(); result = parseType(result); + while(ni < name.length){ + result ~= " . " ~ parseType(parseQualifiedName()); + } + if (ni != name.length) goto Lnot; return result; @@ -484,7 +498,7 @@ { debug(demangle) printf("demangle.demangle.unittest\n"); - static char[][2][] table = + static string[2][] table = [ [ "printf", "printf" ], [ "_foo", "_foo" ], @@ -501,16 +515,22 @@ [ "_D8demangle4testFLAiXi", "int demangle.test(lazy int[] ...)"] ]; - foreach (uint i, char[][2] name; table) + foreach (int i, string[2] name; table) { + // Bugzilla 1377 workaround + if (i == 6 || i == 10) + continue; + static if (real.sizeof != 10) { if (i == 7 || i == 8) continue; } - char[] r = demangle(name[0]); - //writefln("[ \"%s\", \"%s\" ],", name[0], r); + string r = demangle(name[0]); + writefln("%d, [ \"%s\", \"%s\" ],", i, name[0], r); assert(r == name[1]); } } + + diff -uNr gdc-0.23/d/phobos/std/file.d gdc-0.24/d/phobos/std/file.d --- gdc-0.23/d/phobos/std/file.d 2007-03-04 15:51:03.000000000 +0100 +++ gdc-0.24/d/phobos/std/file.d 2007-04-29 18:39:02.000000000 +0200 @@ -123,8 +123,8 @@ if (size == INVALID_FILE_SIZE) goto err2; - auto buf = new void[size]; - if (buf.ptr) + auto buf = std.gc.malloc(size); + if (buf) std.gc.hasNoPointers(buf.ptr); if (ReadFile(h,buf.ptr,size,&numread,null) != 1) @@ -136,7 +136,7 @@ if (!CloseHandle(h)) goto err; - return buf; + return buf[0 .. size]; err2: CloseHandle(h); @@ -912,11 +912,11 @@ if (size > size_t.max) goto err2; - auto buf = new void[size]; + auto buf = std.gc.malloc(size); if (buf.ptr) std.gc.hasNoPointers(buf.ptr); - numread = unix.read(fd, cast(char*)buf, size); + numread = unix.read(fd, buf.ptr, size); if (numread != size) { //printf("\tread error, errno = %d\n",getErrno()); @@ -929,7 +929,7 @@ goto err; } - return buf; + return buf[0 .. size]; err2: unix.close(fd); @@ -1464,7 +1464,7 @@ goto err2; } - size_t BUFSIZ = 4069 * 16; + size_t BUFSIZ = 4096 * 16; void* buf = std.c.stdlib.malloc(BUFSIZ); if (!buf) { BUFSIZ = 4096; diff -uNr gdc-0.23/d/phobos/std/format.d gdc-0.24/d/phobos/std/format.d --- gdc-0.23/d/phobos/std/format.d 2007-03-04 15:51:34.000000000 +0100 +++ gdc-0.24/d/phobos/std/format.d 2007-07-27 02:07:14.000000000 +0200 @@ -1,3 +1,6 @@ + +// Written in the D programming language. + /** * This module implements the workhorse functionality for string and I/O formatting. * It's comparable to C99's vsprintf(). @@ -124,6 +127,9 @@ Tenum = 'E', Ttypedef = 'T', Tdelegate = 'D', + + Tconst = 'x', + Tinvariant = 'y', } // return the TypeInfo for a primitive type and null otherwise. @@ -446,8 +452,13 @@ ------------------------ */ -void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr, - void * p_args = null) +void doFormat(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr) +{ + doFormatPtr(putc, arguments, argptr, null); +} + +void doFormatPtr(void delegate(dchar) putc, TypeInfo[] arguments, va_list argptr, + void * p_args) { int j; TypeInfo ti; Mangle m; @@ -610,14 +621,26 @@ return; } + static Mangle getMan(TypeInfo ti) + { + auto m = cast(Mangle)ti.classinfo.name[9]; + if (ti.classinfo.name.length == 20 && + ti.classinfo.name[9..20] == "StaticArray") + m = cast(Mangle)'G'; + return m; + } + void putArray(void* p, size_t len, TypeInfo valti) { + //printf("\nputArray(len = %u), tsize = %u\n", len, valti.tsize()); putc('['); size_t tsize = valti.tsize(); auto argptrSave = p_args; auto tiSave = ti; + auto mSave = m; ti = valti; - m = cast(Mangle)valti.classinfo.name[9]; + //printf("\n%.*s\n", valti.classinfo.name); + m = getMan(valti); while (len--) { //doFormat(putc, (&valti)[0 .. 1], p); @@ -627,6 +650,7 @@ p += tsize; if (len > 0) putc(','); } + m = mSave; ti = tiSave; p_args = argptrSave; putc(']'); @@ -645,6 +669,7 @@ bool comma=false; auto argptrSave = p_args; auto tiSave = ti; + auto mSave = m; foreach(inout fakevalue; vaa) { if (comma) putc(','); @@ -655,7 +680,7 @@ //doFormat(putc, (&keyti)[0..1], key); p_args = key; ti = keyti; - m = cast(Mangle)keyti.classinfo.name[9]; + m = getMan(keyti); formatArg('s'); putc(':'); @@ -663,9 +688,10 @@ //doFormat(putc, (&valti)[0..1], value); p_args = value; ti = valti; - m = cast(Mangle)valti.classinfo.name[9]; + m = getMan(valti); formatArg('s'); } + m = mSave; ti = tiSave; p_args = argptrSave; putc(']'); @@ -818,6 +844,13 @@ vcreal = va_arg!(creal)(argptr); goto Lcomplex; + case Mangle.Tsarray: + /* Static arrays are converted to dynamic arrays when + passed as a variadic argument, so this code should + never be executed with GDC. The case of an + embedded static array is handled below. */ + goto Lerror; + case Mangle.Tarray: if (ti.classinfo.name.length == 14 && ti.classinfo.name[9..14] == "Array") @@ -882,6 +915,8 @@ case Mangle.Tstruct: { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; + if (tis.xtoString is null) + throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); static if ( is( typeof(argptr): void[] ) || @@ -1049,6 +1084,11 @@ vcreal = *cast(creal*)p_args; p_args += creal.sizeof; goto Lcomplex; + case Mangle.Tsarray: + putArray(p_args, (cast(TypeInfo_StaticArray)ti).len, (cast(TypeInfo_StaticArray)ti).next); + p_args += ti.tsize(); + return; + case Mangle.Tarray: alias void[] array_t; if (ti.classinfo.name.length == 14 && @@ -1114,6 +1154,8 @@ case Mangle.Tstruct: { TypeInfo_Struct tis = cast(TypeInfo_Struct)ti; + if (tis.xtoString is null) + throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined"); s = tis.xtoString(p_args); p_args += tis.tsize(); goto Lputstr; @@ -1255,6 +1297,11 @@ { ti = arguments[j++]; //printf("test1: '%.*s' %d\n", ti.classinfo.name, ti.classinfo.name.length); //ti.print(); + + flags = 0; + precision = 0; + field_width = 0; + if (ti.classinfo.name.length < 10) goto Lerror; m = cast(Mangle)ti.classinfo.name[9]; @@ -1262,9 +1309,9 @@ if (m == Mangle.Tarray) { Mangle m2 = cast(Mangle)ti.classinfo.name[10]; - char[] fmt; // format string - wchar[] wfmt; - dchar[] dfmt; + string fmt; // format string + wstring wfmt; + dstring dfmt; /* For performance reasons, this code takes advantage of the * fact that most format strings will be ASCII, and that the @@ -1447,9 +1494,6 @@ } else { - field_width = 0; - flags = 0; - precision = 0; formatArg('s'); } } @@ -1464,10 +1508,11 @@ version (skyos) version = no_hexfloat; +import std.stdio;//xx unittest { int i; - char[] s; + string s; debug(format) printf("std.format.format.unittest\n"); @@ -1559,7 +1604,7 @@ assert(s == "0.00001000"); s = "helloworld"; - char[] r; + string r; r = std.string.format("%.2s", s[0..5]); assert(r == "he"); r = std.string.format("%.20s", s[0..5]); @@ -1622,7 +1667,7 @@ r = std.string.format(arrulong); assert(r == "[100,999,0,0]"); - char[][] arr2 = new char[][4]; + string[] arr2 = new char[][4]; arr2[0] = "hello"; arr2[1] = "world"; arr2[3] = "foo"; @@ -1738,5 +1783,16 @@ } r = std.string.format("%s", TestEnum.Value2); assert(r == "1"); + + char[5][int] aa = ([3:"hello", 4:"betty"]); + r = std.string.format("%s", aa.values); + writefln(aa); + assert(r == "[[h,e,l,l,o],[b,e,t,t,y]]"); + r = std.string.format("%s", aa); + writefln(aa); + assert(r == "[3:[h,e,l,l,o],4:[b,e,t,t,y]]"); + + r = std.string.format(">%14d<, ", 15, [1,2,3]); + assert(r == "> 15<, [1,2,3]"); } diff -uNr gdc-0.23/d/phobos/std/gc.d gdc-0.24/d/phobos/std/gc.d --- gdc-0.23/d/phobos/std/gc.d 2007-02-02 19:43:55.000000000 +0100 +++ gdc-0.24/d/phobos/std/gc.d 2007-04-28 18:45:43.000000000 +0200 @@ -76,6 +76,46 @@ void setTypeInfo(TypeInfo ti, void* p); /** + * Allocate nbytes of uninitialized data. + * The allocated memory will be scanned for pointers during + * a gc collection cycle, unless + * it is followed by a call to hasNoPointers(). + */ +void[] malloc(size_t nbytes); + +/** + * Resize allocated memory block pointed to by p to be at least nbytes long. + * It will try to resize the memory block in place. + * If nbytes is 0, the memory block is free'd. + * If p is null, the memory block is allocated using malloc. + * The returned array may not be at the same location as the original + * memory block. + * The allocated memory will be scanned for pointers during + * a gc collection cycle, unless + * it is followed by a call to hasNoPointers(). + */ +void[] realloc(void* p, size_t nbytes); + +/** + * Attempt to enlarge the memory block pointed to by p + * by at least minbytes beyond its current capacity, + * up to a maximum of maxbytes. + * Returns: + * 0 if could not extend p, + * total size of entire memory block if successful. + */ +size_t extend(void* p, size_t minbytes, size_t maxbytes); + +/** + * Returns capacity (size of the memory block) that p + * points to the beginning of. + * If p does not point into the gc memory pool, or does + * not point to the beginning of an allocated memory block, + * 0 is returned. + */ +size_t capacity(void* p); + +/** * Set gc behavior to match that of 1.0. */ void setV1_0(); diff -uNr gdc-0.23/d/phobos/std/intrinsic.d gdc-0.24/d/phobos/std/intrinsic.d --- gdc-0.23/d/phobos/std/intrinsic.d 2006-06-03 04:57:13.000000000 +0200 +++ gdc-0.24/d/phobos/std/intrinsic.d 2007-07-23 02:23:26.000000000 +0200 @@ -55,6 +55,7 @@ * The return value is undefined if v is zero. * Example: * --- + * import std.stdio; * import std.intrinsic; * * int main() @@ -64,9 +65,9 @@ * * v = 0x21; * x = bsf(v); - * printf("bsf(x%x) = %d\n", v, x); + * writefln("bsf(x%x) = %d", v, x); * x = bsr(v); - * printf("bsr(x%x) = %d\n", v, x); + * writefln("bsr(x%x) = %d", v, x); * return 0; * } * --- @@ -144,6 +145,7 @@ * * Example: * --- +import std.stdio; import std.intrinsic; int main() @@ -153,20 +155,20 @@ array[0] = 2; array[1] = 0x100; - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); + writefln("btc(array, 35) = %d", btc(array, 35)); + writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); - printf("btc(array, 35) = %d\n", btc(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); + writefln("btc(array, 35) = %d", btc(array, 35)); + writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); - printf("bts(array, 35) = %d\n", bts(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); + writefln("bts(array, 35) = %d", bts(array, 35)); + writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); - printf("btr(array, 35) = %d\n", btr(array, 35)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); + writefln("btr(array, 35) = %d", btr(array, 35)); + writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); - printf("bt(array, 1) = %d\n", bt(array, 1)); - printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); + writefln("bt(array, 1) = %d", bt(array, 1)); + writefln("array = [0]:x%x, [1]:x%x", array[0], array[1]); return 0; } diff -uNr gdc-0.23/d/phobos/std/loader.d gdc-0.24/d/phobos/std/loader.d --- gdc-0.23/d/phobos/std/loader.d 2007-02-28 19:41:31.000000000 +0100 +++ gdc-0.24/d/phobos/std/loader.d 2007-07-27 02:07:14.000000000 +0200 @@ -1,3 +1,6 @@ + +// Written in the D programming language. + /* ///////////////////////////////////////////////////////////////////////////// * File: loader.d (originally from synsoft.win32.loader) * @@ -8,45 +11,26 @@ * * Author: Matthew Wilson * - * License: - * - * Copyright (C) 2002-2004, Synesis Software Pty Ltd. - * - * All rights reserved. + * Copyright 2004-2005 by Matthew Wilson and Synesis Software + * Written by Matthew Wilson * - * www: http://www.synesis.com.au/software - * http://www.synsoft.org/ + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. * - * email: submissions@synsoft.org for submissions - * admin@synsoft.org for other enquiries + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, in both source and binary form, subject to the following - * restrictions: - * - * - The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - This notice may not be removed or altered from any source - * distribution. - * - * This source code is provided by Synesis Software "as is" and any - * warranties, whether expressed or implied, including, but not - * limited to, the implied warranties of merchantability and - * fitness for a particular purpose are disclaimed. In no event - * shall the Synesis Software be liable for any direct, indirect, - * incidental, special, exemplary, or consequential damages - * (including, but not limited to, procurement of substitute goods - * or services; loss of use, data, or profits; or business - * interruption) however caused and on any theory of liability, - * whether in contract, strict liability, or tort (including - * negligence or otherwise) arising in any way out of the use of - * this software, even if advised of the possibility of such - * damage. + * - The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * - Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * - This notice may not be removed or altered from any source + * distribution. * * ////////////////////////////////////////////////////////////////////////// */ @@ -125,18 +109,11 @@ } else version(dlopen) { + private import std.c.linux.linux; + extern(C) { - const int RTLD_NOW = 0x00002; /* Correct for Red Hat 8 */ - - typedef void *HModule_; - - HModule_ dlopen(char *path, int mode); - int dlclose(HModule_ handle); - void *dlsym(HModule_ handle, char *symbolName); - char *dlerror(); - - char* strerror(int); + alias void* HModule_; } } else version(darwin) @@ -286,12 +263,12 @@ * system, and you must not attempt to use it with any other operating system * or other APIs. It is only valid for use with the ExeModule library. */ -public HXModule ExeModule_Load(in char[] moduleName) +public HXModule ExeModule_Load(in string moduleName) { return ExeModule_Load_(moduleName); } -public HXModule ExeModule_AddRef(in HXModule hModule) +public HXModule ExeModule_AddRef(HXModule hModule) { return ExeModule_AddRef_(hModule); } @@ -305,12 +282,12 @@ ExeModule_Release_(hModule); } -public void *ExeModule_GetSymbol(inout HXModule hModule, in char[] symbolName) +public void *ExeModule_GetSymbol(inout HXModule hModule, in string symbolName) { return ExeModule_GetSymbol_(hModule, symbolName); } -public char[] ExeModule_Error() +public string ExeModule_Error() { return ExeModule_Error_(); } @@ -337,7 +314,7 @@ --s_init; } - private HXModule ExeModule_Load_(in char[] moduleName) + private HXModule ExeModule_Load_(in string moduleName) in { assert(null !is moduleName); @@ -354,7 +331,7 @@ return hmod; } - private HXModule ExeModule_AddRef_(in HXModule hModule) + private HXModule ExeModule_AddRef_(HXModule hModule) in { assert(null !is hModule); @@ -378,7 +355,7 @@ hModule = null; } - private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) + private void *ExeModule_GetSymbol_(inout HXModule hModule, in string symbolName) in { assert(null !is hModule); @@ -395,12 +372,12 @@ return symbol; } - private char[] ExeModule_Error_() + private string ExeModule_Error_() { return sysErrorString(s_lastError); } - private char[] ExeModule_GetPath_(HXModule hModule) + private string ExeModule_GetPath_(HXModule hModule) { char szFileName[260]; // Need to use a constant here @@ -421,9 +398,9 @@ public: int m_cRefs; HModule_ m_hmod; - char[] m_name; + string m_name; - this(HModule_ hmod, char[] name) + this(HModule_ hmod, string name) { m_cRefs = 1; m_hmod = hmod; @@ -432,8 +409,8 @@ }; private int s_init; - private ExeModuleInfo [char[]] s_modules; - private char[] s_lastError; // This is NOT thread-specific + private ExeModuleInfo [string] s_modules; + private string s_lastError; // This is NOT thread-specific private void record_error_() { @@ -466,11 +443,12 @@ } body { - ExeModuleInfo *p_mi = moduleName in s_modules; + ExeModuleInfo* mi_p = moduleName in s_modules; + ExeModuleInfo mi = mi_p is null ? null : *mi_p; - if(p_mi != null) + if(null !is mi) { - return (++(*p_mi).m_cRefs, cast(HXModule)*p_mi); + return (++mi.m_cRefs, cast(HXModule)mi); } else { @@ -484,16 +462,16 @@ } else { - ExeModuleInfo mi = new ExeModuleInfo(hmod, moduleName); + ExeModuleInfo mi2 = new ExeModuleInfo(hmod, moduleName); - s_modules[moduleName] = mi; + s_modules[moduleName] = mi2; - return cast(HXModule)mi; + return cast(HXModule)mi2; } } } - private HXModule ExeModule_AddRef_(in HXModule hModule) + private HXModule ExeModule_AddRef_(HXModule hModule) in { assert(null !is hModule); @@ -539,7 +517,7 @@ if(0 == --mi.m_cRefs) { - char[] name = mi.m_name; + string name = mi.m_name; if (dlclose(mi.m_hmod)) { @@ -552,7 +530,7 @@ hModule = null; } - private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) + private void *ExeModule_GetSymbol_(inout HXModule hModule, in string symbolName) in { assert(null !is hModule); @@ -578,12 +556,12 @@ return symbol; } - private char[] ExeModule_Error_() + private string ExeModule_Error_() { return s_lastError; } - private char[] ExeModule_GetPath_(HXModule hModule) + private string ExeModule_GetPath_(HXModule hModule) in { assert(null !is hModule); @@ -873,7 +851,7 @@ : Exception { public: - this(char[] message) + this(string message) { super(message); } @@ -891,7 +869,7 @@ /// @{ public: /// Constructs from an existing image handle - this(in HXModule hModule, boolean bTakeOwnership) + this(HXModule hModule, boolean bTakeOwnership) in { assert(null !is hModule); @@ -906,7 +884,7 @@ { version (Windows) { - char[] path = Path(); + string path = Path(); m_hModule = cast(HXModule)LoadLibraryA(toStringz(path)); if (m_hModule == null) throw new ExeModuleException(GetLastError()); @@ -924,7 +902,7 @@ } } - this(char[] moduleName) + this(string moduleName) in { assert(null !is moduleName); @@ -998,7 +976,7 @@ * \return A pointer to the symbol. There is no null return - failure to retrieve the symbol * results in an ExeModuleException exception being thrown. */ - void *getSymbol(in char[] symbolName) + void *getSymbol(in string symbolName) { version (Windows) { @@ -1038,7 +1016,7 @@ * * \return A pointer to the symbol, or null if it does not exist */ - void *findSymbol(in char[] symbolName) + void *findSymbol(in string symbolName) { return ExeModule_GetSymbol(m_hModule, symbolName); } @@ -1058,7 +1036,7 @@ /// The handle of the module /// /// \note Will be \c null if the module load in the constructor failed - char[] Path() + string Path() { assert(null != m_hModule); @@ -1094,7 +1072,7 @@ version(TestMain) { - int main(char[][] args) + int main(string[] args) { if(args.length < 3) { @@ -1102,8 +1080,8 @@ } else { - char[] moduleName = args[1]; - char[] symbolName = args[2]; + string moduleName = args[1]; + string symbolName = args[2]; try { diff -uNr gdc-0.23/d/phobos/std/math2.d gdc-0.24/d/phobos/std/math2.d --- gdc-0.23/d/phobos/std/math2.d 2007-02-24 02:40:20.000000000 +0100 +++ gdc-0.24/d/phobos/std/math2.d 2007-07-23 02:23:26.000000000 +0200 @@ -1,3 +1,6 @@ + +/* This module is obsolete and will be removed eventually */ + /* * Copyright (c) 2002 * Pavel "EvilOne" Minayev diff -uNr gdc-0.23/d/phobos/std/metastrings.d gdc-0.24/d/phobos/std/metastrings.d --- gdc-0.23/d/phobos/std/metastrings.d 2007-02-08 19:18:13.000000000 +0100 +++ gdc-0.24/d/phobos/std/metastrings.d 2007-07-23 02:23:26.000000000 +0200 @@ -34,7 +34,7 @@ void main() { - char[] s = Format!("Arg %s = %s", "foo", 27); + string s = Format!("Arg %s = %s", "foo", 27); writefln(s); // "Arg foo = 27" } * --- @@ -51,7 +51,7 @@ const char[] Format = ToString!(A[0]) ~ Format!(A[1..$]); } -template FormatString(char[] F, A...) +template FormatString(string F, A...) { static if (F.length == 0) const char[] FormatString = Format!(A); @@ -85,9 +85,11 @@ static if (I < 0) const char[] ToString = "-" ~ ToString!(cast(ulong)(-I)); else - const char[] ToString = ToString!(cast(uint)I); + const char[] ToString = ToString!(cast(ulong)I); } +static assert(ToString!(0x100000000) == "4294967296"); + /// ditto template ToString(uint U) { @@ -131,7 +133,7 @@ } /// ditto -template ToString(char[] S) +template ToString(string S) { const char[] ToString = S; } @@ -144,7 +146,7 @@ unittest { - char[] s = Format!("hel%slo", "world", -138, 'c', true); + string s = Format!("hel%slo", "world", -138, 'c', true); assert(s == "helworldlo-138ctrue"); } @@ -159,7 +161,7 @@ * .rest = s */ -template ParseUinteger(char[] s) +template ParseUinteger(string s) { static if (s.length == 0) { const char[] value = ""; @@ -186,7 +188,7 @@ * .rest = s */ -template ParseInteger(char[] s) +template ParseInteger(string s) { static if (s.length == 0) { const char[] value = ""; diff -uNr gdc-0.23/d/phobos/std/mmfile.d gdc-0.24/d/phobos/std/mmfile.d --- gdc-0.23/d/phobos/std/mmfile.d 2006-12-09 17:40:24.000000000 +0100 +++ gdc-0.24/d/phobos/std/mmfile.d 2007-07-23 02:23:26.000000000 +0200 @@ -1,8 +1,25 @@ -// Copyright (c) 2004 by Digital Mars -// All Rights Reserved -// written by Walter Bright and Matthew Wilson (Synesis Software Pty Ltd.) -// www.digitalmars.com -// www.synesis.com.au/software +/* Copyright 2004-2005 by Digital Mars + * Written by Walter Bright and Matthew Wilson + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * - The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * - Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * - This notice may not be removed or altered from any source + * distribution. + * + */ /** * Read and write memory mapped files. diff -uNr gdc-0.23/d/phobos/std/moduleinit.d gdc-0.24/d/phobos/std/moduleinit.d --- gdc-0.23/d/phobos/std/moduleinit.d 2007-02-25 23:10:47.000000000 +0100 +++ gdc-0.24/d/phobos/std/moduleinit.d 2007-04-28 18:45:43.000000000 +0200 @@ -12,6 +12,7 @@ private { import object; + import std.stdio; import std.c.stdio; import std.c.stdlib; import std.string; @@ -24,6 +25,9 @@ // ctors being done first } +/*********************** + * Information about each module. + */ class ModuleInfo { char name[]; @@ -35,6 +39,14 @@ void (*ctor)(); void (*dtor)(); void (*unitTest)(); + + /****************** + * Return collection of all modules in the program. + */ + static ModuleInfo[] modules() + { + return _moduleinfo_array; + } } class ModuleCtorError : Exception @@ -108,6 +120,18 @@ _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); _moduleCtor2(_moduleinfo_array, 0); + + version (none) + { + foreach (m; _moduleinfo_array) + { + writefln("module %s, %d", m.name, m.localClasses.length); + foreach (c; m.localClasses) + { + writefln("\tclass %s", c.name); + } + } + } } void _moduleCtor2(ModuleInfo[] mi, int skip) diff -uNr gdc-0.23/d/phobos/std/outbuffer.d gdc-0.24/d/phobos/std/outbuffer.d --- gdc-0.23/d/phobos/std/outbuffer.d 2007-02-24 14:21:13.000000000 +0100 +++ gdc-0.24/d/phobos/std/outbuffer.d 2007-07-23 02:23:26.000000000 +0200 @@ -49,6 +49,7 @@ { //printf("this = %p, offset = %x, data.length = %u\n", this, offset, data.length); assert(offset <= data.length); + assert(data.length <= std.gc.capacity(data.ptr)); } this() @@ -79,13 +80,15 @@ out { assert(offset + nbytes <= data.length); + assert(data.length <= std.gc.capacity(data.ptr)); } body { - //c.stdio.printf("OutBuffer.reserve: length = %d, offset = %d, nbytes = %d\n", data.length, offset, nbytes); if (data.length < offset + nbytes) { + //std.c.stdio.printf("OutBuffer.reserve: ptr = %p, length = %d, offset = %d, nbytes = %d, capacity = %d\n", data.ptr, data.length, offset, nbytes, std.gc.capacity(data.ptr)); data.length = (offset + nbytes) * 2; + //std.c.stdio.printf("OutBuffer.reserve: ptr = %p, length = %d, capacity = %d\n", data.ptr, data.length, std.gc.capacity(data.ptr)); std.gc.hasPointers(data.ptr); } } diff -uNr gdc-0.23/d/phobos/std/path.d gdc-0.24/d/phobos/std/path.d --- gdc-0.23/d/phobos/std/path.d 2007-02-24 15:19:05.000000000 +0100 +++ gdc-0.24/d/phobos/std/path.d 2007-04-22 16:06:53.000000000 +0200 @@ -86,9 +86,9 @@ * */ -version (Windows) alias std.string.cmp fcmp; +version (Windows) alias std.string.icmp fcmp; -version (Unix) alias std.string.icmp fcmp; +version (Unix) alias std.string.cmp fcmp; /************************** * Extracts the extension from a filename or path. diff -uNr gdc-0.23/d/phobos/std/regexp.d gdc-0.24/d/phobos/std/regexp.d --- gdc-0.23/d/phobos/std/regexp.d 2007-03-04 15:51:39.000000000 +0100 +++ gdc-0.24/d/phobos/std/regexp.d 2007-04-28 18:45:43.000000000 +0200 @@ -1148,6 +1148,30 @@ /************************************************ * Search string[] for match. * Returns: 0 for no match, !=0 for match + * Example: +--- +import std.stdio; +import std.regexp; +import std.string; + +int grep(int delegate(char[]) pred, char[][] list) +{ + int count; + foreach (s; list) + { if (pred(s)) + ++count; + } + return count; +} + +void main() +{ + auto x = grep(&RegExp("[Ff]oo").test, + std.string.split("mary had a foo lamb")); + writefln(x); +} +--- + * which prints: 1 */ public int test(rchar[] string) diff -uNr gdc-0.23/d/phobos/std/socket.d gdc-0.24/d/phobos/std/socket.d --- gdc-0.23/d/phobos/std/socket.d 2007-02-26 15:14:18.000000000 +0100 +++ gdc-0.24/d/phobos/std/socket.d 2007-07-27 02:07:14.000000000 +0200 @@ -1,3 +1,5 @@ +// Written in the D programming language + /* Copyright (C) 2004-2005 Christopher E. Miller @@ -98,7 +100,7 @@ { int errorCode; /// Platform-specific error code. - this(char[] msg, int err = 0) + this(string msg, int err = 0) { errorCode = err; @@ -199,8 +201,8 @@ class Protocol { ProtocolType type; /// These members are populated when one of the following functions are called without failure: - char[] name; /// ditto - char[][] aliases; /// ditto + string name; /// ditto + string[] aliases; /// ditto void populate(protoent* proto) @@ -217,7 +219,7 @@ if(i) { - aliases = new char[][i]; + aliases = new string[i]; for(i = 0; i != aliases.length; i++) { aliases[i] = std.string.toString(proto.p_aliases[i]).dup; @@ -230,7 +232,7 @@ } /** Returns false on failure */ - bool getProtocolByName(char[] name) + bool getProtocolByName(string name) { protoent* proto; proto = getprotobyname(toStringz(name)); @@ -266,7 +268,7 @@ assert(proto.getProtocolByType(ProtocolType.TCP)); printf("About protocol TCP:\n\tName: %.*s\n", cast(int) proto.name.length, proto.name.ptr); - foreach(char[] s; proto.aliases) + foreach(string s; proto.aliases) { printf("\tAlias: %.*s\n", cast(int) s.length, s.ptr); } @@ -279,10 +281,10 @@ class Service { /** These members are populated when one of the following functions are called without failure: */ - char[] name; - char[][] aliases; /// ditto + string name; + string[] aliases; /// ditto ushort port; /// ditto - char[] protocolName; /// ditto + string protocolName; /// ditto void populate(servent* serv) @@ -300,7 +302,7 @@ if(i) { - aliases = new char[][i]; + aliases = new string[i]; for(i = 0; i != aliases.length; i++) { aliases[i] = std.string.toString(serv.s_aliases[i]).dup; @@ -316,7 +318,7 @@ * If a protocol name is omitted, any protocol will be matched. * Returns: false on failure. */ - bool getServiceByName(char[] name, char[] protocolName) + bool getServiceByName(string name, string protocolName) { servent* serv; serv = getservbyname(toStringz(name), toStringz(protocolName)); @@ -329,7 +331,7 @@ // Any protocol name will be matched. /// ditto - bool getServiceByName(char[] name) + bool getServiceByName(string name) { servent* serv; serv = getservbyname(toStringz(name), null); @@ -341,7 +343,7 @@ /// ditto - bool getServiceByPort(ushort port, char[] protocolName) + bool getServiceByPort(ushort port, string protocolName) { version (have_getservbyport) { @@ -404,7 +406,7 @@ int errorCode; /// Platform-specific error code. - this(char[] msg, int err = 0) + this(string msg, int err = 0) { errorCode = err; super(msg); @@ -417,8 +419,8 @@ class InternetHost { /** These members are populated when one of the following functions are called without failure: */ - char[] name; - char[][] aliases; /// ditto + string name; + string[] aliases; /// ditto uint32_t[] addrList; /// ditto @@ -445,7 +447,7 @@ if(i) { - aliases = new char[][i]; + aliases = new string[i]; for(i = 0; i != aliases.length; i++) { aliases[i] = std.string.toString(he.h_aliases[i]).dup; @@ -480,7 +482,7 @@ /** * Resolve host name. Returns false if unable to resolve. */ - bool getHostByName(char[] name) + bool getHostByName(string name) { hostent* he = gethostbyname(toStringz(name)); if(!he) @@ -511,7 +513,7 @@ * dotted-decimal form $(I a.b.c.d). * Returns false if unable to resolve. */ - bool getHostByAddr(char[] addr) + bool getHostByAddr(string addr) { uint x = inet_addr(std.string.toStringz(addr)); hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET); @@ -534,7 +536,7 @@ char[] sia = ia.toAddrString(); printf("IPaddress = %.*s\nname = %.*s\n", cast(int) sia.length, sia.ptr, cast(int) ih.name.length, ih.name.ptr); - foreach(int i, char[] s; ih.aliases) + foreach(int i, string s; ih.aliases) { printf("aliases[%d] = %.*s\n", i, cast(int) s.length, s.ptr); } @@ -543,7 +545,7 @@ assert(ih.getHostByAddr(ih.addrList[0])); printf("name = %.*s\n", cast(int) ih.name.length, ih.name.ptr); - foreach(int i, char[] s; ih.aliases) + foreach(int i, string s; ih.aliases) { printf("aliases[%d] = %.*s\n", i, cast(int) s.length, s.ptr); } @@ -555,7 +557,7 @@ */ class AddressException: Exception { - this(char[] msg) + this(string msg) { super(msg); } @@ -570,7 +572,7 @@ protected sockaddr* name(); protected int nameLen(); AddressFamily addressFamily(); /// Family of this address. - char[] toString(); /// Human readable string representing this address. + string toString(); /// Human readable string representing this address. } /** @@ -601,7 +603,7 @@ } - char[] toString() + string toString() { return "Unknown"; } @@ -665,7 +667,7 @@ * object. * port = may be PORT_ANY as stated below. */ - this(char[] addr, ushort port) + this(string addr, ushort port) { uint uiaddr = parse(addr); if(ADDR_NONE == uiaddr) @@ -699,19 +701,19 @@ } /// Human readable string representing the IPv4 address in dotted-decimal form. - char[] toAddrString() + string toAddrString() { return std.string.toString(inet_ntoa(sin.sin_addr)).dup; } /// Human readable string representing the IPv4 port. - char[] toPortString() + string toPortString() { return std.string.toString(port()); } /// Human readable string representing the IPv4 address and port in the form $(I a.b.c.d:e). - char[] toString() + string toString() { return toAddrString() ~ ":" ~ toPortString(); } @@ -722,7 +724,7 @@ * If the string is not a legitimate IPv4 address, * ADDR_NONE is returned. */ - static uint parse(char[] addr) + static uint parse(string addr) { return ntohl(inet_addr(std.string.toStringz(addr))); } @@ -739,7 +741,7 @@ /** */ class SocketAcceptException: SocketException { - this(char[] msg, int err = 0) + this(string msg, int err = 0) { super(msg, err); } @@ -785,44 +787,21 @@ class SocketSet { private: - uint nbytes; // Win32: excludes uint.sizeof "count". - byte* buf; + uint maxsockets; /// max desired sockets, the fd_set might be capable of holding more + fd_set set; version(Win32) { uint count() { - return *(cast(uint*)buf); - } - - - void count(int setter) - { - *(cast(uint*)buf) = setter; - } - - - socket_t* first() - { - return cast(socket_t*)(buf + uint.sizeof); + return set.fd_count; } } else version(BsdSockets) { - int maxfd = -1; - - - socket_t* first() - { - return cast(socket_t*)buf; - } - } - - - fd_set* _fd_set() - { - return cast(fd_set*)buf; + int maxfd; + uint count; } @@ -831,19 +810,8 @@ /// Set the maximum amount of sockets that may be added. this(uint max) { - version(Win32) - { - nbytes = max * socket_t.sizeof; - buf = (new byte[nbytes + uint.sizeof]).ptr; - count = 0; - } - else version(BsdSockets) - { - nbytes = max / NFDBITS * socket_t.sizeof; - if(max % NFDBITS) - nbytes += socket_t.sizeof; - buf = (new byte[nbytes]).ptr; // new initializes to 0. - } + maxsockets = max; + reset(); } /// Uses the default maximum for the system. @@ -855,22 +823,13 @@ /// Reset the SocketSet so that there are 0 Sockets in the collection. void reset() { - version(Win32) - { + FD_ZERO(&set); + + version(BsdSockets) + { + maxfd = -1; count = 0; - } - else version(BsdSockets) - { - maxfd = -1; - version(GNU) - { - FD_ZERO(_fd_set); - } - else - { - buf[0 .. nbytes] = 0; - } - } + } } @@ -878,11 +837,8 @@ in { // Make sure too many sockets don't get added. - version(Win32) - { - assert(count < max); - } - else version(BsdSockets) + assert(count < maxsockets); + version(BsdSockets) { version(GNU) { @@ -891,16 +847,17 @@ } else { - assert(FDELT(s) < nbytes / socket_t.sizeof); + assert(FDELT(s) < (FD_SETSIZE / NFDBITS)); } } } body { - FD_SET(s, _fd_set); + FD_SET(s, &set); version(BsdSockets) { + ++count; if(s > maxfd) maxfd = s; } @@ -914,7 +871,12 @@ void remove(socket_t s) { - FD_CLR(s, _fd_set); + FD_CLR(s, &set); + version(BsdSockets) + { + --count; + // note: adjusting maxfd would require scanning the set, not worth it + } } @@ -926,7 +888,7 @@ int isSet(socket_t s) { - return FD_ISSET(s, _fd_set); + return FD_ISSET(s, &set); } @@ -940,24 +902,13 @@ /// Return maximum amount of sockets that can be added, like FD_SETSIZE. uint max() { - version(Win32) - { - return nbytes / socket_t.sizeof; - } - else version(BsdSockets) - { - return nbytes / socket_t.sizeof * NFDBITS; - } - else - { - static assert(0); - } + return maxsockets; } fd_set* toFd_set() { - return _fd_set; + return &set; } @@ -965,7 +916,7 @@ { version(Win32) { - return 0; + return count; } else version(BsdSockets) { @@ -1101,7 +1052,7 @@ /// ditto - this(AddressFamily af, SocketType type, char[] protocolName) + this(AddressFamily af, SocketType type, string protocolName) { protoent* proto; proto = getprotobyname(toStringz(protocolName)); @@ -1333,7 +1284,7 @@ /// Returns the local machine's host name. Idea from mango. - static char[] hostName() // getter + static string hostName() // getter { char[256] result; // Host names are limited to 255 chars. if(_SOCKET_ERROR == .gethostname(result.ptr, result.length)) diff -uNr gdc-0.23/d/phobos/std/stdio.d gdc-0.24/d/phobos/std/stdio.d --- gdc-0.23/d/phobos/std/stdio.d 2007-03-04 15:51:46.000000000 +0100 +++ gdc-0.24/d/phobos/std/stdio.d 2007-07-28 00:45:28.000000000 +0200 @@ -1,7 +1,7 @@ // Written in the D programming language. -/* Written by Walter Bright +/* Written by Walter Bright and Andrei Alexandrescu * www.digitalmars.com * Placed in the Public Domain. */ @@ -9,7 +9,7 @@ /* NOTE: This file has been patched from the original DMD distribution to work with the GDC compiler. - Modified by David Friedman, July 2006 + Modified by David Friedman, April 2007 */ /******************************** @@ -22,123 +22,192 @@ module std.stdio; -public import std.c.stdio; +public import std.c.stdio; import std.format; import std.utf; +import std.string; +import std.gc; +import std.c.stdlib; +import std.c.string; +import std.c.stddef; + import std.stdarg; -version (DigitalMars) +version (GNU) { - version (Windows) + static import gcc.config; + import gcc.config : Have_getdelim, Have_Unlocked_Stdio, + Have_Unlocked_Wide_Stdio, Have_fwide, Have_fgetln, + Have_fgetline; + + extern(C) { - version = DIGITAL_MARS_STDIO; + char * fgetln(FILE *stream, size_t *len); + char * fgetline(FILE *stream, size_t *len); + int putc_unlocked(int, FILE*); + int putwc_unlocked(wchar_t, FILE*); + int getc_unlocked(FILE*); + int getwc_unlocked(FILE*); + void flockfile(FILE*); + void funlockfile(FILE*); + } + + static if (gcc.config.Have_getdelim) + { + import gcc.configunix; + extern(C) ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); } -} - -version (DIGITAL_MARS_STDIO) -{ - extern (C) + static if (gcc.config.Have_Unlocked_Stdio) { - int _fputc_nlock(int, FILE*); - int _fputwc_nlock(int, FILE*); - int __fp_lock(FILE*); - void __fp_unlock(FILE*); + alias flockfile FLOCK; + alias funlockfile FUNLOCK; + alias putc_unlocked FPUTC; + alias getc_unlocked FGETC; + static if (gcc.config.Have_Unlocked_Wide_Stdio) + { + alias putwc_unlocked FPUTWC; + alias getwc_unlocked FGETWC; + } + else + { + alias fputwc FPUTWC; + alias fgetwc FGETWC; + } + } + else + { + private void fnop(FILE *) { } + alias fnop FLOCK; + alias fnop FUNLOCK; + alias fputc FPUTC; + alias fgetc FGETC; + alias fputwc FPUTWC; + alias fgetwc FGETWC; } - alias _fputc_nlock FPUTC; - alias _fputwc_nlock FPUTWC; } else + static assert(0); + + +/********************* + * Thrown if I/O errors happen. + */ +class StdioException : Exception { - alias std.c.stdio.fputc FPUTC; - alias std.c.stdio.fputwc FPUTWC; + uint errno; // operating system error code + + this(char[] msg) + { + super(msg); + } - int __fp_lock(FILE* fp) { return 0; } - void __fp_unlock(FILE* fp) { } + this(uint errno) + { char* s = strerror(errno); + super(std.string.toString(s).dup); + } + + static void opCall(char[] msg) + { + throw new StdioException(msg); + } + + static void opCall() + { + throw new StdioException(getErrno()); + } } +private void writefx(FILE* fp, TypeInfo[] arguments, va_list argptr, int newline=false) { int orientation; - version(GNU_Have_fwide) + static if (Have_fwide) orientation = fwide(fp, 0); - try - { - /* Do the file stream locking at the outermost level - * rather than character by character. - */ - __fp_lock(fp); - if (orientation <= 0) // byte orientation or no orientation + if (orientation <= 0) // byte orientation or no orientation + { + static if (Have_Unlocked_Stdio) + { + /* Do the file stream locking at the outermost level + * rather than character by character. + */ + FLOCK(fp); + scope(exit) FUNLOCK(fp); + } + + void putc(dchar c) { - void putc(dchar c) + if (c <= 0x7F) { - if (c <= 0x7F) - { - FPUTC(c, fp); - } - else - { char[4] buf; - char[] b; - - b = std.utf.toUTF8(buf, c); - for (size_t i = 0; i < b.length; i++) - FPUTC(b[i], fp); - } + FPUTC(c, fp); } + else + { char[4] buf; + char[] b; - std.format.doFormat(&putc, arguments, argptr); - if (newline) - FPUTC('\n', fp); + b = std.utf.toUTF8(buf, c); + for (size_t i = 0; i < b.length; i++) + FPUTC(b[i], fp); + } } - else if (orientation > 0) // wide orientation - { - version (GNU_Have_fwide) - { - version (Windows) - { - void putcw(dchar c) - { - assert(isValidDchar(c)); - if (c <= 0xFFFF) - { - FPUTWC(c, fp); - } - else - { wchar[2] buf; + std.format.doFormat(&putc, arguments, argptr); + if (newline) + FPUTC('\n', fp); + } + else if (orientation > 0) // wide orientation + { + static if (Have_fwide) + { + + static if (Have_Unlocked_Wide_Stdio) + { + /* Do the file stream locking at the outermost level + * rather than character by character. + */ + FLOCK(fp); + scope(exit) FUNLOCK(fp); + } - buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); - buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); - FPUTWC(buf[0], fp); - FPUTWC(buf[1], fp); - } - } - } - else version (Unix) + static if (wchar_t.sizeof == 2) + { + void putcw(dchar c) { - void putcw(dchar c) + assert(isValidDchar(c)); + if (c <= 0xFFFF) { FPUTWC(c, fp); } + else + { wchar[2] buf; + + buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800); + buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00); + FPUTWC(buf[0], fp); + FPUTWC(buf[1], fp); + } } - else + } + else static if (wchar_t.sizeof == 4) + { + void putcw(dchar c) { - static assert(0); + FPUTWC(c, fp); } + } + else + { + static assert(0); + } - std.format.doFormat(&putcw, arguments, argptr); - if (newline) - FPUTWC('\n', fp); + std.format.doFormat(&putcw, arguments, argptr); + if (newline) + FPUTWC('\n', fp); - } } } - finally - { - __fp_unlock(fp); - } } @@ -182,3 +251,212 @@ { writefx(fp, _arguments, _argptr, 1); } + +/********************************** + * Read line from stream fp. + * Returns: + * null for end of file, + * char[] for line read from fp, including terminating '\n' + * Params: + * fp = input stream + * Throws: + * $(B StdioException) on error + * Example: + * Reads $(B stdin) and writes it to $(B stdout). +--- +import std.stdio; + +int main() +{ + char[] buf; + while ((buf = readln()) != null) + writef("%s", buf); + return 0; +} +--- + */ +char[] readln(FILE* fp = stdin) +{ + char[] buf; + readln(fp, buf); + return buf; +} + +/********************************** + * Read line from stream fp and write it to buf[], + * including terminating '\n'. + * + * This is often faster than readln(FILE*) because the buffer + * is reused each call. Note that reusing the buffer means that + * the previous contents of it need to be copied if needed. + * Params: + * fp = input stream + * buf = buffer used to store the resulting line data. buf + * is resized as necessary. + * Returns: + * 0 for end of file, otherwise + * number of characters read + * Throws: + * $(B StdioException) on error + * Example: + * Reads $(B stdin) and writes it to $(B stdout). +--- +import std.stdio; + +int main() +{ + char[] buf; + while (readln(stdin, buf)) + writef("%s", buf); + return 0; +} +--- + */ +size_t readln(FILE* fp, inout char[] buf) +{ + version (GNU) + { + int orientation; + static if (Have_fwide) + orientation = fwide(fp, 0); + + if (orientation > 0) + { /* Stream is in wide characters. + * Read them and convert to chars. + */ + static if (Have_fwide) + { + + static if (Have_Unlocked_Wide_Stdio) + { + FLOCK(fp); + scope(exit) FUNLOCK(fp); + } + + static if (wchar_t.sizeof == 2) + { + buf.length = 0; + int c2; + for (int c; (c = FGETWC(fp)) != -1; ) + { + if ((c & ~0x7F) == 0) + { buf ~= c; + if (c == '\n') + break; + } + else + { + if (c >= 0xD800 && c <= 0xDBFF) + { + if ((c2 = FGETWC(fp)) != -1 || + c2 < 0xDC00 && c2 > 0xDFFF) + { + StdioException("unpaired UTF-16 surrogate"); + } + c = ((c - 0xD7C0) << 10) + (c2 - 0xDC00); + } + std.utf.encode(buf, c); + } + } + if (ferror(fp)) + StdioException(); + return buf.length; + } + else static if (wchar_t.sizeof == 4) + { + buf.length = 0; + for (int c; (c = FGETWC(fp)) != -1; ) + { + if ((c & ~0x7F) == 0) + buf ~= c; + else + std.utf.encode(buf, cast(dchar)c); + if (c == '\n') + break; + } + if (ferror(fp)) + StdioException(); + return buf.length; + } + else + { + static assert(0); + } + + } + } + + char *lineptr = null; + size_t s; + static if (Have_getdelim) + { + size_t n = 0; + s = getdelim(&lineptr, &n, '\n', fp); + scope(exit) free(lineptr); + if (s < 0) + { + if (ferror(fp)) + StdioException(); + buf.length = 0; // end of file + return 0; + } + } + else static if (Have_fgetln || Have_fgetline) + { + static if (Have_fgetln) + lineptr = fgetln(fp, & s); + else + lineptr = fgetline(fp, & s); + if (lineptr is null) + { + if (ferror(fp)) + StdioException(); + buf.length = 0; // end of file + return 0; + } + } + else + { + { + static if (Have_Unlocked_Stdio) + { + FLOCK(fp); + scope(exit) FUNLOCK(fp); + } + + buf.length = 0; + for (int c; (c = FGETC(fp)) != -1; ) + { + buf ~= c; + if (c == '\n') + break; + } + } + if (ferror(fp)) + StdioException(); + return buf.length; + } + buf = buf.ptr[0 .. std.gc.capacity(buf.ptr)]; + if (s <= buf.length) + { + buf.length = s; + buf[] = lineptr[0 .. s]; + } + else + { + buf = lineptr[0 .. s].dup; + } + return s; + } + else + { + static assert(0); + } +} + +/** ditto */ +size_t readln(inout char[] buf) +{ + return readln(stdin, buf); +} + diff -uNr gdc-0.23/d/phobos/std/string.d gdc-0.24/d/phobos/std/string.d --- gdc-0.23/d/phobos/std/string.d 2007-03-04 15:53:28.000000000 +0100 +++ gdc-0.24/d/phobos/std/string.d 2007-07-23 02:23:26.000000000 +0200 @@ -268,8 +268,8 @@ } /****************************************** - * find, ifind _find first occurrance of c in string s. - * rfind, irfind _find last occurrance of c in string s. + * find, ifind _find first occurrence of c in string s. + * rfind, irfind _find last occurrence of c in string s. * * find, rfind are case sensitive; ifind, irfind are case insensitive. * Returns: @@ -484,8 +484,8 @@ /****************************************** - * find, ifind _find first occurrance of sub[] in string s[]. - * rfind, irfind _find last occurrance of sub[] in string s[]. + * find, ifind _find first occurrence of sub[] in string s[]. + * rfind, irfind _find last occurrence of sub[] in string s[]. * * find, rfind are case sensitive; ifind, irfind are case insensitive. * Returns: @@ -617,7 +617,7 @@ { size_t imax = s.length - sublength; - for (i = 0; i < imax; i++) + for (i = 0; i <= imax; i++) { if (icmp(s[i .. i + sublength], sub) == 0) return i; @@ -663,6 +663,9 @@ i = ifind(sPlts, sPlts); assert(i == 0); + i = ifind("\u0100", "\u0100"); + assert(i == 0); + // Thanks to Carlos Santander B. and zwang i = ifind("sus mejores cortesanos. Se embarcaron en el puerto de Dubai y", "page-break-before"); @@ -812,10 +815,10 @@ * Convert string s[] to lower case. */ -char[] tolower(char[] s) +string tolower(string s) { - bool changed; - auto r = s; + int changed; + char[] r; for (size_t i = 0; i < s.length; i++) { @@ -825,13 +828,13 @@ if (!changed) { r = s.dup; - changed = true; + changed = 1; } r[i] = cast(char) (c + (cast(char)'a' - 'A')); } - else if (c >= 0x7F) + else if (c > 0x7F) { - foreach(size_t j, dchar dc; s[i .. length]) + foreach (size_t j, dchar dc; s[i .. length]) { if (std.uni.isUniUpper(dc)) { @@ -839,20 +842,22 @@ if (!changed) { r = s[0 .. i + j].dup; - changed = true; + changed = 2; } } if (changed) { - if (r.length != i + j) - r = r[0 .. i + j]; + if (changed == 1) + { r = r[0 .. i + j]; + changed = 2; + } std.utf.encode(r, dc); } } break; } } - return r; + return changed ? r : s; } unittest @@ -875,16 +880,21 @@ s2 = tolower(s1); assert(cmp(s2, "a\u0461b\u0461d") == 0); assert(s2 !is s1); + + s1 = "\u0130"; + s2 = tolower(s1); + assert(s2 == "i"); + assert(s2 !is s1); } /************************************ * Convert string s[] to upper case. */ -char[] toupper(char[] s) +string toupper(string s) { - bool changed; - auto r = s; + int changed; + char[] r; for (size_t i = 0; i < s.length; i++) { @@ -894,13 +904,13 @@ if (!changed) { r = s.dup; - changed = true; + changed = 1; } r[i] = cast(char) (c - (cast(char)'a' - 'A')); } - else if (c >= 0x7F) + else if (c > 0x7F) { - foreach(size_t j, dchar dc; s[i .. length]) + foreach (size_t j, dchar dc; s[i .. length]) { if (std.uni.isUniLower(dc)) { @@ -908,20 +918,22 @@ if (!changed) { r = s[0 .. i + j].dup; - changed = true; + changed = 2; } } if (changed) { - if (r.length != i + j) - r = r[0 .. i + j]; + if (changed == 1) + { r = r[0 .. i + j]; + changed = 2; + } std.utf.encode(r, dc); } } break; } } - return r; + return changed ? r : s; } unittest @@ -1222,7 +1234,7 @@ unittest { - debug(string) printf("string.join.split1\n"); + debug(string) printf("string.split1\n"); char[] s = " peter paul\tjerry "; char[][] words; @@ -1346,7 +1358,7 @@ unittest { - debug(string) printf("string.join.split2\n"); + debug(string) printf("string.split2\n"); char[] s = ",peter,paul,jerry,"; char[][] words; @@ -1468,7 +1480,7 @@ unittest { - debug(string) printf("string.join.splitlines\n"); + debug(string) printf("string.splitlines\n"); char[] s = "\rpeter\n\rpaul\r\njerry\n"; char[][] lines; @@ -3960,3 +3972,119 @@ } +/*************************** + * Does string s[] start with an email address? + * Returns: + * null it does not + * char[] it does, and this is the slice of s[] that is that email address + * References: + * RFC2822 + */ +char[] isEmail(char[] s) +{ size_t i; + + if (!isalpha(s[0])) + goto Lno; + + for (i = 1; 1; i++) + { + if (i == s.length) + goto Lno; + auto c = s[i]; + if (isalnum(c)) + continue; + if (c == '-' || c == '_' || c == '.') + continue; + if (c != '@') + goto Lno; + i++; + break; + } + //writefln("test1 '%s'", s[0 .. i]); + + /* Now do the part past the '@' + */ + size_t lastdot; + for (; i < s.length; i++) + { + auto c = s[i]; + if (isalnum(c)) + continue; + if (c == '-' || c == '_') + continue; + if (c == '.') + { + lastdot = i; + continue; + } + break; + } + if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) + goto Lno; + + return s[0 .. i]; + +Lno: + return null; +} + + +/*************************** + * Does string s[] start with a URL? + * Returns: + * null it does not + * char[] it does, and this is the slice of s[] that is that URL + */ + +char[] isURL(char[] s) +{ + /* Must start with one of: + * http:// + * https:// + * www. + */ + + size_t i; + + if (s.length <= 4) + goto Lno; + + //writefln("isURL(%s)", s); + if (s.length > 7 && std.string.icmp(s[0 .. 7], "http://") == 0) + i = 7; + else if (s.length > 8 && std.string.icmp(s[0 .. 8], "https://") == 0) + i = 8; +// if (icmp(s[0 .. 4], "www.") == 0) +// i = 4; + else + goto Lno; + + size_t lastdot; + for (; i < s.length; i++) + { + auto c = s[i]; + if (isalnum(c)) + continue; + if (c == '-' || c == '_' || c == '?' || + c == '=' || c == '%' || c == '&' || + c == '/' || c == '+' || c == '#' || + c == '~') + continue; + if (c == '.') + { + lastdot = i; + continue; + } + break; + } + //if (!lastdot || (i - lastdot != 3 && i - lastdot != 4)) + if (!lastdot) + goto Lno; + + return s[0 .. i]; + +Lno: + return null; +} + + diff -uNr gdc-0.23/d/phobos/std/uni.d gdc-0.24/d/phobos/std/uni.d --- gdc-0.23/d/phobos/std/uni.d 2006-12-03 17:59:05.000000000 +0100 +++ gdc-0.24/d/phobos/std/uni.d 2007-07-27 02:07:14.000000000 +0200 @@ -180,91 +180,73 @@ /******************************* * Return !=0 if u is a Unicode alpha character. + * (general Unicode category: Lu, Ll, Lt, Lm and Lo) + * + * Standards: Unicode 5.0.0 */ int isUniAlpha(dchar u) { - static ushort table[][2] = + static dchar table[][2] = [ [ 'A', 'Z' ], [ 'a', 'z' ], [ 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 ], + [ 0x00F8, 0x02C1 ], + [ 0x02C6, 0x02D1 ], [ 0x02E0, 0x02E4 ], - [ 0x037A, 0x037A ], + [ 0x02EE, 0x02EE ], + [ 0x037A, 0x037D ], [ 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 ], + [ 0x03D0, 0x03F5 ], + [ 0x03F7, 0x0481 ], + [ 0x048A, 0x0513 ], [ 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 ], + [ 0x0640, 0x064A ], + [ 0x066E, 0x066F ], + [ 0x0671, 0x06D3 ], + [ 0x06D5, 0x06D5 ], + [ 0x06E5, 0x06E6 ], + [ 0x06EE, 0x06EF ], + [ 0x06FA, 0x06FC ], + [ 0x06FF, 0x06FF ], + [ 0x0710, 0x0710 ], + [ 0x0712, 0x072F ], + [ 0x074D, 0x076D ], + [ 0x0780, 0x07A5 ], + [ 0x07B1, 0x07B1 ], + [ 0x07CA, 0x07EA ], + [ 0x07F4, 0x07F5 ], + [ 0x07FA, 0x07FA ], + [ 0x0904, 0x0939 ], [ 0x093D, 0x093D ], - [ 0x093E, 0x094D ], - [ 0x0950, 0x0952 ], - [ 0x0958, 0x0963 ], - [ 0x0966, 0x096F ], - [ 0x0981, 0x0983 ], + [ 0x0950, 0x0950 ], + [ 0x0958, 0x0961 ], + [ 0x097B, 0x097F ], [ 0x0985, 0x098C ], [ 0x098F, 0x0990 ], [ 0x0993, 0x09A8 ], [ 0x09AA, 0x09B0 ], [ 0x09B2, 0x09B2 ], [ 0x09B6, 0x09B9 ], - [ 0x09BE, 0x09C4 ], - [ 0x09C7, 0x09C8 ], - [ 0x09CB, 0x09CD ], + [ 0x09BD, 0x09BD ], + [ 0x09CE, 0x09CE ], [ 0x09DC, 0x09DD ], - [ 0x09DF, 0x09E3 ], - [ 0x09E6, 0x09EF ], + [ 0x09DF, 0x09E1 ], [ 0x09F0, 0x09F1 ], - [ 0x0A02, 0x0A02 ], [ 0x0A05, 0x0A0A ], [ 0x0A0F, 0x0A10 ], [ 0x0A13, 0x0A28 ], @@ -272,42 +254,29 @@ [ 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 ], + [ 0x0A72, 0x0A74 ], + [ 0x0A85, 0x0A8D ], [ 0x0A8F, 0x0A91 ], [ 0x0A93, 0x0AA8 ], [ 0x0AAA, 0x0AB0 ], [ 0x0AB2, 0x0AB3 ], [ 0x0AB5, 0x0AB9 ], - [ 0x0ABD, 0x0AC5 ], - [ 0x0AC7, 0x0AC9 ], - [ 0x0ACB, 0x0ACD ], + [ 0x0ABD, 0x0ABD ], [ 0x0AD0, 0x0AD0 ], - [ 0x0AE0, 0x0AE0 ], - [ 0x0AE6, 0x0AEF ], - [ 0x0B01, 0x0B03 ], + [ 0x0AE0, 0x0AE1 ], [ 0x0B05, 0x0B0C ], [ 0x0B0F, 0x0B10 ], [ 0x0B13, 0x0B28 ], [ 0x0B2A, 0x0B30 ], [ 0x0B32, 0x0B33 ], - [ 0x0B36, 0x0B39 ], + [ 0x0B35, 0x0B39 ], [ 0x0B3D, 0x0B3D ], - [ 0x0B3E, 0x0B43 ], - [ 0x0B47, 0x0B48 ], - [ 0x0B4B, 0x0B4D ], [ 0x0B5C, 0x0B5D ], [ 0x0B5F, 0x0B61 ], - [ 0x0B66, 0x0B6F ], - [ 0x0B82, 0x0B83 ], + [ 0x0B71, 0x0B71 ], + [ 0x0B83, 0x0B83 ], [ 0x0B85, 0x0B8A ], [ 0x0B8E, 0x0B90 ], [ 0x0B92, 0x0B95 ], @@ -316,50 +285,34 @@ [ 0x0B9E, 0x0B9F ], [ 0x0BA3, 0x0BA4 ], [ 0x0BA8, 0x0BAA ], - [ 0x0BAE, 0x0BB5 ], - [ 0x0BB7, 0x0BB9 ], - [ 0x0BBE, 0x0BC2 ], - [ 0x0BC6, 0x0BC8 ], - [ 0x0BCA, 0x0BCD ], - [ 0x0BE7, 0x0BEF ], - [ 0x0C01, 0x0C03 ], + [ 0x0BAE, 0x0BB9 ], [ 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 ], + [ 0x0CBD, 0x0CBD ], [ 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 ], // Digits? Why does this overlap previous? - + [ 0x0D85, 0x0D96 ], + [ 0x0D9A, 0x0DB1 ], + [ 0x0DB3, 0x0DBB ], + [ 0x0DBD, 0x0DBD ], + [ 0x0DC0, 0x0DC6 ], + [ 0x0E01, 0x0E30 ], + [ 0x0E32, 0x0E33 ], + [ 0x0E40, 0x0E46 ], [ 0x0E81, 0x0E82 ], [ 0x0E84, 0x0E84 ], [ 0x0E87, 0x0E88 ], @@ -371,31 +324,68 @@ [ 0x0EA5, 0x0EA5 ], [ 0x0EA7, 0x0EA7 ], [ 0x0EAA, 0x0EAB ], - [ 0x0EAD, 0x0EAE ], - [ 0x0EB0, 0x0EB9 ], - [ 0x0EBB, 0x0EBD ], + [ 0x0EAD, 0x0EB0 ], + [ 0x0EB2, 0x0EB3 ], + [ 0x0EBD, 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 ], + [ 0x0F40, 0x0F47 ], + [ 0x0F49, 0x0F6A ], + [ 0x0F88, 0x0F8B ], + [ 0x1000, 0x1021 ], + [ 0x1023, 0x1027 ], + [ 0x1029, 0x102A ], + [ 0x1050, 0x1055 ], [ 0x10A0, 0x10C5 ], - [ 0x10D0, 0x10F6 ], + [ 0x10D0, 0x10FA ], + [ 0x10FC, 0x10FC ], + [ 0x1100, 0x1159 ], + [ 0x115F, 0x11A2 ], + [ 0x11A8, 0x11F9 ], + [ 0x1200, 0x1248 ], + [ 0x124A, 0x124D ], + [ 0x1250, 0x1256 ], + [ 0x1258, 0x1258 ], + [ 0x125A, 0x125D ], + [ 0x1260, 0x1288 ], + [ 0x128A, 0x128D ], + [ 0x1290, 0x12B0 ], + [ 0x12B2, 0x12B5 ], + [ 0x12B8, 0x12BE ], + [ 0x12C0, 0x12C0 ], + [ 0x12C2, 0x12C5 ], + [ 0x12C8, 0x12D6 ], + [ 0x12D8, 0x1310 ], + [ 0x1312, 0x1315 ], + [ 0x1318, 0x135A ], + [ 0x1380, 0x138F ], + [ 0x13A0, 0x13F4 ], + [ 0x1401, 0x166C ], + [ 0x166F, 0x1676 ], + [ 0x1681, 0x169A ], + [ 0x16A0, 0x16EA ], + [ 0x1700, 0x170C ], + [ 0x170E, 0x1711 ], + [ 0x1720, 0x1731 ], + [ 0x1740, 0x1751 ], + [ 0x1760, 0x176C ], + [ 0x176E, 0x1770 ], + [ 0x1780, 0x17B3 ], + [ 0x17D7, 0x17D7 ], + [ 0x17DC, 0x17DC ], + [ 0x1820, 0x1877 ], + [ 0x1880, 0x18A8 ], + [ 0x1900, 0x191C ], + [ 0x1950, 0x196D ], + [ 0x1970, 0x1974 ], + [ 0x1980, 0x19A9 ], + [ 0x19C1, 0x19C7 ], + [ 0x1A00, 0x1A16 ], + [ 0x1B05, 0x1B33 ], + [ 0x1B45, 0x1B4B ], + [ 0x1D00, 0x1DBF ], [ 0x1E00, 0x1E9B ], [ 0x1EA0, 0x1EF9 ], [ 0x1F00, 0x1F15 ], @@ -417,30 +407,145 @@ [ 0x1FE0, 0x1FEC ], [ 0x1FF2, 0x1FF4 ], [ 0x1FF6, 0x1FFC ], - [ 0x203F, 0x2040 ], + [ 0x2071, 0x2071 ], [ 0x207F, 0x207F ], + [ 0x2090, 0x2094 ], [ 0x2102, 0x2102 ], [ 0x2107, 0x2107 ], [ 0x210A, 0x2113 ], [ 0x2115, 0x2115 ], - [ 0x2118, 0x211D ], + [ 0x2119, 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 ], + [ 0x212A, 0x212D ], + [ 0x212F, 0x2139 ], + [ 0x213C, 0x213F ], + [ 0x2145, 0x2149 ], + [ 0x214E, 0x214E ], + [ 0x2183, 0x2184 ], + [ 0x2C00, 0x2C2E ], + [ 0x2C30, 0x2C5E ], + [ 0x2C60, 0x2C6C ], + [ 0x2C74, 0x2C77 ], + [ 0x2C80, 0x2CE4 ], + [ 0x2D00, 0x2D25 ], + [ 0x2D30, 0x2D65 ], + [ 0x2D6F, 0x2D6F ], + [ 0x2D80, 0x2D96 ], + [ 0x2DA0, 0x2DA6 ], + [ 0x2DA8, 0x2DAE ], + [ 0x2DB0, 0x2DB6 ], + [ 0x2DB8, 0x2DBE ], + [ 0x2DC0, 0x2DC6 ], + [ 0x2DC8, 0x2DCE ], + [ 0x2DD0, 0x2DD6 ], + [ 0x2DD8, 0x2DDE ], + [ 0x3005, 0x3006 ], + [ 0x3031, 0x3035 ], + [ 0x303B, 0x303C ], + [ 0x3041, 0x3096 ], + [ 0x309D, 0x309F ], + [ 0x30A1, 0x30FA ], + [ 0x30FC, 0x30FF ], [ 0x3105, 0x312C ], - [ 0x4E00, 0x9FA5 ], + [ 0x3131, 0x318E ], + [ 0x31A0, 0x31B7 ], + [ 0x31F0, 0x31FF ], + [ 0x3400, 0x4DB5 ], + [ 0x4E00, 0x9FBB ], + [ 0xA000, 0xA48C ], + [ 0xA717, 0xA71A ], + [ 0xA800, 0xA801 ], + [ 0xA803, 0xA805 ], + [ 0xA807, 0xA80A ], + [ 0xA80C, 0xA822 ], + [ 0xA840, 0xA873 ], [ 0xAC00, 0xD7A3 ], + [ 0xF900, 0xFA2D ], + [ 0xFA30, 0xFA6A ], + [ 0xFA70, 0xFAD9 ], + [ 0xFB00, 0xFB06 ], + [ 0xFB13, 0xFB17 ], + [ 0xFB1D, 0xFB1D ], + [ 0xFB1F, 0xFB28 ], + [ 0xFB2A, 0xFB36 ], + [ 0xFB38, 0xFB3C ], + [ 0xFB3E, 0xFB3E ], + [ 0xFB40, 0xFB41 ], + [ 0xFB43, 0xFB44 ], + [ 0xFB46, 0xFBB1 ], + [ 0xFBD3, 0xFD3D ], + [ 0xFD50, 0xFD8F ], + [ 0xFD92, 0xFDC7 ], + [ 0xFDF0, 0xFDFB ], + [ 0xFE70, 0xFE74 ], + [ 0xFE76, 0xFEFC ], [ 0xFF21, 0xFF3A ], [ 0xFF41, 0xFF5A ], + [ 0xFF66, 0xFFBE ], + [ 0xFFC2, 0xFFC7 ], + [ 0xFFCA, 0xFFCF ], + [ 0xFFD2, 0xFFD7 ], + [ 0xFFDA, 0xFFDC ], + [ 0x10000, 0x1000B ], + [ 0x1000D, 0x10026 ], + [ 0x10028, 0x1003A ], + [ 0x1003C, 0x1003D ], + [ 0x1003F, 0x1004D ], + [ 0x10050, 0x1005D ], + [ 0x10080, 0x100FA ], + [ 0x10300, 0x1031E ], + [ 0x10330, 0x10340 ], + [ 0x10342, 0x10349 ], + [ 0x10380, 0x1039D ], + [ 0x103A0, 0x103C3 ], + [ 0x103C8, 0x103CF ], + [ 0x10400, 0x1049D ], + [ 0x10800, 0x10805 ], + [ 0x10808, 0x10808 ], + [ 0x1080A, 0x10835 ], + [ 0x10837, 0x10838 ], + [ 0x1083C, 0x1083C ], + [ 0x1083F, 0x1083F ], + [ 0x10900, 0x10915 ], + [ 0x10A00, 0x10A00 ], + [ 0x10A10, 0x10A13 ], + [ 0x10A15, 0x10A17 ], + [ 0x10A19, 0x10A33 ], + [ 0x12000, 0x1236E ], + [ 0x1D400, 0x1D454 ], + [ 0x1D456, 0x1D49C ], + [ 0x1D49E, 0x1D49F ], + [ 0x1D4A2, 0x1D4A2 ], + [ 0x1D4A5, 0x1D4A6 ], + [ 0x1D4A9, 0x1D4AC ], + [ 0x1D4AE, 0x1D4B9 ], + [ 0x1D4BB, 0x1D4BB ], + [ 0x1D4BD, 0x1D4C3 ], + [ 0x1D4C5, 0x1D505 ], + [ 0x1D507, 0x1D50A ], + [ 0x1D50D, 0x1D514 ], + [ 0x1D516, 0x1D51C ], + [ 0x1D51E, 0x1D539 ], + [ 0x1D53B, 0x1D53E ], + [ 0x1D540, 0x1D544 ], + [ 0x1D546, 0x1D546 ], + [ 0x1D54A, 0x1D550 ], + [ 0x1D552, 0x1D6A5 ], + [ 0x1D6A8, 0x1D6C0 ], + [ 0x1D6C2, 0x1D6DA ], + [ 0x1D6DC, 0x1D6FA ], + [ 0x1D6FC, 0x1D714 ], + [ 0x1D716, 0x1D734 ], + [ 0x1D736, 0x1D74E ], + [ 0x1D750, 0x1D76E ], + [ 0x1D770, 0x1D788 ], + [ 0x1D78A, 0x1D7A8 ], + [ 0x1D7AA, 0x1D7C2 ], + [ 0x1D7C4, 0x1D7CB ], + [ 0x20000, 0x2A6D6 ], + [ 0x2F800, 0x2FA1D ], ]; debug @@ -457,8 +562,18 @@ } } - if (u > 0xD7A3 && u < 0xFF21) + if (u < 0xAA) + { + if (u < 'A') + goto Lisnot; + if (u <= 'Z') + goto Lis; + if (u < 'a') + goto Lisnot; + if (u <= 'z') + goto Lis; goto Lisnot; + } // Binary search uint mid; @@ -491,12 +606,12 @@ Lis: debug { - for (int i = 0; 1; i++) + for (int i = 0; i < table.length; i++) { - assert(i < table.length); // should have been in table if (u >= table[i][0] && u <= table[i][1]) - break; + return 1; } + assert(0); // should have been in table } return 1; } diff -uNr gdc-0.23/d/phobos/std/windows/registry.d gdc-0.24/d/phobos/std/windows/registry.d --- gdc-0.23/d/phobos/std/windows/registry.d 2007-02-26 00:37:57.000000000 +0100 +++ gdc-0.24/d/phobos/std/windows/registry.d 2007-07-23 02:23:26.000000000 +0200 @@ -10,43 +10,26 @@ * * License: * - * Copyright (C) 2002-2004, Synesis Software Pty Ltd. + * Copyright 2003-2004 by Matthew Wilson and Synesis Software + * Written by Matthew Wilson * - * All rights reserved. + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. * - * www: http://www.synesis.com.au/software - * http://www.synsoft.org/ + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: * - * email: submissions@synsoft.org for submissions - * admin@synsoft.org for other enquiries - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, in both source and binary form, subject to the following - * restrictions: - * - * - The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - This notice may not be removed or altered from any source - * distribution. - * - * This source code is provided by Synesis Software "as is" and any - * warranties, whether expressed or implied, including, but not - * limited to, the implied warranties of merchantability and - * fitness for a particular purpose are disclaimed. In no event - * shall the Synesis Software be liable for any direct, indirect, - * incidental, special, exemplary, or consequential damages - * (including, but not limited to, procurement of substitute goods - * or services; loss of use, data, or profits; or business - * interruption) however caused and on any theory of liability, - * whether in contract, strict liability, or tort (including - * negligence or otherwise) arising in any way out of the use of - * this software, even if advised of the possibility of such - * damage. + * - The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * - Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * - This notice may not be removed or altered from any source + * distribution. * * ////////////////////////////////////////////////////////////////////////// */ @@ -1612,7 +1595,7 @@ } private: - this(); + this() { } /// \name Hives //@{ diff -uNr gdc-0.23/d/phobos/std.ddoc gdc-0.24/d/phobos/std.ddoc --- gdc-0.23/d/phobos/std.ddoc 2007-02-08 19:07:06.000000000 +0100 +++ gdc-0.24/d/phobos/std.ddoc 2007-04-29 20:05:44.000000000 +0200 @@ -11,7 +11,7 @@ -Digital Mars - The D Programming Language - $(TITLE) +$(TITLE) - D Programming Language - Digital Mars @@ -111,7 +111,7 @@

    std

    $(UL $(LI std.base64) - $(LI std.bind) + $(LI std.bind) $(LI std.bitarray) $(LI std.boxer) $(LI std.compiler) diff -uNr gdc-0.23/d/phobos/win32.mak gdc-0.24/d/phobos/win32.mak --- gdc-0.23/d/phobos/win32.mak 2007-02-08 19:07:06.000000000 +0100 +++ gdc-0.24/d/phobos/win32.mak 2007-07-23 02:23:26.000000000 +0200 @@ -15,17 +15,19 @@ # This relies on LIB.EXE 8.00 or later, and MAKE.EXE 5.01 or later. CP=cp +DIR=\dmd CFLAGS=-mn -6 -r #CFLAGS=-g -mn -6 -r DFLAGS=-O -release -nofloat -w +#DFLAGS=-nofloat -w #DFLAGS=-unittest -g -w #DFLAGS=-unittest -cov -g CC=dmc -DMD=\dmd\bin\dmd +DMD=$(DIR)\bin\dmd #DMD=..\dmd DOC=..\..\html\d\phobos @@ -66,7 +68,7 @@ compiler.obj system.obj moduleinit.obj md5.obj base64.obj \ cast.obj syserror.obj path.obj string.obj memset.obj math.obj \ outbuffer.obj ctype.obj regexp.obj random.obj windows.obj stat.obj \ - stream.obj switcherr.obj com.obj array.obj gc.obj mmfile.obj \ + stream.obj switcherr.obj com.obj array.obj mmfile.obj \ qsort.obj math2.obj date.obj dateparse.obj thread.obj obj.obj \ iunknown.obj crc32.obj conv.obj arraycast.obj utf.obj uri.obj \ Czlib.obj Dzlib.obj zip.obj process.obj registry.obj \ @@ -842,18 +844,18 @@ del $(DOCS) install: - $(CP) phobos.lib gcstub.obj \dmd\lib - $(CP) win32.mak linux.mak phoboslicense.txt minit.obj std.ddoc \dmd\src\phobos - $(CP) $(SRC) \dmd\src\phobos - $(CP) $(SRC_STD) \dmd\src\phobos\std - $(CP) $(SRC_STD_C) \dmd\src\phobos\std\c - $(CP) $(SRC_TI) \dmd\src\phobos\std\typeinfo - $(CP) $(SRC_INT) \dmd\src\phobos\internal - $(CP) $(SRC_STD_WIN) \dmd\src\phobos\std\windows - $(CP) $(SRC_STD_C_WIN) \dmd\src\phobos\std\c\windows - $(CP) $(SRC_STD_C_LINUX) \dmd\src\phobos\std\c\linux - $(CP) $(SRC_ETC) \dmd\src\phobos\etc - $(CP) $(SRC_ETC_C) \dmd\src\phobos\etc\c - $(CP) $(SRC_ZLIB) \dmd\src\phobos\etc\c\zlib - $(CP) $(SRC_GC) \dmd\src\phobos\internal\gc + $(CP) phobos.lib gcstub.obj $(DIR)\lib + $(CP) win32.mak linux.mak phoboslicense.txt minit.obj std.ddoc $(DIR)\src\phobos + $(CP) $(SRC) $(DIR)\src\phobos + $(CP) $(SRC_STD) $(DIR)\src\phobos\std + $(CP) $(SRC_STD_C) $(DIR)\src\phobos\std\c + $(CP) $(SRC_TI) $(DIR)\src\phobos\std\typeinfo + $(CP) $(SRC_INT) $(DIR)\src\phobos\internal + $(CP) $(SRC_STD_WIN) $(DIR)\src\phobos\std\windows + $(CP) $(SRC_STD_C_WIN) $(DIR)\src\phobos\std\c\windows + $(CP) $(SRC_STD_C_LINUX) $(DIR)\src\phobos\std\c\linux + $(CP) $(SRC_ETC) $(DIR)\src\phobos\etc + $(CP) $(SRC_ETC_C) $(DIR)\src\phobos\etc\c + $(CP) $(SRC_ZLIB) $(DIR)\src\phobos\etc\c\zlib + $(CP) $(SRC_GC) $(DIR)\src\phobos\internal\gc diff -uNr gdc-0.23/d/rdmd.1 gdc-0.24/d/rdmd.1 --- gdc-0.23/d/rdmd.1 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.24/d/rdmd.1 2007-08-22 04:20:58.000000000 +0200 @@ -0,0 +1,31 @@ +.TH rdmd 1 +.SH NAME +rdmd - DMD Script Shell +.SH SYNOPSIS +.B rdmd +.I [dmd arguments] +.I [rdmd arguments] +progfile.d +.I [program arguments] +.SH OPTIONS +.IP --help +This message +.IP --force +Force re-compilation of source code [default = do not force] +.IP --verbose +Show detailed info of operations [default = do not show] +.IP --compiler=(dmd|gdmd) +Specify compiler [default = same compiler that compiled rdmd] +.IP --tmpdir=tmp_dir_path +Specify directory to store cached program and other temporaries [default = /tmp] +.SH NOTES +dmd or gdmd must be in the current user context $PATH + +rdmd does not support execution of D source code via stdin + +rdmd will only compile and execute files with '.d' or '.ds' file extensions +.SH AUTHOR +written by Dave Fladebo (linux version) +and Robert Mariottini (Windows version) +.SH COPYRIGHT +released into the public domain diff -uNr gdc-0.23/d/rdmd.d gdc-0.24/d/rdmd.d --- gdc-0.23/d/rdmd.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.24/d/rdmd.d 2007-08-22 07:35:00.000000000 +0200 @@ -0,0 +1,392 @@ +// rdmd - a program to compile, cache and execute D programming +// language source files via either the command-line or as a +// 'pseudo shell script' on POSIX conforming Linux/Unix systems. +// +// Written by Dave Fladebo and released into the public domain as +// explained by http://creativecommons.org/licenses/publicdomain +// Windows version by Roberto Mariottini, GDC/Unix version by afb. +// +// This software is provided "AS IS" and without any express or +// implied warranties, including and without limitation to, any +// warranty of merchantability or fitness for any purpose. +// +// version 1.2 + +version (Windows) +{ + import std.c.windows.windows; + + char[] fileSeparator = "\\"; + char[] pathSeparator = ";"; + char[] objectExtension = ".obj"; + char[] exeExtension = ".exe"; +} +else version (linux) +{ + import std.c.linux.linux; + + char[] fileSeparator = "/"; + char[] pathSeparator = ":"; + char[] objectExtension = ".o"; + char[] exeExtension = ""; +} +else version (Unix) +{ + import std.c.unix.unix; + + char[] fileSeparator = "/"; + char[] pathSeparator = ":"; + char[] objectExtension = ".o"; + char[] exeExtension = ""; +} +else static assert(0); + +version (DigitalMars) + version (linux) + version = Unix; + +bool verbose = false; + +import std.c.stdlib, std.file, std.md5, std.process, std.stdio, std.string; + +version (Unix) +{ + extern(C) ushort getuid(); // moved to top, because of mac linker issues +} + +int main(char[][] args) +{ + int retval = -1; + bool havefile = false, force = false; + char[][] cmpv, argv; // cmpv = compiler arguments, argv = program arguments + char[] exepath, dfilepath, compiler = "dmd", tmpdir = "/tmp"; + + version (GNU) + { + compiler = "gdmd"; + } + version (Windows) + { + tmpdir = toString(getenv("TEMP")); + } + + .myname = args[0]; + .defcmp = compiler; + + foreach(int i, char[] arg; args) + { + if(i == 0) + continue; + + if(find(arg,".d") >= 0 || find(arg,".ds") >= 0) + { + havefile = true; + dfilepath = arg; + } + else + { + if(havefile == false) + { + bool skip = false; + if(arg == "--help") + usage; + else if(arg == "--force") + skip = force = true; + else if(arg == "--verbose") + skip = verbose = true; + else + { + const char[] cs = "--compiler="; + if(arg.length > cs.length && arg[0..cs.length] == cs) + { + compiler = split(arg,"=")[1]; + skip = true; + } + const char[] td = "--tmpdir="; + if(arg.length > td.length && arg[0..td.length] == td) + { + tmpdir = split(arg,"=")[1]; + skip = true; + } + } + + if(!skip) + cmpv ~= arg; + } + else + argv ~= arg; + } + } + + if(!havefile) + error("Couldn't find any D source code file to compile or execute.", retval); + + if(compile(tmpdir,compiler,force,dfilepath,cmpv,exepath)) + { + char[][] exeargv; + version (Windows) + { + exeargv ~= "\"" ~ exepath ~ "\""; + foreach(char[] arg; argv) exeargv ~= "\"" ~ arg ~ "\""; + } + else + { + exeargv ~= exepath; + foreach(char[] arg; argv) exeargv ~= arg; + } + + if(verbose) + { + fwritef(stderr,"running: "); + foreach(char[] arg; exeargv) + { + fwritef(stderr,arg," "); + } + fwritefln(stderr); + } + + // execute + version (Windows) + { + retval = spawnvp(std.c.process._P_WAIT, exepath, exeargv); + } + else + { + retval = spawnapp(exepath,exeargv); + } + } + else + { + try { std.file.remove(exepath); } catch {} + error("Couldn't compile or execute " ~ dfilepath ~ ".", retval); + } + + return retval; +} + +char[] myname; +char[] defcmp; +void error(char[] errmsg, int errno) +{ + fwritefln(stderr,myname,": ",errmsg); + exit(errno); +} + +void usage() +{ + fwritefln(stderr,"Usage:"); + fwritefln(stderr," ",myname," [D compiler arguments] [",myname," arguments] progfile.d [program arguments]"); + fwritefln(stderr); + fwritefln(stderr,myname," arguments:"); + fwritefln(stderr," --help\t\tThis message"); + fwritefln(stderr," --force\t\tForce re-compilation of source code [default = do not force]"); + fwritefln(stderr," --verbose\t\tShow detailed info of operations [default = do not show]"); + fwritefln(stderr," --compiler=(dmd|gdmd)\tSpecify compiler [default = "~ .defcmp ~"]"); + fwritefln(stderr," --tmpdir=tmp_dir_path\tSpecify directory to store cached program and other temporaries [default = /tmp]"); + fwritefln(stderr); + fwritefln(stderr,"Notes:"); + fwritefln(stderr," dmd or gdmd must be in the current user context $PATH"); + fwritefln(stderr," ",myname," does not support execution of D source code via stdin"); + fwritefln(stderr," ",myname," will only compile and execute files with a '.d' file extension"); + exit(EXIT_SUCCESS); +} + +bool compile(char[] tmpdir, char[] compiler, bool force, char[] dfilepath, char[][] cmpv, inout char[] exepath) +{ + int retval = 0; + + struct_stat dfilestat; // D source code file status info. + int filrv = stat(toStringz(dfilepath),&dfilestat); + + char[][] pathcomps = split(dfilepath,fileSeparator); + char[] exefile = split(pathcomps[$-1],".")[0]; + + char[] cmdline = compiler ~ " -quiet"; + foreach(char[] str; cmpv) + if(str != "") + cmdline ~= " " ~ str; + + // MD5 sum of compiler arguments + ubyte[16] digest; + sum(digest,cast(void[])cmdline); + + // directory for temp. files + if(!tmpdir.length) + tmpdir = "/tmp/"; + else + if(tmpdir[$-1] != fileSeparator[0]) + tmpdir ~= fileSeparator; + + // exe filename format is basename-uid-filesysdev-inode-MD5 + // append MD5 sum of the compiler arguments onto the file name to force recompile if they have changed + char[] uid_str; + version(Windows) + uid_str = getuid(); + else + uid_str = toString(getuid()); + exepath = tmpdir ~ exefile ~ "-" ~ uid_str ~ "-" ~ toString(dfilestat.st_dev) ~ "-" ~ toString(dfilestat.st_ino) ~ "-" ~ digestToString(digest) ~ exeExtension; + + struct_stat exestat; // temp. executable status info. + int exerv = stat(toStringz(exepath),&exestat); + if(force || // force compilation + exerv || // stat returned an error (e.g.: no exefile) + dfilestat.st_mtime > exestat.st_mtime || // source code file is newer than executable + progstat(.myname).st_mtime > exestat.st_mtime || // this program is newer than executable + progstat(compiler).st_mtime > exestat.st_mtime) // compiler is newer than executable + { + cmdline ~= " " ~ dfilepath ~ " -of" ~ exepath ~ " -od" ~ tmpdir; + if(verbose) + { + fwritefln(stderr,"running: ",cmdline); + } + retval = std.process.system(cmdline); // compile ("system" is also in std.c.stdlib) + chmod(toStringz(exepath),0700); + } + + // remove object file + try { std.file.remove(tmpdir ~ exefile ~ objectExtension); } catch {} + + return cast(bool)(retval == 0); +} + +struct_stat progstat(char[] program) +{ + struct_stat progstat; // D source code file status info. + + try + { + int prgrv; + if(find(program,fileSeparator) >= 0) + prgrv = stat(toStringz(program), &progstat); + else + { + // There's got to be a better way... + char[][] pathdirs = split(toString(getenv("PATH")),pathSeparator); + foreach(char[] dir; pathdirs) + { + prgrv = stat(toStringz(dir ~ fileSeparator ~ program), &progstat); + if (prgrv == 0) + { + break; + } + } + } + } + catch {} + + return progstat; +} + +version (Unix) +{ +extern(C) char* strerror(int); + +int spawnapp(char[] pathname, char[][] argv) +{ + int retval = 0; + pid_t pid = fork(); + + if(pid != -1) + { + if(pid == 0) + { + execv(pathname,argv); + goto Lerror; + } + + while(1) + { + int status; + pid_t wpid = waitpid(pid, &status, 0); + if(exited(status)) + { + retval = exitstatus(status); + break; + } + else if(signaled(status)) + { + retval = -termsig(status); + break; + } + else if(stopped(status)) // ptrace support + continue; + else + goto Lerror; + } + + return retval; + } + +Lerror: + retval = getErrno; + error("Cannot spawn " ~ pathname ~ "; " ~ toString(strerror(retval)) ~ " [errno " ~ toString(retval) ~ "]", retval); + return retval; +} + +bool stopped(int status) { return cast(bool)((status & 0xff) == 0x7f); } +bool signaled(int status) { return cast(bool)((cast(char)((status & 0x7f) + 1) >> 1) > 0); } +int termsig(int status) { return status & 0x7f; } +bool exited(int status) { return cast(bool)((status & 0x7f) == 0); } +int exitstatus(int status) { return (status & 0xff00) >> 8; } + +} // version (Unix) + +version (Windows) +{ + extern (Windows) + { + BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, + LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime); + BOOL GetUserNameA(LPTSTR lpBuffer, LPDWORD nSize); + } + + // fake struct stat + struct struct_stat + { + ulong st_dev; + uint st_ino; + ulong st_mtime; + } + + // fake stat function + int stat(char* name, struct_stat* st) + { + int retval = -1; + HANDLE h = CreateFileA(name, FILE_GENERIC_READ, 0, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, null); + if (h != INVALID_HANDLE_VALUE) + { + FILETIME lastWriteTime; + if (GetFileTime(h, null, null, &lastWriteTime)) + { + st.st_mtime = lastWriteTime.dwHighDateTime; + st.st_mtime <<= 32; + st.st_mtime |= lastWriteTime.dwLowDateTime; + retval = 0; + } + CloseHandle(h); + } + if(verbose) + { + fwritefln(stderr,"stat: ",toString(name)," : ",retval); + } + return retval; + } + + // fake getuid function + char[] getuid() + { + char[] buffer; + DWORD size = buffer.length = 64; + if(GetUserNameA(buffer.ptr, &size)) + { + buffer.length = size; + return buffer; + } + return ""; + } + + // fake chmod function + void chmod(...) + { + } +} diff -uNr gdc-0.23/d/README gdc-0.24/d/README --- gdc-0.23/d/README 2007-03-05 01:42:21.000000000 +0100 +++ gdc-0.24/d/README 2007-08-22 05:21:08.000000000 +0200 @@ -1,12 +1,14 @@ -D Front End for GCC - Release 0.23 +D Front End for GCC - Release 0.24 -Last update: March 4, 2007 +Last update: August 22, 2007 -Release Notes for 0.23 - * Added support for 64-bit targets - * Added multilib support - * Updated to DMD 1.007 - * Fixed Bugzilla 984, 1013 +Release Notes for 0.24 + * Removed support for GCC 3.3.x + * Updated to DMD 1.020 + * Fixed Bugzilla 1037, 1038 (gdc specific), 1043, 1045, 1046, + 1031, 1032, 1034, 1065, 1109, 1191, 1137, 1152, 1208, 1325, + 1329, 1898, 1400 + * Fixed SourceForge issues 1689634, 1749622, 1721496, 1721435 Supported Systems diff -uNr gdc-0.23/d/setup-gcc.sh gdc-0.24/d/setup-gcc.sh --- gdc-0.23/d/setup-gcc.sh 2007-02-28 02:05:05.000000000 +0100 +++ gdc-0.24/d/setup-gcc.sh 2007-03-10 15:58:53.000000000 +0100 @@ -10,9 +10,7 @@ top=`pwd` # 0. Find out what GCC version this is -if grep version_string gcc/version.c | grep -q '"3.3'; then - gcc_ver=3.3 -elif grep version_string gcc/version.c | grep -q '"3.4'; then +if grep version_string gcc/version.c | grep -q '"3.4'; then gcc_ver=3.4 elif grep version_string gcc/version.c | grep -q '"4.0'; then gcc_ver=4.0 @@ -73,17 +71,6 @@ if test -f d/patch-gcc-darwin-eh-${gcc_ver}.x; then patch -p1 < d/patch-gcc-darwin-eh-${gcc_ver}.x || exit 1 fi - 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 - elif test "$gcc_ver" = 4.0; then - # Framework support is built in. - : - else - echo - echo "Note: The MacOS X frameworks patch does not support GCC $gcc_ver." - fi fi echo