root/trunk/meta/demangle.d

Revision 258, 23.9 kB (checked in by Don Clugston, 8 years ago)

For DMD 0.166 -- now demangles lazy parameters and lazy variadics.

Line 
1 /**
2  *   Demangle a ".mangleof" name at compile time.
3  *
4  */
5
6 module meta.demangle;
7 private import meta.ctype;
8 /*
9  Implementation is via pairs of metafunctions:
10  a 'demangle' metafunction, which returns a const char [],
11  and a 'Consumed' metafunction, which returns an integer, the number of characters which
12  are used.
13 */
14
15 /*****************************************
16  * How should the name be displayed?
17  */
18 enum MangledNameType
19 {
20     PrettyName,    // With full type information
21     QualifiedName, // No type information, just identifiers seperated by dots
22     SymbolName     // Only the ultimate identifier
23 }
24
25 /*****************************************
26  * Pretty-prints a mangled type string.
27  */
28 template demangleType(char[] str, MangledNameType wantQualifiedNames = MangledNameType.PrettyName)
29 {
30     static if (wantQualifiedNames != MangledNameType.PrettyName) {
31         // There are only a few types where symbolnameof!(), qualifiednameof!()
32         // make sense.
33         static if (str[0]=='C' || str[0]=='S' || str[0]=='E' || str[0]=='T')
34             const char [] demangleType = prettyLname!(str[1..$], wantQualifiedNames);
35         else {
36             static assert(0, "Demangle error: type '" ~ str ~ "' does not contain a qualified name");
37         }
38     } else static if (str[0] == 'A') // dynamic array
39         const char [] demangleType = demangleType!(str[1..$], wantQualifiedNames) ~ "[]";
40     else static if (str[0] == 'H')   // associative array
41         const char [] demangleType
42             = demangleType!(str[1+demangleTypeConsumed!(str[1..$])..$], wantQualifiedNames)
43             ~ "[" ~ demangleType!(str[1..1+(demangleTypeConsumed!(str[1..$]))], wantQualifiedNames) ~ "]";
44     else static if (str[0] == 'G') // static array
45         const char [] demangleType
46             = demangleType!(str[1+countLeadingDigits!(str[1..$])..$], wantQualifiedNames)
47             ~ "[" ~ str[1..1+countLeadingDigits!(str[1..$]) ] ~ "]";
48     else static if (str[0]=='C')
49         const char [] demangleType = "class " ~ prettyLname!(str[1..$], wantQualifiedNames);
50     else static if (str[0]=='S')
51         const char [] demangleType = "struct " ~ prettyLname!(str[1..$], wantQualifiedNames);
52     else static if (str[0]=='E')
53         const char [] demangleType = "enum " ~ prettyLname!(str[1..$], wantQualifiedNames);
54     else static if (str[0]=='T')
55         const char [] demangleType = "typedef " ~ prettyLname!(str[1..$], wantQualifiedNames);
56     else static if (str[0]=='D' && str.length>2 && isMangledFunction!(( str[1] )) ) // delegate
57         const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "delegate ", wantQualifiedNames);
58     else static if (str[0]=='P' && str.length>2 && isMangledFunction!(( str[1] )) ) // function pointer
59         const char [] demangleType = demangleFunctionOrDelegate!(str[1..$], "function ", wantQualifiedNames);
60     else static if (str[0]=='P') // only after we've dealt with function pointers
61         const char [] demangleType = demangleType!(str[1..$], wantQualifiedNames) ~ "*";
62     else static if (str[0]=='F')
63         const char [] demangleType = demangleFunctionOrDelegate!(str, "", wantQualifiedNames);
64     else const char [] demangleType = demangleBasicType!(str);
65 }
66
67 // split these off because they're numerous and simple
68 // Note: For portability, could replace "v" with void.mangleof, etc.
69 template demangleBasicType(char [] str)
70 {
71          static if (str == "v") const char [] demangleBasicType = "void";
72     else static if (str == "b") const char [] demangleBasicType = "bool";
73     // possibly a bug in the D name mangling algorithm?
74     else static if (str == "x") const char [] demangleBasicType = "bool";
75
76     // integral types
77     else static if (str == "g") const char [] demangleBasicType = "byte";
78     else static if (str == "h") const char [] demangleBasicType = "ubyte";
79     else static if (str == "s") const char [] demangleBasicType = "short";
80     else static if (str == "t") const char [] demangleBasicType = "ushort";
81     else static if (str == "i") const char [] demangleBasicType = "int";
82     else static if (str == "k") const char [] demangleBasicType = "uint";
83     else static if (str == "l") const char [] demangleBasicType = "long";
84     else static if (str == "m") const char [] demangleBasicType = "ulong";
85     // floating point
86     else static if (str == "e") const char [] demangleBasicType = "real";
87     else static if (str == "d") const char [] demangleBasicType = "double";
88     else static if (str == "f") const char [] demangleBasicType = "float";
89
90     else static if (str == "j") const char [] demangleBasicType = "ireal";
91     else static if (str == "p") const char [] demangleBasicType = "idouble";
92     else static if (str == "o") const char [] demangleBasicType = "ifloat";
93
94     else static if (str == "c") const char [] demangleBasicType = "creal";
95     else static if (str == "r") const char [] demangleBasicType = "cdouble";
96     else static if (str == "q") const char [] demangleBasicType = "cfloat";
97     // Char types
98     else static if (str == "a") const char [] demangleBasicType = "char";
99     else static if (str == "u") const char [] demangleBasicType = "wchar";
100     else static if (str == "w") const char [] demangleBasicType = "dchar";
101
102     else static assert(0, "Demangle Error: '" ~ str ~ "' is not a recognised basic type");
103 }
104
105 template demangleTypeConsumed(char [] str)
106 {
107     static if (str[0]=='A')
108         const int demangleTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]);
109     else static if (str[0]=='H')
110         const int demangleTypeConsumed = 1 + demangleTypeConsumed!(str[1..$])
111             + demangleTypeConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]);
112     else static if (str[0]=='G')
113         const int demangleTypeConsumed = 1 + countLeadingDigits!(str[1..$])
114             + demangleTypeConsumed!( str[1+countLeadingDigits!(str[1..$])..$] );
115     else static if (str.length>2 && (str[0]=='P' || str[0]=='D') && isMangledFunction!(( str[1] )) )
116         const int demangleTypeConsumed = 2 + demangleParamListAndRetValConsumed!(str[2..$]);
117     else static if (str[0]=='P') // only after we've dealt with function pointers
118         const int demangleTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]);
119     else static if (str[0]=='C' || str[0]=='S' || str[0]=='E' || str[0]=='T')
120         const int demangleTypeConsumed = 1 + getQualifiedNameConsumed!(str[1..$]);
121     else static if (str[0]=='F' && str.length>1)
122         const int demangleTypeConsumed = 1 + demangleParamListAndRetValConsumed!(str[1..$]);
123     else // it's a Basic Type
124         const int demangleTypeConsumed = 1;
125 }
126
127 // --------------------------------------------
128 //              STATIC ARRAYS
129
130 // For static arrays, count number of digits used (eg, return 3 for "674")
131 template countLeadingDigits(char [] str)
132 {
133     static if (str.length>0 && isdigit!( (str[0]) ))
134         const int countLeadingDigits = 1 + countLeadingDigits!( str[1..$]);
135     else const int countLeadingDigits = 0;
136 }
137
138 // --------------------------------------------
139 //              LNAMES
140
141 // str must start with an Lname: first chars give the length
142 // reads the digits from the front of str, gets the Lname
143 // Sometimes the characters following the length are also digits!
144 // (this happens with templates, when the name being 'lengthed' is itself an Lname).
145 // We guard against this by ensuring that the L is less than the length of the string.
146 template getLname(char [] str)
147 {
148     static if (str.length <= 9+1 || !isdigit!( (str[1]) ) )
149         const char [] getLname = str[1..(str[0]-'0' + 1)];
150     else static if (str.length <= 99+2 || !isdigit!( (str[2]) ))
151         const char [] getLname = str[2..((str[0]-'0')*10 + str[1]-'0'+ 2)];
152     else static if (str.length <= 999+3 || !isdigit!( (str[3]) ))
153         const char [] getLname =
154             str[3..((str[0]-'0')*100 + (str[1]-'0')*10 + str[2]-'0' + 3)];
155     else
156         const char [] getLname =
157             str[4..((str[0]-'0')*1000 + (str[1]-'0')*100 + (str[2]-'0')*10 + (str[3]-'0') + 4)];
158 }
159
160 // Deal with the case where an Lname contains an embedded "__D".
161 // This can happen when classes, typedefs, etc are declared inside a function.
162 template pretty_Dname(char [] str, int dotnameconsumed, MangledNameType wantQualifiedNames)
163 {
164     static if ( isMangledFunction!( (str[2+dotnameconsumed]))) {
165         const char [] pretty_Dname = pretty_Dfunction!(str, dotnameconsumed,
166             demangleParamListAndRetValConsumed!(str[3+dotnameconsumed..$]), wantQualifiedNames);
167     } else {
168         static if (wantQualifiedNames == MangledNameType.PrettyName) {
169             const char [] pretty_Dname =
170                 demangleType!(str[2+dotnameconsumed..$], wantQualifiedNames)
171                 ~ " " ~ getQualifiedName!(str[2..$], wantQualifiedNames);
172         } else {
173             const char [] pretty_Dname = getQualifiedName!(str[2..$], wantQualifiedNames);
174         }
175     }
176 }
177
178 // Deal with the case where an Lname contains an embedded ("__D") function.
179 // Split into a seperate function because it's so complicated.
180 template pretty_Dfunction(char [] str, int dotnameconsumed, int paramlistconsumed,
181     MangledNameType wantQualifiedNames)
182 {
183     static if (wantQualifiedNames == MangledNameType.PrettyName) {
184         const char [] pretty_Dfunction =
185             demangleFunctionOrDelegate!(str[2 + dotnameconsumed .. 3 + dotnameconsumed + paramlistconsumed],
186                 getQualifiedName!(str[2..2+dotnameconsumed], wantQualifiedNames), wantQualifiedNames)
187                 // BUG: This shouldn't be necessary, the string length is wrong somewhere
188             ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, ".");
189     } else static if (wantQualifiedNames == MangledNameType.QualifiedName) {
190         // Qualified name
191         const char [] pretty_Dfunction = getQualifiedName!(str[2..2+dotnameconsumed], wantQualifiedNames)
192             ~ getQualifiedName!(str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames, ".");
193     } else { // symbol name
194         static if (3 + dotnameconsumed + paramlistconsumed == str.length)
195             const char [] pretty_Dfunction = getQualifiedName!(str[2..2+dotnameconsumed], wantQualifiedNames);
196         else const char [] pretty_Dfunction = getQualifiedName!(
197             str[3 + dotnameconsumed + paramlistconsumed .. $], wantQualifiedNames);
198     }
199  }
200
201 // for an Lname that begins with "_D"
202 template get_DnameConsumed(char [] str)
203 {
204     const int get_DnameConsumed = 2 + getQualifiedNameConsumed!(str[2..$])
205         + demangleTypeConsumed!(str[2+getQualifedNameConsumed!(str[2..$])..$]);
206 }
207
208 // If Lname is a template, shows it as a template
209 template prettyLname(char [] str, MangledNameType wantQualifiedNames)
210 {
211     static if (str.length>3 && str[0..3] == "__T") // Template instance name
212         static if (wantQualifiedNames == MangledNameType.PrettyName) {
213             const char [] prettyLname =
214                 prettyLname!(str[3..$], wantQualifiedNames) ~ "!("
215                 ~ prettyTemplateArgList!(str[3+getQualifiedNameConsumed!(str[3..$])..$], wantQualifiedNames)
216                 ~ ")";
217         } else {
218             const char [] prettyLname =
219                 prettyLname!(str[3..$], wantQualifiedNames);
220         }
221     else static if (str.length>2 && str[0..2] == "_D") {
222         const char [] prettyLname = pretty_Dname!(str, getQualifiedNameConsumed!(str[2..$]), wantQualifiedNames);
223     } else static if ( isdigit!( (str[0]) ) )
224         const char [] prettyLname = getQualifiedName!(str[0..getQualifiedNameConsumed!(str)], wantQualifiedNames);
225     else const char [] prettyLname = str;
226 }
227
228 // str must start with an lname: first chars give the length
229 // how many chars are taken up with length digits + the name itself
230 template getLnameConsumed(char [] str)
231 {
232     static if (str.length==0)
233         const int getLnameConsumed=0;
234     else static if (str.length <= (9+1) || !isdigit!( (str[1]) ) )
235         const int getLnameConsumed = 1 + str[0]-'0';
236     else static if (str.length <= (99+2) || !isdigit!( (str[2]) ))
237         const int getLnameConsumed = (str[0]-'0')*10 + str[1]-'0' + 2;
238     else static if (str.length <= (999+3) || !isdigit!( (str[3]) ))
239         const int getLnameConsumed = (str[0]-'0')*100 + (str[1]-'0')*10 + str[2]-'0' + 3;
240     else
241         const int getLnameConsumed = (str[0]-'0')*1000 + (str[1]-'0')*100 + (str[2]-'0')*10 + (str[3]-'0') + 4;
242 }
243
244 template getQualifiedName(char [] str, MangledNameType wantQualifiedNames, char [] dotstr = "")
245 {
246     static if (str.length==0) const char [] getQualifiedName="";
247 //    else static if (str.length>2 && str[0]=='_' && str[1]=='D')
248 //        const char [] getDotName = getQualifiedName!(str[2..$], wantQualifiedNames);
249     else {
250         static assert (isdigit!(( str[0] )));
251         static if ( getLnameConsumed!(str) < str.length && isdigit!(( str[getLnameConsumed!(str)] ))) {
252             static if (wantQualifiedNames == MangledNameType.SymbolName) {
253                 // For symbol names, only display the last symbol
254                 const char [] getQualifiedName =
255                     getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, "");
256             } else {
257                 // Qualified and pretty names display everything
258                 const char [] getQualifiedName = dotstr
259                     ~ prettyLname!(getLname!(str), wantQualifiedNames)
260                     ~ getQualifiedName!(str[getLnameConsumed!(str) .. $], wantQualifiedNames, ".");
261             }
262         } else {
263             const char [] getQualifiedName = dotstr ~ prettyLname!(getLname!(str), wantQualifiedNames);
264         }
265     }
266 }
267
268 template getQualifiedNameConsumed (char [] str)
269 {
270     static if (str.length>1 &&  isdigit!(( str[0] )) ) {
271         static if (getLnameConsumed!(str) < str.length && isdigit!(( str[getLnameConsumed!(str)] ))) {
272             const int getQualifiedNameConsumed = getLnameConsumed!(str)
273                 + getQualifiedNameConsumed!(str[getLnameConsumed!(str) .. $]);
274         } else {
275             const int getQualifiedNameConsumed = getLnameConsumed!(str);
276         }
277     } /*else static if (str.length>1 && str[0]=='_' && str[1]=='D') {
278         const int getQualifiedNameConsumed = get_DnameConsumed!(str)
279             + getQualifiedNameConsumed!(str[1+get_DnameConsumed!(str)..$]);
280     }*/ else static assert(0);
281 }
282
283 // ----------------------------------------
284 //              FUNCTIONS
285
286 /* str[0] must indicate the extern linkage of the function. funcOrDelegStr is the name of the function,
287 * or "function " or "delegate "
288 */
289 template demangleFunctionOrDelegate(char [] str, char [] funcOrDelegStr, MangledNameType wantQualifiedNames)
290 {
291     const char [] demangleFunctionOrDelegate = demangleExtern!(( str[0] ))
292         ~ demangleReturnValue!(str[1..$], wantQualifiedNames)
293         ~ " " ~ funcOrDelegStr ~ "("
294         ~ demangleParamList!(str[1..1+demangleParamListAndRetValConsumed!(str[1..$])], wantQualifiedNames)
295         ~ ")";
296 }
297
298 // Special case: types that are in function parameters
299 // For function parameters, the type can also contain 'lazy', 'out' or 'inout'.
300 template demangleFunctionParamType(char[] str, MangledNameType wantQualifiedNames)
301 {
302     static if (str[0]=='L')
303         const char [] demangleFunctionParamType = "lazy " ~ demangleType!(str[1..$], wantQualifiedNames);
304     else static if (str[0]=='K')
305         const char [] demangleFunctionParamType = "inout " ~ demangleType!(str[1..$], wantQualifiedNames);
306     else static if (str[0]=='J')
307         const char [] demangleFunctionParamType = "out " ~ demangleType!(str[1..$], wantQualifiedNames);
308     else const char [] demangleFunctionParamType = demangleType!(str, wantQualifiedNames);
309 }
310
311 // Deal with 'out' and 'inout' parameters
312 template demangleFunctionParamTypeConsumed(char[] str)
313 {
314     static if (str[0]=='K' || str[0]=='J' || str[0]=='L')
315         const int demangleFunctionParamTypeConsumed = 1 + demangleTypeConsumed!(str[1..$]);
316     else const int demangleFunctionParamTypeConsumed = demangleTypeConsumed!(str);
317 }
318
319 // Return true if c indicates a function. As well as 'F', it can be extern(Pascal), (C), (C++) or (Windows).
320 template isMangledFunction(char c)
321 {
322     const bool isMangledFunction = (c=='F' || c=='U' || c=='W' || c=='V' || c=='R');
323 }
324
325 template demangleExtern(char c)
326 {
327     static if (c=='F') const char [] demangleExtern = "";
328     else static if (c=='U') const char [] demangleExtern = "extern (C) ";
329     else static if (c=='W') const char [] demangleExtern = "extern (Windows) ";
330     else static if (c=='V') const char [] demangleExtern = "extern (Pascal) ";
331     else static if (c=='R') const char [] demangleExtern = "extern (C++) ";
332     else static assert(0, "Unrecognized extern function.");
333 }
334
335 // Skip through the string until we find the return value. It can either be Z for normal
336 // functions, or Y for vararg functions.
337 template demangleReturnValue(char [] str, MangledNameType wantQualifiedNames)
338 {
339     static assert(str.length>=1, "Demangle error(Function): No return value found");
340     static if (str[0]=='Z' || str[0]=='Y' || str[0]=='X')
341         const char[] demangleReturnValue = demangleType!(str[1..$], wantQualifiedNames);
342     else const char [] demangleReturnValue = demangleReturnValue!(str[demangleFunctionParamTypeConsumed!(str)..$], wantQualifiedNames);
343 }
344
345 // Stop when we get to the return value
346 template demangleParamList(char [] str, MangledNameType wantQualifiedNames, char[] commastr = "")
347 {
348     static if (str[0] == 'Z')
349         const char [] demangleParamList = "";
350     else static if (str[0] == 'Y')
351         const char [] demangleParamList = commastr ~ "...";
352     else static if (str[0]=='X') // lazy ...
353         const char[] demangleParamList = commastr ~ "...";
354     else
355         const char [] demangleParamList =  commastr ~
356             demangleFunctionParamType!(str[0..demangleFunctionParamTypeConsumed!(str)], wantQualifiedNames)
357             ~ demangleParamList!(str[demangleFunctionParamTypeConsumed!(str)..$], wantQualifiedNames, ", ");
358 }
359
360 // How many characters are used in the parameter list and return value
361 template demangleParamListAndRetValConsumed(char [] str)
362 {
363     static assert (str.length>0, "Demangle error(ParamList): No return value found");
364     static if (str[0]=='Z' || str[0]=='Y' || str[0]=='X')
365         const int demangleParamListAndRetValConsumed = 1 + demangleTypeConsumed!(str[1..$]);
366     else {
367         const int demangleParamListAndRetValConsumed = demangleFunctionParamTypeConsumed!(str)
368             + demangleParamListAndRetValConsumed!(str[demangleFunctionParamTypeConsumed!(str)..$]);
369     }
370 }
371
372 // --------------------------------------------
373 //              TEMPLATES
374
375 template templateValueArgConsumed(char [] str)
376 {
377     static if (str[0]=='n') const int templateValueArgConsumed = 1;
378     else static if (isdigit!( (str[0]) )) const int templateValueArgConsumed = countLeadingDigits!(str);
379     else static if (str[0]=='N') const int templateValueArgConsumed = 1 + countLeadingDigits!(str[1..$]);
380     else static if (str[0]=='e') const int templateValueArgConsumed = 1 + 20;
381     else static if (str[0]=='c') const int templateValueArgConsumed = 1 + 40;
382     else static assert(0, "Unknown character in template value argument");
383 }
384
385 // pretty-print a template value argument.
386 template prettyValueArg(char [] str)
387 {
388     static if (str[0]=='n') const char [] prettyValueArg = "null";
389     else static if (isdigit!( (str[0]) )) const char [] prettyValueArg = str;
390     else static if ( str[0]=='N') const char [] prettyValueArg = "-" ~ str[1..$];
391     else static if ( str[0]=='e') const char [] prettyValueArg = "0x" ~ str[1..$];
392     else static if ( str[0]=='c') const char [] prettyValueArg = "0x" ~ str[1..22] ~ " + 0x" ~ str[21..41] ~ "i";
393     else const char [] prettyValueArg = "Value arg {" ~ str[0..$] ~ "}";
394 }
395
396 // Pretty-print a template argument
397 template prettyTemplateArg(char [] str, MangledNameType wantQualifiedNames)
398 {
399     static if (str[0]=='S') // symbol name
400         const char [] prettyTemplateArg = prettyLname!(str[1..$], wantQualifiedNames);
401     else static if (str[0]=='V') // value
402         const char [] prettyTemplateArg =
403             demangleType!(str[1..1+demangleTypeConsumed!(str[1..$])], wantQualifiedNames)
404             ~ " = " ~ prettyValueArg!(str[1+demangleTypeConsumed!(str[1..$])..$]);
405     else static if (str[0]=='T') // type
406         const char [] prettyTemplateArg = demangleType!(str[1..$], wantQualifiedNames);
407     else static assert(0, "Unrecognised template argument type: {" ~ str ~ "}");
408 }
409
410 template templateArgConsumed(char [] str)
411 {
412     static if (str[0]=='S') // symbol name
413         const int templateArgConsumed = 1 + getLnameConsumed!(str[1..$]);
414     else static if (str[0]=='V') // value
415         const int templateArgConsumed = 1 + demangleTypeConsumed!(str[1..$]) +
416             templateValueArgConsumed!(str[1+demangleTypeConsumed!(str[1..$])..$]);
417     else static if (str[0]=='T') // type
418         const int templateArgConsumed = 1 + demangleTypeConsumed!(str[1..$]);
419     else static assert(0, "Unrecognised template argument type: {" ~ str ~ "}");
420 }
421
422 // Like function parameter lists, template parameter lists also end in a Z,
423 // but they don't have a return value at the end.
424 template prettyTemplateArgList(char [] str, MangledNameType wantQualifiedNames, char [] commastr="")
425 {
426     static if (str[0]=='Z')
427         const char[] prettyTemplateArgList = "";
428     else
429        const char [] prettyTemplateArgList = commastr
430             ~ prettyTemplateArg!(str[0..templateArgConsumed!(str)], wantQualifiedNames)
431             ~ prettyTemplateArgList!(str[templateArgConsumed!(str)..$], wantQualifiedNames, ", ");
432 }
433
434 template templateArgListConsumed(char [] str)
435 {
436     static assert(str.length>0, "No Z found at end of template argument list");
437     static if (str[0]=='Z')
438         const int templateArgListConsumed = 1;
439     else
440         const int templateArgListConsumed = templateArgConsumed!(str)
441             + templateArgListConsumed!(str[templateArgConsumed!(str)..$]);
442 }
443
444
445
446 // --------------------------------------------
447 //              UNIT TESTS
448
449 version(testmeta){
450 private {
451
452 const char [] THISFILE = "meta.demangle";
453
454 ireal SomeFunc(ushort u) { return -3i; }
455 idouble SomeFunc2(inout ushort u, ubyte w) { return -3i; }
456 byte[] SomeFunc3(out dchar d, ...) { return null; }
457 ifloat SomeFunc4(lazy void[] x...) { return 2i; }
458 char[dchar] SomeFunc5(lazy int delegate()[] z...);
459
460 extern (Windows) {
461     typedef void function (double, long) WinFunc;
462 }
463 extern (Pascal) {
464     typedef short[wchar] delegate (bool, ...) PascFunc;
465 }
466 extern (C) {
467     typedef dchar delegate () CFunc;
468 }
469 extern (C++) {
470     typedef cfloat function (wchar) CPPFunc;
471 }
472
473 interface SomeInterface {}
474
475 static assert( demangleType!((&SomeFunc).mangleof) == "ireal function (ushort)" );
476 static assert( demangleType!((&SomeFunc2).mangleof) == "idouble function (inout ushort, ubyte)");
477 static assert( demangleType!((&SomeFunc3).mangleof) == "byte[] function (out dchar, ...)");
478 static assert( demangleType!((&SomeFunc4).mangleof) == "ifloat function (lazy void[], ...)");
479 static assert( demangleType!((&SomeFunc5).mangleof) == "char[dchar] function (lazy int delegate ()[], ...)");
480 static assert( demangleType!((WinFunc).mangleof)== "extern (Windows) void function (double, long)");
481 static assert( demangleType!((PascFunc).mangleof) == "extern (Pascal) short[wchar] delegate (bool, ...)");
482 static assert( demangleType!((CFunc).mangleof) == "extern (C) dchar delegate ()");
483 static assert( demangleType!((CPPFunc).mangleof) == "extern (C++) cfloat function (wchar)");
484 // Interfaces are mangled as classes
485 static assert( demangleType!(SomeInterface.mangleof) == "class " ~ THISFILE ~ ".SomeInterface");
486
487 template ComplexTemplate(real a, creal b)
488 {
489     class ComplexTemplate {}
490 }
491
492 static assert( demangleType!((ComplexTemplate!(1.23, 4.56+3.2i)).mangleof) == "class " ~ THISFILE ~ ".ComplexTemplate!(double = 0xa4703d0ad7a3709dff3f, cdouble = 0x85eb51b81e85eb910140c + 0xcdcccccccccccccc0040i).ComplexTemplate");
493
494 }
495 }
Note: See TracBrowser for help on using the browser.