From f2237662df175c9d5fa17c84be847a3ba3939f63 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Thu, 5 Apr 2012 11:45:25 +0400 Subject: [PATCH] Squashed 'dmd2/' changes from 10017d5..3443f38 3443f38 Fix issue 7493 Initialization of void[][N] 0b371da foreach can run semantic again 7216e2a fix Issue 7735 - Functions with variadic void[][]... arguments corrupt passed data 4fb2b2a Merge pull request #850 from 9rnsr/fix7773 9c59931 Merge pull request #851 from donc/ctfe7785pointerToVar 407f7e4 Merge pull request #852 from donc/segfault7639 9370f83 Fix issue 7380 Crash trying to use address of variable in struct constructor at module level 240866b Fix issue 7639 Undefined enum AA key crashes compiler 19b7096 Fix issue 7785 [CTFE] ICE when slicing pointer to variable d9b11f6 fix Issue 7773 - UCFS syntax on built-in attributes too? 296d812 Merge pull request #846 from donc/ctfe7781segfault 65aca2d Merge pull request #848 from donc/regression7751 5576737 Merge pull request #849 from donc/bug7794 0310838 Merge pull request #828 from 9rnsr/fix7751 4027e4f Fix issue 7794 Sea of errors when calling regex() after compile error 59cc12d Fix issue 7781 [CTFE] Segmentation fault on 'mixin({return;}());' 3430947 fix seg fault in fail91.d 948274e Merge pull request #824 from donc/regression7745 22ac4b1 Merge pull request #826 from 9rnsr/fix6659 1c15841 Merge pull request #823 from redstar/mscclean 5f54752 Merge pull request #827 from 9rnsr/fix7694 399e4a3 Merge pull request #844 from donc/regression7782 516f49b Fix issue 7789 [CTFE] null pointer exception on setting array length d74b354 Fix issue 7782 Regression: ICE with wrong import syntax 0269194 Fix issue 7751 [ICE] (Regression 2.059head) From auto and forward reference 42ad236 Merge pull request #830 from 9rnsr/fix_ufcs 67bf025 Merge pull request #832 from 9rnsr/fix7608 d13f107 Merge pull request #829 from 9rnsr/fix7754 e25cbe2 Merge pull request #834 from 9rnsr/fix2367 7fac235 merge D2 pull #842 c836773 Merge pull request #836 from 9rnsr/fix7757 a2754c5 Merge pull request #839 from 9rnsr/fix7768 4948836 fix Issue 7694 - Internal error: e2ir.c 1251 when calling member function inside struct via alias param 9f23335 Merge pull request #838 from 9rnsr/fix7621 92eba60 Merge pull request #840 from 9rnsr/fix7769 8fae3c2 fix issue 7742 - 'More initializers than fields' error with correct number of fields 6c2d706 to enum 35e4f08 fix Issue 7769 - relax inout rule doesn't work for template function 96a0105 fix Issue 7768 - More readable template error messages 8012d58 Merge pull request #831 from 9rnsr/fix7743 9c0cbdd fix Issue 7621 - Immutable type equivalence problem f67f313 Merge pull request #833 from 9rnsr/fix7731 29754dd Merge pull request #837 from braddr/cleanup-backend2 374109a restore original binary() function and re-fix the new version 78c04aa fix Issue 7757 - Inout function with lazy inout parameter doesn't compile 50c34e9 fix Issue 7754 - static this() in template is stripped during header gen 11acdff Fix auto tester breaking. f0b7157 fix Issue 7755 - regression(2.059head): ICE in glue.c cfceb77 fix Issue 7751 - [ICE] From auto and forward reference 7a86807 fix Issue 2367 - Overloading error with string literals 6039c40 fix Issue 7731 - Assertion failure: 't' on line 7911 in file 'mtype.c' aea3a39 fix Issue 7608 - __traits(allMembers) is broken f46f07a fix Issue 7743 - Parsing problem with nothrow delegate fa9d29f Revert "Revert "Refactor for UFCS property getter/setter resolution."" d9698d8 Revert "Revert "fix Issue 7722 - Refuse normal functions to be used as properties"" 0fbc772 Revert "Revert "Allow property function has two arguments"" 07a3b09 fix Issue 6659 - Destructor in range foreach called after initialization e499d4d Fix issue 7745 Regression(2.059beta) Methods defined in external object files when a pointer to it is taken 79a74e1 Fixes an unknown pragma warning. 2b12052 Fix issue 176 [module] message "module and package have the same name" 90e89a4 Merge pull request #814 from 9rnsr/fix7713 3ab0e79 Merge pull request #818 from donc/assoc7732 b3360e9 Fix issue 7732 [CTFE] wrong code for a struct called AssociativeArray 05f0b08 Merge pull request #779 from 9rnsr/fix7534 867e567 Revert "Allow property function has two arguments" 9171aeb Revert "fix Issue 7722 - Refuse normal functions to be used as properties" 989ced7 Revert "Refactor for UFCS property getter/setter resolution." e9b5292 Refactor for UFCS property getter/setter resolution. 761d000 fix Issue 7722 - Refuse normal functions to be used as properties 9f5956b Allow property function has two arguments 1a11862 Revert "Allow property function has two arguments" 32f57e5 Revert "fix Issue 7722 - Refuse normal functions to be used as properties" 6489bb4 Revert "Refactor for UFCS property getter/setter resolution." 214296f Merge pull request #817 from 9rnsr/fix_ufcs c3c7f2a Merge pull request #816 from donc/voidctfe6438 185d031 Refactor for UFCS property getter/setter resolution. 08bf89d fix Issue 7722 - Refuse normal functions to be used as properties f0e3433 Allow property function has two arguments 1b67ac9 Direct check by Type::reliesOnTident a3cd7d9 fix Issue 7713 - lambda inference doesn't work on template function argument 1762112 Fix issue 6438 - [CTFE] wrong error "value used before set" when slicing =void array ace1eca fix complex constant folding 76f9b22 Consider return type covariance. f700dbc fix Issue 7534 - Allow attribute-overloading of an overridden method cba8f5c Merge pull request #763 from 9rnsr/fix7578 392d93f Merge pull request #815 from dawgfoto/fixSegFault e48aba2 merge part of pull #769 d72a17e revert dd5a543 24d860b error(Loc loc,) doesn't abort program 4c79117 Use correct opcodes for moving cfloat from st->xmm and xmm->st af875ff Merge pull request #785 from braddr/cleanup-backend2 9d3021a remove debugging printfs b3df5ee Merge pull request #807 from dawgfoto/fix7698 f005537 Merge pull request #802 from dawgfoto/fixVC 65a145d Merge pull request #803 from donc/ctfeunion6681yebblies 1cf39ca Merge pull request #812 from 9rnsr/fix_ufcs d846c3c Merge pull request #808 from 9rnsr/fix7702 fd0a492 fix Issue 7670 - UFCS problem with @property and structs 1ad35b2 Fix for UFCS with property syntax, and add exhaustive test 96f15a1 Resolve broken build after merging 4712aab fix regression 4e05482 Merge pull request #805 from donc/regression7681 245a107 dt_ functions aren't x86 specific b35f43a another missing loc in an error() call 001addb minor cleanups 2fb1e46 make util_assert take a const string 907da39 cleanup whitespace in binary(), add binary() that takes the length of the string to search for 59d0425 Merge pull request #804 from braddr/nearsighted d725eed Merge pull request #806 from donc/ctfe7633equalmsg 12a5c26 Merge pull request #811 from donc/bug7699 4279d5e revert the revert c895c3b revert pull #809 865fb20 fix Issue 5733 - Calling opDispatch As Template Results in Compiler Infinite Loop 96e16d3 fix Issue 7702 - opDispatch goes into infinite loop 5e343c0 Remove special case for DotIdExp and opDispatch semantic, it isn't need anymore 1a9d607 Fix issue 7699 - Cannot get frame pointer to in contract when compiling with -inline d1476eb Merge pull request #809 from 9rnsr/fix_funclit afc7c60 allow out-of-order semantic analysis of fields 17da3a0 fix Issue 7705 - lambda syntax doesn't allow some valid signatures e29d06d fix issue 7698 911d053 Fix issue 7633 - Missing CTFE error message 3802dde Fix issue 7681 Regression(2.059head):ICE:opCatAssign(delegate) to undefined identifier 8da4121 near-ectomy cd6dc83 fix Library::error()s format string to take a const char* f3f03c6 switch to apply() faf873a fix Issue 3510 - Cannot forward reference a templated type from within a template mixin 23aa2be fix Issue 3509 - Cannot forward reference a template mixin's members in a compile-time context e81309b Add missing 'loc' to error message. b6898e3 Fix issue 6681 - struct constructor call is converted to struct literal that breaks union initialization b79afba long double => longdouble e48c319 Merge pull request #742 from yebblies/issue5879 d74485a Merge pull request #787 from eco/ddoc-srcfilename 3038cb9 Merge pull request #795 from dawgfoto/fixComment 89a039a Merge pull request #801 from dawgfoto/fix4507 c17c2d8 fix issue 4507 dd86c72 Merge pull request #796 from dawgfoto/fixVC a516588 Merge pull request #797 from 9rnsr/fix7682 1b9839a Merge pull request #799 from 9rnsr/fix6982 4596774 Merge pull request #800 from 9rnsr/fix_type_deduction b68d546 forgot about @system bfe1083 add attributes to toHash 8f819d6 Stop special case in mutableOf/makeMutable with inout type. 319b1a3 Fix the lacks of type merging in Type::mutableOf() and uhSharedOf() cfe7450 fix Issue 7671 - Broken inout deduction of shared(inout(T[n])) from immutable(int[3]) aca5c37 Stop too eager call of TypeAArray::getImpl() When implicitConvTo(non aa Tstruct => Taarray) 50b2a97 fix Issue 6982 - immutability isn't respected on associative array assignment a5daa5e fix Issue 7684 - IFTI and shared overload doesn't work e43fbac fix Issue 7682 - shared array type and "cast() is not an lvalue" error 8191801 cpp_prettyident only needed for C++ 4487f75 fix ldval 525647c tparam is the specialization f893925 fix issue 7592 https://github.com/yebblies/dmd/commit/d847c1c2dd3c254324924530beab38b49510bf13 108b25d Merge pull request #780 from 9rnsr/fix7641 105a51f Merge pull request #784 from 9rnsr/fix7110 8b5b67f Merge pull request #792 from donc/bug7667 f72f237 fix Issue 3682 - Regression(2.038) is expression fails to match types 436b711 Fix issue 7667. ICE(interpret.c): 'ctfeStack.stackPointer() == 0' 9005276 Merge pull request #679 from yebblies/issue783 350a3ce Merge pull request #582 from 9rnsr/fix3382_ufcs 5f020c3 Merge pull request #788 from braddr/cleanup-backend3 6aa91cf Merge pull request #790 from p0nce/master 351d595 remove tls bracketing a137d72 Fix bug #6391 6ce219c remove some of the bracketing aec4c13 fix Issue 7578 - ICE on indexing result of vararg opDispatch 95e3dc1 Fix unintended infinite loop in Phobos build b66196a fix Issue 3382 - [tdpl] Implement uniform function call syntax ee2fe6c Fix 977 is with counting end-of-lines towards msot advanced lexer peeking 7790b16 fix Issue 7650 - Bad lambda inference in associative array literal c03484e fix Issue 7649 - Bad lambda inference in default function argument f293a10 fix Issue 7499 - [ICE] ('cast.c line 1495) with lambda array 9f0622c Expression::inferType() and remove FuncExp::setType() cfc67b7 refactor lambda inference process 6d49586 more de-TX86'ing in relation to a bunch of OP codes 2efbf6a TX86-ectomy in evalu8.c 953f6d7 rip TX86 conditionals out of el.c d5663c7 fix Issue 7595 - Data being overwritten. 449c165 Add predefined Ddoc macro SRCFILENAME 5c5da66 fix uninitialized field 29cde54 Merge pull request #783 from 9rnsr/fix7038 06d65ab fix Issue 7038 - Type mismatch with const struct b77e2c9 fix Issue 7110 - opSlice() & opIndex functions works unstable as template arguments a65f02f Merge pull request #781 from braddr/fix 08d6cd5 Merge pull request #782 from braddr/fixiasm 2492332 fix latent bug with Lexer::peek and recently introduced bug in Lexer::scan ec1888e initialize popndTmp rather than rely on carefulness when usNumops == 0 and emitting a vector instruction, popndTmp is left uninitialized and is later dereferenced. 1d4a742 Merge pull request #766 from 9rnsr/fix7563 e1cd535 refactor 90f8dcf fix Issue 7641 - std.typecons.Proxy incorrectly allows implicit conversion to class 83a93cf Merge pull request #778 from dawgfoto/MoreSpellCorrection 7f0bcde 2nd go at fix issue 5590 567d7df fix Issue 5590 - Regression(2.036) ICE(e2ir.c): when using .values on enum which is associative array 48ea951 fix Issue 4820 - Regression(1.058, 2.044) in DStress caused by changeset 452 e8f9f3b more spell correction afd9a45 fix Issue 7618 - delegate/function pointer call bypass parameter storage class dabcdfb Merge pull request #773 from 9rnsr/fix7583 9846bb2 Merge pull request #774 from donc/ctfe7568 8c20445 Merge pull request #775 from donc/_error6785 d41e58e Avoiding shallow copy is more better. cccef09 Revert "fix Issue 7585 - functions in templates inferred as delegate" fc8dfc0 6785 Wrong error message from pragma(msg) of failed instantiation 61ec04d 7568 pragma(msg) segfaults with an aggregate including a class. 4d86d39 Merge pull request #767 from 9rnsr/fix7585 207d351 fix Issue 7583 - [CTFE] ICE with tuple and alias this 53bafa2 fix Issue 7411 - Deduce base type from vector types in templates 5ab1bd9 fix Issue 7518 - std.array.empty doesn't work for shared arrays a1030d3 fix Issue 7554 - Immutable function pointer arguments too 5e96900 Merge pull request #771 from donc/bug7589 2287ebc fix Issue 7547 - -deps output lists object as a top level module e611781 7589 __traits(compiles) does not work with a template that fails to compile 0113cde fix Issue 7585 - functions in templates inferred as delegate 4b978d5 fix Issue 7563 - Class members with default template arguments have no type 4d68981 fix Issue 7500 - [ICE] (template.c line 5287) with immutable lambda function 1a39c3c missed a line 6dd89ca Merge pull request #765 from 9rnsr/fix7525 8d6dcac fix Issue 7502 - 2.056 regression: Assigning .init takes forever to compile for large structs 042096e fix Issue 7525 - Broken return type inference for delegate returns c5affa5 fix Issue 7582 - Untyped nested delegate literals don't compile 121677c fix Issue 7580 - Identity assignment of Nullable crashes dmd adc0502 Small refactoring to resolve alias this. 1f52383 Merge pull request #671 from yebblies/issue4958 2a12345 fix build breakage 8755819 fix build ba86204 fix vcbuild 464c664 fix linux build 31197c8 tweaked command line moved some inline asm to C-function to not interfere with optimizations build with VS2011 4dcdc9c increase stack size for win64 build 77262aa add missing include to root 56afe3f batch to build through win32.mak 5a0fd30 build through win32.mak a5b5190 long_double -> longdouble remove C99 printf add Win64 support 9640110 vcbuild b619171 Merge pull request #761 from donc/ctfe7473structref 7756328 Merge pull request #725 from kennytm/bug7399-import-too-fatal bbac9e4 Merge pull request #759 from yebblies/issue1149 d1ff23b 7473 [CTFE] Non-ref argument behaves as if it's a ref argument ab5cb18 Fix OPmsw codegen - integer only is too restrictive. a00833b Merge pull request #743 from yebblies/issue3354 b006e11 Merge pull request #757 from 9rnsr/fix7562 3bccbb0 fix Issue 7562 - DMD crashes by using TemplateThisParameter a7dc50e Merge pull request #749 from yebblies/issue1149 a873c5f Merge pull request #758 from 9rnsr/fix5525 5d639ec fix Issue 5525 - Eponymous templates should allow for overloaded eponymous members f50852c Merge pull request #729 from donc/gag4269 de02523 fix Issue 3927 - array.length++; is an error, but ++array.length compiles 1dc5bfd Merge pull request #680 from yebblies/issue3812 cf887ba move errors to Dsymbol fc4acf5 Merge pull request #755 from donc/seaOfErrors7557 be2f3a9 7557b soldier on through dottemplate expressions 8cec825 7557 Sea of errors after template failure 37ec6d6 A small fixup to call Type::defaultInitLiteral 7b5e2cb Revert "Revert "Merge pull request #41 from 9rnsr/rvalue-struct-literal"" 3d8f09a Merge branch 'master' of github.com:D-Programming-Language/dmd 7dfb4cc Merge pull request #752 from braddr/cleanup-backend2 1b28f51 Merge branch 'master' of github.com:D-Programming-Language/dmd 31ad73c Merge pull request #746 from yebblies/issue5554 25f770d Change lexer to support # as a token, preserving #line's original behavior dd8d20a Revert "Merge pull request #41 from 9rnsr/rvalue-struct-literal" ee2fdf9 Merge pull request #41 from 9rnsr/rvalue-struct-literal f94fdbf Merge pull request #750 from yebblies/issue3630 61f5fcf Improve codegen for OPmsw 05a3fa4 Merge pull request #744 from Safety0ff/avx-fix 0231d6a Merge pull request #748 from 9rnsr/fix7552 9a97979 Merge pull request #751 from donc/ctfe7536 e091e6e 7536 ctfeAdrOnStack triggered c9edaf4 fix Issue 7552 - Cannot get and combine a part of overloaded functions 1edeba9 Fix Issue 3630 - bad error location in "has no effect in expression" error 7d0fb72 Fix Issue 5554 - [qtd] Covariance detection failure 4f36aca fix Issue 7550 - Missing AVX instruction VPMULDQ 0b82dfe Fix Issue 5879 - Not all frontend errors use stderr 963a41a Merge pull request #695 from yebblies/refactor_expression 3f06690 Fix Issue 3354 - asm fld x, ST(6); accepted 713f69f Merge pull request #677 from yebblies/issue4241 cf22ce3 Merge pull request #711 from yebblies/issue3559 56ca73c Merge pull request #700 from kennytm/bug7452_lazy_safe c4dc723 Merge pull request #736 from ibuclaw/in_gcc 121c9b9 Merge pull request #737 from yebblies/issue7544 cedcb3c Merge pull request #740 from yebblies/issue7545 fb3e8f2 Merge pull request #741 from dawgfoto/DMCWarning 5d26c1e Merge pull request #735 from 9rnsr/fix7105 734a921 dmc warning 1e1cfbc Fix Issue 7545 - ICE(cast.c) Merge integral types through alias this 6b135be Fix Issue 7544 - ICE(interpret.c) Catching an exception with a null catch block c5336f9 Update already existing gdc-specific code, harmonise headers. 44b8d59 Merge pull request #703 from kennytm/bug435_template_ctor 6b368e1 Merge pull request #707 from yebblies/issue3822 8439e07 Merge pull request #717 from yebblies/issue6611 2b4502e fix Issue 7105 - relax inout rules ac4463a wildsubparam isn't need anymore, because it works properly. f77879a Issue 6611 - better error message for array post increment/decrement 7393395 Merge pull request #716 from yebblies/issue6685 77568f0 Merge pull request #719 from yebblies/issue4536 9accb04 tired of tdata() 5fbd5a2 Merge pull request #732 from dawgfoto/fix5412 41a901a Revert "hide private/package module level symbols" 23d5e14 Merge pull request #733 from dawgfoto/HideModuleMembers e2f8a23 hide private/package module level symbols ae75287 detect collisions with renamed imports 75a2442 fix Dsymbol::search_correct 50e122a Merge pull request #723 from kennytm/bug7504_null_array c5b7601 Revert "fix 7494 - selective imports in function scope" aa6f4d9 Revert "fix Protection" 5be660e Revert "fix Imports" 040371b Revert "detect collisions with renamed imports" 0159818 Revert "find private symbols during spell correction" 0c95c45 find private symbols during spell correction ca22fb2 detect collisions with renamed imports 0dca0af fix Imports 37d4fda fix Protection 16a2e7e fix 7494 - selective imports in function scope c16f5b2 Merge pull request #667 from 9rnsr/fix7406 f776617 explanatory comments belong in the code, not bugzilla bfa2060 Merge pull request #704 from donc/_error6699 f46705c fix fail222 regression 28d9635 Merge pull request #708 from donc/soldieron7481 2c2a7af Merge pull request #715 from 9rnsr/fix6738 98cfa64 Merge pull request #722 from 9rnsr/fix7353 b040567 revert pull 724 0e84f63 revert part of pull 724 400f702 Merge pull request #724 from yebblies/issue3632 d82cc74 Merge pull request #720 from yebblies/issue3279 2da3bed Merge pull request #718 from yebblies/fixdebugmsg f6627ec 7527 [CTFE] Segfault when slicing a pointer at compile time c8f09bf 4269a Regression(2.031): invalid type accepted if evaluated while errors are gagged d10fba0 implement const/purity/nothrow/@safe inheritance ad689fb Fix bug 7399: Broken import statement in trySemantic() causes silent compiler error eb0c643 Add global.speculativeGag c18220a Refactor isSpeculativeFunction into Dsymbol f5c56d8 Issue 3632 - modify float is float to do a bitwise compare af1cab4 Issue 7353 - NRVO not properly working with inferred return type 03ee438 Fix bug 7504: Cannot assign an object of type 'typeof(null)' to an array dfb941c Remove debug printing in code that generates errors. 62118e3 Issue 4536 - Typetuples (T...) should have an .init member 989da7b Issue 3279 - Confusing error message when comparing types 36e8045 Issue 6685 - Allow using "with" with rvalues 60cbc6f fix issue 6738 revisited 4e20e7d Issue 3822 - Invalid optimization of alloca called with constant size b37bf8c Fixes bug 435: Constructors should be templatized ad8157d Issue 3559 - DMD 1.048+ fails to take function pointer from overloaded member functions 838cd06 7481 Compiler should 'soldier on' after template errors 673063e Simplify fix for 6699 1a0b199 6699a __error when instantiating function template b6d072d 6699b __error in alias expression df16ffa 6699c __error in synchronized error message 338f804 7462 Error message with _error_ in overridden function 0f60bd3 7463 Duplicated error message with bad template value parameter f43e93a 6699E: _error inside error msg for bad base class 5109a5a Fixes bug 7452. 04d888f Refactor XxxAssignExp semantic 73973d6 Issue 3812 - Missing line number for implicit cast of variadic function to array f0bbf18 Issue 3927 - array.length++; is an error, but ++array.length compiles 24576c2 Issue 783 - Cannot use an array w/ const or variable index as new[] size argument. 7e4cd4b Issue 4241 - duplicate union initialization error doesn't give a file location 9987127 Issue 4958 - Floating point enums should check for total loss of precision 60287fd Issue 7406 - tuple foreach doesn't work with mixed tuples 633d88e Issue 5889 - Struct literal/construction should be rvalue 5d5f78a Now function overloading with ref and non-ref parameter is legal for struct type git-subtree-dir: dmd2 git-subtree-split: 3443f38fc4c17807a0f36005a05d598cfc7301db --- aggregate.h | 23 +- aliasthis.c | 23 + attrib.c | 308 +++---- attrib.h | 9 +- backend/bcomplex.c | 30 +- backend/bcomplex.h | 14 +- backend/cc.h | 10 +- backend/cdef.h | 17 +- backend/cdeflnx.h | 2 - backend/cg87.c | 27 +- backend/cgcod.c | 2 +- backend/cgcs.c | 17 +- backend/cgcv.c | 2 +- backend/cgcv.h | 2 +- backend/cgelem.c | 85 +- backend/cgobj.c | 12 +- backend/cgxmm.c | 29 + backend/cod1.c | 2 +- backend/cod3.c | 12 +- backend/code.h | 19 +- backend/cppman.c | 2 +- backend/debug.c | 11 +- backend/dt.h | 4 - backend/dwarf.c | 9 +- backend/el.c | 83 +- backend/evalu8.c | 76 +- backend/gflow.c | 6 - backend/global.h | 12 +- backend/glocal.c | 12 +- backend/gloop.c | 10 +- backend/html.c | 8 +- backend/machobj.c | 13 - backend/md5.c | 15 +- backend/newman.c | 8 +- backend/oper.h | 6 +- backend/optabgen.c | 5 +- backend/os.c | 15 +- backend/ptrntab.c | 6 + backend/strtold.c | 60 +- backend/tassert.h | 4 +- backend/token.h | 12 +- backend/type.c | 13 +- backend/type.h | 2 + builtin.c | 19 +- cast.c | 279 +++++- class.c | 91 +- clone.c | 14 + complex_t.h | 26 +- constfold.c | 18 +- cppmangle.c | 2 +- declaration.c | 133 ++- declaration.h | 20 +- delegatize.c | 5 +- dmd_msc.vcproj | 2088 ++++++++++++++++++++++++++++++++++++++++++ doc.c | 3 + dsymbol.c | 70 +- dsymbol.h | 9 +- dump.c | 2 +- e2ir.c | 166 +++- eh.c | 6 + enum.c | 21 +- enum.h | 3 + expression.c | 1607 +++++++++++++++----------------- expression.h | 42 +- func.c | 144 ++- glue.c | 33 +- iasm.c | 47 +- identifier.c | 2 +- idgen.c | 2 +- import.c | 73 +- init.c | 129 ++- inline.c | 16 + interpret.c | 389 ++++++-- lexer.c | 82 +- lexer.h | 6 +- lib.h | 14 + libomf.c | 8 +- link.c | 4 +- mangle.c | 4 +- mars.c | 81 +- mars.h | 14 +- module.c | 32 +- module.h | 2 +- mtype.c | 439 ++++++--- mtype.h | 26 +- opover.c | 76 +- optimize.c | 12 +- parse.c | 34 +- posix.mak | 9 +- root/dchar.h | 4 +- root/longdouble.c | 636 +++++++++++++ root/longdouble.h | 254 +++++ root/lstring.h | 2 + root/port.c | 179 +--- root/port.h | 12 +- root/response.c | 7 + root/root.c | 6 +- root/root.h | 6 +- root/speller.c | 2 +- scope.c | 4 +- scope.h | 11 +- statement.c | 189 +++- statement.h | 2 + struct.c | 191 ++-- template.c | 500 ++++++---- template.h | 15 +- tk/mem.c | 5 +- tk/vec.h | 2 +- tocsym.c | 2 +- tocvdebug.c | 103 ++- todt.c | 122 +-- toir.c | 2 +- traits.c | 10 +- typinf.c | 23 + util.c | 64 +- vcbuild/alloca.h | 1 + vcbuild/builddmd.bat | 13 + vcbuild/dmc_cl.bat | 44 + vcbuild/fenv.h | 5 + vcbuild/ldfpu.asm | 336 +++++++ vcbuild/stdint.h | 206 +++++ vcbuild/warnings.h | 30 + win32.mak | 3 +- 123 files changed, 7585 insertions(+), 2745 deletions(-) create mode 100644 dmd_msc.vcproj create mode 100644 root/longdouble.c create mode 100644 root/longdouble.h create mode 100644 vcbuild/alloca.h create mode 100644 vcbuild/builddmd.bat create mode 100644 vcbuild/dmc_cl.bat create mode 100644 vcbuild/fenv.h create mode 100644 vcbuild/ldfpu.asm create mode 100644 vcbuild/stdint.h create mode 100644 vcbuild/warnings.h diff --git a/aggregate.h b/aggregate.h index e11a8061..66c4a270 100644 --- a/aggregate.h +++ b/aggregate.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -34,6 +34,12 @@ struct TypeInfoClassDeclaration; struct VarDeclaration; struct dt_t; +enum Sizeok +{ + SIZEOKnone, // size of aggregate is not computed yet + SIZEOKdone, // size of aggregate is set correctly + SIZEOKfwd, // error in computing size of aggregate +}; struct AggregateDeclaration : ScopeDsymbol { @@ -46,10 +52,7 @@ struct AggregateDeclaration : ScopeDsymbol unsigned structalign; // struct member alignment in effect int hasUnions; // set if aggregate has overlapping fields VarDeclarations fields; // VarDeclaration fields - unsigned sizeok; // set when structsize contains valid data - // 0: no size - // 1: size is correct - // 2: cannot determine size; fwd referenced + enum Sizeok sizeok; // set when structsize contains valid data Dsymbol *deferred; // any deferred semantic2() or semantic3() symbol bool isdeprecated; // !=0 if deprecated @@ -74,7 +77,8 @@ struct AggregateDeclaration : ScopeDsymbol FuncDeclaration *dtor; // aggregate destructor #ifdef IN_GCC - Array methods; // flat list of all methods for debug information + Expressions *attributes; // GCC decl/type attributes + FuncDeclarations methods; // flat list of all methods for debug information #endif AggregateDeclaration(Loc loc, Identifier *id); @@ -83,8 +87,10 @@ struct AggregateDeclaration : ScopeDsymbol void inlineScan(); unsigned size(Loc loc); static void alignmember(unsigned salign, unsigned size, unsigned *poffset); + static unsigned placeField(unsigned *nextoffset, + unsigned memsize, unsigned memalignsize, unsigned memalign, + unsigned *paggsize, unsigned *paggalignsize, bool isunion); Type *getType(); - void addField(Scope *sc, VarDeclaration *v); int firstFieldInUnion(int indx); // first field in union that includes indx int numFieldsInUnion(int firstIndex); // #fields in union starting at index int isDeprecated(); // is aggregate deprecated? @@ -143,7 +149,7 @@ struct StructDeclaration : AggregateDeclaration void toCBuffer(OutBuffer *buf, HdrGenState *hgs); char *mangle(); const char *kind(); - void finalizeSize(); + void finalizeSize(Scope *sc); #if DMDV1 Expression *cloneMembers(); #endif @@ -203,6 +209,7 @@ struct BaseClass #define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size #else #define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size +#define CLASSINFO_SIZE_64 (0x98) // value of ClassInfo.size #endif struct ClassDeclaration : AggregateDeclaration diff --git a/aliasthis.c b/aliasthis.c index f8a74b48..0f6ff452 100644 --- a/aliasthis.c +++ b/aliasthis.c @@ -17,9 +17,32 @@ #include "scope.h" #include "aggregate.h" #include "dsymbol.h" +#include "mtype.h" #if DMDV2 +Expression *resolveAliasThis(Scope *sc, Expression *e) +{ + Type *t = e->type->toBasetype(); + AggregateDeclaration *ad; + + if (t->ty == Tclass) + { ad = ((TypeClass *)t)->sym; + goto L1; + } + else if (t->ty == Tstruct) + { ad = ((TypeStruct *)t)->sym; + L1: + if (ad && ad->aliasthis) + { + e = new DotIdExp(e->loc, e, ad->aliasthis->ident); + e = e->semantic(sc); + e = resolveProperties(sc, e); + } + } + + return e; +} AliasThis::AliasThis(Loc loc, Identifier *ident) : Dsymbol(NULL) // it's anonymous (no identifier) diff --git a/attrib.c b/attrib.c index e55dd83b..3970138b 100644 --- a/attrib.c +++ b/attrib.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -47,6 +47,24 @@ Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) return decl; } +int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param) +{ + Dsymbols *d = include(NULL, NULL); + + if (d) + { + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; + if (s) + { + if (s->apply(fp, param)) + return 1; + } + } + } + return 0; +} + int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int m = 0; @@ -54,8 +72,8 @@ int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); m |= s->addMember(sc, sd, m | memnum); } @@ -85,8 +103,8 @@ void AttribDeclaration::setScopeNewSc(Scope *sc, newsc->explicitProtection = explicitProtection; newsc->structalign = structalign; } - for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + for (size_t i = 0; i < decl->dim; i++) + { Dsymbol *s = (*decl)[i]; s->setScope(newsc); // yes, the only difference from semanticNewSc() } @@ -120,8 +138,8 @@ void AttribDeclaration::semanticNewSc(Scope *sc, newsc->explicitProtection = explicitProtection; newsc->structalign = structalign; } - for (unsigned i = 0; i < decl->dim; i++) - { Dsymbol *s = decl->tdata()[i]; + for (size_t i = 0; i < decl->dim; i++) + { Dsymbol *s = (*decl)[i]; s->semantic(newsc); } @@ -142,7 +160,7 @@ void AttribDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->semantic(sc); } @@ -156,7 +174,7 @@ void AttribDeclaration::semantic2(Scope *sc) if (d) { for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = (*d)[i]; s->semantic2(sc); } } @@ -169,7 +187,7 @@ void AttribDeclaration::semantic3(Scope *sc) if (d) { for (size_t i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + { Dsymbol *s = (*d)[i]; s->semantic3(sc); } } @@ -181,8 +199,8 @@ void AttribDeclaration::inlineScan() if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); s->inlineScan(); } @@ -198,8 +216,8 @@ void AttribDeclaration::addComment(unsigned char *comment) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -223,8 +241,8 @@ void AttribDeclaration::emitComment(Scope *sc) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("AttribDeclaration::emitComment %s\n", s->toChars()); s->emitComment(sc); } @@ -237,30 +255,24 @@ void AttribDeclaration::toObjFile(int multiobj) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->toObjFile(multiobj); } } } -int AttribDeclaration::cvMember(unsigned char *p) +void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) { - int nwritten = 0; - int n; Dsymbols *d = include(NULL, NULL); if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; - n = s->cvMember(p); - if (p) - p += n; - nwritten += n; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; + s->setFieldOffset(ad, poffset, isunion); } } - return nwritten; } int AttribDeclaration::hasPointers() @@ -271,7 +283,7 @@ int AttribDeclaration::hasPointers() { for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; if (s->hasPointers()) return 1; } @@ -313,8 +325,8 @@ void AttribDeclaration::checkCtorConstInit() if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->checkCtorConstInit(); } } @@ -329,8 +341,8 @@ void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->addLocalClass(aclasses); } } @@ -344,15 +356,15 @@ void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) if (decl->dim == 0) buf->writestring("{}"); else if (decl->dim == 1) - (decl->tdata()[0])->toCBuffer(buf, hgs); + ((*decl)[0])->toCBuffer(buf, hgs); else { buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -571,9 +583,9 @@ void LinkDeclaration::semantic3(Scope *sc) { enum LINK linkage_save = sc->linkage; sc->linkage = linkage; - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; s->semantic3(sc); } @@ -740,6 +752,7 @@ AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl) : AttribDeclaration(decl) { this->loc = loc; + this->alignment = 0; this->isunion = isunion; this->sem = 0; } @@ -757,21 +770,6 @@ void AnonDeclaration::semantic(Scope *sc) { //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); - if (sem == 1) - { //printf("already completed\n"); - scope = NULL; - return; // semantic() already completed - } - - Scope *scx = NULL; - if (scope) - { sc = scope; - scx = scope; - scope = NULL; - } - - unsigned dprogress_save = Module::dprogress; - assert(sc->parent); Dsymbol *parent = sc->parent->pastMixin(); @@ -783,106 +781,85 @@ void AnonDeclaration::semantic(Scope *sc) return; } + alignment = sc->structalign; if (decl) { - AnonymousAggregateDeclaration aad; - int adisunion; - - if (sc->anonAgg) - { ad = sc->anonAgg; - adisunion = sc->inunion; - } - else - adisunion = ad->isUnionDeclaration() != NULL; - -// printf("\tsc->anonAgg = %p\n", sc->anonAgg); -// printf("\tad = %p\n", ad); -// printf("\taad = %p\n", &aad); - sc = sc->push(); - sc->anonAgg = &aad; sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared); sc->inunion = isunion; sc->offset = 0; sc->flags = 0; - aad.structalign = sc->structalign; - aad.parent = ad; - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; - + Dsymbol *s = (*decl)[i]; s->semantic(sc); - if (isunion) - sc->offset = 0; - if (aad.sizeok == 2) - { - break; - } } sc = sc->pop(); + } +} - // If failed due to forward references, unwind and try again later - if (aad.sizeok == 2) + +void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this); + + if (decl) + { + /* This works by treating an AnonDeclaration as an aggregate 'member', + * so in order to place that member we need to compute the member's + * size and alignment. + */ + + size_t fieldstart = ad->fields.dim; + + /* Hackishly hijack ad's structsize and alignsize fields + * for use in our fake anon aggregate member. + */ + unsigned savestructsize = ad->structsize; + unsigned savealignsize = ad->alignsize; + ad->structsize = 0; + ad->alignsize = 0; + + unsigned offset = 0; + for (size_t i = 0; i < decl->dim; i++) { - ad->sizeok = 2; - //printf("\tsetting ad->sizeok %p to 2\n", ad); - if (!sc->anonAgg) - { - scope = scx ? scx : new Scope(*sc); - scope->setNoFree(); - scope->module->addDeferredSemantic(this); - } - Module::dprogress = dprogress_save; - //printf("\tforward reference %p\n", this); - return; + Dsymbol *s = (*decl)[i]; + + s->setFieldOffset(ad, &offset, this->isunion); + if (this->isunion) + offset = 0; } - if (sem == 0) - { Module::dprogress++; - sem = 1; - //printf("\tcompleted %p\n", this); - } - else - ;//printf("\talready completed %p\n", this); + + unsigned anonstructsize = ad->structsize; + unsigned anonalignsize = ad->alignsize; + ad->structsize = savestructsize; + ad->alignsize = savealignsize; // 0 sized structs are set to 1 byte - if (aad.structsize == 0) + if (anonstructsize == 0) { - aad.structsize = 1; - aad.alignsize = 1; + anonstructsize = 1; + anonalignsize = 1; } - // Align size of anonymous aggregate -//printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); - ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); - //ad->structsize = sc->offset; -//printf("sc->offset = %d\n", sc->offset); + /* Given the anon 'member's size and alignment, + * go ahead and place it. + */ + unsigned anonoffset = AggregateDeclaration::placeField( + poffset, + anonstructsize, anonalignsize, alignment, + &ad->structsize, &ad->alignsize, + isunion); - // Add members of aad to ad - //printf("\tadding members of aad to '%s'\n", ad->toChars()); - for (unsigned i = 0; i < aad.fields.dim; i++) + // Add to the anon fields the base offset of this anonymous aggregate + //printf("anon fields, anonoffset = %d\n", anonoffset); + for (size_t i = fieldstart; i < ad->fields.dim; i++) { - VarDeclaration *v = aad.fields.tdata()[i]; - - v->offset += sc->offset; - ad->fields.push(v); + VarDeclaration *v = ad->fields[i]; + //printf("\t[%d] %s %d\n", i, v->toChars(), v->offset); + v->offset += anonoffset; } - - // Add size of aad to ad - if (adisunion) - { - if (aad.structsize > ad->structsize) - ad->structsize = aad.structsize; - sc->offset = 0; - } - else - { - ad->structsize = sc->offset + aad.structsize; - sc->offset = ad->structsize; - } - - if (ad->alignsize < aad.alignsize) - ad->alignsize = aad.alignsize; } } @@ -893,9 +870,9 @@ void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writestring("\n{\n"); if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; //buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -941,10 +918,10 @@ void PragmaDeclaration::setScope(Scope *sc) } else { - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; + (*args)[0] = e; StringExp* se = e->toString(); if (!se) { @@ -974,10 +951,15 @@ void PragmaDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { - Expression *e = args->tdata()[i]; + Expression *e = (*args)[i]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKerror) + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op == TOKerror) + { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); + return; + } StringExp *se = e->toString(); if (se) { @@ -996,11 +978,11 @@ void PragmaDeclaration::semantic(Scope *sc) error("string expected for library name"); else { - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; + (*args)[0] = e; if (e->op == TOKerror) goto Lnodecl; StringExp *se = e->toString(); @@ -1028,7 +1010,7 @@ void PragmaDeclaration::semantic(Scope *sc) Declaration *d = NULL; StringExp *s = NULL; - e = args->tdata()[0]; + e = (*args)[0]; e = e->semantic(sc); if (e->op == TOKvar) { @@ -1039,14 +1021,14 @@ void PragmaDeclaration::semantic(Scope *sc) if (!d) error("first argument of GNU_asm must be a function or variable declaration"); - e = args->tdata()[1]; + e = (*args)[1]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); e = e->toString(); if (e && ((StringExp *)e)->sz == 1) s = ((StringExp *)e); else - error("second argument of GNU_asm must be a char string"); + error("second argument of GNU_asm must be a character string"); if (d && s) d->c_ident = Lexer::idPool((char*) s->string); @@ -1061,10 +1043,10 @@ void PragmaDeclaration::semantic(Scope *sc) error("function name expected for start address"); else { - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); - args->tdata()[0] = e; + (*args)[0] = e; Dsymbol *sa = getDsymbol(e); if (!sa || !sa->isFuncDeclaration()) error("function name expected for start address, not '%s'", e->toChars()); @@ -1088,7 +1070,7 @@ void PragmaDeclaration::semantic(Scope *sc) { for (size_t i = 0; i < args->dim; i++) { - Expression *e = args->tdata()[i]; + Expression *e = (*args)[i]; e = e->semantic(sc); e = e->optimize(WANTvalue | WANTinterpret); if (i == 0) @@ -1110,9 +1092,9 @@ void PragmaDeclaration::semantic(Scope *sc) Ldecl: if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; s->semantic(sc); } @@ -1144,7 +1126,7 @@ void PragmaDeclaration::toObjFile(int multiobj) { assert(args && args->dim == 1); - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; assert(e->op == TOKstring); @@ -1172,7 +1154,7 @@ void PragmaDeclaration::toObjFile(int multiobj) else if (ident == Id::startaddress) { assert(args && args->dim == 1); - Expression *e = args->tdata()[0]; + Expression *e = (*args)[0]; Dsymbol *sa = getDsymbol(e); FuncDeclaration *f = sa->isFuncDeclaration(); assert(f); @@ -1243,8 +1225,8 @@ void ConditionalDeclaration::emitComment(Scope *sc) * a template, then include(NULL, NULL) will fail. */ Dsymbols *d = decl ? decl : elsedecl; - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; s->emitComment(sc); } } @@ -1266,9 +1248,9 @@ void ConditionalDeclaration::setScope(Scope *sc) //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d); if (d) { - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->setScope(sc); } @@ -1282,9 +1264,9 @@ void ConditionalDeclaration::importAll(Scope *sc) //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); if (d) { - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->importAll(sc); } @@ -1307,10 +1289,8 @@ void ConditionalDeclaration::addComment(unsigned char *comment) { if (d) { - for (unsigned i = 0; i < d->dim; i++) - { Dsymbol *s; - - s = d->tdata()[i]; + for (size_t i = 0; i < d->dim; i++) + { Dsymbol *s = (*d)[i]; //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } @@ -1330,9 +1310,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); if (decl) { - for (unsigned i = 0; i < decl->dim; i++) + for (size_t i = 0; i < decl->dim; i++) { - Dsymbol *s = decl->tdata()[i]; + Dsymbol *s = (*decl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1346,9 +1326,9 @@ void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) buf->writenl(); buf->writeByte('{'); buf->writenl(); - for (unsigned i = 0; i < elsedecl->dim; i++) + for (size_t i = 0; i < elsedecl->dim; i++) { - Dsymbol *s = elsedecl->tdata()[i]; + Dsymbol *s = (*elsedecl)[i]; buf->writestring(" "); s->toCBuffer(buf, hgs); @@ -1432,9 +1412,9 @@ void StaticIfDeclaration::semantic(Scope *sc) addisdone = 1; } - for (unsigned i = 0; i < d->dim; i++) + for (size_t i = 0; i < d->dim; i++) { - Dsymbol *s = d->tdata()[i]; + Dsymbol *s = (*d)[i]; s->semantic(sc); } diff --git a/attrib.h b/attrib.h index ab04c075..7806517f 100644 --- a/attrib.h +++ b/attrib.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -33,6 +33,7 @@ struct AttribDeclaration : Dsymbol AttribDeclaration(Dsymbols *decl); virtual Dsymbols *include(Scope *sc, ScopeDsymbol *s); + int apply(Dsymbol_apply_ft_t fp, void *param); int addMember(Scope *sc, ScopeDsymbol *s, int memnum); void setScopeNewSc(Scope *sc, StorageClass newstc, enum LINK linkage, enum PROT protection, int explictProtection, @@ -48,6 +49,7 @@ struct AttribDeclaration : Dsymbol void emitComment(Scope *sc); const char *kind(); int oneMember(Dsymbol **ps, Identifier *ident); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); int hasPointers(); bool hasStaticCtorOrDtor(); void checkCtorConstInit(); @@ -57,7 +59,6 @@ struct AttribDeclaration : Dsymbol AttribDeclaration *isAttribDeclaration() { return this; } void toObjFile(int multiobj); // compile to .obj file - int cvMember(unsigned char *p); }; struct StorageClassDeclaration: AttribDeclaration @@ -114,12 +115,14 @@ struct AlignDeclaration : AttribDeclaration struct AnonDeclaration : AttribDeclaration { - int isunion; + bool isunion; + unsigned alignment; int sem; // 1 if successful semantic() AnonDeclaration(Loc loc, int isunion, Dsymbols *decl); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); const char *kind(); }; diff --git a/backend/bcomplex.c b/backend/bcomplex.c index ec31a93d..13370363 100644 --- a/backend/bcomplex.c +++ b/backend/bcomplex.c @@ -9,8 +9,8 @@ Complex_ld Complex_ld::div(Complex_ld &x, Complex_ld &y) { Complex_ld q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -38,9 +38,9 @@ Complex_ld Complex_ld::mul(Complex_ld &x, Complex_ld &y) return p; } -long double Complex_ld::abs(Complex_ld &z) +longdouble Complex_ld::abs(Complex_ld &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -64,7 +64,7 @@ long double Complex_ld::abs(Complex_ld &z) Complex_ld Complex_ld::sqrtc(Complex_ld &z) { Complex_ld c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { @@ -104,8 +104,8 @@ Complex_ld Complex_ld::sqrtc(Complex_ld &z) Complex_d Complex_d::div(Complex_d &x, Complex_d &y) { Complex_d q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -133,9 +133,9 @@ Complex_d Complex_d::mul(Complex_d &x, Complex_d &y) return p; } -long double Complex_d::abs(Complex_d &z) +longdouble Complex_d::abs(Complex_d &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -159,7 +159,7 @@ long double Complex_d::abs(Complex_d &z) Complex_d Complex_d::sqrtc(Complex_d &z) { Complex_d c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { @@ -199,8 +199,8 @@ Complex_d Complex_d::sqrtc(Complex_d &z) Complex_f Complex_f::div(Complex_f &x, Complex_f &y) { Complex_f q; - long double r; - long double den; + longdouble r; + longdouble den; if (fabs(y.re) < fabs(y.im)) { @@ -228,9 +228,9 @@ Complex_f Complex_f::mul(Complex_f &x, Complex_f &y) return p; } -long double Complex_f::abs(Complex_f &z) +longdouble Complex_f::abs(Complex_f &z) { - long double x,y,ans,temp; + longdouble x,y,ans,temp; x = fabs(z.re); y = fabs(z.im); @@ -254,7 +254,7 @@ long double Complex_f::abs(Complex_f &z) Complex_f Complex_f::sqrtc(Complex_f &z) { Complex_f c; - long double x,y,w,r; + longdouble x,y,w,r; if (z.re == 0 && z.im == 0) { diff --git a/backend/bcomplex.h b/backend/bcomplex.h index bdebb6cf..2d8b7525 100644 --- a/backend/bcomplex.h +++ b/backend/bcomplex.h @@ -3,6 +3,12 @@ #ifndef BCOMPLEX_H #define BCOMPLEX_H 1 +#if _MSC_VER +#include "longdouble.h" +#else +typedef long double longdouble; +#endif + // Avoid interfering with system and other // such; roll our own for reliable bootstrapping @@ -11,7 +17,7 @@ struct Complex_f static Complex_f div(Complex_f &x, Complex_f &y); static Complex_f mul(Complex_f &x, Complex_f &y); - static long double abs(Complex_f &z); + static longdouble abs(Complex_f &z); static Complex_f sqrtc(Complex_f &z); }; @@ -20,16 +26,16 @@ struct Complex_d static Complex_d div(Complex_d &x, Complex_d &y); static Complex_d mul(Complex_d &x, Complex_d &y); - static long double abs(Complex_d &z); + static longdouble abs(Complex_d &z); static Complex_d sqrtc(Complex_d &z); }; struct Complex_ld -{ long double re, im; +{ longdouble re, im; static Complex_ld div(Complex_ld &x, Complex_ld &y); static Complex_ld mul(Complex_ld &x, Complex_ld &y); - static long double abs(Complex_ld &z); + static longdouble abs(Complex_ld &z); static Complex_ld sqrtc(Complex_ld &z); }; diff --git a/backend/cc.h b/backend/cc.h index b5278972..d11dd347 100644 --- a/backend/cc.h +++ b/backend/cc.h @@ -1,5 +1,5 @@ // Copyright (C) 1985-1998 by Symantec -// Copyright (C) 2000-2009 by Digital Mars +// Copyright (C) 2000-2012 by Digital Mars // All Rights Reserved // http://www.digitalmars.com // Written by Walter Bright @@ -1330,9 +1330,13 @@ struct Aliassym : Symbol { }; #endif /* Format the identifier for presentation to the user */ -char *cpp_prettyident (Symbol *s); +#if SCPP + char *cpp_prettyident (Symbol *s); + inline char *prettyident(Symbol *s) { return CPP ? cpp_prettyident(s) : s->Sident; } +#else + inline char *prettyident(Symbol *s) { return s->Sident; } +#endif -inline char *prettyident(Symbol *s) { return CPP ? cpp_prettyident(s) : s->Sident; } /********************************** * Function parameters: diff --git a/backend/cdef.h b/backend/cdef.h index 5a73153a..3540e475 100644 --- a/backend/cdef.h +++ b/backend/cdef.h @@ -240,7 +240,7 @@ One and only one of these macros must be set by the makefile: #if __GNUC__ #define LONGLONG 1 -#elif __SC__ < 0x700 || _MSC_VER +#elif __SC__ > 0 && __SC__ < 0x700 #define LONGLONG 0 #else #define LONGLONG 1 // add in code to support 64 bit integral types @@ -252,6 +252,12 @@ One and only one of these macros must be set by the makefile: #define LDOUBLE (config.exe == EX_NT) // support true long doubles #endif +#if _MSC_VER +#include "longdouble.h" +#else +typedef long double longdouble; +#endif + // Precompiled header variations #define MEMORYHX (_WINDLL && _WIN32) // HX and SYM files are cached in memory #define MMFIO (_WIN32 || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4) // if memory mapped files @@ -444,7 +450,7 @@ typedef unsigned long long targ_ullong; #endif typedef float targ_float; typedef double targ_double; -typedef long double targ_ldouble; +typedef longdouble targ_ldouble; // Extract most significant register from constant #define MSREG(p) ((REGSIZE == 2) ? (p) >> 16 : ((sizeof(targ_llong) == 8) ? (p) >> 32 : 0)) @@ -459,6 +465,7 @@ typedef unsigned targ_uns; #define WCHARSIZE 2 // 2 for WIN32, 4 for linux/OSX/FreeBSD/OpenBSD/Solaris #define LONGSIZE 4 #define LLONGSIZE 8 +#define CENTSIZE 16 #define FLOATSIZE 4 #define DOUBLESIZE 8 #if TARGET_OSX @@ -482,7 +489,8 @@ typedef unsigned targ_uns; #define FPTRSIZE tysize[TYfptr] #define REGMASK 0xFFFF -#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || TARGET_OSX +// targ_llong is also used to store host pointers, so it should have at least their size +#if TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS || TARGET_OSX || _WIN64 typedef targ_llong targ_ptrdiff_t; /* ptrdiff_t for target machine */ typedef targ_ullong targ_size_t; /* size_t for the target machine */ #else @@ -585,9 +593,6 @@ typedef int bool; #define __far #define __cs #define __ss -#define near -#define _near -#define __near #endif // gcc defines this for us, dmc doesn't, so look for it's __I86__ diff --git a/backend/cdeflnx.h b/backend/cdeflnx.h index 5d1bd12e..720d7a33 100644 --- a/backend/cdeflnx.h +++ b/backend/cdeflnx.h @@ -28,8 +28,6 @@ #define __stdcall __attribute__ ((__stdcall__)) #define __pascal -#define __near -#define _near #define __far #define _far #define __ss diff --git a/backend/cg87.c b/backend/cg87.c index 67c0cbe1..53161d45 100644 --- a/backend/cg87.c +++ b/backend/cg87.c @@ -663,21 +663,18 @@ __body {0.0,1.0,PI,LOG2T,LOG2E,LOG2,LN2}; static double dval[7] = {0.0,1.0,PI,LOG2T,LOG2E,LOG2,LN2}; - static long double ldval[7] = -#if __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 -#define M_PIl 0x1.921fb54442d1846ap+1L // 3.14159 fldpi + static longdouble ldval[7] = +#if __DMC__ // from math.h + {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; +#elif _MSC_VER // struct longdouble constants + {ld_zero, ld_one, ld_pi, ld_log2t, ld_log2e, ld_log2, ld_ln2}; +#else // C99 hexadecimal floats (GCC, CLANG, ...) +#define M_PI_L 0x1.921fb54442d1846ap+1L // 3.14159 fldpi #define M_LOG2T_L 0x1.a934f0979a3715fcp+1L // 3.32193 fldl2t -#define M_LOG2El 0x1.71547652b82fe178p+0L // 1.4427 fldl2e +#define M_LOG2E_L 0x1.71547652b82fe178p+0L // 1.4427 fldl2e #define M_LOG2_L 0x1.34413509f79fef32p-2L // 0.30103 fldlg2 -#define M_LN2l 0x1.62e42fefa39ef358p-1L // 0.693147 fldln2 - {0.0,1.0,M_PIl,M_LOG2T_L,M_LOG2El,M_LOG2_L,M_LN2l}; -#elif __GNUC__ - // BUG: should get proper 80 bit values for these - #define M_LOG2T_L LOG2T - #define M_LOG2_L LOG2 - {0.0,1.0,M_PIl,M_LOG2T_L,M_LOG2El,M_LOG2_L,M_LN2l}; -#else - {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; +#define M_LN2_L 0x1.62e42fefa39ef358p-1L // 0.693147 fldln2 + {0.0,1.0,M_PI_L,M_LOG2T_L,M_LOG2E_L,M_LOG2_L,M_LN2_L}; #endif static char opcode[7 + 1] = /* FLDZ,FLD1,FLDPI,FLDL2T,FLDL2E,FLDLG2,FLDLN2,0 */ @@ -689,7 +686,7 @@ __body int sz; int zero; void *p; - static char zeros[sizeof(long double)]; + static char zeros[sizeof(longdouble)]; if (im == 0) { @@ -2302,7 +2299,7 @@ code *opass87(elem *e,regm_t *pretregs) retregs = mST0; cr = codelem(e->E2,&retregs,FALSE); // evaluate rvalue note87(e->E2,0,0); - cl = getlvalue(&cs,e->E1,0); + cl = getlvalue(&cs,e->E1,e->Eoper==OPmodass?mAX:0); cl = cat(cl,makesure87(e->E2,0,0,0)); cs.Iflags |= ADDFWAIT() ? CFwait : 0; if (I32) diff --git a/backend/cgcod.c b/backend/cgcod.c index 395b4fa2..2a8267b2 100644 --- a/backend/cgcod.c +++ b/backend/cgcod.c @@ -17,7 +17,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/backend/cgcs.c b/backend/cgcs.c index 9b981f04..28bcfbb7 100644 --- a/backend/cgcs.c +++ b/backend/cgcs.c @@ -302,7 +302,6 @@ STATIC void ecom(elem **pe) if (tyfloating(tym)) return; break; -#if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: @@ -312,9 +311,7 @@ STATIC void ecom(elem **pe) ecom(&e->E1); touchfunc(0); return; -#endif default: /* other operators */ -#if TX86 #ifdef DEBUG if (!EBIN(e)) WROP(e->Eoper); #endif @@ -334,16 +331,6 @@ STATIC void ecom(elem **pe) ecom(&e->E1); ecom(&e->E2); break; -#else -#ifdef DEBUG - if (!EOP(e)) WROP(e->Eoper); -#endif - assert(EOP(e)); - ecom(&e->E1); - if (EBIN(e)) - ecom(&e->E2); /* eval left first */ - break; -#endif case OPstring: case OPaddr: case OPbit: @@ -620,12 +607,10 @@ STATIC void touchfunc(int flag) } break; case OPind: -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: -#endif goto L1; #if TARGET_SEGMENTED case OPvp_fp: @@ -653,7 +638,7 @@ STATIC void touchstar() for (i = touchstari; i < hcstop; i++) { e = hcstab[i].Helem; - if (e && (e->Eoper == OPind || e->Eoper == OPbt) /*&& !(e->Ety & mTYconst)*/) + if (e && (e->Eoper == OPind || e->Eoper == OPbt) ) hcstab[i].Helem = NULL; } touchstari = hcstop; diff --git a/backend/cgcv.c b/backend/cgcv.c index 96645a25..0290df59 100644 --- a/backend/cgcv.c +++ b/backend/cgcv.c @@ -519,7 +519,7 @@ void cv_init() * Return number of bytes required to store a numeric leaf. */ -inline unsigned cv4_numericbytes(targ_size_t value) +unsigned cv4_numericbytes(targ_size_t value) { unsigned u; if (value < 0x8000) diff --git a/backend/cgcv.h b/backend/cgcv.h index 9af3727c..a0186c0e 100644 --- a/backend/cgcv.h +++ b/backend/cgcv.h @@ -58,7 +58,7 @@ extern Cgcv cgcv; debtyp_t * debtyp_alloc(unsigned length); int cv_stringbytes(const char *name); -inline unsigned cv4_numericbytes(targ_size_t value); +unsigned cv4_numericbytes(targ_size_t value); void cv4_storenumeric(unsigned char *p,targ_size_t value); idx_t cv_debtyp ( debtyp_t *d ); int cv_namestring ( unsigned char *p , const char *name ); diff --git a/backend/cgelem.c b/backend/cgelem.c index b72a8f89..86fdac42 100644 --- a/backend/cgelem.c +++ b/backend/cgelem.c @@ -581,12 +581,6 @@ STATIC elem * elstrcpy(elem *e) #endif case OPstring: /* Replace strcpy(e1,"string") with memcpy(e1,"string",sizeof("string")) */ -#if 0 - // As memcpy - e->Eoper = OPmemcpy; - elem *en = el_long(TYsize_t, strlen(e->E2->EV.ss.Vstring) + 1); - e->E2 = el_bin(OPparam,TYvoid,e->E2,en); -#else // As streq e->Eoper = OPstreq; type *t = type_allocn(TYarray, tschar); @@ -599,7 +593,6 @@ STATIC elem * elstrcpy(elem *e) e = el_bin(OPcomma,e->Ety,e,el_copytree(e->E1->E1)); if (el_sideeffect(e->E2)) fixside(&e->E1->E1->E1,&e->E2); -#endif e = optelem(e,TRUE); break; } @@ -741,7 +734,6 @@ STATIC elem * elmemxxx(elem *e) el_free(ex); return optelem(e, TRUE); } -#if 1 // Convert OPmemcpy to OPstreq e->Eoper = OPstreq; type *t = type_allocn(TYarray, tschar); @@ -761,7 +753,6 @@ STATIC elem * elmemxxx(elem *e) if (el_sideeffect(e->E2)) fixside(&e->E1->E1->E1,&e->E2); return optelem(e,TRUE); -#endif } break; @@ -2520,7 +2511,6 @@ CEXTERN elem * elstruct(elem *e) if (e->ET) switch ((int) type_size(e->ET)) { -#if TX86 case CHARSIZE: tym = TYchar; goto L1; case SHORTSIZE: tym = TYshort; goto L1; case LONGSIZE: tym = TYlong; goto L1; @@ -2547,7 +2537,6 @@ CEXTERN elem * elstruct(elem *e) break; } break; -#endif case 0: if (e->Eoper == OPstreq) { e->Eoper = OPcomma; @@ -3853,6 +3842,78 @@ STATIC elem * elshr(elem *e) return e; } +/*********************************** + * Handle OPmsw. + */ + +elem *elmsw(elem *e) +{ +#if TX86 + tym_t ty = e->Ety; + elem *e1 = e->E1; + + if (OPTIMIZER && + tysize(e1->Ety) == LLONGSIZE && + tysize(ty) == LONGSIZE) + { + // Replace (int)(msw (long)x) with (int)*(&x+4) + if (e1->Eoper == OPvar) + { + e1->EV.sp.Voffset += LONGSIZE; // address high dword in longlong + if (I64) + // Cannot independently address high word of register + e1->EV.sp.Vsym->Sflags &= ~GTregcand; + e1->Ety = ty; + e = optelem(e1,TRUE); + } + // Replace (int)(msw (long)*x) with (int)*(&*x+4) + else if (e1->Eoper == OPind) + { + e1 = el_una(OPind,ty, + el_bin(OPadd,e1->E1->Ety, + el_una(OPaddr,e1->E1->Ety,e1), + el_int(TYint,LONGSIZE))); + e = optelem(e1,TRUE); + } + else + { + e = evalu8(e); + } + } + else if (OPTIMIZER && I64 && + tysize(e1->Ety) == CENTSIZE && + tysize(ty) == LLONGSIZE) + { + // Replace (long)(msw (cent)x) with (long)*(&x+8) + if (e1->Eoper == OPvar) + { + e1->EV.sp.Voffset += LLONGSIZE; // address high dword in longlong + e1->Ety = ty; + e = optelem(e1,TRUE); + } + // Replace (long)(msw (cent)*x) with (long)*(&*x+8) + else if (e1->Eoper == OPind) + { + e1 = el_una(OPind,ty, + el_bin(OPadd,e1->E1->Ety, + el_una(OPaddr,e1->E1->Ety,e1), + el_int(TYint,LLONGSIZE))); + e = optelem(e1,TRUE); + } + else + { + e = evalu8(e); + } + } + else + { + e = evalu8(e); + } + +#endif + return e; +} + /*********************************** * Handle OPpair, OPrpair. */ @@ -4147,7 +4208,6 @@ beg: goto retnull; leftgoal = rightgoal; break; -#if TX86 case OPmemcmp: if (!goal) { // So OPmemcmp is removed cleanly @@ -4156,7 +4216,6 @@ beg: } leftgoal = rightgoal; break; -#endif } e1 = e->E1; diff --git a/backend/cgobj.c b/backend/cgobj.c index 60d253b9..25909041 100644 --- a/backend/cgobj.c +++ b/backend/cgobj.c @@ -1129,7 +1129,7 @@ void obj_user(const char *p) STATIC void obj_defaultlib() { char library[4]; // default library - static const char model[MEMMODELS] = "SMCLV"; + static const char model[MEMMODELS+1] = "SMCLV"; #if MARS memcpy(library,"SM?",4); @@ -1264,7 +1264,7 @@ void obj_theadr(const char *modname) void obj_compiler() { - static const char compiler[] = "\0\xDBDigital Mars C/C++" + static const char compiler[] = "\0\xDB" "Digital Mars C/C++" VERSION ; // compiled by ... @@ -1292,7 +1292,7 @@ STATIC void objheader(char *csegname) int texti = 8; // index of _TEXT static char comment[] = {0,0x9D,'0','?','O'}; // memory model - static char model[MEMMODELS] = "smclv"; + static char model[MEMMODELS+1] = "smclv"; static char exten[] = {0,0xA1,1,'C','V'}; // extended format static char pmdeb[] = {0x80,0xA1,1,'H','L','L',0}; // IBM PM debug format @@ -1606,7 +1606,7 @@ void obj_funcptr(Symbol *s) { // We need to always put out the segments in triples, so that the // linker will put them in the correct order. - static char lnames[4][5+4+5] = + static char lnames[4][5+4+5+1] = { "\03XIB\02XI\03XIE", // near constructor "\03XCB\02XC\03XCE", // near destructor "\04XIFB\03XIF\04XIFE", // far constructor @@ -2137,7 +2137,7 @@ size_t obj_mangle(Symbol *s,char *dest) // Use as max length the max length lib.exe can handle // Use 5 as length of _ + @nnn - #define LIBIDMAX ((512 - 0x25 - 3 - 4) - 5) +// #define LIBIDMAX ((512 - 0x25 - 3 - 4) - 5) #define LIBIDMAX 128 if (len > LIBIDMAX) //if (len > IDMAX) @@ -2954,7 +2954,7 @@ unsigned obj_bytes(int seg,targ_size_t offset,unsigned nbytes, void *p) while (nbytes) { obj_byte(seg,offset,*(char *)p); offset++; - ((char *)p)++; + p = ((char *)p) + 1; nbytes--; lr = SegData[seg]->ledata; if (lr->i + nbytes <= LEDATAMAX) diff --git a/backend/cgxmm.c b/backend/cgxmm.c index 727b9c0e..4b2daf41 100644 --- a/backend/cgxmm.c +++ b/backend/cgxmm.c @@ -92,6 +92,32 @@ code *orthxmm(elem *e, regm_t *pretregs) unsigned op = xmmoperator(e1->Ety, e->Eoper); unsigned rreg = findreg(rretregs); + // float + ifloat is not actually addition + if ((e->Eoper == OPadd || e->Eoper == OPmin) && + ((tyreal(e1->Ety) && tyimaginary(e2->Ety)) || + (tyreal(e2->Ety) && tyimaginary(e1->Ety)))) + { + retregs |= rretregs; + c = cat(c, cr); + if (e->Eoper == OPmin) + { + unsigned nretregs = XMMREGS & ~retregs; + unsigned sreg; // hold sign bit + unsigned sz = tysize[tybasic(e1->Ety)]; + c = cat(c,allocreg(&nretregs,&sreg,e2->Ety)); + targ_size_t signbit = 0x80000000; + if (sz == 8) + signbit = 0x8000000000000000LL; + c = cat(c, movxmmconst(sreg, sz, signbit, 0)); + c = cat(c, getregs(nretregs)); + unsigned xop = (sz == 8) ? XORPD : XORPS; // XORPD/S rreg,sreg + c = cat(c, gen2(CNIL,xop,modregxrmx(3,rreg-XMM0,sreg-XMM0))); + } + if (retregs != *pretregs) + c = cat(c, fixresult(e,retregs,pretregs)); + return c; + } + code *cg; if (OTrel(e->Eoper)) { @@ -482,8 +508,10 @@ unsigned xmmload(tym_t tym) switch (tybasic(tym)) { case TYfloat: + case TYcfloat: case TYifloat: op = LODSS; break; // MOVSS case TYdouble: + case TYcdouble: case TYidouble: op = LODSD; break; // MOVSD case TYfloat4: op = LODAPS; break; // MOVAPS @@ -520,6 +548,7 @@ unsigned xmmstore(tym_t tym) case TYullong: case TYuint: case TYlong: + case TYcdouble: case TYcfloat: op = STOSD; break; // MOVSD case TYfloat4: op = STOAPS; break; // MOVAPS diff --git a/backend/cod1.c b/backend/cod1.c index 4474989c..e5b79506 100644 --- a/backend/cod1.c +++ b/backend/cod1.c @@ -17,7 +17,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/backend/cod3.c b/backend/cod3.c index 7848ade4..372f1582 100644 --- a/backend/cod3.c +++ b/backend/cod3.c @@ -631,7 +631,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym code_orrex(cs, REX_W); } } - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); if (nalign) { cs = genc2(cs,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -694,7 +694,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym code_orrex(c, REX_W); } // CALL bl->Bsucc - c = genc(c,0xE8,0,0,0,FLblock,(long)list_block(bl->Bsucc)); + c = genc(c,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bl->Bsucc)); if (nalign) { c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -711,7 +711,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym // corresponding BC_ret //assert(list_block(list_next(bl->Bsucc))->BC == BC_ret); // PUSH &succ - c = genc(c,0x68,0,0,0,FLblock,(long)list_block(list_next(bl->Bsucc))); + c = genc(c,0x68,0,0,0,FLblock,(targ_size_t)list_block(list_next(bl->Bsucc))); nextb = list_block(bl->Bsucc); goto L2; } @@ -811,7 +811,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym c = cat(c,nteh_gensindex(-1)); gensaverestore(retregs,&cs,&cr); - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); bl->Bcode = cat3(c,cs,cr); } else @@ -836,7 +836,7 @@ void outblkexitcode(block *bl, code*& c, int& anyspill, const char* sflsave, sym } } // CALL bf->Bsucc - cs = genc(cs,0xE8,0,0,0,FLblock,(long)list_block(bf->Bsucc)); + cs = genc(cs,0xE8,0,0,0,FLblock,(targ_size_t)list_block(bf->Bsucc)); if (nalign) { cs = genc2(cs,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign if (I64) @@ -5179,7 +5179,7 @@ static char *pgen; #define GEN(c) (*pgen++ = (c)) #define GENP(n,p) (memcpy(pgen,(p),(n)), pgen += (n)) -#if ELFOBJ || MACHOBJ +#if ELFOBJ || MACHOBJ || _MSC_VER #define FLUSH() if (pgen-bytes) cod3_flush() #else #define FLUSH() ((pgen - bytes) && cod3_flush()) diff --git a/backend/code.h b/backend/code.h index 8c79aef2..588dc733 100644 --- a/backend/code.h +++ b/backend/code.h @@ -32,14 +32,17 @@ struct Declaration; #define SI 6 #define DI 7 -#define R8 8 -#define R9 9 -#define R10 10 -#define R11 11 -#define R12 12 -#define R13 13 -#define R14 14 -#define R15 15 +enum // #defining R12-R15 interfere with setjmps' _JUMP_BUFFER members +{ + R8 = 8, + R9 = 9, + R10 = 10, + R11 = 11, + R12 = 12, + R13 = 13, + R14 = 14, + R15 = 15, +}; #define XMM0 16 #define XMM1 17 diff --git a/backend/cppman.c b/backend/cppman.c index bcb82357..3bfc8631 100644 --- a/backend/cppman.c +++ b/backend/cppman.c @@ -624,7 +624,7 @@ char *template_mangle(symbol *s,param_t *arglist) } p = (char *)&d; // ni = tysize[TYdouble]; - ni = sizeof(long double); // just until new unmangler is in + ni = sizeof(longdouble); // just until new unmangler is in L1: a[1] = 0; n = cpp_catname(n,a); diff --git a/backend/debug.c b/backend/debug.c index f46390e1..c26396d7 100644 --- a/backend/debug.c +++ b/backend/debug.c @@ -1,5 +1,5 @@ // Copyright (C) 1985-1998 by Symantec -// Copyright (C) 2000-2009 by Digital Mars +// Copyright (C) 2000-2012 by Digital Mars // All Rights Reserved // http://www.digitalmars.com // Written by Walter Bright @@ -201,8 +201,17 @@ void WReqn(elem *e) dbg_printf("%g ",e->EV.Vdouble); break; case TYldouble: +#if _MSC_VER + { + char buffer[3 + 3 * sizeof(targ_ldouble) + 1]; + ld_sprint(buffer, 'g', e->EV.Vldouble); + dbg_printf("%s ",buffer); + break; + } +#else dbg_printf("%Lg ",e->EV.Vldouble); break; +#endif case TYcent: case TYucent: dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw); diff --git a/backend/dt.h b/backend/dt.h index 99e722ae..805c9352 100644 --- a/backend/dt.h +++ b/backend/dt.h @@ -60,10 +60,8 @@ struct dt_t #define DTpbytes _DU._DN.DTpbytes_ unsigned DTnbytes_; // # of bytes #define DTnbytes _DU._DN.DTnbytes_ -#if TX86 int DTseg_; // segment it went into #define DTseg _DU._DN.DTseg_ -#endif targ_size_t DTabytes_; // offset of abytes for DTabytes #define DTabytes _DU._DN.DTabytes_ }_DN; @@ -90,11 +88,9 @@ enum DT_ibytes, // 8 }; -#if TX86 dt_t *dt_calloc(char dtx); void dt_free(dt_t *); void dt_term(void); -#endif dt_t **dtnbytes(dt_t **,targ_size_t,const char *); dt_t **dtabytes(dt_t **pdtend,tym_t ty, targ_size_t offset, targ_size_t size, const char *ptr); diff --git a/backend/dwarf.c b/backend/dwarf.c index c3a473a3..11a3433b 100644 --- a/backend/dwarf.c +++ b/backend/dwarf.c @@ -1621,9 +1621,12 @@ unsigned dwarf_typidx(type *t) tym_t ty; ty = tybasic(t->Tty); - idx = typidx_tab[ty]; - if (idx) - return idx; + if (!(t->Tnext && (ty == TYucent || ty == TYcent))) + { // use cached basic type if it's not TYdarray or TYdelegate + idx = typidx_tab[ty]; + if (idx) + return idx; + } unsigned char ate; ate = tyuns(t->Tty) ? DW_ATE_unsigned : DW_ATE_signed; diff --git a/backend/el.c b/backend/el.c index 4d2f76ad..85ecbf00 100644 --- a/backend/el.c +++ b/backend/el.c @@ -93,7 +93,6 @@ void el_reset() memset(stable,0,sizeof(stable)); } -#if TX86 /************************ * Terminate el package. */ @@ -101,9 +100,7 @@ void el_reset() void el_term() { #if TERMCODE - int i; - - for (i = 0; i < arraysize(stable); i++) + for (int i = 0; i < arraysize(stable); i++) mem_free(stable[i].p); #ifdef DEBUG @@ -122,7 +119,6 @@ void el_term() assert(elcount == 0); #endif } -#endif /*********************** * Allocate an element. @@ -873,12 +869,7 @@ void el_toconst(elem *e) { elem_debug(e); assert(PARSER); -#if TX86 if (e->Eoper == OPvar && e->EV.sp.Vsym->Sflags & SFLvalue) -#else - if (e->Eoper == OPvar && e->EV.sp.Vsym->Sflags & SFLvalue && - tybasic(e->ET->Tty) != TYstruct) -#endif { elem *es = e->EV.sp.Vsym->Svalue; type_debug(e->ET); @@ -1053,7 +1044,6 @@ int el_sideeffect(elem *e) el_sideeffect(e->E2))); } -#if TX86 /****************************** * Input: * ea lvalue (might be an OPbit) @@ -1100,7 +1090,6 @@ int el_depends(elem *ea,elem *eb) Lnodep: return 0; } -#endif /*************************************** * Allocate localgot symbol. @@ -1570,12 +1559,12 @@ elem * el_var(symbol *s) e->Eoper = OPvar; e->EV.sp.Vsym = s; if (SCPP && PARSER) -#if TX86 && TARGET_WINDOS { type *t = s->Stype; type_debug(t); e->ET = t; t->Tcount++; +#if TARGET_WINDOS switch (t->Tty & (mTYimport | mTYthread)) { case mTYimport: obj_import(e); @@ -1613,18 +1602,11 @@ elem * el_var(symbol *s) break; case mTYthread | mTYimport: assert(SCPP); -#if SCPP tx86err(EM_thread_and_dllimport,s->Sident); // can't be both thread and import -#endif break; } - } -#else - { type_debug(s->Stype); - e->ET = s->Stype; - e->ET->Tcount++; - } #endif + } else e->Ety = s->ty(); return e; @@ -2037,8 +2019,13 @@ void shrinkLongDoubleConstantIfPossible(elem *e) * Use 'volatile' to prevent optimizer from folding away the conversions, * and thereby missing the truncation in the conversion to double. */ +#if _MSC_VER + volatile_longdouble v = e->EV.Vldouble; +#else volatile long double v = e->EV.Vldouble; +#endif volatile double vDouble; + *(&vDouble) = v; if (v == vDouble) // This will fail if compiler does NaN incorrectly! { @@ -2217,10 +2204,8 @@ elem *el_ctor(elem *ector,elem *e,symbol *sdtor) } if (!sdtor || ector->Eoper == OPcall || (ector->Eoper == OPrelconst && !(sytab[ector->EV.sp.Vsym->Sclass] & SCSS)) -#if TX86 // Not ambient memory model || (tyfarfunc(sdtor->ty()) ? !LARGECODE : LARGECODE) -#endif ) { el_free(ector); @@ -2327,11 +2312,7 @@ L1: if ((tym = typemask(n1)) != (tym2 = typemask(n2))) { -#if TX86 if ((tym & ~mTYbasic) != (tym2 & ~mTYbasic)) -#else - if ((tym & ~mTYbasic & ~mTYMAN) != (tym2 & ~mTYbasic & ~mTYMAN)) -#endif { if (!(gmatch2 & 2)) goto nomatch; @@ -2441,7 +2422,6 @@ L1: else goto case_long; -#if TX86 #if JHANDLE case TYjhandle: #endif @@ -2459,7 +2439,6 @@ L1: { assert(NPTRSIZE == LLONGSIZE); goto case_llong; } -#endif case TYbool: case TYchar: @@ -2717,7 +2696,7 @@ L1: Ushort: result = e->EV.Vushort; break; -#if SCPP && TX86 +#if SCPP case TYenum: assert(PARSER); ty = e->ET->Tnext->Tty; @@ -2869,7 +2848,6 @@ targ_ldouble el_toldouble(elem *e) elem_debug(e); assert(cnst(e)); -#if TX86 switch (tybasic(typemask(e))) { case TYfloat: @@ -2889,28 +2867,6 @@ targ_ldouble el_toldouble(elem *e) result = 0; break; } -#else - switch (tysize[tybasic(typemask(e))]) - { - case FLOATSIZE: // TYfloat - result = e->EV.Vfloat; - break; - case DOUBLESIZE: // TYdouble - result = e->EV.Vdouble; - break; -#if DOUBLESIZE != LNGDBLSIZE - case LNGDBLSIZE: // TYldouble -#ifdef LNGHDBLSIZE - case LNGHDBLSIZE: -#endif - result = e->EV.Vldouble; - break; -#endif - default: - result = 0; - break; - } -#endif return result; } @@ -3096,10 +3052,8 @@ void elem_print(elem *e) case TYint: case TYuint: case TYvoid: /* in case (void)(1) */ -#if TX86 if (tysize[TYint] == LONGSIZE) goto L1; -#endif case TYshort: case TYwchar_t: case TYushort: @@ -3141,9 +3095,16 @@ void elem_print(elem *e) dbg_printf("%g ",(double)e->EV.Vdouble); break; case TYldouble: + { +#if _MSC_VER + char buffer[3 + 3 * sizeof(targ_ldouble) + 1]; + ld_sprint(buffer, 'g', e->EV.Vldouble); + dbg_printf("%s ", buffer); +#else dbg_printf("%Lg ", e->EV.Vldouble); +#endif break; - + } case TYifloat: dbg_printf("%gfi ", (double)e->EV.Vfloat); break; @@ -3252,11 +3213,7 @@ void el_hydrate(elem **pe) //if (tybasic(e->ET->Tty) == TYmemptr) //el_hydrate(&e->EV.sm.ethis); case OPvar: -#if TX86 symbol_hydrate(&e->EV.sp.Vsym); -#else - ph_hydrate(&e->EV.sp.Vsym); -#endif symbol_debug(e->EV.sp.Vsym); break; } @@ -3288,10 +3245,8 @@ void el_dehydrate(elem **pe) return; #endif type_dehydrate(&e->ET); -#if TX86 if (configv.addlinenumbers) srcpos_dehydrate(&e->Esrcpos); -#endif if (EOP(e)) { el_dehydrate(&e->E1); if (EBIN(e)) @@ -3312,11 +3267,7 @@ void el_dehydrate(elem **pe) //if (tybasic(e->ET->Tty) == TYmemptr) //el_dehydrate(&e->EV.sm.ethis); case OPvar: -#if TX86 symbol_dehydrate(&e->EV.sp.Vsym); -#else - ph_dehydrate(&e->EV.sp.Vsym); -#endif break; } } diff --git a/backend/evalu8.c b/backend/evalu8.c index 59600236..86ddf3af 100644 --- a/backend/evalu8.c +++ b/backend/evalu8.c @@ -78,7 +78,7 @@ static int resolve_sizeof; */ #if __DMC__ -long double _modulo(long double x, long double y) +longdouble _modulo(longdouble x, longdouble y) { short sw; __asm @@ -384,7 +384,6 @@ elem *poptelem(elem *e) L3: e = selecte1(e,e->ET); e->Eoper = OPrelconst; -#if 1 // If this is an address of a function template, // try to expand the template if it's got an explicit // parameter list. @@ -402,56 +401,16 @@ elem *poptelem(elem *e) type_settype(&e->ET, newpointer(s->Stype)); } } -#endif } break; case OPind: e->E1 = e1 = poptelem(e->E1); -#if TX86 if (e1->Eoper == OPrelconst) { /* convert *(&var) to var */ e = selecte1(e,e->ET); e->Eoper = OPvar; } -#else - if (e1->Eoper == OPrelconst) - { - unsigned to_sz = tysize(tym_conv(e->ET)); - unsigned frm_sz = tysize(tym_conv(e1->ET)); - - if (tyfunc(tybasic(e->ET->Tty))) - to_sz = LONGSIZE; - else if (tybasic(e->ET->Tty) == TYstruct || tybasic(e->ET->Tty) == TYarray) - { - to_sz = LONGSIZE; - e1->ET = e->ET; - } - if(to_sz == frm_sz) - { /* convert *(&var) to var */ -doit: - e = selecte1(e,e->ET); - e->Eoper = OPvar; - } - else /* handle the most common cases for now */ - { unsigned offset = e1->Eoffset; - switch(to_sz) - { - case SHORTSIZE: - if (frm_sz == LONGSIZE && (offset%LONGSIZE) == SHORTSIZE) - goto doit; - break; - case CHARSIZE: - if (frm_sz == LONGSIZE && - offset%(LONGSIZE-CHARSIZE) == CHARSIZE) - goto doit; - if (frm_sz == SHORTSIZE && offset&1) - goto doit; - break; - } - } - } -#endif break; #if TARGET_SEGMENTED case OPnp_fp: @@ -640,13 +599,13 @@ elem * evalu8(elem *e) d1 = el_toldouble(e1); tym = tybasic(typemask(e1)); /* type of op is type of left child */ -#if TX86 && SCPP +#if TARGET_SEGMENTED && SCPP // Huge pointers are always evaluated at runtime if (tym == TYhptr && (l1 != 0 || l2 != 0)) return e; #endif esave = *e; -#if !__OpenBSD__ +#if TX86 && !__OpenBSD__ _clear87(); #endif } @@ -844,7 +803,7 @@ elem * evalu8(elem *e) break; default: -#if TX86 +#if TARGET_SEGMENTED if (intsize == 2) { if (tyfv(tym)) e->EV.Vlong = (l1 & 0xFFFF0000) | @@ -1039,7 +998,7 @@ elem * evalu8(elem *e) break; default: -#if TX86 +#if TARGET_SEGMENTED if (intsize == 2 && tyfv(tym) && tysize[tym2] == 2) e->EV.Vllong = (l1 & 0xFFFF0000) | @@ -1589,7 +1548,6 @@ elem * evalu8(elem *e) break; case OPneg: -#if TX86 // Avoid converting NANS to NAN memcpy(&e->EV.Vcldouble,&e1->EV.Vcldouble,sizeof(e->EV.Vcldouble)); switch (tym) @@ -1622,25 +1580,8 @@ elem * evalu8(elem *e) e->EV.Vllong = -l1; break; } -#else - switch (tym) - { case TYdouble: - e->EV.Vdouble = -e1->EV.Vdouble; - break; - case TYfloat: - e->EV.Vfloat = -e1->EV.Vfloat; - break; - case TYldouble: - e->EV.Vldouble = -d1; - break; - default: - e->EV.Vllong = -l1; - break; - } -#endif break; case OPabs: -#if 1 switch (tym) { case TYdouble: @@ -1674,7 +1615,6 @@ elem * evalu8(elem *e) break; } break; -#endif case OPsqrt: case OPrndtol: case OPsin: @@ -1745,7 +1685,7 @@ elem * evalu8(elem *e) case TYcfloat: if (isnan(e1->EV.Vcfloat.re) || isnan(e1->EV.Vcfloat.im) || isnan(e2->EV.Vcfloat.re) || isnan(e2->EV.Vcfloat.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcfloat.re == e2->EV.Vcfloat.re) && (e1->EV.Vcfloat.im == e2->EV.Vcfloat.im)); @@ -1753,7 +1693,7 @@ elem * evalu8(elem *e) case TYcdouble: if (isnan(e1->EV.Vcdouble.re) || isnan(e1->EV.Vcdouble.im) || isnan(e2->EV.Vcdouble.re) || isnan(e2->EV.Vcdouble.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcdouble.re == e2->EV.Vcdouble.re) && (e1->EV.Vcdouble.im == e2->EV.Vcdouble.im)); @@ -1761,7 +1701,7 @@ elem * evalu8(elem *e) case TYcldouble: if (isnan(e1->EV.Vcldouble.re) || isnan(e1->EV.Vcldouble.im) || isnan(e2->EV.Vcldouble.re) || isnan(e2->EV.Vcldouble.im)) - i ^= 1; + ; else i ^= (int)((e1->EV.Vcldouble.re == e2->EV.Vcldouble.re) && (e1->EV.Vcldouble.im == e2->EV.Vcldouble.im)); diff --git a/backend/gflow.c b/backend/gflow.c index 5a92125a..a7b7f95b 100644 --- a/backend/gflow.c +++ b/backend/gflow.c @@ -805,12 +805,10 @@ void main() ) break; #endif -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: // OPbt is like OPind -#endif vec_setbit(i,defkill); vec_setbit(i,starkill); break; @@ -1339,11 +1337,9 @@ STATIC void accumlv(vec_t GEN,vec_t KILL,elem *n) case OPcall: case OPcallns: -#if TX86 case OPstrcpy: case OPmemcpy: case OPmemset: -#endif #ifdef DEBUG assert(OTrtol(op)); #endif @@ -1351,14 +1347,12 @@ STATIC void accumlv(vec_t GEN,vec_t KILL,elem *n) accumlv(GEN,KILL,n->E1); goto L1; -#if TX86 case OPstrcat: #ifdef DEBUG assert(!OTrtol(op)); #endif accumlv(GEN,KILL,n->E1); accumlv(GEN,KILL,n->E2); -#endif L1: vec_orass(GEN,ambigsym); vec_subass(GEN,KILL); diff --git a/backend/global.h b/backend/global.h index c0f361f9..7a7111e8 100644 --- a/backend/global.h +++ b/backend/global.h @@ -115,11 +115,14 @@ elem *exp2_copytotemp(elem *e); /* util.c */ #if __clang__ -void util_exit(int) __attribute__((analyzer_noreturn)); -void util_assert(char *, int) __attribute__((analyzer_noreturn)); +void util_exit(int) __attribute__((noreturn)); +void util_assert(const char *, int) __attribute__((noreturn)); +#elif _MSC_VER +__declspec(noreturn) void util_exit(int); +__declspec(noreturn) void util_assert(const char *, int); #else void util_exit(int); -void util_assert(char *, int); +void util_assert(const char *, int); #if __DMC__ #pragma ZTC noreturn(util_exit) #pragma ZTC noreturn(util_assert) @@ -512,7 +515,8 @@ Symbol *symboldata(targ_size_t offset,tym_t ty); int dom(block *A , block *B); unsigned revop(unsigned op); unsigned invrel(unsigned op); -int binary(const char *p, const char __near * __near *tab, int high); +int binary(const char *p, const char ** tab, int high); +int binary(const char *p, size_t len, const char ** tab, int high); /* go.c */ void go_term(void); diff --git a/backend/glocal.c b/backend/glocal.c index 10fd0373..680da44e 100644 --- a/backend/glocal.c +++ b/backend/glocal.c @@ -16,7 +16,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif @@ -269,9 +269,7 @@ Loop: local_remove(LFambigdef | LFambigref); } break; -#if TX86 case OPstrlen: -#endif case OPind: local_exp(e->E1,1); local_ambigref(); @@ -316,7 +314,6 @@ Loop: local_remove(LFfloat | LFambigref | LFambigdef); break; -#if TX86 case OPmemset: local_exp(e->E2,1); if (e->E1->Eoper == OPvar) @@ -334,7 +331,6 @@ Loop: local_exp(e->E1,1); local_ambigdef(); break; -#endif case OPvar: s = e->EV.sp.Vsym; @@ -590,23 +586,19 @@ STATIC int local_getflags(elem *e,symbol *s) case OPcallns: case OPnewarray: case OPmultinewarray: -#if TX86 case OPstrcat: case OPstrcpy: case OPmemcpy: case OPbtc: case OPbtr: case OPbts: -#endif case OPstrctor: flags |= LFambigref | LFambigdef; break; -#if TX86 case OPmemset: flags |= LFambigdef; break; -#endif case OPvar: if (e->EV.sp.Vsym == s) @@ -618,12 +610,10 @@ STATIC int local_getflags(elem *e,symbol *s) case OPind: case OParray: case OPfield: -#if TX86 case OPstrlen: case OPstrcmp: case OPmemcmp: case OPbt: -#endif flags |= LFambigref; break; diff --git a/backend/gloop.c b/backend/gloop.c index d8600ac9..ff03c25b 100644 --- a/backend/gloop.c +++ b/backend/gloop.c @@ -958,7 +958,6 @@ STATIC void markinvar(elem *n,vec_t rd) markinvar(n->E1,rd); break; -#if TX86 case OPstrcpy: case OPstrcat: case OPmemcpy: @@ -974,7 +973,6 @@ STATIC void markinvar(elem *n,vec_t rd) markinvar(n->E2,rd); updaterd(n,rd,NULL); break; -#endif case OPucall: markinvar(n->E1,rd); /* FALL-THROUGH */ @@ -987,20 +985,20 @@ STATIC void markinvar(elem *n,vec_t rd) case OPstrpar: case OPstrctor: case OPvector: -#if TX86 case OPvoid: case OPstrlen: +#if TX86 case OPinp: #endif markinvar(n->E1,rd); break; case OPcond: case OPparam: -#if TX86 - case OPoutp: case OPstrcmp: case OPmemcmp: case OPbt: // OPbt is like OPind, assume not LI +#if TX86 + case OPoutp: #endif markinvar(n->E1,rd); markinvar(n->E2,rd); @@ -1057,12 +1055,10 @@ STATIC void markinvar(elem *n,vec_t rd) case OPsin: case OPcos: case OPrint: -#if TX86 case OPsetjmp: case OPbsf: case OPbsr: case OPbswap: -#endif #if TARGET_SEGMENTED case OPvp_fp: /* BUG for MacHandles */ case OPnp_f16p: case OPf16p_np: case OPoffset: case OPnp_fp: diff --git a/backend/html.c b/backend/html.c index 4e26303f..81d15458 100644 --- a/backend/html.c +++ b/backend/html.c @@ -101,15 +101,15 @@ Html::Html(const char *sourcename, unsigned char *base, unsigned length) void Html::error(const char *format, ...) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + fprintf(stderr, "%s(%d) : HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); - vprintf(format, ap); + vfprintf(stderr, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); + fprintf(stderr, "\n"); + fflush(stderr); //#if MARS // global.errors++; diff --git a/backend/machobj.c b/backend/machobj.c index a710ea02..2b136480 100644 --- a/backend/machobj.c +++ b/backend/machobj.c @@ -1600,9 +1600,7 @@ void obj_ehtables(Symbol *sfunc,targ_size_t size,Symbol *ehsym) int align = I64 ? 3 : 2; // align to NPTRSIZE // The size is sizeof(struct FuncTable) in deh2.d - mach_getsegment("__deh_beg", "__DATA", align, S_COALESCED, 3 * NPTRSIZE); int seg = mach_getsegment("__deh_eh", "__DATA", align, S_REGULAR); - mach_getsegment("__deh_end", "__DATA", align, S_COALESCED, NPTRSIZE); Outbuffer *buf = SegData[seg]->SDbuf; if (I64) @@ -1692,11 +1690,7 @@ int obj_comdat(Symbol *s) else if ((s->ty() & mTYLINK) == mTYthread) { s->Sfl = FLtlsdata; - align = I64 ? 4 : 2; // align to 16 bytes for floating point - mach_getsegment("__tls_beg", "__DATA", align, S_COALESCED, 4); - mach_getsegment("__tls_data", "__DATA", align, S_REGULAR, 4); s->Sseg = mach_getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED); - mach_getsegment("__tls_end", "__DATA", align, S_COALESCED, 4); elf_data_start(s, 1 << align, s->Sseg); } else @@ -1887,10 +1881,7 @@ seg_data *obj_tlsseg() if (seg_tlsseg == UNKNOWN) { int align = I64 ? 4 : 2; // align to 16 bytes for floating point - mach_getsegment("__tls_beg", "__DATA", align, S_COALESCED, 4); seg_tlsseg = mach_getsegment("__tls_data", "__DATA", align, S_REGULAR); - mach_getsegment("__tlscoal_nt", "__DATA", 4, S_COALESCED, 4); - mach_getsegment("__tls_end", "__DATA", align, S_COALESCED, 4); } return SegData[seg_tlsseg]; } @@ -2703,8 +2694,6 @@ void obj_moduleinfo(Symbol *scc) { int align = I64 ? 4 : 2; - mach_getsegment("__minfo_beg", "__DATA", align, S_COALESCED, 4); - int seg = mach_getsegment("__minfodata", "__DATA", align, S_REGULAR); //printf("obj_moduleinfo(%s) seg = %d:x%x\n", scc->Sident, seg, Offset(seg)); @@ -2722,8 +2711,6 @@ void obj_moduleinfo(Symbol *scc) if (I64) flags |= CFoffset64; SegData[seg]->SDoffset += reftoident(seg, Offset(seg), scc, 0, flags); - - mach_getsegment("__minfo_end", "__DATA", align, S_COALESCED, 4); } #endif diff --git a/backend/md5.c b/backend/md5.c index 8675d4a2..2034986f 100644 --- a/backend/md5.c +++ b/backend/md5.c @@ -80,8 +80,7 @@ static unsigned char PADDING[64] = { (a) += (b); \ } -void MD5Init (mdContext) -MD5_CTX *mdContext; +void MD5Init (MD5_CTX *mdContext) { mdContext->i[0] = mdContext->i[1] = (UINT4)0; @@ -93,10 +92,7 @@ MD5_CTX *mdContext; mdContext->buf[3] = (UINT4)0x10325476; } -void MD5Update (mdContext, inBuf, inLen) -MD5_CTX *mdContext; -unsigned char *inBuf; -unsigned int inLen; +void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) { UINT4 in[16]; int mdi; @@ -128,8 +124,7 @@ unsigned int inLen; } } -void MD5Final (mdContext) -MD5_CTX *mdContext; +void MD5Final (MD5_CTX *mdContext) { UINT4 in[16]; int mdi; @@ -169,9 +164,7 @@ MD5_CTX *mdContext; /* Basic MD5 step. Transform buf based on in. */ -static void Transform (buf, in) -UINT4 *buf; -UINT4 *in; +static void Transform (UINT4 *buf, UINT4 *in) { UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; diff --git a/backend/newman.c b/backend/newman.c index c0ac6c86..8cb351c3 100644 --- a/backend/newman.c +++ b/backend/newman.c @@ -132,7 +132,7 @@ struct OPTABLE { unsigned char tokn; unsigned char oper; - char __near *string; + char *string; char *pretty; } #endif @@ -199,6 +199,7 @@ struct OPTABLE /**************************************** * Convert from identifier to operator */ +#if SCPP #if __GNUC__ // NOT DONE - FIX char * unmangle_pt(const char **s) @@ -264,6 +265,7 @@ char *cpp_unmangleident(const char *p) //printf("-cpp_unmangleident() = '%s'\n", p); return (char *)p; } +#endif /**************************************** * Find index in oparray[] for operator. @@ -271,6 +273,8 @@ char *cpp_unmangleident(const char *p) * index or -1 if not found */ +#if SCPP + int cpp_opidx(int op) { int i; @@ -280,6 +284,8 @@ int cpp_opidx(int op) return -1; } +#endif + /*************************************** * Find identifier string associated with operator. * Returns: diff --git a/backend/oper.h b/backend/oper.h index 6d1f2749..3a9c2980 100644 --- a/backend/oper.h +++ b/backend/oper.h @@ -45,9 +45,9 @@ enum OPER OPaddr, /* &E */ OPneg, /* unary - */ OPuadd, /* unary + */ -#if TX86 OPvoid, // where casting to void is not a no-op OPabs, /* absolute value */ +#if TX86 OPsqrt, /* square root */ OPrndtol, // round to short, long, long long (inline 8087 only) OPsin, // sine @@ -56,6 +56,7 @@ enum OPER OPscale, // ldexp OPyl2x, // y * log2(x) OPyl2xp1, // y * log2(x + 1) +#endif OPstrlen, /* strlen() */ OPstrcpy, /* strcpy() */ OPstrcat, /* strcat() */ @@ -64,11 +65,9 @@ enum OPER OPmemcmp, OPmemset, OPsetjmp, // setjmp() -#endif OPremquo, // / and % in one operation -#if TX86 OPbsf, // bit scan forward OPbsr, // bit scan reverse OPbt, // bit test @@ -78,7 +77,6 @@ enum OPER OPbswap, // swap bytes OProl, // rotate left OPror, // rotate right -#endif OPstreq, /* structure assignment */ diff --git a/backend/optabgen.c b/backend/optabgen.c index 69e2ac6d..eefe8cbd 100644 --- a/backend/optabgen.c +++ b/backend/optabgen.c @@ -75,7 +75,6 @@ int _assign[] = {OPstreq,OPeq,OPaddass,OPminass,OPmulass,OPdivass,OPmodass, OPshrass,OPashrass,OPshlass,OPandass,OPxorass,OPorass,OPpostinc,OPpostdec, OPnegass, - /* OPbtc,OPbtr,OPbts,*/ }; int _wid[] = {OPadd,OPmin,OPand,OPor,OPxor,OPcom,OPneg,OPmul,OPaddass,OPnegass, @@ -142,7 +141,7 @@ int _ae[] = {OPvar,OPconst,OPrelconst,OPneg, #if TARGET_SEGMENTED OPvp_fp,OPcvp_fp,OPnp_fp,OPnp_f16p,OPf16p_np,OPoffset, #endif - /*OPcomma,OPbit,OPoror,OPandand,OPcond,OPcolon,OPcolon2*/}; + }; int _exp[] = {OPvar,OPconst,OPrelconst,OPneg,OPabs,OPsqrt,OPrndtol,OPrint, OPsin,OPcos,OPscale,OPyl2x,OPyl2xp1, OPstrlen,OPstrcmp,OPind,OPaddr, @@ -583,7 +582,7 @@ void dotab() case OPu64_128: X("u64_128", evalu8, cdshtlng); case OPs64_128: X("s64_128", evalu8, cdshtlng); case OP128_64: X("128_64", el64_32, cdlngsht); - case OPmsw: X("msw", evalu8, cdmsw); + case OPmsw: X("msw", elmsw, cdmsw); case OPd_s64: X("d_s64", evalu8, cdcnvt); case OPs64_d: X("s64_d", evalu8, cdcnvt); diff --git a/backend/os.c b/backend/os.c index aee44283..02cede08 100644 --- a/backend/os.c +++ b/backend/os.c @@ -40,13 +40,17 @@ #include #endif -#if __DMC__ || __GNUC__ +#if __DMC__ || __GNUC__ || _MSC_VER static char __file__[] = __FILE__; /* for tassert.h */ #include "tassert.h" #else #include #endif +#if _MSC_VER +#include +#endif + #if _WINDLL extern void dll_printf(const char *format,...); #define dbg_printf dll_printf @@ -61,6 +65,9 @@ int file_createdirs(char *name); * This function does not return. */ +#if _MSC_VER +__declspec(noreturn) +#endif void os_error(int line) { #if _WIN32 @@ -75,7 +82,9 @@ void os_error(int line) #endif #define os_error() os_error(__LINE__) +#if __DMC__ #pragma noreturn(os_error) +#endif #if _WIN32 /********************************* @@ -672,13 +681,13 @@ int os_file_exists(const char *name) * Get file size of open file. Return -1L on error. */ -#if _WIN32 +#if _WIN32 && !_MSC_VER extern "C" void * __cdecl _osfhnd[]; #endif long os_file_size(int fd) { -#if _WIN32 +#if _WIN32 && !_MSC_VER return GetFileSize(_osfhnd[fd],NULL); #else struct stat buf; diff --git a/backend/ptrntab.c b/backend/ptrntab.c index 99b6c9df..a5f39ce6 100644 --- a/backend/ptrntab.c +++ b/backend/ptrntab.c @@ -4039,6 +4039,11 @@ PTRNTAB2 aptb2PMULDQ[] = /* PMULDQ */ { { ASM_END } }; +PTRNTAB3 aptb3VPMULDQ[] = /* VPMULDQ */ { + { VEX_NDS_128_WIG(PMULDQ), _r, _xmm, _xmm, _xmm_m128 }, + { ASM_END } +}; + PTRNTAB2 aptb2PMULLD[] = /* PMULLD */ { { PMULLD, _r, _xmm, _xmm_m128 }, { ASM_END } @@ -5573,6 +5578,7 @@ PTRNTAB3 aptb3VFMSUB231SS[] = /* VFMSUB231SS */ { X("vpmovzxdq", 2, (P) aptb2VPMOVZXDQ ) \ X("vpmovzxwd", 2, (P) aptb2VPMOVZXWD ) \ X("vpmovzxwq", 2, (P) aptb2VPMOVZXWQ ) \ + X("vpmuldq", 3, (P) aptb3VPMULDQ ) \ X("vpmulhrsw", 3, (P) aptb3VPMULHRSW ) \ X("vpmulhuw", 3, (P) aptb3VPMULHUW ) \ X("vpmulhw", 3, (P) aptb3VPMULHW ) \ diff --git a/backend/strtold.c b/backend/strtold.c index 190d5577..bbe0188d 100644 --- a/backend/strtold.c +++ b/backend/strtold.c @@ -16,7 +16,7 @@ #include #include #include -#if _WIN32 +#if _WIN32 && __DMC__ #include #include #endif @@ -24,7 +24,9 @@ #include #endif -#if _WIN32 +#include "longdouble.h" + +#if _WIN32 && __DMC__ // from \sc\src\include\setlocal.h extern char * __cdecl __locale_decpoint; void __pascal __set_errno (int an_errno); @@ -37,22 +39,22 @@ void __pascal __set_errno (int an_errno); * and also makes it clearer what constants we're trying to use. */ -static long double negtab[] = +static longdouble negtab[] = {1e-4096L,1e-2048L,1e-1024L,1e-512L, 1e-256L,1e-128L,1e-64L,1e-32L,1e-16L,1e-8L,1e-4L,1e-2L,1e-1L,1.0L}; -static long double postab[] = +static longdouble postab[] = {1e+4096L,1e+2048L,1e+1024L,1e+512L, 1e+256L,1e+128L,1e+64L,1e+32L,1e+16L,1e+8L,1e+4L,1e+2L,1e+1L}; -#elif defined(__GNUC__) && __FreeBSD__ && __i386__ +#elif (defined(__GNUC__) && __FreeBSD__ && __i386__) || _MSC_VER // GCC on FreeBSD/i386 incorrectly rounds long double constants to double precision. Workaround: -// Note that the [sizeof(long double)] takes care of whatever the 0 padding is for the +// Note that the [sizeof(longdouble)] takes care of whatever the 0 padding is for the // target platform -static unsigned char _negtab_bytes[][sizeof(long double)] = +static unsigned char _negtab_bytes[][sizeof(longdouble)] = { { 0xDE,0x9F,0xCE,0xD2,0xC8,0x04,0xDD,0xA6,0xD8,0x0A,0xBF,0xBF }, { 0xE4,0x2D,0x36,0x34,0x4F,0x53,0xAE,0xCE,0x6B,0x25,0xBF,0xBF }, { 0xBE,0xC0,0x57,0xDA,0xA5,0x82,0xA6,0xA2,0xB5,0x32,0xBF,0xBF }, @@ -68,7 +70,7 @@ static unsigned char _negtab_bytes[][sizeof(long double)] = { 0xCD,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFB,0x3F,0xBF,0xBF }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0xBF,0xBF } }; -static unsigned char _postab_bytes[][sizeof(long double)] = +static unsigned char _postab_bytes[][sizeof(longdouble)] = { { 0x9B,0x97,0x20,0x8A,0x02,0x52,0x60,0xC4,0x25,0x75,0x18,0x28 }, { 0xE5,0x5D,0x3D,0xC5,0x5D,0x3B,0x8B,0x9E,0x92,0x5A,0x18,0x28 }, { 0x17,0x0C,0x75,0x81,0x86,0x75,0x76,0xC9,0x48,0x4D,0x18,0x28 }, @@ -84,8 +86,8 @@ static unsigned char _postab_bytes[][sizeof(long double)] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x02,0x40,0x18,0x28 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0x18,0x28 } }; -static long double *negtab = (long double *) _negtab_bytes; -static long double *postab = (long double *) _postab_bytes; +static longdouble *negtab = (longdouble *) _negtab_bytes; +static longdouble *postab = (longdouble *) _postab_bytes; #else @@ -93,7 +95,7 @@ static long double *postab = (long double *) _postab_bytes; // The digits here past 17 are just for amusement value, they // only contribute to the 'sticky' bit. -static long double negtab[] = +static longdouble negtab[] = { 1 / 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 1 / 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, @@ -110,7 +112,7 @@ static long double negtab[] = 1 / 0xa.p+0L, }; -static long double postab[] = +static longdouble postab[] = { 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, @@ -134,9 +136,9 @@ static long double postab[] = * Terminates on first unrecognized character. */ -long double strtold(const char *p,char **endp) +longdouble strtold(const char *p,char **endp) { - long double ldval; + longdouble ldval; int exp; long long msdec,lsdec; unsigned long msscale; @@ -149,7 +151,7 @@ long double strtold(const char *p,char **endp) unsigned int old_cw; unsigned int old_status; -#if _WIN32 +#if _WIN32 && __DMC__ fenv_t flagp; fegetenv(&flagp); /* Store all exceptions, and current status word */ if (_8087) @@ -264,7 +266,7 @@ long double strtold(const char *p,char **endp) exp -= dot; i = *++p; } -#ifdef _WIN32 +#if _WIN32 && __DMC__ if (i == *__locale_decpoint && !dot) #else if (i == '.' && !dot) @@ -395,7 +397,7 @@ long double strtold(const char *p,char **endp) exp -= dot; i = *++p; } -#if _WIN32 +#if _WIN32 && __DMC__ if (i == *__locale_decpoint && !dot) #else if (i == '.' && !dot) @@ -435,7 +437,7 @@ long double strtold(const char *p,char **endp) goto Lerr; // return 0.0 } -#if _WIN32 +#if _WIN32 && __DMC__ __asm { fild qword ptr msdec @@ -460,7 +462,7 @@ long double strtold(const char *p,char **endp) u = 0; pow = 4096; -#if _WIN32 +#if _WIN32 && __DMC__ //printf("msdec = x%x, lsdec = x%x, msscale = x%x\n",msdec,lsdec,msscale); //printf("dval = %g, x%llx, exp = %d\n",dval,dval,exp); __asm fld tbyte ptr ldval @@ -470,7 +472,7 @@ long double strtold(const char *p,char **endp) { while (exp >= pow) { -#if _WIN32 +#if _WIN32 && __DMC__ __asm { mov EAX,u @@ -486,13 +488,13 @@ long double strtold(const char *p,char **endp) pow >>= 1; u++; } -#if _WIN32 +#if _WIN32 && __DMC__ __asm fstp tbyte ptr ldval #endif while (exp < 0) { while (exp <= -pow) { -#if _WIN32 +#if _WIN32 && __DMC__ __asm { mov EAX,u @@ -506,7 +508,7 @@ long double strtold(const char *p,char **endp) ldval *= negtab[u]; #endif if (ldval == 0) -#if _WIN32 +#if _WIN32 && __DMC__ __set_errno (ERANGE); #else errno = ERANGE; @@ -528,7 +530,7 @@ long double strtold(const char *p,char **endp) } L6: // if overflow occurred if (ldval == HUGE_VAL) -#if _WIN32 +#if _WIN32 && __DMC__ __set_errno (ERANGE); // range error #else errno = ERANGE; @@ -540,7 +542,7 @@ long double strtold(const char *p,char **endp) *endp = (char *) p; } L3: -#if _WIN32 +#if _WIN32 && __DMC__ fesetenv(&flagp); // reset floating point environment if (_8087) { @@ -563,7 +565,7 @@ long double strtold(const char *p,char **endp) #else -long double strtold(const char *p,char **endp) +longdouble strtold(const char *p,char **endp) { return strtod(p, endp); } @@ -578,7 +580,7 @@ long double strtold(const char *p,char **endp) #include #include -extern "C" long double strtold(const char *p,char **endp); +extern "C" longdouble strtold(const char *p,char **endp); struct longdouble { @@ -587,7 +589,7 @@ struct longdouble void main() { - long double ld; + longdouble ld; struct longdouble x; int i; @@ -674,7 +676,7 @@ void main() int i; int j; - static long double tab[] = + static longdouble tab[] = { 0x62.30290145104bcd64a60a9fc025254932bb0fd922271133eeae7be4a2f9151ffff868e970c234d8f51c5563f48bd2b496d868b27518ae42404964046f87cc1d213d5d0b54f74eb9281bb6c6e435fcb457200c03a5bca35f7792959da22e8d623b3e7b21e2b6100fab123cd8a1a75409f23956d4b941c759f83557de068edd2d00bcdd9d4a52ec8721ac7867f9e974996fb03d7ecd2fdc6349af06940d48741a6c2ed4684e5ab8d9c7bd7991dc03b4f63b8afd6b25ff66e42caeee333b7000a51987ec7038aec29e6ee8cac982a4ba47440496fcbe00d313d584e857fd214495bbdf373f41fd86fe49b70a5c7d2b17e0b2544f10cd4d8bfa89d0d73df29d0176cca7c234f4e6d2767113fd01c8c1a08a138c4ef80456c02d9a0ff4f1d4e3e51cb9255858325ed8d2399faddd9e9985a2df904ff6bf5c4f2ef0650ebc692c5508c2cbd6667097aced8e437b3d7fe03b2b6341a4c954108b89bc108f19ade5b533458e0dd75a53400d03119534074e89541bae9641fdd6266a3fdcbf778900fc509ba674343dd6769f3b72b882e7282566fbc6cc3f8d6b0dd9bc96119b31a96ddeff35e836b5d298f9994b8c90918e7b9a73491260806f233b7c94ab6feba2ebd6c1d9960e2d73a130d84c4a74fde9ce4724ed5bf546a03f40a8fb126ab1c32da38338eb3acc1a67778cfbe8b12acf1b23504dcd6cd995aca6a8b492ed8aa19adb95484971870239f4cea6e9cfda20c33857b32c450c3fecb534b71bd1a45b060904788f6e50fe78d6823613c8509ee3352c90ca19cfe90afb779eea37c8ab8db59a0a80627ce41d3cc425971d582dfe6d97ee63302b8e13e25feeaf19e63d326a7eb6d1c7bf2608c4cf1cc939c1307641d9b2c39497a8fcd8e0cd9e8d7c3172826ac9df13cb3d04e8d2fca26a9ff7d8b57e27ecf57bbb9373f46fee7aab86deb3f078787e2ab608b89572dac789bf627ede440b3f251f2b2322ab312bb95893d4b850be10e02d2408206e7bb8272181327ec8fa2e8a37a2d4390caea134c53c0adf9462ea75ecf9b5d0ed4d542dc19e1faf7a872e74f984d83e2dd8d92580152f18390a2b295138753d1fa8fd5d59c89f1b095edc162e2690f3cd8f62ff42923bbd87d1cde840b464a0e137d5e9a4eb8f8cde35c88baf63b71292baf1deeca19beb77fb8af6176ca776743074fa7021b97a1e0a68173c20ee69e79dadf7eb83cadbdfea5242a8329761ffe062053ccb5b92ac50b9c175a697b2b5341743c994a4503b9af26b398c6fed037d19eef4090ee8ae0725b1655fec303297cd0c2bd9cc1110c4e9968738b909454eb2a0dcfe388f15b8c898d3967a1b6dc3a5b4811a4f04f3618ac0280f4d3295a842bcfd82373a3f8ec72af2acd5071a8309cb2130504dd97d9556a1ebcad7947e0d0e30c7ae41eb659fb878f061814f6cea9c441c2d473bfe167b1a1c304e7613b22454ab9c41ff0b0905bc13176168dde6d488052f8cf8169c84cb4bf982870097012c23481161959127142e0e80cab3e6d7af6a25743dbeabcd0f237f1a016b67b2c2dfae78e341be10d6bfdf759b8ba1e81d1f4cce7c4823da7e1e7c34c0591cc245155e93b86ae5be806c0ed3f0da6146e599574efb29b172506be82913b1bb5154e05154ef084117f89a1e908efe7ae7d4724e8d2a67c001p+13600L, 0x9.e8b3b5dc53d5de4a74d28ce329ace526a3197bbebe3034f77154ce2bcba19648b21c11eb962b1b61b93cf2ee5ca6f7e928e61d08e2d694222771e50f30278c9836230af908b40a753b7d77cd8c6be7151aab4efac5dcd83e49d6907855eeb028af623f6f7024d2c36fa9ce9d04a487fa1fb992be221ef1bd0ad5f775677ce0de08402ad3fa140eac7d56c7c9dee0bedd8a6c038f9245b2e87c348ad803ecca8f0070f8dbb57a6a445f278b3d5cf42915e818415c7f3ef82df84658ccf45cfad379433f3389a4408f43c513ef5a83fb8886fbf56d9d4bd5f860792e55ecee70beb1810d76ce39de9ec24bcf99d01953761abd9d7389c0a244de3c195355d84eeebeee6f46eadb56c6815b785ce6b7b125ac8edb0708fd8f6cae5f5715f7915b33eb417bf03c19d7917c7ba1fc6b9681428c85744695f0e866d7efc9ac375d77c1a42f40660460944545ff87a7dc62d752f7a66a57b1ab730f203c1aa9f44484d80e2e5fc5a04779c56b8a9e110c7bcbea4ca7982da4663cfe491d0dbd21feab49869733554c36685e5510c4a656654419bd438e48ff35d6c7d6ab91bac974fb1264b4f111821fa2bca416afe609c313b41e449952fbed5a151440967abbb3a8281ed6a8f16f9210c17f94e3892ee98074ff01e3cb64f32dbb6643a7a8289c8c6c54de34c101349713b44938209ce1f3861ce0fb7fedcc235552eb57a7842d71c7fd8f66912e4ad2f869c29279498719342c12866ed6f1c850dabc98342c9e51b78db2ea50d142fd8277732ed56d55a5e5a191368b8abbb6067584ee87e354ec2e472149e28dcfb27d4d3fe30968651333e001p+6800L, diff --git a/backend/tassert.h b/backend/tassert.h index 3e9e8410..9d4360d9 100644 --- a/backend/tassert.h +++ b/backend/tassert.h @@ -23,7 +23,7 @@ #if __clang__ -void util_assert ( char * , int ) __attribute__((analyzer_noreturn)); +void util_assert(const char * , int) __attribute__((noreturn)); static void local_assert(int line) { @@ -36,7 +36,7 @@ static void local_assert(int line) #if _MSC_VER __declspec(noreturn) #endif -void util_assert ( char * , int ); +void util_assert(const char *, int); static void local_assert(int line) { diff --git a/backend/token.h b/backend/token.h index b00d0da2..b28eca7a 100644 --- a/backend/token.h +++ b/backend/token.h @@ -346,11 +346,11 @@ inline enum_TK stoken() { return toklist ? stokenx() : rtoken(1); } void token_init(void); void removext(void); -void __near comment(void); -void __near cppcomment(void); +void comment(void); +void cppcomment(void); char *combinestrings(targ_size_t *plen); char *combinestrings(targ_size_t *plen, tym_t *pty); -void __near inident(void); +void inident(void); void inidentX(char *p); unsigned comphash(const char *p); int insertSpace(unsigned char xclast, unsigned char xcnext); @@ -368,9 +368,9 @@ void token_term(void); /* from pragma.c */ //enum_TK ptoken(void); void pragma_process(); -int __near pragma_search(char *id); -macro_t * __near macfind(void); -void __near listident(void); +int pragma_search(char *id); +macro_t * macfind(void); +void listident(void); void pragma_term(void); macro_t *defmac(const char *name , const char *text); int pragma_defined(void); diff --git a/backend/type.c b/backend/type.c index 071ad7dc..896fb7cc 100644 --- a/backend/type.c +++ b/backend/type.c @@ -188,8 +188,8 @@ L1: if (t->Tflags & TFsizeunknown) goto err1; sz = t->Ttag->Sstruct->Salignsize; - if (sz > t->Ttag->Sstruct->Sstructalign) - sz = t->Ttag->Sstruct->Sstructalign; + if (sz > t->Ttag->Sstruct->Sstructalign + 1) + sz = t->Ttag->Sstruct->Sstructalign + 1; break; case TYldouble: @@ -239,7 +239,7 @@ type *type_alloc(tym_t ty) { type *t; static type tzero; -#if TARGET_SEGMENTED +#if !MARS assert(tybasic(ty) != TYtemplate); #endif if (type_list) @@ -336,7 +336,7 @@ type *type_allocn(tym_t ty,type *tn) * Allocate a TYmemptr type. */ -#if !MARS +#if SCPP type *type_allocmemptr(Classsym *stag,type *tn) { type *t; @@ -415,7 +415,7 @@ type_count_free() * Initialize type package. */ -STATIC type * __near type_allocbasic(tym_t ty) +STATIC type * type_allocbasic(tym_t ty) { type *t; t = type_alloc(ty); @@ -1139,9 +1139,6 @@ param_t *param_calloc() static param_t pzero; param_t *p; -#if !TX86 - debug_assert(PARSER); -#endif if (param_list) { p = param_list; diff --git a/backend/type.h b/backend/type.h index 8f92566d..c42044a0 100644 --- a/backend/type.h +++ b/backend/type.h @@ -187,7 +187,9 @@ targ_size_t type_paramsize(type *t); type *type_alloc(tym_t); type *type_alloc_template(symbol *s); type *type_allocn(tym_t,type *tn); +#if SCPP type *type_allocmemptr(Classsym *stag,type *tn); +#endif type *type_fake(tym_t); type *type_setty(type **,long); type *type_settype(type **pt, type *t); diff --git a/builtin.c b/builtin.c index 4cfee71f..0c8a780a 100644 --- a/builtin.c +++ b/builtin.c @@ -12,15 +12,6 @@ #include #include -#if __FreeBSD__ -extern "C" -{ - long double sinl(long double); - long double cosl(long double); - long double tanl(long double); - long double sqrtl(long double); -} -#endif #include "mars.h" #include "declaration.h" @@ -33,6 +24,16 @@ extern "C" #include "id.h" #include "module.h" +#if __FreeBSD__ +extern "C" +{ + longdouble sinl(longdouble); + longdouble cosl(longdouble); + longdouble tanl(longdouble); + longdouble sqrtl(longdouble); +} +#endif + #if DMDV2 /********************************** diff --git a/cast.c b/cast.c index 74c67f92..aab06e63 100644 --- a/cast.c +++ b/cast.c @@ -17,6 +17,7 @@ #include "utf.h" #include "declaration.h" #include "aggregate.h" +#include "template.h" #include "scope.h" //#define DUMP .dump(__PRETTY_FUNCTION__, this) @@ -107,6 +108,9 @@ fflush(stdout); else if (t->reliesOnTident()) error("forward reference to type %s", t->reliesOnTident()->toChars()); +//printf("type %p ty %d deco %p\n", type, type->ty, type->deco); +//type = type->semantic(loc, sc); +//printf("type %s t %s\n", type->deco, t->deco); error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type->toChars(), t->toChars()); } @@ -131,6 +135,12 @@ Expression *ErrorExp::implicitCastTo(Scope *sc, Type *t) return this; } +Expression *FuncExp::implicitCastTo(Scope *sc, Type *t) +{ + //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + return inferType(t); +} + /******************************************* * Return !=0 if we can implicitly convert this to type t. * Don't do the actual cast. @@ -352,16 +362,16 @@ MATCH IntegerExp::implicitConvTo(Type *t) case Tfloat80: { - volatile long double f; + volatile_longdouble f; if (type->isunsigned()) { - f = (long double)value; - if (f != value) + f = ldouble(value); + if (f != value) // isn't this a noop, because the compiler prefers ld goto Lno; } else { - f = (long double)(long long)value; + f = ldouble((long long)value); if (f != (long long)value) goto Lno; } @@ -490,14 +500,17 @@ MATCH StringExp::implicitConvTo(Type *t) return MATCHnomatch; m = MATCHconst; } - switch (tn->ty) + if (!committed) { - case Tchar: - case Twchar: - case Tdchar: - if (!committed) - return m; - break; + switch (tn->ty) + { + case Tchar: + return (postfix != 'w' && postfix != 'd' ? m : MATCHconvert); + case Twchar: + return (postfix == 'w' ? m : MATCHconvert); + case Tdchar: + return (postfix == 'd' ? m : MATCHconvert); + } } break; } @@ -719,12 +732,24 @@ MATCH DelegateExp::implicitConvTo(Type *t) MATCH FuncExp::implicitConvTo(Type *t) { - //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); - if (type && type != Type::tvoid && tok == TOKreserved && type->ty == Tpointer - && (t->ty == Tpointer || t->ty == Tdelegate)) - { // Allow implicit function to delegate conversion - if (type->nextOf()->covariant(t->nextOf()) == 1) - return t->ty == Tpointer ? MATCHconst : MATCHconvert; + //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", type, type ? type->toChars() : NULL, t->toChars()); + Expression *e = inferType(t, 1); + if (e) + { + if (e != this) + return e->implicitConvTo(t); + + /* MATCHconst: Conversion from implicit to explicit function pointer + * MATCHconvert: Conversion from impliict funciton pointer to delegate + */ + if (tok == TOKreserved && type->ty == Tpointer && + (t->ty == Tpointer || t->ty == Tdelegate)) + { + if (type == t) + return MATCHexact; + if (type->nextOf()->covariant(t->nextOf()) == 1) + return t->ty == Tpointer ? MATCHconst : MATCHconvert; + } } return Expression::implicitConvTo(t); } @@ -845,7 +870,7 @@ Expression *Expression::castTo(Scope *sc, Type *t) { /* Forward the cast to our alias this member, rewrite to: * cast(to)e1.aliasthis */ - Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident); + Expression *e1 = resolveAliasThis(sc, this); Expression *e2 = new CastExp(loc, e1, tb); e2 = e2->semantic(sc); return e2; @@ -866,7 +891,7 @@ Expression *Expression::castTo(Scope *sc, Type *t) /* Forward the cast to our alias this member, rewrite to: * cast(to)e1.aliasthis */ - Expression *e1 = new DotIdExp(loc, this, ts->sym->aliasthis->ident); + Expression *e1 = resolveAliasThis(sc, this); Expression *e2 = new CastExp(loc, e1, tb); e2 = e2->semantic(sc); return e2; @@ -1450,7 +1475,7 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *e = this; Type *tb = t->toBasetype(); Type *typeb = type->toBasetype(); - if (tb != typeb) + if (tb != typeb || hasOverloads) { // Look for delegates to functions where the functions are overloaded. FuncDeclaration *f; @@ -1491,15 +1516,11 @@ Expression *DelegateExp::castTo(Scope *sc, Type *t) Expression *FuncExp::castTo(Scope *sc, Type *t) { //printf("FuncExp::castTo type = %s, t = %s\n", type->toChars(), t->toChars()); - if (tok == TOKreserved) - { assert(type && type != Type::tvoid); - if (type->ty == Tpointer && t->ty == Tdelegate) - { - Expression *e = copy(); - e->type = new TypeDelegate(fd->type); - e->type = e->type->semantic(loc, sc); - return e; - } + Expression *e = inferType(t, 1); + if (e) + { if (e != this) + e = e->castTo(sc, t); + return e; } return Expression::castTo(sc, t); } @@ -1537,6 +1558,180 @@ Expression *CommaExp::castTo(Scope *sc, Type *t) return e; } +/* ==================== inferType ====================== */ + +/**************************************** + * Set type inference target + * flag 1: don't put an error when inference fails + */ + +Expression *Expression::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + return this; +} + +Expression *ArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + if (t->ty == Tarray || t->ty == Tsarray) + { + Type *tn = t->nextOf(); + for (size_t i = 0; i < elements->dim; i++) + { Expression *e = (*elements)[i]; + if (e) + { e = e->inferType(tn, flag, tparams); + (*elements)[i] = e; + } + } + } + } + return this; +} + +Expression *AssocArrayLiteralExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + if (t->ty == Taarray) + { TypeAArray *taa = (TypeAArray *)t; + Type *ti = taa->index; + Type *tv = taa->nextOf(); + for (size_t i = 0; i < keys->dim; i++) + { Expression *e = (*keys)[i]; + if (e) + { e = e->inferType(ti, flag, tparams); + (*keys)[i] = e; + } + } + for (size_t i = 0; i < values->dim; i++) + { Expression *e = (*values)[i]; + if (e) + { e = e->inferType(tv, flag, tparams); + (*values)[i] = e; + } + } + } + } + return this; +} + +Expression *FuncExp::inferType(Type *to, int flag, TemplateParameters *tparams) +{ + if (!to) + return this; + + //printf("FuncExp::interType('%s'), to=%s\n", type?type->toChars():"null", to->toChars()); + + if (!type) // semantic is not yet done + { + if (to->ty == Tdelegate || + to->ty == Tpointer && to->nextOf()->ty == Tfunction) + { treq = to; + } + return this; + } + + Expression *e = NULL; + + Type *t = to; + if (t->ty == Tdelegate) + { if (tok == TOKfunction) + goto L1; + t = t->nextOf(); + } + else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction) + { if (tok == TOKdelegate) + goto L1; + t = t->nextOf(); + } + + if (td) + { /// Parameter types inference from + assert(td->scope); + if (t->ty == Tfunction) + { + TypeFunction *tfv = (TypeFunction *)t; + TypeFunction *tfl = (TypeFunction *)fd->type; + size_t dim = Parameter::dim(tfl->parameters); + + if (Parameter::dim(tfv->parameters) == dim && + tfv->varargs == tfl->varargs) + { + Objects *tiargs = new Objects(); + tiargs->reserve(td->parameters->dim); + + for (size_t i = 0; i < td->parameters->dim; i++) + { + TemplateParameter *tp = (*td->parameters)[i]; + for (size_t u = 0; u < dim; u++) + { Parameter *p = Parameter::getNth(tfl->parameters, u); + if (p->type->ty == Tident && + ((TypeIdentifier *)p->type)->ident == tp->ident) + { p = Parameter::getNth(tfv->parameters, u); + Type *tprm = p->type; + if (tprm->reliesOnTident(tparams)) + goto L1; + tprm = tprm->semantic(loc, td->scope); + tiargs->push(tprm); + u = dim; // break inner loop + } + } + } + + TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); + e = (new ScopeExp(loc, ti))->semantic(td->scope); + if (e->op == TOKfunction) + { FuncExp *fe = (FuncExp *)e; + assert(fe->td == NULL); + e = fe->inferType(to, flag); + } + } + } + } + else if (type) + { + assert(type != Type::tvoid); // semantic is already done + + // Allow conversion from implicit function pointer to delegate + if (tok == TOKreserved && type->ty == Tpointer && + to->ty == Tdelegate) + { + Type *typen = type->nextOf(); + assert(typen->deco); + //if (typen->covariant(to->nextOf()) == 1) + { + FuncExp *fe = (FuncExp *)copy(); + fe->tok = TOKdelegate; + fe->type = (new TypeDelegate(typen))->merge(); + e = fe; + //e = fe->Expression::implicitCastTo(sc, to); + } + } + else + e = this; + } +L1: + if (!flag && !e) + { error("cannot infer function literal type from %s", to->toChars()); + e = new ErrorExp(); + } + return e; +} + +Expression *CondExp::inferType(Type *t, int flag, TemplateParameters *tparams) +{ + if (t) + { + t = t->toBasetype(); + e1 = e1->inferType(t, flag, tparams); + e2 = e2->inferType(t, flag, tparams); + } + return this; +} + /* ==================== ====================== */ /**************************************** @@ -1655,6 +1850,7 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression #endif assert(t2); +Lagain: Type *t1b = t1->toBasetype(); Type *t2b = t2->toBasetype(); @@ -1694,7 +1890,6 @@ int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression t1 = t1b; t2 = t2b; -Lagain: if (t1 == t2) { } @@ -1940,17 +2135,13 @@ Lcc: } else if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident); - e1 = e1->semantic(sc); - e1 = resolveProperties(sc, e1); + e1 = resolveAliasThis(sc, e1); t1 = e1->type; continue; } else if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { - e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident); - e2 = e2->semantic(sc); - e2 = resolveProperties(sc, e2); + e2 = resolveAliasThis(sc, e2); t2 = e2->type; continue; } @@ -1985,16 +2176,12 @@ Lcc: Expression *e2b = NULL; if (ts2->sym->aliasthis) { - e2b = new DotIdExp(e2->loc, e2, ts2->sym->aliasthis->ident); - e2b = e2b->semantic(sc); - e2b = resolveProperties(sc, e2b); + e2b = resolveAliasThis(sc, e2); i1 = e2b->implicitConvTo(t1); } if (ts1->sym->aliasthis) { - e1b = new DotIdExp(e1->loc, e1, ts1->sym->aliasthis->ident); - e1b = e1b->semantic(sc); - e1b = resolveProperties(sc, e1b); + e1b = resolveAliasThis(sc, e1); i2 = e1b->implicitConvTo(t2); } if (i1 && i2) @@ -2021,18 +2208,14 @@ Lcc: { if (t1->ty == Tstruct && ((TypeStruct *)t1)->sym->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ((TypeStruct *)t1)->sym->aliasthis->ident); - e1 = e1->semantic(sc); - e1 = resolveProperties(sc, e1); + e1 = resolveAliasThis(sc, e1); t1 = e1->type; t = t1; goto Lagain; } if (t2->ty == Tstruct && ((TypeStruct *)t2)->sym->aliasthis) { - e2 = new DotIdExp(e2->loc, e2, ((TypeStruct *)t2)->sym->aliasthis->ident); - e2 = e2->semantic(sc); - e2 = resolveProperties(sc, e2); + e2 = resolveAliasThis(sc, e2); t2 = e2->type; t = t2; goto Lagain; diff --git a/class.c b/class.c index 4121946d..857ef2bd 100644 --- a/class.c +++ b/class.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -273,7 +273,7 @@ void ClassDeclaration::semantic(Scope *sc) return; } if (symtab) - { if (sizeok == 1 || !scope) + { if (sizeok == SIZEOKdone || !scope) { //printf("\tsemantic for '%s' is already completed\n", toChars()); return; // semantic() already completed } @@ -333,7 +333,8 @@ void ClassDeclaration::semantic(Scope *sc) //b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty != Tclass) - { error("base type must be class or interface, not %s", b->type->toChars()); + { if (b->type != Type::terror) + error("base type must be class or interface, not %s", b->type->toChars()); baseclasses->remove(0); } else @@ -364,12 +365,12 @@ void ClassDeclaration::semantic(Scope *sc) goto L7; } } - if (!tc->sym->symtab || tc->sym->sizeok == 0) + if (!tc->sym->symtab || tc->sym->sizeok == SIZEOKnone) { // Try to resolve forward reference if (/*sc->mustsemantic &&*/ tc->sym->scope) tc->sym->semantic(NULL); } - if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) + if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == SIZEOKnone) { //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars()); //error("forward reference of base class %s", baseClass->toChars()); @@ -406,8 +407,8 @@ void ClassDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); + { if (b->type != Type::terror) + error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } @@ -512,13 +513,13 @@ void ClassDeclaration::semantic(Scope *sc) protection = sc->protection; storage_class |= sc->stc; - if (sizeok == 0) + if (sizeok == SIZEOKnone) { interfaceSemantic(sc); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } @@ -589,13 +590,6 @@ void ClassDeclaration::semantic(Scope *sc) if (storage_class & STCabstract) isabstract = 1; - if (storage_class & STCimmutable) - type = type->addMod(MODimmutable); - if (storage_class & STCconst) - type = type->addMod(MODconst); - if (storage_class & STCshared) - type = type->addMod(MODshared); - sc = sc->push(this); //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared); //sc->stc |= storage_class & STC_TYPECTOR; @@ -631,17 +625,20 @@ void ClassDeclaration::semantic(Scope *sc) structsize = sc->offset; Scope scsave = *sc; size_t members_dim = members->dim; - sizeok = 0; + sizeok = SIZEOKnone; /* Set scope so if there are forward references, we still might be able to * resolve individual members like enums. */ for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ - if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) + if (s->isEnumDeclaration() || + (s->isAggregateDeclaration() && s->ident) || + s->isTemplateMixin() || + s->isAliasDeclaration()) { //printf("setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc); @@ -649,19 +646,35 @@ void ClassDeclaration::semantic(Scope *sc) } for (size_t i = 0; i < members_dim; i++) - { Dsymbol *s = members->tdata()[i]; + { Dsymbol *s = (*members)[i]; s->semantic(sc); } + // Set the offsets of the fields and determine the size of the class + + unsigned offset = structsize; + bool isunion = isUnionDeclaration() != NULL; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(this, &offset, false); + } + sc->offset = structsize; + if (global.gag && global.gaggedErrors != errors) { // The type is no good, yet the error messages were gagged. type = Type::terror; } - if (sizeok == 2) // failed due to forward references + if (sizeok == SIZEOKfwd) // failed due to forward references { // semantic() failed due to forward references // Unwind what we did, and defer it for later + for (size_t i = 0; i < fields.dim; i++) + { Dsymbol *s = fields[i]; + VarDeclaration *vd = s->isVarDeclaration(); + if (vd) + vd->offset = 0; + } fields.setDim(0); structsize = 0; alignsize = 0; @@ -681,15 +694,19 @@ void ClassDeclaration::semantic(Scope *sc) //printf("\tsemantic('%s') successful\n", toChars()); - structsize = sc->offset; //members->print(); /* Look for special member functions. * They must be in this class, not in a base class. */ - ctor = (CtorDeclaration *)search(0, Id::ctor, 0); + ctor = search(0, Id::ctor, 0); +#if DMDV1 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) ctor = NULL; +#else + if (ctor && (ctor->toParent() != this || !(ctor->isCtorDeclaration() || ctor->isTemplateDeclaration()))) + ctor = NULL; // search() looks through ancestor classes +#endif // dtor = (DtorDeclaration *)search(Id::dtor, 0); // if (dtor && dtor->toParent() != this) @@ -715,7 +732,6 @@ void ClassDeclaration::semantic(Scope *sc) members->push(ctor); ctor->addMember(sc, this, 1); *sc = scsave; // why? What about sc->nofree? - sc->offset = structsize; ctor->semantic(sc); this->ctor = ctor; defaultCtor = ctor; @@ -731,9 +747,10 @@ void ClassDeclaration::semantic(Scope *sc) #endif // Allocate instance of each new interface + sc->offset = structsize; for (size_t i = 0; i < vtblInterfaces->dim; i++) { - BaseClass *b = vtblInterfaces->tdata()[i]; + BaseClass *b = (*vtblInterfaces)[i]; unsigned thissize = PTRSIZE; alignmember(structalign, thissize, &sc->offset); @@ -752,7 +769,7 @@ void ClassDeclaration::semantic(Scope *sc) alignsize = thissize; } structsize = sc->offset; - sizeok = 1; + sizeok = SIZEOKdone; Module::dprogress++; dtor = buildDtor(sc); @@ -898,7 +915,12 @@ Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) if (scope && !symtab) { Scope *sc = scope; sc->mustsemantic++; + // If speculatively gagged, ungag now. + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging()) + global.gag = 0; semantic(sc); + global.gag = oldgag; sc->mustsemantic--; } @@ -1017,7 +1039,7 @@ FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) { for (size_t i = 0; i < vtbl->dim; i++) { - FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration(); + FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration(); if (!fd) continue; // the first entry might be a ClassInfo @@ -1236,7 +1258,7 @@ void InterfaceDeclaration::semantic(Scope *sc) // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) - { BaseClass *b = baseclasses->tdata()[0]; + { BaseClass *b = (*baseclasses)[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); @@ -1272,8 +1294,8 @@ void InterfaceDeclaration::semantic(Scope *sc) else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) - { - error("base type must be interface, not %s", b->type->toChars()); + { if (b->type != Type::terror) + error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } @@ -1330,7 +1352,7 @@ void InterfaceDeclaration::semantic(Scope *sc) { BaseClass *b = interfaces[i]; // Skip if b has already appeared - for (int k = 0; k < i; k++) + for (size_t k = 0; k < i; k++) { if (b == interfaces[k]) goto Lcontinue; @@ -1338,11 +1360,11 @@ void InterfaceDeclaration::semantic(Scope *sc) // Copy vtbl[] from base class if (b->base->vtblOffset()) - { int d = b->base->vtbl.dim; + { size_t d = b->base->vtbl.dim; if (d > 1) { vtbl.reserve(d - 1); - for (int j = 1; j < d; j++) + for (size_t j = 1; j < d; j++) vtbl.push(b->base->vtbl.tdata()[j]); } } @@ -1360,7 +1382,7 @@ void InterfaceDeclaration::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } @@ -1376,6 +1398,7 @@ void InterfaceDeclaration::semantic(Scope *sc) sc->explicitProtection = 0; structalign = sc->structalign; sc->offset = PTRSIZE * 2; + structsize = sc->offset; inuse++; /* Set scope so if there are forward references, we still might be able to diff --git a/clone.c b/clone.c index 2664f864..d0b22c40 100644 --- a/clone.c +++ b/clone.c @@ -204,6 +204,11 @@ int StructDeclaration::needOpEquals() if (hasIdentityEquals) goto Lneed; +#if 0 + if (isUnionDeclaration()) + goto Ldontneed; +#endif + /* If any of the fields has an opEquals, then we * need it too. */ @@ -215,6 +220,14 @@ int StructDeclaration::needOpEquals() if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); +#if 0 + if (tv->isfloating()) + goto Lneed; + if (tv->ty == Tarray) + goto Lneed; + if (tv->ty == Tclass) + goto Lneed; +#endif while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; tv = tv->nextOf()->toBasetype(); @@ -226,6 +239,7 @@ int StructDeclaration::needOpEquals() goto Lneed; } } +Ldontneed: if (X) printf("\tdontneed\n"); return 0; diff --git a/complex_t.h b/complex_t.h index a1b4f4ed..fa39271e 100644 --- a/complex_t.h +++ b/complex_t.h @@ -16,12 +16,14 @@ struct complex_t { - long double re; - long double im; + longdouble re; + longdouble im; complex_t() { this->re = 0; this->im = 0; } - complex_t(long double re) { this->re = re; this->im = 0; } - complex_t(long double re, long double im) { this->re = re; this->im = im; } + complex_t(longdouble re) { this->re = re; this->im = 0; } + complex_t(double re) { this->re = re; this->im = 0; } + complex_t(longdouble re, longdouble im) { this->re = re; this->im = im; } + complex_t(double re, double im) { this->re = re; this->im = im; } complex_t operator + (complex_t y) { complex_t r; r.re = re + y.re; r.im = im + y.im; return r; } complex_t operator - (complex_t y) { complex_t r; r.re = re - y.re; r.im = im - y.im; return r; } @@ -30,9 +32,9 @@ struct complex_t complex_t operator / (complex_t y) { - long double abs_y_re = y.re < 0 ? -y.re : y.re; - long double abs_y_im = y.im < 0 ? -y.im : y.im; - long double r, den; + longdouble abs_y_re = y.re < 0 ? -y.re : y.re; + longdouble abs_y_im = y.im < 0 ? -y.im : y.im; + longdouble r, den; if (abs_y_re < abs_y_im) { @@ -56,17 +58,17 @@ struct complex_t int operator != (complex_t y) { return re != y.re || im != y.im; } }; -inline complex_t operator * (long double x, complex_t y) { return complex_t(x) * y; } -inline complex_t operator * (complex_t x, long double y) { return x * complex_t(y); } -inline complex_t operator / (complex_t x, long double y) { return x / complex_t(y); } +inline complex_t operator * (longdouble x, complex_t y) { return complex_t(x) * y; } +inline complex_t operator * (complex_t x, longdouble y) { return x * complex_t(y); } +inline complex_t operator / (complex_t x, longdouble y) { return x / complex_t(y); } -inline long double creall(complex_t x) +inline longdouble creall(complex_t x) { return x.re; } -inline long double cimagl(complex_t x) +inline longdouble cimagl(complex_t x) { return x.im; } diff --git a/constfold.c b/constfold.c index acb65b75..9824a989 100644 --- a/constfold.c +++ b/constfold.c @@ -577,12 +577,12 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) if (e1->type->isfloating()) { r = new RealExp(loc, e1->toReal(), e1->type); - v = new RealExp(loc, 1.0, e1->type); + v = new RealExp(loc, ldouble(1.0), e1->type); } else { r = new RealExp(loc, e1->toReal(), Type::tfloat64); - v = new RealExp(loc, 1.0, Type::tfloat64); + v = new RealExp(loc, ldouble(1.0), Type::tfloat64); } while (n != 0) @@ -594,7 +594,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) } if (neg) - v = Div(v->type, new RealExp(loc, 1.0, v->type), v); + v = Div(v->type, new RealExp(loc, ldouble(1.0), v->type), v); if (type->isintegral()) e = new IntegerExp(loc, v->toInteger(), type); @@ -606,7 +606,7 @@ Expression *Pow(Type *type, Expression *e1, Expression *e2) // x ^^ y for x < 0 and y not an integer is not defined if (e1->toReal() < 0.0) { - e = new RealExp(loc, Port::nan, type); + e = new RealExp(loc, ldouble(Port::nan), type); } else if (e2->toReal() == 0.5) { @@ -1346,7 +1346,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) if (i >= es1->len) { - e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len); + e1->error("string index %llu is out of bounds [0 .. %llu]", i, (ulonglong)es1->len); e = new ErrorExp(); } else @@ -1361,7 +1361,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) if (i >= length) { - e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length); + e1->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length); e = new ErrorExp(); } else if (e1->op == TOKarrayliteral) @@ -1380,7 +1380,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2) { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; if (i >= ale->elements->dim) { - e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); + e1->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); e = new ErrorExp(); } else @@ -1436,7 +1436,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) if (iupr > es1->len || ilwr > iupr) { - e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); + e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr); e = new ErrorExp(); } else @@ -1466,7 +1466,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) if (iupr > es1->elements->dim || ilwr > iupr) { - e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); + e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr); e = new ErrorExp(); } else diff --git a/cppmangle.c b/cppmangle.c index 630567ef..915bb23c 100644 --- a/cppmangle.c +++ b/cppmangle.c @@ -277,7 +277,7 @@ void TypeVector::toCppMangle(OutBuffer *buf, CppMangleState *cms) void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms) { if (!cms->substitute(buf, this)) - { buf->printf("A%ju_", dim ? dim->toInteger() : 0); + { buf->printf("A%llu_", dim ? dim->toInteger() : 0); next->toCppMangle(buf, cms); } } diff --git a/declaration.c b/declaration.c index 3fc3df01..bcb063be 100644 --- a/declaration.c +++ b/declaration.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -490,7 +490,8 @@ void AliasDeclaration::semantic(Scope *sc) if (s) goto L2; - error("cannot alias an expression %s", e->toChars()); + if (e->op != TOKerror) + error("cannot alias an expression %s", e->toChars()); t = e->type; } else if (t) @@ -502,7 +503,7 @@ void AliasDeclaration::semantic(Scope *sc) ScopeDsymbol::multiplyDefined(0, this, overnext); this->inSemantic = 0; - if (errors != global.errors) + if (global.gag && errors != global.errors) type = savedtype; return; @@ -538,7 +539,7 @@ void AliasDeclaration::semantic(Scope *sc) assert(global.errors); s = NULL; } - if (errors != global.errors) + if (global.gag && errors != global.errors) { type = savedtype; overnext = savedovernext; @@ -669,6 +670,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer #if DMDV1 nestedref = 0; #endif + alignment = 0; ctorinit = 0; aliassym = NULL; onstack = 0; @@ -976,7 +978,7 @@ Lnomatch: { Parameter *arg = Parameter::getNth(tt->arguments, i); OutBuffer buf; - buf.printf("_%s_field_%zu", ident->toChars(), i); + buf.printf("_%s_field_%llu", ident->toChars(), (ulonglong)i); buf.writeByte(0); const char *name = (const char *)buf.extractData(); Identifier *id = Lexer::idPool(name); @@ -1051,9 +1053,7 @@ Lnomatch: } else { - AggregateDeclaration *aad = sc->anonAgg; - if (!aad) - aad = parent->isAggregateDeclaration(); + AggregateDeclaration *aad = parent->isAggregateDeclaration(); if (aad) { #if DMDV2 @@ -1065,15 +1065,16 @@ Lnomatch: storage_class |= STCstatic; } else +#endif { - aad->addField(sc, this); + storage_class |= STCfield; + alignment = sc->structalign; +#if DMDV2 if (tb->ty == Tstruct && ((TypeStruct *)tb)->sym->noDefaultCtor || tb->ty == Tclass && ((TypeClass *)tb)->sym->noDefaultCtor) aad->noDefaultCtor = TRUE; - } -#else - aad->addField(sc, this); #endif + } } InterfaceDeclaration *id = parent->isInterfaceDeclaration(); @@ -1126,7 +1127,7 @@ Lnomatch: { if (func->fes) func = func->fes->func; - if (!func->type->hasWild()) + if (!((TypeFunction *)func->type)->iswild) { error("inout variables can only be declared inside inout functions"); } @@ -1232,9 +1233,6 @@ Lnomatch: StructInitializer *si = init->isStructInitializer(); ExpInitializer *ei = init->isExpInitializer(); - if (ei && ei->exp->op == TOKfunction && !inferred) - ((FuncExp *)ei->exp)->setType(type); - if (ei && isScope()) { // See if initializer is a NewExp that can be allocated on the stack @@ -1283,6 +1281,8 @@ Lnomatch: Expression *e1 = new VarExp(loc, this); Type *t = type->toBasetype(); + if (ei && !inferred) + ei->exp = ei->exp->inferType(t); Linit2: if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) @@ -1558,6 +1558,31 @@ Ldtor: void VarDeclaration::semantic2(Scope *sc) { //printf("VarDeclaration::semantic2('%s')\n", toChars()); + // Inside unions, default to void initializers + if (!init && sc->inunion && !toParent()->isFuncDeclaration()) + { + AggregateDeclaration *aad = parent->isAggregateDeclaration(); + if (aad) + { + if (aad->fields[0] == this) + { + int hasinit = 0; + for (size_t i = 1; i < aad->fields.dim; i++) + { + if (aad->fields[i]->init && + !aad->fields[i]->init->isVoidInitializer()) + { + hasinit = 1; + break; + } + } + if (!hasinit) + init = new ExpInitializer(loc, type->defaultInitLiteral(loc)); + } + else + init = new VoidInitializer(loc); + } + } if (init && !toParent()->isFuncDeclaration()) { inuse++; #if 0 @@ -1574,6 +1599,82 @@ void VarDeclaration::semantic2(Scope *sc) sem = Semantic2Done; } +void VarDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad->toChars(), toChars()); + + if (aliassym) + { // If this variable was really a tuple, set the offsets for the tuple fields + TupleDeclaration *v2 = aliassym->isTupleDeclaration(); + assert(v2); + for (size_t i = 0; i < v2->objects->dim; i++) + { Object *o = (*v2->objects)[i]; + assert(o->dyncast() == DYNCAST_EXPRESSION); + Expression *e = (Expression *)o; + assert(e->op == TOKdsymbol); + DsymbolExp *se = (DsymbolExp *)e; + se->s->setFieldOffset(ad, poffset, isunion); + } + return; + } + + if (!(storage_class & STCfield)) + return; + assert(!(storage_class & (STCstatic | STCextern | STCparameter | STCtls))); + + /* Fields that are tuples appear both as part of TupleDeclarations and + * as members. That means ignore them if they are already a field. + */ + if (offset) + return; // already a field + for (size_t i = 0; i < ad->fields.dim; i++) + { + if (ad->fields[i] == this) + return; // already a field + } + + // Check for forward referenced types which will fail the size() call + Type *t = type->toBasetype(); + if (storage_class & STCref) + { // References are the size of a pointer + t = Type::tvoidptr; + } + if (t->ty == Tstruct) + { TypeStruct *ts = (TypeStruct *)t; +#if DMDV2 + if (ts->sym == ad) + { + ad->error("cannot have field %s with same struct type", toChars()); + } +#endif + + if (ts->sym->sizeok != SIZEOKdone && ts->sym->scope) + ts->sym->semantic(NULL); + if (ts->sym->sizeok != SIZEOKdone) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced + return; + } + } + if (t->ty == Tident) + { + ad->sizeok = SIZEOKfwd; // cannot finish; flag as forward referenced + return; + } + + unsigned memsize = t->size(loc); // size of member + unsigned memalignsize = t->alignsize(); // size of member for alignment purposes + unsigned memalign = t->memalign(alignment); // alignment boundaries + + offset = AggregateDeclaration::placeField(poffset, memsize, memalignsize, memalign, + &ad->structsize, &ad->alignsize, isunion); + + //printf("\t%s: alignsize = %d\n", toChars(), alignsize); + + //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad->toChars(), offset, memsize); + ad->fields.push(this); +} + const char *VarDeclaration::kind() { return "variable"; diff --git a/declaration.h b/declaration.h index deab930e..61a703de 100644 --- a/declaration.h +++ b/declaration.h @@ -119,6 +119,10 @@ struct Declaration : Dsymbol enum LINK linkage; int inuse; // used to detect cycles +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif + enum Semantic sem; Declaration(Identifier *id); @@ -246,6 +250,7 @@ struct VarDeclaration : Declaration #else int nestedref; // referenced by a lexically nested function #endif + unsigned short alignment; 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 @@ -272,6 +277,7 @@ struct VarDeclaration : Declaration VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); void semantic2(Scope *sc); const char *kind(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); @@ -523,6 +529,9 @@ enum BUILTIN BUILTINbsr, // core.bitop.bsr BUILTINbsf, // core.bitop.bsf BUILTINbswap, // core.bitop.bswap +#if IN_GCC + BUILTINgcc, // GCC builtin +#endif }; Expression *eval_builtin(Loc loc, enum BUILTIN builtin, Expressions *arguments); @@ -596,6 +605,7 @@ struct FuncDeclaration : Declaration VarDeclarations closureVars; // local variables in this function // which are referenced by nested // functions + FuncDeclarations deferred; // toObjFile() these functions after this one unsigned flags; #define FUNCFLAGpurityInprocess 1 // working on determining purity @@ -640,10 +650,12 @@ struct FuncDeclaration : Declaration int isAbstract(); int isCodeseg(); int isOverloadable(); + int hasOverloads(); enum PURE isPure(); enum PURE isPureBypassingInference(); bool setImpure(); int isSafe(); + bool isSafeBypassingInference(); int isTrusted(); bool setUnsafe(); virtual int isNested(); @@ -677,6 +689,8 @@ struct FuncDeclaration : Declaration void buildClosure(IRState *irs); FuncDeclaration *isFuncDeclaration() { return this; } + + virtual FuncDeclaration *toAliasFunc() { return this; } }; #if DMDV2 @@ -690,12 +704,16 @@ FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s, struct FuncAliasDeclaration : FuncDeclaration { FuncDeclaration *funcalias; + int hasOverloads; - FuncAliasDeclaration(FuncDeclaration *funcalias); + FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads = 1); FuncAliasDeclaration *isFuncAliasDeclaration() { return this; } const char *kind(); Symbol *toSymbol(); + char *mangle() { return toAliasFunc()->mangle(); } + + FuncDeclaration *toAliasFunc(); }; struct FuncLiteralDeclaration : FuncDeclaration diff --git a/delegatize.c b/delegatize.c index a4d37152..b08892f1 100644 --- a/delegatize.c +++ b/delegatize.c @@ -34,7 +34,10 @@ int lambdaCheckForNestedRef(Expression *e, void *param); Expression *Expression::toDelegate(Scope *sc, Type *t) { //printf("Expression::toDelegate(t = %s) %s\n", t->toChars(), toChars()); - TypeFunction *tf = new TypeFunction(NULL, t, 0, LINKd); + Type *tw = t->semantic(loc, sc); + Type *tc = t->substWildTo(MODconst)->semantic(loc, sc); + TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd); + (tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757 FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL); Expression *e; diff --git a/dmd_msc.vcproj b/dmd_msc.vcproj new file mode 100644 index 00000000..94a9e4f9 --- /dev/null +++ b/dmd_msc.vcproj @@ -0,0 +1,2088 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc.c b/doc.c index 51c9d9c0..4d8f104d 100644 --- a/doc.c +++ b/doc.c @@ -261,6 +261,9 @@ void Module::gendocfile() Macro::define(¯otable, (unsigned char *)"YEAR", 4, (unsigned char *)p + 20, 4); } + char *srcfilename = srcfile->toChars(); + Macro::define(¯otable, (unsigned char *)"SRCFILENAME", 11, (unsigned char *)srcfilename, strlen(srcfilename)); + char *docfilename = docfile->toChars(); Macro::define(¯otable, (unsigned char *)"DOCFILENAME", 11, (unsigned char *)docfilename, strlen(docfilename)); diff --git a/dsymbol.c b/dsymbol.c index be460198..bc11a9b2 100644 --- a/dsymbol.c +++ b/dsymbol.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -45,6 +45,7 @@ Dsymbol::Dsymbol() this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; } Dsymbol::Dsymbol(Identifier *ident) @@ -58,6 +59,7 @@ Dsymbol::Dsymbol(Identifier *ident) this->loc = 0; this->comment = NULL; this->scope = NULL; + this->errors = false; } int Dsymbol::equals(Object *o) @@ -130,12 +132,15 @@ int Dsymbol::oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident) if (!(*ps)->ident || !(*ps)->ident->equals(ident)) continue; } - if (s) // more than one symbol + if (!s) + s = *ps; + else if (s->isOverloadable() && (*ps)->isOverloadable()) + ; // keep head of overload set + else // more than one symbol { *ps = NULL; //printf("\tfalse 2\n"); return FALSE; } - s = *ps; } } } @@ -160,6 +165,10 @@ bool Dsymbol::hasStaticCtorOrDtor() return FALSE; } +void Dsymbol::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ +} + char *Dsymbol::toChars() { return ident ? ident->toChars() : (char *)"__anonymous"; @@ -274,6 +283,23 @@ TemplateInstance *Dsymbol::inTemplateInstance() return NULL; } +// Check if this function is a member of a template which has only been +// instantiated speculatively, eg from inside is(typeof()). +// Return the speculative template instance it is part of, +// or NULL if not speculative. +TemplateInstance *Dsymbol::isSpeculative() +{ + Dsymbol * par = parent; + while (par) + { + TemplateInstance *ti = par->isTemplateInstance(); + if (ti && ti->speculative) + return ti; + par = par->toParent(); + } + return NULL; +} + int Dsymbol::isAnonymous() { return ident ? 0 : 1; @@ -358,11 +384,21 @@ Dsymbol *Dsymbol::search(Loc loc, Identifier *ident, int flags) void *symbol_search_fp(void *arg, const char *seed) { + /* If not in the lexer's string table, it certainly isn't in the symbol table. + * Doing this first is a lot faster. + */ + size_t len = strlen(seed); + if (!len) + return NULL; + StringValue *sv = Lexer::stringtable.lookup(seed, len); + if (!sv) + return NULL; + Identifier *id = (Identifier *)sv->ptrvalue; + assert(id); + Dsymbol *s = (Dsymbol *)arg; - Identifier id(seed, 0); Module::clearCache(); - s = s->search(0, &id, 4|2); - return s; + return s->search(0, id, 4|2); } Dsymbol *Dsymbol::search_correct(Identifier *ident) @@ -400,8 +436,14 @@ Dsymbol *Dsymbol::searchX(Loc loc, Scope *sc, Identifier *id) 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()); + { + sm = s->search_correct(id); + if (sm) + error("template identifier '%s' is not a member of '%s %s', did you mean '%s %s'?", + id->toChars(), s->kind(), s->toChars(), sm->kind(), sm->toChars()); + else + error("template identifier '%s' is not a member of '%s %s'", + id->toChars(), s->kind(), s->toChars()); return NULL; } sm = sm->toAlias(); @@ -490,6 +532,11 @@ int Dsymbol::isOverloadable() { return 0; } + +int Dsymbol::hasOverloads() +{ + return 0; +} #endif LabelDsymbol *Dsymbol::isLabel() // is this a LabelDsymbol()? @@ -515,6 +562,11 @@ int Dsymbol::needThis() return FALSE; } +int Dsymbol::apply(Dsymbol_apply_ft_t fp, void *param) +{ + return (*fp)(this, param); +} + int Dsymbol::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { //printf("Dsymbol::addMember('%s')\n", toChars()); @@ -1093,7 +1145,7 @@ int ScopeDsymbol::foreach(Dsymbols *members, ScopeDsymbol::ForeachDg dg, void *c { Dsymbol *s = (*members)[i]; if (AttribDeclaration *a = s->isAttribDeclaration()) - result = foreach(a->decl, dg, ctx, &n); + result = foreach(a->include(NULL, NULL), dg, ctx, &n); else if (TemplateMixin *tm = s->isTemplateMixin()) result = foreach(tm->members, dg, ctx, &n); else if (s->isTemplateInstance()) diff --git a/dsymbol.h b/dsymbol.h index 97406f0b..3b66cde9 100644 --- a/dsymbol.h +++ b/dsymbol.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -109,6 +109,8 @@ enum PASS PASSobj, // toObjFile() run }; +typedef int (*Dsymbol_apply_ft_t)(Dsymbol *, void *); + struct Dsymbol : Object { Identifier *ident; @@ -119,6 +121,7 @@ struct Dsymbol : Object unsigned char *comment; // documentation comment for this Dsymbol Loc loc; // where defined Scope *scope; // !=NULL means context to use for semantic() + bool errors; // this symbol failed to pass semantic() Dsymbol(); Dsymbol(Identifier *); @@ -136,6 +139,7 @@ struct Dsymbol : Object Dsymbol *toParent(); Dsymbol *toParent2(); TemplateInstance *inTemplateInstance(); + TemplateInstance *isSpeculative(); int dyncast() { return DYNCAST_DSYMBOL; } // kludge for template.isSymbol() @@ -144,6 +148,7 @@ struct Dsymbol : Object virtual const char *toPrettyChars(); virtual const char *kind(); virtual Dsymbol *toAlias(); // resolve real symbol + virtual int apply(Dsymbol_apply_ft_t fp, void *param); virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); @@ -172,6 +177,7 @@ struct Dsymbol : Object virtual int isDeprecated(); // is Dsymbol deprecated? #if DMDV2 virtual int isOverloadable(); + virtual int hasOverloads(); #endif virtual LabelDsymbol *isLabel(); // is this a LabelDsymbol? virtual AggregateDeclaration *isMember(); // is this symbol a member of an AggregateDeclaration? @@ -182,6 +188,7 @@ struct Dsymbol : Object virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual int oneMember(Dsymbol **ps, Identifier *ident); static int oneMembers(Dsymbols *members, Dsymbol **ps, Identifier *ident = NULL); + virtual void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); virtual int hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addLocalClass(ClassDeclarations *) { } diff --git a/dump.c b/dump.c index 4fd0d04e..c9e4f5ff 100644 --- a/dump.c +++ b/dump.c @@ -55,7 +55,7 @@ void Expression::dump(int i) void IntegerExp::dump(int i) { indent(i); - printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type)); + printf("%p %lld type=%s\n", this, (ulonglong)value, type_print(type)); } void IdentifierExp::dump(int i) diff --git a/e2ir.c b/e2ir.c index 35060b81..c40bdc3c 100644 --- a/e2ir.c +++ b/e2ir.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -11,7 +11,7 @@ #include #include #include -#include +//#include #include "port.h" @@ -2784,13 +2784,8 @@ elem *AssignExp::toElem(IRState *irs) esize = el_bin(OPmul, TYsize_t, elen, esize); elem *epto = array_toPtr(e1->type, ex); elem *epfr = array_toPtr(e2->type, efrom); -#if 1 - // memcpy() is faster, so if we can't beat 'em, join 'em e = el_params(esize, epfr, epto, NULL); e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_MEMCPY]),e); -#else - e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize)); -#endif e = el_pair(eto->Ety, el_copytree(elen), e); e = el_combine(eto, e); } @@ -3377,7 +3372,7 @@ elem *CondExp::toElem(IRState *irs) elem *TypeExp::toElem(IRState *irs) { -#ifdef DEBUG +#if 0 printf("TypeExp::toElem()\n"); #endif error("type %s is not an expression", toChars()); @@ -3426,11 +3421,28 @@ elem *DelegateExp::toElem(IRState *irs) int directcall = 0; //printf("DelegateExp::toElem() '%s'\n", toChars()); + + if (func->semanticRun == PASSsemantic3done) + { // Bug 7745 - only include the function if it belongs to this module + // ie, it is a member of this module, or is a template instance + // (the template declaration could come from any module). + Dsymbol * owner = func->toParent(); + while (!owner->isTemplateInstance() && owner->toParent()) + owner = owner->toParent(); + if (owner->isTemplateInstance() || owner == irs->m ) + { + irs->deferToObj->push(func); + } + } + sfunc = func->toSymbol(); if (func->isNested()) { ep = el_ptr(sfunc); - ethis = getEthis(loc, irs, func); + if (e1->op == TOKnull) + ethis = e1->toElem(irs); + else + ethis = getEthis(loc, irs, func); } else { @@ -3460,8 +3472,7 @@ elem *DelegateExp::toElem(IRState *irs) ep = el_una(OPind, TYnptr, ep); vindex = func->vtblIndex; - if ((int)vindex < 0) - error("Internal compiler error: malformed delegate. See Bugzilla 4860"); + assert((int)vindex >= 0); // Build *(ep + vindex * 4) ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * PTRSIZE)); @@ -3534,6 +3545,10 @@ elem *CallExp::toElem(IRState *irs) } break; } + if (dve->e1->op == TOKstructliteral) + { StructLiteralExp *sle = (StructLiteralExp *)dve->e1; + sle->sinit = NULL; // don't modify initializer + } ec = dve->e1->toElem(irs); ectype = dve->e1->type->toBasetype(); } @@ -3541,7 +3556,10 @@ elem *CallExp::toElem(IRState *irs) { fd = ((VarExp *)e1)->var->isFuncDeclaration(); - if (fd && fd->ident == Id::alloca && +#if 0 // This optimization is not valid if alloca can be called + // multiple times within the same function, eg in a loop + // see issue 3822 + if (fd && fd->ident == Id::__alloca && !fd->fbody && fd->linkage == LINKc && arguments && arguments->dim == 1) { Expression *arg = arguments->tdata()[0]; @@ -3567,6 +3585,7 @@ elem *CallExp::toElem(IRState *irs) } } } +#endif ec = e1->toElem(irs); } @@ -4336,7 +4355,7 @@ Lagain: case X(Timaginary80,Tfloat32): case X(Timaginary80,Tfloat64): case X(Timaginary80,Tfloat80): goto Lzero; - case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e); + case X(Timaginary80,Timaginary32): e = el_una(OPld_d, TYidouble, e); fty = Timaginary64; goto Lagain; case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop; @@ -4428,6 +4447,9 @@ Lagain: fty = Tcomplex64; goto Lagain; + case X(Tnull, Tarray): + goto Lzero; + /* ============================= */ default: @@ -4789,22 +4811,34 @@ elem *ArrayLiteralExp::toElem(IRState *irs) * exps[]. * Return the initialization expression, and the symbol for the static array in *psym. */ -elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, Type *telem, symbol **psym) +elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, symbol **psym) { // Create a static array of type telem[dim] size_t dim = exps->dim; - Type *tsarray = new TypeSArray(telem, new IntegerExp(loc, dim, Type::tsize_t)); - tsarray = tsarray->semantic(loc, NULL); - symbol *stmp = symbol_genauto(tsarray->toCtype()); - targ_size_t szelem = telem->size(); Elems elems; elems.setDim(dim); - ::type *te = telem->toCtype(); // stmp[] element type + Type *telem; + Type *tsarray; + symbol *stmp; + targ_size_t szelem; + ::type *te; // stmp[] element type for (size_t i = 0; i < dim; i++) - { Expression *el = exps->tdata()[i]; + { Expression *el = (*exps)[i]; + + if (i == 0) + { + telem = el->type; + szelem = telem->size(); + te = telem->toCtype(); + + tsarray = new TypeSArray(telem, new IntegerExp(loc, dim, Type::tsize_t)); + tsarray = tsarray->semantic(loc, NULL); + stmp = symbol_genauto(tsarray->toCtype()); + *psym = stmp; + } /* Generate: *(&stmp + i * szelem) = element[i] */ @@ -4825,44 +4859,62 @@ elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, Type *t eeq->Ejty = eeq->Ety = TYstruct; eeq->ET = te; } - elems.tdata()[i] = eeq; + elems[i] = eeq; } - *psym = stmp; return el_combines((void **)elems.tdata(), dim); } elem *AssocArrayLiteralExp::toElem(IRState *irs) { //printf("AssocArrayLiteralExp::toElem() %s\n", toChars()); - size_t dim = keys->dim; - elem *e; - // call _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values) - // Prefer this to avoid the varargs fiasco in 64 bit code Type *t = type->toBasetype()->mutableOf(); - assert(t->ty == Taarray); - TypeAArray *ta = (TypeAArray *)t; - symbol *skeys; - elem *ekeys = ExpressionsToStaticArray(irs, loc, keys, ta->index, &skeys); + size_t dim = keys->dim; + if (dim) + { + // call _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values) + // Prefer this to avoid the varargs fiasco in 64 bit code - symbol *svalues; - elem *evalues = ExpressionsToStaticArray(irs, loc, values, ta->nextOf(), &svalues); + Type *ta; + if (t->ty == Taarray) + ta = t; + else + { // It's the AssociativeArray type. + // Turn it back into a TypeAArray + ta = new TypeAArray((*values)[0]->type, (*keys)[0]->type); + ta = ta->semantic(loc, NULL); + } - e = el_params(el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(svalues)), - el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(skeys )), - ta->getTypeInfo(NULL)->toElem(irs), - NULL); + symbol *skeys = NULL; + elem *ekeys = ExpressionsToStaticArray(irs, loc, keys, &skeys); - // call _d_assocarrayliteralTX(ti, keys, values) - e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALTX]),e); - el_setLoc(e,loc); + symbol *svalues = NULL; + elem *evalues = ExpressionsToStaticArray(irs, loc, values, &svalues); - e = el_combine(evalues, e); - e = el_combine(ekeys, e); + elem *e = el_params(el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(svalues)), + el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(skeys )), + ta->getTypeInfo(NULL)->toElem(irs), + NULL); - return e; + // call _d_assocarrayliteralTX(ti, keys, values) + e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALTX]),e); + if (t != ta) + e = addressElem(e, ta); + el_setLoc(e,loc); + + e = el_combine(evalues, e); + e = el_combine(ekeys, e); + return e; + } + else + { + elem *e = el_long(TYnptr, 0); // empty associative array is the null pointer + if (t->ty != Taarray) + e = addressElem(e, Type::tvoidptr); + return e; + } } @@ -4911,15 +4963,35 @@ elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff) } elem *StructLiteralExp::toElem(IRState *irs) -{ elem *e; - size_t dim; - +{ //printf("StructLiteralExp::toElem() %s\n", toChars()); + if (sinit) + { + elem *e = el_var(sinit); + e->ET = sd->type->toCtype(); + el_setLoc(e,loc); + + if (sym) + { elem *ev = el_var(sym); + if (tybasic(ev->Ety) == TYnptr) + ev = el_una(OPind, e->Ety, ev); + ev->ET = e->ET; + e = el_bin(OPstreq,e->Ety,ev,e); + e->ET = ev->ET; + + //ev = el_var(sym); + //ev->ET = e->ET; + //e = el_combine(e, ev); + el_setLoc(e,loc); + } + return e; + } + // struct symbol to initialize with the literal Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype()); - e = NULL; + elem *e = NULL; if (fillHoles) { @@ -4944,7 +5016,7 @@ elem *StructLiteralExp::toElem(IRState *irs) if (elements) { - dim = elements->dim; + size_t dim = elements->dim; assert(dim <= sd->fields.dim); for (size_t i = 0; i < dim; i++) { Expression *el = elements->tdata()[i]; diff --git a/eh.c b/eh.c index 2896b745..e6c64ff6 100644 --- a/eh.c +++ b/eh.c @@ -31,6 +31,10 @@ static char __file__[] = __FILE__; /* for tassert.h */ #include "tassert.h" +#if _MSC_VER +#include +#endif + /* If we do our own EH tables and stack walking scheme * (Otherwise use NT Structured Exception Handling) */ @@ -103,6 +107,8 @@ void except_fillInEHTable(symbol *s) */ #if OUREH #define GUARD_SIZE (I64 ? 3*8 : 5*4) // sizeof(Guard) +#elif _WIN64 +#define GUARD_SIZE (I64 ? 3*8 : 3*4) // sizeof(Guard) depends on target #else #define GUARD_SIZE (sizeof(Guard)) #endif diff --git a/enum.c b/enum.c index d88d6e3d..93beb303 100644 --- a/enum.c +++ b/enum.c @@ -167,6 +167,7 @@ void EnumDeclaration::semantic(Scope *sc) { EnumMember *em = (*members)[i]->isEnumMember(); Expression *e; + Expression *emax = NULL; if (!em) /* The e->semantic(sce) can insert other symbols, such as @@ -217,10 +218,18 @@ void EnumDeclaration::semantic(Scope *sc) } else { + // Lazily evaluate enum.max + if (!emax) + { + emax = t->getProperty(0, Id::max); + emax = emax->semantic(sce); + emax = emax->optimize(WANTvalue | WANTinterpret); + } + // Set value to (elast + 1). // But first check that (elast != t.max) assert(elast); - e = new EqualExp(TOKequal, em->loc, elast, t->getProperty(0, Id::max)); + e = new EqualExp(TOKequal, em->loc, elast, emax); e = e->semantic(sce); e = e->optimize(WANTvalue | WANTinterpret); if (e->toInteger()) @@ -231,6 +240,16 @@ void EnumDeclaration::semantic(Scope *sc) e = e->semantic(sce); e = e->castTo(sce, elast->type); e = e->optimize(WANTvalue | WANTinterpret); + + if (t->isfloating()) + { + // Check that e != elast (not always true for floats) + Expression *etest = new EqualExp(TOKequal, em->loc, e, elast); + etest = etest->semantic(sce); + etest = etest->optimize(WANTvalue | WANTinterpret); + if (etest->toInteger()) + error("enum member %s has inexact value, due to loss of precision", em->toChars()); + } } elast = e; em->value = e; diff --git a/enum.h b/enum.h index 0d617630..cc36b494 100644 --- a/enum.h +++ b/enum.h @@ -42,6 +42,9 @@ struct EnumDeclaration : ScopeDsymbol int isdeprecated; int isdone; // 0: not done // 1: semantic() successfully completed +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif EnumDeclaration(Loc loc, Identifier *id, Type *memtype); Dsymbol *syntaxCopy(Dsymbol *s); diff --git a/expression.c b/expression.c index 3b41fd35..266999f5 100644 --- a/expression.c +++ b/expression.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -301,6 +301,113 @@ return_expr: return e; } +/****************************** + * Check the tail CallExp is really property function call. + */ + +void checkPropertyCall(Expression *e, Expression *emsg) +{ + while (e->op == TOKcomma) + e = ((CommaExp *)e)->e2; + + if (e->op == TOKcall) + { CallExp *ce = (CallExp *)e; + TypeFunction *tf; + if (ce->f) + tf = (TypeFunction *)ce->f->type; + else if (ce->e1->type->ty == Tfunction) + tf = (TypeFunction *)ce->e1->type; + else if (ce->e1->type->ty == Tdelegate) + tf = (TypeFunction *)ce->e1->type->nextOf(); + else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction) + tf = (TypeFunction *)ce->e1->type->nextOf(); + else + assert(0); + + if (!tf->isproperty && global.params.enforcePropertySyntax) + ce->e1->error("not a property %s", emsg->toChars()); + } +} + +/****************************** + * Pull out property with UFCS. + */ + +Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL) +{ + Expression *e = NULL; + Expression *eleft; + Identifier *ident; + Objects* tiargs; + Loc loc = e1->loc; + + if (e1->op == TOKdot) + { + DotIdExp *die = (DotIdExp *)e1; + eleft = die->e1; + ident = die->ident; + tiargs = NULL; + goto L1; + } + else if (e1->op == TOKdotti) + { + DotTemplateInstanceExp *dti; + dti = (DotTemplateInstanceExp *)e1; + eleft = dti->e1; + ident = dti->ti->name; + tiargs = dti->ti->tiargs; + L1: + /* .ident + * .ident!tiargs + */ + e = new IdentifierExp(loc, Id::empty); + if (tiargs) + e = new DotTemplateInstanceExp(loc, e, ident, tiargs); + else + e = new DotIdExp(loc, e, ident); + + Expressions *arguments = new Expressions(); + /* .f(e1, e2) + */ + if (e2) + { + arguments->setDim(2); + (*arguments)[0] = eleft; + (*arguments)[1] = e2; + + Expression *ex = e->syntaxCopy(); + e = new CallExp(loc, e, arguments); + e = e->trySemantic(sc); + if (e) + { checkPropertyCall(e, e1); + return e->semantic(sc); + } + e = ex; + } + + /* .f(e1) + * .f(e1) = e2 + */ + { + arguments->setDim(1); + (*arguments)[0] = eleft; + e = new CallExp(loc, e, arguments); + e = e->trySemantic(sc); + if (!e) + goto Leprop; + checkPropertyCall(e, e1); + if (e2) + e = new AssignExp(loc, e, e2); + return e->semantic(sc); + } + } + return e; + +Leprop: + e1->error("not a property %s", e1->toChars()); + return new ErrorExp(); +} + /****************************** * Perform semantic() on an array of Expressions. */ @@ -506,7 +613,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt e = resolveProperties(sc, e); if (!e->type) - { error("%s has no value", e->toChars()); + { e->error("%s has no value", e->toChars()); e = new ErrorExp(); } @@ -670,23 +777,6 @@ Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope) } #endif -// Check if this function is a member of a template which has only been -// instantiated speculatively, eg from inside is(typeof()). -// Return the speculative template instance it is part of, -// or NULL if not speculative. -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd) -{ - Dsymbol * par = fd->parent; - while (par) - { - TemplateInstance *ti = par->isTemplateInstance(); - if (ti && ti->speculative) - return ti; - par = par->toParent(); - } - return NULL; -} - /**************************************** * Now that we know the exact type of the function we're calling, * the arguments[] need to be adjusted: @@ -709,14 +799,14 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, size_t nparams = Parameter::dim(tf->parameters); if (nargs > nparams && tf->varargs == 0) - { error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf->toChars()); + { error(loc, "expected %zu arguments, not %llu for non-variadic function type %s", nparams, (ulonglong)nargs, tf->toChars()); return Type::terror; } // If inferring return type, and semantic3() needs to be run if not already run if (!tf->next && fd->inferRetType) { - TemplateInstance *spec = isSpeculativeFunction(fd); + TemplateInstance *spec = fd->isSpeculative(); int olderrs = global.errors; fd->semantic3(fd->scope); // Update the template instantiation with the number @@ -761,7 +851,7 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, { if (tf->varargs == 2 && i + 1 == nparams) goto L2; - error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); return Type::terror; } arg = p->defaultArg; @@ -772,25 +862,25 @@ Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf, arguments->push(arg); nargs++; } - else if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; + else + { Type *pt = p->type; if (tf->varargs == 2 && i + 1 == nparams && pt->nextOf()) pt = pt->nextOf(); - fe->setType(pt); - arg = fe->semantic(sc); - arguments->tdata()[i] = arg; + arg = arg->inferType(pt); + arguments->tdata()[i] = arg; } if (tf->varargs == 2 && i + 1 == nparams) { //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars()); - if (arg->implicitConvTo(p->type)) + MATCH m; + if ((m = arg->implicitConvTo(p->type)) != MATCHnomatch) { - if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf())) + if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m) goto L2; else if (nargs != nparams) - { error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs); return Type::terror; } goto L1; @@ -1126,18 +1216,17 @@ void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr) * Write out argument list to buf. */ -void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs) +void argsToCBuffer(OutBuffer *buf, Expressions *expressions, HdrGenState *hgs) { - if (arguments) + if (expressions) { - for (size_t i = 0; i < arguments->dim; i++) - { Expression *arg = arguments->tdata()[i]; + for (size_t i = 0; i < expressions->dim; i++) + { Expression *e = (*expressions)[i]; - if (arg) - { if (i) - buf->writeByte(','); - expToCBuffer(buf, hgs, arg, PREC_assign); - } + if (i) + buf->writeByte(','); + if (e) + expToCBuffer(buf, hgs, e, PREC_assign); } } } @@ -1152,12 +1241,12 @@ void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *h { OutBuffer argbuf; for (size_t i = 0; i < arguments->dim; i++) - { Expression *arg = arguments->tdata()[i]; + { Expression *e = (*arguments)[i]; if (i) buf->writeByte(','); argbuf.reset(); - arg->type->toCBuffer2(&argbuf, hgs, 0); + e->type->toCBuffer2(&argbuf, hgs, 0); buf->write(&argbuf); } } @@ -1323,13 +1412,13 @@ uinteger_t Expression::toUInteger() real_t Expression::toReal() { error("Floating point constant expression expected instead of %s", toChars()); - return 0; + return ldouble(0); } real_t Expression::toImaginary() { error("Floating point constant expression expected instead of %s", toChars()); - return 0; + return ldouble(0); } complex_t Expression::toComplex() @@ -1338,7 +1427,7 @@ complex_t Expression::toComplex() #ifdef IN_GCC return complex_t(real_t(0)); // %% nicer #else - return 0; + return 0.0; #endif } @@ -1355,9 +1444,6 @@ void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs) void Expression::toMangleBuffer(OutBuffer *buf) { error("expression %s is not a valid template value argument", toChars()); -#ifdef DEBUG -dump(0); -#endif } /*************************************** @@ -1547,7 +1633,7 @@ void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis) break; if (ff->setImpure() && !msg) { error("pure function '%s' cannot access mutable static data '%s'", - sc->func->toChars(), v->toChars()); + sc->func->toPrettyChars(), v->toChars()); msg = TRUE; // only need the innermost message } } @@ -1619,6 +1705,7 @@ Expression *Expression::checkToBoolean(Scope *sc) #ifdef DEBUG if (!type) dump(0); + assert(type); #endif // Structs can be converted to bool using opCast(bool)() @@ -1639,9 +1726,7 @@ Expression *Expression::checkToBoolean(Scope *sc) // Forward to aliasthis. if (ad->aliasthis) { - Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident); - e = e->semantic(sc); - e = resolveProperties(sc, e); + Expression *e = resolveAliasThis(sc, this); e = e->checkToBoolean(sc); return e; } @@ -1847,7 +1932,7 @@ char *IntegerExp::toChars() #else static char buffer[sizeof(value) * 3 + 1]; - sprintf(buffer, "%jd", value); + sprintf(buffer, "%lld", value); return buffer; #endif } @@ -1919,14 +2004,14 @@ real_t IntegerExp::toReal() toInteger(); t = type->toBasetype(); if (t->ty == Tuns64) - return (real_t)(d_uns64)value; + return ldouble((d_uns64)value); else - return (real_t)(d_int64)value; + return ldouble((d_int64)value); } real_t IntegerExp::toImaginary() { - return (real_t) 0; + return ldouble(0); } complex_t IntegerExp::toComplex() @@ -2043,12 +2128,12 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) break; case Tint64: - buf->printf("%jdL", v); + buf->printf("%lldL", v); break; case Tuns64: L4: - buf->printf("%juLU", v); + buf->printf("%lluLU", v); break; case Tbool: @@ -2081,15 +2166,15 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) } } else if (v & 0x8000000000000000LL) - buf->printf("0x%jx", v); + buf->printf("0x%llx", v); else - buf->printf("%jd", v); + buf->printf("%lld", v); } void IntegerExp::toMangleBuffer(OutBuffer *buf) { if ((sinteger_t)value < 0) - buf->printf("N%jd", -value); + buf->printf("N%lld", -value); else { /* This is an awful hack to maintain backwards compatibility. @@ -2101,7 +2186,7 @@ void IntegerExp::toMangleBuffer(OutBuffer *buf) if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1])) buf->writeByte('i'); - buf->printf("%jd", value); + buf->printf("%lld", value); } } @@ -2143,11 +2228,12 @@ char *RealExp::toChars() #ifdef IN_GCC value.format(buffer, sizeof(buffer)); +#else + ld_sprint(buffer, 'g', value); +#endif if (type->isimaginary()) strcat(buffer, "i"); -#else - sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value); -#endif + assert(strlen(buffer) < sizeof(buffer)); return mem.strdup(buffer); } @@ -2155,7 +2241,7 @@ char *RealExp::toChars() dinteger_t RealExp::toInteger() { #ifdef IN_GCC - return toReal().toInt(); + return (sinteger_t) toReal().toInt(); #else return (sinteger_t) toReal(); #endif @@ -2172,12 +2258,12 @@ uinteger_t RealExp::toUInteger() real_t RealExp::toReal() { - return type->isreal() ? value : 0; + return type->isreal() ? value : ldouble(0); } real_t RealExp::toImaginary() { - return type->isreal() ? 0 : value; + return type->isreal() ? ldouble(0) : value; } complex_t RealExp::toComplex() @@ -2244,7 +2330,7 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) * always exact. */ char buffer[25]; - sprintf(buffer, "%Lg", value); + ld_sprint(buffer, 'g', value); assert(strlen(buffer) < sizeof(buffer)); #if _WIN32 && __DMC__ char *save = __locale_decpoint; @@ -2254,10 +2340,9 @@ void floatToBuffer(OutBuffer *buf, Type *type, real_t value) #else real_t r = strtold(buffer, NULL); #endif - if (r == value) // if exact duplication - buf->writestring(buffer); - else - buf->printf("%La", value); // ensure exact duplication + if (r != value) // if exact duplication + ld_sprint(buffer, 'a', value); + buf->writestring(buffer); if (type) { @@ -2307,7 +2392,7 @@ void realToMangleBuffer(OutBuffer *buf, real_t value) else { char buffer[32]; - int n = sprintf(buffer, "%LA", value); + int n = ld_sprint(buffer, 'A', value); assert(n > 0 && n < sizeof(buffer)); for (int i = 0; i < n; i++) { char c = buffer[i]; @@ -2355,16 +2440,17 @@ char *ComplexExp::toChars() { char buffer[sizeof(value) * 3 + 8 + 1]; -#ifdef IN_GCC char buf1[sizeof(value) * 3 + 8 + 1]; char buf2[sizeof(value) * 3 + 8 + 1]; +#ifdef IN_GCC creall(value).format(buf1, sizeof(buf1)); cimagl(value).format(buf2, sizeof(buf2)); - sprintf(buffer, "(%s+%si)", buf1, buf2); #else - sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value)); - assert(strlen(buffer) < sizeof(buffer)); + ld_sprint(buffer, 'g', creall(value)); + ld_sprint(buffer, 'g', cimagl(value)); #endif + sprintf(buffer, "(%s+%si)", buf1, buf2); + assert(strlen(buffer) < sizeof(buffer)); return mem.strdup(buffer); } @@ -2633,6 +2719,8 @@ DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads) this->hasOverloads = hasOverloads; } +AggregateDeclaration *isAggregate(Type *t); + Expression *DsymbolExp::semantic(Scope *sc) { #if LOGSEMANTIC @@ -2690,6 +2778,7 @@ Lagain: if (em) { e = em->value; + e->loc = loc; e = e->semantic(sc); return e; } @@ -2736,12 +2825,18 @@ Lagain: { //printf("'%s' is a function\n", f->toChars()); if (!f->originalType && f->scope) // semantic not yet run + { + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !f->isSpeculative()) + global.gag = 0; f->semantic(f->scope); + global.gag = oldgag; + } // if inferring return type, sematic3 needs to be run if (f->inferRetType && f->scope && f->type && !f->type->nextOf()) { - TemplateInstance *spec = isSpeculativeFunction(f); + TemplateInstance *spec = f->isSpeculative(); int olderrs = global.errors; f->semantic3(f->scope); // Update the template instantiation with the number @@ -2819,7 +2914,7 @@ Lagain: } TemplateInstance *ti = s->isTemplateInstance(); - if (ti && !global.errors) + if (ti) { if (!ti->semanticRun) ti->semantic(sc); s = ti->inst->toAlias(); @@ -2833,12 +2928,14 @@ Lagain: TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) { -#if 0 // This was the fix for Bugzilla 6738, but it breaks 7498 Dsymbol *p = td->toParent2(); - if (hasThis(sc) && p && p->isAggregateDeclaration()) + FuncDeclaration *fdthis = hasThis(sc); + AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL; + if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad) + { e = new DotTemplateExp(loc, new ThisExp(loc), td); + } else -#endif e = new TemplateExp(loc, td); e = e->semantic(sc); return e; @@ -3687,6 +3784,9 @@ Expression *AssocArrayLiteralExp::semantic(Scope *sc) keys = arrayExpressionToCommonType(sc, keys, &tkey); values = arrayExpressionToCommonType(sc, values, &tvalue); + if (tkey == Type::terror || tvalue == Type::terror) + return new ErrorExp; + type = new TypeAArray(tvalue, tkey); type = type->semantic(loc, sc); return this; @@ -3738,10 +3838,12 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions * this->sd = sd; this->elements = elements; this->stype = stype; + this->sinit = NULL; this->sym = NULL; this->soffset = 0; this->fillHoles = 1; this->ownedByCtfe = false; + //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars()); } Expression *StructLiteralExp::syntaxCopy() @@ -3751,7 +3853,6 @@ Expression *StructLiteralExp::syntaxCopy() Expression *StructLiteralExp::semantic(Scope *sc) { Expression *e; - size_t nfields = sd->fields.dim - sd->isnested; #if LOGSEMANTIC printf("StructLiteralExp::semantic('%s')\n", toChars()); @@ -3759,6 +3860,11 @@ Expression *StructLiteralExp::semantic(Scope *sc) if (type) return this; + sd->size(loc); + if (sd->sizeok != SIZEOKdone) + return new ErrorExp(); + size_t nfields = sd->fields.dim - sd->isnested; + elements = arrayExpressionSemantic(elements, sc); // run semantic() on each element expandTuples(elements); size_t offset = 0; @@ -3769,7 +3875,12 @@ Expression *StructLiteralExp::semantic(Scope *sc) e = resolveProperties(sc, e); if (i >= nfields) - { error("more initializers than fields of %s", sd->toChars()); + { +#if 0 + for (size_t i = 0; i < sd->fields.dim; i++) + printf("[%d] = %s\n", i, sd->fields[i]->toChars()); +#endif + error("more initializers than fields (%d) of %s", nfields, sd->toChars()); return new ErrorExp(); } Dsymbol *s = sd->fields.tdata()[i]; @@ -3791,14 +3902,6 @@ Expression *StructLiteralExp::semantic(Scope *sc) telem = telem->toBasetype()->nextOf(); } - if (e->op == TOKfunction) - { e = ((FuncExp *)e)->inferType(sc, telem); - if (!e) - { error("cannot infer function literal type from %s", telem->toChars()); - e = new ErrorExp(); - } - } - e = e->implicitCastTo(sc, telem); elements->tdata()[i] = e; @@ -3941,19 +4044,6 @@ int StructLiteralExp::getFieldIndex(Type *type, unsigned offset) return -1; } -#if DMDV2 -int StructLiteralExp::isLvalue() -{ - return 1; -} -#endif - -Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) -{ - return this; -} - - void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { buf->writestring(sd->toChars()); @@ -4053,8 +4143,9 @@ Expression *ScopeExp::semantic(Scope *sc) #endif Lagain: ti = sds->isTemplateInstance(); - if (ti && !global.errors) + if (ti && !ti->errors) { + unsigned olderrs = global.errors; if (!ti->semanticRun) ti->semantic(sc); if (ti->inst) @@ -4084,7 +4175,7 @@ Lagain: } //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars()); } - if (global.errors) + if (olderrs != global.errors) return new ErrorExp(); } else @@ -4970,49 +5061,49 @@ FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td) this->fd = fd; this->td = td; tok = fd->tok; // save original kind of function/delegate/(infer) - tded = NULL; - scope = NULL; + treq = NULL; } Expression *FuncExp::syntaxCopy() { - return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL)); + TemplateDeclaration *td2 = td ? (TemplateDeclaration *)td->syntaxCopy(NULL) : NULL; + return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL), td2); } Expression *FuncExp::semantic(Scope *sc) { #if LOGSEMANTIC printf("FuncExp::semantic(%s)\n", toChars()); + if (treq) printf(" treq = %s\n", treq->toChars()); #endif if (!type || type == Type::tvoid) { - // save for later use - scope = sc; + if (treq) + treq = treq->semantic(loc, sc); - //printf("td = %p, tded = %p\n", td, tded); + // Set target of return type inference + if (treq && !fd->type->nextOf()) + { TypeFunction *tfv = NULL; + if (treq->ty == Tdelegate || + (treq->ty == Tpointer && treq->nextOf()->ty == Tfunction)) + tfv = (TypeFunction *)treq->nextOf(); + if (tfv) + { TypeFunction *tfl = (TypeFunction *)fd->type; + tfl->next = tfv->nextOf(); + } + } + + //printf("td = %p, treq = %p\n", td, treq); if (td) { assert(td->parameters && td->parameters->dim); td->semantic(sc); + type = Type::tvoid; // temporary type - if (!tded) - { // defer type determination - type = Type::tvoid; // temporary type + if (!treq) // defer type determination return this; - } - else - { - Expression *e = inferType(sc, tded); - if (e) - { e = e->castTo(sc, tded); - e = e->semantic(sc); - } - if (!e) - { error("cannot infer function literal type"); - e = new ErrorExp(); - } - return e; - } + + return inferType(treq); } unsigned olderrors = global.errors; @@ -5041,7 +5132,7 @@ Expression *FuncExp::semantic(Scope *sc) // Type is a "delegate to" or "pointer to" the function literal if ((fd->isNested() && fd->tok == TOKdelegate) || - (tok == TOKreserved && tded && tded->ty == Tdelegate)) + (tok == TOKreserved && treq && treq->ty == Tdelegate)) { type = new TypeDelegate(fd->type); type = type->semantic(loc, sc); @@ -5058,9 +5149,6 @@ Expression *FuncExp::semantic(Scope *sc) // used from CallExp::semantic() Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) { - assert(!tded); - assert(!scope); - if ((!type || type == Type::tvoid) && td && arguments && arguments->dim) { for (size_t k = 0; k < arguments->dim; k++) @@ -5104,83 +5192,6 @@ Expression *FuncExp::semantic(Scope *sc, Expressions *arguments) return semantic(sc); } -Expression *FuncExp::inferType(Scope *sc, Type *to) -{ - //printf("inferType sc = %p, to = %s\n", sc, to->toChars()); - if (!sc) - { // used from TypeFunction::callMatch() - assert(scope); - sc = scope; - } - - Expression *e = NULL; - if (td) - { /// Parameter types inference from - assert(!type || type == Type::tvoid); - Type *t = to; - if (t->ty == Tdelegate || - t->ty == Tpointer && t->nextOf()->ty == Tfunction) - { t = t->nextOf(); - } - if (t->ty == Tfunction) - { - TypeFunction *tfv = (TypeFunction *)t; - TypeFunction *tfl = (TypeFunction *)fd->type; - size_t dim = Parameter::dim(tfl->parameters); - - if (Parameter::dim(tfv->parameters) == dim && - tfv->varargs == tfl->varargs) - { - Objects *tiargs = new Objects(); - tiargs->reserve(td->parameters->dim); - - for (size_t i = 0; i < td->parameters->dim; i++) - { - TemplateParameter *tp = (*td->parameters)[i]; - for (size_t u = 0; u < dim; u++) - { Parameter *p = Parameter::getNth(tfl->parameters, u); - if (p->type->ty == Tident && - ((TypeIdentifier *)p->type)->ident == tp->ident) - { p = Parameter::getNth(tfv->parameters, u); - if (p->type->ty == Tident) - return NULL; - tiargs->push(p->type); - u = dim; // break inner loop - } - } - } - - TemplateInstance *ti = new TemplateInstance(loc, td, tiargs); - e = (new ScopeExp(loc, ti))->semantic(sc); - } - } - } - else - { - assert(type && type != Type::tvoid); // semantic is already done - e = this; - } - - if (e) - { // Check implicit function to delegate conversion - if (e->implicitConvTo(to)) - e = e->castTo(sc, to); - else - e = NULL; - } - return e; -} - -void FuncExp::setType(Type *t) -{ - assert(t); - - if (t->ty == Tdelegate || - t->ty == Tpointer && t->nextOf()->ty == Tfunction) - { tded = t; - } -} - char *FuncExp::toChars() { return fd->toChars(); @@ -5871,44 +5882,122 @@ Expression *BinExp::semanticp(Scope *sc) } -// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary -void BinExp::checkComplexMulAssign() +Expression *BinExp::checkComplexOpAssign(Scope *sc) { - // Any multiplication by an imaginary or complex number yields a complex result. - // r *= c, i*=c, r*=i, i*=i are all forbidden operations. - const char *opstr = Token::toChars(op); - if ( e1->type->isreal() && e2->type->iscomplex()) + // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary + if (op == TOKmulass || op == TOKdivass || op == TOKmodass) { - error("%s %s %s is undefined. Did you mean %s %s %s.re ?", - e1->type->toChars(), opstr, e2->type->toChars(), - e1->type->toChars(), opstr, e2->type->toChars()); + // Any multiplication by an imaginary or complex number yields a complex result. + // r *= c, i*=c, r*=i, i*=i are all forbidden operations. + const char *opstr = Token::toChars(op); + if ( e1->type->isreal() && e2->type->iscomplex()) + { + error("%s %s %s is undefined. Did you mean %s %s %s.re ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } + else if (e1->type->isimaginary() && e2->type->iscomplex()) + { + error("%s %s %s is undefined. Did you mean %s %s %s.im ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } + else if ((e1->type->isreal() || e1->type->isimaginary()) && + e2->type->isimaginary()) + { + error("%s %s %s is an undefined operation", e1->type->toChars(), + opstr, e2->type->toChars()); + } } - else if (e1->type->isimaginary() && e2->type->iscomplex()) - { - error("%s %s %s is undefined. Did you mean %s %s %s.im ?", - e1->type->toChars(), opstr, e2->type->toChars(), - e1->type->toChars(), opstr, e2->type->toChars()); - } - else if ((e1->type->isreal() || e1->type->isimaginary()) && - e2->type->isimaginary()) - { - error("%s %s %s is an undefined operation", e1->type->toChars(), - opstr, e2->type->toChars()); - } -} -// generate an error if this is a nonsensical += or -=, eg real += imaginary -void BinExp::checkComplexAddAssign() -{ - // Addition or subtraction of a real and an imaginary is a complex result. - // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. - if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || - (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) - ) + // generate an error if this is a nonsensical += or -=, eg real += imaginary + if (op == TOKaddass || op == TOKminass) { - error("%s %s %s is undefined (result is complex)", - e1->type->toChars(), Token::toChars(op), e2->type->toChars()); + // Addition or subtraction of a real and an imaginary is a complex result. + // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. + if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || + (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) + ) + { + error("%s %s %s is undefined (result is complex)", + e1->type->toChars(), Token::toChars(op), e2->type->toChars()); + } + if (type->isreal() || type->isimaginary()) + { + assert(global.errors || e2->type->isfloating()); + e2 = e2->castTo(sc, e1->type); + } } + + if (op == TOKmulass) + { + if (e2->type->isfloating()) + { + Type *t1 = e1->type; + Type *t2 = e2->type; + if (t1->isreal()) + { + if (t2->isimaginary() || t2->iscomplex()) + { + e2 = e2->castTo(sc, t1); + } + } + else if (t1->isimaginary()) + { + if (t2->isimaginary() || t2->iscomplex()) + { + switch (t1->ty) + { + case Timaginary32: t2 = Type::tfloat32; break; + case Timaginary64: t2 = Type::tfloat64; break; + case Timaginary80: t2 = Type::tfloat80; break; + default: + assert(0); + } + e2 = e2->castTo(sc, t2); + } + } + } + } else if (op == TOKdivass) + { + if (e2->type->isimaginary()) + { + Type *t1 = e1->type; + if (t1->isreal()) + { // x/iv = i(-x/v) + // Therefore, the result is 0 + e2 = new CommaExp(loc, e2, new RealExp(loc, ldouble(0.0), t1)); + e2->type = t1; + Expression *e = new AssignExp(loc, e1, e2); + e->type = t1; + return e; + } + else if (t1->isimaginary()) + { Type *t2; + + switch (t1->ty) + { + case Timaginary32: t2 = Type::tfloat32; break; + case Timaginary64: t2 = Type::tfloat64; break; + case Timaginary80: t2 = Type::tfloat80; break; + default: + assert(0); + } + e2 = e2->castTo(sc, t2); + Expression *e = new AssignExp(loc, e1, e2); + e->type = t1; + return e; + } + } + } else if (op == TOKmodass) + { + if (e2->type->iscomplex()) + { + error("cannot perform modulo complex arithmetic"); + return new ErrorExp(); + } + } + return this; } void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs) @@ -5930,9 +6019,18 @@ Expression *BinExp::incompatibleTypes() if (e1->type->toBasetype() != Type::terror && e2->type->toBasetype() != Type::terror ) - { error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", + { + if (e1->op == TOKtype || e2->op == TOKtype) + { + error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types", + e1->toChars(), Token::toChars(op), e2->toChars(), Token::toChars(op)); + } + else + { + error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", e1->toChars(), Token::toChars(op), e2->toChars(), e1->type->toChars(), e2->type->toChars()); + } return new ErrorExp(); } return this; @@ -5940,94 +6038,91 @@ Expression *BinExp::incompatibleTypes() /********************** BinAssignExp **************************************/ -/*************************** - * Common semantic routine for some xxxAssignExp's. - */ +Expression *BinAssignExp::semantic(Scope *sc) +{ + Expression *e; -Expression *BinAssignExp::commonSemanticAssign(Scope *sc) -{ Expression *e; + if (type) + return this; - if (!type) + e = op_overload(sc); + if (e) + return e; + + if (e1->op == TOKarraylength) { - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] op= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - type = e1->type; - if (type->toBasetype()->ty == Tbool) - { - error("operator not allowed on bool expression %s", toChars()); - return new ErrorExp(); - } - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - - if (op == TOKmodass) - { - if (e2->type->iscomplex()) - { error("cannot perform modulo complex arithmetic"); - return new ErrorExp(); - } - else if (type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - } + e = ArrayLengthExp::rewriteOpAssign(this); + e = e->semantic(sc); + return e; } - return this; -} -Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc) -{ Expression *e; - - if (!type) + if (e1->op == TOKslice) { - e = op_overload(sc); - if (e) + // T[] op= ... + e = typeCombine(sc); + if (e->op == TOKerror) return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] op= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); type = e1->type; - if (type->toBasetype()->ty == Tbool) - { - e2 = e2->implicitCastTo(sc, type); - } - - typeCombine(sc); - e1->checkIntegral(); - e2->checkIntegral(); + return arrayOp(sc); } - return this; + + e1 = e1->modifiableLvalue(sc, e1); + e1 = e1->semantic(sc); + type = e1->type; + checkScalar(); + + int arith = (op == TOKaddass || op == TOKminass || op == TOKmulass || + op == TOKdivass || op == TOKmodass || op == TOKpowass); + int bitwise = (op == TOKandass || op == TOKorass || op == TOKxorass); + int shift = (op == TOKshlass || op == TOKshrass || op == TOKushrass); + + if (bitwise && type->toBasetype()->ty == Tbool) + e2 = e2->implicitCastTo(sc, type); + else + checkNoBool(); + + if ((op == TOKaddass || op == TOKminass) && + e1->type->toBasetype()->ty == Tpointer && + e2->type->toBasetype()->isintegral()) + return scaleFactor(sc); + + typeCombine(sc); + if (arith) + { + e1 = e1->checkArithmetic(); + e2 = e2->checkArithmetic(); + } + if (bitwise || shift) + { + e1 = e1->checkIntegral(); + e2 = e2->checkIntegral(); + } + if (shift) + { + e2 = e2->castTo(sc, Type::tshiftcnt); + } + + // vectors + if (shift && (e1->type->toBasetype()->ty == Tvector || + e2->type->toBasetype()->ty == Tvector)) + return incompatibleTypes(); + + int isvector = type->toBasetype()->ty == Tvector; + + if (op == TOKmulass && isvector && !e2->type->isfloating() && + ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) + return incompatibleTypes(); // Only short[8] and ushort[8] work with multiply + + if (op == TOKdivass && isvector && !e1->type->isfloating()) + return incompatibleTypes(); + + if (op == TOKmodass && isvector) + return incompatibleTypes(); + + if (e1->op == TOKerror || e2->op == TOKerror) + return new ErrorExp(); + + return checkComplexOpAssign(sc); } #if DMDV2 @@ -6267,7 +6362,7 @@ DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident) Expression *DotIdExp::semantic(Scope *sc) { - // Indicate we didn't come from CallExp::semantic() + // Indicate we need to resolve by UFCS. return semantic(sc, 0); } @@ -6544,7 +6639,12 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) e = e->semantic(sc); return e; } - error("undefined identifier %s", toChars()); + s = ie->sds->search_correct(ident); + if (s) + error("undefined identifier '%s', did you mean '%s %s'?", + ident->toChars(), s->kind(), s->toChars()); + else + error("undefined identifier '%s'", ident->toChars()); return new ErrorExp(); } else if (t1b->ty == Tpointer && @@ -6561,23 +6661,26 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) return e->type->dotExp(sc, e, ident); } #if DMDV2 - else if ((t1b->ty == Tarray || t1b->ty == Tsarray || - t1b->ty == Taarray) && - ident != Id::sort && ident != Id::reverse && - ident != Id::dup && ident != Id::idup) + else if (!flag) { /* If ident is not a valid property, rewrite: * e1.ident * as: * .ident(e1) */ + if (e1->op == TOKtype || + t1b->ty == Tvoid || + (t1b->ty == Tarray || t1b->ty == Tsarray || t1b->ty == Taarray) && + (ident == Id::sort || ident == Id::reverse || ident == Id::dup || ident == Id::idup)) + { goto L2; + } + unsigned errors = global.startGagging(); Type *t1 = e1->type; e = e1->type->dotExp(sc, e1, ident); - if (global.endGagging(errors)) // if failed to find the property + if (global.endGagging(errors)) // if failed to find the property { e1->type = t1; // kludge to restore type - e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident); - e = new CallExp(loc, e, e1); + e = resolveUFCSProperties(sc, this); } e = e->semantic(sc); return e; @@ -6585,9 +6688,9 @@ Expression *DotIdExp::semantic(Scope *sc, int flag) #endif else { + L2: e = e1->type->dotExp(sc, e1, ident); - if (!(flag && e->op == TOKdotti)) // let CallExp::semantic() handle this - e = e->semantic(sc); + e = e->semantic(sc); return e; } } @@ -6874,23 +6977,41 @@ TemplateDeclaration *DotTemplateInstanceExp::getTempdecl(Scope *sc) } Expression *DotTemplateInstanceExp::semantic(Scope *sc) +{ + // Indicate we need to resolve by UFCS. + return semantic(sc, 0); +} +Expression *DotTemplateInstanceExp::semantic(Scope *sc, int flag) { #if LOGSEMANTIC printf("DotTemplateInstanceExp::semantic('%s')\n", toChars()); #endif - Expression *eleft; + + UnaExp::semantic(sc); Expression *e = new DotIdExp(loc, e1, ti->name); + + if (e1->op == TOKimport && ((ScopeExp *)e1)->sds->isModule()) + e = ((DotIdExp *)e)->semantic(sc, 1); + else + { + unsigned errors = global.startGagging(); + e = ((DotIdExp *)e)->semantic(sc, 1); + if (global.endGagging(errors) && !flag) + { + return resolveUFCSProperties(sc, this); + } + } + L1: - e = e->semantic(sc); if (e->op == TOKerror) return e; if (e->op == TOKdottd) { - if (global.errors) - return new ErrorExp(); // TemplateInstance::semantic() will fail anyway + if (ti->errors) + return new ErrorExp(); DotTemplateExp *dte = (DotTemplateExp *)e; TemplateDeclaration *td = dte->td; - eleft = dte->e1; + Expression *eleft = dte->e1; ti->tempdecl = td; if (ti->needsTypeInference(sc)) { @@ -6964,8 +7085,15 @@ L1: { TemplateExp *te = (TemplateExp *) de->e2; e = new DotTemplateExp(loc,de->e1,te->td); } + else + goto Lerr; + + e = e->semantic(sc); + if (e == de) + goto Lerr; goto L1; } +Lerr: error("%s isn't a template", e->toChars()); return new ErrorExp(); } @@ -7089,7 +7217,7 @@ Expression *CallExp::syntaxCopy() Expression *CallExp::resolveUFCS(Scope *sc) { - Expression *ethis = NULL; + Expression *e = NULL; DotIdExp *dotid; DotTemplateInstanceExp *dotti; Identifier *ident; @@ -7098,48 +7226,73 @@ Expression *CallExp::resolveUFCS(Scope *sc) { dotid = (DotIdExp *)e1; ident = dotid->ident; - ethis = dotid->e1 = dotid->e1->semantic(sc); - if (ethis->op == TOKdotexp) + e = dotid->e1 = dotid->e1->semantic(sc); + if (e->op == TOKdotexp) return NULL; - ethis = resolveProperties(sc, ethis); + e = resolveProperties(sc, e); } else if (e1->op == TOKdotti) { dotti = (DotTemplateInstanceExp *)e1; ident = dotti->ti->name; - ethis = dotti->e1 = dotti->e1->semantic(sc); - if (ethis->op == TOKdotexp) + e = dotti->e1 = dotti->e1->semantic(sc); + if (e->op == TOKdotexp) return NULL; - ethis = resolveProperties(sc, ethis); + e = resolveProperties(sc, e); } - if (ethis && ethis->type) + if (e && e->type) { + if (e->op == TOKtype || e->op == TOKimport) + return NULL; + //printf("resolveUCSS %s, e->op = %s\n", toChars(), Token::toChars(e->op)); AggregateDeclaration *ad; + Expression *esave = e; Lagain: - Type *tthis = ethis->type->toBasetype(); - if (tthis->ty == Tclass) - { - ad = ((TypeClass *)tthis)->sym; - if (search_function(ad, ident)) - return NULL; - goto L1; - } - else if (tthis->ty == Tstruct) - { - ad = ((TypeStruct *)tthis)->sym; - if (search_function(ad, ident)) - return NULL; - L1: - if (ad->aliasthis) + Type *t = e->type->toBasetype(); + if (t->ty == Tpointer) + { Type *tn = t->nextOf(); + if (tn->ty == Tclass || tn->ty == Tstruct) { - ethis = new DotIdExp(ethis->loc, ethis, ad->aliasthis->ident); - ethis = ethis->semantic(sc); - ethis = resolveProperties(sc, ethis); - goto Lagain; + e = new PtrExp(e->loc, e); + e = e->semantic(sc); + t = e->type->toBasetype(); } } - else if (tthis->ty == Taarray && e1->op == TOKdot) + if (t->ty == Tclass) + { + ad = ((TypeClass *)t)->sym; + goto L1; + } + else if (t->ty == Tstruct) + { + ad = ((TypeStruct *)t)->sym; + L1: + if (ad->search(loc, ident, 0)) + return NULL; + if (ad->aliasthis) + { + e = resolveAliasThis(sc, e); + goto Lagain; + } + if (ad->search(loc, Id::opDot, 0)) + { + e = new DotIdExp(e->loc, e, Id::opDot); + e = e->semantic(sc); + e = resolveProperties(sc, e); + goto Lagain; + } + if (ad->search(loc, Id::opDispatch, 0)) + return NULL; + e = esave; + goto Lshift; + } + else if ((t->isTypeBasic() && t->ty != Tvoid) || + t->ty == Tenum || t->ty == Tnull) + { + goto Lshift; + } + else if (t->ty == Taarray && e1->op == TOKdot) { if (ident == Id::remove) { @@ -7150,23 +7303,35 @@ Lagain: { error("expected key as argument to aa.remove()"); return new ErrorExp(); } + if (!e->type->isMutable()) + { const char *p = NULL; + if (e->type->isConst()) + p = "const"; + else if (e->type->isImmutable()) + p = "immutable"; + else + p = "inout"; + error("cannot remove key from %s associative array %s", p, e->toChars()); + return new ErrorExp(); + } Expression *key = arguments->tdata()[0]; key = key->semantic(sc); key = resolveProperties(sc, key); + + TypeAArray *taa = (TypeAArray *)t; + key = key->implicitCastTo(sc, taa->index); + if (!key->rvalue()) return new ErrorExp(); - TypeAArray *taa = (TypeAArray *)tthis; - key = key->implicitCastTo(sc, taa->index); - - return new RemoveExp(loc, ethis, key); + return new RemoveExp(loc, e, key); } else if (ident == Id::apply || ident == Id::applyReverse) { return NULL; } else - { TypeAArray *taa = (TypeAArray *)tthis; + { TypeAArray *taa = (TypeAArray *)t; assert(taa->ty == Taarray); StructDeclaration *sd = taa->getImpl(); Dsymbol *s = sd->search(0, ident, 2); @@ -7175,12 +7340,12 @@ Lagain: goto Lshift; } } - else if (tthis->ty == Tarray || tthis->ty == Tsarray) + else if (t->ty == Tarray || t->ty == Tsarray) { Lshift: if (!arguments) arguments = new Expressions(); - arguments->shift(ethis); + arguments->shift(e); if (e1->op == TOKdot) { /* Transform: @@ -7215,7 +7380,6 @@ Lshift: Expression *CallExp::semantic(Scope *sc) { - TypeFunction *tf; Type *t1; int istemp; Objects *targsi = NULL; // initial list of template arguments @@ -7281,7 +7445,10 @@ Expression *CallExp::semantic(Scope *sc) /* Attempt to instantiate ti. If that works, go with it. * If not, go with partial explicit specialization. */ + unsigned olderrors = global.errors; ti->semanticTiargs(sc); + if (olderrors != global.errors) + return new ErrorExp(); if (ti->needsTypeInference(sc)) { /* Go with partial explicit specialization @@ -7354,7 +7521,7 @@ Lagain: { if (e1->op == TOKdot) { DotIdExp *die = (DotIdExp *)e1; - e1 = die->semantic(sc, 1); + e1 = die->semantic(sc); /* Look for e1 having been rewritten to expr.opDispatch!(string) * We handle such earlier, so go back. * Note that in the rewrite, we carefully did not run semantic() on e1 @@ -7385,7 +7552,10 @@ Lagain: if (ve->var->storage_class & STClazy) { // lazy paramaters can be called without violating purity and safety - TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd, STCsafe | STCpure); + Type *tw = ve->var->type; + Type *tc = ve->var->type->substWildTo(MODconst); + TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd, STCsafe | STCpure); + (tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757 TypeDelegate *t = new TypeDelegate(tf); ve->type = t->semantic(loc, sc); } @@ -7514,6 +7684,17 @@ Lagain: if (e1->op == TOKerror) return e1; + // If there was an error processing any template argument, + // return an error without trying to resolve the template. + if (targsi && targsi->dim) + { + for (size_t k = 0; k < targsi->dim; k++) + { Object *o = targsi->tdata()[k]; + if (isError(o)) + return new ErrorExp(); + } + } + if (e1->op == TOKdotvar && t1->ty == Tfunction || e1->op == TOKdottd) { @@ -7651,8 +7832,8 @@ Lagain: // Base class constructor call ClassDeclaration *cd = NULL; - if (sc->func) - cd = sc->func->toParent()->isClassDeclaration(); + if (sc->func && sc->func->isThis()) + cd = sc->func->isThis()->isClassDeclaration(); if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration()) { error("super class constructor call must be in a constructor"); @@ -7697,8 +7878,8 @@ Lagain: // same class constructor call AggregateDeclaration *cd = NULL; - if (sc->func) - cd = sc->func->toParent()->isAggregateDeclaration(); + if (sc->func && sc->func->isThis()) + cd = sc->func->isThis()->isAggregateDeclaration(); if (!cd || !sc->func->isCtorDeclaration()) { error("constructor call must be in a constructor"); @@ -7783,38 +7964,18 @@ Lagain: } else if (t1->ty != Tfunction) { + TypeFunction *tf; + const char *p; if (t1->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)t1; assert(td->next->ty == Tfunction); tf = (TypeFunction *)(td->next); - if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) - { - if (sc->func->setImpure()) - error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars()); - } - if (sc->func && tf->trust <= TRUSTsystem) - { - if (sc->func->setUnsafe()) - error("safe function '%s' cannot call system delegate '%s'", sc->func->toChars(), e1->toChars()); - } - goto Lcheckargs; + p = "delegate"; } else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) { - Expression *e = new PtrExp(loc, e1); - t1 = ((TypePointer *)t1)->next; - if (sc->func && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug)) - { - if (sc->func->setImpure()) - error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars()); - } - if (sc->func && ((TypeFunction *)t1)->trust <= TRUSTsystem) - { - if (sc->func->setUnsafe()) - error("safe function '%s' cannot call system function pointer '%s'", sc->func->toChars(), e1->toChars()); - } - e->type = t1; - e1 = e; + tf = (TypeFunction *)(((TypePointer *)t1)->next); + p = "function pointer"; } else if (e1->op == TOKtemplate) { @@ -7841,6 +8002,50 @@ Lagain: { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars()); return new ErrorExp(); } + + if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug)) + { + if (sc->func->setImpure()) + error("pure function '%s' cannot call impure %s '%s'", sc->func->toChars(), p, e1->toChars()); + } + if (sc->func && tf->trust <= TRUSTsystem) + { + if (sc->func->setUnsafe()) + error("safe function '%s' cannot call system %s '%s'", sc->func->toChars(), p, e1->toChars()); + } + + if (!tf->callMatch(NULL, arguments)) + { + OutBuffer buf; + + buf.writeByte('('); + if (arguments) + { + HdrGenState hgs; + + argExpTypesToCBuffer(&buf, arguments, &hgs); + buf.writeByte(')'); + if (ethis) + ethis->type->modToBuffer(&buf); + } + else + buf.writeByte(')'); + + //printf("tf = %s, args = %s\n", tf->deco, arguments->tdata()[0]->type->deco); + ::error(loc, "%s %s %s is not callable using argument types %s", + p, e1->toChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), + buf.toChars()); + + return new ErrorExp(); + } + + if (t1->ty == Tpointer) + { + Expression *e = new PtrExp(loc, e1); + e->type = tf; + e1 = e; + } + t1 = tf; } else if (e1->op == TOKvar) { @@ -7878,10 +8083,7 @@ Lagain: t1 = f->type; } assert(t1->ty == Tfunction); - tf = (TypeFunction *)(t1); - -Lcheckargs: - assert(tf->ty == Tfunction); + TypeFunction *tf = (TypeFunction *)(t1); if (!arguments) arguments = new Expressions(); @@ -7916,11 +8118,14 @@ Lcheckargs: #if DMDV2 int CallExp::isLvalue() { -// if (type->toBasetype()->ty == Tstruct) -// return 1; Type *tb = e1->type->toBasetype(); if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref) + { + if (e1->op == TOKdotvar) + if (((DotVarExp *)e1)->var->isCtorDeclaration()) + return 0; return 1; // function returns a reference + } return 0; } #endif @@ -8075,10 +8280,20 @@ Expression *AddrExp::semantic(Scope *sc) * mark here that we took its address because castTo() * may not be called with an exact match. */ - f->toParent2()->isFuncDeclaration()) + f->isNested()) f->tookAddressOf++; if (f->isNested()) { + if (f->isFuncLiteralDeclaration()) + { + if (!f->FuncDeclaration::isNested()) + { /* Supply a 'null' for a this pointer if no this is available + */ + Expression *e = new DelegateExp(loc, new NullExp(loc, Type::tnull), f, ve->hasOverloads); + e = e->semantic(sc); + return e; + } + } Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads); e = e->semantic(sc); return e; @@ -8527,26 +8742,6 @@ Expression *CastExp::semantic(Scope *sc) Type *t1b = e1->type->toBasetype(); Type *tob = to->toBasetype(); - if (e1->op == TOKfunction && - (tob->ty == Tdelegate || tob->ty == Tpointer && tob->nextOf()->ty == Tfunction)) - { - FuncExp *fe = (FuncExp *)e1; - Expression *e = NULL; - if (e1->type == Type::tvoid) - { - e = fe->inferType(sc, tob); - } - else if (e1->type->ty == Tpointer && e1->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - tob->ty == Tdelegate) - { - if (fe->implicitConvTo(tob)) - e = fe->castTo(sc, tob); - } - if (e) - e1 = e->semantic(sc); - } - if (tob->ty == Tstruct && !tob->equals(t1b) ) @@ -8821,7 +9016,7 @@ Lagain: } if (ad->aliasthis) { - e1 = new DotIdExp(e1->loc, e1, ad->aliasthis->ident); + e1 = resolveAliasThis(sc, e1); goto Lagain; } goto Lerror; @@ -8923,7 +9118,7 @@ Lagain: } else { - error("string slice [%ju .. %ju] is out of bounds", i1, i2); + error("string slice [%llu .. %llu] is out of bounds", i1, i2); goto Lerr; } return e; @@ -9390,8 +9585,8 @@ Expression *IndexExp::semantic(Scope *sc) } else { - error("array index [%ju] is outside array bounds [0 .. %zu]", - index, length); + error("array index [%llu] is outside array bounds [0 .. %llu]", + index, (ulonglong)length); e = e1; } break; @@ -9473,10 +9668,18 @@ Expression *PostExp::semantic(Scope *sc) if (e) return e; - e1 = e1->modifiableLvalue(sc, e1); + if (e1->op == TOKslice) + { + const char *s = op == TOKplusplus ? "increment" : "decrement"; + error("cannot post-%s array slice '%s', use pre-%s instead", s, e1->toChars(), s); + return new ErrorExp(); + } + + if (e1->op != TOKarraylength) + e1 = e1->modifiableLvalue(sc, e1); Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tclass || t1->ty == Tstruct) + if (t1->ty == Tclass || t1->ty == Tstruct || e1->op == TOKarraylength) { /* Check for operator overloading, * but rewrite in terms of ++e instead of e++ */ @@ -9484,7 +9687,7 @@ Expression *PostExp::semantic(Scope *sc) /* If e1 is not trivial, take a reference to it */ Expression *de = NULL; - if (e1->op != TOKvar) + if (e1->op != TOKvar && e1->op != TOKarraylength) { // ref v = e1; Identifier *id = Lexer::uniqueId("__postref"); @@ -9607,6 +9810,7 @@ Expression *AssignExp::semantic(Scope *sc) Identifier *id = Id::index; ae->e1 = ae->e1->semantic(sc); + ae->e1 = resolveProperties(sc, ae->e1); Type *t1 = ae->e1->type->toBasetype(); if (t1->ty == Tstruct) { @@ -9672,18 +9876,17 @@ Expression *AssignExp::semantic(Scope *sc) // No opIndexAssign found yet, but there might be an alias this to try. if (ad && ad->aliasthis) - { Expression *at = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - at = at->semantic(sc); - Type *attype = at->type->toBasetype(); + { Expression *e = resolveAliasThis(sc, ae->e1); + Type *t = e->type->toBasetype(); - if (attype->ty == Tstruct) + if (t->ty == Tstruct) { - ad = ((TypeStruct *)attype)->sym; + ad = ((TypeStruct *)t)->sym; goto L1; } - else if (attype->ty == Tclass) + else if (t->ty == Tclass) { - ad = ((TypeClass *)attype)->sym; + ad = ((TypeClass *)t)->sym; goto L1; } } @@ -9731,31 +9934,66 @@ Expression *AssignExp::semantic(Scope *sc) // No opSliceAssign found yet, but there might be an alias this to try. if (ad && ad->aliasthis) - { Expression *at = new DotIdExp(loc, ae->e1, ad->aliasthis->ident); - at = at->semantic(sc); - Type *attype = at->type->toBasetype(); + { Expression *e = resolveAliasThis(sc, ae->e1); + Type *t = e->type->toBasetype(); - if (attype->ty == Tstruct) + if (t->ty == Tstruct) { - ad = ((TypeStruct *)attype)->sym; + ad = ((TypeStruct *)t)->sym; goto L2; } - else if (attype->ty == Tclass) + else if (t->ty == Tclass) { - ad = ((TypeClass *)attype)->sym; + ad = ((TypeClass *)t)->sym; goto L2; } } } - { - Expression *e = BinExp::semantic(sc); - if (e->op == TOKerror) - return e; - } - + e2 = e2->semantic(sc); + if (e2->op == TOKerror) + return new ErrorExp(); e2 = resolveProperties(sc, e2); + /* With UFCS, e.f = value + * Could mean: + * .f(e, value) + * or: + * .f(e) = value + */ + if (e1->op == TOKdotti) + { + DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)e1; + dti->e1 = dti->e1->semantic(sc); + if (!global.errors && dti->e1->type) + { + unsigned errors = global.startGagging(); + e1 = dti->semantic(sc, 1); + if (global.endGagging(errors) || e1->op == TOKerror) + { + return resolveUFCSProperties(sc, dti, e2); + } + } + } + else if (e1->op == TOKdot) + { + DotIdExp *die = (DotIdExp *)e1; + die->e1 = die->e1->semantic(sc); + if (!global.errors && die->e1->type) + { + unsigned errors = global.startGagging(); + e1 = die->semantic(sc, 1); + if (global.endGagging(errors) || e1->op == TOKerror) + { + return resolveUFCSProperties(sc, die, e2); + } + } + } +Le1: + e1 = e1->semantic(sc); + if (e1->op == TOKerror) + return new ErrorExp(); + /* We have f = value. * Could mean: * f(value) @@ -9897,7 +10135,8 @@ Ltupleassign: TypeTuple *tt = (TypeTuple *)e1->type; Identifier *id = Lexer::uniqueId("__tup"); - VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, new ExpInitializer(e2->loc, e2)); + ExpInitializer *ei = new ExpInitializer(e2->loc, e2); + VarDeclaration *v = new VarDeclaration(e2->loc, NULL, id, ei); v->storage_class = STCctfe | STCref | STCforeach; Expression *ve = new VarExp(e2->loc, v); ve->type = e2->type; @@ -9945,27 +10184,6 @@ Ltupleassign: Type *t1 = e1->type->toBasetype(); - if (t1->ty == Tdelegate || (t1->ty == Tpointer && t1->nextOf()->ty == Tfunction) - && e2->op == TOKfunction) - { - FuncExp *fe = (FuncExp *)e2; - if (e2->type == Type::tvoid) - { - e2 = fe->inferType(sc, t1); - } - else if (e2->type->ty == Tpointer && e2->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved && - t1->ty == Tdelegate) - { - if (fe->implicitConvTo(t1)) - e2 = fe->castTo(sc, t1); - } - if (!e2) - { error("cannot infer function literal type from %s", t1->toChars()); - e2 = new ErrorExp(); - } - } - /* If it is an assignment from a 'foreign' type, * check for operator overloading. */ @@ -10071,7 +10289,7 @@ Ltupleassign: } else if (t1->ty == Tclass) { // Disallow assignment operator overloads for same type - if (!e2->implicitConvTo(e1->type)) + if (op == TOKassign && !e2->implicitConvTo(e1->type)) { Expression *e = op_overload(sc); if (e) @@ -10107,6 +10325,7 @@ Ltupleassign: } } + e2 = e2->inferType(t1); if (!e2->rvalue()) return new ErrorExp(); @@ -10146,8 +10365,16 @@ Ltupleassign: } else #endif + // If it is a array, get the element type. Note that it may be + // multi-dimensional. + Type *telem = t1; + while (telem->ty == Tarray) + telem = telem->nextOf(); + + // Check for block assignment. If it is of type void[], void[][], etc, + // '= null' is the only allowable block assignment (Bug 7493) if (e1->op == TOKslice && - t1->nextOf() && + t1->nextOf() && (telem->ty != Tvoid || e2->op == TOKnull) && e2->implicitConvTo(t1->nextOf()) ) { // memset @@ -10229,112 +10456,6 @@ AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *AddAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - e = op_overload(sc); - if (e) - return e; - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - else - { - e1 = e1->modifiableLvalue(sc, e1); - } - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->nextOf()->equals(tb2->nextOf()) - ) - { - type = e1->type; - typeCombine(sc); - e = this; - } - else - { - e1->checkScalar(); - e1->checkNoBool(); - if (tb1->ty == Tpointer && tb2->isintegral()) - e = scaleFactor(sc); - else if (tb1->ty == Tbool) - { -#if 0 - // Need to rethink this - if (e1->op != TOKvar) - { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2 - VarDeclaration *v; - Expression *ea; - Expression *ex; - - Identifier *id = Lexer::uniqueId("__name"); - - v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); - v->semantic(sc); - if (!sc->insert(v)) - assert(0); - v->parent = sc->func; - - ea = new AddrExp(loc, e1); - ea = new AssignExp(loc, new VarExp(loc, v), ea); - - ex = new VarExp(loc, v); - ex = new PtrExp(loc, ex); - e = new AddExp(loc, ex, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, ex->syntaxCopy(), e); - - e = new CommaExp(loc, ea, e); - } - else -#endif - { // Rewrite e1+=e2 to e1=e1+e2 - // BUG: doesn't account for side effects in e1 - // BUG: other assignment operators for bits aren't handled at all - e = new AddExp(loc, e1, e2); - e = new CastExp(loc, e, e1->type); - e = new AssignExp(loc, e1->syntaxCopy(), e); - } - e = e->semantic(sc); - } - else - { - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexAddAssign(); - if (type->isreal() || type->isimaginary()) - { - assert(global.errors || e2->type->isfloating()); - e2 = e2->castTo(sc, e1->type); - } - e = this; - } - } - return e; -} - /************************************************************/ MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10342,54 +10463,6 @@ MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *MinAssignExp::semantic(Scope *sc) -{ Expression *e; - - if (type) - return this; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - if (e1->op == TOKslice) - { // T[] -= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - if (e1->type->ty == Tpointer && e2->type->isintegral()) - e = scaleFactor(sc); - else - { - e1 = e1->checkArithmetic(); - e2 = e2->checkArithmetic(); - checkComplexAddAssign(); - type = e1->type; - typeCombine(sc); - if (type->isreal() || type->isimaginary()) - { - assert(e2->type->isfloating()); - e2 = e2->castTo(sc, e1->type); - } - e = this; - } - return e; -} - /************************************************************/ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10398,10 +10471,9 @@ CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2) } Expression *CatAssignExp::semantic(Scope *sc) -{ Expression *e; - +{ //printf("CatAssignExp::semantic() %s\n", toChars()); - e = op_overload(sc); + Expression *e = op_overload(sc); if (e) return e; @@ -10415,14 +10487,17 @@ Expression *CatAssignExp::semantic(Scope *sc) } e1 = e1->modifiableLvalue(sc, e1); + if (e1->op == TOKerror) + return e1; Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); + Type *tb1next = tb1->nextOf(); + e2 = e2->inferType(tb1next); if (!e2->rvalue()) return new ErrorExp(); - Type *tb1next = tb1->nextOf(); + Type *tb2 = e2->type->toBasetype(); if ((tb1->ty == Tarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && @@ -10475,73 +10550,6 @@ MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *MulAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - -#if DMDV2 - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } -#endif - - if (e1->op == TOKslice) - { // T[] *= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexMulAssign(); - if (e2->type->isfloating()) - { - Type *t1 = e1->type; - Type *t2 = e2->type; - if (t1->isreal()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - e2 = e2->castTo(sc, t1); - } - } - else if (t1->isimaginary()) - { - if (t2->isimaginary() || t2->iscomplex()) - { - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(sc, t2); - } - } - } - else if (type->toBasetype()->ty == Tvector && - ((TypeVector *)type->toBasetype())->elementType()->size(loc) != 2) - { // Only short[8] and ushort[8] work with multiply - return incompatibleTypes(); - } - return this; -} - /************************************************************/ DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10549,73 +10557,6 @@ DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *DivAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - -#if DMDV2 - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } -#endif - - if (e1->op == TOKslice) - { // T[] /= ... - e = typeCombine(sc); - if (e->op == TOKerror) - return e; - type = e1->type; - return arrayOp(sc); - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); - checkComplexMulAssign(); - if (e2->type->isimaginary()) - { - Type *t1 = e1->type; - if (t1->isreal()) - { // x/iv = i(-x/v) - // Therefore, the result is 0 - e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1)); - e2->type = t1; - e = new AssignExp(loc, e1, e2); - e->type = t1; - return e; - } - else if (t1->isimaginary()) - { Type *t2; - - switch (t1->ty) - { - case Timaginary32: t2 = Type::tfloat32; break; - case Timaginary64: t2 = Type::tfloat64; break; - case Timaginary80: t2 = Type::tfloat80; break; - default: - assert(0); - } - e2 = e2->castTo(sc, t2); - Expression *e = new AssignExp(loc, e1, e2); - e->type = t1; - return e; - } - } - else if (type->toBasetype()->ty == Tvector && !e1->type->isfloating()) - return incompatibleTypes(); - return this; -} - /************************************************************/ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10623,20 +10564,6 @@ ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ModAssignExp::semantic(Scope *sc) -{ - if (!type) - { - Expression *e = op_overload(sc); - if (e) - return e; - - checkComplexMulAssign(); - return commonSemanticAssign(sc); - } - return this; -} - /************************************************************/ ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10644,35 +10571,6 @@ ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ShlAssignExp::semantic(Scope *sc) -{ Expression *e; - - //printf("ShlAssignExp::semantic()\n"); - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10680,33 +10578,6 @@ ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *ShrAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10714,33 +10585,6 @@ UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *UshrAssignExp::semantic(Scope *sc) -{ Expression *e; - - e = op_overload(sc); - if (e) - return e; - - if (e1->op == TOKarraylength) - { - e = ArrayLengthExp::rewriteOpAssign(this); - e = e->semantic(sc); - return e; - } - - e1 = e1->modifiableLvalue(sc, e1); - e1->checkScalar(); - e1->checkNoBool(); - type = e1->type; - if (e1->type->toBasetype()->ty == Tvector || e2->type->toBasetype()->ty == Tvector) - return incompatibleTypes(); - typeCombine(sc); - e1->checkIntegral(); - e2 = e2->checkIntegral(); - e2 = e2->castTo(sc, Type::tshiftcnt); - return this; -} - /************************************************************/ AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10748,11 +10592,6 @@ AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *AndAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /************************************************************/ OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10760,11 +10599,6 @@ OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *OrAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /************************************************************/ XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -10772,11 +10606,6 @@ XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2) { } -Expression *XorAssignExp::semantic(Scope *sc) -{ - return commonSemanticAssignIntegral(sc); -} - /***************** PowAssignExp *******************************************/ PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2) diff --git a/expression.h b/expression.h index 5febe4c9..7c91273d 100644 --- a/expression.h +++ b/expression.h @@ -79,7 +79,9 @@ int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow); TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s); void valueNoDtor(Expression *e); void modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1); - +#if DMDV2 +Expression *resolveAliasThis(Scope *sc, Expression *e); +#endif /* Interpreter: what form of return value expression is required? */ @@ -133,6 +135,7 @@ struct Expression : Object virtual MATCH implicitConvTo(Type *t); virtual IntRange getIntRange(); virtual Expression *castTo(Scope *sc, Type *t); + virtual Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); virtual void checkEscape(); virtual void checkEscapeRef(); virtual Expression *resolveLoc(Loc loc, Scope *sc); @@ -436,6 +439,7 @@ struct ArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); dt_t **toDt(dt_t **pdt); Expression *doInline(InlineDoState *ids); @@ -461,6 +465,7 @@ struct AssocArrayLiteralExp : Expression Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); @@ -473,6 +478,7 @@ struct StructLiteralExp : Expression // NULL entries for fields to skip Type *stype; // final type of result (can be different from sd's type) + Symbol *sinit; // if this is a defaultInitLiteral, this symbol contains the default initializer Symbol *sym; // back end symbol to initialize with literal size_t soffset; // offset from start of s int fillHoles; // fill alignment 'holes' with zero @@ -491,8 +497,6 @@ struct StructLiteralExp : Expression Expression *optimize(int result); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); dt_t **toDt(dt_t **pdt); - int isLvalue(); - Expression *toLvalue(Scope *sc, Expression *e); MATCH implicitConvTo(Type *t); int inlineCost3(InlineCostState *ics); @@ -654,18 +658,17 @@ struct FuncExp : Expression FuncLiteralDeclaration *fd; TemplateDeclaration *td; enum TOK tok; - Type *tded; - Scope *scope; + Type *treq; FuncExp(Loc loc, FuncLiteralDeclaration *fd, TemplateDeclaration *td = NULL); Expression *syntaxCopy(); Expression *semantic(Scope *sc); Expression *semantic(Scope *sc, Expressions *arguments); Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); + Expression *implicitCastTo(Scope *sc, Type *t); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); - Expression *inferType(Scope *sc, Type *t); - void setType(Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); elem *toElem(IRState *irs); @@ -778,8 +781,7 @@ struct BinExp : Expression int apply(apply_fp_t fp, void *param); Expression *semantic(Scope *sc); Expression *semanticp(Scope *sc); - void checkComplexMulAssign(); - void checkComplexAddAssign(); + Expression *checkComplexOpAssign(Scope *sc); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Expression *scaleFactor(Scope *sc); Expression *typeCombine(Scope *sc); @@ -787,6 +789,7 @@ struct BinExp : Expression int isunsigned(); Expression *incompatibleTypes(); void dump(int indent); + Expression *interpretCommon(InterState *istate, CtfeGoal goal, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, CtfeGoal goal, @@ -811,8 +814,7 @@ struct BinAssignExp : BinExp { } - Expression *commonSemanticAssign(Scope *sc); - Expression *commonSemanticAssignIntegral(Scope *sc); + Expression *semantic(Scope *sc); Expression *op_overload(Scope *sc); @@ -898,6 +900,7 @@ struct DotTemplateInstanceExp : UnaExp Expression *syntaxCopy(); TemplateDeclaration *getTempdecl(Scope *sc); Expression *semantic(Scope *sc); + Expression *semantic(Scope *sc, int flag); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void dump(int indent); }; @@ -1248,7 +1251,7 @@ struct ConstructExp : AssignExp struct op##AssignExp : BinAssignExp \ { \ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ - Expression *semantic(Scope *sc); \ + S(Expression *semantic(Scope *sc);) \ Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue); \ X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ X(Expression *buildArrayLoop(Parameters *fparams);) \ @@ -1259,6 +1262,7 @@ struct op##AssignExp : BinAssignExp \ }; #define X(a) a +#define S(a) ASSIGNEXP(Add) ASSIGNEXP(Min) ASSIGNEXP(Mul) @@ -1267,17 +1271,28 @@ ASSIGNEXP(Mod) ASSIGNEXP(And) ASSIGNEXP(Or) ASSIGNEXP(Xor) +#undef S + #if DMDV2 +#define S(a) a ASSIGNEXP(Pow) +#undef S #endif + +#undef S #undef X #define X(a) +#define S(a) ASSIGNEXP(Shl) ASSIGNEXP(Shr) ASSIGNEXP(Ushr) +#undef S + +#define S(a) a ASSIGNEXP(Cat) +#undef S #undef X #undef ASSIGNEXP @@ -1580,7 +1595,7 @@ struct EqualExp : BinExp elem *toElem(IRState *irs); }; -// === and !=== +// is and !is struct IdentityExp : BinExp { @@ -1613,6 +1628,7 @@ struct CondExp : BinExp void toCBuffer(OutBuffer *buf, HdrGenState *hgs); MATCH implicitConvTo(Type *t); Expression *castTo(Scope *sc, Type *t); + Expression *inferType(Type *t, int flag = 0, TemplateParameters *tparams = NULL); Expression *doInline(InlineDoState *ids); Expression *inlineScan(InlineScanState *iss); diff --git a/func.c b/func.c index 39ba3aba..94ed87fe 100644 --- a/func.c +++ b/func.c @@ -1,5 +1,5 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -307,13 +307,6 @@ void FuncDeclaration::semantic(Scope *sc) } #endif -#ifdef IN_GCC - { - AggregateDeclaration *ad = parent->isAggregateDeclaration(); - if (ad) - ad->methods.push(this); - } -#endif sd = parent->isStructDeclaration(); if (sd) { @@ -434,6 +427,9 @@ void FuncDeclaration::semantic(Scope *sc) //printf("\tnot virtual\n"); goto Ldone; } + // Suppress further errors if the return type is an error + if (type->nextOf() == Type::terror) + goto Ldone; /* Find index of existing function in base class's vtbl[] to override * (the index will be the same as in cd's current vtbl[]) @@ -445,6 +441,7 @@ void FuncDeclaration::semantic(Scope *sc) switch (vi) { case -1: + Lintro: /* Didn't find one, so * This is an 'introducing' function which gets a new * slot in the vtbl[]. @@ -481,7 +478,7 @@ void FuncDeclaration::semantic(Scope *sc) break; case -2: // can't determine because of fwd refs - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; @@ -500,9 +497,12 @@ void FuncDeclaration::semantic(Scope *sc) FuncDeclaration *fdc = ((Dsymbol *)cd->vtbl.data[vi])->isFuncDeclaration(); if (fdc->toParent() == parent) { + // fdc overrides fdv exactly, then this introduces new function. + if (fdc->type->mod == fdv->type->mod && this->type->mod != fdv->type->mod) + goto Lintro; + // If both are mixins, then error. // If either is not, the one that is not overrides the other. - if (this->parent->isClassDeclaration() && fdc->parent->isClassDeclaration()) error("multiple overrides of same function"); @@ -566,7 +566,7 @@ void FuncDeclaration::semantic(Scope *sc) break; case -2: - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; @@ -602,7 +602,7 @@ void FuncDeclaration::semantic(Scope *sc) { // any error in isBaseOf() is a forward reference error, so we bail out global.errors = errors; - cd->sizeok = 2; // can't finish due to forward reference + cd->sizeok = SIZEOKfwd; // can't finish due to forward reference Module::dprogress = dprogress_save; return; } @@ -613,9 +613,14 @@ void FuncDeclaration::semantic(Scope *sc) } if (ti) { - if (tintro && !tintro->equals(ti)) + if (tintro) { - error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); + if (!tintro->nextOf()->equals(ti->nextOf()) && + !tintro->nextOf()->isBaseOf(ti->nextOf(), NULL) && + !ti->nextOf()->isBaseOf(tintro->nextOf(), NULL)) + { + error("incompatible covariant types %s and %s", tintro->toChars(), ti->toChars()); + } } tintro = ti; } @@ -626,7 +631,11 @@ void FuncDeclaration::semantic(Scope *sc) if (!doesoverride && isOverride()) { - error("does not override any function"); + Dsymbol *s = cd->search_correct(ident); + if (s) + error("does not override any function, did you mean '%s'", s->toPrettyChars()); + else + error("does not override any function"); } L2: ; @@ -836,7 +845,7 @@ void FuncDeclaration::semantic3(Scope *sc) //printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc); assert(0); } - //printf("FuncDeclaration::semantic3('%s.%s', sc = %p, loc = %s)\n", parent->toChars(), toChars(), sc, loc.toChars()); + //printf("FuncDeclaration::semantic3('%s.%s', %p, sc = %p, loc = %s)\n", parent->toChars(), toChars(), this, sc, loc.toChars()); //fflush(stdout); //printf("storage class = x%x %x\n", sc->stc, storage_class); //{ static int x; if (++x == 2) *(char*)0=0; } @@ -925,6 +934,9 @@ void FuncDeclaration::semantic3(Scope *sc) } else assert(!isNested() || sc->intypeof); // can't be both member and nested +#if IN_GCC + ad->methods.push(this); +#endif } vthis = declareThis(sc2, ad); @@ -936,6 +948,7 @@ void FuncDeclaration::semantic3(Scope *sc) #else Type *t; +#ifndef IN_GCC if (global.params.is64bit) { // Declare save area for varargs registers Type *t = new TypeIdentifier(loc, Id::va_argsave_t); @@ -953,6 +966,7 @@ void FuncDeclaration::semantic3(Scope *sc) v_argsave->parent = this; } } +#endif if (f->linkage == LINKd) { // Declare _arguments[] @@ -1241,7 +1255,7 @@ void FuncDeclaration::semantic3(Scope *sc) } } - if (inferRetType || f->retStyle() != RETstack) + if (!inferRetType && f->retStyle() != RETstack) nrvo_can = 0; fbody = fbody->semantic(sc2); @@ -1763,11 +1777,13 @@ int FuncDeclaration::equals(Object *o) Dsymbol *s = isDsymbol(o); if (s) { - FuncDeclaration *fd = s->isFuncDeclaration(); - if (fd) + FuncDeclaration *fd1 = this->toAliasFunc(); + FuncDeclaration *fd2 = s->isFuncDeclaration(); + if (fd2) { - return toParent()->equals(fd->toParent()) && - ident->equals(fd->ident) && type->equals(fd->type); + fd2 = fd2->toAliasFunc(); + return fd1->toParent()->equals(fd2->toParent()) && + fd1->ident->equals(fd2->ident) && fd1->type->equals(fd2->type); } } return FALSE; @@ -1983,6 +1999,8 @@ int FuncDeclaration::overrides(FuncDeclaration *fd) int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) { FuncDeclaration *mismatch = NULL; + StorageClass mismatchstc = 0; + int mismatchvi = -1; int bestvi = -1; for (int vi = 0; vi < dim; vi++) { @@ -1992,7 +2010,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) if (type->equals(fdv->type)) // if exact match return vi; // no need to look further - int cov = type->covariant(fdv->type); + StorageClass stc = 0; + int cov = type->covariant(fdv->type, &stc); //printf("\tbaseclass cov = %d\n", cov); switch (cov) { @@ -2004,6 +2023,8 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) break; // keep looking for an exact match case 2: + mismatchvi = vi; + mismatchstc = stc; mismatch = fdv; // overrides, but is not covariant break; // keep looking for an exact match @@ -2020,8 +2041,15 @@ int FuncDeclaration::findVtblIndex(Dsymbols *vtbl, int dim) //type->print(); //mismatch->type->print(); //printf("%s %s\n", type->deco, mismatch->type->deco); - error("of type %s overrides but is not covariant with %s of type %s", - type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); + //printf("stc = %llx\n", mismatchstc); + if (mismatchstc) + { // Fix it by modifying the type to add the storage classes + type = type->addStorageClass(mismatchstc); + bestvi = mismatchvi; + } + else + error("of type %s overrides but is not covariant with %s of type %s", + type->toChars(), mismatch->toPrettyChars(), mismatch->type->toChars()); } return bestvi; } @@ -2108,8 +2136,21 @@ int overloadApply(FuncDeclaration *fstart, if (fa) { - if (overloadApply(fa->funcalias, fp, param)) - return 1; + if (fa->hasOverloads) + { + if (overloadApply(fa->funcalias, fp, param)) + return 1; + } + else + { + f = fa->toAliasFunc(); + if (!f) + { d->error("is aliased to a function"); + break; + } + if ((*fp)(param, f)) + return 1; + } next = fa->overnext; } else @@ -2457,7 +2498,7 @@ MATCH FuncDeclaration::leastAsSpecialized(FuncDeclaration *g) e->type = p->type; } else - e = p->type->defaultInit(); + e = p->type->defaultInitLiteral(0); args.tdata()[u] = e; } @@ -2771,6 +2812,11 @@ int FuncDeclaration::isOverloadable() return 1; // functions can be overloaded } +int FuncDeclaration::hasOverloads() +{ + return overnext != NULL; +} + enum PURE FuncDeclaration::isPure() { //printf("FuncDeclaration::isPure() '%s'\n", toChars()); @@ -2828,6 +2874,14 @@ int FuncDeclaration::isSafe() return ((TypeFunction *)type)->trust == TRUSTsafe; } +bool FuncDeclaration::isSafeBypassingInference() +{ + if (flags & FUNCFLAGsafetyInprocess) + return false; + else + return isSafe(); +} + int FuncDeclaration::isTrusted() { assert(type->ty == Tfunction); @@ -2858,21 +2912,16 @@ bool FuncDeclaration::setUnsafe() int FuncDeclaration::isNested() { - //if (!toParent()) - //printf("FuncDeclaration::isNested('%s') parent=%p\n", toChars(), parent); - //printf("\ttoParent2() = '%s'\n", toParent2()->toChars()); - return ((storage_class & STCstatic) == 0) && - (toParent2()->isFuncDeclaration() != NULL); + FuncDeclaration *f = toAliasFunc(); + //printf("\ttoParent2() = '%s'\n", f->toParent2()->toChars()); + return ((f->storage_class & STCstatic) == 0) && + (f->toParent2()->isFuncDeclaration() != NULL); } int FuncDeclaration::needThis() { //printf("FuncDeclaration::needThis() '%s'\n", toChars()); - int i = isThis() != NULL; - //printf("\t%d\n", i); - if (!i && isFuncAliasDeclaration()) - i = ((FuncAliasDeclaration *)this)->funcalias->needThis(); - return i; + return toAliasFunc()->isThis() != NULL; } int FuncDeclaration::addPreInvariant() @@ -3114,12 +3163,24 @@ Parameters *FuncDeclaration::getParameters(int *pvarargs) // Used as a way to import a set of functions from another scope into this one. -FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias) +FuncAliasDeclaration::FuncAliasDeclaration(FuncDeclaration *funcalias, int hasOverloads) : FuncDeclaration(funcalias->loc, funcalias->endloc, funcalias->ident, funcalias->storage_class, funcalias->type) { assert(funcalias != this); this->funcalias = funcalias; + + this->hasOverloads = hasOverloads; + if (hasOverloads) + { + if (FuncAliasDeclaration *fad = funcalias->isFuncAliasDeclaration()) + this->hasOverloads = fad->hasOverloads; + } + else + { // for internal use + assert(!funcalias->isFuncAliasDeclaration()); + this->hasOverloads = 0; + } } const char *FuncAliasDeclaration::kind() @@ -3127,6 +3188,11 @@ const char *FuncAliasDeclaration::kind() return "function alias"; } +FuncDeclaration *FuncAliasDeclaration::toAliasFunc() +{ + return funcalias->toAliasFunc(); +} + /****************************** FuncLiteralDeclaration ************************/ @@ -3574,7 +3640,7 @@ int StaticCtorDeclaration::addPostInvariant() void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - if (hgs->hdrgen) + if (hgs->hdrgen && !hgs->tpltMember) { buf->writestring("static this();"); buf->writenl(); return; diff --git a/glue.c b/glue.c index 9c223223..726d574b 100644 --- a/glue.c +++ b/glue.c @@ -674,6 +674,12 @@ void FuncDeclaration::toObjFile(int multiobj) irs.shidden = shidden; this->shidden = shidden; } + else + { // Register return style cannot make nrvo. + // Auto functions keep the nrvo_can flag up to here, + // so we should eliminate it before entering backend. + nrvo_can = 0; + } if (vthis) { @@ -969,10 +975,32 @@ void FuncDeclaration::toObjFile(int multiobj) for (size_t i = 0; i < irs.deferToObj->dim; i++) { - Dsymbol *s = irs.deferToObj->tdata()[i]; + Dsymbol *s = (*irs.deferToObj)[i]; + + FuncDeclaration *fd = s->isFuncDeclaration(); + if (fd) + { FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration(); + if (fdp && fdp->semanticRun < PASSobj) + { /* Bugzilla 7595 + * FuncDeclaration::buildClosure() relies on nested functions + * being toObjFile'd after the outer function. Otherwise, the + * v->offset's for the closure variables are wrong. + * So, defer fd until after fdp is done. + */ + fdp->deferred.push(fd); + continue; + } + } + s->toObjFile(0); } + for (size_t i = 0; i < deferred.dim; i++) + { + FuncDeclaration *fd = deferred[i]; + fd->toObjFile(0); + } + #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS // A hack to get a pointer to this function put in the .dtors segment if (ident && memcmp(ident->toChars(), "_STD", 4) == 0) @@ -1048,9 +1076,6 @@ unsigned Type::totym() case Tident: case Ttypeof: -#ifdef DEBUG - printf("ty = %d, '%s'\n", ty, toChars()); -#endif error(0, "forward reference of %s", toChars()); t = TYint; break; diff --git a/iasm.c b/iasm.c index 6973bf7f..00d12b7e 100644 --- a/iasm.c +++ b/iasm.c @@ -459,7 +459,7 @@ typedef struct opnd opflag_t usFlags; Dsymbol *s; targ_llong disp; - long double real; + longdouble real; Type *ptype; ASM_JUMPTYPE ajt; } OPND; @@ -638,6 +638,11 @@ RETRY: if (I64 && (pop->ptb.pptb0->usFlags & _i64_bit)) asmerr( EM_invalid_64bit_opcode, asm_opstr(pop)); // illegal opcode in 64bit mode + if ((asmstate.ucItype == ITopt || + asmstate.ucItype == ITfloat) && + usNumops != 0) + goto PARAM_ERROR; + ptbRet = pop->ptb; goto RETURN_IT; @@ -674,16 +679,23 @@ RETRY: 0)) && popnd1->disp == table1->usFlags) break; - if ((asmstate.ucItype == ITopt || - asmstate.ucItype == ITfloat) && - !usNumops && - !table1->usOp1) + if (asmstate.ucItype == ITopt || + asmstate.ucItype == ITfloat) { - if (usNumops > 1) - goto PARAM_ERROR; - break; + switch (usNumops) + { + case 0: + if (!table1->usOp1) + goto Lfound1; + break; + case 1: + break; + default: + goto PARAM_ERROR; + } } } + Lfound1: if (table1->usOpcode == ASM_END) { #ifdef DEBUG @@ -1293,7 +1305,7 @@ STATIC code *asm_emit(Loc loc, unsigned char *puc; unsigned usDefaultseg; code *pc = NULL; - OPND *popndTmp; + OPND *popndTmp = NULL; ASM_OPERAND_TYPE aoptyTmp; unsigned uSizemaskTmp; REG *pregSegment; @@ -2123,18 +2135,12 @@ code *asm_genloc(Loc loc, code *c) STATIC void asmerr(int errnum, ...) { const char *format; - const char *p = asmstate.loc.toChars(); - if (*p) - printf("%s: ", p); - format = asmerrmsgs[errnum]; va_list ap; va_start(ap, errnum); - vprintf(format, ap); + verror(asmstate.loc, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); longjmp(asmstate.env,1); } @@ -2143,18 +2149,11 @@ STATIC void asmerr(int errnum, ...) STATIC void asmerr(const char *format, ...) { - const char *p = asmstate.loc.toChars(); - if (*p) - printf("%s: ", p); - va_list ap; va_start(ap, format); - vprintf(format, ap); + verror(asmstate.loc, format, ap); va_end(ap); - printf("\n"); - fflush(stdout); - longjmp(asmstate.env,1); } diff --git a/identifier.c b/identifier.c index 178ae12b..825d78b6 100644 --- a/identifier.c +++ b/identifier.c @@ -94,7 +94,7 @@ Identifier *Identifier::generateId(const char *prefix, size_t i) { OutBuffer buf; buf.writestring(prefix); - buf.printf("%zu", i); + buf.printf("%llu", (ulonglong)i); char *id = buf.toChars(); buf.data = NULL; diff --git a/idgen.c b/idgen.c index 075c73d0..0f57821d 100644 --- a/idgen.c +++ b/idgen.c @@ -271,7 +271,7 @@ Msgtable msgtable[] = { "getmembers", "getMembers" }, // Special functions - { "alloca" }, + { "__alloca", "alloca" }, // has to be mapped because alloca is #defined if _MSC_VER { "main" }, { "WinMain" }, { "DllMain" }, diff --git a/import.c b/import.c index bd43af90..f4582c23 100644 --- a/import.c +++ b/import.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -77,13 +77,11 @@ Dsymbol *Import::syntaxCopy(Dsymbol *s) { assert(!s); - Import *si; - - si = new Import(loc, packages, id, aliasId, isstatic); + Import *si = new Import(loc, packages, id, aliasId, isstatic); for (size_t i = 0; i < names.dim; i++) { - si->addAlias(names.tdata()[i], aliases.tdata()[i]); + si->addAlias(names[i], aliases[i]); } return si; @@ -95,7 +93,16 @@ void Import::load(Scope *sc) // See if existing module DsymbolTable *dst = Package::resolve(packages, NULL, &pkg); - +#if TARGET_NET //dot net needs modules and packages with same name +#else + if (pkg && pkg->isModule()) + { + ::error(loc, "can only import from a module, not from a member of module %s. Did you mean `import %s : %s`?", + pkg->toChars(), pkg->toPrettyChars(), id->toChars()); + mod = pkg->isModule(); // Error recovery - treat as import of that module + return; + } +#endif Dsymbol *s = dst->lookup(id); if (s) { @@ -105,7 +112,8 @@ void Import::load(Scope *sc) if (s->isModule()) mod = (Module *)s; else - error("package and module have the same name"); + ::error(loc, "can only import from a module, not from package %s.%s", + pkg->toPrettyChars(), id->toChars()); #endif } @@ -113,10 +121,13 @@ void Import::load(Scope *sc) { // Load module mod = Module::load(loc, packages, id); - dst->insert(id, mod); // id may be different from mod->ident, - // if so then insert alias - if (!mod->importedFrom) - mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; + if (mod) + { + dst->insert(id, mod); // id may be different from mod->ident, + // if so then insert alias + if (!mod->importedFrom) + mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; + } } if (!pkg) pkg = mod; @@ -167,7 +178,8 @@ void Import::semantic(Scope *sc) // Load if not already done so if (!mod) { load(sc); - mod->importAll(0); + if (mod) + mod->importAll(0); } if (mod) @@ -217,18 +229,26 @@ void Import::semantic(Scope *sc) sc->protection = PROTpublic; #endif for (size_t i = 0; i < aliasdecls.dim; i++) - { Dsymbol *s = aliasdecls.tdata()[i]; + { Dsymbol *s = aliasdecls[i]; //printf("\tImport alias semantic('%s')\n", s->toChars()); - if (!mod->search(loc, names.tdata()[i], 0)) - error("%s not found", (names.tdata()[i])->toChars()); - - s->semantic(sc); + if (mod->search(loc, names[i], 0)) + s->semantic(sc); + else + { + s = mod->search_correct(names[i]); + if (s) + mod->error(loc, "import '%s' not found, did you mean '%s %s'?", names[i]->toChars(), s->kind(), s->toChars()); + else + mod->error(loc, "import '%s' not found", names[i]->toChars()); + } } sc = sc->pop(); } - if (global.params.moduleDeps != NULL) + if (global.params.moduleDeps != NULL && + // object self-imports itself, so skip that (Bugzilla 7547) + !(id == Id::object && sc->module->ident == Id::object)) { /* The grammar of the file is: * ImportDeclaration @@ -259,7 +279,7 @@ void Import::semantic(Scope *sc) { for (size_t i = 0; i < packages->dim; i++) { - Identifier *pid = packages->tdata()[i]; + Identifier *pid = (*packages)[i]; ob->printf("%s.", pid->toChars()); } } @@ -279,8 +299,8 @@ void Import::semantic(Scope *sc) else ob->writebyte(','); - Identifier *name = names.tdata()[i]; - Identifier *alias = aliases.tdata()[i]; + Identifier *name = names[i]; + Identifier *alias = aliases[i]; if (!alias) { @@ -367,8 +387,15 @@ Dsymbol *Import::search(Loc loc, Identifier *ident, int flags) int Import::overloadInsert(Dsymbol *s) { - // Allow multiple imports of the same name - return s->isImport() != NULL; + /* Allow multiple imports with the same package base, but disallow + * alias collisions (Bugzilla 5412). + */ + assert(ident && ident == s->ident); + Import *imp; + if (!aliasId && (imp = s->isImport()) != NULL && !imp->aliasId) + return TRUE; + else + return FALSE; } void Import::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/init.c b/init.c index d18c434c..768c6137 100644 --- a/init.c +++ b/init.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -53,10 +53,10 @@ Initializers *Initializer::arraySyntaxCopy(Initializers *ai) a = new Initializers(); a->setDim(ai->dim); for (size_t i = 0; i < a->dim; i++) - { Initializer *e = ai->tdata()[i]; + { Initializer *e = (*ai)[i]; e = e->syntaxCopy(); - a->tdata()[i] = e; + (*a)[i] = e; } } return a; @@ -125,11 +125,11 @@ Initializer *StructInitializer::syntaxCopy() ai->value.setDim(value.dim); for (size_t i = 0; i < field.dim; i++) { - ai->field.tdata()[i] = field.tdata()[i]; + ai->field[i] = field[i]; - Initializer *init = value.tdata()[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.tdata()[i] = init; + ai->value[i] = init; } return ai; } @@ -161,8 +161,8 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) if (((StructDeclaration *)ad)->isnested) nfields--; for (size_t i = 0; i < field.dim; i++) { - Identifier *id = field.tdata()[i]; - Initializer *val = value.tdata()[i]; + Identifier *id = field[i]; + Initializer *val = value[i]; Dsymbol *s; VarDeclaration *v; @@ -177,7 +177,7 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) } else { - s = ad->fields.tdata()[fieldi]; + s = ad->fields[fieldi]; } } else @@ -186,7 +186,12 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) s = ad->search(loc, id, 0); if (!s) { - error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); + s = ad->search_correct(id); + if (s) + error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", + id->toChars(), t->toChars(), s->kind(), s->toChars()); + else + error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); errors = 1; continue; } @@ -202,15 +207,15 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) errors = 1; break; } - if (s == ad->fields.tdata()[fieldi]) + if (s == ad->fields[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type, needInterpret); - value.tdata()[i] = val; - vars.tdata()[i] = v; + value[i] = val; + vars[i] = v; } else { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); @@ -271,12 +276,12 @@ Expression *StructInitializer::toExpression() elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) { - elements->tdata()[i] = NULL; + (*elements)[i] = NULL; } unsigned fieldi = 0; for (size_t i = 0; i < value.dim; i++) { - Identifier *id = field.tdata()[i]; + Identifier *id = field[i]; if (id) { Dsymbol * s = ad->search(loc, id, 0); @@ -295,7 +300,7 @@ Expression *StructInitializer::toExpression() s->error("is not a per-instance initializable field"); goto Lno; } - if (s == ad->fields.tdata()[fieldi]) + if (s == ad->fields[fieldi]) break; } } @@ -303,18 +308,18 @@ Expression *StructInitializer::toExpression() { error(loc, "too many initializers for '%s'", ad->toChars()); goto Lno; } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); if (!ex) goto Lno; - if (elements->tdata()[fieldi]) + if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", - ad->fields.tdata()[fieldi]->toChars()); + ad->fields[fieldi]->toChars()); goto Lno; } - elements->tdata()[fieldi] = ex; + (*elements)[fieldi] = ex; ++fieldi; } // Now, fill in any missing elements with default initializers. @@ -322,20 +327,20 @@ Expression *StructInitializer::toExpression() offset = 0; for (size_t i = 0; i < elements->dim; ) { - VarDeclaration * vd = ad->fields.tdata()[i]->isVarDeclaration(); + VarDeclaration * vd = ad->fields[i]->isVarDeclaration(); //printf("test2 [%d] : %s %d %d\n", i, vd->toChars(), (int)offset, (int)vd->offset); if (vd->offset < offset) { // Only the first field of a union can have an initializer - if (elements->tdata()[i]) + if ((*elements)[i]) goto Lno; } else { - if (!elements->tdata()[i]) + if (!(*elements)[i]) // Default initialize - elements->tdata()[i] = vd->type->defaultInit(); + (*elements)[i] = vd->type->defaultInit(); } offset = vd->offset + vd->type->size(); i++; @@ -343,15 +348,15 @@ Expression *StructInitializer::toExpression() int unionSize = ad->numFieldsInUnion(i); if (unionSize == 1) { // Not a union -- default initialize if missing - if (!elements->tdata()[i]) - elements->tdata()[i] = vd->type->defaultInit(); + if (!(*elements)[i]) + (*elements)[i] = vd->type->defaultInit(); } else { // anonymous union -- check for errors int found = -1; // index of the first field with an initializer - for (int j = i; j < i + unionSize; ++j) + for (size_t j = i; j < i + unionSize; ++j) { - if (!elements->tdata()[j]) + if (!(*elements)[j]) continue; if (found >= 0) { @@ -392,13 +397,13 @@ void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i > 0) buf->writebyte(','); - Identifier *id = field.tdata()[i]; + Identifier *id = field[i]; if (id) { buf->writestring(id->toChars()); buf->writebyte(':'); } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -425,14 +430,14 @@ Initializer *ArrayInitializer::syntaxCopy() ai->index.setDim(index.dim); ai->value.setDim(value.dim); for (size_t i = 0; i < ai->value.dim; i++) - { Expression *e = index.tdata()[i]; + { Expression *e = index[i]; if (e) e = e->syntaxCopy(); - ai->index.tdata()[i] = e; + ai->index[i] = e; - Initializer *init = value.tdata()[i]; + Initializer *init = value[i]; init = init->syntaxCopy(); - ai->value.tdata()[i] = init; + ai->value[i] = init; } return ai; } @@ -471,17 +476,17 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) length = 0; for (i = 0; i < index.dim; i++) { - Expression *idx = index.tdata()[i]; + Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); - index.tdata()[i] = idx; + index[i] = idx; length = idx->toInteger(); } - Initializer *val = value.tdata()[i]; + Initializer *val = value[i]; val = val->semantic(sc, t->nextOf(), needInterpret); - value.tdata()[i] = val; + value[i] = val; length++; if (length == 0) { error(loc, "array dimension overflow"); @@ -495,7 +500,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int needInterpret) dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { - error(loc, "array initializer has %u elements, but array length is %jd", dim, edim); + error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } @@ -549,8 +554,8 @@ Expression *ArrayInitializer::toExpression() edim = value.dim; for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index.tdata()[i]) - j = index.tdata()[i]->toInteger(); + if (index[i]) + j = index[i]->toInteger(); if (j >= edim) edim = j + 1; } @@ -561,10 +566,10 @@ Expression *ArrayInitializer::toExpression() elements->zero(); for (size_t i = 0, j = 0; i < value.dim; i++, j++) { - if (index.tdata()[i]) - j = (index.tdata()[i])->toInteger(); + if (index[i]) + j = (index[i])->toInteger(); assert(j < edim); - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; Expression *ex = iz->toExpression(); @@ -572,7 +577,7 @@ Expression *ArrayInitializer::toExpression() { goto Lno; } - elements->tdata()[j] = ex; + (*elements)[j] = ex; } /* Fill in any missing elements with the default initializer @@ -581,13 +586,13 @@ Expression *ArrayInitializer::toExpression() Expression *init = NULL; for (size_t i = 0; i < edim; i++) { - if (!elements->tdata()[i]) + if (!(*elements)[i]) { if (!type) goto Lno; if (!init) init = ((TypeNext *)t)->next->defaultInit(); - elements->tdata()[i] = init; + (*elements)[i] = init; } } @@ -618,18 +623,18 @@ Expression *ArrayInitializer::toAssocArrayLiteral() for (size_t i = 0; i < value.dim; i++) { - e = index.tdata()[i]; + e = index[i]; if (!e) goto Lno; - keys->tdata()[i] = e; + (*keys)[i] = e; - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (!iz) goto Lno; e = iz->toExpression(); if (!e) goto Lno; - values->tdata()[i] = e; + (*values)[i] = e; } e = new AssocArrayLiteralExp(loc, keys, values); return e; @@ -645,7 +650,7 @@ int ArrayInitializer::isAssociativeArray() { for (size_t i = 0; i < value.dim; i++) { - if (index.tdata()[i]) + if (index[i]) return 1; } return 0; @@ -707,13 +712,13 @@ void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i > 0) buf->writebyte(','); - Expression *ex = index.tdata()[i]; + Expression *ex = index[i]; if (ex) { ex->toCBuffer(buf, hgs); buf->writebyte(':'); } - Initializer *iz = value.tdata()[i]; + Initializer *iz = value[i]; if (iz) iz->toCBuffer(buf, hgs); } @@ -778,10 +783,8 @@ bool hasNonConstPointers(Expression *e) bool arrayHasNonConstPointers(Expressions *elems) { for (size_t i = 0; i < elems->dim; i++) - { - if (!elems->tdata()[i]) - continue; - if (hasNonConstPointers(elems->tdata()[i])) + { Expression *e = (*elems)[i]; + if (e && hasNonConstPointers(e)) return true; } return false; @@ -802,7 +805,7 @@ Initializer *ExpInitializer::semantic(Scope *sc, Type *t, int needInterpret) return this; // Failed, suppress duplicate error messages if (exp->op == TOKtype) - error("initializer must be an expression, not '%s'", exp->toChars()); + exp->error("initializer must be an expression, not '%s'", exp->toChars()); // Make sure all pointers are constants if (needInterpret && hasNonConstPointers(exp)) @@ -851,12 +854,6 @@ L1: Type *ExpInitializer::inferType(Scope *sc) { //printf("ExpInitializer::inferType() %s\n", toChars()); - if (exp->op == TOKfunction && ((FuncExp *)exp)->td) - { - exp->error("cannot infer type from ambiguous function literal %s", exp->toChars()); - return Type::terror; - } - exp = exp->semantic(sc); exp = resolveProperties(sc, exp); @@ -870,7 +867,7 @@ Type *ExpInitializer::inferType(Scope *sc) // Give error for overloaded function addresses if (exp->op == TOKdelegate) { DelegateExp *se = (DelegateExp *)exp; - if ( + if (se->hasOverloads && se->func->isFuncDeclaration() && !se->func->isFuncDeclaration()->isUnique()) exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); diff --git a/inline.c b/inline.c index e0ebe6c1..966371c5 100644 --- a/inline.c +++ b/inline.c @@ -1486,6 +1486,9 @@ int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo) if ( !fbody || ident == Id::ensure || // ensure() has magic properties the inliner loses + (ident == Id::require && // require() has magic properties too + toParent()->isFuncDeclaration() && // see bug 7699 + toParent()->isFuncDeclaration()->needThis()) || !hdrscan && ( #if 0 @@ -1779,6 +1782,18 @@ Expression *Expression::inlineCopy(Scope *sc) */ return copy(); #else + if (op == TOKdelegate) + { DelegateExp *de = (DelegateExp *)this; + + if (de->func->isNested()) + { /* See Bugzilla 4820 + * Defer checking until later if we actually need the 'this' pointer + */ + Expression *e = de->copy(); + return e; + } + } + InlineCostState ics; memset(&ics, 0, sizeof(ics)); @@ -1795,3 +1810,4 @@ Expression *Expression::inlineCopy(Scope *sc) return e; #endif } + diff --git a/interpret.c b/interpret.c index 3258566a..56436990 100644 --- a/interpret.c +++ b/interpret.c @@ -27,7 +27,6 @@ #include "attrib.h" // for AttribDeclaration #include "template.h" -TemplateInstance *isSpeculativeFunction(FuncDeclaration *fd); #define LOG 0 @@ -45,6 +44,10 @@ private: together with the VarDeclaration, and the previous stack address of that variable, so that we can restore it when we leave the stack frame. + Note that when a function is forward referenced, the interpreter must + run semantic3, and that may start CTFE again with a NULL istate. Thus + the stack might not be empty when CTFE begins. + Ctfe Stack addresses are just 0-based integers, but we save them as 'void *' because ArrayBase can only do pointers. */ @@ -143,7 +146,11 @@ public: } void saveGlobalConstant(VarDeclaration *v, Expression *e) { - assert(v->isDataseg() && !v->isCTFE()); +#if DMDV2 + assert( v->init && (v->isConst() || v->isImmutable()) && !v->isCTFE()); +#else + assert( v->init && v->isConst() && !v->isCTFE()); +#endif v->ctfeAdrOnStack = globalValues.dim; globalValues.push(e); } @@ -208,7 +215,7 @@ VarDeclaration *findParentVar(Expression *e, Expression *thisval); bool needToCopyLiteral(Expression *expr); Expression *copyLiteral(Expression *e); Expression *paintTypeOntoLiteral(Type *type, Expression *lit); -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2); +Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2); Expression *evaluateIfBuiltin(InterState *istate, Loc loc, FuncDeclaration *fd, Expressions *arguments, Expression *pthis); Expression *scrubReturnValue(Loc loc, Expression *e); @@ -243,6 +250,16 @@ struct ClassReferenceExp : Expression { return value->sd->isClassDeclaration(); } + VarDeclaration *getFieldAt(int index) + { + ClassDeclaration *cd = originalClass(); + size_t fieldsSoFar = 0; + while (index - fieldsSoFar >= cd->fields.dim) + { fieldsSoFar += cd->fields.dim; + cd = cd->baseClass; + } + return cd->fields.tdata()[index - fieldsSoFar]; + } // Return index of the field, or -1 if not found int getFieldIndex(Type *fieldtype, size_t fieldoffset) { @@ -283,6 +300,28 @@ struct ClassReferenceExp : Expression } }; +struct VoidInitExp : Expression +{ + VarDeclaration *var; + + VoidInitExp(VarDeclaration *var, Type *type) + : Expression(var->loc, TOKvoid, sizeof(VoidInitExp)) + { + this->var = var; + this->type = var->type; + } + char *toChars() + { + return (char *)"void"; + } + Expression *interpret(InterState *istate, CtfeGoal goal = ctfeNeedRvalue) + { + error("CTFE internal error: trying to read uninitialized variable"); + assert(0); + return EXP_CANT_INTERPRET; + } +}; + // Return index of the field, or -1 if not found // Same as getFieldIndex, but checks for a direct match with the VarDeclaration int findFieldIndexByName(StructDeclaration *sd, VarDeclaration *v) @@ -456,7 +495,8 @@ void showCtfeExpr(Expression *e, int level = 0) * arguments function arguments * thisarg 'this', if a needThis() function, NULL if not. * - * Return result expression if successful, EXP_CANT_INTERPRET if not. + * Return result expression if successful, EXP_CANT_INTERPRET if not, + * or EXP_VOID_INTERPRET if function returned void. */ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) @@ -475,7 +515,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument */ int olderrors = global.errors; int oldgag = global.gag; - TemplateInstance *spec = isSpeculativeFunction(this); + TemplateInstance *spec = isSpeculative(); if (global.gag && !spec) global.gag = 0; semantic3(scope); @@ -576,6 +616,15 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument --evaluatingArgs; if (earg == EXP_CANT_INTERPRET) return earg; + /* Struct literals are passed by value, but we don't need to + * copy them if they are passed as const + */ + if (earg->op == TOKstructliteral +#if DMDV2 + && !(arg->storageClass & (STCconst | STCimmutable)) +#endif + ) + earg = copyLiteral(earg); } if (earg->op == TOKthrownexception) { @@ -675,6 +724,11 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument // If fell off the end of a void function, return void if (!e && type->toBasetype()->nextOf()->ty == Tvoid) return EXP_VOID_INTERPRET; + + // If result is void, return void + if (e == EXP_VOID_INTERPRET) + return e; + // If it generated an exception, return it if (exceptionOrCantInterpret(e)) { @@ -683,6 +737,9 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument ((ThrownExceptionExp *)e)->generateUncaughtError(); return EXP_CANT_INTERPRET; } + + // If we're about to leave CTFE, make sure we don't crash the + // compiler by returning a CTFE-internal expression. if (!istate && !evaluatingArgs) { e = scrubReturnValue(loc, e); @@ -896,13 +953,16 @@ uinteger_t resolveArrayLength(Expression *e) } // As Equal, but resolves slices before comparing -Expression *ctfeEqual(enum TOK op, Type *type, Expression *e1, Expression *e2) +Expression *ctfeEqual(Loc loc, enum TOK op, Type *type, Expression *e1, Expression *e2) { if (e1->op == TOKslice) e1 = resolveSlice(e1); if (e2->op == TOKslice) e2 = resolveSlice(e2); - return Equal(op, type, e1, e2); + Expression *e = Equal(op, type, e1, e2); + if (e == EXP_CANT_INTERPRET) + error(loc, "cannot evaluate %s==%s at compile time", e1->toChars(), e2->toChars()); + return e; } Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) @@ -973,7 +1033,7 @@ Expression *ctfeCat(Type *type, Expression *e1, Expression *e2) return Cat(type, e1, e2); } -void scrubArray(Loc loc, Expressions *elems); +bool scrubArray(Loc loc, Expressions *elems, bool structlit = false); /* All results destined for use outside of CTFE need to have their CTFE-specific * features removed. @@ -986,6 +1046,11 @@ Expression *scrubReturnValue(Loc loc, Expression *e) error(loc, "%s class literals cannot be returned from CTFE", ((ClassReferenceExp*)e)->originalClass()->toChars()); return EXP_CANT_INTERPRET; } + if (e->op == TOKvoid) + { + error(loc, "uninitialized variable '%s' cannot be returned from CTFE", ((VoidInitExp *)e)->var->toChars()); + e = new ErrorExp(); + } if (e->op == TOKslice) { e = resolveSlice(e); @@ -994,7 +1059,8 @@ Expression *scrubReturnValue(Loc loc, Expression *e) { StructLiteralExp *se = (StructLiteralExp *)e; se->ownedByCtfe = false; - scrubArray(loc, se->elements); + if (!scrubArray(loc, se->elements, true)) + return EXP_CANT_INTERPRET; } if (e->op == TOKstring) { @@ -1003,29 +1069,38 @@ Expression *scrubReturnValue(Loc loc, Expression *e) if (e->op == TOKarrayliteral) { ((ArrayLiteralExp *)e)->ownedByCtfe = false; - scrubArray(loc, ((ArrayLiteralExp *)e)->elements); + if (!scrubArray(loc, ((ArrayLiteralExp *)e)->elements)) + return EXP_CANT_INTERPRET; } if (e->op == TOKassocarrayliteral) { AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)e; aae->ownedByCtfe = false; - scrubArray(loc, aae->keys); - scrubArray(loc, aae->values); + if (!scrubArray(loc, aae->keys)) + return EXP_CANT_INTERPRET; + if (!scrubArray(loc, aae->values)) + return EXP_CANT_INTERPRET; } return e; } -// Scrub all members of an array -void scrubArray(Loc loc, Expressions *elems) +// Scrub all members of an array. Return false if error +bool scrubArray(Loc loc, Expressions *elems, bool structlit) { for (size_t i = 0; i < elems->dim; i++) { Expression *m = elems->tdata()[i]; if (!m) continue; - m = scrubReturnValue(loc, m); + if (m && m->op == TOKvoid && structlit) + m = NULL; + if (m) + m = scrubReturnValue(loc, m); + if (m == EXP_CANT_INTERPRET) + return false; elems->tdata()[i] = m; } + return true; } @@ -1360,7 +1435,7 @@ Expression *SwitchStatement::interpret(InterState *istate) Expression * caseExp = cs->exp->interpret(istate); if (exceptionOrCantInterpret(caseExp)) return caseExp; - e = ctfeEqual(TOKequal, Type::tint32, econdition, caseExp); + e = ctfeEqual(caseExp->loc, TOKequal, Type::tint32, econdition, caseExp); if (exceptionOrCantInterpret(e)) return e; if (e->isBool(TRUE)) @@ -1475,25 +1550,25 @@ Expression *TryCatchStatement::interpret(InterState *istate) ThrownExceptionExp *ex = (ThrownExceptionExp *)e; Type *extype = ex->thrown->originalClass()->type; // Search for an appropriate catch clause. - for (size_t i = 0; i < catches->dim; i++) - { + for (size_t i = 0; i < catches->dim; i++) + { #if DMDV1 - Catch *ca = (Catch *)catches->data[i]; + Catch *ca = (Catch *)catches->data[i]; #else - Catch *ca = catches->tdata()[i]; + Catch *ca = catches->tdata()[i]; #endif - Type *catype = ca->type; + Type *catype = ca->type; - if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) - { // Execute the handler + if (catype->equals(extype) || catype->isBaseOf(extype, NULL)) + { // Execute the handler if (ca->var) { ctfeStack.push(ca->var); ca->var->setValue(ex->thrown); } - return ca->handler->interpret(istate); - } + return ca->handler ? ca->handler->interpret(istate) : NULL; } + } return e; } @@ -1734,6 +1809,8 @@ Expression *SymOffExp::interpret(InterState *istate, CtfeGoal goal) } Type *pointee = ((TypePointer *)type)->next; Expression *val = getVarExp(loc, istate, var, goal); + if (val == EXP_CANT_INTERPRET) + return val; if (val->type->ty == Tarray || val->type->ty == Tsarray) { // Check for unsupported type painting operations @@ -1903,10 +1980,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal if (e && e != EXP_CANT_INTERPRET && e->op != TOKthrownexception) { e = copyLiteral(e); - if (v->isDataseg()) - ctfeStack.saveGlobalConstant(v, e); - else - v->setValueWithoutChecking(e); + ctfeStack.saveGlobalConstant(v, e); } } else if (v->isCTFE() && !v->hasValue()) @@ -1915,11 +1989,16 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal { if (v->init->isVoidInitializer()) { - error(loc, "variable %s is used before initialization", v->toChars()); - return EXP_CANT_INTERPRET; + // var should have been initialized when it was created + error(loc, "CTFE internal error - trying to access uninitialized var"); + assert(0); + e = EXP_CANT_INTERPRET; + } + else + { + e = v->init->toExpression(); + e = e->interpret(istate); } - e = v->init->toExpression(); - e = e->interpret(istate); } else e = v->type->defaultInitLiteral(loc); @@ -1935,7 +2014,11 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal e = EXP_CANT_INTERPRET; } else if (!e) - error(loc, "variable %s is used before initialization", v->toChars()); + { + assert(0); + assert(v->init && v->init->isVoidInitializer()); + e = v->type->voidInitLiteral(v); + } else if (exceptionOrCantInterpret(e)) return e; else if (goal == ctfeNeedLvalue && v->isRef() && e->op == TOKindex) @@ -1954,6 +2037,13 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal || e->op == TOKassocarrayliteral || e->op == TOKslice || e->type->toBasetype()->ty == Tpointer) return e; // it's already an Lvalue + else if (e->op == TOKvoid) + { + VoidInitExp *ve = (VoidInitExp *)e; + error(loc, "cannot read uninitialized variable %s in ctfe", v->toPrettyChars()); + errorSupplemental(ve->var->loc, "%s was uninitialized and used before set", ve->var->toChars()); + e = EXP_CANT_INTERPRET; + } else e = e->interpret(istate, goal); } @@ -1963,10 +2053,12 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d, CtfeGoal goal else if (s) { // Struct static initializers, for example if (s->dsym->toInitializer() == s->sym) - { e = s->dsym->type->defaultInitLiteral(); + { e = s->dsym->type->defaultInitLiteral(loc); e = e->semantic(NULL); if (e->op == TOKerror) e = EXP_CANT_INTERPRET; + else // Convert NULL to VoidExp + e = e->interpret(istate, goal); } else error(loc, "cannot interpret symbol %s at compile time", v->toChars()); @@ -2035,7 +2127,12 @@ Expression *DeclarationExp::interpret(InterState *istate, CtfeGoal goal) if (ie) e = ie->exp->interpret(istate); else if (v->init->isVoidInitializer()) - e = NULL; + { + e = v->type->voidInitLiteral(v); + // There is no AssignExp for void initializers, + // so set it here. + v->setValue(e); + } else { error("Declaration %s is not yet implemented in CTFE", toChars()); @@ -2264,7 +2361,7 @@ Expression *AssocArrayLiteralExp::interpret(InterState *istate, CtfeGoal goal) ekey = resolveSlice(ekey); for (size_t j = i; j < keysx->dim; j++) { Expression *ekey2 = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, ekey2); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, ekey2); if (ex == EXP_CANT_INTERPRET) goto Lerr; if (ex->isBool(TRUE)) // if a match @@ -2438,10 +2535,10 @@ Expression *recursivelyCreateArrayLiteral(Loc loc, Type *newtype, InterState *is if (elemType->ty == Tchar || elemType->ty == Twchar || elemType->ty == Tdchar) return createBlockDuplicatedStringLiteral(loc, newtype, - (unsigned)(elemType->defaultInitLiteral()->toInteger()), + (unsigned)(elemType->defaultInitLiteral(loc)->toInteger()), len, elemType->size()); return createBlockDuplicatedArrayLiteral(loc, newtype, - elemType->defaultInitLiteral(), + elemType->defaultInitLiteral(loc), len); } @@ -2455,7 +2552,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) if (newtype->toBasetype()->ty == Tstruct) { - Expression *se = newtype->defaultInitLiteral(); + Expression *se = newtype->defaultInitLiteral(loc); #if DMDV2 if (member) { @@ -2492,7 +2589,7 @@ Expression *NewExp::interpret(InterState *istate, CtfeGoal goal) Dsymbol *s = c->fields.tdata()[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v); - Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(); + Expression *m = v->init ? v->init->toExpression() : v->type->defaultInitLiteral(loc); if (exceptionOrCantInterpret(m)) return m; elems->tdata()[fieldsSoFar+i] = copyLiteral(m); @@ -2662,7 +2759,7 @@ Expression *pointerArithmetic(Loc loc, enum TOK op, Type *type, } if (indx < 0 || indx > len) { - error(loc, "cannot assign pointer to index %jd inside memory block [0..%jd]", indx, len); + error(loc, "cannot assign pointer to index %lld inside memory block [0..%lld]", indx, len); return EXP_CANT_INTERPRET; } @@ -2964,7 +3061,7 @@ Expression *assignAssocArrayElement(Loc loc, AssocArrayLiteralExp *aae, Expressi for (size_t j = valuesx->dim; j; ) { j--; Expression *ekey = aae->keys->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index); if (exceptionOrCantInterpret(ex)) return ex; if (ex->isBool(TRUE)) @@ -3134,7 +3231,7 @@ Expression *copyLiteral(Expression *e) assert(v); // If it is a void assignment, use the default initializer if (!m) - m = v->type->defaultInitLiteral(e->loc); + m = v->type->voidInitLiteral(v); if (m->op == TOKslice) m = resolveSlice(m); if ((v->type->ty != m->type->ty) && v->type->ty == Tsarray) @@ -3161,7 +3258,8 @@ Expression *copyLiteral(Expression *e) || e->op == TOKsymoff || e->op == TOKnull || e->op == TOKvar || e->op == TOKint64 || e->op == TOKfloat64 - || e->op == TOKchar || e->op == TOKcomplex80) + || e->op == TOKchar || e->op == TOKcomplex80 + || e->op == TOKvoid) { // Simple value types Expression *r = e->syntaxCopy(); r->type = e->type; @@ -3331,7 +3429,7 @@ void assignInPlace(Expression *dest, Expression *src) assert(o->op == e->op); assignInPlace(o, e); } - else if (e->type->ty == Tsarray && o->type->ty == Tsarray) + else if (e->type->ty == Tsarray && o->type->ty == Tsarray && e->op != TOKvoid) { assignInPlace(o, e); } @@ -3626,7 +3724,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ Type *elemType= NULL; elemType = ((TypeArray *)t)->next; assert(elemType); - Expression *defaultElem = elemType->defaultInitLiteral(); + Expression *defaultElem = elemType->defaultInitLiteral(loc); Expressions *elements = new Expressions(); elements->setDim(newlen); @@ -3734,7 +3832,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ // only modifying part of the variable. So we need to make sure // that the parent variable exists. if (e1->op != TOKvar && ultimateVar && !ultimateVar->getValue()) - ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral())); + ultimateVar->setValue(copyLiteral(ultimateVar->type->defaultInitLiteral(loc))); // --------------------------------------- // Deal with reference assignment @@ -3812,7 +3910,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ indx = resolveSlice(indx); // Look up this index in it up in the existing AA, to get the next level of AA. - AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(existingAA, indx); + AssocArrayLiteralExp *newAA = (AssocArrayLiteralExp *)findKeyInAA(loc, existingAA, indx); if (exceptionOrCantInterpret(newAA)) return newAA; if (!newAA) @@ -3958,14 +4056,29 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ? (StructLiteralExp *)exx : ((ClassReferenceExp *)exx)->value; int fieldi = exx->op == TOKstructliteral - ? se->getFieldIndex(member->type, member->offset) - : ((ClassReferenceExp *)exx)->getFieldIndex(member->type, member->offset); + ? findFieldIndexByName(se->sd, member) + : ((ClassReferenceExp *)exx)->findFieldIndexByName(member); if (fieldi == -1) { error("CTFE internal error: cannot find field %s in %s", member->toChars(), exx->toChars()); return EXP_CANT_INTERPRET; } - assert(fieldi>=0 && fieldi < se->elements->dim); + assert(fieldi >= 0 && fieldi < se->elements->dim); + // If it's a union, set all other members of this union to void + if (exx->op == TOKstructliteral) + { + assert(se->sd); + int unionStart = se->sd->firstFieldInUnion(fieldi); + int unionSize = se->sd->numFieldsInUnion(fieldi); + for(int i = unionStart; i < unionStart + unionSize; ++i) + { if (i == fieldi) + continue; + Expression **el = &se->elements->tdata()[i]; + if ((*el)->op != TOKvoid) + *el = (*el)->type->voidInitLiteral(member); + } + } + if (newval->op == TOKstructliteral) assignInPlace(se->elements->tdata()[fieldi], newval); else @@ -4040,6 +4153,21 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ } aggregate = getAggregateFromPointer(aggregate, &ofs); indexToModify += ofs; + if (aggregate->op != TOKslice && aggregate->op != TOKstring && + aggregate->op != TOKarrayliteral && aggregate->op != TOKassocarrayliteral) + { + if (indexToModify != 0) + { + error("pointer index [%lld] lies outside memory block [0..1]", indexToModify); + return EXP_CANT_INTERPRET; + } + // It is equivalent to *aggregate = newval. + // Aggregate could be varexp, a dotvar, ... + // TODO: we could support this + error("indexed assignment of non-array pointers is not yet supported at compile time; use *%s = %s instead", + ie->e1->toChars(), e2->toChars()); + return EXP_CANT_INTERPRET; + } destarraylen = resolveArrayLength(aggregate); } if (indexToModify >= destarraylen) @@ -4065,7 +4193,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) { IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2); if (!aggregate) { error("key %s not found in associative array %s", @@ -4167,6 +4295,8 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (isPointer(oldval->type)) { // Slicing a pointer oldval = oldval->interpret(istate, ctfeNeedLvalue); + if (exceptionOrCantInterpret(oldval)) + return oldval; dinteger_t ofs; oldval = getAggregateFromPointer(oldval, &ofs); assignmentToSlicedPointer = true; @@ -4176,7 +4306,13 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ if (oldval->op != TOKarrayliteral && oldval->op != TOKstring && oldval->op != TOKslice && oldval->op != TOKnull) { - error("CTFE ICE: cannot resolve array length"); + if (assignmentToSlicedPointer) + { + error("pointer %s cannot be sliced at compile time (it does not point to an array)", + sexp->e1->toChars()); + } + else + error("CTFE ICE: cannot resolve array length"); return EXP_CANT_INTERPRET; } uinteger_t dollar = resolveArrayLength(oldval); @@ -4239,7 +4375,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ ((IndexExp *)aggregate)->e1->op == TOKassocarrayliteral) { IndexExp *ix = (IndexExp *)aggregate; - aggregate = findKeyInAA((AssocArrayLiteralExp *)ix->e1, ix->e2); + aggregate = findKeyInAA(loc, (AssocArrayLiteralExp *)ix->e1, ix->e2); if (!aggregate) { error("key %s not found in associative array %s", @@ -4263,7 +4399,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ firstIndex = lowerbound + sexpold->lwr->toInteger(); if (hi > sexpold->upr->toInteger()) { - error("slice [%d..%d] exceeds array bounds [0..%jd]", + error("slice [%d..%d] exceeds array bounds [0..%lld]", lowerbound, upperbound, sexpold->upr->toInteger() - sexpold->lwr->toInteger()); return EXP_CANT_INTERPRET; @@ -4275,11 +4411,16 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ aggregate = sexp->e1->interpret(istate, ctfeNeedLvalue); dinteger_t ofs; aggregate = getAggregateFromPointer(aggregate, &ofs); + if (aggregate->op == TOKnull) + { + error("cannot slice null pointer %s", sexp->e1->toChars()); + return EXP_CANT_INTERPRET; + } dinteger_t hi = upperbound + ofs; firstIndex = lowerbound + ofs; if (firstIndex < 0 || hi > dim) { - error("slice [%d..%jd] exceeds memory block bounds [0..%jd]", + error("slice [lld..%lld] exceeds memory block bounds [0..%lld]", firstIndex, hi, dim); return EXP_CANT_INTERPRET; } @@ -4420,9 +4561,6 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, CtfeGoal goal, fp_ else { error("%s cannot be evaluated at compile time", toChars()); -#ifdef DEBUG - dump(0); -#endif } return returnValue; } @@ -4802,6 +4940,10 @@ Expression *CallExp::interpret(InterState *istate, CtfeGoal goal) if (!global.gag) showCtfeBackTrace(istate, this, fd); } + else if (eresult == EXP_VOID_INTERPRET) + ; + else + eresult->loc = loc; return eresult; } @@ -4820,7 +4962,6 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) InterState istateComma; if (!istate && firstComma->e1->op == TOKdeclaration) { - assert(ctfeStack.stackPointer() == 0); ctfeStack.startFrame(); istate = &istateComma; } @@ -4838,7 +4979,7 @@ Expression *CommaExp::interpret(InterState *istate, CtfeGoal goal) ctfeStack.push(v); if (!v->init && !v->getValue()) { - v->setValue(copyLiteral(v->type->defaultInitLiteral())); + v->setValue(copyLiteral(v->type->defaultInitLiteral(loc))); } if (!v->getValue()) { Expression *newval = v->init->toExpression(); @@ -4934,7 +5075,7 @@ Expression *ArrayLengthExp::interpret(InterState *istate, CtfeGoal goal) * Return ae[e2] if present, or NULL if not found. * Return EXP_CANT_INTERPRET on error. */ -Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) +Expression *findKeyInAA(Loc loc, AssocArrayLiteralExp *ae, Expression *e2) { /* Search the keys backwards, in case there are duplicate keys */ @@ -4942,13 +5083,9 @@ Expression *findKeyInAA(AssocArrayLiteralExp *ae, Expression *e2) { i--; Expression *ekey = ae->keys->tdata()[i]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, e2); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, e2); if (ex == EXP_CANT_INTERPRET) - { - error("cannot evaluate %s==%s at compile time", - ekey->toChars(), e2->toChars()); return ex; - } if (ex->isBool(TRUE)) { return ae->values->tdata()[i]; @@ -5003,23 +5140,37 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if (exceptionOrCantInterpret(e2)) return e2; dinteger_t indx = e2->toInteger(); + dinteger_t ofs; Expression *agg = getAggregateFromPointer(e1, &ofs); + if (agg->op == TOKnull) { error("cannot index null pointer %s", this->e1->toChars()); return EXP_CANT_INTERPRET; } - assert(agg->op == TOKarrayliteral || agg->op == TOKstring); - dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); - Type *pointee = ((TypePointer *)agg->type)->next; - if ((indx + ofs) < 0 || (indx+ofs) > len) + if ( agg->op == TOKarrayliteral || agg->op == TOKstring) { - error("pointer index [%jd] exceeds allocated memory block [0..%jd]", - indx+ofs, len); - return EXP_CANT_INTERPRET; + dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); + Type *pointee = ((TypePointer *)agg->type)->next; + if ((indx + ofs) < 0 || (indx+ofs) > len) + { + error("pointer index [%lld] exceeds allocated memory block [0..%lld]", + indx+ofs, len); + return EXP_CANT_INTERPRET; + } + return ctfeIndex(loc, type, agg, indx+ofs); + } + else + { // Pointer to a non-array variable + if ((indx + ofs) != 0) + { + error("pointer index [%lld] lies outside memory block [0..1]", + indx+ofs); + return EXP_CANT_INTERPRET; + } + return agg->interpret(istate); } - return ctfeIndex(loc, type, agg, indx+ofs); } e1 = this->e1; if (!(e1->op == TOKarrayliteral && ((ArrayLiteralExp *)e1)->ownedByCtfe)) @@ -5060,7 +5211,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) if (indx > iup - ilo) { - error("index %ju exceeds array length %ju", indx, iup - ilo); + error("index %llu exceeds array length %llu", indx, iup - ilo); return EXP_CANT_INTERPRET; } indx += ilo; @@ -5081,7 +5232,7 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) { if (e2->op == TOKslice) e2 = resolveSlice(e2); - e = findKeyInAA((AssocArrayLiteralExp *)e1, e2); + e = findKeyInAA(loc, (AssocArrayLiteralExp *)e1, e2); if (!e) { error("key %s not found in associative array %s", @@ -5102,6 +5253,12 @@ Expression *IndexExp::interpret(InterState *istate, CtfeGoal goal) return e; if (goal == ctfeNeedRvalue && (e->op == TOKslice || e->op == TOKdotvar)) e = e->interpret(istate); + if (goal == ctfeNeedRvalue && e->op == TOKvoid) + { + error("%s is used before initialized", toChars()); + errorSupplemental(e->loc, "originally uninitialized here"); + return EXP_CANT_INTERPRET; + } e = paintTypeOntoLiteral(type, e); return e; } @@ -5156,12 +5313,18 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) error("cannot slice null pointer %s", this->e1->toChars()); return EXP_CANT_INTERPRET; } + if (agg->op != TOKarrayliteral && agg->op != TOKstring) + { + error("pointer %s cannot be sliced at compile time (it does not point to an array)", + this->e1->toChars()); + return EXP_CANT_INTERPRET; + } assert(agg->op == TOKarrayliteral || agg->op == TOKstring); dinteger_t len = ArrayLength(Type::tsize_t, agg)->toInteger(); Type *pointee = ((TypePointer *)agg->type)->next; if ((ilwr + ofs) < 0 || (iupr+ofs) > (len + 1) || iupr < ilwr) { - error("pointer slice [%jd..%jd] exceeds allocated memory block [0..%jd]", + error("pointer slice [%lld..%lld] exceeds allocated memory block [0..%lld]", ilwr+ofs, iupr+ofs, len); return EXP_CANT_INTERPRET; } @@ -5225,7 +5388,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) { if (ilwr== 0 && iupr == 0) return e1; - e1->error("slice [%ju..%ju] is out of bounds", ilwr, iupr); + e1->error("slice [%llu..%llu] is out of bounds", ilwr, iupr); return EXP_CANT_INTERPRET; } if (e1->op == TOKslice) @@ -5237,7 +5400,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) uinteger_t up1 = se->upr->toInteger(); if (ilwr > iupr || iupr > up1 - lo1) { - error("slice[%ju..%ju] exceeds array bounds[%ju..%ju]", + error("slice[%llu..%llu] exceeds array bounds[%llu..%llu]", ilwr, iupr, lo1, up1); return EXP_CANT_INTERPRET; } @@ -5254,7 +5417,7 @@ Expression *SliceExp::interpret(InterState *istate, CtfeGoal goal) { if (iupr < ilwr || ilwr < 0 || iupr > dollar) { - error("slice [%jd..%jd] exceeds array bounds [0..%jd]", + error("slice [%lld..%lld] exceeds array bounds [0..%lld]", ilwr, iupr, dollar); return EXP_CANT_INTERPRET; } @@ -5285,7 +5448,7 @@ Expression *InExp::interpret(InterState *istate, CtfeGoal goal) } if (e1->op == TOKslice) e1 = resolveSlice(e1); - e = findKeyInAA((AssocArrayLiteralExp *)e2, e1); + e = findKeyInAA(loc, (AssocArrayLiteralExp *)e2, e1); if (exceptionOrCantInterpret(e)) return e; if (!e) @@ -5344,8 +5507,12 @@ bool isAssocArray(Type *t) if (t->ty != Tstruct) return false; StructDeclaration *sym = ((TypeStruct *)t)->sym; - if (sym->ident == Id::AssociativeArray) + if (sym->ident == Id::AssociativeArray && sym->parent && + sym->parent->parent && + sym->parent->parent->ident == Id::object) + { return true; + } #endif return false; } @@ -5500,9 +5667,15 @@ Expression *CastExp::interpret(InterState *istate, CtfeGoal goal) e->type = type; return e; } - error("pointer cast from %s to %s is not supported at compile time", + + // Check if we have a null pointer (eg, inside a struct) + e1 = e1->interpret(istate); + if (e1->op != TOKnull) + { + error("pointer cast from %s to %s is not supported at compile time", e1->type->toChars(), to->toChars()); - return EXP_CANT_INTERPRET; + return EXP_CANT_INTERPRET; + } } if (to->ty == Tarray && e1->op == TOKslice) { @@ -5650,7 +5823,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) assert(indx >=0 && indx <= len); // invalid pointer if (indx == len) { - error("dereference of pointer %s one past end of memory block limits [0..%jd]", + error("dereference of pointer %s one past end of memory block limits [0..%lld]", toChars(), len); return EXP_CANT_INTERPRET; } @@ -5695,7 +5868,7 @@ Expression *PtrExp::interpret(InterState *istate, CtfeGoal goal) } else if (e->op == TOKaddress) e = ((AddrExp*)e)->e1; // *(&x) ==> x - if (e->op == TOKnull) + else if (e->op == TOKnull) { error("dereference of null pointer '%s'", e1->toChars()); return EXP_CANT_INTERPRET; @@ -5784,6 +5957,13 @@ Expression *DotVarExp::interpret(InterState *istate, CtfeGoal goal) if (e->op == TOKstructliteral || e->op == TOKarrayliteral || e->op == TOKassocarrayliteral || e->op == TOKstring) return e; + if (e->op == TOKvoid) + { + VoidInitExp *ve = (VoidInitExp *)e; + error("cannot read uninitialized variable %s in ctfe", toChars()); + ve->var->error("was uninitialized and used before set"); + return EXP_CANT_INTERPRET; + } if ( isPointer(type) ) { return paintTypeOntoLiteral(type, e); @@ -5828,7 +6008,7 @@ Expression *RemoveExp::interpret(InterState *istate, CtfeGoal goal) size_t removed = 0; for (size_t j = 0; j < valuesx->dim; ++j) { Expression *ekey = keysx->tdata()[j]; - Expression *ex = ctfeEqual(TOKequal, Type::tbool, ekey, index); + Expression *ex = ctfeEqual(loc, TOKequal, Type::tbool, ekey, index); if (exceptionOrCantInterpret(ex)) return ex; if (ex->isBool(TRUE)) @@ -6007,7 +6187,7 @@ Expression *foreachApplyUtf(InterState *istate, Expression *str, Expression *del else if (str->op == TOKarrayliteral) ale = (ArrayLiteralExp *)str; else - { error("CTFE internal error: cannot foreach %s", str->toChars()); + { str->error("CTFE internal error: cannot foreach %s", str->toChars()); return EXP_CANT_INTERPRET; } Expressions args; @@ -6462,6 +6642,10 @@ bool isCtfeValueValid(Expression *newval) assert(((ArrayLiteralExp *)se->e1)->ownedByCtfe); return true; } + if (newval->op == TOKvoid) + { + return true; + } newval->error("CTFE internal error: illegal value %s\n", newval->toChars()); return false; } @@ -6494,3 +6678,28 @@ void VarDeclaration::setValue(Expression *newval) assert(isCtfeValueValid(newval)); ctfeStack.setValue(this, newval); } + + +Expression *Type::voidInitLiteral(VarDeclaration *var) +{ + return new VoidInitExp(var, this); +} + +Expression *TypeSArray::voidInitLiteral(VarDeclaration *var) +{ + return createBlockDuplicatedArrayLiteral(var->loc, this, next->voidInitLiteral(var), dim->toInteger()); +} + +Expression *TypeStruct::voidInitLiteral(VarDeclaration *var) +{ + Expressions *exps = new Expressions(); + exps->setDim(sym->fields.dim); + for (size_t i = 0; i < sym->fields.dim; i++) + { + (*exps)[i] = new VoidInitExp(var, sym->fields[i]->type); + } + StructLiteralExp *se = new StructLiteralExp(var->loc, sym, exps); + se->type = this; + se->ownedByCtfe = true; + return se; +} diff --git a/lexer.c b/lexer.c index 8070f820..ae4eb2ba 100644 --- a/lexer.c +++ b/lexer.c @@ -121,11 +121,11 @@ const char *Token::toChars() break; case TOKint64v: - sprintf(buffer,"%jdL",(intmax_t)int64value); + sprintf(buffer,"%lldL",(intmax_t)int64value); break; case TOKuns64v: - sprintf(buffer,"%juUL",(uintmax_t)uns64value); + sprintf(buffer,"%lluUL",(uintmax_t)uns64value); break; #if IN_GCC @@ -143,27 +143,32 @@ const char *Token::toChars() break; #else case TOKfloat32v: - sprintf(buffer,"%Lgf", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "f"); break; case TOKfloat64v: - sprintf(buffer,"%Lg", float80value); + ld_sprint(buffer, 'g', float80value); break; case TOKfloat80v: - sprintf(buffer,"%LgL", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "L"); break; case TOKimaginary32v: - sprintf(buffer,"%Lgfi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "fi"); break; case TOKimaginary64v: - sprintf(buffer,"%Lgi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "i"); break; case TOKimaginary80v: - sprintf(buffer,"%LgLi", float80value); + ld_sprint(buffer, 'g', float80value); + strcat(buffer, "Li"); break; #endif @@ -302,7 +307,7 @@ void Lexer::error(const char *format, ...) { va_list ap; va_start(ap, format); - verror(loc, format, ap); + verror(tokenLoc(), format, ap); va_end(ap); } @@ -365,7 +370,6 @@ Token *Lexer::peek(Token *ct) { t = new Token(); scan(t); - t->next = NULL; ct->next = t; } return t; @@ -1224,9 +1228,21 @@ void Lexer::scan(Token *t) #undef DOUBLE case '#': + { p++; - pragma(); - continue; + Token *n = peek(t); + if (n->value == TOKidentifier && n->ident == Id::line) + { + nextToken(); + poundLine(); + continue; + } + else + { + t->value = TOKpound; + return; + } + } default: { unsigned c = *p; @@ -2562,22 +2578,17 @@ done: } /********************************************* - * Do pragma. - * Currently, the only pragma supported is: + * parse: * #line linnum [filespec] */ -void Lexer::pragma() +void Lexer::poundLine() { Token tok; int linnum; char *filespec = NULL; Loc loc = this->loc; - scan(&tok); - if (tok.value != TOKidentifier || tok.ident != Id::line) - goto Lerr; - scan(&tok); if (tok.value == TOKint32v || tok.value == TOKint64v) { linnum = tok.uns64value - 1; @@ -2861,6 +2872,38 @@ unsigned char *Lexer::combineComments(unsigned char *c1, unsigned char *c2) return c; } +/******************************************* + * Search actual location of current token + * even when infinite look-ahead was done. + */ +Loc Lexer::tokenLoc() +{ + Loc result = this->loc; + Token* last = &token; + while (last->next) + last = last->next; + + unsigned char* start = token.ptr; + unsigned char* stop = last->ptr; + + for (unsigned char* p = start; p < stop; ++p) + { + switch (*p) + { + case '\n': + result.linnum--; + break; + case '\r': + if (p[1] != '\n') + result.linnum--; + break; + default: + break; + } + } + return result; +} + /******************************************** * Create an identifier in the string table. */ @@ -3160,6 +3203,7 @@ void Lexer::initKeywords() Token::tochars[TOKpow] = "^^"; Token::tochars[TOKpowass] = "^^="; Token::tochars[TOKgoesto] = "=>"; + Token::tochars[TOKpound] = "#"; #endif // For debugging diff --git a/lexer.h b/lexer.h index 9b1e132e..9284bdbf 100644 --- a/lexer.h +++ b/lexer.h @@ -170,6 +170,7 @@ enum TOK TOKpowass, TOKgoesto, TOKvector, + TOKpound, #endif TOKMAX @@ -251,6 +252,7 @@ struct Token static const char *tochars[TOKMAX]; static void *operator new(size_t sz); + Token() : next(NULL) {} int isKeyword(); void print(); const char *toChars(); @@ -305,12 +307,14 @@ struct Lexer void error(const char *format, ...); void error(Loc loc, const char *format, ...); void verror(Loc loc, const char *format, va_list ap); - void pragma(); + void poundLine(); unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); static int isValidIdentifier(char *p); static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); + + Loc tokenLoc(); }; #endif /* DMD_LEXER_H */ diff --git a/lib.h b/lib.h index abd31cb2..3a67ed30 100644 --- a/lib.h +++ b/lib.h @@ -48,6 +48,20 @@ struct Library unsigned short numDictPages(unsigned padding); int FillDict(unsigned char *bucketsP, unsigned short uNumPages); void WriteLibToBuffer(OutBuffer *libbuf); + + void error(const char *format, ...) + { + Loc loc; + if (libfile) + { + loc.filename = libfile->name->toChars(); + loc.linnum = 0; + } + va_list ap; + va_start(ap, format); + ::verror(loc, format, ap); + va_end(ap); + } }; #endif /* DMD_LIB_H */ diff --git a/libomf.c b/libomf.c index b3703c6a..2e89b558 100644 --- a/libomf.c +++ b/libomf.c @@ -260,6 +260,7 @@ void Library::scanObjModule(ObjModule *om) if (easyomf) recTyp = COMDAT+1; // convert to MS format case COMDAT+1: + { int pickAny = 0; if (*p++ & 5) // if continuation or local comdat @@ -292,7 +293,7 @@ void Library::scanObjModule(ObjModule *om) //printf("[s] name='%s'\n",name); addSymbol(om, names.tdata()[idx],pickAny); break; - + } case ALIAS: while (p + 1 < pnext) { @@ -484,6 +485,7 @@ void Library::addObject(const char *module_name, void *buf, size_t buflen) case MODEND : case M386END: + { if (om) { om->page = (om->base - pstart) / g_page_size; om->length = pnext - om->base; @@ -494,7 +496,7 @@ void Library::addObject(const char *module_name, void *buf, size_t buflen) t = (t + g_page_size - 1) & ~(unsigned)(g_page_size - 1); pnext = pstart + t; break; - + } default: // ignore ; @@ -740,7 +742,7 @@ int Library::FillDict(unsigned char *bucketsP, unsigned short ndicpages) } // Sort the symbols - qsort( objsymbols.tdata(), objsymbols.dim, 4, (cmpfunc_t)NameCompare ); + qsort( objsymbols.tdata(), objsymbols.dim, sizeof(objsymbols.tdata()[0]), (cmpfunc_t)NameCompare ); // Add each of the symbols for (size_t i = 0; i < objsymbols.dim; i++) diff --git a/link.c b/link.c index 7e1c86f3..ddc9dccf 100644 --- a/link.c +++ b/link.c @@ -208,7 +208,7 @@ int runLINK() flnk.setbuffer(p, plen); flnk.ref = 1; if (flnk.write()) - error("error writing file %s", lnkfilename); + error(0, "error writing file %s", lnkfilename); if (lnkfilename->len() < plen) sprintf(p, "@%s", lnkfilename->toChars()); } @@ -490,7 +490,7 @@ int executecmd(char *cmd, char *args, int useenv) else { L1: - error("command line length of %d is too long",len); + error(0, "command line length of %d is too long",len); } } diff --git a/mangle.c b/mangle.c index c4baa871..d8664d82 100644 --- a/mangle.c +++ b/mangle.c @@ -234,7 +234,7 @@ char *TemplateInstance::mangle() buf.writestring(p); } } - buf.printf("%zu%s", strlen(id), id); + buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.toChars(); buf.data = NULL; //printf("TemplateInstance::mangle() %s = %s\n", toChars(), id); @@ -262,7 +262,7 @@ char *Dsymbol::mangle() p += 2; buf.writestring(p); } - buf.printf("%zu%s", strlen(id), id); + buf.printf("%llu%s", (ulonglong)strlen(id), id); id = buf.toChars(); buf.data = NULL; //printf("Dsymbol::mangle() %s = %s\n", toChars(), id); diff --git a/mars.c b/mars.c index 5c7f38eb..e273a381 100644 --- a/mars.c +++ b/mars.c @@ -94,7 +94,7 @@ Global::Global() "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates."; #endif ; - version = "v2.058"; + version = "v2.059"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -117,6 +117,11 @@ bool Global::endGagging(unsigned oldGagged) return anyErrs; } +bool Global::isSpeculativeGagging() +{ + return gag && gag == speculativeGag; +} + char *Loc::toChars() { @@ -368,7 +373,7 @@ Usage:\n\ extern signed char tyalignsize[]; -#if _WIN32 +#if _WIN32 && __DMC__ extern "C" { extern int _xi_a; @@ -376,11 +381,11 @@ extern "C" } #endif -int main(int argc, char *argv[]) +int tryMain(int argc, char *argv[]) { mem.init(); // initialize storage allocator mem.setStackBottom(&argv); -#if _WIN32 +#if _WIN32 && __DMC__ mem.addroots((char *)&_xi_a, (char *)&_end); #endif @@ -404,7 +409,7 @@ int main(int argc, char *argv[]) if (argc < 1 || !argv) { Largs: - error("missing or null command line arguments"); + error(0, "missing or null command line arguments"); fatal(); } for (size_t i = 0; i < argc; i++) @@ -414,7 +419,7 @@ int main(int argc, char *argv[]) } if (response_expand(&argc,&argv)) // expand response files - error("can't open response file"); + error(0, "can't open response file"); files.reserve(argc - 1); @@ -441,6 +446,7 @@ int main(int argc, char *argv[]) global.params.is64bit = (sizeof(size_t) == 8); #if TARGET_WINDOS + global.params.is64bit = 0; global.params.defaultlibname = "phobos"; #elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS global.params.defaultlibname = "phobos2"; @@ -542,7 +548,7 @@ int main(int argc, char *argv[]) else if (strcmp(p + 1, "gs") == 0) global.params.alwaysframe = 1; else if (strcmp(p + 1, "gt") == 0) - { error("use -profile instead of -gt\n"); + { error(0, "use -profile instead of -gt\n"); global.params.trace = 1; } else if (strcmp(p + 1, "m32") == 0) @@ -562,7 +568,7 @@ int main(int argc, char *argv[]) #if DMDV1 global.params.Dversion = 1; #else - error("use DMD 1.0 series compilers for -v1 switch"); + error(0, "use DMD 1.0 series compilers for -v1 switch"); break; #endif } @@ -599,7 +605,7 @@ int main(int argc, char *argv[]) break; case 0: - error("-o no longer supported, use -of or -od"); + error(0, "-o no longer supported, use -of or -od"); break; default: @@ -844,11 +850,11 @@ int main(int argc, char *argv[]) else { Lerror: - error("unrecognized switch '%s'", argv[i]); + error(0, "unrecognized switch '%s'", argv[i]); continue; Lnoarg: - error("argument expected for switch '%s'", argv[i]); + error(0, "argument expected for switch '%s'", argv[i]); continue; } } @@ -883,7 +889,7 @@ int main(int argc, char *argv[]) #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS if (global.params.lib && global.params.dll) - error("cannot mix -lib and -shared\n"); + error(0, "cannot mix -lib and -shared\n"); #endif if (global.params.release) @@ -945,7 +951,7 @@ int main(int argc, char *argv[]) } else if (global.params.run) { - error("flags conflict with -run"); + error(0, "flags conflict with -run"); fatal(); } else @@ -1051,10 +1057,10 @@ int main(int argc, char *argv[]) #if _WIN32 // Convert / to \ so linker will work - for (size_t i = 0; p[i]; i++) + for (size_t j = 0; p[j]; j++) { - if (p[i] == '/') - p[i] = '\\'; + if (p[j] == '/') + p[j] = '\\'; } #endif @@ -1136,12 +1142,12 @@ int main(int argc, char *argv[]) strcmp(name, ".") == 0) { Linvalid: - error("invalid file name '%s'", files.tdata()[i]); + error(0, "invalid file name '%s'", files.tdata()[i]); fatal(); } } else - { error("unrecognized file extension %s\n", ext); + { error(0, "unrecognized file extension %s\n", ext); fatal(); } } @@ -1165,10 +1171,6 @@ int main(int argc, char *argv[]) } } -#if WINDOWS_SEH - __try - { -#endif // Read files #define ASYNCREAD 1 #if ASYNCREAD @@ -1205,7 +1207,8 @@ int main(int argc, char *argv[]) #if ASYNCREAD if (aw->read(filei)) { - error("cannot read file %s", m->srcfile->name->toChars()); + error(0, "cannot read file %s", m->srcfile->name->toChars()); + fatal(); } #endif m->parse(); @@ -1239,7 +1242,7 @@ int main(int argc, char *argv[]) if (anydocfiles && modules.dim && (global.params.oneobj || global.params.objname)) { - error("conflicting Ddoc and obj generation options"); + error(0, "conflicting Ddoc and obj generation options"); fatal(); } if (global.errors) @@ -1426,14 +1429,6 @@ int main(int argc, char *argv[]) if (global.params.lib && !global.errors) library->write(); -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - printf("Stack overflow\n"); - fatal(); - } -#endif backend_term(); if (global.errors) fatal(); @@ -1441,7 +1436,7 @@ int main(int argc, char *argv[]) if (!global.params.objfiles->dim) { if (global.params.link) - error("no object files to link"); + error(0, "no object files to link"); } else { @@ -1471,6 +1466,24 @@ int main(int argc, char *argv[]) return status; } +int main(int argc, char *argv[]) +{ + int status = -1; +#if WINDOWS_SEH + __try + { +#endif + status = tryMain(argc, argv); +#if WINDOWS_SEH + } + __except (__ehfilter(GetExceptionInformation())) + { + printf("Stack overflow\n"); + fatal(); + } +#endif + return status; +} /*********************************** @@ -1584,7 +1597,7 @@ long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep) //printf("%x\n", ep->ExceptionRecord->ExceptionCode); if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) { -#ifndef DEBUG +#if 1 //ndef DEBUG return EXCEPTION_EXECUTE_HANDLER; #endif } diff --git a/mars.h b/mars.h index 24cd00b2..f4b05739 100644 --- a/mars.h +++ b/mars.h @@ -262,6 +262,12 @@ struct Global unsigned gag; // !=0 means gag reporting of errors & warnings unsigned gaggedErrors; // number of errors reported while gagged + /* Gagging can either be speculative (is(typeof()), etc) + * or because of forward references + */ + unsigned speculativeGag; // == gag means gagging is for is(typeof); + bool isSpeculativeGagging(); + // Start gagging. Return the current number of gagged errors unsigned startGagging(); @@ -278,10 +284,12 @@ extern Global global; /* Set if Windows Structured Exception Handling C extensions are supported. * Apparently, VC has dropped support for these? */ -#define WINDOWS_SEH (_WIN32 && __DMC__) +#define WINDOWS_SEH _WIN32 +#include "longdouble.h" #ifdef __DMC__ + #include typedef _Complex long double complex_t; #else #ifndef IN_GCC @@ -312,7 +320,7 @@ typedef uint64_t d_uns64; typedef float d_float32; typedef double d_float64; -typedef long double d_float80; +typedef longdouble d_float80; typedef d_uns8 d_char; typedef d_uns16 d_wchar; @@ -321,7 +329,7 @@ typedef d_uns32 d_dchar; #ifdef IN_GCC #include "d-gcc-real.h" #else -typedef long double real_t; +typedef longdouble real_t; #endif // Modify OutBuffer::writewchar to write the correct size of wchar diff --git a/module.c b/module.c index 716f36d8..a87d3a32 100644 --- a/module.c +++ b/module.c @@ -342,7 +342,9 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) printf("%s\t(%s)\n", ident->toChars(), m->srcfile->toChars()); } - m->read(loc); + if (!m->read(loc)) + return NULL; + m->parse(); #ifdef IN_GCC @@ -352,7 +354,7 @@ Module *Module::load(Loc loc, Identifiers *packages, Identifier *ident) return m; } -void Module::read(Loc loc) +bool Module::read(Loc loc) { //printf("Module::read('%s') file '%s'\n", toChars(), srcfile->toChars()); if (srcfile->read()) @@ -365,14 +367,16 @@ void Module::read(Loc loc) for (size_t i = 0; i < global.path->dim; i++) { char *p = global.path->tdata()[i]; - fprintf(stdmsg, "import path[%zd] = %s\n", i, p); + fprintf(stdmsg, "import path[%llu] = %s\n", (ulonglong)i, p); } } else fprintf(stdmsg, "Specify path to file '%s' with -I switch\n", srcfile->toChars()); + fatal(); } - fatal(); + return false; } + return true; } inline unsigned readwordLE(unsigned short *p) @@ -1167,19 +1171,23 @@ DsymbolTable *Package::resolve(Identifiers *packages, Dsymbol **pparent, Package else { assert(p->isPackage()); -#if TARGET_NET //dot net needs modules and packages with same name -#else - if (p->isModule()) - { p->error("module and package have the same name"); - fatal(); - break; - } -#endif + // It might already be a module, not a package, but that needs + // to be checked at a higher level, where a nice error message + // can be generated. + // dot net needs modules and packages with same name } parent = p; dst = ((Package *)p)->symtab; if (ppkg && !*ppkg) *ppkg = (Package *)p; +#if TARGET_NET +#else + if (p->isModule()) + { // Return the module so that a nice error message can be generated + *ppkg = (Package *)p; + break; + } +#endif } if (pparent) { diff --git a/module.h b/module.h index 6b045985..692491a6 100644 --- a/module.h +++ b/module.h @@ -120,7 +120,7 @@ struct Module : Package void toJsonBuffer(OutBuffer *buf); const char *kind(); void setDocfile(); // set docfile member - void read(Loc loc); // read file + bool read(Loc loc); // read file, returns 'true' if succeed, 'false' otherwise. #if IN_GCC void parse(bool dump_source = false); // syntactic parse #else diff --git a/mtype.c b/mtype.c index c7f22412..be554dd9 100644 --- a/mtype.c +++ b/mtype.c @@ -81,6 +81,10 @@ int REALALIGNSIZE = 4; int REALSIZE = 10; int REALPAD = 0; int REALALIGNSIZE = 2; +#elif IN_GCC +int REALSIZE = 0; +int REALPAD = 0; +int REALALIGNSIZE = 0; #else #error "fix this" #endif @@ -247,7 +251,7 @@ void Type::init() for (size_t i = 0; i < TMAX; i++) { if (!mangleChar[i]) - fprintf(stdmsg, "ty = %zd\n", i); + fprintf(stdmsg, "ty = %llu\n", (ulonglong)i); assert(mangleChar[i]); } @@ -413,6 +417,8 @@ Type *Type::mutableOf() t = t->merge(); t->fixTo(this); } + else + t = t->merge(); assert(t->isMutable()); return t; } @@ -504,6 +510,8 @@ Type *Type::unSharedOf() t->fixTo(this); } + else + t = t->merge(); assert(!t->isShared()); return t; } @@ -1280,7 +1288,19 @@ Type *Type::aliasthisOf() Expression *ethis = this->defaultInit(0); fd = fd->overloadResolve(0, ethis, NULL); if (fd) + { TypeFunction *tf = (TypeFunction *)fd->type; + if (!tf->next && fd->inferRetType) + { + TemplateInstance *spec = fd->isSpeculative(); + int olderrs = global.errors; + fd->semantic3(fd->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } t = ((TypeFunction *)fd->type)->next; + } } return t; } @@ -1290,6 +1310,32 @@ Type *Type::aliasthisOf() Type *t = ed->type; return t; } + TemplateDeclaration *td = ad->aliasthis->isTemplateDeclaration(); + if (td) + { assert(td->scope); + Expression *ethis = defaultInit(0); + FuncDeclaration *fd = td->deduceFunctionTemplate(td->scope, 0, NULL, ethis, NULL, 1); + if (fd) + { + //if (!fd->type->nextOf() && fd->inferRetType) + { + TemplateInstance *spec = fd->isSpeculative(); + int olderrs = global.errors; + fd->semantic3(fd->scope); + // Update the template instantiation with the number + // of errors which occured. + if (spec && global.errors != olderrs) + spec->errors = global.errors - olderrs; + } + if (!global.errors) + { + Type *t = fd->type->nextOf(); + t = t->substWildTo(mod == 0 ? MODmutable : mod); + return t; + } + } + return Type::terror; + } //printf("%s\n", ad->aliasthis->kind()); } return NULL; @@ -1580,6 +1626,8 @@ Type *Type::merge() if (ty == Ttypeof) return this; if (ty == Tident) return this; if (ty == Tinstance) return this; + if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco) + return this; if (nextOf() && !nextOf()->merge()->deco) return this; @@ -1836,12 +1884,12 @@ Type *Type::substWildTo(unsigned mod) else if (ty == Taarray) { t = new TypeAArray(t, ((TypeAArray *)this)->index->syntaxCopy()); - t = t->merge(); + ((TypeAArray *)t)->sc = ((TypeAArray *)this)->sc; // duplicate scope } else assert(0); - t = t->addMod(this->mod); + t = t->merge(); } } else @@ -1978,35 +2026,6 @@ Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident) } else if (ident == Id::init) { -#if 0 - if (v->init) - { - if (v->init->isVoidInitializer()) - error(e->loc, "%s.init is void", v->toChars()); - else - { Loc loc = e->loc; - e = v->init->toExpression(); - if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit) - { - e = ((AssignExp *)e)->e2; - - /* Take care of case where we used a 0 - * to initialize the struct. - */ - if (e->type == Type::tint32 && - e->isBool(0) && - v->type->toBasetype()->ty == Tstruct) - { - e = v->type->defaultInit(e->loc); - } - } - e = e->optimize(WANTvalue | WANTinterpret); -// if (!e->isConst()) -// error(loc, ".init cannot be evaluated at compile time"); - } - goto Lreturn; - } -#endif e = defaultInitLiteral(e->loc); goto Lreturn; } @@ -2082,7 +2101,6 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) tiargs->push(se); e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs); ((DotTemplateInstanceExp *)e)->ti->tempdecl = td; - //return e; e = e->semantic(sc); return e; } @@ -2093,7 +2111,7 @@ Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident) { /* Rewrite e.ident as: * e.aliasthis.ident */ - e = new DotIdExp(e->loc, e, sym->aliasthis->ident); + e = resolveAliasThis(sc, e); e = new DotIdExp(e->loc, e, ident); return e->semantic(sc); } @@ -2170,11 +2188,15 @@ void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) } /******************************* - * If one of the subtypes of this type is a TypeIdentifier, - * i.e. it's an unresolved type, return that type. + * tparams == NULL: + * If one of the subtypes of this type is a TypeIdentifier, + * i.e. it's an unresolved type, return that type. + * tparams != NULL: + * Only when the TypeIdentifier is one of template parameters, + * return that type. */ -Type *Type::reliesOnTident() +Type *Type::reliesOnTident(TemplateParameters *tparams) { return NULL; } @@ -2294,9 +2316,9 @@ void TypeNext::checkDeprecated(Loc loc, Scope *sc) } -Type *TypeNext::reliesOnTident() +Type *TypeNext::reliesOnTident(TemplateParameters *tparams) { - return next->reliesOnTident(); + return next->reliesOnTident(tparams); } int TypeNext::hasWild() @@ -2463,9 +2485,7 @@ Type *TypeNext::makeMutable() { //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); TypeNext *t = (TypeNext *)Type::makeMutable(); - if ((ty != Tfunction && next->ty != Tfunction && - //(next->deco || next->ty == Tfunction) && - next->isWild()) || ty == Tsarray) + if (ty == Tsarray) { t->next = next->mutableOf(); } @@ -3037,7 +3057,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) case Timaginary64: t = tfloat64; goto L2; case Timaginary80: t = tfloat80; goto L2; L2: - e = new RealExp(0, 0.0, t); + e = new RealExp(e->loc, ldouble(0.0), t); break; default: @@ -3069,7 +3089,7 @@ Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident) case Tfloat32: case Tfloat64: case Tfloat80: - e = new RealExp(0, 0.0, this); + e = new RealExp(e->loc, ldouble(0.0), this); break; default: @@ -3096,7 +3116,7 @@ Expression *TypeBasic::defaultInit(Loc loc) */ union { unsigned short us[8]; - long double ld; + longdouble ld; } snan = {{ 0, 0, 0, 0xA000, 0x7FFF }}; /* * Although long doubles are 10 bytes long, some @@ -3324,11 +3344,25 @@ Type *TypeVector::semantic(Loc loc, Scope *sc) if (errors != global.errors) return terror; basetype = basetype->toBasetype()->mutableOf(); - if (basetype->ty != Tsarray || basetype->size() != 16) - { error(loc, "base type of __vector must be a 16 byte static array, not %s", basetype->toChars()); + if (basetype->ty != Tsarray) + { error(loc, "T in __vector(T) must be a static array, not %s", basetype->toChars()); return terror; } TypeSArray *t = (TypeSArray *)basetype; + + if (sc && sc->parameterSpecialization && t->dim->op == TOKvar && + ((VarExp *)t->dim)->var->storage_class & STCtemplateparameter) + { + /* It could be a template parameter N which has no value yet: + * template Foo(T : __vector(T[N]), size_t N); + */ + return this; + } + + if (t->size(loc) != 16) + { error(loc, "base type of __vector must be a 16 byte static array, not %s", t->toChars()); + return terror; + } TypeBasic *tb = t->nextOf()->isTypeBasic(); if (!tb || !(tb->flags & TFLAGSvector)) { error(loc, "base type of __vector must be a static array of an arithmetic type, not %s", t->toChars()); @@ -3601,7 +3635,7 @@ d_uns64 TypeSArray::size(Loc loc) return sz; Loverflow: - error(loc, "index %jd overflow for static array", sz); + error(loc, "index %lld overflow for static array", sz); return 1; } @@ -3649,7 +3683,10 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt); if (*pe) { // It's really an index expression - Expression *e = new IndexExp(loc, *pe, dim); + Expressions *exps = new Expressions(); + exps->setDim(1); + (*exps)[0] = dim; + Expression *e = new ArrayExp(loc, *pe, exps); *pe = e; } else if (*ps) @@ -3668,7 +3705,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->pop(); if (d >= td->objects->dim) - { error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim); + { error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim); goto Ldefault; } Object *o = td->objects->tdata()[(size_t)d]; @@ -3728,7 +3765,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) uinteger_t d = dim->toUInteger(); if (d >= sd->objects->dim) - { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim); + { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim); return Type::terror; } Object *o = sd->objects->tdata()[(size_t)d]; @@ -3795,7 +3832,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) if (n && n2 / n != d2) { Loverflow: - error(loc, "index %jd overflow for static array", d1); + error(loc, "index %lld overflow for static array", d1); goto Lerror; } } @@ -3809,7 +3846,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc) uinteger_t d = dim->toUInteger(); if (d >= tt->arguments->dim) - { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim); + { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim); goto Lerror; } Parameter *arg = tt->arguments->tdata()[(size_t)d]; @@ -3850,7 +3887,7 @@ void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag) { Type::toDecoBuffer(buf, flag); if (dim) - buf->printf("%ju", dim->toInteger()); + buf->printf("%llu", dim->toInteger()); if (next) /* Note that static arrays are value types, so * for a parameter, propagate the 0x100 to the next @@ -4102,6 +4139,31 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc) return merge(); } +void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps) +{ + //printf("TypeDArray::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 a slice expression + Expression *e = new SliceExp(loc, *pe, NULL, NULL); + *pe = e; + } + else if (*ps) + { + TupleDeclaration *td = (*ps)->isTupleDeclaration(); + if (td) + ; // keep *ps + else + goto Ldefault; + } + else + { + Ldefault: + Type::resolve(loc, sc, pe, pt, ps); + } +} + void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag) { Type::toDecoBuffer(buf, flag); @@ -4373,8 +4435,8 @@ StructDeclaration *TypeAArray::getImpl() * which has Tident's instead of real types. */ Objects *tiargs = new Objects(); - tiargs->push(index); - tiargs->push(next); + tiargs->push(index->substWildTo(MODconst)); // hack for bug7757 + tiargs->push(next ->substWildTo(MODconst)); // hack for bug7757 // Create AssociativeArray!(index, next) #if 1 @@ -4514,8 +4576,12 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident) ident != Id::stringof && ident != Id::offsetof) { - e->type = getImpl()->type; - e = e->type->dotExp(sc, e, ident); +//printf("test1: %s, %s\n", e->toChars(), e->type->toChars()); + Type *t = getImpl()->type; +//printf("test2: %s, %s\n", e->toChars(), e->type->toChars()); + e->type = t; + e = t->dotExp(sc, e, ident); +//printf("test3: %s, %s\n", e->toChars(), e->type->toChars()); } else e = Type::dotExp(sc, e, ident); @@ -4559,6 +4625,22 @@ int TypeAArray::checkBoolean() return TRUE; } +Expression *TypeAArray::toExpression() +{ + Expression *e = next->toExpression(); + if (e) + { + Expression *ei = index->toExpression(); + if (ei) + { + Expressions *arguments = new Expressions(); + arguments->push(ei); + return new ArrayExp(loc, e, arguments); + } + } + return NULL; +} + int TypeAArray::hasPointers() { return TRUE; @@ -4590,11 +4672,7 @@ MATCH TypeAArray::implicitConvTo(Type *to) MATCH mi = index->constConv(ta->index); if (m != MATCHnomatch && mi != MATCHnomatch) { - if (m == MATCHexact && mod != to->mod) - m = MATCHconst; - if (mi < m) - m = mi; - return m; + return MODimplicitConv(mod, to->mod) ? MATCHconst : MATCHnomatch; } } else if (to->ty == Tstruct && ((TypeStruct *)to)->sym->ident == Id::AssociativeArray) @@ -4660,7 +4738,8 @@ Type *TypePointer::semantic(Loc loc, Scope *sc) deco = NULL; } next = n; - transitive(); + if (next->ty != Tfunction) + transitive(); return merge(); } @@ -4865,6 +4944,7 @@ TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, e this->purity = PUREimpure; this->isproperty = false; this->isref = false; + this->iswild = false; this->fargs = NULL; if (stc & STCpure) @@ -4910,9 +4990,10 @@ Type *TypeFunction::syntaxCopy() * 2 arguments match as far as overloading goes, * but types are not covariant * 3 cannot determine covariance because of forward references + * *pstc STCxxxx which would make it covariant */ -int Type::covariant(Type *t) +int Type::covariant(Type *t, StorageClass *pstc) { #if 0 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars()); @@ -4921,6 +5002,10 @@ int Type::covariant(Type *t) printf("mod = %x, %x\n", mod, t->mod); #endif + if (pstc) + *pstc = 0; + StorageClass stc = 0; + int inoutmismatch = 0; TypeFunction *t1; @@ -5024,35 +5109,39 @@ int Type::covariant(Type *t) goto Lnotcovariant; Lcovariant: + if (t1->isref != t2->isref) + goto Lnotcovariant; + /* Can convert mutable to const */ if (!MODimplicitConv(t2->mod, t1->mod)) - goto Lnotcovariant; -#if 0 - if (t1->mod != t2->mod) { - if (!(t1->mod & MODconst) && (t2->mod & MODconst)) - goto Lnotcovariant; - if (!(t1->mod & MODshared) && (t2->mod & MODshared)) + // If adding 'const' will make it covariant + if (MODimplicitConv(t2->mod, MODmerge(t1->mod, MODconst))) + stc |= STCconst; + else goto Lnotcovariant; } -#endif /* Can convert pure to impure, and nothrow to throw */ if (!t1->purity && t2->purity) - goto Lnotcovariant; + stc |= STCpure; if (!t1->isnothrow && t2->isnothrow) - goto Lnotcovariant; - - if (t1->isref != t2->isref) - goto Lnotcovariant; + stc |= STCnothrow; /* Can convert safe/trusted to system */ if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted) + // Should we infer trusted or safe? Go with safe. + stc |= STCsafe; + + if (stc) + { if (pstc) + *pstc = stc; goto Lnotcovariant; + } //printf("\tcovaraint: 1\n"); return 1; @@ -5317,10 +5406,14 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) tf->isnothrow = TRUE; if (sc->stc & STCref) tf->isref = TRUE; + if (sc->stc & STCsafe) tf->trust = TRUSTsafe; + if (sc->stc & STCsystem) + tf->trust = TRUSTsystem; if (sc->stc & STCtrusted) tf->trust = TRUSTtrusted; + if (sc->stc & STCproperty) tf->isproperty = TRUE; @@ -5328,13 +5421,15 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) /* If the parent is @safe, then this function defaults to safe * too. + * If the parent's @safe-ty is inferred, then this function's @safe-ty needs + * to be inferred first. */ if (tf->trust == TRUSTdefault) for (Dsymbol *p = sc->func; p; p = p->toParent2()) { FuncDeclaration *fd = p->isFuncDeclaration(); if (fd) { - if (fd->isSafe()) + if (fd->isSafeBypassingInference()) tf->trust = TRUSTsafe; // default to @safe break; } @@ -5371,7 +5466,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) } bool wildparams = FALSE; - bool wildsubparams = FALSE; if (tf->parameters) { /* Create a scope for evaluating the default arguments for the parameters @@ -5413,17 +5507,38 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) !(t->ty == Tpointer && t->nextOf()->ty == Tfunction || t->ty == Tdelegate)) { wildparams = TRUE; - if (tf->next && !wildreturn) - error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); + //if (tf->next && !wildreturn) + // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); } - else if (!wildsubparams && t->hasWild()) - wildsubparams = TRUE; if (fparam->defaultArg) - { - fparam->defaultArg = fparam->defaultArg->semantic(argsc); - fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg); - fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type); + { Expression *e = fparam->defaultArg; + e = e->inferType(fparam->type); + e = e->semantic(argsc); + e = resolveProperties(argsc, e); + if (e->op == TOKfunction) // see Bugzilla 4820 + { FuncExp *fe = (FuncExp *)e; + if (fe->fd) + { if (fe->fd->tok == TOKreserved) + { + if (fe->type->ty == Tpointer) + { + fe->fd->vthis = NULL; + fe->fd->tok = TOKfunction; + } + else + fe->fd->tok = TOKdelegate; + } + // Replace function literal with a function symbol, + // since default arg expression must be copied when used + // and copying the literal itself is wrong. + e = new VarExp(e->loc, fe->fd, 0); + e = new AddrExp(e->loc, e); + e = e->semantic(argsc); + } + } + e = e->implicitCastTo(argsc, fparam->type); + fparam->defaultArg = e; } /* If fparam after semantic() turns out to be a tuple, the number of parameters may @@ -5484,8 +5599,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) if (wildreturn && !wildparams) error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); - if (wildsubparams && wildparams) - error(loc, "inout must be all or none on top level for %s", toChars()); + tf->iswild = wildparams; if (tf->next) tf->deco = tf->merge()->deco; @@ -5496,8 +5610,8 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc) return terror; } - if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 1)) - error(loc, "properties can only have zero or one parameter"); + if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2)) + error(loc, "properties can only have zero, one, or two parameter"); if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0) error(loc, "variadic functions with non-D linkage must have at least one parameter"); @@ -5690,9 +5804,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = p->type; - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(p->type, 1); if (!arg) goto L1; // try typesafe variadics } @@ -5779,9 +5892,8 @@ int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag) assert(arg); #if 1 if (arg->op == TOKfunction) - { FuncExp *fe = (FuncExp *)arg; - Type *pt = tb->nextOf(); - arg = ((FuncExp *)arg)->inferType(NULL, pt); + { + arg = ((FuncExp *)arg)->inferType(tb->nextOf(), 1); if (!arg) goto Nomatch; } @@ -5841,16 +5953,16 @@ Nomatch: return MATCHnomatch; } -Type *TypeFunction::reliesOnTident() +Type *TypeFunction::reliesOnTident(TemplateParameters *tparams) { size_t dim = Parameter::dim(parameters); for (size_t i = 0; i < dim; i++) { Parameter *fparam = Parameter::getNth(parameters, i); - Type *t = fparam->type->reliesOnTident(); + Type *t = fparam->type->reliesOnTident(tparams); if (t) return t; } - return next ? next->reliesOnTident() : NULL; + return next ? next->reliesOnTident(tparams) : NULL; } /******************************************** @@ -5908,6 +6020,36 @@ Expression *TypeFunction::defaultInit(Loc loc) return new ErrorExp(); } +Type *TypeFunction::addStorageClass(StorageClass stc) +{ + TypeFunction *t = (TypeFunction *)Type::addStorageClass(stc); + if ((stc & STCpure && !t->purity) || + (stc & STCnothrow && !t->isnothrow) || + (stc & STCsafe && t->trust < TRUSTtrusted)) + { + // Klunky to change these + TypeFunction *tf = new TypeFunction(t->parameters, t->next, t->varargs, t->linkage, 0); + tf->mod = t->mod; + tf->fargs = fargs; + tf->purity = t->purity; + tf->isnothrow = t->isnothrow; + tf->isproperty = t->isproperty; + tf->isref = t->isref; + tf->trust = t->trust; + + if (stc & STCpure) + tf->purity = PUREfwdref; + if (stc & STCnothrow) + tf->isnothrow = true; + if (stc & STCsafe) + tf->trust = TRUSTsafe; + + tf->deco = tf->merge()->deco; + t = tf; + } + return t; +} + /***************************** TypeDelegate *****************************/ TypeDelegate::TypeDelegate(Type *t) @@ -6200,7 +6342,19 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc, else { Lerror: - error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); + if (id->dyncast() == DYNCAST_DSYMBOL) + { // searchX already handles errors for template instances + assert(global.errors); + } + else + { + sm = s->search_correct(id); + if (sm) + error(loc, "identifier '%s' of '%s' is not defined, did you mean '%s %s'?", + id->toChars(), toChars(), sm->kind(), sm->toChars()); + else + error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars()); + } *pe = new ErrorExp(); } return; @@ -6437,10 +6591,6 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc) } else { -#ifdef DEBUG - if (!global.gag) - printf("1: "); -#endif if (s) { s->error(loc, "is used as a type"); @@ -6454,9 +6604,23 @@ Type *TypeIdentifier::semantic(Loc loc, Scope *sc) return t; } -Type *TypeIdentifier::reliesOnTident() +Type *TypeIdentifier::reliesOnTident(TemplateParameters *tparams) { - return this; + if (tparams) + { + if (idents.dim == 0) + { + for (size_t i = 0; i < tparams->dim; i++) + { TemplateParameter *tp = tparams->tdata()[i]; + + if (tp->ident->equals(ident)) + return this; + } + } + return NULL; + } + else + return this; } Expression *TypeIdentifier::toExpression() @@ -6537,12 +6701,11 @@ Type *TypeInstance::semantic(Loc loc, Scope *sc) Expression *e; Dsymbol *s; - //printf("TypeInstance::semantic(%s)\n", toChars()); + //printf("TypeInstance::semantic(%p, %s)\n", this, toChars()); if (sc->parameterSpecialization) { unsigned errors = global.startGagging(); - resolve(loc, sc, &e, &t, &s); if (global.endGagging(errors)) @@ -6691,8 +6854,14 @@ Type *TypeTypeof::semantic(Loc loc, Scope *sc) { Scope *sc2 = sc->push(); sc2->intypeof++; + sc2->speculative = true; sc2->flags |= sc->flags & SCOPEstaticif; + unsigned oldspecgag = global.speculativeGag; + if (global.gag) + global.speculativeGag = global.gag; exp = exp->semantic(sc2); + global.speculativeGag = oldspecgag; + #if DMDV2 if (exp->type && exp->type->ty == Tfunction && ((TypeFunction *)exp->type)->isproperty) @@ -6883,9 +7052,6 @@ unsigned TypeEnum::alignsize() { if (!sym->memtype) { -#ifdef DEBUG - printf("1: "); -#endif error(0, "enum %s is forward referenced", sym->toChars()); return 4; } @@ -6912,9 +7078,6 @@ Type *TypeEnum::toBasetype() } if (!sym->memtype) { -#ifdef DEBUG - printf("2: "); -#endif error(sym->loc, "enum %s is forward referenced", sym->toChars()); return tint32; } @@ -7099,9 +7262,6 @@ int TypeEnum::isZeroInit(Loc loc) } if (!sym->defaultval) { -#ifdef DEBUG - printf("3: "); -#endif error(loc, "enum %s is forward referenced", sym->toChars()); return 0; } @@ -7707,10 +7867,17 @@ Expression *TypeStruct::defaultInitLiteral(Loc loc) e = vd->init->toExpression(); } else - e = vd->type->defaultInitLiteral(); - structelems->tdata()[j] = e; + e = vd->type->defaultInitLiteral(loc); + (*structelems)[j] = e; } StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); + + /* Copy from the initializer symbol for larger symbols, + * otherwise the literals expressed as code get excessively large. + */ + if (size(loc) > PTRSIZE * 4) + structinit->sinit = sym->toInitializer(); + // Why doesn't the StructLiteralExp constructor do this, when // sym->type != NULL ? structinit->type = sym->type; @@ -7788,7 +7955,7 @@ MATCH TypeStruct::implicitConvTo(Type *to) { MATCH m; //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars()); - if (to->ty == Taarray) + if (to->ty == Taarray && sym->ident == Id::AssociativeArray) { /* If there is an error instantiating AssociativeArray!(), it shouldn't * be reported -- it just means implicit conversion is impossible. @@ -8244,7 +8411,7 @@ L1: return e; } - DotVarExp *de = new DotVarExp(e->loc, e, d); + DotVarExp *de = new DotVarExp(e->loc, e, d, d->hasOverloads()); return de->semantic(sc); } @@ -8480,14 +8647,14 @@ int TypeTuple::equals(Object *o) return 0; } -Type *TypeTuple::reliesOnTident() +Type *TypeTuple::reliesOnTident(TemplateParameters *tparams) { if (arguments) { for (size_t i = 0; i < arguments->dim; i++) { Parameter *arg = arguments->tdata()[i]; - Type *t = arg->type->reliesOnTident(); + Type *t = arg->type->reliesOnTident(tparams); if (t) return t; } @@ -8538,6 +8705,10 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) { e = new IntegerExp(loc, arguments->dim, Type::tsize_t); } + else if (ident == Id::init) + { + e = defaultInitLiteral(loc); + } else { error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars()); @@ -8546,6 +8717,22 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident) return e; } +Expression *TypeTuple::defaultInit(Loc loc) +{ + Expressions *exps = new Expressions(); + exps->setDim(arguments->dim); + for (size_t i = 0; i < arguments->dim; i++) + { + Parameter *p = (*arguments)[i]; + assert(p->type); + Expression *e = p->type->defaultInitLiteral(loc); + if (e->op == TOKerror) + return e; + (*exps)[i] = e; + } + return new TupleExp(loc, exps); +} + /***************************** TypeSlice *****************************/ /* This is so we can slice a TypeTuple */ @@ -8588,7 +8775,7 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc) uinteger_t i2 = upr->toUInteger(); if (!(i1 <= i2 && i2 <= tt->arguments->dim)) - { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim); + { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim); return Type::terror; } @@ -8634,7 +8821,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol sc = sc->pop(); if (!(i1 <= i2 && i2 <= td->objects->dim)) - { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim); + { error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim); goto Ldefault; } diff --git a/mtype.h b/mtype.h index b5bedf9e..109c124a 100644 --- a/mtype.h +++ b/mtype.h @@ -223,7 +223,7 @@ struct Type : Object virtual Type *syntaxCopy(); int equals(Object *o); int dyncast() { return DYNCAST_TYPE; } // kludge for template.isType() - int covariant(Type *t); + int covariant(Type *t, StorageClass *pstc = NULL); char *toChars(); static char needThisPrefix(); static void init(); @@ -275,7 +275,7 @@ struct Type : Object Type *addSTC(StorageClass stc); Type *castMod(unsigned mod); Type *addMod(unsigned mod); - Type *addStorageClass(StorageClass stc); + virtual Type *addStorageClass(StorageClass stc); Type *pointerTo(); Type *referenceTo(); Type *arrayOf(); @@ -301,7 +301,8 @@ struct Type : Object Expression *noMember(Scope *sc, Expression *e, Identifier *ident); virtual unsigned memalign(unsigned salign); virtual Expression *defaultInit(Loc loc = 0); - virtual Expression *defaultInitLiteral(Loc loc = 0); + virtual Expression *defaultInitLiteral(Loc loc); + virtual Expression *voidInitLiteral(VarDeclaration *var); virtual int isZeroInit(Loc loc = 0); // if initializer is 0 virtual dt_t **toDt(dt_t **pdt); Identifier *getTypeInfoIdent(int internal); @@ -311,7 +312,7 @@ struct Type : Object Expression *getTypeInfo(Scope *sc); virtual TypeInfoDeclaration *getTypeInfoDeclaration(); virtual int builtinTypeInfo(); - virtual Type *reliesOnTident(); + virtual Type *reliesOnTident(TemplateParameters *tparams = NULL); virtual int hasWild(); virtual Expression *toExpression(); virtual int hasPointers(); @@ -354,7 +355,7 @@ struct TypeNext : Type TypeNext(TY ty, Type *next); void toDecoBuffer(OutBuffer *buf, int flag); void checkDeprecated(Loc loc, Scope *sc); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); int hasWild(); Type *nextOf(); Type *makeConst(); @@ -416,6 +417,7 @@ struct TypeVector : Type char *toChars(); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toDecoBuffer(OutBuffer *buf, int flag); + MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif @@ -459,6 +461,7 @@ struct TypeSArray : TypeArray MATCH implicitConvTo(Type *to); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + Expression *voidInitLiteral(VarDeclaration *var); dt_t **toDt(dt_t **pdt); dt_t **toDtElem(dt_t **pdt, Expression *e); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); @@ -483,6 +486,7 @@ struct TypeDArray : TypeArray d_uns64 size(Loc loc); unsigned alignsize(); Type *semantic(Loc loc, Scope *sc); + void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps); void toDecoBuffer(OutBuffer *buf, int flag); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); @@ -525,6 +529,7 @@ struct TypeAArray : TypeArray int isZeroInit(Loc loc); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + Expression *toExpression(); int hasPointers(); TypeTuple *toArgTypes(); MATCH implicitConvTo(Type *to); @@ -612,6 +617,7 @@ struct TypeFunction : TypeNext enum LINK linkage; // calling convention enum TRUST trust; // level of trust enum PURE purity; // PURExxxx + bool iswild; // is inout function Expressions *fargs; // function arguments int inuse; @@ -627,12 +633,13 @@ struct TypeFunction : TypeNext void attributesToCBuffer(OutBuffer *buf, int mod); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); TypeInfoDeclaration *getTypeInfoDeclaration(); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); bool hasLazyParameters(); #if CPP_MANGLE void toCppMangle(OutBuffer *buf, CppMangleState *cms); #endif bool parameterEscapes(Parameter *p); + Type *addStorageClass(StorageClass stc); int callMatch(Expression *ethis, Expressions *toargs, int flag = 0); type *toCtype(); @@ -695,7 +702,7 @@ struct TypeIdentifier : TypeQualified Dsymbol *toDsymbol(Scope *sc); Type *semantic(Loc loc, Scope *sc); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch = NULL); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); Expression *toExpression(); }; @@ -755,6 +762,7 @@ struct TypeStruct : Type unsigned memalign(unsigned salign); Expression *defaultInit(Loc loc); Expression *defaultInitLiteral(Loc loc); + Expression *voidInitLiteral(VarDeclaration *var); int isZeroInit(Loc loc); int isAssignable(); int checkBoolean(); @@ -911,10 +919,11 @@ struct TypeTuple : Type Type *syntaxCopy(); Type *semantic(Loc loc, Scope *sc); int equals(Object *o); - Type *reliesOnTident(); + Type *reliesOnTident(TemplateParameters *tparams = NULL); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toDecoBuffer(OutBuffer *buf, int flag); Expression *getProperty(Loc loc, Identifier *ident); + Expression *defaultInit(Loc loc); TypeInfoDeclaration *getTypeInfoDeclaration(); }; @@ -979,6 +988,7 @@ struct Parameter : Object extern int PTRSIZE; extern int REALSIZE; extern int REALPAD; +extern int REALALIGNSIZE; extern int Tsize_t; extern int Tptrdiff_t; diff --git a/opover.c b/opover.c index 786fac06..34f89441 100644 --- a/opover.c +++ b/opover.c @@ -354,11 +354,9 @@ Expression *UnaExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } #endif } @@ -413,11 +411,9 @@ Expression *ArrayExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } } return NULL; @@ -460,11 +456,9 @@ Expression *CastExp::op_overload(Scope *sc) /* Rewrite op(e1) as: * op(e1.aliasthis) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad->aliasthis->ident); - Expression *e = copy(); - ((UnaExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + UnaExp *e = (UnaExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad->aliasthis->ident); + return e->trySemantic(sc); } } return NULL; @@ -720,11 +714,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -737,11 +729,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } #endif return NULL; @@ -893,11 +883,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -906,11 +894,9 @@ Expression *BinExp::compare_overload(Scope *sc, Identifier *id) /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } return NULL; @@ -1055,6 +1041,10 @@ Expression *BinAssignExp::op_overload(Scope *sc) e1 = resolveProperties(sc, e1); e2 = resolveProperties(sc, e2); + // Don't attempt 'alias this' if an error occured + if (e1->type->ty == Terror || e2->type->ty == Terror) + return new ErrorExp(); + Identifier *id = opId(); Expressions args2; @@ -1141,11 +1131,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1.aliasthis op e2) */ - Expression *e1 = new DotIdExp(loc, this->e1, ad1->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e1 = e1; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e1 = new DotIdExp(loc, e->e1, ad1->aliasthis->ident); + return e->trySemantic(sc); } // Try alias this on second operand @@ -1155,11 +1143,9 @@ L1: /* Rewrite (e1 op e2) as: * (e1 op e2.aliasthis) */ - Expression *e2 = new DotIdExp(loc, this->e2, ad2->aliasthis->ident); - Expression *e = copy(); - ((BinExp *)e)->e2 = e2; - e = e->trySemantic(sc); - return e; + BinExp *e = (BinExp *)syntaxCopy(); + e->e2 = new DotIdExp(loc, e->e2, ad2->aliasthis->ident); + return e->trySemantic(sc); } #endif return NULL; diff --git a/optimize.c b/optimize.c index 315c1793..232fe4a7 100644 --- a/optimize.c +++ b/optimize.c @@ -381,7 +381,7 @@ Expression *AddrExp::optimize(int result) TypeSArray *ts = (TypeSArray *)ve->type; dinteger_t dim = ts->dim->toInteger(); if (index < 0 || index >= dim) - error("array index %jd is out of bounds [0..%jd]", index, dim); + error("array index %lld is out of bounds [0..%lld]", index, dim); e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size()); e->type = type; return e; @@ -633,7 +633,7 @@ Expression *CastExp::optimize(int result) } // We can convert 'head const' to mutable - if (to->constOf()->equals(e1->type->constOf())) + if (to->mutableOf()->constOf()->equals(e1->type->mutableOf()->constOf())) { e1->type = type; if (X) printf(" returning5 %s\n", e1->toChars()); @@ -679,7 +679,7 @@ Expression *BinExp::optimize(int result) dinteger_t i2 = e2->toInteger(); d_uns64 sz = e1->type->size() * 8; if (i2 < 0 || i2 >= sz) - { error("shift assign by %jd is outside the range 0..%zu", i2, sz - 1); + { error("shift assign by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1); e2 = new IntegerExp(0); } } @@ -774,7 +774,7 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E dinteger_t i2 = e->e2->toInteger(); d_uns64 sz = e->e1->type->size() * 8; if (i2 < 0 || i2 >= sz) - { e->error("shift by %jd is outside the range 0..%zu", i2, sz - 1); + { e->error("shift by %lld is outside the range 0..%llu", i2, (ulonglong)sz - 1); e->e2 = new IntegerExp(0); } if (e->e1->isConst() == 1) @@ -863,7 +863,7 @@ Expression *PowExp::optimize(int result) if (e1->type->isintegral()) e = new IntegerExp(loc, 1, e1->type); else - e = new RealExp(loc, 1.0, e1->type); + e = new RealExp(loc, ldouble(1.0), e1->type); e = new CommaExp(loc, e1, e); } @@ -876,7 +876,7 @@ Expression *PowExp::optimize(int result) // Replace x ^^ -1.0 by (1.0 / x) else if ((e2->op == TOKfloat64 && e2->toReal() == -1.0)) { - e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1); + e = new DivExp(loc, new RealExp(loc, ldouble(1.0), e2->type), e1); } // All other negative integral powers are illegal else if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0) diff --git a/parse.c b/parse.c index addefc74..67ffe6b9 100644 --- a/parse.c +++ b/parse.c @@ -130,7 +130,7 @@ Dsymbols *Parser::parseModule() decldefs = parseDeclDefs(0); if (token.value != TOKeof) - { error("unrecognized declaration"); + { error(loc, "unrecognized declaration"); goto Lerr; } return decldefs; @@ -1377,8 +1377,15 @@ Parameters *Parser::parseParameters(int *pvarargs, TemplateParameters **tpl) error("scope cannot be ref or out"); Token *t; +#if 0 if (tpl && !stc && token.value == TOKidentifier && (t = peek(&token), (t->value == TOKcomma || t->value == TOKrparen))) +#else + if (tpl && token.value == TOKidentifier && + (t = peek(&token), (t->value == TOKcomma || + t->value == TOKrparen || + t->value == TOKdotdotdot))) +#endif { Identifier *id = Lexer::uniqueId("__T"); at = new TypeIdentifier(loc, id); if (!*tpl) @@ -3561,6 +3568,9 @@ Statement *Parser::parseStatement(int flags) goto Ldeclaration; case BASIC_TYPES: + // bug 7773: int.max is always a part of expression + if (peekNext() == TOKdot) + goto Lexp; case TOKtypedef: case TOKalias: case TOKconst: @@ -5472,15 +5482,18 @@ Expression *Parser::parsePrimaryExp() } case TOKlparen: - { enum TOK past = peekPastParen(&token)->value; - - if (past == TOKgoesto) - { // (arguments) => expression - goto case_delegate; - } - else if (past == TOKlcurly) - { // (arguments) { statements... } - goto case_delegate; + { Token *tk = peekPastParen(&token); + if (skipAttributes(tk, &tk)) + { + enum TOK past = tk->value; + if (past == TOKgoesto) + { // (arguments) => expression + goto case_delegate; + } + else if (past == TOKlcurly) + { // (arguments) { statements... } + goto case_delegate; + } } // ( expression ) nextToken(); @@ -6589,6 +6602,7 @@ void initPrecedence() precedence[TOKtraits] = PREC_primary; precedence[TOKdefault] = PREC_primary; precedence[TOKoverloadset] = PREC_primary; + precedence[TOKvoid] = PREC_primary; #endif // post diff --git a/posix.mak b/posix.mak index b35596eb..87c9abfb 100644 --- a/posix.mak +++ b/posix.mak @@ -57,11 +57,11 @@ CC=$(HOST_CC) -m$(MODEL) $(TARGET_CFLAGS) WARNINGS=-Wno-deprecated -Wstrict-aliasing -#GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) -GFLAGS = $(WARNINGS) -D__near= -D__pascal= -fno-exceptions -O2 +#GFLAGS = $(WARNINGS) -D__pascal= -fno-exceptions -g -DDEBUG=1 -DUNITTEST $(COV) +GFLAGS = $(WARNINGS) -D__pascal= -fno-exceptions -O2 CFLAGS = $(GFLAGS) -I$(ROOT) -DMARS=1 -DTARGET_$(TARGET)=1 -MFLAGS = $(GFLAGS) -I$C -I$(TK) -DMARS=1 -DTARGET_$(TARGET)=1 +MFLAGS = $(GFLAGS) -I$C -I$(TK) -I$(ROOT) -DMARS=1 -DTARGET_$(TARGET)=1 CH= $C/cc.h $C/global.h $C/oper.h $C/code.h $C/type.h \ $C/dt.h $C/cgcv.h $C/el.h $C/iasm.h @@ -137,6 +137,7 @@ SRC = win32.mak posix.mak \ $(ROOT)/stringtable.h $(ROOT)/stringtable.c \ $(ROOT)/response.c $(ROOT)/async.h $(ROOT)/async.c \ $(ROOT)/aav.h $(ROOT)/aav.c \ + $(ROOT)/longdouble.h $(ROOT)/longdouble.c \ $(ROOT)/speller.h $(ROOT)/speller.c @@ -528,7 +529,7 @@ stringtable.o: $(ROOT)/stringtable.c $(CC) -c $(GFLAGS) -I$(ROOT) $< strtold.o: $C/strtold.c - gcc -m$(MODEL) -c $< + gcc -m$(MODEL) -I$(ROOT) -c $< struct.o: struct.c $(CC) -c $(CFLAGS) $< diff --git a/root/dchar.h b/root/dchar.h index 2b8df523..6ac7994c 100644 --- a/root/dchar.h +++ b/root/dchar.h @@ -152,10 +152,10 @@ typedef char dchar; struct Dchar { static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { return p - 1; } + static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } static int len(const dchar *p) { return strlen(p); } static int get(dchar *p) { return *p & 0xFF; } - static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; } + static int getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1] & 0xFF; } static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } diff --git a/root/longdouble.c b/root/longdouble.c new file mode 100644 index 00000000..8a0f00e7 --- /dev/null +++ b/root/longdouble.c @@ -0,0 +1,636 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Rainer Schuetze +// 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. + +// 80 bit floating point value implementation for Microsoft compiler + +#if _MSC_VER +#include "longdouble.h" + +#include "assert.h" + +#include +#include +#include + +extern "C" +{ + // implemented in ldfpu.asm for _WIN64 + int ld_initfpu(int bits, int mask); + void ld_expl(longdouble* ld, int exp); + longdouble ld_add(longdouble ld1, longdouble ld2); + longdouble ld_sub(longdouble ld1, longdouble ld2); + longdouble ld_mul(longdouble ld1, longdouble ld2); + longdouble ld_div(longdouble ld1, longdouble ld2); + longdouble ld_mod(longdouble ld1, longdouble ld2); + bool ld_cmpb(longdouble ld1, longdouble ld2); + bool ld_cmpbe(longdouble ld1, longdouble ld2); + bool ld_cmpa(longdouble ld1, longdouble ld2); + bool ld_cmpae(longdouble ld1, longdouble ld2); + bool ld_cmpe(longdouble ld1, longdouble ld2); + bool ld_cmpne(longdouble ld1, longdouble ld2); + longdouble ld_sqrt(longdouble ld1); + longdouble ld_sin(longdouble ld1); + longdouble ld_cos(longdouble ld1); + longdouble ld_tan(longdouble ld1); +} + +bool initFPU() +{ +#ifdef _WIN64 +// int old_cw = ld_initfpu(_RC_NEAR); + int old_cw = ld_initfpu(0x300 /*_PC_64 | _RC_NEAR*/, // #defines NOT identical to CPU FPU control word! + 0xF00 /*_MCW_PC | _MCW_RC*/); +#else + int old_cw = _control87(_MCW_EM | _PC_64 | _RC_NEAR, + _MCW_EM | _MCW_PC | _MCW_RC); +#endif + return true; +} +static bool doInitFPU = initFPU(); + +#ifndef _WIN64 +extern "C" +{ + +double ld_read(const longdouble* pthis) +{ + double res; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fstp res + } + return res; +} +long long ld_readll(const longdouble* pthis) +{ +#if 1 + return ld_readull(pthis); +#elif defined _WIN64 + return ld_readll(this); +#else + longdouble* pthis = this; + long long res; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fistp qword ptr res + } + return res; +#endif +} + +unsigned long long ld_readull(const longdouble* pthis) +{ +#if 1 + // somehow the FPU does not respect the CHOP mode of the rounding control + // in 64-bit mode + // so we roll our own conversion (it also allows the usual C wrap-around + // instead of the "invalid value" created by the FPU) + int expo = pthis->exponent - 0x3fff; + unsigned long long u; + if(expo < 0 || expo > 127) + return 0; + if(expo < 64) + u = pthis->mantissa >> (63 - expo); + else + u = pthis->mantissa << (expo - 63); + if(pthis->sign) + u = ~u + 1; + return u; +#else + longdouble* pthis = this; + long long res; // cannot use unsigned, VC will not generate "fistp qword" + longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 }; + __asm + { + mov eax, pthis + fld tbyte ptr [eax] + fld tbyte ptr twoPow63 + fsubp ST(1),ST(0) // move it into signed range + + lea eax, res + fistp qword ptr [eax] + } + res ^= (1LL << 63); + return res; +#endif +} + +void ld_set(longdouble* pthis, double d) +{ + __asm + { + mov eax, pthis + fld d + fstp tbyte ptr [eax] + } +} +void ld_setll(longdouble* pthis, long long d) +{ + __asm + { + fild qword ptr d + mov eax, pthis + fstp tbyte ptr [eax] + } +} +void ld_setull(longdouble* pthis, unsigned long long d) +{ + d ^= (1LL << 63); + longdouble twoPow63 = { 1ULL << 63, 0x3fff + 63, 0 }; + __asm + { + fild qword ptr d + fld tbyte ptr twoPow63 + faddp ST(1),ST(0) + mov eax, pthis + fstp tbyte ptr [eax] + } +} + +} // extern "C" +#endif // !_WIN64 + +longdouble ldexpl(longdouble ld, int exp) +{ +#ifdef _WIN64 + ld_expl(&ld, exp); +#else + __asm + { + fild dword ptr exp + fld tbyte ptr ld + fscale // ST(0) = ST(0) * (2**ST(1)) + fstp ST(1) + fstp tbyte ptr ld + } +#endif + return ld; +} + +/////////////////////////////////////////////////////////////////////// +longdouble operator+(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_add(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fadd + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator-(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_sub(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fsub + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator*(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_mul(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fmul + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble operator/(longdouble ld1, longdouble ld2) +{ +#ifdef _WIN64 + return ld_div(ld1, ld2); +#else + longdouble res; + __asm + { + fld tbyte ptr ld1 + fld tbyte ptr ld2 + fdiv + fstp tbyte ptr res; + } + return res; +#endif +} + +bool operator< (longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpb(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setb AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator<=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpbe(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setbe AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator> (longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpa(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + seta AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator>=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpae(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setae AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator==(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpe(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + sete AL + setnp AH + and AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} +bool operator!=(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_cmpne(x, y); +#else + short sw; + bool res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y + fucomip ST(0),ST(1) + setne AL + setp AH + or AL,AH + mov res,AL + fstp ST(0) + } + return res; +#endif +} + + +int _isnan(longdouble ld) +{ + return (ld.exponent == 0x7fff && ld.mantissa != 0); +} + +longdouble fabsl(longdouble ld) +{ + ld.sign = 0; + return ld; +} + +longdouble sqrtl(longdouble ld) +{ +#ifdef _WIN64 + return ld_sqrt(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fsqrt; + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble sinl (longdouble ld) +{ +#ifdef _WIN64 + return ld_sin(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fsin; // exact for |x|<=PI/4 + fstp tbyte ptr res + } + return res; +#endif +} +longdouble cosl (longdouble ld) +{ +#ifdef _WIN64 + return ld_cos(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fcos; // exact for |x|<=PI/4 + fstp tbyte ptr res; + } + return res; +#endif +} +longdouble tanl (longdouble ld) +{ +#ifdef _WIN64 + return ld_tan(ld); +#else + longdouble res; + __asm + { + fld tbyte ptr ld; + fptan; + fstp ST(0); // always 1 + fstp tbyte ptr res; + } + return res; +#endif +} + +longdouble fmodl(longdouble x, longdouble y) +{ +#ifdef _WIN64 + return ld_mod(x, y); +#else + short sw; + longdouble res; + __asm + { + fld tbyte ptr y + fld tbyte ptr x // ST = x, ST1 = y +FM1: // We don't use fprem1 because for some inexplicable + // reason we get -5 when we do _modulo(15, 10) + fprem // ST = ST % ST1 + fstsw word ptr sw + fwait + mov AH,byte ptr sw+1 // get msb of status word in AH + sahf // transfer to flags + jp FM1 // continue till ST < ST1 + fstp ST(1) // leave remainder on stack + fstp tbyte ptr res; + } + return res; +#endif +} + +////////////////////////////////////////////////////////////// + +longdouble ld_qnan = { 0x8000000000000000ULL, 0x7fff, 0 }; +longdouble ld_snan = { 0x0000000000000001ULL, 0x7fff, 0 }; +longdouble ld_inf = { 0x0000000000000000ULL, 0x7fff, 0 }; + +longdouble ld_zero = { 0, 0, 0 }; +longdouble ld_one = { 0x8000000000000000ULL, 0x3fff, 0 }; +longdouble ld_pi = { 0xc90fdaa22168c235ULL, 0x4000, 0 }; +longdouble ld_log2t = { 0xd49a784bcd1b8afeULL, 0x4000, 0 }; +longdouble ld_log2e = { 0xb8aa3b295c17f0bcULL, 0x3fff, 0 }; +longdouble ld_log2 = { 0x9a209a84fbcff799ULL, 0x3ffd, 0 }; +longdouble ld_ln2 = { 0xb17217f7d1cf79acULL, 0x3ffe, 0 }; + +longdouble ld_pi2 = ld_pi*2; +longdouble ld_piOver2 = ld_pi*0.5; +longdouble ld_piOver4 = ld_pi*0.25; + +////////////////////////////////////////////////////////////// + +#define LD_TYPE_OTHER 0 +#define LD_TYPE_ZERO 1 +#define LD_TYPE_INFINITE 2 +#define LD_TYPE_SNAN 3 +#define LD_TYPE_QNAN 4 + +int ld_type(longdouble x) +{ + if(x.exponent == 0) + return x.mantissa == 0 ? LD_TYPE_ZERO : LD_TYPE_OTHER; // dnormal if not zero + if(x.exponent != 0x7fff) + return LD_TYPE_OTHER; + if(x.mantissa == 0) + return LD_TYPE_INFINITE; + if(x.mantissa & (1LL << 63)) + return LD_TYPE_QNAN; + return LD_TYPE_SNAN; +} + +int ld_sprint(char* str, int fmt, longdouble x) +{ + // fmt is 'a','A','f' or 'g' + if(fmt != 'a' && fmt != 'A') + { + char format[] = { '%', fmt, 0 }; + return sprintf(str, format, ld_read(&x)); + } + + unsigned short exp = x.exponent; + unsigned long long mantissa = x.mantissa; + + switch(ld_type(x)) + { + case LD_TYPE_ZERO: + return sprintf(str, "0x0.0L"); + case LD_TYPE_QNAN: + case LD_TYPE_SNAN: + return sprintf(str, "NAN"); + case LD_TYPE_INFINITE: + return sprintf(str, x.sign ? "-INF" : "INF"); + } + + int len = 0; + if(x.sign) + str[len++] = '-'; + len += sprintf(str + len, mantissa & (1LL << 63) ? "0x1." : "0x0."); + mantissa = mantissa << 1; + while(mantissa) + { + int dig = (mantissa >> 60) & 0xf; + dig += dig < 10 ? '0' : fmt - 10; + str[len++] = dig; + mantissa = mantissa << 4; + } + str[len++] = 'p'; + if(exp < 0x3fff) + { + str[len++] = '-'; + exp = 0x3fff - exp; + } + else + { + str[len++] = '+'; + exp = exp - 0x3fff; + } + int exppos = len; + for(int i = 12; i >= 0; i -= 4) + { + int dig = (exp >> i) & 0xf; + if(dig != 0 || len > exppos || i == 0) + str[len++] = dig + (dig < 10 ? '0' : fmt - 10); + } + str[len] = 0; + return len; +} + +////////////////////////////////////////////////////////////// + +#if UNITTEST +static bool unittest() +{ + char buffer[32]; + ld_sprint(buffer, 'a', ld_pi); + assert(strcmp(buffer, "0x1.921fb54442d1846ap+1") == 0); + + longdouble ldb = ldouble(0.4); + long long b = ldb; + assert(b == 0); + + b = ldouble(0.9); + assert(b == 0); + + long long x = 0x12345678abcdef78LL; + longdouble ldx = ldouble(x); + assert(ldx > 0); + long long y = ldx; + assert(x == y); + + x = -0x12345678abcdef78LL; + ldx = ldouble(x); + assert(ldx < 0); + y = ldx; + assert(x == y); + + unsigned long long u = 0x12345678abcdef78LL; + longdouble ldu = ldouble(u); + assert(ldu > 0); + unsigned long long v = ldu; + assert(u == v); + + u = 0xf234567812345678ULL; + ldu = ldouble(u); + assert(ldu > 0); + v = ldu; + assert(u == v); + + u = 0xf2345678; + ldu = ldouble(u); + ldu = ldu * ldu; + ldu = sqrt(ldu); + v = ldu; + assert(u == v); + + u = 0x123456789A; + ldu = ldouble(u); + ldu = ldu * (1LL << 23); + v = ldu; + u = u * (1LL << 23); + assert(u == v); + + return true; +} + +static bool runUnittest = unittest(); + +#endif // UNITTEST + +#endif // _MSC_VER + diff --git a/root/longdouble.h b/root/longdouble.h new file mode 100644 index 00000000..d25223a7 --- /dev/null +++ b/root/longdouble.h @@ -0,0 +1,254 @@ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2011 by Digital Mars +// All Rights Reserved +// written by Rainer Schuetze +// 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. + +// 80 bit floating point value implementation for Microsoft compiler + +#ifndef __LONG_DOUBLE_H__ +#define __LONG_DOUBLE_H__ + +#if IN_GCC +#include "d-gcc-real.h" +typedef real_t longdouble; + +template longdouble ldouble(T x) { return (longdouble) x; } +inline int ld_sprint(char* str, int fmt, longdouble x) +{ + if(fmt == 'a' || fmt == 'A') + return x.formatHex(buffer, 46); // don't know the size here, but 46 is the max + return x.format(buffer, 46); +} + +#elif !_MSC_VER // has native 10 byte doubles +#include +typedef long double longdouble; +typedef volatile long double volatile_longdouble; + +// also used from within C code, so use a #define rather than a template +// template longdouble ldouble(T x) { return (longdouble) x; } +#define ldouble(x) ((longdouble)(x)) + +inline int ld_sprint(char* str, int fmt, longdouble x) +{ + char sfmt[4] = "%Lg"; + sfmt[2] = fmt; + return sprintf(str, sfmt, x); +} + +#else + +#include +#include + +struct longdouble; + +extern "C" +{ + // implemented in ldfpu.asm for _WIN64 + double ld_read(const longdouble* ld); + long long ld_readll(const longdouble* ld); + unsigned long long ld_readull(const longdouble* ld); + void ld_set(longdouble* ld, double d); + void ld_setll(longdouble* ld, long long d); + void ld_setull(longdouble* ld, unsigned long long d); +} + +struct longdouble +{ + unsigned long long mantissa; + unsigned short exponent:15; // bias 0x3fff + unsigned short sign:1; + unsigned short fill:16; // for 12 byte alignment + + // no constructor to be able to use this class in a union + // use ldouble() to explicitely create a longdouble value + + template longdouble& operator=(T x) { set(x); return *this; } + + void set(longdouble ld) { mantissa = ld.mantissa; exponent = ld.exponent; sign = ld.sign; } + + // we need to list all basic types to avoid ambiguities + void set(float d) { ld_set(this, d); } + void set(double d) { ld_set(this, d); } + void set(long double d) { ld_set(this, d); } + + void set(signed char d) { ld_set(this, d); } + void set(short d) { ld_set(this, d); } + void set(int d) { ld_set(this, d); } + void set(long d) { ld_set(this, d); } + void set(long long d) { ld_setll(this, d); } + + void set(unsigned char d) { ld_set(this, d); } + void set(unsigned short d) { ld_set(this, d); } + void set(unsigned int d) { ld_set(this, d); } + void set(unsigned long d) { ld_set(this, d); } + void set(unsigned long long d) { ld_setull(this, d); } + void set(bool d) { ld_set(this, d); } + + operator float () { return ld_read(this); } + operator double () { return ld_read(this); } + + operator signed char () { return ld_read(this); } + operator short () { return ld_read(this); } + operator int () { return ld_read(this); } + operator long () { return ld_read(this); } + operator long long () { return ld_readll(this); } + + operator unsigned char () { return ld_read(this); } + operator unsigned short () { return ld_read(this); } + operator unsigned int () { return ld_read(this); } + operator unsigned long () { return ld_read(this); } + operator unsigned long long() { return ld_readull(this); } + operator bool () { return mantissa != 0 || exponent != 0; } // correct? +}; + +// some optimizations are avoided by adding volatile to the longdouble +// type, but this introduces bad ambiguities when using the class implementation above +// as we are going through asm these optimizations won't kick in anyway, so "volatile" +// is not required. +typedef longdouble volatile_longdouble; + +inline longdouble ldouble(unsigned long long mantissa, int exp, int sign = 0) +{ + longdouble d; + d.mantissa = mantissa; + d.exponent = exp; + d.sign = sign; + return d; +} +template inline longdouble ldouble(T x) { longdouble d; d.set(x); return d; } +//template inline longdouble ldouble(volatile T x) { longdouble d; d.set(x); return d; } + +longdouble operator+(longdouble ld1, longdouble ld2); +longdouble operator-(longdouble ld1, longdouble ld2); +longdouble operator*(longdouble ld1, longdouble ld2); +longdouble operator/(longdouble ld1, longdouble ld2); + +bool operator< (longdouble ld1, longdouble ld2); +bool operator<=(longdouble ld1, longdouble ld2); +bool operator> (longdouble ld1, longdouble ld2); +bool operator>=(longdouble ld1, longdouble ld2); +bool operator==(longdouble ld1, longdouble ld2); +bool operator!=(longdouble ld1, longdouble ld2); + +inline longdouble operator-(longdouble ld1) { ld1.sign ^= 1; return ld1; } +inline longdouble operator+(longdouble ld1) { return ld1; } + +template inline longdouble operator+(longdouble ld, T x) { return ld + ldouble(x); } +template inline longdouble operator-(longdouble ld, T x) { return ld - ldouble(x); } +template inline longdouble operator*(longdouble ld, T x) { return ld * ldouble(x); } +template inline longdouble operator/(longdouble ld, T x) { return ld / ldouble(x); } + +template inline longdouble operator+(T x, longdouble ld) { return ldouble(x) + ld; } +template inline longdouble operator-(T x, longdouble ld) { return ldouble(x) - ld; } +template inline longdouble operator*(T x, longdouble ld) { return ldouble(x) * ld; } +template inline longdouble operator/(T x, longdouble ld) { return ldouble(x) / ld; } + +template inline longdouble& operator+=(longdouble& ld, T x) { return ld = ld + x; } +template inline longdouble& operator-=(longdouble& ld, T x) { return ld = ld - x; } +template inline longdouble& operator*=(longdouble& ld, T x) { return ld = ld * x; } +template inline longdouble& operator/=(longdouble& ld, T x) { return ld = ld / x; } + +template inline bool operator< (longdouble ld, T x) { return ld < ldouble(x); } +template inline bool operator<=(longdouble ld, T x) { return ld <= ldouble(x); } +template inline bool operator> (longdouble ld, T x) { return ld > ldouble(x); } +template inline bool operator>=(longdouble ld, T x) { return ld >= ldouble(x); } +template inline bool operator==(longdouble ld, T x) { return ld == ldouble(x); } +template inline bool operator!=(longdouble ld, T x) { return ld != ldouble(x); } + +template inline bool operator< (T x, longdouble ld) { return ldouble(x) < ld; } +template inline bool operator<=(T x, longdouble ld) { return ldouble(x) <= ld; } +template inline bool operator> (T x, longdouble ld) { return ldouble(x) > ld; } +template inline bool operator>=(T x, longdouble ld) { return ldouble(x) >= ld; } +template inline bool operator==(T x, longdouble ld) { return ldouble(x) == ld; } +template inline bool operator!=(T x, longdouble ld) { return ldouble(x) != ld; } + +int _isnan(longdouble ld); + +longdouble fabsl(longdouble ld); +longdouble sqrtl(longdouble ld); +longdouble sinl (longdouble ld); +longdouble cosl (longdouble ld); +longdouble tanl (longdouble ld); + +longdouble fmodl(longdouble x, longdouble y); +longdouble ldexpl(longdouble ldval, int exp); // see strtold + +inline longdouble fabs (longdouble ld) { return fabsl(ld); } +inline longdouble sqrt (longdouble ld) { return sqrtl(ld); } + +#undef LDBL_DIG +#undef LDBL_MAX +#undef LDBL_MIN +#undef LDBL_EPSILON +#undef LDBL_MANT_DIG +#undef LDBL_MAX_EXP +#undef LDBL_MIN_EXP +#undef LDBL_MAX_10_EXP +#undef LDBL_MIN_10_EXP + +#define LDBL_DIG 18 +#define LDBL_MAX ldouble(0xffffffffffffffffULL, 0x7ffe) +#define LDBL_MIN ldouble(0x8000000000000000ULL, 1) +#define LDBL_EPSILON ldouble(0x8000000000000000ULL, 0x3fff - 63) // allow denormal? +#define LDBL_MANT_DIG 64 +#define LDBL_MAX_EXP 16384 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MAX_10_EXP 4932 +#define LDBL_MIN_10_EXP (-4932) + +extern longdouble ld_zero; +extern longdouble ld_one; +extern longdouble ld_pi; +extern longdouble ld_log2t; +extern longdouble ld_log2e; +extern longdouble ld_log2; +extern longdouble ld_ln2; + +extern longdouble ld_inf; +extern longdouble ld_qnan; +extern longdouble ld_snan; + +/////////////////////////////////////////////////////////////////////// +// CLASS numeric_limits +template<> class _CRTIMP2_PURE std::numeric_limits +: public _Num_float_base +{ // limits for type long double +public: + typedef longdouble _Ty; + + static _Ty (__CRTDECL min)() _THROW0() { return LDBL_MIN; } + static _Ty (__CRTDECL max)() _THROW0() { return LDBL_MAX; } + static _Ty __CRTDECL epsilon() _THROW0() { return LDBL_EPSILON; } + static _Ty __CRTDECL round_error() _THROW0() { return ldouble(0.5); } + static _Ty __CRTDECL denorm_min() _THROW0() { return ldouble(0x0000000000000001ULL, 1); } + static _Ty __CRTDECL infinity() _THROW0() { return ld_inf; } + static _Ty __CRTDECL quiet_NaN() _THROW0() { return ld_qnan; } + static _Ty __CRTDECL signaling_NaN() _THROW0() { return ld_snan; } + + _STCONS(int, digits, LDBL_MANT_DIG); + _STCONS(int, digits10, LDBL_DIG); + _STCONS(int, max_exponent, (int)LDBL_MAX_EXP); + _STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP); + _STCONS(int, min_exponent, (int)LDBL_MIN_EXP); + _STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP); +}; + +//_STCONSDEF(numeric_limits, int, digits) +//_STCONSDEF(numeric_limits, int, digits10) +//_STCONSDEF(numeric_limits, int, max_exponent) +//_STCONSDEF(numeric_limits, int, max_exponent10) +//_STCONSDEF(numeric_limits, int, min_exponent) +//_STCONSDEF(numeric_limits, int, min_exponent10) + +int ld_sprint(char* str, int fmt, longdouble x); + +#endif // !_MSC_VER + +#endif // __LONG_DOUBLE_H__ diff --git a/root/lstring.h b/root/lstring.h index 17a8e447..0c545790 100644 --- a/root/lstring.h +++ b/root/lstring.h @@ -19,8 +19,10 @@ struct Lstring { unsigned length; +#ifndef IN_GCC // Disable warning about nonstandard extension #pragma warning (disable : 4200) +#endif dchar string[]; static Lstring zero; // 0 length string diff --git a/root/port.c b/root/port.c index 59698cba..d2bcf067 100644 --- a/root/port.c +++ b/root/port.c @@ -17,14 +17,14 @@ double Port::nan = NAN; double Port::infinity = INFINITY; double Port::dbl_max = DBL_MAX; double Port::dbl_min = DBL_MIN; -long double Port::ldbl_max = LDBL_MAX; +longdouble Port::ldbl_max = LDBL_MAX; int Port::isNan(double r) { return ::isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return ::isnan(r); } @@ -37,7 +37,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +int Port::isSignallingNan(longdouble r) { /* A signalling NaN is a NaN with 0 as the most significant bit of * its significand, which is bit 62 of 0..79 for 80 bit reals. @@ -70,7 +70,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { return ::fmodl(x, y); } @@ -140,7 +140,7 @@ double Port::infinity = 1 / zero; double Port::dbl_max = DBL_MAX; double Port::dbl_min = DBL_MIN; -long double Port::ldbl_max = LDBL_MAX; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -151,7 +151,7 @@ static PortInitializer portinitializer; PortInitializer::PortInitializer() { - Port::infinity = std::numeric_limits::infinity(); + Port::infinity = std::numeric_limits::infinity(); } int Port::isNan(double r) @@ -159,7 +159,7 @@ int Port::isNan(double r) return ::_isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return ::_isnan(r); } @@ -172,7 +172,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +int Port::isSignallingNan(longdouble r) { /* MSVC doesn't have 80 bit long doubles */ @@ -206,7 +206,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { return ::fmodl(x, y); } @@ -351,7 +351,7 @@ double Port::nan = copysign(NAN, 1.0); double Port::infinity = 1 / zero; double Port::dbl_max = 1.7976931348623157e308; double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -366,9 +366,9 @@ PortInitializer::PortInitializer() #if __FreeBSD__ && __i386__ // LDBL_MAX comes out as infinity. Fix. - static unsigned char x[sizeof(long double)] = + static unsigned char x[sizeof(longdouble)] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F }; - Port::ldbl_max = *(long double *)&x[0]; + Port::ldbl_max = *(longdouble *)&x[0]; // FreeBSD defaults to double precision. Switch to extended precision. fpsetprec(FP_PE); #endif @@ -386,7 +386,7 @@ int Port::isNan(double r) #endif } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { #if __APPLE__ return __inline_isnan(r); @@ -406,7 +406,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +int Port::isSignallingNan(longdouble r) { /* A signalling NaN is a NaN with 0 as the most significant bit of * its significand, which is bit 62 of 0..79 for 80 bit reals. @@ -450,7 +450,7 @@ double Port::pow(double x, double y) return ::pow(x, y); } -long double Port::fmodl(long double x, long double y) +longdouble Port::fmodl(longdouble x, longdouble y) { #if __FreeBSD__ || __OpenBSD__ return ::fmod(x, y); // hack for now, fix later @@ -528,7 +528,7 @@ double Port::nan = NAN; double Port::infinity = 1 / zero; double Port::dbl_max = 1.7976931348623157e308; double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; +longdouble Port::ldbl_max = LDBL_MAX; struct PortInitializer { @@ -542,7 +542,7 @@ PortInitializer::PortInitializer() // gcc nan's have the sign bit set by default, so turn it off // Need the volatile to prevent gcc from doing incorrect // constant folding. - volatile long double foo; + volatile longdouble foo; foo = NAN; if (signbit(foo)) // signbit sometimes, not always, set foo = -foo; // turn off sign bit @@ -554,7 +554,7 @@ int Port::isNan(double r) return isnan(r); } -int Port::isNan(long double r) +int Port::isNan(longdouble r) { return isnan(r); } @@ -567,7 +567,7 @@ int Port::isSignallingNan(double r) return isNan(r) && !((((unsigned char*)&r)[6]) & 8); } -int Port::isSignallingNan(long double r) +int Port::isSignallingNan(longdouble r) { /* A signalling NaN is a NaN with 0 as the most significant bit of * its significand, which is bit 62 of 0..79 for 80 bit reals. @@ -649,144 +649,3 @@ char *Port::strupr(char *s) #endif -#if IN_GCC - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static double zero = 0; -double Port::nan = NAN; -double Port::infinity = 1 / zero; -double Port::dbl_max = 1.7976931348623157e308; -double Port::dbl_min = 5e-324; -long double Port::ldbl_max = LDBL_MAX; - -#include "d-gcc-real.h" -extern "C" bool real_isnan (const real_t *); - -struct PortInitializer -{ - PortInitializer(); -}; - -static PortInitializer portinitializer; - -PortInitializer::PortInitializer() -{ - Port::infinity = real_t::getinfinity(); - Port::nan = real_t::getnan(real_t::LongDouble); -} - -#undef isnan -int Port::isNan(double r) -{ -#if __APPLE__ - return __inline_isnan(r); -#else - return ::isnan(r); -#endif -} - -int Port::isNan(long double r) -{ - return real_isnan(&r); -} - -int Port::isSignallingNan(double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 51 of 0..63 for 64 bit doubles. - */ - return isNan(r) && !((((unsigned char*)&r)[6]) & 8); -} - -int Port::isSignallingNan(long double r) -{ - /* A signalling NaN is a NaN with 0 as the most significant bit of - * its significand, which is bit 62 of 0..79 for 80 bit reals. - */ - return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40); -} - -#undef isfinite -int Port::isFinite(double r) -{ - return ::finite(r); -} - -#undef isinf -int Port::isInfinity(double r) -{ - return ::isinf(r); -} - -#undef signbit -int Port::Signbit(double r) -{ - return (long)(((long *)&r)[1] & 0x80000000); -} - -double Port::floor(double d) -{ - return ::floor(d); -} - -double Port::pow(double x, double y) -{ - return ::pow(x, y); -} - -unsigned long long Port::strtoull(const char *p, char **pend, int base) -{ - return ::strtoull(p, pend, base); -} - -char *Port::ull_to_string(char *buffer, ulonglong ull) -{ - sprintf(buffer, "%llu", ull); - return buffer; -} - -wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull) -{ - swprintf(buffer, L"%llu", ull); - return buffer; -} - -double Port::ull_to_double(ulonglong ull) -{ - return (double) ull; -} - -const char *Port::list_separator() -{ - return ","; -} - -const wchar_t *Port::wlist_separator() -{ - return L","; -} - -char *Port::strupr(char *s) -{ - char *t = s; - - while (*s) - { - *s = toupper(*s); - s++; - } - - return t; -} - -#endif - diff --git a/root/port.h b/root/port.h index 40c07bb9..790a941b 100644 --- a/root/port.h +++ b/root/port.h @@ -10,6 +10,8 @@ // Portable wrapper around compiler/system specific things. // The idea is to minimize #ifdef's in the app code. +#include "longdouble.h" + #ifndef TYPEDEFS #define TYPEDEFS @@ -20,7 +22,7 @@ typedef __int64 longlong; typedef unsigned __int64 ulonglong; // According to VC 8.0 docs, long double is the same as double -#define strtold strtod +longdouble strtold(const char *p,char **endp); #define strtof strtod #else @@ -38,7 +40,7 @@ struct Port static double infinity; static double dbl_max; static double dbl_min; - static long double ldbl_max; + static longdouble ldbl_max; #if __OpenBSD__ #elif __GNUC__ @@ -49,10 +51,10 @@ struct Port #undef signbit #endif static int isNan(double); - static int isNan(long double); + static int isNan(longdouble); static int isSignallingNan(double); - static int isSignallingNan(long double); + static int isSignallingNan(longdouble); static int isFinite(double); static int isInfinity(double); @@ -61,7 +63,7 @@ struct Port static double floor(double); static double pow(double x, double y); - static long double fmodl(long double x, long double y); + static longdouble fmodl(longdouble x, longdouble y); static ulonglong strtoull(const char *p, char **pend, int base); diff --git a/root/response.c b/root/response.c index 2096f11b..31e35686 100644 --- a/root/response.c +++ b/root/response.c @@ -29,6 +29,13 @@ #include #endif +#if _MSC_VER +#include +#include +#include +#include +#endif + /********************************* * #include * int response_expand(int *pargc,char ***pargv); diff --git a/root/root.c b/root/root.c index f0d02426..ee3a8b6a 100644 --- a/root/root.c +++ b/root/root.c @@ -1527,7 +1527,7 @@ void File::stat() void File::checkoffset(size_t offset, size_t nbytes) { if (offset > len || offset + nbytes > len) - error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset); + error("Corrupt file '%s': offset x%llx off end of file",toChars(),(ulonglong)offset); } char *File::toChars() @@ -1796,7 +1796,7 @@ void OutBuffer::align(unsigned size) // The compiler shipped with Visual Studio 2005 (and possible // other versions) does not support C99 printf format specfiers // such as %z and %j -#if _MSC_VER +#if 0 && _MSC_VER using std::string; using std::wstring; @@ -1815,7 +1815,7 @@ search_and_replace(S& str, const S& what, const S& replacement) #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ S tmp = f; \ search_and_replace(fmt, S("%z"), S("%l")); \ - search_and_replace(fmt, S("%j"), S("%i")); \ + search_and_replace(fmt, S("%j"), S("%l")); \ f = tmp.c_str(); #else #define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) diff --git a/root/root.h b/root/root.h index bac6036e..830ea43b 100644 --- a/root/root.h +++ b/root/root.h @@ -23,6 +23,7 @@ typedef size_t hash_t; +#include "longdouble.h" #include "dchar.h" char *wchar2ascii(wchar_t *); @@ -32,9 +33,6 @@ int wcharIsAscii(wchar_t *, unsigned len); int bstrcmp(unsigned char *s1, unsigned char *s2); char *bstr2str(unsigned char *b); -void error(const char *format, ...); -void error(const wchar_t *format, ...); -void warning(const char *format, ...); #ifndef TYPEDEFS #define TYPEDEFS @@ -43,7 +41,7 @@ void warning(const char *format, ...); #include // for _isnan #include // for alloca // According to VC 8.0 docs, long double is the same as double -#define strtold strtod +longdouble strtold(const char *p,char **endp); #define strtof strtod #define isnan _isnan diff --git a/root/speller.c b/root/speller.c index d6437379..373baf6d 100644 --- a/root/speller.c +++ b/root/speller.c @@ -4,7 +4,7 @@ #include #include -#if __sun&&__SVR4 +#if __sun&&__SVR4 || _MSC_VER #include #endif diff --git a/scope.c b/scope.c index 44215108..70480eb8 100644 --- a/scope.c +++ b/scope.c @@ -74,10 +74,10 @@ Scope::Scope() this->noaccesscheck = 0; this->mustsemantic = 0; this->intypeof = 0; + this->speculative = 0; this->parameterSpecialization = 0; this->callSuper = 0; this->flags = 0; - this->anonAgg = NULL; this->lastdc = NULL; this->lastoffset = 0; this->docbuf = NULL; @@ -122,10 +122,10 @@ Scope::Scope(Scope *enclosing) this->noaccesscheck = enclosing->noaccesscheck; this->mustsemantic = enclosing->mustsemantic; this->intypeof = enclosing->intypeof; + this->speculative = enclosing->speculative; this->parameterSpecialization = enclosing->parameterSpecialization; this->callSuper = enclosing->callSuper; this->flags = 0; - this->anonAgg = NULL; this->lastdc = NULL; this->lastoffset = 0; this->docbuf = enclosing->docbuf; diff --git a/scope.h b/scope.h index d8c371f2..96c92e06 100644 --- a/scope.h +++ b/scope.h @@ -1,5 +1,5 @@ -// Copyright (c) 1999-2009 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -57,11 +57,16 @@ struct Scope Statement *scontinue; // enclosing statement that supports "continue" ForeachStatement *fes; // if nested function for ForeachStatement, this is it unsigned offset; // next offset to use in aggregate + // This really shouldn't be a part of Scope, because it requires + // semantic() to be done in the lexical field order. It should be + // set in a pass after semantic() on all fields so they can be + // semantic'd in any order. int inunion; // we're processing members of a union int incontract; // we're inside contract code int nofree; // set if shouldn't free it int noctor; // set if constructor calls aren't allowed int intypeof; // in typeof(exp) + bool speculative; // in __traits(compiles) or typeof(exp) int parameterSpecialization; // if in template parameter specialization int noaccesscheck; // don't do access checks int mustsemantic; // cannot defer semantic() @@ -90,7 +95,9 @@ struct Scope #define SCOPEstaticassert 8 // inside static assert #define SCOPEdebug 0x10 // inside debug conditional - AnonymousAggregateDeclaration *anonAgg; // for temporary analysis +#if IN_GCC + Expressions *attributes; // GCC decl/type attributes +#endif DocComment *lastdc; // documentation comment for last symbol at this scope unsigned lastoffset; // offset in docbuf of where to insert next dec diff --git a/statement.c b/statement.c index bc8a55c4..4cd42d5b 100644 --- a/statement.c +++ b/statement.c @@ -1217,6 +1217,7 @@ ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expr this->condition = condition; this->increment = increment; this->body = body; + this->nest = 0; } Statement *ForStatement::syntaxCopy() @@ -1234,17 +1235,145 @@ Statement *ForStatement::syntaxCopy() return s; } +/* + * Run semantic on init recursively. + * Rewrite: + * for (auto x=X(), y = Y(); ...; ...) {} + * as: + * try { + * try { + * for (auto x=X(), auto y=Y(); ...; ...) {} + * } + * finally { y.~this(); } + * } + * finally { x.~this(); } + */ +Statement *ForStatement::semanticInit(Scope *sc) +{ + assert(init); + ++nest; + + Loc locinit = init->loc; + Statements *ainit = init->flatten(sc); + if (!ainit) + (ainit = new Statements())->push(init); + init = NULL; + + Statement *statement = this; + + for (size_t i = 0; i < ainit->dim; i++) + { Statement *s = (*ainit)[i]; + s = s->semantic(sc); + (*ainit)[i] = s; + if (s) + { + Statement *sentry; + Statement *sexception; + Statement *sfinally; + + (*ainit)[i] = s->scopeCode(sc, &sentry, &sexception, &sfinally); + + if (sentry) + { sentry = sentry->semantic(sc); + if (sentry) + ainit->insert(i++, sentry); + } + if (sexception) + sexception = sexception->semantic(sc); + if (sexception) + { // Re-initialize this->init + if (i + 1 < ainit->dim) + { + Statements *a = new Statements(); + for (size_t j = i + 1; j < ainit->dim; j++) + a->push((*ainit)[j]); + init = new CompoundStatement(0, a); + } + + Identifier *id = Lexer::uniqueId("__o"); + Statement *handler = sexception; + if (sexception->blockExit(FALSE) & BEfallthru) + { handler = new ThrowStatement(0, new IdentifierExp(0, id)); + handler = new CompoundStatement(0, sexception, handler); + } + Catches *catches = new Catches(); + Catch *ctch = new Catch(0, NULL, id, handler); + catches->push(ctch); + s = new TryCatchStatement(0, this, catches); + + if (sfinally) + s = new TryFinallyStatement(0, s, sfinally); + //printf("ex {{{\n"); + s = s->semantic(sc); + //printf("}}}\n"); + statement = s; + + if (init) + { Statements *a = init->flatten(sc); + if (!a) + (a = new Statements())->push(init); + for (size_t j = 0; j < i + 1; j++) + a->insert(j, (*ainit)[j]); + init = new CompoundStatement(locinit, a); + } + break; + } + else if (sfinally) + { // Re-initialize this->init + if (i + 1 < ainit->dim) + { + Statements *a = new Statements(); + for (size_t j = i + 1; j < ainit->dim; j++) + a->push((*ainit)[j]); + init = new CompoundStatement(0, a); + } + + s = new TryFinallyStatement(0, this, sfinally); + //printf("fi {{{\n"); + s = s->semantic(sc); + //printf("}}} fi\n"); + statement = s; + + if (init) + { Statements *a = init->flatten(sc); + if (!a) + (a = new Statements())->push(init); + for (size_t j = 0; j < i + 1; j++) + a->insert(j, (*ainit)[j]); + init = new CompoundStatement(locinit, a); + } + break; + } + } + } + if (!init) + { // whole init semantic is completely done. + init = new CompoundStatement(locinit, ainit); + } + + --nest; + return statement; +} + Statement *ForStatement::semantic(Scope *sc) { - ScopeDsymbol *sym = new ScopeDsymbol(); - sym->parent = sc->scopesym; - sc = sc->push(sym); + if (!nest) + { ScopeDsymbol *sym = new ScopeDsymbol(); + sym->parent = sc->scopesym; + sc = sc->push(sym); + } + else if (init) + { // Process this->init recursively + return semanticInit(sc); + } + + Statement *statement = this; if (init) - init = init->semantic(sc); + statement = semanticInit(sc); + sc->noctor++; if (condition) - { - condition = condition->semantic(sc); + { condition = condition->semantic(sc); condition = resolveProperties(sc, condition); condition = condition->optimize(WANTvalue); condition = condition->checkToBoolean(sc); @@ -1261,18 +1390,16 @@ Statement *ForStatement::semantic(Scope *sc) body = body->semanticNoScope(sc); sc->noctor--; - sc->pop(); - return this; + if (!nest) + sc->pop(); + //if (!nest) statement->print(); + return statement; } Statement *ForStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally) { //printf("ForStatement::scopeCode()\n"); - //print(); - if (init) - init = init->scopeCode(sc, sentry, sexception, sfinally); - else - Statement::scopeCode(sc, sentry, sexception, sfinally); + Statement::scopeCode(sc, sentry, sexception, sfinally); return this; } @@ -1512,6 +1639,10 @@ Statement *ForeachStatement::semantic(Scope *sc) if (arg->storageClass & STCref) error("symbol %s cannot be ref", s->toChars()); } + else if (e->op == TOKtype) + { + var = new AliasDeclaration(loc, arg->ident, e->type); + } else { arg->type = e->type; @@ -2044,7 +2175,7 @@ Lagain: default: assert(0); } const char *r = (op == TOKforeach_reverse) ? "R" : ""; - int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim); + int j = sprintf(fdname, "_aApply%s%.*s%llu", r, 2, fntab[flag], (ulonglong)dim); assert(j < sizeof(fdname)); FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); @@ -2750,7 +2881,12 @@ Statement *PragmaStatement::semantic(Scope *sc) Expression *e = (*args)[i]; e = e->semantic(sc); - e = e->optimize(WANTvalue | WANTinterpret); + if (e->op != TOKerror) + e = e->optimize(WANTvalue | WANTinterpret); + if (e->op == TOKerror) + { errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars()); + goto Lerror; + } StringExp *se = e->toString(); if (se) { @@ -2816,7 +2952,7 @@ Statement *PragmaStatement::semantic(Scope *sc) #endif else error("unrecognized pragma(%s)", ident->toChars()); - +Lerror: if (body) { body = body->semantic(sc); @@ -2919,6 +3055,7 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b, bool isFi Statement *SwitchStatement::syntaxCopy() { + //printf("SwitchStatement::syntaxCopy(%p)\n", this); SwitchStatement *s = new SwitchStatement(loc, condition->syntaxCopy(), body->syntaxCopy(), isFinal); return s; @@ -2928,7 +3065,8 @@ Statement *SwitchStatement::semantic(Scope *sc) { //printf("SwitchStatement::semantic(%p)\n", this); tf = sc->tf; - assert(!cases); // ensure semantic() is only run once + if (cases) + return this; // already run condition = condition->semantic(sc); condition = resolveProperties(sc, condition); if (condition->type->isString()) @@ -3323,7 +3461,7 @@ DefaultStatement::DefaultStatement(Loc loc, Statement *s) { this->statement = s; #if IN_GCC -+ cblock = NULL; + cblock = NULL; #endif } @@ -3550,9 +3688,8 @@ Statement *ReturnStatement::semantic(Scope *sc) { fd->hasReturnExp |= 1; - if (exp->op == TOKfunction && tbret) - ((FuncExp *)exp)->setType(tbret); - + if (tret) + exp = exp->inferType(tbret); exp = exp->semantic(sc); exp = resolveProperties(sc, exp); if (!((TypeFunction *)fd->type)->isref) @@ -4077,6 +4214,8 @@ Statement *SynchronizedStatement::semantic(Scope *sc) { exp = exp->semantic(sc); exp = resolveProperties(sc, exp); + if (exp->op == TOKerror) + goto Lbody; ClassDeclaration *cd = exp->type->isClassHandle(); if (!cd) error("can only synchronize on class objects, not '%s'", exp->type->toChars()); @@ -4155,6 +4294,7 @@ Statement *SynchronizedStatement::semantic(Scope *sc) return s->semantic(sc); } #endif +Lbody: if (body) body = body->semantic(sc); return this; @@ -4254,6 +4394,13 @@ Statement *WithStatement::semantic(Scope *sc) } else if (t->ty == Tstruct) { + if (!exp->isLvalue()) + { + init = new ExpInitializer(loc, exp); + wthis = new VarDeclaration(loc, exp->type, Lexer::uniqueId("__withtmp"), init); + exp = new CommaExp(loc, new DeclarationExp(loc, wthis), new VarExp(loc, wthis)); + exp = exp->semantic(sc); + } Expression *e = exp->addressOf(sc); init = new ExpInitializer(loc, e); wthis = new VarDeclaration(loc, e->type, Id::withSym, init); diff --git a/statement.h b/statement.h index 6ce93d1d..ff2198b6 100644 --- a/statement.h +++ b/statement.h @@ -318,9 +318,11 @@ struct ForStatement : Statement Expression *condition; Expression *increment; Statement *body; + int nest; ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body); Statement *syntaxCopy(); + Statement *semanticInit(Scope *sc); Statement *semantic(Scope *sc); Statement *scopeCode(Scope *sc, Statement **sentry, Statement **sexit, Statement **sfinally); int hasBreak(); diff --git a/struct.c b/struct.c index 3a5bb4ea..6c71f583 100644 --- a/struct.c +++ b/struct.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -38,7 +38,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id) alignsize = 0; // size of struct for alignment purposes structalign = 0; // struct member alignment in effect hasUnions = 0; - sizeok = 0; // size not determined yet + sizeok = SIZEOKnone; // size not determined yet deferred = NULL; isdeprecated = false; inv = NULL; @@ -117,9 +117,46 @@ unsigned AggregateDeclaration::size(Loc loc) //printf("AggregateDeclaration::size() %s, scope = %p\n", toChars(), scope); if (!members) error(loc, "unknown size"); - if (sizeok != 1 && scope) + if (sizeok != SIZEOKdone && scope) semantic(NULL); - if (sizeok != 1) + + StructDeclaration *sd = isStructDeclaration(); + if (sizeok != SIZEOKdone && sd && sd->members) + { + /* See if enough is done to determine the size, + * meaning all the fields are done. + */ + struct SV + { + static int func(Dsymbol *s, void *param) + { SV *psv = (SV *)param; + VarDeclaration *v = s->isVarDeclaration(); + if (v) + { + if (v->scope) + v->semantic(NULL); + if (v->storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCconst | STCimmutable | STCmanifest | STCctfe | STCtemplateparameter)) + return 0; + if (v->storage_class & STCfield && v->sem >= SemanticDone) + return 0; + return 1; + } + return 0; + } + }; + SV sv; + + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + if (s->apply(&SV::func, &sv)) + goto L1; + } + sd->finalizeSize(NULL); + + L1: ; + } + + if (sizeok != SIZEOKdone) { error(loc, "no size yet for forward reference"); //*(char*)0=0; } @@ -163,76 +200,38 @@ void AggregateDeclaration::alignmember( //printf("result = %d\n",offset); } - -void AggregateDeclaration::addField(Scope *sc, VarDeclaration *v) +/**************************************** + * Place a member (mem) into an aggregate (agg), which can be a struct, union or class + * Returns: + * offset to place field at + */ +unsigned AggregateDeclaration::placeField( + unsigned *nextoffset, // next location in aggregate + unsigned memsize, // size of member + unsigned memalignsize, // size of member for alignment purposes + unsigned memalign, // alignment in effect for this member + unsigned *paggsize, // size of aggregate (updated) + unsigned *paggalignsize, // size of aggregate for alignment purposes (updated) + bool isunion // the aggregate is a union + ) { - unsigned memsize; // size of member - unsigned memalignsize; // size of member for alignment purposes - unsigned xalign; // alignment boundaries - - //printf("AggregateDeclaration::addField('%s') %s\n", v->toChars(), toChars()); - assert(!(v->storage_class & (STCstatic | STCextern | STCparameter | STCtls))); - - // Check for forward referenced types which will fail the size() call - Type *t = v->type->toBasetype(); - if (v->storage_class & STCref) - { // References are the size of a pointer - t = Type::tvoidptr; - } - if (t->ty == Tstruct /*&& isStructDeclaration()*/) - { TypeStruct *ts = (TypeStruct *)t; -#if DMDV2 - if (ts->sym == this) - { - error("cannot have field %s with same struct type", v->toChars()); - } -#endif - - if (ts->sym->sizeok != 1 && ts->sym->scope) - ts->sym->semantic(NULL); - if (ts->sym->sizeok != 1) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - } - if (t->ty == Tident) - { - sizeok = 2; // cannot finish; flag as forward referenced - return; - } - - memsize = t->size(loc); - memalignsize = t->alignsize(); - xalign = t->memalign(sc->structalign); -#if 0 - alignmember(xalign, memalignsize, &sc->offset); - v->offset = sc->offset; - sc->offset += memsize; - if (sc->offset > structsize) - structsize = sc->offset; -#else - unsigned ofs = sc->offset; - alignmember(xalign, memalignsize, &ofs); - v->offset = ofs; + unsigned ofs = *nextoffset; + alignmember(memalign, memalignsize, &ofs); + unsigned memoffset = ofs; ofs += memsize; - if (ofs > structsize) - structsize = ofs; - if (!isUnionDeclaration()) - sc->offset = ofs; -#endif - if (global.params.is64bit && sc->structalign == 8 && memalignsize == 16) + if (ofs > *paggsize) + *paggsize = ofs; + if (!isunion) + *nextoffset = ofs; + if (global.params.is64bit && memalign == 8 && memalignsize == 16) /* Not sure how to handle this */ ; - else if (sc->structalign < memalignsize) - memalignsize = sc->structalign; - if (alignsize < memalignsize) - alignsize = memalignsize; - //printf("\t%s: alignsize = %d\n", toChars(), alignsize); + else if (memalign < memalignsize) + memalignsize = memalign; + if (*paggalignsize < memalignsize) + *paggalignsize = memalignsize; - v->storage_class |= STCfield; - //printf(" addField '%s' to '%s' at offset %d, size = %d\n", v->toChars(), toChars(), v->offset, memsize); - fields.push(v); + return memoffset; } @@ -342,7 +341,7 @@ void StructDeclaration::semantic(Scope *sc) return; if (symtab) - { if (sizeok == 1 || !scope) + { if (sizeok == SIZEOKdone || !scope) { //printf("already completed\n"); scope = NULL; return; // semantic() already completed @@ -377,16 +376,8 @@ void StructDeclaration::semantic(Scope *sc) assert(!isAnonymous()); if (sc->stc & STCabstract) error("structs, unions cannot be abstract"); -#if DMDV2 - if (storage_class & STCimmutable) - type = type->addMod(MODimmutable); - if (storage_class & STCconst) - type = type->addMod(MODconst); - if (storage_class & STCshared) - type = type->addMod(MODshared); -#endif - if (sizeok == 0) // if not already done the addMember step + if (sizeok == SIZEOKnone) // if not already done the addMember step { int hasfunctions = 0; for (size_t i = 0; i < members->dim; i++) @@ -432,7 +423,7 @@ void StructDeclaration::semantic(Scope *sc) } } - sizeok = 0; + sizeok = SIZEOKnone; sc2 = sc->push(this); sc2->stc &= STCsafe | STCtrusted | STCsystem; sc2->parent = this; @@ -451,7 +442,7 @@ void StructDeclaration::semantic(Scope *sc) /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ - if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) + //if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) { //printf("setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc2); @@ -469,15 +460,27 @@ void StructDeclaration::semantic(Scope *sc) */ if (i + 1 == members_dim) { - if (sizeok == 0 && s->isAliasDeclaration()) - finalizeSize(); + if (sizeok == SIZEOKnone && s->isAliasDeclaration()) + finalizeSize(sc2); } + // Ungag errors when not speculative + unsigned oldgag = global.gag; + if (global.isSpeculativeGagging() && !isSpeculative()) + global.gag = 0; s->semantic(sc2); + global.gag = oldgag; } + finalizeSize(sc2); - if (sizeok == 2) + if (sizeok == SIZEOKfwd) { // semantic() failed because of forward references. // Unwind what we did, and defer it for later + for (size_t i = 0; i < fields.dim; i++) + { Dsymbol *s = fields[i]; + VarDeclaration *vd = s->isVarDeclaration(); + if (vd) + vd->offset = 0; + } fields.setDim(0); structsize = 0; alignsize = 0; @@ -492,7 +495,6 @@ void StructDeclaration::semantic(Scope *sc) return; } - finalizeSize(); Module::dprogress++; //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars()); @@ -501,7 +503,7 @@ void StructDeclaration::semantic(Scope *sc) zeroInit = 1; for (size_t i = 0; i < fields.dim; i++) { - Dsymbol *s = fields.tdata()[i]; + Dsymbol *s = fields[i]; VarDeclaration *vd = s->isVarDeclaration(); if (vd && !vd->isDataseg()) { @@ -640,8 +642,21 @@ Dsymbol *StructDeclaration::search(Loc loc, Identifier *ident, int flags) return ScopeDsymbol::search(loc, ident, flags); } -void StructDeclaration::finalizeSize() +void StructDeclaration::finalizeSize(Scope *sc) { + if (sizeok != SIZEOKnone) + return; + + // Set the offsets of the fields and determine the size of the struct + unsigned offset = 0; + bool isunion = isUnionDeclaration() != NULL; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(this, &offset, isunion); + } + if (sizeok == SIZEOKfwd) + return; + // 0 sized struct's are set to 1 byte if (structsize == 0) { @@ -654,7 +669,7 @@ void StructDeclaration::finalizeSize() // aligned properly. structsize = (structsize + alignsize - 1) & ~(alignsize - 1); - sizeok = 1; + sizeok = SIZEOKdone; } void StructDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) diff --git a/template.c b/template.c index 9b0d3115..d0563c0e 100644 --- a/template.c +++ b/template.c @@ -203,7 +203,7 @@ int match(Object *o1, Object *o2, TemplateDeclaration *tempdecl, Scope *sc) { if (sc1->scopesym == ti1) { - error("recursive template expansion for template argument %s", t1->toChars()); + tempdecl->error("recursive template expansion for template argument %s", t1->toChars()); return 1; // fake a match } } @@ -381,7 +381,7 @@ TemplateDeclaration::TemplateDeclaration(Loc loc, Identifier *id, this->members = decldefs; this->overnext = NULL; this->overroot = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->onemember = NULL; this->literal = 0; this->ismixin = ismixin; @@ -432,7 +432,7 @@ void TemplateDeclaration::semantic(Scope *sc) #endif if (semanticRun) return; // semantic() already run - semanticRun = 1; + semanticRun = PASSsemantic; if (sc->module && sc->module->ident == Id::object && ident == Id::AssociativeArray) { Type::associativearray = this; @@ -490,7 +490,7 @@ void TemplateDeclaration::semantic(Scope *sc) origParameters->setDim(parameters->dim); for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; origParameters->tdata()[i] = tp->syntaxCopy(); } } @@ -504,11 +504,13 @@ void TemplateDeclaration::semantic(Scope *sc) for (size_t i = 0; i < parameters->dim; i++) { - TemplateParameter *tp = parameters->tdata()[i]; + TemplateParameter *tp = (*parameters)[i]; tp->semantic(paramscope); if (i + 1 != parameters->dim && tp->isTemplateTupleParameter()) - error("template tuple parameter must be last one"); + { error("template tuple parameter must be last one"); + errors = true; + } } paramscope->pop(); @@ -682,6 +684,9 @@ MATCH TemplateDeclaration::matchWithInstance(TemplateInstance *ti, #endif dedtypes->zero(); + if (errors) + return MATCHnomatch; + size_t parameters_dim = parameters->dim; int variadic = isVariadic() != NULL; @@ -962,6 +967,9 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec dedtypes.setDim(parameters->dim); dedtypes.zero(); + if (errors) + return MATCHnomatch; + // Set up scope for parameters ScopeDsymbol *paramsym = new ScopeDsymbol(); paramsym->parent = scope->parent; @@ -1102,6 +1110,14 @@ MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Scope *sc, Loc loc, Objec t->objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { Expression *farg = fargs->tdata()[fptupindex + i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + + if (!(fparam->storageClass & STClazy) && farg->type->ty == Tvoid) + goto Lnomatch; + unsigned mod = farg->type->mod; Type *tt; MATCH m; @@ -1378,6 +1394,11 @@ L2: else { Expression *farg = fargs->tdata()[i]; + + // Check invalid arguments to detect errors early. + if (farg->op == TOKerror || farg->type->ty == Terror) + goto Lnomatch; + Lretry: #if 0 printf("\tfarg->type = %s\n", farg->type->toChars()); @@ -1407,22 +1428,16 @@ Lretry: if (farg->op == TOKfunction) { FuncExp *fe = (FuncExp *)farg; Type *tp = fparam->type; - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { Type *tdg = new TypeDelegate(fe->type->nextOf()); - tdg = tdg->semantic(loc, sc); - farg = fe->inferType(sc, tdg); - } - else if (fe->type == Type::tvoid) - { - farg = fe->inferType(sc, tp); - if (!farg) - goto Lvarargs; - } + Expression *e = fe->inferType(tp, 1, parameters); + if (!e) + goto Lvarargs; + farg = e; argtype = farg->type; } + if (!(fparam->storageClass & STClazy) && argtype->ty == Tvoid) + goto Lnomatch; + /* Remove top const for dynamic array types and pointer types */ if ((argtype->ty == Tarray || argtype->ty == Tpointer) && @@ -1437,12 +1452,11 @@ Lretry: if (fvarargs == 2 && i + 1 == nfparams && i + 1 < nfargs) goto Lvarargs; - MATCH m; - m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, - tf->hasWild() ? &wildmatch : NULL); + unsigned wm = 0; + MATCH m = argtype->deduceType(paramscope, fparam->type, parameters, &dedtypes, &wm); //printf("\tdeduceType m = %d\n", m); - //if (tf->hasWild()) - // printf("\twildmatch = x%x m = %d\n", wildmatch, m); + //printf("\twildmatch = x%x m = %d\n", wildmatch, m); + wildmatch |= wm; /* If no match, see if there's a conversion to a delegate */ @@ -1477,9 +1491,7 @@ Lretry: * eg purity(bug 7295), just regard it as not a match. */ unsigned olderrors = global.startGagging(); - Expression *e = new DotIdExp(farg->loc, farg, ad->aliasthis->ident); - e = e->semantic(sc); - e = resolveProperties(sc, e); + Expression *e = resolveAliasThis(sc, farg); if (!global.endGagging(olderrors)) { farg = e; goto Lretry; @@ -1536,19 +1548,11 @@ Lretry: if (arg->op == TOKfunction) { FuncExp *fe = (FuncExp *)arg; Type *tp = tb->nextOf(); - if (tp->ty == Tdelegate && - fe->type->ty == Tpointer && fe->type->nextOf()->ty == Tfunction && - fe->tok == TOKreserved) - { tp = new TypeDelegate(fe->type->nextOf()); - tp = tp->semantic(loc, sc); - arg = fe->inferType(sc, tp); - } - else if (arg->type == Type::tvoid) - { - arg = fe->inferType(sc, tp); - if (!arg) - goto Lnomatch; - } + + Expression *e = fe->inferType(tp, 1, parameters); + if (!e) + goto Lnomatch; + arg = e; } MATCH m; @@ -1890,11 +1894,10 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, goto Lerror; } - MATCH m; Objects dedargs; FuncDeclaration *fd = NULL; - m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); + MATCH m = td->deduceFunctionTemplateMatch(sc, loc, targsi, ethis, fargs, &dedargs); //printf("deduceFunctionTemplateMatch = %d\n", m); if (!m) // if no match continue; @@ -1923,9 +1926,7 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, goto Lerror; } { - tdargs->setDim(dedargs.dim); - memcpy(tdargs->data, dedargs.data, tdargs->dim * sizeof(void *)); - fd = td->doHeaderInstantiation(sc, tdargs, fargs); + fd = td->doHeaderInstantiation(sc, &dedargs, fargs); if (!fd) goto Lerror; } @@ -1978,13 +1979,14 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, if (!td_best) { if (!(flags & 1)) - error(loc, "does not match any function template declaration"); + ::error(loc, "%s %s.%s does not match any function template declaration", + kind(), parent->toPrettyChars(), ident->toChars()); goto Lerror; } if (td_ambig) { - error(loc, "%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", - toChars(), + ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + kind(), parent->toPrettyChars(), ident->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } @@ -1998,6 +2000,16 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, fd_best = ti->toAlias()->isFuncDeclaration(); if (!fd_best || !((TypeFunction*)fd_best->type)->callMatch(ethis, fargs, flags)) goto Lerror; + + /* As Bugzilla 3682 shows, a template instance can be matched while instantiating + * that same template. Thus, the function type can be incomplete. Complete it. + */ + { TypeFunction *tf = (TypeFunction *)fd_best->type; + assert(tf->ty == Tfunction); + if (tf->next) + fd_best->type = tf->semantic(loc, sc); + } + return fd_best; Lerror: @@ -2021,8 +2033,13 @@ FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc, OutBuffer buf; argExpTypesToCBuffer(&buf, fargs, &hgs); - error(loc, "cannot deduce template function from argument types !(%s)(%s)", - bufa.toChars(), buf.toChars()); + if (this->overnext) + ::error(loc, "%s %s.%s cannot deduce template function from argument types !(%s)(%s)", + kind(), parent->toPrettyChars(), ident->toChars(), + bufa.toChars(), buf.toChars()); + else + error("cannot deduce template function from argument types !(%s)(%s)", + bufa.toChars(), buf.toChars()); } return NULL; } @@ -2218,7 +2235,7 @@ int templateParameterLookup(Type *tparam, TemplateParameters *parameters) * Foo!(int*) // template instantiation * Input: * this = int* - * tparam = T + * tparam = T* * parameters = [ T:T* ] // Array of TemplateParameter's * Output: * dedtypes = [ int ] // Array of Expression/Type's @@ -2280,13 +2297,17 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, { switch (X(tparam->mod, mod)) { - case X(MODwild, MODwild): - case X(MODwild | MODshared, MODwild | MODshared): case X(MODwild, 0): + case X(MODwild, MODshared): case X(MODwild, MODconst): + case X(MODwild, MODconst | MODshared): case X(MODwild, MODimmutable): + case X(MODwild, MODwild): + case X(MODwild, MODwild | MODshared): case X(MODwild | MODshared, MODshared): case X(MODwild | MODshared, MODconst | MODshared): + case X(MODwild | MODshared, MODimmutable): + case X(MODwild | MODshared, MODwild | MODshared): if (!at) { @@ -2400,11 +2421,18 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, } break; + case X(MODconst, MODshared): + // foo(U:const(U)) shared(T) => shared(T) + if (!at) + { (*dedtypes)[i] = tt; + goto Lconst; + } + break; + case X(MODimmutable, 0): case X(MODimmutable, MODconst): case X(MODimmutable, MODshared): case X(MODimmutable, MODconst | MODshared): - case X(MODconst, MODshared): case X(MODshared, 0): case X(MODshared, MODconst): case X(MODshared, MODimmutable): @@ -2527,6 +2555,23 @@ Lconst: #endif } +#if DMDV2 +MATCH TypeVector::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, + Objects *dedtypes, unsigned *wildmatch) +{ +#if 0 + printf("TypeVector::deduceType()\n"); + printf("\tthis = %d, ", ty); print(); + printf("\ttparam = %d, ", tparam->ty); tparam->print(); +#endif + if (tparam->ty == Tvector) + { TypeVector *tp = (TypeVector *)tparam; + return basetype->deduceType(sc, tp->basetype, parameters, dedtypes, wildmatch); + } + return Type::deduceType(sc, tparam, parameters, dedtypes, wildmatch); +} +#endif + #if DMDV2 MATCH TypeDArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes, unsigned *wildmatch) @@ -3818,7 +3863,16 @@ void TemplateValueParameter::declareParameter(Scope *sc) void TemplateValueParameter::semantic(Scope *sc) { + bool wasSame = (sparam->type == valType); sparam->semantic(sc); + if (sparam->type == Type::terror && wasSame) + { /* If sparam has a type error, avoid duplicate errors + * The simple solution of leaving that function if sparam->type == Type::terror + * doesn't quite work because it causes failures in xtest46 for bug 6295 + */ + valType = Type::terror; + return; + } valType = valType->semantic(loc, sc); if (!(valType->isintegral() || valType->isfloating() || valType->isString()) && valType->ty != Tident) @@ -3827,6 +3881,7 @@ void TemplateValueParameter::semantic(Scope *sc) error(loc, "arithmetic/string type expected for value-parameter, not %s", valType->toChars()); } +#if 0 // defer semantic analysis to arg match if (specValue) { Expression *e = specValue; @@ -3839,7 +3894,6 @@ void TemplateValueParameter::semantic(Scope *sc) //e->toInteger(); } -#if 0 // defer semantic analysis to arg match if (defaultValue) { Expression *e = defaultValue; @@ -3876,8 +3930,8 @@ Lnomatch: } -MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs, - size_t i, TemplateParameters *parameters, Objects *dedtypes, +MATCH TemplateValueParameter::matchArg(Scope *sc, + Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) { //printf("TemplateValueParameter::matchArg()\n"); @@ -3934,7 +3988,7 @@ MATCH TemplateValueParameter::matchArg(Scope *sc, Objects *tiargs, Expression *e = specValue; e = e->semantic(sc); - e = e->implicitCastTo(sc, valType); + e = e->implicitCastTo(sc, vt); e = e->optimize(WANTvalue | WANTinterpret); ei = ei->syntaxCopy(); @@ -4192,13 +4246,12 @@ TemplateInstance::TemplateInstance(Loc loc, Identifier *ident) this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->semantictiargsdone = 0; this->withsym = NULL; this->nest = 0; this->havetempdecl = 0; this->isnested = NULL; - this->errors = 0; this->speculative = 0; } @@ -4221,13 +4274,12 @@ TemplateInstance::TemplateInstance(Loc loc, TemplateDeclaration *td, Objects *ti this->tinst = NULL; this->argsym = NULL; this->aliasdecl = NULL; - this->semanticRun = 0; + this->semanticRun = PASSinit; this->semantictiargsdone = 1; this->withsym = NULL; this->nest = 0; this->havetempdecl = 1; this->isnested = NULL; - this->errors = 0; this->speculative = 0; assert((size_t)tempdecl->scope > 0x10000); @@ -4269,21 +4321,96 @@ void TemplateInstance::semantic(Scope *sc) semantic(sc, NULL); } +void TemplateInstance::expandMembers(Scope *sc2) +{ + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setScope(sc2); + } + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *s = members->tdata()[i]; + //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->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()); + s->semantic(sc2); + //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); + sc2->module->runDeferredSemantic(); + } +} + +void TemplateInstance::tryExpandMembers(Scope *sc2) +{ + static int nest; + // extracted to a function to allow windows SEH to work without destructors in the same function + //printf("%d\n", nest); + if (++nest > 500) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + +#if WINDOWS_SEH + if(nest == 1) + { + // do not catch at every nesting level, because generating the output error might cause more stack + // errors in the __except block otherwise + __try + { + expandMembers(sc2); + } + __except (__ehfilter(GetExceptionInformation())) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + else +#endif + expandMembers(sc2); + nest--; +} + +void TemplateInstance::trySemantic3(Scope *sc2) +{ + // extracted to a function to allow windows SEH to work without destructors in the same function + static int nest; + if (++nest > 300) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } +#if WINDOWS_SEH + if(nest == 1) + { + // do not catch at every nesting level, because generating the output error might cause more stack + // errors in the __except block otherwise + __try + { + semantic3(sc2); + } + __except (__ehfilter(GetExceptionInformation())) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + } + else +#endif + semantic3(sc2); + + --nest; +} + void TemplateInstance::semantic(Scope *sc, Expressions *fargs) { //printf("TemplateInstance::semantic('%s', this=%p, gag = %d, sc = %p)\n", toChars(), this, global.gag, sc); - if (global.errors && name != Id::AssociativeArray) - { - //printf("not instantiating %s due to %d errors\n", toChars(), global.errors); - if (!global.gag) - { - /* Trying to soldier on rarely generates useful messages - * at this point. - */ - fatal(); - } -// return; - } #if LOG printf("\n+TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); #endif @@ -4298,7 +4425,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // get the enclosing template instance from the scope tinst tinst = sc->tinst; - if (semanticRun != 0) + if (semanticRun != PASSinit) { #if LOG printf("Recursive template expansion\n"); @@ -4307,7 +4434,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) // inst = this; return; } - semanticRun = 1; + semanticRun = PASSsemantic; #if LOG printf("\tdo semantic\n"); @@ -4335,11 +4462,11 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) //printf("error return %p, %d\n", tempdecl, global.errors); return; // error recovery } - + unsigned errs = global.errors; tempdecl = findTemplateDeclaration(sc); if (tempdecl) tempdecl = findBestMatch(sc, fargs); - if (!tempdecl || global.errors) + if (!tempdecl || (errs != global.errors)) { inst = this; //printf("error return %p, %d\n", tempdecl, global.errors); return; // error recovery @@ -4370,10 +4497,8 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) //printf("test2 isnested %s ti->isnested %s\n", isnested ? isnested->toChars() : "", ti->isnested ? ti->isnested->toChars() : ""); continue; } -#if 0 - if (isnested && sc->parent != ti->parent) - continue; -#endif + //printf("parent = %s, ti->parent = %s\n", tempdecl->parent->toPrettyChars(), ti->parent->toPrettyChars()); + if (!arrayObjectMatch(&tdtypes, &ti->tdtypes, tempdecl, sc)) goto L1; @@ -4430,7 +4555,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) } #if LOG - printf("\tit's a match with instance %p\n", inst); + printf("\tit's a match with instance %p, %d\n", inst, inst->semanticRun); #endif return; @@ -4447,7 +4572,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) unsigned errorsave = global.errors; inst = this; // Mark as speculative if we are instantiated from inside is(typeof()) - if (global.gag && sc->intypeof) + if (global.gag && sc->speculative) speculative = 1; int tempdecl_instance_idx = tempdecl->instances.dim; @@ -4608,46 +4733,9 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) sc2->parent = /*isnested ? sc->parent :*/ this; sc2->tinst = this; -#if WINDOWS_SEH - __try - { -#endif - static int nest; - //printf("%d\n", nest); - if (++nest > 500) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } + tryExpandMembers(sc2); - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = (*members)[i]; - s->setScope(sc2); - } - - for (size_t i = 0; i < members->dim; i++) - { - Dsymbol *s = members->tdata()[i]; - //printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s->toChars(), s, s->kind(), this->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()); - s->semantic(sc2); - //printf("test4: isnested = %d, s->parent = %s\n", isnested, s->parent->toChars()); - sc2->module->runDeferredSemantic(); - } - --nest; -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } -#endif + semanticRun = PASSsemanticdone; /* If any of the instantiation members didn't get semantic() run * on them due to forward references, we cannot run semantic2() @@ -4701,28 +4789,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) if (sc->func || dosemantic3) { -#if WINDOWS_SEH - __try - { -#endif - static int nest; - if (++nest > 300) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } - semantic3(sc2); - --nest; -#if WINDOWS_SEH - } - __except (__ehfilter(GetExceptionInformation())) - { - global.gag = 0; // ensure error message gets printed - error("recursive expansion"); - fatal(); - } -#endif + trySemantic3(sc2); } Laftersemantic: @@ -4752,7 +4819,7 @@ void TemplateInstance::semantic(Scope *sc, Expressions *fargs) assert(target_symbol_list->tdata()[target_symbol_list_idx] == this); target_symbol_list->remove(target_symbol_list_idx); } - semanticRun = 0; + semanticRun = PASSinit; inst = NULL; } } @@ -5129,13 +5196,14 @@ TemplateDeclaration *TemplateInstance::findBestMatch(Scope *sc, Expressions *far // Only one template, so we can give better error message error("%s does not match template declaration %s", toChars(), tempdecl->toChars()); else - error("%s does not match any template declaration", toChars()); + ::error(loc, "%s %s.%s does not match any template declaration", + tempdecl->kind(), tempdecl->parent->toPrettyChars(), tempdecl->ident->toChars()); return NULL; } if (td_ambig) { - error("%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", - toChars(), + ::error(loc, "%s %s.%s matches more than one template declaration, %s(%d):%s and %s(%d):%s", + td_best->kind(), td_best->parent->toPrettyChars(), td_best->ident->toChars(), td_best->loc.filename, td_best->loc.linnum, td_best->toChars(), td_ambig->loc.filename, td_ambig->loc.linnum, td_ambig->toChars()); } @@ -5194,6 +5262,11 @@ int TemplateInstance::hasNestedArgs(Objects *args) sa = ((VarExp *)ea)->var; goto Lsa; } + if (ea->op == TOKthis) + { + sa = ((ThisExp *)ea)->var; + goto Lsa; + } if (ea->op == TOKfunction) { sa = ((FuncExp *)ea)->fd; @@ -5266,7 +5339,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) //printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars()); char *id = tempdecl->ident->toChars(); - buf.printf("__T%zu%s", strlen(id), id); + buf.printf("__T%llu%s", (ulonglong)strlen(id), id); for (size_t i = 0; i < args->dim; i++) { Object *o = args->tdata()[i]; Type *ta = isType(o); @@ -5282,7 +5355,8 @@ Identifier *TemplateInstance::genIdent(Objects *args) else { #ifdef DEBUG - printf("ta = %d, %s\n", ta->ty, ta->toChars()); + if (!global.errors) + printf("ta = %d, %s\n", ta->ty, ta->toChars()); #endif assert(global.errors); } @@ -5315,8 +5389,9 @@ Identifier *TemplateInstance::genIdent(Objects *args) continue; } // Now that we know it is not an alias, we MUST obtain a value + unsigned olderr = global.errors; ea = ea->optimize(WANTvalue | WANTinterpret); - if (ea->op == TOKerror) + if (ea->op == TOKerror || olderr != global.errors) continue; #if 1 /* Use deco that matches what it would be for a function parameter @@ -5361,7 +5436,7 @@ Identifier *TemplateInstance::genIdent(Objects *args) * Unfortunately, fixing this ambiguity will break existing binary * compatibility and the demanglers, so we'll leave it as is. */ - buf.printf("%zu%s", strlen(p), p); + buf.printf("%llu%s", (ulonglong)strlen(p), p); } else if (va) { @@ -5434,12 +5509,33 @@ int TemplateInstance::needsTypeInference(Scope *sc) /* Determine if the instance arguments, tiargs, are all that is necessary * to instantiate the template. */ - TemplateTupleParameter *tp = td->isVariadic(); //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); TypeFunction *fdtype = (TypeFunction *)fd->type; - if (Parameter::dim(fdtype->parameters) && - ((tp && td->parameters->dim > 1) || tiargs->dim < td->parameters->dim)) - return TRUE; + if (Parameter::dim(fdtype->parameters)) + { + TemplateParameter *tp = td->isVariadic(); + if (tp && td->parameters->dim > 1) + return TRUE; + + if (tiargs->dim < td->parameters->dim) + { // Can remain tiargs be filled by default arguments? + for (size_t i = tiargs->dim; i < td->parameters->dim; i++) + { tp = (*td->parameters)[i]; + if (TemplateTypeParameter *ttp = tp->isTemplateTypeParameter()) + { if (!ttp->defaultType) + return TRUE; + } + else if (TemplateAliasParameter *tap = tp->isTemplateAliasParameter()) + { if (!tap->defaultAlias) + return TRUE; + } + else if (TemplateValueParameter *tvp = tp->isTemplateValueParameter()) + { if (!tvp->defaultValue) + return TRUE; + } + } + } + } /* If there is more than one function template which matches, we may * need type inference (see Bugzilla 4430) */ @@ -5453,9 +5549,9 @@ int TemplateInstance::needsTypeInference(Scope *sc) void TemplateInstance::semantic2(Scope *sc) { int i; - if (semanticRun >= 2) + if (semanticRun >= PASSsemantic2) return; - semanticRun = 2; + semanticRun = PASSsemantic2; #if LOG printf("+TemplateInstance::semantic2('%s')\n", toChars()); #endif @@ -5488,9 +5584,9 @@ void TemplateInstance::semantic3(Scope *sc) printf("TemplateInstance::semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun); #endif //if (toChars()[0] == 'D') *(char*)0=0; - if (semanticRun >= 3) + if (semanticRun >= PASSsemantic3) return; - semanticRun = 3; + semanticRun = PASSsemantic3; if (!errors && members) { sc = tempdecl->scope; @@ -5653,7 +5749,7 @@ void TemplateInstance::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { if (i) buf->writeByte(','); - Object *oarg = args->tdata()[i]; + Object *oarg = (*args)[i]; ObjectToCBuffer(buf, hgs, oarg); } nest--; @@ -5668,9 +5764,24 @@ Dsymbol *TemplateInstance::toAlias() printf("TemplateInstance::toAlias()\n"); #endif if (!inst) - { error("cannot resolve forward reference"); - errors = 1; - return this; + { + // Maybe we can resolve it + if (scope) + { + /* Anything that affects scope->offset must be + * done in lexical order. Fwd ref error if it is affected, otherwise allow. + */ + unsigned offset = scope->offset; + Scope *sc = scope; + semantic(scope); +// if (offset != sc->offset) +// inst = NULL; // trigger fwd ref error + } + if (!inst) + { error("cannot resolve forward reference"); + errors = 1; + return this; + } } if (inst != this) @@ -5761,7 +5872,7 @@ void TemplateMixin::semantic(Scope *sc) // This for when a class/struct contains mixin members, and // is done over because of forward references if (parent && toParent()->isAggregateDeclaration()) - semanticRun = 1; // do over + semanticRun = PASSsemantic; // do over else { #if LOG @@ -5771,11 +5882,13 @@ void TemplateMixin::semantic(Scope *sc) } } if (!semanticRun) - semanticRun = 1; + semanticRun = PASSsemantic; #if LOG printf("\tdo semantic\n"); #endif +#ifndef IN_GCC util_progress(); +#endif Scope *scx = NULL; if (scope) @@ -5850,10 +5963,10 @@ void TemplateMixin::semantic(Scope *sc) * runDeferred will re-run mixin's semantic outside of the struct's * semantic. */ - semanticRun = 0; + semanticRun = PASSinit; AggregateDeclaration *ad = toParent()->isAggregateDeclaration(); if (ad) - ad->sizeok = 2; + ad->sizeok = SIZEOKfwd; else { // Forward reference @@ -5898,11 +6011,11 @@ void TemplateMixin::semantic(Scope *sc) continue; for (size_t i = 0; i < tiargs->dim; i++) - { Object *o = tiargs->tdata()[i]; + { Object *o = (*tiargs)[i]; Type *ta = isType(o); Expression *ea = isExpression(o); Dsymbol *sa = isDsymbol(o); - Object *tmo = tm->tiargs->tdata()[i]; + Object *tmo = (*tm->tiargs)[i]; if (ta) { Type *tmta = isType(tmo); @@ -5966,10 +6079,8 @@ void TemplateMixin::semantic(Scope *sc) declareParameters(argscope); // Add members to enclosing scope, as well as this scope - for (unsigned i = 0; i < members->dim; i++) - { Dsymbol *s; - - s = members->tdata()[i]; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; s->addMember(argscope, this, i); //sc->insert(s); //printf("sc->parent = %p, sc->scopesym = %p\n", sc->parent, sc->scopesym); @@ -5995,7 +6106,7 @@ void TemplateMixin::semantic(Scope *sc) for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; s->semantic(sc2); } @@ -6037,9 +6148,9 @@ void TemplateMixin::semantic(Scope *sc) void TemplateMixin::semantic2(Scope *sc) { - if (semanticRun >= 2) + if (semanticRun >= PASSsemantic2) return; - semanticRun = 2; + semanticRun = PASSsemantic2; #if LOG printf("+TemplateMixin::semantic2('%s')\n", toChars()); #endif @@ -6050,7 +6161,7 @@ void TemplateMixin::semantic2(Scope *sc) sc = sc->push(this); for (size_t i = 0; i < members->dim; i++) { - Dsymbol *s = members->tdata()[i]; + Dsymbol *s = (*members)[i]; #if LOG printf("\tmember '%s', kind = '%s'\n", s->toChars(), s->kind()); #endif @@ -6066,9 +6177,9 @@ void TemplateMixin::semantic2(Scope *sc) void TemplateMixin::semantic3(Scope *sc) { - if (semanticRun >= 3) + if (semanticRun >= PASSsemantic3) return; - semanticRun = 3; + semanticRun = PASSsemantic3; #if LOG printf("TemplateMixin::semantic3('%s')\n", toChars()); #endif @@ -6101,6 +6212,22 @@ int TemplateMixin::oneMember(Dsymbol **ps, Identifier *ident) return Dsymbol::oneMember(ps, ident); } +int TemplateMixin::apply(Dsymbol_apply_ft_t fp, void *param) +{ + if (members) + { + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + if (s) + { + if (s->apply(fp, param)) + return 1; + } + } + } + return 0; +} + int TemplateMixin::hasPointers() { //printf("TemplateMixin::hasPointers() %s\n", toChars()); @@ -6118,6 +6245,17 @@ int TemplateMixin::hasPointers() return 0; } +void TemplateMixin::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion) +{ + if (members) + { + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->setFieldOffset(ad, poffset, isunion); + } + } +} + char *TemplateMixin::toChars() { OutBuffer buf; diff --git a/template.h b/template.h index 60bcd1b1..ad7b448d 100644 --- a/template.h +++ b/template.h @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -37,6 +37,7 @@ struct AliasDeclaration; struct FuncDeclaration; struct HdrGenState; enum MATCH; +enum PASS; struct Tuple : Object { @@ -57,7 +58,7 @@ struct TemplateDeclaration : ScopeDsymbol TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overroot; // first in overnext list - int semanticRun; // 1 semantic() run + enum PASS semanticRun; // 1 semantic() run Dsymbol *onemember; // if !=NULL then one member of this template @@ -182,8 +183,6 @@ struct TemplateThisParameter : TemplateTypeParameter /* Syntax: * this ident : specType = defaultType */ - Type *specType; // type parameter: if !=NULL, this is the type specialization - Type *defaultType; TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); @@ -291,12 +290,11 @@ struct TemplateInstance : ScopeDsymbol AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its // sole member WithScopeSymbol *withsym; // if a member of a with statement - int semanticRun; // has semantic() been done? + enum PASS semanticRun; // has semantic() been done? int semantictiargsdone; // has semanticTiargs() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor Dsymbol *isnested; // if referencing local symbols, this is the context - int errors; // 1 if compiled with errors int speculative; // 1 if only instantiated with errors gagged #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol @@ -333,6 +331,9 @@ struct TemplateInstance : ScopeDsymbol void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); Identifier *genIdent(Objects *args); + void expandMembers(Scope *sc); + void tryExpandMembers(Scope *sc); + void trySemantic3(Scope *sc2); TemplateInstance *isTemplateInstance() { return this; } AliasDeclaration *isAliasDeclaration(); @@ -351,7 +352,9 @@ struct TemplateMixin : TemplateInstance void inlineScan(); const char *kind(); int oneMember(Dsymbol **ps, Identifier *ident); + int apply(Dsymbol_apply_ft_t fp, void *param); int hasPointers(); + void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff --git a/tk/mem.c b/tk/mem.c index 5851e4f1..25f05c2e 100644 --- a/tk/mem.c +++ b/tk/mem.c @@ -6,7 +6,6 @@ #if MSDOS || __OS2__ || __NT__ || _WIN32 #include #else -#define _near #include #include #include @@ -361,7 +360,7 @@ void mem_setnewfileline( void *ptr, const char *fil, int lin) * Print out struct mem_debug. */ -static void _near mem_printdl(struct mem_debug *dl) +static void mem_printdl(struct mem_debug *dl) { PRINT "alloc'd from file '%s' line %d nbytes %d ptr %p\n", dl->Mfile,dl->Mline,dl->Mnbytes,(long)mem_dltoptr(dl)); @@ -371,7 +370,7 @@ static void _near mem_printdl(struct mem_debug *dl) * Print out file and line number. */ -static void _near mem_fillin(const char *fil, int lin) +static void mem_fillin(const char *fil, int lin) { PRINT "File '%s' line %d\n",fil,lin); #ifdef ferr diff --git a/tk/vec.h b/tk/vec.h index 77429c9c..b429eacc 100644 --- a/tk/vec.h +++ b/tk/vec.h @@ -50,7 +50,7 @@ void vec_clearextrabits (vec_t v); void vec_print (vec_t v); void vec_println (vec_t v); -#if _M_I86 && __INTSIZE == 4 +#if _M_I86 && __INTSIZE == 4 && __SC__ #define vec_setclear(b,vs,vc) { \ __asm mov EAX,b \ __asm mov ECX,vs \ diff --git a/tocsym.c b/tocsym.c index 1d614a1c..e1cd5f7f 100644 --- a/tocsym.c +++ b/tocsym.c @@ -87,7 +87,7 @@ Symbol *Dsymbol::toSymbolX(const char *prefix, int sclass, type *t, const char * } #endif id = (char *) alloca(2 + nlen + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1); - sprintf(id,"_D%s%zu%s%s", n, strlen(prefix), prefix, suffix); + sprintf(id,"_D%s%llu%s%s", n, (ulonglong)strlen(prefix), prefix, suffix); #if 0 if (global.params.isWindows && (type_mangle(t) == mTYman_c || type_mangle(t) == mTYman_std)) diff --git a/tocvdebug.c b/tocvdebug.c index e54bfeb0..2a6627c7 100644 --- a/tocvdebug.c +++ b/tocvdebug.c @@ -1,5 +1,5 @@ -// Copyright (c) 2004-2011 by Digital Mars +// Copyright (c) 2004-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -281,6 +281,34 @@ void EnumDeclaration::toDebug() } } +// Closure variables for Lambda cv_mem_count +struct CvMemberCount +{ + unsigned nfields; + unsigned fnamelen; +}; + +// Lambda function +int cv_mem_count(Dsymbol *s, void *param) +{ CvMemberCount *pmc = (CvMemberCount *)param; + + int nwritten = s->cvMember(NULL); + if (nwritten) + { + pmc->fnamelen += nwritten; + pmc->nfields++; + } + return 0; +} + +// Lambda function +int cv_mem_p(Dsymbol *s, void *param) +{ + unsigned char **pp = (unsigned char **)param; + *pp += s->cvMember(*pp); + return 0; +} + void StructDeclaration::toDebug() { @@ -354,24 +382,18 @@ void StructDeclaration::toDebug() return /*typidx*/; } - // Compute the number of fields, and the length of the fieldlist record - nfields = 0; - fnamelen = 2; + // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen) + CvMemberCount mc; + mc.nfields = 0; + mc.fnamelen = 2; + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_count, &mc); + } + nfields = mc.nfields; + fnamelen = mc.fnamelen; count = nfields; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - int nwritten; - - nwritten = s->cvMember(NULL); - if (nwritten) - { - fnamelen += nwritten; - nfields++; - count++; - } - } - TOWORD(d->data + 2,count); TOWORD(d->data + 6,property); @@ -383,9 +405,8 @@ void StructDeclaration::toDebug() TOWORD(p,LF_FIELDLIST); p += 2; for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - - p += s->cvMember(p); + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_p, &p); } //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); @@ -516,32 +537,25 @@ void ClassDeclaration::toDebug() return /*typidx*/; } - // Compute the number of fields, and the length of the fieldlist record - nfields = 0; - fnamelen = 2; - + // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen) + CvMemberCount mc; + mc.nfields = 0; + mc.fnamelen = 2; // Add in base classes for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *bc = baseclasses->tdata()[i]; + { BaseClass *bc = (*baseclasses)[i]; - nfields++; - fnamelen += 6 + cv4_numericbytes(bc->offset); + mc.nfields++; + mc.fnamelen += 6 + cv4_numericbytes(bc->offset); } + for (size_t i = 0; i < members->dim; i++) + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_count, &mc); + } + nfields = mc.nfields; + fnamelen = mc.fnamelen; count = nfields; - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - int nwritten; - - nwritten = s->cvMember(NULL); - if (nwritten) - { - fnamelen += nwritten; - nfields++; - count++; - } - } - TOWORD(d->data + 2,count); TOWORD(d->data + 6,property); @@ -555,7 +569,7 @@ void ClassDeclaration::toDebug() // Add in base classes for (size_t i = 0; i < baseclasses->dim; i++) - { BaseClass *bc = baseclasses->tdata()[i]; + { BaseClass *bc = (*baseclasses)[i]; idx_t typidx; unsigned attribute; @@ -572,12 +586,9 @@ void ClassDeclaration::toDebug() p += cv4_numericbytes(bc->offset); } - - for (size_t i = 0; i < members->dim; i++) - { Dsymbol *s = members->tdata()[i]; - - p += s->cvMember(p); + { Dsymbol *s = (*members)[i]; + s->apply(&cv_mem_p, &p); } //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); diff --git a/todt.c b/todt.c index 12a60333..610ebf2f 100644 --- a/todt.c +++ b/todt.c @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2011 by Digital Mars +// Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com @@ -20,7 +20,6 @@ #include #include #include -#include #include "lexer.h" #include "mtype.h" @@ -78,20 +77,20 @@ dt_t *StructInitializer::toDt() for (size_t i = 0; i < vars.dim; i++) { - VarDeclaration *v = vars.tdata()[i]; - Initializer *val = value.tdata()[i]; + VarDeclaration *v = vars[i]; + Initializer *val = value[i]; //printf("vars[%d] = %s\n", i, v->toChars()); for (size_t j = 0; 1; j++) { assert(j < dts.dim); - //printf(" adfield[%d] = %s\n", j, (ad->fields.tdata()[j])->toChars()); - if (ad->fields.tdata()[j] == v) + //printf(" adfield[%d] = %s\n", j, (ad->fields[j])->toChars()); + if (ad->fields[j] == v) { - if (dts.tdata()[j]) + if (dts[j]) error(loc, "field %s of %s already initialized", v->toChars(), ad->toChars()); - dts.tdata()[j] = val->toDt(); + dts[j] = val->toDt(); break; } } @@ -102,14 +101,16 @@ dt_t *StructInitializer::toDt() offset = 0; for (size_t j = 0; j < dts.dim; j++) { - VarDeclaration *v = ad->fields.tdata()[j]; + VarDeclaration *v = ad->fields[j]; - d = dts.tdata()[j]; + d = dts[j]; if (!d) { // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition - if (v->init) + if (v->init && v->init->isVoidInitializer()) + ; + else if (v->init) { d = v->init->toDt(); } @@ -126,9 +127,9 @@ dt_t *StructInitializer::toDt() v->type->toDt(&d); break; } - VarDeclaration *v2 = ad->fields.tdata()[k]; + VarDeclaration *v2 = ad->fields[k]; - if (v2->offset < offset2 && dts.tdata()[k]) + if (v2->offset < offset2 && dts[k]) break; // overlap } } @@ -209,17 +210,17 @@ dt_t *ArrayInitializer::toDt() { Expression *idx; Initializer *val; - idx = index.tdata()[i]; + idx = index[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); - val = value.tdata()[i]; + val = value[i]; dt = val->toDt(); - if (dts.tdata()[length]) + if (dts[length]) error(loc, "duplicate initializations for index %d", length); - dts.tdata()[length] = dt; + dts[length] = dt; length++; } @@ -236,7 +237,7 @@ dt_t *ArrayInitializer::toDt() pdtend = &d; for (size_t i = 0; i < dim; i++) { - dt = dts.tdata()[i]; + dt = dts[i]; if (dt) pdtend = dtcat(pdtend, dt); else @@ -267,9 +268,6 @@ dt_t *ArrayInitializer::toDt() } else if (dim > tadim) { -#ifdef DEBUG - printf("1: "); -#endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; @@ -335,7 +333,7 @@ dt_t *ArrayInitializer::toDtBit() if (tb->nextOf()->defaultInit()->toInteger()) databits.set(); - size = sizeof(databits.tdata()[0]); + size = sizeof(databits[0]); length = 0; for (size_t i = 0; i < index.dim; i++) @@ -343,7 +341,7 @@ dt_t *ArrayInitializer::toDtBit() Initializer *val; Expression *eval; - idx = index.tdata()[i]; + idx = index[i]; if (idx) { dinteger_t value; value = idx->toInteger(); @@ -355,7 +353,7 @@ dt_t *ArrayInitializer::toDtBit() } assert(length < dim); - val = value.tdata()[i]; + val = value[i]; eval = val->toExpression(); if (initbits.test(length)) error(loc, "duplicate initializations for index %d", length); @@ -424,7 +422,7 @@ dt_t *ExpInitializer::toDt() dt_t **Expression::toDt(dt_t **pdt) { -#ifdef DEBUG +#if 0 printf("Expression::toDt() %d\n", op); dump(0); #endif @@ -580,7 +578,7 @@ dt_t **ArrayLiteralExp::toDt(dt_t **pdt) d = NULL; pdtend = &d; for (size_t i = 0; i < elements->dim; i++) - { Expression *e = elements->tdata()[i]; + { Expression *e = (*elements)[i]; pdtend = e->toDt(pdtend); } @@ -619,55 +617,65 @@ dt_t **ArrayLiteralExp::toDt(dt_t **pdt) dt_t **StructLiteralExp::toDt(dt_t **pdt) { - Dts dts; - dt_t *dt; - dt_t *d; - unsigned offset; + //printf("StructLiteralExp::toDt() %s, ctfe = %d\n", toChars(), ownedByCtfe); - //printf("StructLiteralExp::toDt() %s)\n", toChars()); + /* For elements[], construct a corresponding array dts[] the elements + * of which are the initializers. + * Nulls in elements[] become nulls in dts[]. + */ + Dts dts; dts.setDim(sd->fields.dim); dts.zero(); assert(elements->dim <= sd->fields.dim); - for (size_t i = 0; i < elements->dim; i++) { - Expression *e = elements->tdata()[i]; + Expression *e = (*elements)[i]; if (!e) continue; - dt = NULL; - e->toDt(&dt); - dts.tdata()[i] = dt; + dt_t *dt = NULL; + e->toDt(&dt); // convert e to an initializer dt + dts[i] = dt; } - offset = 0; + unsigned offset = 0; for (size_t j = 0; j < dts.dim; j++) { - VarDeclaration *v = sd->fields.tdata()[j]; + VarDeclaration *v = sd->fields[j]; - d = dts.tdata()[j]; + dt_t *d = dts[j]; if (!d) - { // An instance specific initializer was not provided. + { /* An instance specific initializer was not provided. + * If there is no overlap with any explicit initializer in dts[], + * supply a default initializer. + */ +#if 0 + // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition - if (v->init) + if (v->init && v->init->isVoidInitializer()) + ; + else if (v->init) { d = v->init->toDt(); - } - else if (v->offset >= offset) + } else +#endif + if (v->offset >= offset) { unsigned offset2 = v->offset + v->type->size(); - // Make sure this field (v) does not overlap any explicitly - // initialized field. for (size_t k = j + 1; 1; k++) { if (k == dts.dim) // didn't find any overlap { - v->type->toDt(&d); + // Set d to be the default initializer + if (v->init) + d = v->init->toDt(); + else + v->type->toDt(&d); break; } - VarDeclaration *v2 = sd->fields.tdata()[k]; + VarDeclaration *v2 = sd->fields[k]; - if (v2->offset < offset2 && dts.tdata()[k]) + if (v2->offset < offset2 && dts[k]) break; // overlap } } @@ -735,7 +743,7 @@ dt_t **SymOffExp::toDt(dt_t **pdt) var->needThis() || var->isThreadlocal()) { -#ifdef DEBUG +#if 0 printf("SymOffExp::toDt()\n"); #endif error("non-constant expression %s", toChars()); @@ -771,7 +779,7 @@ dt_t **VarExp::toDt(dt_t **pdt) sd->dsym->toDt(pdt); return pdt; } -#ifdef DEBUG +#if 0 printf("VarExp::toDt(), kind = %s\n", var->kind()); #endif error("non-constant expression %s", toChars()); @@ -833,7 +841,7 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) // Note equivalence of this loop to struct's for (size_t i = 0; i < fields.dim; i++) { - VarDeclaration *v = fields.tdata()[i]; + VarDeclaration *v = fields[i]; Initializer *init; //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset); @@ -843,7 +851,9 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) { //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); - if (ei && tb->ty == Tsarray) + if (init->isVoidInitializer()) + ; + else if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); @@ -870,7 +880,7 @@ void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) toSymbol(); // define csym for (size_t i = 0; i < vtblInterfaces->dim; i++) - { BaseClass *b = vtblInterfaces->tdata()[i]; + { BaseClass *b = (*vtblInterfaces)[i]; #if 1 || INTERFACE_VIRTUAL for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass) @@ -910,7 +920,7 @@ void StructDeclaration::toDt(dt_t **pdt) // Note equivalence of this loop to class's for (size_t i = 0; i < fields.dim; i++) { - VarDeclaration *v = fields.tdata()[i]; + VarDeclaration *v = fields[i]; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; int sz; @@ -929,7 +939,9 @@ void StructDeclaration::toDt(dt_t **pdt) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); - if (ei && tb->ty == Tsarray) + if (init->isVoidInitializer()) + ; + else if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); diff --git a/toir.c b/toir.c index b1ee5108..8442b0d3 100644 --- a/toir.c +++ b/toir.c @@ -15,7 +15,7 @@ #include #include #include -#include +//#include #include "lexer.h" #include "expression.h" diff --git a/traits.c b/traits.c index e49fd553..2175f500 100644 --- a/traits.c +++ b/traits.c @@ -64,10 +64,10 @@ static int fptraits(void *param, FuncDeclaration *f) if (p->e1->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)p->e1; - e = new DotVarExp(0, dve->e1, f); + e = new DotVarExp(0, dve->e1, new FuncAliasDeclaration(f, 0)); } else - e = new DsymbolExp(0, f); + e = new DsymbolExp(0, new FuncAliasDeclaration(f, 0)); p->exps->push(e); return 0; } @@ -451,6 +451,10 @@ Expression *TraitsExp::semantic(Scope *sc) Expression *e; unsigned errors = global.startGagging(); + unsigned oldspec = global.speculativeGag; + global.speculativeGag = global.gag; + bool scSpec = sc->speculative; + sc->speculative = true; Type *t = isType(o); if (t) @@ -471,6 +475,8 @@ Expression *TraitsExp::semantic(Scope *sc) } } + sc->speculative = scSpec; + global.speculativeGag = oldspec; if (global.endGagging(errors)) { goto Lfalse; diff --git a/typinf.c b/typinf.c index ceb768a1..97bdc91a 100644 --- a/typinf.c +++ b/typinf.c @@ -547,6 +547,8 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) { Scope sc; + /* const hash_t toHash(); + */ tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); tftohash->mod = MODconst; tftohash = (TypeFunction *)tftohash->semantic(0, &sc); @@ -558,6 +560,9 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) TypeFunction *tfcmpptr; { Scope sc; + + /* const int opCmp(ref const KeyType s); + */ Parameters *arguments = new Parameters; #if STRUCTTHISREF // arg type is ref const T @@ -578,10 +583,28 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt) if (fdx) { fd = fdx->overloadExactMatch(tftohash); if (fd) + { dtxoff(pdt, fd->toSymbol(), 0, TYnptr); + TypeFunction *tf = (TypeFunction *)fd->type; + assert(tf->ty == Tfunction); + if (global.params.warnings) + { + /* I'm a little unsure this is the right way to do it. Perhaps a better + * way would to automatically add these attributes to any struct member + * function with the name "toHash". + * So I'm leaving this here as an experiment for the moment. + */ + if (!tf->isnothrow || tf->trust == TRUSTsystem || tf->purity == PUREimpure) + { warning(fd->loc, "toHash() must be declared as extern (D) uint toHash() const pure nothrow @safe, not %s", tf->toChars()); + global.errors++; + } + } + } else + { //fdx->error("must be declared as extern (D) uint toHash()"); dtsize_t(pdt, 0); + } } else dtsize_t(pdt, 0); diff --git a/util.c b/util.c index 77ecf8e8..5553aced 100644 --- a/util.c +++ b/util.c @@ -50,7 +50,7 @@ void file_progress() * Alternative assert failure. */ -void util_assert(char *file,int line) +void util_assert(const char *file, int line) { fflush(stdout); printf("Internal error: %s %d\n",file,line); @@ -86,7 +86,7 @@ void util_exit(int exitcode) } -#if _WIN32 +#if _WIN32 && !_MSC_VER volatile int controlc_saw; @@ -136,7 +136,7 @@ void util_progress(int linnum) #endif -#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 +#if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4 || _MSC_VER void util_progress() { } @@ -213,18 +213,19 @@ L63: #else -int binary(const char *p, const char __near * __near *table,int high) -{ int low,mid; - signed char cond; - char cp; +int binary(const char *p, const char ** table, int high) +{ + int low = 0; + char cp = *p; + high--; + p++; - low = 0; - high--; - cp = *p; - p++; - while (low <= high) - { mid = (low + high) >> 1; - if ((cond = table[mid][0] - cp) == 0) + while (low <= high) + { + int mid = (low + high) >> 1; + int cond = table[mid][0] - cp; + + if (cond == 0) cond = strcmp(table[mid] + 1,p); if (cond > 0) high = mid - 1; @@ -232,12 +233,43 @@ int binary(const char *p, const char __near * __near *table,int high) low = mid + 1; else return mid; /* match index */ - } - return -1; + } + return -1; } #endif +// search table[0 .. high] for p[0 .. len] (where p.length not necessairily equal to len) +int binary(const char *p, size_t len, const char ** table, int high) +{ + int low = 0; + char cp = *p; + high--; + p++; + len--; + + while (low <= high) + { + int mid = (low + high) >> 1; + int cond = table[mid][0] - cp; + + if (cond == 0) + { + cond = strncmp(table[mid] + 1, p, len); + if (cond == 0) + cond = table[mid][len+1]; // same as: if (table[mid][len+1] != '\0') cond = 1; + } + + if (cond > 0) + high = mid - 1; + else if (cond < 0) + low = mid + 1; + else + return mid; /* match index */ + } + return -1; +} + /********************** * If c is a power of 2, return that power else -1. */ diff --git a/vcbuild/alloca.h b/vcbuild/alloca.h new file mode 100644 index 00000000..c0d7985b --- /dev/null +++ b/vcbuild/alloca.h @@ -0,0 +1 @@ +#include diff --git a/vcbuild/builddmd.bat b/vcbuild/builddmd.bat new file mode 100644 index 00000000..b355610d --- /dev/null +++ b/vcbuild/builddmd.bat @@ -0,0 +1,13 @@ +@echo off +rem Run this batch file from the src folder like this: +rem vcbuild\builddmd.bat +rem +rem Make sure that you do not have cl.exe from the dmc compiler +rem in your path! +rem +rem "make" should be the Digital Mars make, this can be found +rem if dmd's bin folder is in the path + +set DEBUG=/Zi +if "%1" == "release" set DEBUG=/O2 +make -f win32.mak CC=vcbuild\dmc_cl INCLUDE=vcbuild DEBUG=%DEBUG% dmd.exe diff --git a/vcbuild/dmc_cl.bat b/vcbuild/dmc_cl.bat new file mode 100644 index 00000000..f6dab6a2 --- /dev/null +++ b/vcbuild/dmc_cl.bat @@ -0,0 +1,44 @@ +@echo off +rem echo called with: %* +set def=/DLITTLE_ENDIAN=1 /D__pascal= /D_M_I86=1 +rem copt defaults to linker options +set copt=/nologo /link /LARGEADDRESSAWARE +set cmd= +:next +if "%1" == "" goto done +rem echo %1 + +set opt=%1 +if "%opt:~0,1%" == "-" goto opt +if "%opt:~0,1%" == "/" goto opt + +if "%opt:~-2%" == ".c" goto isC +if "%opt:~-4%" == ".obj" goto add +set opt=%opt%.c +:isC +set copt=/TP /Ivcbuild /Iroot /nologo /EHsc /Zp1 %def% +goto add + +:opt +if "%opt:~0,2%" == "-o" ( + if "%opt:~-4%" == ".exe" set opt=/Fe%opt:~2% + if "%opt:~-4%" == ".obj" set opt=/Fo%opt:~2% +) +if "%opt%" == "-e" goto shift +if "%opt%" == "-Ae" goto shift +if "%opt%" == "-Ar" goto shift +if "%opt%" == "-mn" goto shift +if "%opt%" == "-cpp" goto shift +if "%opt%" == "-wx" goto shift +if "%opt%" == "-m32" goto shift + +:add +set cmd=%cmd% %opt% + +:shift +shift +goto next + +:done +rem echo cl %copt% %cmd% +cl %cmd% %copt% diff --git a/vcbuild/fenv.h b/vcbuild/fenv.h new file mode 100644 index 00000000..e8ccb9ce --- /dev/null +++ b/vcbuild/fenv.h @@ -0,0 +1,5 @@ + +#include + +#define isnan _isnan + diff --git a/vcbuild/ldfpu.asm b/vcbuild/ldfpu.asm new file mode 100644 index 00000000..c7958d69 --- /dev/null +++ b/vcbuild/ldfpu.asm @@ -0,0 +1,336 @@ +;; Compiler implementation of the D programming language +;; Copyright (c) 1999-2011 by Digital Mars +;; All Rights Reserved +;; written by Rainer Schuetze +;; 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. + +;; 80 bit floating point value implementation for Microsoft compiler + +;.386 +;.model flat, c + +; Custom Build Step, including a listing file placed in intermediate directory +; debug: +; ml -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)" +; release: +; ml -c "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)" +; outputs: +; $(IntDir)\$(InputName).obj + +.data + +twoPow63 dd 0, 80000000h, 03fffh + 63 + +.code + +; double ld_read(longdouble* ld); +; rcx: ld +ld_read PROC + fld tbyte ptr [rcx] + push rax + fstp qword ptr [esp] + movq xmm0,qword ptr [rsp] + pop rax + ret +ld_read ENDP + +; long long ld_readll(longdouble* ld); +; rcx: ld +ld_readll PROC + fld tbyte ptr [rcx] + push rax + fistp qword ptr [esp] + pop rax + ret +ld_readll ENDP + +; unsigned long long ld_readull(longdouble* ld); +; rcx: ld +ld_readull PROC + fld tbyte ptr [rcx] + push rax + lea rax,twoPow63 + fld tbyte ptr [rax] + fsubp ST(1),ST(0) ; move it into signed range + fistp qword ptr [esp] + pop rax + btc rax,63 + ret +ld_readull ENDP + +; void ld_set(longdouble* ld, double d); +; rcx: ld +; xmm1: d +ld_set PROC + push rax + movq qword ptr [rsp],xmm1 + fld qword ptr [rsp] + fstp tbyte ptr [rcx] + pop rax + ret +ld_set ENDP + +; void ld_setll(longdouble* ld, long long d); +; rcx: ld +; rdx: d +ld_setll PROC + push rdx + fild qword ptr [esp] + fstp tbyte ptr [rcx] + pop rax + ret +ld_setll ENDP + +; void ld_setull(longdouble* ld, long long d); +; rcx: ld +; rax: d +ld_setull PROC + btc rdx,63 + push rdx + fild qword ptr [esp] + lea rax,twoPow63 + fld tbyte ptr [rax] + faddp ST(1),ST(0) + fstp tbyte ptr [rcx] + pop rax + ret +ld_setull ENDP + +; void ld_expl(longdouble* ld, int exp); +; rcx: ld +; edx: exp +ld_expl PROC + push rdx + fild dword ptr [esp] + fld tbyte ptr [rcx] + fscale ; ST(0) = ST(0) * (2**ST(1)) + fstp ST(1) + fstp tbyte ptr [rcx] + pop rax + ret +ld_expl ENDP + +; long_double ld_add(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_add PROC + fld tbyte ptr [r8] + fld tbyte ptr [rdx] + fadd + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_add ENDP + +; long_double ld_sub(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_sub PROC + fld tbyte ptr [rdx] + fld tbyte ptr [r8] + fsub + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sub ENDP + +; long_double ld_mul(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_mul PROC + fld tbyte ptr [r8] + fld tbyte ptr [rdx] + fmul + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_mul ENDP + +; long_double ld_div(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_div PROC + fld tbyte ptr [rdx] + fld tbyte ptr [r8] + fdiv + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_div ENDP + +; long_double ld_mod(long_double ld1, long_double ld2); +; rcx: &res +; rdx: &ld1 +; r8: &ld2 +ld_mod PROC + push rax + fld tbyte ptr [r8] + fld tbyte ptr [rdx] ; ST = x, ST1 = y +FM1: ; We don't use fprem1 because for some inexplicable + ; reason we get -5 when we do _modulo(15, 10) + fprem ; ST = ST % ST1 + fstsw word ptr [rsp] + fwait + mov AH,byte ptr [rsp+1] ; get msb of status word in AH + sahf ; transfer to flags + jp FM1 ; continue till ST < ST1 + fstp ST(1) ; leave remainder on stack + fstp tbyte ptr [ecx] + pop rax + mov rax,rcx + ret +ld_mod ENDP + +; bool ld_cmpb(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpb PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setb AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpb ENDP + +; bool ld_cmpbe(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpbe PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setbe AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpbe ENDP + +; bool ld_cmpa(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpa PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + seta AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpa ENDP + +; bool ld_cmpae(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpae PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setae AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpae ENDP + +; bool ld_cmpe(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpe PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + sete AL + setnp AH + and AL,AH + fstp ST(0) + ret +ld_cmpe ENDP + +; bool ld_cmpne(long_double x, long_double y); +; rcx: &x +; rdx: &y +ld_cmpne PROC + fld tbyte ptr [rdx] + fld tbyte ptr [rcx] + fucomip ST(0),ST(1) + setne AL + setp AH + or AL,AH + fstp ST(0) + ret +ld_cmpne ENDP + +; long_double ld_sqrt(long_double x); +; rcx: &res +; rdx: &x +ld_sqrt PROC + fld tbyte ptr [rdx] + fsqrt + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sqrt ENDP + +; long_double ld_sin(long_double x); +; rcx: &res +; rdx: &x +ld_sin PROC + fld tbyte ptr [rdx] + fsin + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_sin ENDP + +; long_double ld_cos(long_double x); +; rcx: &res +; rdx: &x +ld_cos PROC + fld tbyte ptr [rdx] + fcos + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_cos ENDP + +; long_double ld_tan(long_double x); +; rcx: &res +; rdx: &x +ld_tan PROC + fld tbyte ptr [rdx] + fptan + fstp st(0) + fstp tbyte ptr [rcx] + mov rax,rcx + ret +ld_tan ENDP + +; int ld_initfpu(int bits, int mask) +; ecx: bits +; edx: mask +ld_initfpu PROC + push rcx + fstcw word ptr [rsp] + movzx EAX,word ptr [rsp] ; also return old CW in EAX + not EDX + and EDX,EAX + or ECX,EDX + mov dword ptr [rsp],ECX + fldcw word ptr [rsp] + pop rcx + ret +ld_initfpu ENDP + +end diff --git a/vcbuild/stdint.h b/vcbuild/stdint.h new file mode 100644 index 00000000..57db989c --- /dev/null +++ b/vcbuild/stdint.h @@ -0,0 +1,206 @@ +/* ISO C9x 7.18 Integer types + * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * Contributor: Danny Smith + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2000-12-02 + */ + + +#ifndef _STDINT_H +#define _STDINT_H +#define __need_wint_t +#define __need_wchar_t +#include + +/* 7.18.1.1 Exact-width integer types */ +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +/* 7.18.1.2 Minimum-width integer types */ +typedef signed char int_least8_t; +typedef unsigned char uint_least8_t; +typedef short int_least16_t; +typedef unsigned short uint_least16_t; +typedef int int_least32_t; +typedef unsigned uint_least32_t; +typedef long long int_least64_t; +typedef unsigned long long uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types + * Not actually guaranteed to be fastest for all purposes + * Here we use the exact-width types for 8 and 16-bit ints. + */ +typedef char int_fast8_t; +typedef unsigned char uint_fast8_t; +typedef short int_fast16_t; +typedef unsigned short uint_fast16_t; +typedef int int_fast32_t; +typedef unsigned int uint_fast32_t; +typedef long long int_fast64_t; +typedef unsigned long long uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +#ifndef _INTPTR_T_DEFINED +#define _INTPTR_T_DEFINED +#ifdef _WIN64 + typedef __int64 intptr_t; +#else + typedef int intptr_t; +#endif +#endif + +#ifndef _UINTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED +#ifdef _WIN64 + typedef unsigned __int64 uintptr_t; +#else + typedef unsigned int uintptr_t; +#endif +#endif + +/* 7.18.1.5 Greatest-width integer types */ +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +/* 7.18.2 Limits of specified-width integer types */ +#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS) + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647 - 1) +#define INT64_MIN (-9223372036854775807LL - 1) + +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807LL + +#define UINT8_MAX 0xff /* 255U */ +#define UINT16_MAX 0xffff /* 65535U */ +#define UINT32_MAX 0xffffffff /* 4294967295U */ +#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */ + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding + object pointers */ +#ifdef _WIN64 +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* 7.18.3 Limits of other integer types */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +#define SIG_ATOMIC_MIN INTPTR_MIN +#define SIG_ATOMIC_MAX INTPTR_MAX + +#define SIZE_MAX UINTPTR_MAX + +#ifndef WCHAR_MIN /* also in wchar.h */ +#define WCHAR_MIN 0 +#define WCHAR_MAX 0xffff /* UINT16_MAX */ +#endif + +/* + * wint_t is unsigned short for compatibility with MS runtime + */ +#define WINT_MIN 0 +#define WINT_MAX 0xffff /* UINT16_MAX */ + +#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */ + + +/* 7.18.4 Macros for integer constants */ +#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS) + +/* 7.18.4.1 Macros for minimum-width integer constants + + Accoding to Douglas Gwyn : + "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC + 9899:1999 as initially published, the expansion was required + to be an integer constant of precisely matching type, which + is impossible to accomplish for the shorter types on most + platforms, because C99 provides no standard way to designate + an integer constant with width less than that of type int. + TC1 changed this to require just an integer constant + *expression* with *promoted* type." +*/ + +#define INT8_C(val) ((int8_t) + (val)) +#define UINT8_C(val) ((uint8_t) + (val##U)) +#define INT16_C(val) ((int16_t) + (val)) +#define UINT16_C(val) ((uint16_t) + (val##U)) + +#define INT32_C(val) val##L +#define UINT32_C(val) val##UL +#define INT64_C(val) val##LL +#define UINT64_C(val) val##ULL + +/* 7.18.4.2 Macros for greatest-width integer constants */ +#define INTMAX_C(val) INT64_C(val) +#define UINTMAX_C(val) UINT64_C(val) + +#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */ + +#endif diff --git a/vcbuild/warnings.h b/vcbuild/warnings.h new file mode 100644 index 00000000..3e60ae6f --- /dev/null +++ b/vcbuild/warnings.h @@ -0,0 +1,30 @@ +#pragma warning(disable:4996) // This function or variable may be unsafe. +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4101) // unreferenced local variable +#pragma warning(disable:4100) // unreferenced formal parameter +#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable:4244) // conversion from 'int' to 'unsigned short', possible loss of data +#pragma warning(disable:4245) // conversion from 'int' to 'unsigned int', signed/unsigned mismatch +#pragma warning(disable:4018) // signed/unsigned mismatch +#pragma warning(disable:4389) // signed/unsigned mismatch +#pragma warning(disable:4505) // unreferenced local function has been removed +#pragma warning(disable:4701) // potentially uninitialized local variable 'm' used +#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union +#pragma warning(disable:4189) // local variable is initialized but not referenced +#pragma warning(disable:4102) // unreferenced label +#pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable:4390) // ';' : empty controlled statement found; is this the intent? +#pragma warning(disable:4702) // unreachable code +#pragma warning(disable:4703) // potentially uninitialized local pointer variable 'm' used + +#ifdef _WIN64 +#pragma warning(disable:4366) // The result of the unary '&' operator may be unaligned +#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int', possible loss of data +#pragma warning(disable:4310) // cast truncates constant value +#endif + +#define LITTLE_ENDIAN 1 +#define __pascal +#define MARS 1 +#define UNITTEST 1 +#define _M_I86 1 diff --git a/win32.mak b/win32.mak index 1b1ab046..1a8fd198 100644 --- a/win32.mak +++ b/win32.mak @@ -164,6 +164,7 @@ ROOTSRC= $(ROOT)\dchar.h $(ROOT)\dchar.c $(ROOT)\lstring.h \ $(ROOT)\response.c $(ROOT)\async.h $(ROOT)\async.c \ $(ROOT)\speller.h $(ROOT)\speller.c \ $(ROOT)\aav.h $(ROOT)\aav.c \ + $(ROOT)\longdouble.h $(ROOT)\longdouble.c \ $(ROOT)\dmgcmem.c $(ROOT)\gc\bits.c $(ROOT)\gc\gc.c $(ROOT)\gc\gc.h $(ROOT)\gc\mscbitops.h \ $(ROOT)\gc\bits.h $(ROOT)\gc\gccbitops.h $(ROOT)\gc\linux.c $(ROOT)\gc\os.h \ $(ROOT)\gc\win32.c @@ -339,7 +340,7 @@ module.obj : $(TOTALH) $C\html.h module.c $(CC) -c $(CFLAGS) -I$C $(PREC) module.c msc.obj : $(CH) mars.h msc.c - $(CC) -c $(MFLAGS) msc + $(CC) -c $(MFLAGS) -I$(ROOT) msc newman.obj : $(CH) $C\newman.c $(CC) -c $(MFLAGS) $C\newman