comparison dmd2/attrib.c @ 1452:638d16625da2

LDC 2 compiles again.
author Robert Clipsham <robert@octarineparrot.com>
date Sat, 30 May 2009 17:23:32 +0100
parents 2667e3a145be
children 54b3c1394d62
comparison
equal deleted inserted replaced
1423:42bd767ec5a4 1452:638d16625da2
1 1
2 // Compiler implementation of the D programming language 2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars 3 // Copyright (c) 1999-2009 by Digital Mars
4 // All Rights Reserved 4 // All Rights Reserved
5 // written by Walter Bright 5 // written by Walter Bright
6 // http://www.digitalmars.com 6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License 7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt. 8 // in artistic.txt, or the GNU General Public License in gnu.txt.
10 10
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <assert.h> 13 #include <assert.h>
14 14
15 #if _WIN32 || IN_GCC || IN_LLVM 15 #include "rmem.h"
16 #include "mem.h"
17 #elif POSIX
18 #include "../root/mem.h"
19 #endif
20 16
21 #include "init.h" 17 #include "init.h"
22 #include "declaration.h" 18 #include "declaration.h"
23 #include "attrib.h" 19 #include "attrib.h"
24 #include "cond.h" 20 #include "cond.h"
29 #include "aggregate.h" 25 #include "aggregate.h"
30 #include "module.h" 26 #include "module.h"
31 #include "parse.h" 27 #include "parse.h"
32 #include "template.h" 28 #include "template.h"
33 29
30 #if IN_LLVM
34 #include "../gen/enums.h" 31 #include "../gen/enums.h"
35
36 32
37 #include "llvm/Support/CommandLine.h" 33 #include "llvm/Support/CommandLine.h"
38 34
39 static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore", 35 static llvm::cl::opt<bool> ignoreUnsupportedPragmas("ignore",
40 llvm::cl::desc("Ignore unsupported pragmas"), 36 llvm::cl::desc("Ignore unsupported pragmas"),
41 llvm::cl::ZeroOrMore); 37 llvm::cl::ZeroOrMore);
42 38
39 #endif
43 40
44 41
45 extern void obj_includelib(const char *name); 42 extern void obj_includelib(const char *name);
43
44 #if IN_DMD
46 void obj_startaddress(Symbol *s); 45 void obj_startaddress(Symbol *s);
46 #endif
47 47
48 48
49 /********************************* AttribDeclaration ****************************/ 49 /********************************* AttribDeclaration ****************************/
50 50
51 AttribDeclaration::AttribDeclaration(Array *decl) 51 AttribDeclaration::AttribDeclaration(Array *decl)
149 149
150 void AttribDeclaration::emitComment(Scope *sc) 150 void AttribDeclaration::emitComment(Scope *sc)
151 { 151 {
152 //printf("AttribDeclaration::emitComment(sc = %p)\n", sc); 152 //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
153 153
154 /* If generating doc comment, skip this because if we're inside 154 /* A general problem with this, illustrated by BUGZILLA 2516,
155 * a template, then include(NULL, NULL) will fail. 155 * is that attributes are not transmitted through to the underlying
156 * member declarations for template bodies, because semantic analysis
157 * is not done for template declaration bodies
158 * (only template instantiations).
159 * Hence, Ddoc omits attributes from template members.
156 */ 160 */
157 // if (sc->docbuf)
158 // return;
159 161
160 Array *d = include(NULL, NULL); 162 Array *d = include(NULL, NULL);
161 163
162 if (d) 164 if (d)
163 { 165 {
166 //printf("AttribDeclaration::emitComment %s\n", s->toChars()); 168 //printf("AttribDeclaration::emitComment %s\n", s->toChars());
167 s->emitComment(sc); 169 s->emitComment(sc);
168 } 170 }
169 } 171 }
170 } 172 }
173
174 #if IN_DMD
171 175
172 void AttribDeclaration::toObjFile(int multiobj) 176 void AttribDeclaration::toObjFile(int multiobj)
173 { 177 {
174 Array *d = include(NULL, NULL); 178 Array *d = include(NULL, NULL);
175 179
198 nwritten += n; 202 nwritten += n;
199 } 203 }
200 } 204 }
201 return nwritten; 205 return nwritten;
202 } 206 }
207 #endif
203 208
204 int AttribDeclaration::hasPointers() 209 int AttribDeclaration::hasPointers()
205 { 210 {
206 Array *d = include(NULL, NULL); 211 Array *d = include(NULL, NULL);
207 212
300 void StorageClassDeclaration::semantic(Scope *sc) 305 void StorageClassDeclaration::semantic(Scope *sc)
301 { 306 {
302 if (decl) 307 if (decl)
303 { unsigned stc_save = sc->stc; 308 { unsigned stc_save = sc->stc;
304 309
305 /* These sets of storage classes are mutually exclusive, 310 if (stc & (STCauto | STCscope | STCstatic | STCextern))
306 * so choose the innermost or most recent one. 311 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern);
307 */
308 if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
309 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
310 if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest))
311 sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest);
312 if (stc & (STCconst | STCinvariant | STCmanifest))
313 sc->stc &= ~(STCconst | STCinvariant | STCmanifest);
314 sc->stc |= stc; 312 sc->stc |= stc;
315 for (unsigned i = 0; i < decl->dim; i++) 313 for (unsigned i = 0; i < decl->dim; i++)
316 { 314 {
317 Dsymbol *s = (Dsymbol *)decl->data[i]; 315 Dsymbol *s = (Dsymbol *)decl->data[i];
318 316
322 } 320 }
323 else 321 else
324 sc->stc = stc; 322 sc->stc = stc;
325 } 323 }
326 324
327 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 325 void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, int stc)
328 { 326 {
329 struct SCstring 327 struct SCstring
330 { 328 {
331 int stc; 329 int stc;
332 enum TOK tok; 330 enum TOK tok;
337 { STCauto, TOKauto }, 335 { STCauto, TOKauto },
338 { STCscope, TOKscope }, 336 { STCscope, TOKscope },
339 { STCstatic, TOKstatic }, 337 { STCstatic, TOKstatic },
340 { STCextern, TOKextern }, 338 { STCextern, TOKextern },
341 { STCconst, TOKconst }, 339 { STCconst, TOKconst },
342 { STCinvariant, TOKimmutable }, 340 { STCimmutable, TOKimmutable },
343 { STCshared, TOKshared }, 341 { STCshared, TOKshared },
344 { STCfinal, TOKfinal }, 342 { STCfinal, TOKfinal },
345 { STCabstract, TOKabstract }, 343 { STCabstract, TOKabstract },
346 { STCsynchronized, TOKsynchronized }, 344 { STCsynchronized, TOKsynchronized },
347 { STCdeprecated, TOKdeprecated }, 345 { STCdeprecated, TOKdeprecated },
348 { STCoverride, TOKoverride }, 346 { STCoverride, TOKoverride },
349 { STCnothrow, TOKnothrow }, 347 { STCnothrow, TOKnothrow },
350 { STCpure, TOKpure }, 348 { STCpure, TOKpure },
351 { STCref, TOKref }, 349 { STCref, TOKref },
352 { STCtls, TOKtls }, 350 { STCtls, TOKtls },
351 { STCgshared, TOKgshared },
352 { STClazy, TOKlazy },
353 { STCalias, TOKalias },
354 { STCout, TOKout },
355 { STCin, TOKin },
353 }; 356 };
354 357
355 int written = 0;
356 for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) 358 for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
357 { 359 {
358 if (stc & table[i].stc) 360 if (stc & table[i].stc)
359 { 361 {
360 if (written)
361 buf->writeByte(' ');
362 written = 1;
363 buf->writestring(Token::toChars(table[i].tok)); 362 buf->writestring(Token::toChars(table[i].tok));
364 } 363 buf->writeByte(' ');
365 } 364 }
366 365 }
366 }
367
368 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
369 {
370 stcToCBuffer(buf, stc);
367 AttribDeclaration::toCBuffer(buf, hgs); 371 AttribDeclaration::toCBuffer(buf, hgs);
368 } 372 }
369 373
370 /********************************* LinkDeclaration ****************************/ 374 /********************************* LinkDeclaration ****************************/
371 375
436 case LINKc: p = "C"; break; 440 case LINKc: p = "C"; break;
437 case LINKcpp: p = "C++"; break; 441 case LINKcpp: p = "C++"; break;
438 case LINKwindows: p = "Windows"; break; 442 case LINKwindows: p = "Windows"; break;
439 case LINKpascal: p = "Pascal"; break; 443 case LINKpascal: p = "Pascal"; break;
440 444
441 // LDC 445 #if IN_LLVM
442 case LINKintrinsic: p = "Intrinsic"; break; 446 case LINKintrinsic: p = "Intrinsic"; break;
443 447 #endif
444 default: 448 default:
445 assert(0); 449 assert(0);
446 break; 450 break;
447 } 451 }
448 buf->writestring("extern ("); 452 buf->writestring("extern (");
540 // other alignments are simply ignored. my tests show this is what llvm-gcc does too ... 544 // other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
541 545
542 //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); 546 //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
543 if (decl) 547 if (decl)
544 { unsigned salign_save = sc->structalign; 548 { unsigned salign_save = sc->structalign;
545 549 #if IN_DMD
550 sc->structalign = salign;
551 #endif
546 for (unsigned i = 0; i < decl->dim; i++) 552 for (unsigned i = 0; i < decl->dim; i++)
547 { 553 {
548 Dsymbol *s = (Dsymbol *)decl->data[i]; 554 Dsymbol *s = (Dsymbol *)decl->data[i];
549 555
550 if (s->isStructDeclaration() && salign == 1) 556 if (s->isStructDeclaration() && salign == 1)
629 // printf("\tad = %p\n", ad); 635 // printf("\tad = %p\n", ad);
630 // printf("\taad = %p\n", &aad); 636 // printf("\taad = %p\n", &aad);
631 637
632 sc = sc->push(); 638 sc = sc->push();
633 sc->anonAgg = &aad; 639 sc->anonAgg = &aad;
634 sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls); 640 sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
635 sc->inunion = isunion; 641 sc->inunion = isunion;
636 sc->offset = 0; 642 sc->offset = 0;
637 sc->flags = 0; 643 sc->flags = 0;
638 aad.structalign = sc->structalign; 644 aad.structalign = sc->structalign;
639 aad.parent = ad; 645 aad.parent = ad;
646
640 for (unsigned i = 0; i < decl->dim; i++) 647 for (unsigned i = 0; i < decl->dim; i++)
641 { 648 {
642 Dsymbol *s = (Dsymbol *)decl->data[i]; 649 Dsymbol *s = (Dsymbol *)decl->data[i];
643 650
644 s->semantic(sc); 651 s->semantic(sc);
685 ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); 692 ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
686 //ad->structsize = sc->offset; 693 //ad->structsize = sc->offset;
687 //printf("sc->offset = %d\n", sc->offset); 694 //printf("sc->offset = %d\n", sc->offset);
688 695
689 // Add members of aad to ad 696 // Add members of aad to ad
690 //printf("\tadding members of aad (%p) to '%s'\n", &aad, ad->toChars()); 697 //printf("\tadding members of aad to '%s'\n", ad->toChars());
691 for (unsigned i = 0; i < aad.fields.dim; i++) 698 for (unsigned i = 0; i < aad.fields.dim; i++)
692 { 699 {
693 VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; 700 VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
694 701
695 // LDC 702 #if IN_LLVM
696 v->offset2 = sc->offset; 703 v->offset2 = sc->offset;
697 704 #endif
698 v->offset += sc->offset; 705 v->offset += sc->offset;
699 706
700 // LDC 707 #if IN_LLVM
701 if (!v->anonDecl) 708 if (!v->anonDecl)
702 v->anonDecl = this; 709 v->anonDecl = this;
703 710 #endif
704 ad->fields.push(v); 711 ad->fields.push(v);
705 } 712 }
706 713
707 // Add size of aad to ad 714 // Add size of aad to ad
708 if (adisunion) 715 if (adisunion)
769 this->args = args; 776 this->args = args;
770 } 777 }
771 778
772 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s) 779 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
773 { 780 {
781 //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
774 PragmaDeclaration *pd; 782 PragmaDeclaration *pd;
775 783
776 assert(!s); 784 assert(!s);
777 pd = new PragmaDeclaration(loc, ident, 785 pd = new PragmaDeclaration(loc, ident,
778 Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl)); 786 Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
783 { // Should be merged with PragmaStatement 791 { // Should be merged with PragmaStatement
784 792
785 #if IN_LLVM 793 #if IN_LLVM
786 int llvm_internal = 0; 794 int llvm_internal = 0;
787 std::string arg1str; 795 std::string arg1str;
788
789 #endif 796 #endif
790 797
791 //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); 798 //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
792 if (ident == Id::msg) 799 if (ident == Id::msg)
793 { 800 {
800 e = e->semantic(sc); 807 e = e->semantic(sc);
801 e = e->optimize(WANTvalue | WANTinterpret); 808 e = e->optimize(WANTvalue | WANTinterpret);
802 if (e->op == TOKstring) 809 if (e->op == TOKstring)
803 { 810 {
804 StringExp *se = (StringExp *)e; 811 StringExp *se = (StringExp *)e;
805 fprintf(stdmsg, "%.*s", (int)se->len, se->string); 812 fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
806 } 813 }
807 else 814 else
808 error("string expected for message, not '%s'", e->toChars()); 815 error("string expected for message, not '%s'", e->toChars());
809 } 816 }
810 fprintf(stdmsg, "\n"); 817 fprintf(stdmsg, "\n");
887 error("function name expected for start address, not '%s'", e->toChars()); 894 error("function name expected for start address, not '%s'", e->toChars());
888 } 895 }
889 goto Lnodecl; 896 goto Lnodecl;
890 } 897 }
891 898
892 ///////////////////////////////////////////////////////////// 899 // LDC
893 /////////////////////////////////////////////////////////////
894 // LDC
895 #if IN_LLVM 900 #if IN_LLVM
896 901
897 // pragma(intrinsic, "string") { funcdecl(s) } 902 // pragma(intrinsic, "string") { funcdecl(s) }
898 else if (ident == Id::intrinsic) 903 else if (ident == Id::intrinsic)
899 { 904 {
998 { 1003 {
999 sc->module->llvmForceLogging = true; 1004 sc->module->llvmForceLogging = true;
1000 } 1005 }
1001 else 1006 else
1002 { 1007 {
1003 error("command '%s' invalid"); 1008 error("command '%s' invalid", expr->toChars());
1004 fatal(); 1009 fatal();
1005 } 1010 }
1006 } 1011 }
1007 1012
1008 #endif 1013 // pragma(llvm_inline_asm) { templdecl(s) }
1009 // LDC 1014 else if (ident == Id::llvm_inline_asm)
1010 ///////////////////////////////////////////////////////////// 1015 {
1011 ///////////////////////////////////////////////////////////// 1016 if (args && args->dim > 0)
1017 {
1018 error("takes no parameters");
1019 fatal();
1020 }
1021 llvm_internal = LLVMinline_asm;
1022 }
1023
1024 #endif // LDC
1012 1025
1013 else if (ignoreUnsupportedPragmas) 1026 else if (ignoreUnsupportedPragmas)
1014 { 1027 {
1015 if (global.params.verbose) 1028 if (global.params.verbose)
1016 { 1029 {
1019 printf("pragma %s", ident->toChars()); 1032 printf("pragma %s", ident->toChars());
1020 if (args) 1033 if (args)
1021 { 1034 {
1022 for (size_t i = 0; i < args->dim; i++) 1035 for (size_t i = 0; i < args->dim; i++)
1023 { 1036 {
1037 // ignore errors in ignored pragmas.
1038 global.gag++;
1039 unsigned errors_save = global.errors;
1040
1024 Expression *e = (Expression *)args->data[i]; 1041 Expression *e = (Expression *)args->data[i];
1025 e = e->semantic(sc); 1042 e = e->semantic(sc);
1026 e = e->optimize(WANTvalue | WANTinterpret); 1043 e = e->optimize(WANTvalue | WANTinterpret);
1027 if (i == 0) 1044 if (i == 0)
1028 printf(" ("); 1045 printf(" (");
1029 else 1046 else
1030 printf(","); 1047 printf(",");
1031 printf("%s", e->toChars()); 1048 printf("%s", e->toChars());
1049
1050 // restore error state.
1051 global.gag--;
1052 global.errors = errors_save;
1032 } 1053 }
1033 if (args->dim) 1054 if (args->dim)
1034 printf(")"); 1055 printf(")");
1035 } 1056 }
1036 printf("\n"); 1057 printf("\n");
1037 } 1058 }
1038 goto Lnodecl;
1039 } 1059 }
1040 else 1060 else
1041 error("unrecognized pragma(%s)", ident->toChars()); 1061 error("unrecognized pragma(%s)", ident->toChars());
1042 1062
1043 if (decl) 1063 if (decl)
1135 error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars()); 1155 error("the '%s' pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
1136 fatal(); 1156 fatal();
1137 } 1157 }
1138 break; 1158 break;
1139 1159
1160 case LLVMinline_asm:
1161 if (TemplateDeclaration* td = s->isTemplateDeclaration())
1162 {
1163 if (td->parameters->dim > 1)
1164 {
1165 error("the '%s' pragma template must have exactly zero or one template parameters", ident->toChars());
1166 fatal();
1167 }
1168 else if (!td->onemember)
1169 {
1170 error("the '%s' pragma template must have exactly one member", ident->toChars());
1171 fatal();
1172 }
1173 td->llvmInternal = llvm_internal;
1174 }
1175 else
1176 {
1177 error("the '%s' pragma is only allowed on template declarations", ident->toChars());
1178 fatal();
1179 }
1180 break;
1181
1140 default: 1182 default:
1141 warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars()); 1183 warning("the LDC specific pragma '%s' is not yet implemented, ignoring", ident->toChars());
1142 } 1184 }
1143 } 1185 }
1144 1186
1162 const char *PragmaDeclaration::kind() 1204 const char *PragmaDeclaration::kind()
1163 { 1205 {
1164 return "pragma"; 1206 return "pragma";
1165 } 1207 }
1166 1208
1209 #if IN_DMD
1167 void PragmaDeclaration::toObjFile(int multiobj) 1210 void PragmaDeclaration::toObjFile(int multiobj)
1168 { 1211 {
1169 if (ident == Id::lib) 1212 if (ident == Id::lib)
1170 { 1213 {
1171 assert(args && args->dim == 1); 1214 assert(args && args->dim == 1);
1176 1219
1177 StringExp *se = (StringExp *)e; 1220 StringExp *se = (StringExp *)e;
1178 char *name = (char *)mem.malloc(se->len + 1); 1221 char *name = (char *)mem.malloc(se->len + 1);
1179 memcpy(name, se->string, se->len); 1222 memcpy(name, se->string, se->len);
1180 name[se->len] = 0; 1223 name[se->len] = 0;
1224 #if OMFOBJ
1225 /* The OMF format allows library names to be inserted
1226 * into the object file. The linker will then automatically
1227 * search that library, too.
1228 */
1181 obj_includelib(name); 1229 obj_includelib(name);
1182 } 1230 #elif ELFOBJ || MACHOBJ
1231 /* The format does not allow embedded library names,
1232 * so instead append the library name to the list to be passed
1233 * to the linker.
1234 */
1235 global.params.libfiles->push((void *) name);
1236 #else
1237 error("pragma lib not supported");
1238 #endif
1239 }
1240 #if DMDV2
1183 else if (ident == Id::startaddress) 1241 else if (ident == Id::startaddress)
1184 { 1242 {
1185 assert(args && args->dim == 1); 1243 assert(args && args->dim == 1);
1186 Expression *e = (Expression *)args->data[0]; 1244 Expression *e = (Expression *)args->data[0];
1187 Dsymbol *sa = getDsymbol(e); 1245 Dsymbol *sa = getDsymbol(e);
1188 FuncDeclaration *f = sa->isFuncDeclaration(); 1246 FuncDeclaration *f = sa->isFuncDeclaration();
1189 assert(f); 1247 assert(f);
1190 Symbol *s = f->toSymbol(); 1248 Symbol *s = f->toSymbol();
1191 assert(0 && "startaddress pragma not implemented"); 1249 obj_startaddress(s);
1192 // obj_startaddress(s); 1250 }
1193 } 1251 #endif
1194 AttribDeclaration::toObjFile(multiobj); 1252 AttribDeclaration::toObjFile(multiobj);
1195 } 1253 }
1254 #endif
1196 1255
1197 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) 1256 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1198 { 1257 {
1199 buf->printf("pragma (%s", ident->toChars()); 1258 buf->printf("pragma (%s", ident->toChars());
1200 if (args && args->dim) 1259 if (args && args->dim)
1245 { 1304 {
1246 //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc); 1305 //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
1247 if (condition->inc) 1306 if (condition->inc)
1248 { 1307 {
1249 AttribDeclaration::emitComment(sc); 1308 AttribDeclaration::emitComment(sc);
1309 }
1310 else if (sc->docbuf)
1311 {
1312 /* If generating doc comment, be careful because if we're inside
1313 * a template, then include(NULL, NULL) will fail.
1314 */
1315 Array *d = decl ? decl : elsedecl;
1316 for (unsigned i = 0; i < d->dim; i++)
1317 { Dsymbol *s = (Dsymbol *)d->data[i];
1318 s->emitComment(sc);
1319 }
1250 } 1320 }
1251 } 1321 }
1252 1322
1253 // Decide if 'then' or 'else' code should be included 1323 // Decide if 'then' or 'else' code should be included
1254 1324