Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1561

Show
Ignore:
Timestamp:
05/26/10 14:22:06 (15 years ago)
Author:
rsinfu
Message:

Added code for bugzilla 3909: toDelegate handles only a tiny subset of function pointer types.

The bug is not completely fixed. toDelegate() still does not work well with @safe function pointers... because toDelegate() is unsafe. And variadic arguments are ignored.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/functional.d

    r1556 r1561  
    507507    // assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5); 
    508508    // assert(compose!(baz, bar)("1"[]) == 2.5); 
    509509     
    510510    // @@@BUG@@@ 
    511511    //assert(compose!(baz, bar)("1") == 2.5); 
    512512 
    513513    // @@@BUG@@@ 
    514514    //assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5); 
    515515} 
    516516 
    517 private struct DelegateFaker(R, Args...) { 
    518     R doIt(Args args) { 
    519         // When this function gets called, the this pointer isn't really a 
    520         // this pointer (no instance even really exists), but a function 
    521         // pointer that points to the function 
    522         // to be called.  Cast it to the correct type and call it. 
    523  
    524         auto fp = cast(R function(Args)) &this; 
    525         return fp(args); 
    526     } 
     517private struct DelegateFaker(F) { 
     518    /* 
     519     * What all the stuff below does is this: 
     520     *-------------------- 
     521     * struct DelegateFaker(F) { 
     522     *     extern(linkage) 
     523     *     [ref] ReturnType!F doIt(ParameterTypeTuple!F args) [@attributes] 
     524     *     { 
     525     *         auto fp = cast(F) &this; 
     526     *         return fp(args); 
     527     *     } 
     528     * } 
     529     *-------------------- 
     530     */ 
     531 
     532    // We will use MemberFunctionGenerator in std.typecons.  This is a policy 
     533    // configuration for generating the doIt(). 
     534    template GeneratingPolicy() 
     535    { 
     536        // Inform the genereator that we only have type information. 
     537        enum WITHOUT_SYMBOL = true; 
     538 
     539        // Generate the function body of doIt(). 
     540        template generateFunctionBody(unused...) 
     541        { 
     542            enum generateFunctionBody = 
     543            // [ref] ReturnType doIt(ParameterTypeTuple args) @attributes 
     544            q{ 
     545                // When this function gets called, the this pointer isn't 
     546                // really a this pointer (no instance even really exists), but 
     547                // a function pointer that points to the function to be called. 
     548                // Cast it to the correct type and call it. 
     549 
     550                auto fp = cast(F) &this; // XXX doesn't work with @safe 
     551                return fp(args); 
     552            }; 
     553        } 
     554    } 
     555    // Type information used by the generated code. 
     556    alias FuncInfo!(F) FuncInfo_doIt; 
     557 
     558    // Generate the member function doIt(). 
     559    mixin( std.typecons.MemberFunctionGenerator!(GeneratingPolicy!()) 
     560            .generateFunction!("FuncInfo_doIt", "doIt", F) ); 
    527561} 
    528562 
    529563/**Convert a callable to a delegate with the same parameter list and 
    530564 * return type, avoiding heap allocations and use of auxiliary storage. 
    531565 * 
    532566 * Examples: 
    533567 * --- 
    534568 * void doStuff() { 
    535569 *     writeln("Hello, world."); 
    536570 * } 
    537571 * 
    538572 * void runDelegate(void delegate() myDelegate) { 
    539573 *     myDelegate(); 
    540574 * } 
    541575 * 
    542576 * auto delegateToPass = toDelegate(&doStuff); 
    543577 * runDelegate(delegateToPass);  // Calls doStuff, prints "Hello, world." 
    544578 * --- 
    545579 * 
    546  * Bugs:  Doesn't work properly with ref return.  (See DMD bug 3756.) 
     580 * BUGS: 
     581 * $(UL 
     582 *   $(LI Does not work with $(D @safe) functions.) 
     583 *   $(LI Ignores C-style / D-style variadic arguments.) 
     584 * ) 
    547585 */ 
    548586auto toDelegate(F)(auto ref F fp) if (isCallable!(F)) { 
    549587 
    550588    static if (is(F == delegate)) 
    551589    { 
    552590        return fp; 
    553591    } 
    554592    else static if (is(typeof(&F.opCall) == delegate) 
    555593                || (is(typeof(&F.opCall) V : V*) && is(V == function))) 
    556594    { 
    557595        return toDelegate(&fp.opCall); 
    558596    } 
    559597    else 
    560598    { 
    561         // Workaround for DMD Bug 1818. 
    562         mixin("alias " ~ ReturnType!(F).stringof ~ 
    563             " delegate" ~ ParameterTypeTuple!(F).stringof ~ " DelType;"); 
    564  
    565         version(none) { 
    566             // What the code would be if it weren't for bug 1818: 
    567             alias ReturnType!(F) delegate(ParameterTypeTuple!(F)) DelType; 
    568         } 
     599        alias typeof(&(new DelegateFaker!(F)).doIt) DelType; 
    569600 
    570601        static struct DelegateFields { 
    571602            union { 
    572603                DelType del; 
    573604                //pragma(msg, typeof(del)); 
    574605 
    575606                struct { 
    576607                    void* contextPtr; 
    577608                    void* funcPtr; 
    578609                } 
    579610            } 
    580611        } 
    581612 
    582613        // fp is stored in the returned delegate's context pointer. 
    583614        // The returned delegate's function pointer points to 
    584615        // DelegateFaker.doIt. 
    585616        DelegateFields df; 
    586617 
    587618        df.contextPtr = cast(void*) fp; 
    588619 
    589         DelegateFaker!(ReturnType!(F), ParameterTypeTuple!(F)) dummy; 
     620        DelegateFaker!(F) dummy; 
    590621        auto dummyDel = &(dummy.doIt); 
    591622        df.funcPtr = dummyDel.funcptr; 
    592623 
    593624        return df.del; 
    594625    } 
    595626} 
    596627 
    597628unittest { 
    598629    static int inc(ref uint num) { 
    599630        num++; 
     
    621652    static assert(!is(typeof(&s1.opCall) == delegate)); 
    622653    S1 s1; 
    623654    auto getvals1 = toDelegate(s1); 
    624655    assert(getvals1() == 4); 
    625656     
    626657    struct S2 { static int opCall() { return 123456; } } 
    627658    static assert(!is(typeof(&S2.opCall) == delegate)); 
    628659    S2 s2; 
    629660    auto getvals2 =&S2.opCall; 
    630661    assert(getvals2() == 123456); 
    631 
     662 
     663    /* test for attributes */ 
     664    { 
     665        static int refvar = 0xDeadFace; 
     666 
     667        static ref int func_ref() { return refvar; } 
     668        static int func_pure() pure { return 1; } 
     669        static int func_nothrow() nothrow { return 2; } 
     670        static int func_property() @property { return 3; } 
     671        static int func_safe() @safe { return 4; } 
     672        static int func_trusted() @trusted { return 5; } 
     673        static int func_system() @system { return 6; } 
     674        static int func_pure_nothrow() pure nothrow { return 7; } 
     675        static int func_pure_nothrow_safe() pure @safe { return 8; } 
     676 
     677        auto dg_ref = toDelegate(&func_ref); 
     678        auto dg_pure = toDelegate(&func_pure); 
     679        auto dg_nothrow = toDelegate(&func_nothrow); 
     680        auto dg_property = toDelegate(&func_property); 
     681        //auto dg_safe = toDelegate(&func_safe); 
     682        auto dg_trusted = toDelegate(&func_trusted); 
     683        auto dg_system = toDelegate(&func_system); 
     684        auto dg_pure_nothrow = toDelegate(&func_pure_nothrow); 
     685        //auto dg_pure_nothrow_safe = toDelegate(&func_pure_nothrow_safe); 
     686 
     687        //static assert(is(typeof(dg_ref) == ref int delegate())); // [BUG@DMD] 
     688        static assert(is(typeof(dg_pure) == int delegate() pure)); 
     689        static assert(is(typeof(dg_nothrow) == int delegate() nothrow)); 
     690        static assert(is(typeof(dg_property) == int delegate() @property)); 
     691        //static assert(is(typeof(dg_safe) == int delegate() @safe)); 
     692        static assert(is(typeof(dg_trusted) == int delegate() @trusted)); 
     693        static assert(is(typeof(dg_system) == int delegate() @system)); 
     694        static assert(is(typeof(dg_pure_nothrow) == int delegate() pure nothrow)); 
     695        //static assert(is(typeof(dg_pure_nothrow_safe) == int delegate() pure nothrow @safe)); 
     696 
     697        assert(dg_ref() == refvar); 
     698        assert(dg_pure() == 1); 
     699        assert(dg_nothrow() == 2); 
     700        assert(dg_property() == 3); 
     701        //assert(dg_safe() == 4); 
     702        assert(dg_trusted() == 5); 
     703        assert(dg_system() == 6); 
     704        assert(dg_pure_nothrow() == 7); 
     705        //assert(dg_pure_nothrow_safe() == 8); 
     706    } 
     707    /* test for linkage */ 
     708    { 
     709        struct S 
     710        { 
     711            extern(C) static void xtrnC() {} 
     712            extern(D) static void xtrnD() {} 
     713        } 
     714        auto dg_xtrnC = toDelegate(&S.xtrnC); 
     715        auto dg_xtrnD = toDelegate(&S.xtrnD); 
     716        static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); 
     717    } 
     718
  • trunk/phobos/std/traits.d

    r1551 r1561  
    20142014    static assert(isTypeTuple!(typeof(func))); 
    20152015    static assert(isTypeTuple!(int, char, double)); 
    20162016 
    20172017    static assert(! isTypeTuple!(c)); 
    20182018    static assert(! isTypeTuple!(isTypeTuple)); 
    20192019    static assert(! isTypeTuple!(CONST)); 
    20202020} 
    20212021 
    20222022 
    20232023/** 
     2024Detect whether symbol or type $(D T) is a function pointer. 
     2025 */ 
     2026template isFunctionPointer(T...) 
     2027    if (T.length == 1) 
     2028{ 
     2029    static if (is(T[0] U) || is(typeof(T[0]) U)) 
     2030    { 
     2031        static if (is(U F : F*) && is(F == function)) 
     2032            enum bool isFunctionPointer = true; 
     2033        else 
     2034            enum bool isFunctionPointer = false; 
     2035    } 
     2036    else 
     2037        enum bool isFunctionPointer = false; 
     2038} 
     2039 
     2040unittest 
     2041{ 
     2042    static void foo() {} 
     2043    void bar() {} 
     2044 
     2045    auto fpfoo = &foo; 
     2046    static assert(isFunctionPointer!(fpfoo)); 
     2047    static assert(isFunctionPointer!(void function())); 
     2048 
     2049    auto dgbar = &bar; 
     2050    static assert(! isFunctionPointer!(dgbar)); 
     2051    static assert(! isFunctionPointer!(void delegate())); 
     2052    static assert(! isFunctionPointer!(foo)); 
     2053    static assert(! isFunctionPointer!(bar)); 
     2054} 
     2055 
     2056 
     2057/** 
    20242058Detect whether symbol or type $(D T) is a function, a function pointer or a delegate. 
    20252059 */ 
    20262060template isSomeFunction(T...) 
    20272061    if (T.length == 1) 
    20282062{ 
    20292063    static if (is(typeof(& T[0]) U : U*) && is(U == function)) 
    20302064    { 
    20312065        // T is a function symbol. 
    20322066        enum bool isSomeFunction = true; 
    20332067    } 
  • trunk/phobos/std/typecons.d

    r1554 r1561  
    15291529} 
    15301530 
    15311531 
    15321532/** 
    15331533$(D AutoImplement) automatically implements (by default) all abstract member 
    15341534functions in the class or interface $(D Base) in specified way. 
    15351535 
    15361536Params: 
    15371537  how  = template which specifies _how functions will be implemented/overridden. 
    15381538 
    1539          Two arguments are passed to $(D how): the first one is the $(D Base), 
    1540          and the second one is an alias to a function to be implemented.  Then 
    1541          $(D how) must return a implemented function body as a string. 
     1539         Two arguments are passed to $(D how): the type $(D Base) and an alias 
     1540         to an implemented function.  Then $(D how) must return an implemented 
     1541         function body as a string. 
    15421542 
    15431543         The generated function body can use these keywords: 
    15441544         $(UL 
    15451545            $(LI $(D a0), $(D a1), …: arguments passed to the function;) 
    15461546            $(LI $(D args): a tuple of the arguments;) 
    15471547            $(LI $(D self): an alias to the function itself;) 
    15481548            $(LI $(D parent): an alias to the overridden function (if any).) 
    15491549         ) 
    15501550 
    15511551        You may want to use templated property functions (instead of Implicit 
     
    17661766    { 
    17671767        // base class identifier which generated code should use 
    17681768        enum string BASE_CLASS_ID = baseName; 
    17691769 
    17701770        // FuncInfo instance identifier which generated code should use 
    17711771        template FUNCINFO_ID(string name, size_t i) 
    17721772        { 
    17731773            enum string FUNCINFO_ID = 
    17741774                myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i); 
    17751775        } 
    1776  
    1777         // preferred identifier for i-th parameter variable 
    1778         template PARAMETER_VARIABLE_ID(size_t i) 
    1779         { 
    1780             enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i); 
    1781         } 
    17821776    } 
    17831777 
    17841778    /* Policy configurations for generating constructors. */ 
    17851779    template ConstructorGeneratingPolicy() 
    17861780    { 
    17871781        mixin CommonGeneratingPolicy; 
    17881782 
    17891783        /* Generates constructor body.  Just forward to the base class' one. */ 
    17901784        string generateFunctionBody(ctor.../+[BUG 4217]+/)() @property 
    17911785        { 
     
    18711865        static class C_6 
    18721866        { 
    18731867            this(int n) { assert(n == 42); } 
    18741868            this(string s) { assert(s == "Deeee"); } 
    18751869            this(...) {} 
    18761870        } 
    18771871        auto o1 = new BlackHole!C_6(42); 
    18781872        auto o2 = new BlackHole!C_6("Deeee"); 
    18791873        auto o3 = new BlackHole!C_6(1, 2, 3, 4); 
    18801874    } 
     1875    // attributes 
     1876    { 
     1877        interface I_7 
     1878        { 
     1879            ref int test_ref(); 
     1880            int test_pure() pure; 
     1881            int test_nothrow() nothrow; 
     1882            int test_property() @property; 
     1883            int test_safe() @safe; 
     1884            int test_trusted() @trusted; 
     1885            int test_system() @system; 
     1886            int test_pure_nothrow() pure nothrow; 
     1887        } 
     1888        auto o = new BlackHole!I_7; 
     1889    } 
     1890    // storage classes 
     1891    { 
     1892        interface I_8 
     1893        { 
     1894            void test_const() const; 
     1895            void test_immutable() immutable; 
     1896            void test_shared() shared; 
     1897            void test_shared_const() shared const; 
     1898        } 
     1899        auto o = new BlackHole!I_8; 
     1900    } 
    18811901    /+ // deep inheritance 
    18821902    { 
    18831903    // XXX [BUG 2525,3525] 
    18841904    // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic() 
    18851905        interface I { void foo(); } 
    18861906        interface J : I {} 
    18871907        interface K : J {} 
    1888         static abstract class C_8 : K {} 
    1889         auto o = new BlackHole!C_8
     1908        static abstract class C_9 : K {} 
     1909        auto o = new BlackHole!C_9
    18901910    }+/ 
    18911911} 
    18921912 
    18931913 
    18941914/* 
    18951915Used by MemberFunctionGenerator. 
    18961916 */ 
    1897 private template OverloadSet(string nam, T...) 
     1917package template OverloadSet(string nam, T...) 
    18981918{ 
    18991919    enum string name = nam; 
    19001920    alias T contents; 
    19011921} 
    19021922 
    19031923/* 
    19041924Used by MemberFunctionGenerator. 
    19051925 */ 
    1906 private template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 
     1926package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 
    19071927{ 
    19081928    alias         ReturnType!(T) RT; 
    19091929    alias ParameterTypeTuple!(T) PT; 
    19101930} 
     1931package template FuncInfo(Func) 
     1932{ 
     1933    alias         ReturnType!(Func) RT; 
     1934    alias ParameterTypeTuple!(Func) PT; 
     1935} 
    19111936 
    19121937/* 
    19131938General-purpose member function generator. 
    1914  */ 
    1915 private template MemberFunctionGenerator(alias Policy) 
     1939-------------------- 
     1940template GeneratingPolicy() 
     1941
     1942    // [optional] the name of the class where functions are derived 
     1943    enum string BASE_CLASS_ID; 
     1944 
     1945    // [optional] define this if you have only function types 
     1946    enum bool WITHOUT_SYMBOL; 
     1947 
     1948    // [optional] Returns preferred identifier for i-th parameter. 
     1949    template PARAMETER_VARIABLE_ID(size_t i); 
     1950 
     1951    // Returns the identifier of the FuncInfo instance for the i-th overload 
     1952    // of the specified name.  The identifier must be accessible in the scope 
     1953    // where generated code is mixed. 
     1954    template FUNCINFO_ID(string name, size_t i); 
     1955 
     1956    // Returns implemented function body as a string.  When WITHOUT_SYMBOL is 
     1957    // defined, the latter is used. 
     1958    template generateFunctionBody(alias func); 
     1959    template generateFunctionBody(string name, FuncType); 
     1960
     1961-------------------- 
     1962 */ 
     1963package template MemberFunctionGenerator(alias Policy) 
    19161964{ 
    19171965private static: 
    1918     //mixin Policy; // can't 
    1919  
    19201966    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    19211967    // Internal stuffs 
    19221968    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    19231969 
    19241970    enum CONSTRUCTOR_NAME = "__ctor"; 
    1925     enum WITH_BASE_CLASS  = __traits(compiles, Policy.BASE_CLASS_ID); 
     1971 
     1972    // true if functions are derived from a base class 
     1973    enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID"); 
     1974 
     1975    // true if functions are specified as types, not symbols 
     1976    enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL"); 
     1977 
     1978    // preferred identifier for i-th parameter variable 
     1979    static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID")) 
     1980    { 
     1981        alias Policy.PARAMETER_VARIABLE_ID PARAMETER_VARIABLE_ID; 
     1982    } 
     1983    else 
     1984    { 
     1985        template PARAMETER_VARIABLE_ID(size_t i) 
     1986        { 
     1987            enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i); 
     1988                // default: a0, a1, ... 
     1989        } 
     1990    } 
    19261991 
    19271992    // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach. 
    19281993    template CountUp(size_t n) 
    19291994    { 
    19301995        static if (n > 0) 
    19311996            alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp; 
    19321997        else 
    19331998            alias TypeTuple!() CountUp; 
    19341999    } 
    19352000 
     
    19692034 
    19702035    // handle each overload set 
    19712036    private string generateCodeForOverloadSet(alias oset)() @property 
    19722037    { 
    19732038        string code = ""; 
    19742039 
    19752040        foreach (i_; CountUp!(0 + oset.contents.length)) // workaround 
    19762041        { 
    19772042            enum i = 0 + i_; // workaround 
    19782043            code ~= generateFunction!( 
    1979                     oset.contents[i], Policy.FUNCINFO_ID!(oset.name, i)) ~ "\n"; 
     2044                    Policy.FUNCINFO_ID!(oset.name, i), oset.name, 
     2045                    oset.contents[i]) ~ "\n"; 
    19802046        } 
    19812047        return code; 
    19822048    } 
    19832049 
    19842050    /* 
    19852051     * Returns D code which implements the function func.  This function 
    19862052     * actually generates only the declarator part; the function body part is 
    19872053     * generated by the functionGenerator() policy. 
    19882054     */ 
    1989     //private string generateFunction(alias func, string myFuncInfo)() @property 
    1990     private string generateFunction(args_.../+[BUG 4217]+/)() @property 
    1991     { 
    1992         alias args_[0..1] func; enum myFuncInfo = args_[1]; 
    1993  
    1994         enum name   = __traits(identifier, func); 
     2055    public string generateFunction( 
     2056            string myFuncInfo, string name, func... )() @property 
     2057    { 
    19952058        enum isCtor = (name == CONSTRUCTOR_NAME); 
    19962059 
    19972060        string code; // the result 
    19982061 
    19992062        /*** Function Declarator ***/ 
    20002063        { 
     2064            alias FunctionTypeOf!(func) Func; 
    20012065            alias FunctionAttribute FA; 
    20022066            enum atts     = functionAttributes!(func); 
    20032067            enum realName = isCtor ? "this" : name; 
    20042068 
    2005             /* Just for the sake of Format!(...). */ 
     2069            /* Made them CTFE funcs just for the sake of Format!(...) */ 
     2070 
     2071            // return type with optional "ref" 
     2072            static string make_returnType() 
     2073            { 
     2074                string rtype = ""; 
     2075 
     2076                if (!isCtor) 
     2077                { 
     2078                    if (atts & FA.REF) rtype ~= "ref "; 
     2079                    rtype ~= myFuncInfo ~ ".RT"; 
     2080                } 
     2081                return rtype; 
     2082            } 
     2083            enum returnType = make_returnType(); 
     2084 
     2085            // function attributes attached after declaration 
    20062086            static string make_postAtts() 
    20072087            { 
    20082088                string poatts = ""; 
    20092089                if (atts & FA.PURE    ) poatts ~= " pure"; 
    20102090                if (atts & FA.NOTHROW ) poatts ~= " nothrow"; 
    20112091                if (atts & FA.PROPERTY) poatts ~= " @property"; 
    20122092                if (atts & FA.SAFE    ) poatts ~= " @safe"; 
    20132093                if (atts & FA.TRUSTED ) poatts ~= " @trusted"; 
    20142094                return poatts; 
    20152095            } 
    20162096            enum postAtts = make_postAtts(); 
    20172097 
    2018             static string make_returnType() 
     2098            // function storage class 
     2099            static string make_storageClass() 
    20192100            { 
    2020                 string rtype = ""; 
    2021  
    2022                 if (!isCtor) 
    2023                 { 
    2024                     if (atts & FA.REF) rtype ~= "ret "; 
    2025                     rtype ~= myFuncInfo ~ ".RT"; 
    2026                 } 
    2027                 return rtype; 
     2101                string postc = ""; 
     2102                if (is(Func ==    shared)) postc ~= " shared"; 
     2103                if (is(Func ==     const)) postc ~= " const"; 
     2104                if (is(Func == immutable)) postc ~= " immutable"; 
     2105                return postc; 
    20282106            } 
    2029             enum returnType = make_returnType(); 
     2107            enum storageClass = make_storageClass(); 
    20302108 
    20312109            // 
    2032             code ~= Format!("extern(%s) %s %s(%s) %s\n", 
     2110            code ~= Format!("extern(%s) %s %s(%s) %s %s\n", 
    20332111                    functionLinkage!(func), 
    20342112                    returnType, 
    20352113                    realName, 
    2036                     ""~generateParameters!(func, myFuncInfo), 
    2037                     postAtts ); 
     2114                    ""~generateParameters!(myFuncInfo, func), 
     2115                    postAtts, storageClass ); 
    20382116        } 
    20392117 
    20402118        /*** Function Body ***/ 
    20412119        code ~= "{\n"; 
    20422120        { 
    20432121            enum nparams = ParameterTypeTuple!(func).length; 
    20442122 
    20452123            /* Declare keywords: args, self and parent. */ 
    20462124            string preamble; 
    20472125 
    20482126            preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n"; 
    20492127            if (!isCtor) 
    20502128            { 
    20512129                preamble ~= "alias " ~ name ~ " self;\n"; 
    20522130                if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func)) 
    20532131                    //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540] 
    20542132                    preamble ~= "auto parent = &super." ~ name ~ ";\n"; 
    20552133            } 
    20562134 
    2057             // 
     2135            // Function body 
     2136            static if (WITHOUT_SYMBOL) 
     2137                enum fbody = Policy.generateFunctionBody!(name, func); 
     2138            else 
     2139                enum fbody = Policy.generateFunctionBody!(func); 
     2140 
    20582141            code ~= preamble; 
    2059             code ~= Policy.generateFunctionBody!(func)
     2142            code ~= fbody
    20602143        } 
    20612144        code ~= "}"; 
    20622145 
    20632146        return code; 
    20642147    } 
    20652148 
    20662149    /* 
    20672150     * Returns D code which declares function parameters. 
    20682151     * "ref int a0, real a1, ..." 
    20692152     */ 
    2070     //private string generateParameters(alias func, string myFuncInfo)() @property 
    2071     private string generateParameters(args_.../+[BUG 4217]+/)() @property 
    2072     { 
    2073         alias args_[0..1] func; enum myFuncInfo = args_[1]; 
    2074  
     2153    private string generateParameters(string myFuncInfo, func...)() @property 
     2154    { 
    20752155        alias ParameterStorageClass STC; 
    20762156        alias ParameterStorageClassTuple!(func) stcs; 
    20772157        enum nparams = stcs.length; 
    20782158 
    20792159        string params = ""; // the result 
    20802160 
    20812161        foreach (i, stc; stcs) 
    20822162        { 
    20832163            if (i > 0) params ~= ", "; 
    20842164 
    20852165            // Parameter storage classes. 
    20862166            if (stc & STC.SCOPE) params ~= "scope "; 
    20872167            if (stc & STC.OUT  ) params ~= "out "; 
    20882168            if (stc & STC.REF  ) params ~= "ref "; 
    20892169            if (stc & STC.LAZY ) params ~= "lazy "; 
    20902170 
    20912171            // Take parameter type from the FuncInfo. 
    20922172            params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]"; 
    20932173 
    20942174            // Declare a parameter variable. 
    2095             params ~= " " ~ Policy.PARAMETER_VARIABLE_ID!(i); 
     2175            params ~= " " ~ PARAMETER_VARIABLE_ID!(i); 
    20962176        } 
    20972177 
    20982178        // Add some ellipsis part if needed. 
    20992179        final switch (variadicFunctionStyle!(func)) 
    21002180        { 
    21012181            case Variadic.NO: 
    21022182                break; 
    21032183 
    21042184            case Variadic.C, Variadic.D: 
    21052185                // (...) or (a, b, ...) 
     
    21172197    // Returns D code which enumerates n parameter variables using comma as the 
    21182198    // separator.  "a0, a1, a2, a3" 
    21192199    private string enumerateParameters(size_t n)() @property 
    21202200    { 
    21212201        string params = ""; 
    21222202 
    21232203        foreach (i_; CountUp!(n)) 
    21242204        { 
    21252205            enum i = 0 + i_; // workaround 
    21262206            if (i > 0) params ~= ", "; 
    2127             params ~= Policy.PARAMETER_VARIABLE_ID!(i); 
     2207            params ~= PARAMETER_VARIABLE_ID!(i); 
    21282208        } 
    21292209        return params; 
    21302210    } 
    21312211} 
    21322212 
    21332213 
    21342214/** 
    21352215Predefined how-policies for $(D AutoImplement).  These templates are used by 
    21362216$(D BlackHole) and $(D WhiteHole), respectively. 
    21372217 */