root/trunk/src/cppmangle.c

Revision 762, 10.9 kB (checked in by walter, 2 years ago)

bugzilla 5148 Incorrect C++ mangling of multiple const char* parameters

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "mars.h"
14 #include "dsymbol.h"
15 #include "mtype.h"
16 #include "scope.h"
17 #include "init.h"
18 #include "expression.h"
19 #include "attrib.h"
20 #include "declaration.h"
21 #include "template.h"
22 #include "id.h"
23 #include "enum.h"
24 #include "import.h"
25 #include "aggregate.h"
26
27 #if CPP_MANGLE
28
29 /* Do mangling for C++ linkage.
30  * Follows Itanium C++ ABI 1.86
31  * No attempt is made to support mangling of templates, operator
32  * overloading, or special functions.
33  *
34  * So why don't we use the C++ ABI for D name mangling?
35  * Because D supports a lot of things (like modules) that the C++
36  * ABI has no concept of. These affect every D mangled name,
37  * so nothing would be compatible anyway.
38  */
39
40 struct CppMangleState
41 {
42     static Array components;
43
44     int substitute(OutBuffer *buf, void *p);
45     int exist(void *p);
46     void store(void *p);
47 };
48
49 Array CppMangleState::components;
50
51
52 void writeBase36(OutBuffer *buf, unsigned i)
53 {
54     if (i >= 36)
55     {
56         writeBase36(buf, i / 36);
57         i %= 36;
58     }
59     if (i < 10)
60         buf->writeByte(i + '0');
61     else if (i < 36)
62         buf->writeByte(i - 10 + 'A');
63     else
64         assert(0);
65 }
66
67 int CppMangleState::substitute(OutBuffer *buf, void *p)
68 {
69     for (size_t i = 0; i < components.dim; i++)
70     {
71         if (p == components.data[i])
72         {
73             /* Sequence is S_, S0_, .., S9_, SA_, ..., SZ_, S10_, ...
74              */
75             buf->writeByte('S');
76             if (i)
77                 writeBase36(buf, i - 1);
78             buf->writeByte('_');
79             return 1;
80         }
81     }
82     components.push(p);
83     return 0;
84 }
85
86 int CppMangleState::exist(void *p)
87 {
88     for (size_t i = 0; i < components.dim; i++)
89     {
90         if (p == components.data[i])
91         {
92             return 1;
93         }
94     }
95     return 0;
96 }
97
98 void CppMangleState::store(void *p)
99 {
100     components.push(p);
101 }
102
103 void source_name(OutBuffer *buf, Dsymbol *s)
104 {
105     char *name = s->ident->toChars();
106     buf->printf("%d%s", strlen(name), name);
107 }
108
109 void prefix_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
110 {
111     if (!cms->substitute(buf, s))
112     {
113         Dsymbol *p = s->toParent();
114         if (p && !p->isModule())
115         {
116             prefix_name(buf, cms, p);
117         }
118         source_name(buf, s);
119     }
120 }
121
122 void cpp_mangle_name(OutBuffer *buf, CppMangleState *cms, Dsymbol *s)
123 {
124     Dsymbol *p = s->toParent();
125     if (p && !p->isModule())
126     {
127         buf->writeByte('N');
128
129         FuncDeclaration *fd = s->isFuncDeclaration();
130         if (!fd)
131         {
132             s->error("C++ static variables not supported");
133         }
134         else
135         if (fd->isConst())
136             buf->writeByte('K');
137
138         prefix_name(buf, cms, p);
139         source_name(buf, s);
140
141         buf->writeByte('E');
142     }
143     else
144         source_name(buf, s);
145 }
146
147
148 char *cpp_mangle(Dsymbol *s)
149 {
150     /*
151      * <mangled-name> ::= _Z <encoding>
152      * <encoding> ::= <function name> <bare-function-type>
153      *         ::= <data name>
154      *         ::= <special-name>
155      */
156
157     CppMangleState cms;
158     memset(&cms, 0, sizeof(cms));
159     cms.components.setDim(0);
160
161     OutBuffer buf;
162 #if MACHOBJ
163     buf.writestring("__Z");
164 #else
165     buf.writestring("_Z");
166 #endif
167
168     cpp_mangle_name(&buf, &cms, s);
169
170     FuncDeclaration *fd = s->isFuncDeclaration();
171     if (fd)
172     {   // add <bare-function-type>
173         TypeFunction *tf = (TypeFunction *)fd->type;
174         assert(tf->ty == Tfunction);
175         Parameter::argsCppMangle(&buf, &cms, tf->parameters, tf->varargs);
176     }
177     buf.writeByte(0);
178     return (char *)buf.extractData();
179 }
180
181 /* ============= Type Encodings ============================================= */
182
183 void Type::toCppMangle(OutBuffer *buf, CppMangleState *cms)
184 {
185     /* Make this the 'vendor extended type' when there is no
186      * C++ analog.
187      * u <source-name>
188      */
189     if (!cms->substitute(buf, this))
190     {   assert(deco);
191         buf->printf("u%d%s", strlen(deco), deco);
192     }
193 }
194
195 void TypeBasic::toCppMangle(OutBuffer *buf, CppMangleState *cms)
196 {   char c;
197     char p = 0;
198
199     /* ABI spec says:
200      * v        void
201      * w        wchar_t
202      * b        bool
203      * c        char
204      * a        signed char
205      * h        unsigned char
206      * s        short
207      * t        unsigned short
208      * i        int
209      * j        unsigned int
210      * l        long
211      * m        unsigned long
212      * x        long long, __int64
213      * y        unsigned long long, __int64
214      * n        __int128
215      * o        unsigned __int128
216      * f        float
217      * d        double
218      * e        long double, __float80
219      * g        __float128
220      * z        ellipsis
221      * u <source-name>  # vendor extended type
222      */
223
224     switch (ty)
225     {
226         case Tvoid:     c = 'v';        break;
227         case Tint8:     c = 'a';        break;
228         case Tuns8:     c = 'h';        break;
229         case Tint16:    c = 's';        break;
230         case Tuns16:    c = 't';        break;
231         case Tint32:    c = 'i';        break;
232         case Tuns32:    c = 'j';        break;
233         case Tfloat32:  c = 'f';        break;
234         case Tint64:    c = 'x';        break;
235         case Tuns64:    c = 'y';        break;
236         case Tfloat64:  c = 'd';        break;
237         case Tfloat80:  c = 'e';        break;
238         case Tbool:     c = 'b';        break;
239         case Tchar:     c = 'c';        break;
240         case Twchar:    c = 't';        break;
241         case Tdchar:    c = 'w';        break;
242
243         case Timaginary32: p = 'G'; c = 'f';    break;
244         case Timaginary64: p = 'G'; c = 'd';    break;
245         case Timaginary80: p = 'G'; c = 'e';    break;
246         case Tcomplex32:   p = 'C'; c = 'f';    break;
247         case Tcomplex64:   p = 'C'; c = 'd';    break;
248         case Tcomplex80:   p = 'C'; c = 'e';    break;
249
250         default:        assert(0);
251     }
252     if (p || isConst())
253     {
254         if (cms->substitute(buf, this))
255             return;
256     }
257
258     if (isConst())
259         buf->writeByte('K');
260
261     if (p)
262         buf->writeByte(p);
263
264     buf->writeByte(c);
265 }
266
267
268 void TypeSArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
269 {
270     if (!cms->substitute(buf, this))
271     {   buf->printf("A%ju_", dim ? dim->toInteger() : 0);
272         next->toCppMangle(buf, cms);
273     }
274 }
275
276 void TypeDArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
277 {
278     Type::toCppMangle(buf, cms);
279 }
280
281
282 void TypeAArray::toCppMangle(OutBuffer *buf, CppMangleState *cms)
283 {
284     Type::toCppMangle(buf, cms);
285 }
286
287
288 void TypePointer::toCppMangle(OutBuffer *buf, CppMangleState *cms)
289 {
290     if (!cms->exist(this))
291     {   buf->writeByte('P');
292         next->toCppMangle(buf, cms);
293         cms->store(this);
294     }
295     else
296         cms->substitute(buf, this);
297 }
298
299
300 void TypeReference::toCppMangle(OutBuffer *buf, CppMangleState *cms)
301 {
302     if (!cms->exist(this))
303     {   buf->writeByte('R');
304         next->toCppMangle(buf, cms);
305         cms->store(this);
306     }
307     else
308         cms->substitute(buf, this);
309 }
310
311
312 void TypeFunction::toCppMangle(OutBuffer *buf, CppMangleState *cms)
313 {   /*
314      *  <function-type> ::= F [Y] <bare-function-type> E
315      *  <bare-function-type> ::= <signature type>+
316      *  # types are possible return type, then parameter types
317      */
318
319     /* ABI says:
320         "The type of a non-static member function is considered to be different,
321         for the purposes of substitution, from the type of a namespace-scope or
322         static member function whose type appears similar. The types of two
323         non-static member functions are considered to be different, for the
324         purposes of substitution, if the functions are members of different
325         classes. In other words, for the purposes of substitution, the class of
326         which the function is a member is considered part of the type of
327         function."
328
329         BUG: Right now, types of functions are never merged, so our simplistic
330         component matcher always finds them to be different.
331         We should use Type::equals on these, and use different
332         TypeFunctions for non-static member functions, and non-static
333         member functions of different classes.
334      */
335     if (!cms->substitute(buf, this))
336     {
337         buf->writeByte('F');
338         if (linkage == LINKc)
339             buf->writeByte('Y');
340         next->toCppMangle(buf, cms);
341         Parameter::argsCppMangle(buf, cms, parameters, varargs);
342         buf->writeByte('E');
343     }
344 }
345
346
347 void TypeDelegate::toCppMangle(OutBuffer *buf, CppMangleState *cms)
348 {
349     Type::toCppMangle(buf, cms);
350 }
351
352
353 void TypeStruct::toCppMangle(OutBuffer *buf, CppMangleState *cms)
354 {
355     if (!cms->exist(this))
356     {
357         if (isConst())
358             buf->writeByte('K');
359
360         if (!cms->substitute(buf, sym))
361             cpp_mangle_name(buf, cms, sym);
362
363         if (isConst())
364             cms->store(this);
365     }
366     else
367         cms->substitute(buf, this);
368 }
369
370
371 void TypeEnum::toCppMangle(OutBuffer *buf, CppMangleState *cms)
372 {
373     if (!cms->exist(this))
374     {
375         if (isConst())
376             buf->writeByte('K');
377
378         if (!cms->substitute(buf, sym))
379             cpp_mangle_name(buf, cms, sym);
380
381         if (isConst())
382             cms->store(this);
383     }
384     else
385         cms->substitute(buf, this);
386 }
387
388
389 void TypeTypedef::toCppMangle(OutBuffer *buf, CppMangleState *cms)
390 {
391     Type::toCppMangle(buf, cms);
392 }
393
394
395 void TypeClass::toCppMangle(OutBuffer *buf, CppMangleState *cms)
396 {
397     if (!cms->substitute(buf, this))
398     {   buf->writeByte('P');
399         if (!cms->substitute(buf, sym))
400             cpp_mangle_name(buf, cms, sym);
401     }
402 }
403
404
405
406 void Parameter::argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs)
407 {   int n = 0;
408     if (arguments)
409     {
410         for (size_t i = 0; i < arguments->dim; i++)
411         {   Parameter *arg = (Parameter *)arguments->data[i];
412             Type *t = arg->type;
413             if (arg->storageClass & (STCout | STCref))
414                 t = t->referenceTo();
415             else if (arg->storageClass & STClazy)
416             {   // Mangle as delegate
417                 Type *td = new TypeFunction(NULL, t, 0, LINKd);
418                 td = new TypeDelegate(td);
419                 t = t->merge();
420             }
421             if (t->ty == Tsarray)
422             {   // Mangle static arrays as pointers
423                 t = t->pointerTo();
424             }
425
426             /* If it is a basic, enum or struct type,
427              * then don't mark it const
428              */
429             if ((t->ty == Tenum || t->ty == Tstruct || t->isTypeBasic()) && t->isConst())
430                 t->mutableOf()->toCppMangle(buf, cms);
431             else
432                 t->toCppMangle(buf, cms);
433
434             n++;
435         }
436     }
437     if (varargs)
438         buf->writestring("z");
439     else if (!n)
440         buf->writeByte('v');            // encode ( ) arguments
441 }
442
443
444 #endif
Note: See TracBrowser for help on using the browser.