annotate dmd/FuncDeclaration.d @ 22:fd4acc376c45

Implemented object file output and linking on linux.
author Robert Clipsham <robert@octarineparrot.com>
date Thu, 08 Apr 2010 04:21:03 +0100
parents ddae60498573
children cab4c37afb89
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1 module dmd.FuncDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3 import dmd.Declaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
4 import dmd.DotIdExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
5 import dmd.TryFinallyStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
6 import dmd.StaticDtorDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
7 import dmd.PeelStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
8 import dmd.SynchronizedStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
9 import dmd.TOK;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
10 import dmd.SymOffExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
11 import dmd.AssignExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
12 import dmd.ExpInitializer;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
13 import dmd.BE;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
14 import dmd.Id;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
15 import dmd.StringExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
16 import dmd.DsymbolExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
17 import dmd.HaltExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
18 import dmd.CommaExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
19 import dmd.ReturnStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
20 import dmd.IntegerExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
21 import dmd.ExpStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
22 import dmd.CSX;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
23 import dmd.CompoundStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
24 import dmd.LabelStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
25 import dmd.ThisExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
26 import dmd.SuperExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
27 import dmd.IdentifierExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
28 import dmd.AssertExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
29 import dmd.CallExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
30 import dmd.RET;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
31 import dmd.VarExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
32 import dmd.TupleDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
33 import dmd.ThisDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
34 import dmd.TypeTuple;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
35 import dmd.TemplateInstance;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
36 import dmd.ScopeDsymbol;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
37 import dmd.AliasDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
38 import dmd.MOD;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
39 import dmd.PROT;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
40 import dmd.Lexer;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
41 import dmd.LINK;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
42 import dmd.CtorDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
43 import dmd.Global;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
44 import dmd.DtorDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
45 import dmd.InvariantDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
46 import dmd.TY;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
47 import dmd.PtrExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
48 import dmd.DeclarationExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
49 import dmd.InlineDoState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
50 import dmd.Argument;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
51 import dmd.StructDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
52 import dmd.ClassDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
53 import dmd.InterfaceDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
54 import dmd.Array;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
55 import dmd.Statement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
56 import dmd.Identifier;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
57 import dmd.VarDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
58 import dmd.LabelDsymbol;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
59 import dmd.DsymbolTable;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
60 import dmd.ArrayTypes;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
61 import dmd.Loc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
62 import dmd.ILS;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
63 import dmd.ForeachStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
64 import dmd.Type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
65 import dmd.BUILTIN;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
66 import dmd.TypeFunction;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
67 import dmd.Expression;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
68 import dmd.STC;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
69 import dmd.Dsymbol;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
70 import dmd.Scope;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
71 import dmd.OutBuffer;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
72 import dmd.HdrGenState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
73 import dmd.MATCH;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
74 import dmd.AggregateDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
75 import dmd.InterState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
76 import dmd.InlineScanState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
77 import dmd.IRState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
78 import dmd.Util;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
79 import dmd.BaseClass;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
80 import dmd.Module;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
81 import dmd.ILS;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
82 import dmd.InlineCostState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
83
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
84 import dmd.expression.Util;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
85
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
86 import dmd.declaration.Match;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
87
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
88 import dmd.backend.Symbol;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
89 import dmd.backend.func_t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
90 import dmd.backend.Util;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
91 import dmd.backend.glue;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
92 import dmd.backend.SC;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
93 import dmd.backend.F;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
94 import dmd.backend.Cstate;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
95 import dmd.backend.TYM;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
96 import dmd.backend.OPER;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
97 import dmd.backend.TYFL;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
98 import dmd.backend.TYPE;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
99 import dmd.backend.SFL;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
100 import dmd.backend.mTY;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
101 import dmd.backend.FL;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
102 import dmd.backend.REG;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
103 import dmd.backend.block;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
104 import dmd.backend.Blockx;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
105 import dmd.backend.Config;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
106 import dmd.backend.BC;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
107 import dmd.backend.elem;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
108 import dmd.backend.targ_types;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
109 import dmd.backend.mTYman;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
110 import dmd.backend.RTLSYM;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
111 import dmd.backend.LIST;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
112
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
113 import core.stdc.stdio;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
114 import core.stdc.string;
14
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
115 version (Bug4054) import core.memory;
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
116
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
117 import std.string;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
118
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
119 class FuncDeclaration : Declaration
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
120 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
121 Array fthrows; // Array of Type's of exceptions (not used)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
122 Statement frequire;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
123 Statement fensure;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
124 Statement fbody;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
125
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
126 Identifier outId; // identifier for out statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
127 VarDeclaration vresult; // variable corresponding to outId
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
128 LabelDsymbol returnLabel; // where the return goes
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
129
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
130 DsymbolTable localsymtab; // used to prevent symbols in different
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
131 // scopes from having the same name
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
132 VarDeclaration vthis; // 'this' parameter (member and nested)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
133 VarDeclaration v_arguments; // '_arguments' parameter
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
134 version (IN_GCC) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
135 VarDeclaration v_argptr; // '_argptr' variable
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
136 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
137 Dsymbols parameters; // Array of VarDeclaration's for parameters
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
138 DsymbolTable labtab; // statement label symbol table
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
139 Declaration overnext; // next in overload list
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
140 Loc endloc; // location of closing curly bracket
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
141 int vtblIndex = -1; // for member functions, index into vtbl[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
142 int naked; // !=0 if naked
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
143 int inlineAsm; // !=0 if has inline assembler
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
144 ILS inlineStatus = ILS.ILSuninitialized;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
145 int inlineNest; // !=0 if nested inline
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
146 int cantInterpret; // !=0 if cannot interpret function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
147 int semanticRun; // 1 semantic() run
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
148 // 2 semantic2() run
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
149 // 3 semantic3() started
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
150 // 4 semantic3() done
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
151 // 5 toObjFile() run
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
152 // this function's frame ptr
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
153 ForeachStatement fes; // if foreach body, this is the foreach
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
154 int introducing; // !=0 if 'introducing' function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
155 Type tintro; // if !=null, then this is the type
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
156 // of the 'introducing' function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
157 // this one is overriding
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
158 int inferRetType; // !=0 if return type is to be inferred
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
159
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
160 // Things that should really go into Scope
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
161 int hasReturnExp; // 1 if there's a return exp; statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
162 // 2 if there's a throw statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
163 // 4 if there's an assert(0)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
164 // 8 if there's inline asm
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
165
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
166 // Support for NRVO (named return value optimization)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
167 bool nrvo_can = true; // !=0 means we can do it
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
168 VarDeclaration nrvo_var; // variable to replace with shidden
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
169 Symbol* shidden; // hidden pointer passed to function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
170
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
171 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
172 BUILTIN builtin; // set if this is a known, builtin
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
173 // function we can evaluate at compile
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
174 // time
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
175
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
176 int tookAddressOf; // set if someone took the address of
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
177 // this function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
178 Dsymbols closureVars; // local variables in this function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
179 // which are referenced by nested
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
180 // functions
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
181 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
182 int nestedFrameRef; // !=0 if nested variables referenced
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
183 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
184
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
185 this(Loc loc, Loc endloc, Identifier id, STC storage_class, Type type)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
186 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
187 super(id);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
188
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
189 //printf("FuncDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
190 //printf("storage_class = x%x\n", storage_class);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
191 this.storage_class = storage_class;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
192 this.type = type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
193 this.loc = loc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
194 this.endloc = endloc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
195
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
196 /* The type given for "infer the return type" is a TypeFunction with
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
197 * null for the return type.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
198 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
199 inferRetType = (type && type.nextOf() is null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
200
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
201 closureVars = new Dsymbols();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
202
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
203 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
204 builtin = BUILTIN.BUILTINunknown;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
205 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
206 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
207
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
208 Dsymbol syntaxCopy(Dsymbol s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
209 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
210 FuncDeclaration f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
211
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
212 //printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
213 if (s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
214 f = cast(FuncDeclaration)s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
215 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
216 f = new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
217
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
218 f.outId = outId;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
219 f.frequire = frequire ? frequire.syntaxCopy() : null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
220 f.fensure = fensure ? fensure.syntaxCopy() : null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
221 f.fbody = fbody ? fbody.syntaxCopy() : null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
222 assert(!fthrows); // deprecated
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
223
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
224 return f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
225 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
226
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
227 // Do the semantic analysis on the external interface to the function.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
228 void semantic(Scope sc)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
229 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
230 TypeFunction f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
231 StructDeclaration sd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
232 ClassDeclaration cd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
233 InterfaceDeclaration id;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
234 Dsymbol pd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
235
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
236 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
237 printf("FuncDeclaration.semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc.linkage);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
238 if (isFuncLiteralDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
239 printf("\tFuncLiteralDeclaration()\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
240 printf("sc.parent = %s, parent = %s\n", sc.parent.toChars(), parent ? parent.toChars() : "");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
241 printf("type: %p, %s\n", type, type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
242 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
243
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
244 if (semanticRun && isFuncLiteralDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
245 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
246 /* Member functions that have return types that are
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
247 * forward references can have semantic() run more than
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
248 * once on them.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
249 * See test\interface2.d, test20
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
250 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
251 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
252 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
253 assert(semanticRun <= 1);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
254 semanticRun = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
255
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
256 storage_class |= sc.stc & ~STC.STCref;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
257 //printf("function storage_class = x%x\n", storage_class);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
258
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
259 if (!originalType)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
260 originalType = type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
261 if (!type.deco)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
262 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
263 /* Apply const and invariant storage class
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
264 * to the function type
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
265 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
266 type = type.semantic(loc, sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
267 STC stc = storage_class;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
268 if (type.isInvariant())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
269 stc |= STC.STCimmutable;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
270 if (type.isConst())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
271 stc |= STC.STCconst;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
272 if (type.isShared() || storage_class & STC.STCsynchronized)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
273 stc |= STC.STCshared;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
274 switch (stc & STC.STC_TYPECTOR)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
275 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
276 case STC.STCimmutable:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
277 case STC.STCimmutable | STC.STCconst:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
278 case STC.STCimmutable | STC.STCconst | STC.STCshared:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
279 case STC.STCimmutable | STC.STCshared:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
280 // Don't use toInvariant(), as that will do a merge()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
281 type = type.makeInvariant();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
282 type.deco = type.merge().deco;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
283 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
284
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
285 case STC.STCconst:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
286 type = type.makeConst();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
287 type.deco = type.merge().deco;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
288 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
289
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
290 case STC.STCshared | STC.STCconst:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
291 type = type.makeSharedConst();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
292 type.deco = type.merge().deco;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
293 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
294
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
295 case STC.STCshared:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
296 type = type.makeShared();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
297 type.deco = type.merge().deco;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
298 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
299
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
300 case STC.STCundefined:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
301 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
302
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
303 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
304 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
305 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
306 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
307 //type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
308 if (type.ty != TY.Tfunction)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
309 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
310 error("%s must be a function", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
311 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
312 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
313 f = cast(TypeFunction)type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
314 size_t nparams = Argument.dim(f.parameters);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
315
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
316 linkage = sc.linkage;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
317 // if (!parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
318 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
319 //parent = sc.scopesym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
320 parent = sc.parent;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
321 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
322 protection = sc.protection;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
323 Dsymbol parent = toParent();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
324
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
325 if (storage_class & STC.STCscope)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
326 error("functions cannot be scope");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
327
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
328 if (isAbstract() && !isVirtual())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
329 error("non-virtual functions cannot be abstract");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
330
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
331 if ((f.isConst() || f.isInvariant()) && !isThis())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
332 error("without 'this' cannot be const/immutable");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
333
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
334 if (isAbstract() && isFinal())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
335 error("cannot be both final and abstract");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
336 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
337 if (isAbstract() && fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
338 error("abstract functions cannot have bodies");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
339 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
340
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
341 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
342 if (isStaticConstructor() || isStaticDestructor())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
343 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
344 if (!isStatic() || type.nextOf().ty != Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
345 error("static constructors / destructors must be static void");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
346 if (f.arguments && f.arguments.dim)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
347 error("static constructors / destructors must have empty parameter list");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
348 // BUG: check for invalid storage classes
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
349 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
350 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
351
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
352 version (IN_GCC) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
353 AggregateDeclaration ad;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
354
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
355 ad = parent.isAggregateDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
356 if (ad)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
357 ad.methods.push(cast(void*)this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
358 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
359 sd = parent.isStructDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
360 if (sd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
361 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
362 if (isCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
363 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
364 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
365 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
366 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
367 // Verify no constructors, destructors, etc.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
368 if (isCtorDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
369 //||isDtorDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
370 //|| isInvariantDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
371 //|| isUnitTestDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
372 )
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
373 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
374 error("special member functions not allowed for %ss", sd.kind());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
375 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
376
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
377 if (!sd.inv)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
378 sd.inv = isInvariantDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
379
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
380 if (!sd.aggNew)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
381 sd.aggNew = isNewDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
382
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
383 if (isDelete())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
384 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
385 if (sd.aggDelete)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
386 error("multiple delete's for struct %s", sd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
387 sd.aggDelete = cast(DeleteDeclaration)this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
388 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
389 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
390 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
391
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
392 id = parent.isInterfaceDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
393 if (id)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
394 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
395 storage_class |= STC.STCabstract;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
396
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
397 if (isCtorDeclaration() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
398 ///static if (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
399 isPostBlitDeclaration() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
400 ///}
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
401 isDtorDeclaration() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
402 isInvariantDeclaration() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
403 isUnitTestDeclaration() || isNewDeclaration() || isDelete())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
404 error("special function not allowed in interface %s", id.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
405 if (fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
406 error("function body is not abstract in interface %s", id.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
407 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
408
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
409 /* Template member functions aren't virtual:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
410 * interface TestInterface { void tpl(T)(); }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
411 * and so won't work in interfaces
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
412 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
413 if ((pd = toParent()) !is null &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
414 pd.isTemplateInstance() &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
415 (pd = toParent2()) !is null &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
416 (id = pd.isInterfaceDeclaration()) !is null)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
417 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
418 error("template member function not allowed in interface %s", id.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
419 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
420
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
421 cd = parent.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
422 if (cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
423 { int vi;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
424 CtorDeclaration ctor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
425 DtorDeclaration dtor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
426 InvariantDeclaration inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
427
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
428 if (isCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
429 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
430 // ctor = cast(CtorDeclaration)this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
431 // if (!cd.ctor)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
432 // cd.ctor = ctor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
433 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
434 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
435
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
436 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
437 dtor = isDtorDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
438 if (dtor)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
439 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
440 if (cd.dtor)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
441 error("multiple destructors for class %s", cd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
442 cd.dtor = dtor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
443 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
444
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
445 inv = isInvariantDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
446 if (inv)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
447 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
448 cd.inv = inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
449 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
450
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
451 if (isNewDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
452 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
453 if (!cd.aggNew)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
454 cd.aggNew = cast(NewDeclaration)this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
455 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
456
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
457 if (isDelete())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
458 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
459 if (cd.aggDelete)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
460 error("multiple delete's for class %s", cd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
461 cd.aggDelete = cast(DeleteDeclaration)this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
462 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
463 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
464
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
465 if (storage_class & STC.STCabstract)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
466 cd.isabstract = true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
467
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
468 // if static function, do not put in vtbl[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
469 if (!isVirtual())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
470 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
471 //printf("\tnot virtual\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
472 goto Ldone;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
473 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
474
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
475 // Find index of existing function in vtbl[] to override
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
476 vi = findVtblIndex(cd.vtbl, cd.baseClass ? cd.baseClass.vtbl.dim : 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
477 switch (vi)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
478 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
479 case -1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
480 /* Didn't find one, so
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
481 * This is an 'introducing' function which gets a new
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
482 * slot in the vtbl[].
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
483 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
484
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
485 // Verify this doesn't override previous final function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
486 if (cd.baseClass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
487 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
488 Dsymbol s = cd.baseClass.search(loc, ident, 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
489 if (s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
490 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
491 FuncDeclaration ff = s.isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
492 ff = ff.overloadExactMatch(type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
493 if (ff && ff.isFinal() && ff.prot() != PROT.PROTprivate)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
494 error("cannot override final function %s", ff.toPrettyChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
495 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
496 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
497
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
498 if (isFinal())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
499 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
500 if (isOverride())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
501 error("does not override any function");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
502 cd.vtblFinal.push(cast(void*)this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
503 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
504 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
505 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
506 // Append to end of vtbl[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
507 //printf("\tintroducing function\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
508 introducing = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
509 vi = cd.vtbl.dim;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
510 cd.vtbl.push(cast(void*)this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
511 vtblIndex = vi;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
512 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
513 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
514
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
515 case -2: // can't determine because of fwd refs
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
516 cd.sizeok = 2; // can't finish due to forward reference
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
517 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
518
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
519 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
520 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
521 FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
522 // This function is covariant with fdv
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
523 if (fdv.isFinal())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
524 error("cannot override final function %s", fdv.toPrettyChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
525
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
526 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
527 if (!isOverride())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
528 warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv.toPrettyChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
529 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
530
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
531 if (fdv.toParent() == parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
532 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
533 // If both are mixins, then error.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
534 // If either is not, the one that is not overrides
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
535 // the other.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
536 if (fdv.parent.isClassDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
537 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
538 if (!this.parent.isClassDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
539 ///static if (!BREAKABI) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
540 && !isDtorDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
541 ///}
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
542 ///version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
543 && !isPostBlitDeclaration()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
544 ///}
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
545 )
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
546 error("multiple overrides of same function");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
547 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
548 cd.vtbl.data[vi] = cast(void*)this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
549 vtblIndex = vi;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
550
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
551 /* This works by whenever this function is called,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
552 * it actually returns tintro, which gets dynamically
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
553 * cast to type. But we know that tintro is a base
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
554 * of type, so we could optimize it by not doing a
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
555 * dynamic cast, but just subtracting the isBaseOf()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
556 * offset if the value is != null.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
557 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
558
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
559 if (fdv.tintro)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
560 tintro = fdv.tintro;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
561 else if (!type.equals(fdv.type))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
562 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
563 /* Only need to have a tintro if the vptr
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
564 * offsets differ
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
565 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
566 int offset;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
567 if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
568 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
569 tintro = fdv.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
570 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
571 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
572 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
573 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
574 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
575
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
576 /* Go through all the interface bases.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
577 * If this function is covariant with any members of those interface
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
578 * functions, set the tintro.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
579 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
580 for (int i = 0; i < cd.interfaces_dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
581 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
582 BaseClass b = cd.interfaces[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
583 vi = findVtblIndex(b.base.vtbl, b.base.vtbl.dim);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
584 switch (vi)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
585 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
586 case -1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
587 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
588
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
589 case -2:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
590 cd.sizeok = 2; // can't finish due to forward reference
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
591 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
592
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
593 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
594 { FuncDeclaration fdv = cast(FuncDeclaration)b.base.vtbl.data[vi];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
595 Type ti = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
596
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
597 if (fdv.tintro)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
598 ti = fdv.tintro;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
599 else if (!type.equals(fdv.type))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
600 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
601 /* Only need to have a tintro if the vptr
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
602 * offsets differ
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
603 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
604 int offset;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
605 if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
606 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
607 ti = fdv.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
608 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
609 if (offset)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
610 ti = fdv.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
611 else if (type.nextOf().ty == Tclass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
612 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
613 ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
614 if (cdn && cdn.sizeok != 1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
615 ti = fdv.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
616 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
617 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
618 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
619 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
620 if (ti)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
621 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
622 if (tintro && !tintro.equals(ti))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
623 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
624 error("incompatible covariant types %s and %s", tintro.toChars(), ti.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
625 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
626 tintro = ti;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
627 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
628 goto L2;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
629 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
630 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
631 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
632
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
633 if (introducing && isOverride())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
634 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
635 error("does not override any function");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
636 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
637
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
638 L2: ;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
639 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
640 else if (isOverride() && !parent.isTemplateInstance())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
641 error("override only applies to class member functions");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
642
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
643 /* Do not allow template instances to add virtual functions
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
644 * to a class.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
645 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
646 if (isVirtual())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
647 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
648 TemplateInstance ti = parent.isTemplateInstance();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
649 if (ti)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
650 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
651 // Take care of nested templates
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
652 while (1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
653 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
654 TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
655 if (!ti2)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
656 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
657 ti = ti2;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
658 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
659
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
660 // If it's a member template
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
661 ClassDeclaration cdd = ti.tempdecl.isClassMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
662 if (cdd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
663 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
664 error("cannot use template to add virtual function to class '%s'", cdd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
665 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
666 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
667 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
668
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
669 if (isMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
670 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
671 // Check parameters to see if they are either () or (char[][] args)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
672 switch (nparams)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
673 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
674 case 0:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
675 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
676
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
677 case 1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
678 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
679 Argument arg0 = Argument.getNth(f.parameters, 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
680 if (arg0.type.ty != TY.Tarray ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
681 arg0.type.nextOf().ty != TY.Tarray ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
682 arg0.type.nextOf().nextOf().ty != TY.Tchar ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
683 arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
684 goto Lmainerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
685 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
686 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
687
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
688 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
689 goto Lmainerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
690 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
691
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
692 if (f.nextOf().ty != TY.Tint32 && f.nextOf().ty != TY.Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
693 error("must return int or void, not %s", f.nextOf().toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
694 if (f.varargs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
695 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
696 Lmainerr:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
697 error("parameters must be main() or main(char[][] args)");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
698 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
699 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
700
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
701 if (ident == Id.assign && (sd || cd))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
702 { // Disallow identity assignment operator.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
703
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
704 // opAssign(...)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
705 if (nparams == 0)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
706 { if (f.varargs == 1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
707 goto Lassignerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
708 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
709 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
710 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
711 Argument arg0 = Argument.getNth(f.parameters, 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
712 Type t0 = arg0.type.toBasetype();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
713 Type tb = sd ? sd.type : cd.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
714 if (arg0.type.implicitConvTo(tb) ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
715 (sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
716 )
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
717 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
718 if (nparams == 1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
719 goto Lassignerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
720 Argument arg1 = Argument.getNth(f.parameters, 1);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
721 if (arg1.defaultArg)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
722 goto Lassignerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
723 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
724 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
725 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
726
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
727 Ldone:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
728 /* Save scope for possible later use (if we need the
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
729 * function internals)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
730 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
731 scope_ = new Scope(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
732 scope_.setNoFree();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
733 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
734
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
735 Lassignerr:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
736 if (sd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
737 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
738 sd.hasIdentityAssign = 1; // don't need to generate it
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
739 goto Ldone;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
740 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
741 error("identity assignment operator overload is illegal");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
742 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
743
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
744 void semantic2(Scope sc)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
745 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
746 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
747
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
748 // Do the semantic analysis on the internals of the function.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
749 void semantic3(Scope sc)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
750 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
751 TypeFunction f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
752 VarDeclaration argptr = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
753 VarDeclaration _arguments = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
754
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
755 if (!parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
756 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
757 if (global.errors)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
758 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
759 //printf("FuncDeclaration.semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
760 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
761 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
762 //printf("FuncDeclaration.semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
763 //fflush(stdout);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
764 //printf("storage class = x%x %x\n", sc.stc, storage_class);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
765 //{ static int x; if (++x == 2) *(char*)0=0; }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
766 //printf("\tlinkage = %d\n", sc.linkage);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
767
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
768 //printf(" sc.incontract = %d\n", sc.incontract);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
769 if (semanticRun >= 3)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
770 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
771 semanticRun = 3;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
772
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
773 if (!type || type.ty != TY.Tfunction)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
774 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
775 f = cast(TypeFunction)(type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
776
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
777 // Check the 'throws' clause
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
778 if (fthrows)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
779 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
780 for (int i = 0; i < fthrows.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
781 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
782 Type t = cast(Type)fthrows.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
783
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
784 t = t.semantic(loc, sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
785 if (!t.isClassHandle())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
786 error("can only throw classes, not %s", t.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
787 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
788 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
789
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
790 if (fbody || frequire)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
791 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
792 /* Symbol table into which we place parameters and nested functions,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
793 * solely to diagnose name collisions.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
794 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
795 localsymtab = new DsymbolTable();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
796
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
797 // Establish function scope
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
798 ScopeDsymbol ss = new ScopeDsymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
799 ss.parent = sc.scopesym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
800 Scope sc2 = sc.push(ss);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
801 sc2.func = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
802 sc2.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
803 sc2.callSuper = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
804 sc2.sbreak = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
805 sc2.scontinue = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
806 sc2.sw = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
807 sc2.fes = fes;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
808 sc2.linkage = LINK.LINKd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
809 sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
810 sc2.protection = PROT.PROTpublic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
811 sc2.explicitProtection = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
812 sc2.structalign = 8;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
813 sc2.incontract = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
814 sc2.tf = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
815 sc2.noctor = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
816
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
817 // Declare 'this'
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
818 AggregateDeclaration ad = isThis();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
819 if (ad)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
820 { VarDeclaration v;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
821
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
822 if (isFuncLiteralDeclaration() && isNested())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
823 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
824 error("literals cannot be class members");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
825 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
826 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
827 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
828 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
829 assert(!isNested()); // can't be both member and nested
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
830 assert(ad.handle);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
831 Type thandle = ad.handle;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
832 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
833 thandle = thandle.addMod(type.mod);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
834 thandle = thandle.addStorageClass(storage_class);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
835 if (isPure())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
836 thandle = thandle.addMod(MOD.MODconst);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
837 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
838 if (storage_class & STC.STCconst || type.isConst())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
839 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
840 assert(0); // BUG: shared not handled
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
841 if (thandle.ty == TY.Tclass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
842 thandle = thandle.constOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
843 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
844 { assert(thandle.ty == TY.Tpointer);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
845 thandle = thandle.nextOf().constOf().pointerTo();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
846 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
847 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
848 else if (storage_class & STC.STCimmutable || type.isInvariant())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
849 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
850 if (thandle.ty == TY.Tclass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
851 thandle = thandle.invariantOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
852 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
853 { assert(thandle.ty == TY.Tpointer);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
854 thandle = thandle.nextOf().invariantOf().pointerTo();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
855 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
856 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
857 else if (storage_class & STC.STCshared || type.isShared())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
858 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
859 assert(0); // not implemented
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
860 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
861 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
862 v = new ThisDeclaration(loc, thandle);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
863 v.storage_class |= STC.STCparameter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
864 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
865 if (thandle.ty == TY.Tstruct)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
866 v.storage_class |= STC.STCref;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
867 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
868 v.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
869 if (!sc2.insert(v))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
870 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
871 v.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
872 vthis = v;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
873 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
874 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
875 else if (isNested())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
876 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
877 /* The 'this' for a nested function is the link to the
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
878 * enclosing function's stack frame.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
879 * Note that nested functions and member functions are disjoint.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
880 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
881 VarDeclaration v = new ThisDeclaration(loc, Type.tvoid.pointerTo());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
882 v.storage_class |= STC.STCparameter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
883 v.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
884 if (!sc2.insert(v))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
885 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
886 v.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
887 vthis = v;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
888 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
889
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
890 // Declare hidden variable _arguments[] and _argptr
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
891 if (f.varargs == 1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
892 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
893 version (TARGET_NET) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
894 varArgs(sc2, f, argptr, _arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
895 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
896 Type t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
897
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
898 if (f.linkage == LINK.LINKd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
899 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
900 // Declare _arguments[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
901 version (BREAKABI) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
902 v_arguments = new VarDeclaration(Loc(0), Type.typeinfotypelist.type, Id._arguments_typeinfo, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
903 v_arguments.storage_class = STCparameter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
904 v_arguments.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
905 sc2.insert(v_arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
906 v_arguments.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
907
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
908 //t = Type.typeinfo.type.constOf().arrayOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
909 t = Type.typeinfo.type.arrayOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
910 _arguments = new VarDeclaration(Loc(0), t, Id._arguments, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
911 _arguments.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
912 sc2.insert(_arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
913 _arguments.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
914 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
915 t = Type.typeinfo.type.arrayOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
916 v_arguments = new VarDeclaration(Loc(0), t, Id._arguments, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
917 v_arguments.storage_class = STC.STCparameter | STC.STCin;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
918 v_arguments.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
919 sc2.insert(v_arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
920 v_arguments.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
921 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
922 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
923 if (f.linkage == LINK.LINKd || (parameters && parameters.dim))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
924 { // Declare _argptr
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
925 version (IN_GCC) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
926 t = d_gcc_builtin_va_list_d_type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
927 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
928 t = Type.tvoid.pointerTo();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
929 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
930 argptr = new VarDeclaration(Loc(0), t, Id._argptr, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
931 argptr.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
932 sc2.insert(argptr);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
933 argptr.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
934 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
935 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
936 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
937
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
938 // Propagate storage class from tuple parameters to their element-parameters.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
939 if (f.parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
940 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
941 for (size_t i = 0; i < f.parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
942 { Argument arg = cast(Argument)f.parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
943
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
944 //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
945 if (arg.type.ty == TY.Ttuple)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
946 { TypeTuple t = cast(TypeTuple)arg.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
947 size_t dim = Argument.dim(t.arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
948 for (size_t j = 0; j < dim; j++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
949 { Argument narg = Argument.getNth(t.arguments, j);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
950 narg.storageClass = arg.storageClass;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
951 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
952 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
953 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
954 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
955
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
956 /* Declare all the function parameters as variables
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
957 * and install them in parameters[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
958 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
959 size_t nparams = Argument.dim(f.parameters);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
960 if (nparams)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
961 { /* parameters[] has all the tuples removed, as the back end
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
962 * doesn't know about tuples
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
963 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
964 parameters = new Dsymbols();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
965 parameters.reserve(nparams);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
966 for (size_t i = 0; i < nparams; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
967 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
968 Argument arg = Argument.getNth(f.parameters, i);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
969 Identifier id = arg.ident;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
970 if (!id)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
971 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
972 /* Generate identifier for un-named parameter,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
973 * because we need it later on.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
974 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
975 arg.ident = id = Identifier.generateId("_param_", i);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
976 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
977 Type vtype = arg.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
978 if (isPure())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
979 vtype = vtype.addMod(MOD.MODconst);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
980 VarDeclaration v = new VarDeclaration(loc, vtype, id, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
981 //printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
982 v.storage_class |= STC.STCparameter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
983 if (f.varargs == 2 && i + 1 == nparams)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
984 v.storage_class |= STC.STCvariadic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
985 v.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy | STC.STCfinal | STC.STC_TYPECTOR | STC.STCnodtor);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
986 v.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
987 if (!sc2.insert(v))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
988 error("parameter %s.%s is already defined", toChars(), v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
989 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
990 parameters.push(cast(void*)v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
991 localsymtab.insert(v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
992 v.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
993 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
994 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
995
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
996 // Declare the tuple symbols and put them in the symbol table,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
997 // but not in parameters[].
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
998 if (f.parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
999 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1000 for (size_t i = 0; i < f.parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1001 { Argument arg = cast(Argument)f.parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1002
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1003 if (!arg.ident)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1004 continue; // never used, so ignore
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1005 if (arg.type.ty == TY.Ttuple)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1006 { TypeTuple t = cast(TypeTuple)arg.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1007 size_t dim = Argument.dim(t.arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1008 Objects exps = new Objects();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1009 exps.setDim(dim);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1010 for (size_t j = 0; j < dim; j++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1011 { Argument narg = Argument.getNth(t.arguments, j);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1012 assert(narg.ident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1013 VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1014 assert(v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1015 Expression e = new VarExp(v.loc, v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1016 exps.data[j] = cast(void*)e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1017 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1018 assert(arg.ident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1019 TupleDeclaration v = new TupleDeclaration(loc, arg.ident, exps);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1020 //printf("declaring tuple %s\n", v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1021 v.isexp = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1022 if (!sc2.insert(v))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1023 error("parameter %s.%s is already defined", toChars(), v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1024 localsymtab.insert(v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1025 v.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1026 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1027 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1028 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1029
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1030 /* Do the semantic analysis on the [in] preconditions and
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1031 * [out] postconditions.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1032 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1033 sc2.incontract++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1034
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1035 if (frequire)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1036 { /* frequire is composed of the [in] contracts
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1037 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1038 // BUG: need to error if accessing out parameters
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1039 // BUG: need to treat parameters as const
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1040 // BUG: need to disallow returns and throws
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1041 // BUG: verify that all in and ref parameters are read
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1042 frequire = frequire.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1043 labtab = null; // so body can't refer to labels
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1044 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1045
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1046 if (fensure || addPostInvariant())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1047 { /* fensure is composed of the [out] contracts
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1048 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1049 ScopeDsymbol sym = new ScopeDsymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1050 sym.parent = sc2.scopesym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1051 sc2 = sc2.push(sym);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1052
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1053 assert(type.nextOf());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1054 if (type.nextOf().ty == TY.Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1055 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1056 if (outId)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1057 error("void functions have no result");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1058 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1059 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1060 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1061 if (!outId)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1062 outId = Id.result; // provide a default
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1063 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1064
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1065 if (outId)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1066 { // Declare result variable
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1067 VarDeclaration v;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1068 Loc loc = this.loc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1069
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1070 if (fensure)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1071 loc = fensure.loc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1072
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1073 v = new VarDeclaration(loc, type.nextOf(), outId, null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1074 v.noauto = true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1075 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1076 if (f.isref)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1077 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1078 v.storage_class |= STC.STCref | STC.STCforeach;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1079 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1080 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1081 sc2.incontract--;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1082 v.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1083 sc2.incontract++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1084 if (!sc2.insert(v))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1085 error("out result %s is already defined", v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1086 v.parent = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1087 vresult = v;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1088
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1089 // vresult gets initialized with the function return value
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1090 // in ReturnStatement.semantic()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1091 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1092
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1093 // BUG: need to treat parameters as const
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1094 // BUG: need to disallow returns and throws
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1095 if (fensure)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1096 { fensure = fensure.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1097 labtab = null; // so body can't refer to labels
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1098 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1099
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1100 if (!global.params.useOut)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1101 { fensure = null; // discard
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1102 vresult = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1103 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1104
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1105 // Postcondition invariant
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1106 if (addPostInvariant())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1107 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1108 Expression e = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1109 if (isCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1110 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1111 // Call invariant directly only if it exists
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1112 InvariantDeclaration inv = ad.inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1113 ClassDeclaration cd = ad.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1114
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1115 while (!inv && cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1116 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1117 cd = cd.baseClass;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1118 if (!cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1119 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1120 inv = cd.inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1121 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1122 if (inv)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1123 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1124 e = new DsymbolExp(Loc(0), inv);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1125 e = new CallExp(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1126 e = e.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1127 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1128 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1129 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1130 { // Call invariant virtually
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1131 Expression v = new ThisExp(Loc(0));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1132 v.type = vthis.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1133 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1134 if (ad.isStructDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1135 v = v.addressOf(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1136 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1137 e = new AssertExp(Loc(0), v);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1138 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1139 if (e)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1140 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1141 ExpStatement s = new ExpStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1142 if (fensure)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1143 fensure = new CompoundStatement(Loc(0), s, fensure);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1144 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1145 fensure = s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1146 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1147 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1148
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1149 if (fensure)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1150 { returnLabel = new LabelDsymbol(Id.returnLabel);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1151 LabelStatement ls = new LabelStatement(Loc(0), Id.returnLabel, fensure);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1152 ls.isReturnLabel = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1153 returnLabel.statement = ls;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1154 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1155 sc2 = sc2.pop();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1156 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1157
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1158 sc2.incontract--;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1159
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1160 if (fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1161 { ClassDeclaration cd = isClassMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1162
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1163 /* If this is a class constructor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1164 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1165 if (isCtorDeclaration() && cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1166 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1167 for (int i = 0; i < cd.fields.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1168 { VarDeclaration v = cast(VarDeclaration)cd.fields.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1169
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1170 v.ctorinit = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1171 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1172 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1173
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1174 if (inferRetType || f.retStyle() != RET.RETstack)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1175 nrvo_can = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1176
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1177 fbody = fbody.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1178 if (!fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1179 fbody = new CompoundStatement(Loc(0), new Statements());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1180
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1181 if (inferRetType)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1182 { // If no return type inferred yet, then infer a void
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1183 if (!type.nextOf())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1184 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1185 (cast(TypeFunction)type).next = Type.tvoid;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1186 type = type.semantic(loc, sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1187 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1188 f = cast(TypeFunction)type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1189 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1190
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1191 if (isStaticCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1192 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1193 /* It's a static constructor. Ensure that all
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1194 * ctor consts were initialized.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1195 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1196
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1197 Dsymbol p = toParent();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1198 ScopeDsymbol add = p.isScopeDsymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1199 if (!add)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1200 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1201 error("static constructor can only be member of struct/class/module, not %s %s", p.kind(), p.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1202 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1203 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1204 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1205 for (int i = 0; i < add.members.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1206 { Dsymbol s = cast(Dsymbol)add.members.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1207
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1208 s.checkCtorConstInit();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1209 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1210 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1211 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1212
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1213 if (isCtorDeclaration() && cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1214 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1215 //printf("callSuper = x%x\n", sc2.callSuper);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1216
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1217 // Verify that all the ctorinit fields got initialized
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1218 if (!(sc2.callSuper & CSX.CSXthis_ctor))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1219 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1220 for (int i = 0; i < cd.fields.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1221 { VarDeclaration v = cast(VarDeclaration)cd.fields.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1222
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1223 if (v.ctorinit == 0 && v.isCtorinit())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1224 error("missing initializer for final field %s", v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1225 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1226 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1227
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1228 if (!(sc2.callSuper & CSX.CSXany_ctor) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1229 cd.baseClass && cd.baseClass.ctor)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1230 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1231 sc2.callSuper = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1232
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1233 // Insert implicit super() at start of fbody
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1234 Expression e1 = new SuperExp(Loc(0));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1235 Expression e = new CallExp(Loc(0), e1);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1236
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1237 e = e.trySemantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1238 if (!e)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1239 error("no match for implicit super() call in constructor");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1240 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1241 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1242 Statement s = new ExpStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1243 fbody = new CompoundStatement(Loc(0), s, fbody);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1244 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1245 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1246 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1247 else if (fes)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1248 { // For foreach(){} body, append a return 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1249 Expression e = new IntegerExp(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1250 Statement s = new ReturnStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1251 fbody = new CompoundStatement(Loc(0), fbody, s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1252 assert(!returnLabel);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1253 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1254 else if (!hasReturnExp && type.nextOf().ty != TY.Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1255 error("expected to return a value of type %s", type.nextOf().toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1256 else if (!inlineAsm)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1257 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1258 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1259 BE blockexit = fbody ? fbody.blockExit() : BE.BEfallthru;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1260 if (f.isnothrow && blockexit & BE.BEthrow)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1261 error("'%s' is nothrow yet may throw", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1262
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1263 int offend = blockexit & BE.BEfallthru;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1264 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1265 if (type.nextOf().ty == TY.Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1266 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1267 if (offend && isMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1268 { // Add a return 0; statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1269 Statement s = new ReturnStatement(Loc(0), new IntegerExp(0));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1270 fbody = new CompoundStatement(Loc(0), fbody, s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1271 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1272 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1273 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1274 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1275 if (offend)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1276 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1277 Expression e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1278 version (DMDV1) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1279 warning(loc, "no return exp; or assert(0); at end of function");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1280 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1281 error("no return exp; or assert(0); at end of function");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1282 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1283 if (global.params.useAssert &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1284 !global.params.useInline)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1285 { /* Add an assert(0, msg); where the missing return
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1286 * should be.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1287 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1288 e = new AssertExp(
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1289 endloc,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1290 new IntegerExp(0),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1291 new StringExp(loc, "missing return expression")
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1292 );
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1293 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1294 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1295 e = new HaltExp(endloc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1296
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1297 e = new CommaExp(Loc(0), e, type.nextOf().defaultInit(Loc(0)));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1298 e = e.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1299 Statement s = new ExpStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1300 fbody = new CompoundStatement(Loc(0), fbody, s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1301 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1302 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1303 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1304 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1305
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1306 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1307 Statements a = new Statements();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1308
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1309 // Merge in initialization of 'out' parameters
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1310 if (parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1311 { for (size_t i = 0; i < parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1312 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1313 VarDeclaration v = cast(VarDeclaration)parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1314 if (v.storage_class & STC.STCout)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1315 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1316 assert(v.init);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1317 ExpInitializer ie = v.init.isExpInitializer();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1318 assert(ie);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1319 a.push(cast(void*)new ExpStatement(Loc(0), ie.exp));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1320 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1321 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1322 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1323
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1324 if (argptr)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1325 { // Initialize _argptr to point past non-variadic arg
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1326 version (IN_GCC) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1327 // Handled in FuncDeclaration.toObjFile
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1328 v_argptr = argptr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1329 v_argptr.init = new VoidInitializer(loc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1330 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1331 Expression e1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1332 Expression e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1333 Type t = argptr.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1334 VarDeclaration p;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1335 uint offset;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1336
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1337 e1 = new VarExp(Loc(0), argptr);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1338 if (parameters && parameters.dim)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1339 p = cast(VarDeclaration)parameters.data[parameters.dim - 1];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1340 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1341 p = v_arguments; // last parameter is _arguments[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1342 offset = cast(uint)p.type.size(); ///
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1343 offset = (offset + 3) & ~3; // assume stack aligns on 4
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1344 e = new SymOffExp(Loc(0), p, offset);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1345 e = new AssignExp(Loc(0), e1, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1346 e.type = t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1347 a.push(cast(void*)new ExpStatement(Loc(0), e));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1348 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1349 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1350
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1351 if (_arguments)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1352 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1353 /* Advance to elements[] member of TypeInfo_Tuple with:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1354 * _arguments = v_arguments.elements;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1355 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1356 Expression e = new VarExp(Loc(0), v_arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1357 e = new DotIdExp(Loc(0), e, Id.elements);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1358 Expression e1 = new VarExp(Loc(0), _arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1359 e = new AssignExp(Loc(0), e1, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1360 e.op = TOK.TOKconstruct;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1361 e = e.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1362 a.push(cast(void*)new ExpStatement(Loc(0), e));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1363 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1364
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1365 // Merge contracts together with body into one compound statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1366
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1367 version (_DH) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1368 if (frequire && global.params.useIn)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1369 { frequire.incontract = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1370 a.push(frequire);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1371 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1372 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1373 if (frequire && global.params.useIn)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1374 a.push(cast(void*)frequire);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1375 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1376
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1377 // Precondition invariant
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1378 if (addPreInvariant())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1379 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1380 Expression e = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1381 if (isDtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1382 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1383 // Call invariant directly only if it exists
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1384 InvariantDeclaration inv = ad.inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1385 ClassDeclaration cd = ad.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1386
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1387 while (!inv && cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1388 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1389 cd = cd.baseClass;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1390 if (!cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1391 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1392 inv = cd.inv;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1393 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1394 if (inv)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1395 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1396 e = new DsymbolExp(Loc(0), inv);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1397 e = new CallExp(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1398 e = e.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1399 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1400 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1401 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1402 { // Call invariant virtually
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1403 Expression v = new ThisExp(Loc(0));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1404 v.type = vthis.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1405 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1406 if (ad.isStructDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1407 v = v.addressOf(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1408 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1409 Expression se = new StringExp(Loc(0), "null this");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1410 se = se.semantic(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1411 se.type = Type.tchar.arrayOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1412 e = new AssertExp(loc, v, se);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1413 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1414 if (e)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1415 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1416 ExpStatement s = new ExpStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1417 a.push(cast(void*)s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1418 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1419 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1420
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1421 if (fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1422 a.push(cast(void*)fbody);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1423
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1424 if (fensure)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1425 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1426 a.push(cast(void*)returnLabel.statement);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1427
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1428 if (type.nextOf().ty != TY.Tvoid)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1429 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1430 // Create: return vresult;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1431 assert(vresult);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1432 Expression e = new VarExp(Loc(0), vresult);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1433 if (tintro)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1434 { e = e.implicitCastTo(sc, tintro.nextOf());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1435 e = e.semantic(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1436 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1437 ReturnStatement s = new ReturnStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1438 a.push(cast(void*)s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1439 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1440 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1441
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1442 fbody = new CompoundStatement(Loc(0), a);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1443 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1444 /* Append destructor calls for parameters as finally blocks.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1445 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1446 if (parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1447 { for (size_t i = 0; i < parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1448 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1449 VarDeclaration v = cast(VarDeclaration)parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1450
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1451 if (v.storage_class & (STC.STCref | STC.STCout))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1452 continue;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1453
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1454 /* Don't do this for static arrays, since static
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1455 * arrays are called by reference. Remove this
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1456 * when we change them to call by value.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1457 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1458 if (v.type.toBasetype().ty == TY.Tsarray)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1459 continue;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1460
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1461 Expression e = v.callAutoDtor(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1462 if (e)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1463 { Statement s = new ExpStatement(Loc(0), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1464 s = s.semantic(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1465 if (fbody.blockExit() == BE.BEfallthru)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1466 fbody = new CompoundStatement(Loc(0), fbody, s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1467 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1468 fbody = new TryFinallyStatement(Loc(0), fbody, s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1469 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1470 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1471 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1472 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1473
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1474 static if (true) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1475 if (isSynchronized())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1476 { /* Wrap the entire function body in a synchronized statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1477 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1478 ClassDeclaration cd = parent.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1479 if (cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1480 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1481 ///version (TARGET_WINDOS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1482 if (/*config.flags2 & CFG2.CFG2seh &&*/ // always on for WINDOS
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1483 !isStatic() && !fbody.usesEH())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1484 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1485 /* The back end uses the "jmonitor" hack for syncing;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1486 * no need to do the sync at this level.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1487 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1488 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1489 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1490 ///}
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1491 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1492 Expression vsync;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1493 if (isStatic())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1494 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1495 // The monitor is in the ClassInfo
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1496 vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id.classinfo_);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1497 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1498 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1499 { // 'this' is the monitor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1500 vsync = new VarExp(loc, vthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1501 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1502 fbody = new PeelStatement(fbody); // don't redo semantic()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1503 fbody = new SynchronizedStatement(loc, vsync, fbody);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1504 fbody = fbody.semantic(sc2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1505 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1506 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1507 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1508 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1509 error("synchronized function %s must be a member of a class", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1510 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1511 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1512 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1513 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1514
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1515 sc2.callSuper = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1516 sc2.pop();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1517 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1518 semanticRun = 4;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1519 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1520
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1521 // called from semantic3
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1522 void varArgs(Scope sc, TypeFunction, ref VarDeclaration, ref VarDeclaration)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1523 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1524 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1525 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1526
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1527 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1528 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1529 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1530 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1531
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1532 void bodyToCBuffer(OutBuffer buf, HdrGenState* hgs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1533 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1534 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1535 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1536
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1537 /****************************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1538 * Determine if 'this' overrides fd.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1539 * Return true if it does.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1540 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1541 bool overrides(FuncDeclaration fd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1542 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1543 bool result = false;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1544
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1545 if (fd.ident == ident)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1546 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1547 int cov = type.covariant(fd.type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1548 if (cov)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1549 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1550 ClassDeclaration cd1 = toParent().isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1551 ClassDeclaration cd2 = fd.toParent().isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1552
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1553 if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1554 result = true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1555 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1556 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1557 return result;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1558 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1559
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1560 /*************************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1561 * Find index of function in vtbl[0..dim] that
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1562 * this function overrides.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1563 * Returns:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1564 * -1 didn't find one
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1565 * -2 can't determine because of forward references
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1566 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1567 int findVtblIndex(Array vtbl, int dim)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1568 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1569 for (int vi = 0; vi < dim; vi++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1570 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1571 FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1572 if (fdv && fdv.ident is ident)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1573 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1574 int cov = type.covariant(fdv.type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1575 //printf("\tbaseclass cov = %d\n", cov);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1576 switch (cov)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1577 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1578 case 0: // types are distinct
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1579 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1580
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1581 case 1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1582 return vi;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1583
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1584 case 2:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1585 //type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1586 //fdv.type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1587 //printf("%s %s\n", type.deco, fdv.type.deco);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1588 error("of type %s overrides but is not covariant with %s of type %s",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1589 type.toChars(), fdv.toPrettyChars(), fdv.type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1590 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1591
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1592 case 3:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1593 return -2; // forward references
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1594 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1595 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1596 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1597 return -1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1598 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1599
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1600 /****************************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1601 * Overload this FuncDeclaration with the new one f.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1602 * Return !=0 if successful; i.e. no conflict.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1603 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1604 bool overloadInsert(Dsymbol s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1605 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1606 FuncDeclaration f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1607 AliasDeclaration a;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1608
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1609 //writef("FuncDeclaration.overloadInsert(%s)\n", s.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1610 a = s.isAliasDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1611 if (a)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1612 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1613 if (overnext)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1614 return overnext.overloadInsert(a);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1615
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1616 if (!a.aliassym && a.type.ty != TY.Tident && a.type.ty != TY.Tinstance)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1617 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1618 //writef("\ta = '%s'\n", a.type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1619 return false;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1620 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1621 overnext = a;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1622 //printf("\ttrue: no conflict\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1623 return true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1624 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1625 f = s.isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1626 if (!f)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1627 return false;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1628
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1629 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1630 /* Disable this check because:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1631 * const void foo();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1632 * semantic() isn't run yet on foo(), so the const hasn't been
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1633 * applied yet.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1634 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1635 if (type)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1636 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1637 printf("type = %s\n", type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1638 printf("f.type = %s\n", f.type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1639 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1640 if (type && f.type && // can be null for overloaded constructors
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1641 f.type.covariant(type) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1642 f.type.mod == type.mod &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1643 !isFuncAliasDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1644 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1645 //printf("\tfalse: conflict %s\n", kind());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1646 return false;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1647 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1648 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1649
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1650 if (overnext)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1651 return overnext.overloadInsert(f);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1652 overnext = f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1653 //printf("\ttrue: no conflict\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1654 return true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1655 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1656
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1657 FuncDeclaration overloadExactMatch(Type t)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1658 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1659 Param1 p;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1660 p.t = t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1661 p.f = null;
17
ddae60498573 Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
Robert Clipsham <robert@octarineparrot.com>
parents: 14
diff changeset
1662 overloadApply(this, &p.fp1, &p);
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1663 return p.f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1664 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1665
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1666 FuncDeclaration overloadResolve(Loc loc, Expression ethis, Expressions arguments, int flags = 0)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1667 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1668 TypeFunction tf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1669 Match m;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1670
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1671 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1672 printf("FuncDeclaration.overloadResolve('%s')\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1673 if (arguments)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1674 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1675 int i;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1676
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1677 for (i = 0; i < arguments.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1678 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1679 Expression arg;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1680
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1681 arg = cast(Expression)arguments.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1682 assert(arg.type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1683 printf("\t%s: ", arg.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1684 arg.type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1685 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1686 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1687 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1688
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1689 m.last = MATCH.MATCHnomatch;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1690 overloadResolveX(&m, this, ethis, arguments);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1691
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1692 if (m.count == 1) // exactly one match
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1693 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1694 return m.lastf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1695 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1696 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1697 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1698 scope OutBuffer buf = new OutBuffer();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1699
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1700 buf.writeByte('(');
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1701 if (arguments)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1702 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1703 HdrGenState hgs;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1704
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1705 argExpTypesToCBuffer(buf, arguments, &hgs);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1706 buf.writeByte(')');
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1707 if (ethis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1708 ethis.type.modToBuffer(buf);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1709 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1710 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1711 buf.writeByte(')');
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1712
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1713 if (m.last == MATCH.MATCHnomatch)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1714 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1715 if (flags & 1) // if do not print error messages
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1716 return null; // no match
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1717
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1718 tf = cast(TypeFunction)type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1719
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1720 scope OutBuffer buf2 = new OutBuffer();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1721 tf.modToBuffer(buf2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1722
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1723 //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1724 error(loc, "%s%s is not callable using argument types %s",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1725 Argument.argsTypesToChars(tf.parameters, tf.varargs),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1726 buf2.toChars(),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1727 buf.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1728 return m.anyf; // as long as it's not a FuncAliasDeclaration
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1729 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1730 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1731 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1732 static if (true) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1733 TypeFunction t1 = cast(TypeFunction)m.lastf.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1734 TypeFunction t2 = cast(TypeFunction)m.nextf.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1735
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1736 error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1737 buf.toChars(),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1738 m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1739 m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1740 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1741 error(loc, "overloads %s and %s both match argument list for %s",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1742 m.lastf.type.toChars(),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1743 m.nextf.type.toChars(),
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1744 m.lastf.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1745 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1746 return m.lastf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1747 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1748 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1749 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1750
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1751 /*************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1752 * Determine partial specialization order of 'this' vs g.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1753 * This is very similar to TemplateDeclaration.leastAsSpecialized().
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1754 * Returns:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1755 * match 'this' is at least as specialized as g
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1756 * 0 g is more specialized than 'this'
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1757 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1758 MATCH leastAsSpecialized(FuncDeclaration g)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1759 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1760 version (LOG_LEASTAS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1761 printf("%s.leastAsSpecialized(%s)\n", toChars(), g.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1762 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1763
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1764 /* This works by calling g() with f()'s parameters, and
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1765 * if that is possible, then f() is at least as specialized
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1766 * as g() is.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1767 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1768
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1769 TypeFunction tf = cast(TypeFunction)type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1770 TypeFunction tg = cast(TypeFunction)g.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1771 size_t nfparams = Argument.dim(tf.parameters);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1772 size_t ngparams = Argument.dim(tg.parameters);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1773 MATCH match = MATCHexact;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1774
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1775 /* If both functions have a 'this' pointer, and the mods are not
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1776 * the same and g's is not const, then this is less specialized.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1777 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1778 if (needThis() && g.needThis())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1779 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1780 if (tf.mod != tg.mod)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1781 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1782 if (tg.mod == MODconst)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1783 match = MATCHconst;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1784 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1785 return MATCHnomatch;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1786 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1787 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1788
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1789 /* Create a dummy array of arguments out of the parameters to f()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1790 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1791 scope Expressions args = new Expressions();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1792 args.setDim(nfparams);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1793 for (int u = 0; u < nfparams; u++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1794 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1795 Argument p = Argument.getNth(tf.parameters, u);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1796 Expression e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1797 if (p.storageClass & (STCref | STCout))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1798 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1799 e = new IdentifierExp(Loc(0), p.ident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1800 e.type = p.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1801 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1802 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1803 e = p.type.defaultInit(Loc(0));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1804
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1805 args.data[u] = cast(void*)e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1806 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1807
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1808 MATCH m = cast(MATCH) tg.callMatch(null, args);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1809 if (m)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1810 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1811 /* A variadic parameter list is less specialized than a
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1812 * non-variadic one.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1813 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1814 if (tf.varargs && !tg.varargs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1815 goto L1; // less specialized
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1816
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1817 version (LOG_LEASTAS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1818 printf(" matches %d, so is least as specialized\n", m);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1819 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1820 return m;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1821 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1822 L1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1823 version (LOG_LEASTAS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1824 printf(" doesn't match, so is not as specialized\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1825 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1826 return MATCHnomatch;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1827 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1828
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1829 /********************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1830 * Labels are in a separate scope, one per function.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1831 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1832 LabelDsymbol searchLabel(Identifier ident)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1833 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1834 Dsymbol s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1835
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1836 if (!labtab)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1837 labtab = new DsymbolTable(); // guess we need one
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1838
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1839 s = labtab.lookup(ident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1840 if (!s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1841 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1842 s = new LabelDsymbol(ident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1843 labtab.insert(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1844 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1845
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1846 return cast(LabelDsymbol)s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1847 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1848
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1849 /****************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1850 * If non-static member function that has a 'this' pointer,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1851 * return the aggregate it is a member of.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1852 * Otherwise, return null.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1853 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1854 AggregateDeclaration isThis()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1855 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1856 AggregateDeclaration ad = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1857
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1858 //printf("+FuncDeclaration.isThis() '%s'\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1859 if ((storage_class & STC.STCstatic) == 0)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1860 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1861 ad = isMember2();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1862 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1863 //printf("-FuncDeclaration.isThis() %p\n", ad);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1864 return ad;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1865 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1866
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1867 AggregateDeclaration isMember2()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1868 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1869 AggregateDeclaration ad = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1870
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1871 //printf("+FuncDeclaration.isMember2() '%s'\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1872 for (Dsymbol s = this; s; s = s.parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1873 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1874 //printf("\ts = '%s', parent = '%s', kind = %s\n", s.toChars(), s.parent.toChars(), s.parent.kind());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1875 ad = s.isMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1876 if (ad)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1877 { //printf("test4\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1878 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1879 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1880 if (!s.parent || (!s.parent.isTemplateInstance()))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1881 { //printf("test5\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1882 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1883 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1884 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1885 //printf("-FuncDeclaration.isMember2() %p\n", ad);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1886 return ad;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1887 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1888
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1889 /*****************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1890 * Determine lexical level difference from 'this' to nested function 'fd'.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1891 * Error if this cannot call fd.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1892 * Returns:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1893 * 0 same level
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1894 * -1 increase nesting by 1 (fd is nested within 'this')
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1895 * >0 decrease nesting by number
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1896 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1897 int getLevel(Loc loc, FuncDeclaration fd) // lexical nesting level difference
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1898 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1899 int level;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1900 Dsymbol s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1901 Dsymbol fdparent;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1902
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1903 //printf("FuncDeclaration.getLevel(fd = '%s')\n", fd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1904 fdparent = fd.toParent2();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1905 if (fdparent == this)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1906 return -1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1907 s = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1908 level = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1909 while (fd != s && fdparent != s.toParent2())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1910 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1911 //printf("\ts = '%s'\n", s.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1912 FuncDeclaration thisfd = s.isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1913 if (thisfd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1914 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1915 if (!thisfd.isNested() && !thisfd.vthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1916 goto Lerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1917 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1918 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1919 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1920 AggregateDeclaration thiscd = s.isAggregateDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1921 if (thiscd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1922 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1923 if (!thiscd.isNested())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1924 goto Lerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1925 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1926 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1927 goto Lerr;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1928 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1929
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1930 s = s.toParent2();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1931 assert(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1932 level++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1933 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1934 return level;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1935
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1936 Lerr:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1937 error(loc, "cannot access frame of function %s", fd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1938 return 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1939 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1940
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1941 void appendExp(Expression e)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1942 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1943 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1944 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1945
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1946 void appendState(Statement s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1947 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1948 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1949 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1950
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1951 string mangle()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1952 out (result)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1953 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1954 assert(result.length > 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1955 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1956 body
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1957 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1958 if (isMain()) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1959 return "_Dmain";
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1960 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1961
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1962 if (isWinMain() || isDllMain() || ident == Id.tls_get_addr)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1963 return ident.toChars();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1964
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1965 assert(this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1966
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1967 return Declaration.mangle();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1968 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1969
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1970 string toPrettyChars()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1971 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1972 if (isMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1973 return "D main";
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1974 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1975 return Dsymbol.toPrettyChars();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1976 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1977
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1978 int isMain()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1979 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1980 return ident is Id.main && linkage != LINK.LINKc && !isMember() && !isNested();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1981 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1982
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1983 int isWinMain()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1984 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1985 //printf("FuncDeclaration::isWinMain() %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1986 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1987 int x = ident == Id.WinMain &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1988 linkage != LINK.LINKc && !isMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1989 printf("%s\n", x ? "yes" : "no");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1990 return x;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1991 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1992 return ident == Id.WinMain && linkage != LINK.LINKc && !isMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1993 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1994 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1995
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1996 int isDllMain()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1997 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1998 return ident == Id.DllMain && linkage != LINK.LINKc && !isMember();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1999 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2000
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2001 /**********************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2002 * Determine if function is a builtin one that we can
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2003 * evaluate at compile time.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2004 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2005 BUILTIN isBuiltin()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2006 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2007 static string FeZe = "FNaNbeZe"; // pure nothrow real function(real)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2008
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2009 //printf("FuncDeclaration::isBuiltin() %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2010 if (builtin == BUILTIN.BUILTINunknown)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2011 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2012 builtin = BUILTIN.BUILTINnot;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2013 if (parent && parent.isModule())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2014 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2015 // If it's in the std.math package
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2016 if (parent.ident == Id.math && parent.parent && parent.parent.ident == Id.std && !parent.parent.parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2017 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2018 //printf("deco = %s\n", type.deco);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2019 if (type.deco == FeZe)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2020 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2021 if (ident == Id.sin)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2022 builtin = BUILTIN.BUILTINsin;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2023 else if (ident == Id.cos)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2024 builtin = BUILTIN.BUILTINcos;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2025 else if (ident == Id.tan)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2026 builtin = BUILTIN.BUILTINtan;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2027 else if (ident == Id._sqrt)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2028 builtin = BUILTIN.BUILTINsqrt;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2029 else if (ident == Id.fabs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2030 builtin = BUILTIN.BUILTINfabs;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2031 //printf("builtin = %d\n", builtin);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2032 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2033 // if float or double versions
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2034 else if (type.deco == "FNaNbdZd" || type.deco == "FNaNbfZf")
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2035 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2036 if (ident == Id._sqrt)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2037 builtin = BUILTIN.BUILTINsqrt;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2038 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2039 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2040 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2041 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2042
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2043 return builtin;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2044 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2045
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2046 bool isExport()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2047 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2048 return protection == PROT.PROTexport;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2049 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2050
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2051 bool isImportedSymbol()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2052 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2053 //printf("isImportedSymbol()\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2054 //printf("protection = %d\n", protection);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2055 return (protection == PROT.PROTexport) && !fbody;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2056 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2057
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2058 bool isAbstract()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2059 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2060 return (storage_class & STC.STCabstract) != 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2061 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2062
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2063 bool isCodeseg()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2064 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2065 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2066 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2067
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2068 bool isOverloadable()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2069 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2070 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2071 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2072
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2073 bool isPure()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2074 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2075 //printf("FuncDeclaration::isPure() '%s'\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2076 assert(type.ty == TY.Tfunction);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2077 return (cast(TypeFunction)this.type).ispure;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2078 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2079
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2080 bool isNested()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2081 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2082 //if (!toParent())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2083 //printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2084 //printf("\ttoParent2() = '%s'\n", toParent2().toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2085 return ((storage_class & STC.STCstatic) == 0) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2086 (toParent2().isFuncDeclaration() !is null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2087 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2088
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2089 bool needThis()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2090 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2091 //printf("FuncDeclaration.needThis() '%s'\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2092 bool needThis = isThis() !is null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2093
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2094 //printf("\t%d\n", i);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2095 if (!needThis) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2096 if (auto fa = isFuncAliasDeclaration()) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2097 needThis = fa.funcalias.needThis();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2098 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2099 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2100
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2101 return needThis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2102 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2103
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2104 bool isVirtual()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2105 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2106 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2107 printf("FuncDeclaration.isVirtual(%s)\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2108 printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROT.PROTprivate, isCtorDeclaration(), linkage != LINK.LINKd);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2109 printf("result is %d\n",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2110 isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2111 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2112 return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2113 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2114
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2115 int isFinal()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2116 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2117 ClassDeclaration cd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2118 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2119 printf("FuncDeclaration.isFinal(%s)\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2120 printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROT.PROTprivate, isCtorDeclaration(), linkage != LINK.LINKd);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2121 printf("result is %d\n",
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2122 isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && (cd = toParent().isClassDeclaration()) !is null && cd.storage_class & STC.STCfinal);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2123 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2124 return isMember() && (Declaration.isFinal() || ((cd = toParent().isClassDeclaration()) !is null && cd.storage_class & STC.STCfinal));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2125 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2126
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2127 bool addPreInvariant()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2128 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2129 AggregateDeclaration ad = isThis();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2130 return (ad &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2131 //ad.isClassDeclaration() &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2132 global.params.useInvariants &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2133 (protection == PROT.PROTpublic || protection == PROT.PROTexport) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2134 !naked &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2135 ident !is Id.cpctor);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2136 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2137
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2138 bool addPostInvariant()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2139 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2140 AggregateDeclaration ad = isThis();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2141 return (ad && ad.inv &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2142 //ad.isClassDeclaration() &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2143 global.params.useInvariants &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2144 (protection == PROT.PROTpublic || protection == PROT.PROTexport) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2145 !naked &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2146 ident !is Id.cpctor);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2147 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2148
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2149 Expression interpret(InterState* istate, Expressions arguments, Expression thisexp = null)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2150 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2151 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2152 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2153
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2154 void inlineScan()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2155 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2156 InlineScanState iss;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2157
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2158 version (LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2159 printf("FuncDeclaration.inlineScan('%s')\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2160 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2161 ///memset(&iss, 0, sizeof(iss));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2162 iss.fd = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2163 if (fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2164 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2165 inlineNest++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2166 fbody = fbody.inlineScan(&iss);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2167 inlineNest--;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2168 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2169 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2170
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2171 int canInline(int hasthis, int hdrscan = 0)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2172 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2173 int cost;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2174
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2175 // #define CANINLINE_LOG 0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2176
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2177 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2178 printf("FuncDeclaration.canInline(hasthis = %d, '%s')\n", hasthis, toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2179 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2180
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2181 if (needThis() && !hasthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2182 return 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2183
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2184 if (inlineNest || (semanticRun < 3 && !hdrscan))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2185 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2186 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2187 printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2188 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2189 return 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2190 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2191
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2192 switch (inlineStatus)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2193 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2194 case ILS.ILSyes:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2195 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2196 printf("\t1: yes %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2197 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2198 return 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2199
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2200 case ILS.ILSno:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2201 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2202 printf("\t1: no %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2203 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2204 return 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2205
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2206 case ILS.ILSuninitialized:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2207 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2208
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2209 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2210 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2211 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2212
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2213 if (type)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2214 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2215 assert(type.ty == Tfunction);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2216 TypeFunction tf = cast(TypeFunction)type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2217 if (tf.varargs == 1) // no variadic parameter lists
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2218 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2219
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2220 /* Don't inline a function that returns non-void, but has
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2221 * no return expression.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2222 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2223 if (tf.next && tf.next.ty != Tvoid &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2224 !(hasReturnExp & 1) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2225 !hdrscan)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2226 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2227 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2228 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2229 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2230 CtorDeclaration ctor = isCtorDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2231 if (ctor && ctor.varargs == 1)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2232 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2233 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2234
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2235 if (
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2236 !fbody ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2237 !hdrscan &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2238 (
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2239 /// static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2240 /// isCtorDeclaration() || // cannot because need to convert:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2241 /// // return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2242 /// // to:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2243 /// // return this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2244 /// }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2245 isSynchronized() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2246 isImportedSymbol() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2247 /// version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2248 closureVars.dim || // no nested references to this frame
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2249 /// } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2250 /// nestedFrameRef || // no nested references to this frame
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2251 /// }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2252 (isVirtual() && !isFinal())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2253 ))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2254 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2255 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2256 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2257
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2258 /* If any parameters are Tsarray's (which are passed by reference)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2259 * or out parameters (also passed by reference), don't do inlining.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2260 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2261 if (parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2262 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2263 for (int i = 0; i < parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2264 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2265 VarDeclaration v = cast(VarDeclaration)parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2266 if (v.isOut() || v.isRef() || v.type.toBasetype().ty == Tsarray)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2267 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2268 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2269 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2270
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2271 InlineCostState ics;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2272 ///memset(&ics, 0, sizeof(ics));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2273 ics.hasthis = hasthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2274 ics.fd = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2275 ics.hdrscan = hdrscan;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2276 cost = fbody.inlineCost(&ics);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2277 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2278 printf("cost = %d\n", cost);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2279 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2280 if (cost >= COST_MAX)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2281 goto Lno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2282
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2283 if (!hdrscan) // Don't scan recursively for header content scan
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2284 inlineScan();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2285
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2286 Lyes:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2287 if (!hdrscan) // Don't modify inlineStatus for header content scan
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2288 inlineStatus = ILS.ILSyes;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2289 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2290 printf("\t2: yes %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2291 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2292 return 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2293
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2294 Lno:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2295 if (!hdrscan) // Don't modify inlineStatus for header content scan
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2296 inlineStatus = ILS.ILSno;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2297 version (CANINLINE_LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2298 printf("\t2: no %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2299 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2300 return 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2301 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2302
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2303 Expression doInline(InlineScanState* iss, Expression ethis, Array arguments)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2304 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2305 InlineDoState ids = new InlineDoState();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2306 DeclarationExp de;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2307 Expression e = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2308
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2309 version (LOG) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2310 printf("FuncDeclaration.doInline('%s')\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2311 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2312
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2313 ///memset(&ids, 0, sizeof(ids));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2314 ids.parent = iss.fd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2315
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2316 // Set up vthis
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2317 if (ethis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2318 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2319 VarDeclaration vthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2320 ExpInitializer ei;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2321 VarExp ve;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2322
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2323 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2324 if (ethis.type.ty == Tpointer)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2325 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2326 Type t = ethis.type.nextOf();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2327 ethis = new PtrExp(ethis.loc, ethis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2328 ethis.type = t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2329 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2330 ei = new ExpInitializer(ethis.loc, ethis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2331
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2332 vthis = new VarDeclaration(ethis.loc, ethis.type, Id.This, ei);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2333 if (ethis.type.ty != Tclass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2334 vthis.storage_class = STCref;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2335 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2336 vthis.storage_class = STCin;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2337 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2338 if (ethis.type.ty != Tclass && ethis.type.ty != Tpointer)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2339 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2340 ethis = ethis.addressOf(null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2341 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2342
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2343 ei = new ExpInitializer(ethis.loc, ethis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2344
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2345 vthis = new VarDeclaration(ethis.loc, ethis.type, Id.This, ei);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2346 vthis.storage_class = STCin;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2347 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2348 vthis.linkage = LINKd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2349 vthis.parent = iss.fd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2350
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2351 ve = new VarExp(vthis.loc, vthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2352 ve.type = vthis.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2353
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2354 ei.exp = new AssignExp(vthis.loc, ve, ethis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2355 ei.exp.type = ve.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2356 version (STRUCTTHISREF) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2357 if (ethis.type.ty != Tclass)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2358 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2359 /* This is a reference initialization, not a simple assignment.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2360 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2361 ei.exp.op = TOKconstruct;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2362 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2363 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2364
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2365 ids.vthis = vthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2366 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2367
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2368 // Set up parameters
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2369 if (ethis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2370 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2371 e = new DeclarationExp(Loc(0), ids.vthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2372 e.type = Type.tvoid;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2373 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2374
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2375 if (arguments && arguments.dim)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2376 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2377 assert(parameters.dim == arguments.dim);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2378
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2379 for (int i = 0; i < arguments.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2380 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2381 VarDeclaration vfrom = cast(VarDeclaration)parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2382 VarDeclaration vto;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2383 Expression arg = cast(Expression)arguments.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2384 ExpInitializer ei;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2385 VarExp ve;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2386
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2387 ei = new ExpInitializer(arg.loc, arg);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2388
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2389 vto = new VarDeclaration(vfrom.loc, vfrom.type, vfrom.ident, ei);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2390 vto.storage_class |= vfrom.storage_class & (STCin | STCout | STClazy | STCref);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2391 vto.linkage = vfrom.linkage;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2392 vto.parent = iss.fd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2393 //printf("vto = '%s', vto.storage_class = x%x\n", vto.toChars(), vto.storage_class);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2394 //printf("vto.parent = '%s'\n", iss.fd.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2395
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2396 ve = new VarExp(vto.loc, vto);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2397 //ve.type = vto.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2398 ve.type = arg.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2399
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2400 ei.exp = new AssignExp(vto.loc, ve, arg);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2401 ei.exp.type = ve.type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2402 //ve.type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2403 //arg.type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2404 //ei.exp.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2405
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2406 ids.from.push(cast(void*)vfrom);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2407 ids.to.push(cast(void*)vto);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2408
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2409 de = new DeclarationExp(Loc(0), vto);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2410 de.type = Type.tvoid;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2411
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2412 e = Expression.combine(e, de);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2413 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2414 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2415
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2416 inlineNest++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2417 Expression eb = fbody.doInline(ids);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2418 inlineNest--;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2419 //eb.type.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2420 //eb.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2421 //eb.dump(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2422 return Expression.combine(e, eb);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2423 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2424
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2425 string kind()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2426 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2427 return "function";
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2428 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2429
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2430 void toDocBuffer(OutBuffer buf)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2431 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2432 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2433 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2434
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2435 FuncDeclaration isUnique()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2436 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2437 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2438 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2439
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2440 /*******************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2441 * Look at all the variables in this function that are referenced
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2442 * by nested functions, and determine if a closure needs to be
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2443 * created for them.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2444 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2445 bool needsClosure()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2446 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2447 /* Need a closure for all the closureVars[] if any of the
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2448 * closureVars[] are accessed by a
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2449 * function that escapes the scope of this function.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2450 * We take the conservative approach and decide that any function that:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2451 * 1) is a virtual function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2452 * 2) has its address taken
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2453 * 3) has a parent that escapes
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2454 *
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2455 * Note that since a non-virtual function can be called by
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2456 * a virtual one, if that non-virtual function accesses a closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2457 * var, the closure still has to be taken. Hence, we check for isThis()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2458 * instead of isVirtual(). (thanks to David Friedman)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2459 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2460
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2461 //printf("FuncDeclaration.needsClosure() %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2462 for (int i = 0; i < closureVars.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2463 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2464 VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2465 assert(v.isVarDeclaration());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2466 //printf("\tv = %s\n", v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2467
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2468 for (int j = 0; j < v.nestedrefs.dim; j++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2469 { FuncDeclaration f = cast(FuncDeclaration)v.nestedrefs.data[j];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2470 assert(f != this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2471
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2472 //printf("\t\tf = %s, %d, %p, %d\n", f.toChars(), f.isVirtual(), f.isThis(), f.tookAddressOf);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2473 if (f.isThis() || f.tookAddressOf)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2474 goto Lyes; // assume f escapes this function's scope
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2475
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2476 // Look to see if any parents of f that are below this escape
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2477 for (Dsymbol s = f.parent; s && s !is this; s = s.parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2478 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2479 f = s.isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2480 if (f && (f.isThis() || f.tookAddressOf)) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2481 goto Lyes;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2482 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2483 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2484 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2485 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2486 return false;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2487
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2488 Lyes:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2489 //printf("\tneeds closure\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2490 return true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2491 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2492
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2493 static FuncDeclaration genCfunc(Type treturn, string name)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2494 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2495 return genCfunc(treturn, Lexer.idPool(name));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2496 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2497
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2498 /**********************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2499 * Generate a FuncDeclaration for a runtime library function.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2500 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2501 static FuncDeclaration genCfunc(Type treturn, Identifier id)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2502 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2503 FuncDeclaration fd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2504 TypeFunction tf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2505 Dsymbol s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2506 static DsymbolTable st = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2507
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2508 //printf("genCfunc(name = '%s')\n", id.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2509 //printf("treturn\n\t"); treturn.print();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2510
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2511 // See if already in table
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2512 if (!st)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2513 st = new DsymbolTable();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2514
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2515 s = st.lookup(id);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2516 if (s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2517 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2518 fd = s.isFuncDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2519 assert(fd);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2520 assert(fd.type.nextOf().equals(treturn));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2521 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2522 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2523 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2524 tf = new TypeFunction(null, treturn, 0, LINK.LINKc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2525 fd = new FuncDeclaration(Loc(0), Loc(0), id, STCstatic, tf);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2526 fd.protection = PROT.PROTpublic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2527 fd.linkage = LINK.LINKc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2528
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2529 st.insert(fd);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2530 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2531 return fd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2532 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2533
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2534 Symbol* toSymbol()
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2535 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2536 if (!csym)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2537 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2538 Symbol* s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2539 TYPE* t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2540 string id;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2541
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2542 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2543 id = ident.toChars();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2544 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2545 id = mangle();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2546 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2547 //writef("FuncDeclaration.toSymbol(%s %s)\n", kind(), toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2548 //writef("\tid = '%s'\n", id);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2549 //writef("\ttype = %s\n", type.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2550 s = symbol_calloc(toStringz(id));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2551 slist_add(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2552
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2553 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2554 s.prettyIdent = toStringz(toPrettyChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2555 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2556 symbol_func(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2557 func_t* f = s.Sfunc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2558 if (isVirtual())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2559 f.Fflags |= F.Fvirtual;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2560 else if (isMember2())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2561 f.Fflags |= F.Fstatic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2562 f.Fstartline.Slinnum = loc.linnum;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2563 f.Fstartline.Sfilename = cast(char*)toStringz(loc.filename);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2564 if (endloc.linnum)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2565 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2566 f.Fendline.Slinnum = endloc.linnum;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2567 f.Fendline.Sfilename = cast(char*)toStringz(endloc.filename);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2568 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2569 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2570 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2571 f.Fendline.Slinnum = loc.linnum;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2572 f.Fendline.Sfilename = cast(char*)toStringz(loc.filename);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2573 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2574 t = type.toCtype();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2575 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2576
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2577 mangle_t msave = t.Tmangle;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2578 if (isMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2579 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2580 t.Tty = TYM.TYnfunc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2581 t.Tmangle = mTYman.mTYman_c;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2582 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2583 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2584 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2585 switch (linkage)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2586 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2587 case LINK.LINKwindows:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2588 t.Tmangle = mTYman.mTYman_std;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2589 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2590
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2591 case LINK.LINKpascal:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2592 t.Tty = TYM.TYnpfunc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2593 t.Tmangle = mTYman.mTYman_pas;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2594 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2595
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2596 case LINK.LINKc:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2597 t.Tmangle = mTYman.mTYman_c;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2598 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2599
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2600 case LINK.LINKd:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2601 t.Tmangle = mTYman.mTYman_d;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2602 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2603
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2604 case LINK.LINKcpp:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2605 { t.Tmangle = mTYman.mTYman_cpp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2606 version (TARGET_WINDOS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2607 if (isThis())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2608 t.Tty = TYM.TYmfunc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2609 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2610 s.Sflags |= SFL.SFLpublic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2611 Dsymbol parent = toParent();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2612 ClassDeclaration cd = parent.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2613 if (cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2614 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2615 .type* tt = cd.type.toCtype();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2616 s.Sscope = tt.Tnext.Ttag;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2617 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2618 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2619 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2620 default:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2621 writef("linkage = %d\n", linkage);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2622 assert(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2623 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2624 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2625 if (msave)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2626 assert(msave == t.Tmangle);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2627 //printf("Tty = %x, mangle = x%x\n", t.Tty, t.Tmangle);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2628 t.Tcount++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2629 s.Stype = t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2630 //s.Sfielddef = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2631
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2632 csym = s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2633 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2634 return csym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2635 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2636
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2637 Symbol* toThunkSymbol(int offset) // thunk version
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2638 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2639 Symbol *sthunk;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2640
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2641 toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2642
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2643 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2644 char *id;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2645 char *n;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2646 type *t;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2647
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2648 n = sym.Sident;
14
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2649 version (Bug4054)
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2650 id = cast(char*) GC.malloc(8 + 5 + strlen(n) + 1);
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2651 else
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2652 id = cast(char*) alloca(8 + 5 + strlen(n) + 1);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2653 sprintf(id, "_thunk%d__%s", offset, n);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2654 s = symbol_calloc(id);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2655 slist_add(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2656 s.Stype = csym.Stype;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2657 s.Stype.Tcount++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2658 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2659 sthunk = symbol_generate(SCstatic, csym.Stype);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2660 sthunk.Sflags |= SFLimplem;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2661 cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2662 return sthunk;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2663 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2664
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2665 void toObjFile(int multiobj) // compile to .obj file
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2666 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2667 Symbol* s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2668 func_t* f;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2669 Symbol* senter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2670 Symbol* sexit;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2671
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2672 FuncDeclaration func = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2673 ClassDeclaration cd = func.parent.isClassDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2674 int reverse;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2675 int i;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2676 int has_arguments;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2677
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2678 //printf("FuncDeclaration.toObjFile(%p, %s.%s)\n", func, parent.toChars(), func.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2679 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2680 //printf("line = %d\n",func.getWhere() / LINEINC);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2681 EEcontext ee = env.getEEcontext();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2682 if (ee.EEcompile == 2)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2683 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2684 if (ee.EElinnum < (func.getWhere() / LINEINC) ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2685 ee.EElinnum > (func.endwhere / LINEINC)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2686 )
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2687 return; // don't compile this function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2688 ee.EEfunc = func.toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2689 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2690 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2691
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2692 if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2693 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2694 obj_append(this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2695 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2696 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2697
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2698 if (semanticRun >= 5) // if toObjFile() already run
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2699 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2700
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2701 semanticRun = 5;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2702
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2703 if (!func.fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2704 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2705 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2706 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2707
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2708 if (func.isUnitTestDeclaration() && !global.params.useUnitTests)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2709 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2710
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2711 if (global.params.verbose)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2712 writef("function %s\n",func.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2713
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2714 s = func.toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2715 f = s.Sfunc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2716
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2717 version (TARGET_OSX) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2718 s.Sclass = SC.SCcomdat;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2719 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2720 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2721 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2722
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2723 for (Dsymbol p = parent; p; p = p.parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2724 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2725 if (p.isTemplateInstance())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2726 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2727 s.Sclass = SC.SCcomdat;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2728 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2729 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2730 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2731
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2732 if (isNested())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2733 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2734 // if (!(config.flags3 & CFG3pic))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2735 // s.Sclass = SCstatic;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2736 f.Fflags3 |= F3.Fnested;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2737 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2738 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2739 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2740 const(char)* libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2741
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2742 // Pull in RTL startup code
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2743 if (func.isMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2744 { objextdef("_main");
22
fd4acc376c45 Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents: 17
diff changeset
2745 version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2746 obj_ehsections(); // initialize exception handling sections
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2747 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2748 objextdef("__acrtused_con");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2749 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2750 obj_includelib(libname);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2751 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2752 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2753 else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2754 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2755
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2756 else if (func.isWinMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2757 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2758 objextdef("__acrtused");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2759 obj_includelib(libname);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2760 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2761 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2762
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2763 // Pull in RTL startup code
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2764 else if (func.isDllMain())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2765 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2766 objextdef("__acrtused_dll");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2767 obj_includelib(libname);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2768 s.Sclass = SC.SCglobal;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2769 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2770 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2771
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2772 cstate.CSpsymtab = &f.Flocsym;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2773
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2774 // Find module m for this function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2775 Module m = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2776 for (Dsymbol p = parent; p; p = p.parent)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2777 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2778 m = p.isModule();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2779 if (m)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2780 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2781 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2782
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2783 IRState irs = IRState(m, func);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2784 Array deferToObj = new Array(); // write these to OBJ file later
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2785 irs.deferToObj = deferToObj;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2786
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2787 TypeFunction tf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2788 RET retmethod;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2789 Symbol* shidden = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2790 Symbol* sthis = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2791 tym_t tyf;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2792
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2793 tyf = tybasic(s.Stype.Tty);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2794 //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2795 reverse = tyrevfunc(s.Stype.Tty);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2796
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2797 assert(func.type.ty == TY.Tfunction);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2798 tf = cast(TypeFunction)(func.type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2799 has_arguments = (tf.linkage == LINK.LINKd) && (tf.varargs == 1);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2800 retmethod = tf.retStyle();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2801 if (retmethod == RET.RETstack)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2802 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2803 // If function returns a struct, put a pointer to that
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2804 // as the first argument
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2805 .type* thidden = tf.next.pointerTo().toCtype();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2806 char hiddenparam[5+4+1];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2807 static int hiddenparami; // how many we've generated so far
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2808
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2809 sprintf(hiddenparam.ptr, "__HID%d".ptr, ++hiddenparami);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2810 shidden = symbol_name(hiddenparam.ptr, SC.SCparameter, thidden);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2811 shidden.Sflags |= SFL.SFLtrue | SFL.SFLfree;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2812
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2813 version (DMDV1) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2814 bool nestedref = func.nrvo_can && func.nrvo_var && func.nrvo_var.nestedref;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2815 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2816 bool nestedref = func.nrvo_can && func.nrvo_var && (func.nrvo_var.nestedrefs.dim != 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2817 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2818 if (nestedref) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2819 type_setcv(&shidden.Stype, shidden.Stype.Tty | mTY.mTYvolatile);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2820 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2821
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2822 irs.shidden = shidden;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2823 this.shidden = shidden;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2824 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2825
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2826 if (vthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2827 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2828 assert(!vthis.csym);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2829 sthis = vthis.toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2830 irs.sthis = sthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2831 if (!(f.Fflags3 & F3.Fnested))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2832 f.Fflags3 |= F3.Fmember;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2833 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2834
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2835 Symbol** params;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2836 uint pi;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2837
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2838 // Estimate number of parameters, pi
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2839 pi = (v_arguments !is null);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2840 if (parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2841 pi += parameters.dim;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2842
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2843 // Allow extra 2 for sthis and shidden
14
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2844 version (Bug4054)
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2845 params = cast(Symbol**)GC.malloc((pi + 2) * (Symbol*).sizeof);
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
2846 else
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2847 params = cast(Symbol**)alloca((pi + 2) * (Symbol*).sizeof);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2848
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2849 // Get the actual number of parameters, pi, and fill in the params[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2850 pi = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2851 if (v_arguments)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2852 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2853 params[pi] = v_arguments.toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2854 pi += 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2855 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2856 if (parameters)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2857 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2858 for (i = 0; i < parameters.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2859 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2860 VarDeclaration v = cast(VarDeclaration)parameters.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2861 debug {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2862 if (v.csym)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2863 writef("parameter '%s'\n", v.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2864 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2865 assert(!v.csym);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2866 params[pi + i] = v.toSymbol();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2867 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2868 pi += i;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2869 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2870
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2871 if (reverse)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2872 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2873 // Reverse params[] entries
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2874 for (i = 0; i < pi/2; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2875 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2876 Symbol* sptmp = params[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2877 params[i] = params[pi - 1 - i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2878 params[pi - 1 - i] = sptmp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2879 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2880 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2881
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2882 if (shidden)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2883 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2884 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2885 // shidden becomes last parameter
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2886 params[pi] = shidden;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2887 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2888 // shidden becomes first parameter
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2889 memmove(params + 1, params, pi * (*params).sizeof);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2890 params[0] = shidden;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2891 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2892 pi++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2893 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2894
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2895
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2896 if (sthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2897 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2898 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2899 // sthis becomes last parameter
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2900 params[pi] = sthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2901 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2902 // sthis becomes first parameter
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2903 memmove(params + 1, params, pi * (*params).sizeof);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2904 params[0] = sthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2905 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2906 pi++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2907 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2908
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2909 if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2910 linkage != LINK.LINKd && shidden && sthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2911 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2912 /* swap shidden and sthis
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2913 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2914 Symbol* sp = params[0];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2915 params[0] = params[1];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2916 params[1] = sp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2917 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2918
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2919 for (i = 0; i < pi; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2920 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2921 Symbol *sp = params[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2922 sp.Sclass = SC.SCparameter;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2923 sp.Sflags &= ~SFL.SFLspill;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2924 sp.Sfl = FL.FLpara;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2925 symbol_add(sp);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2926 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2927
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2928 // First parameter goes in register
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2929 if (pi)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2930 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2931 Symbol* sp = params[0];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2932 if ((tyf == TYM.TYjfunc || tyf == TYM.TYmfunc) && type_jparam(sp.Stype))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2933 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2934 sp.Sclass = SC.SCfastpar;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2935 sp.Spreg = (tyf == TYM.TYjfunc) ? REG.AX : REG.CX;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2936 sp.Sfl = FL.FLauto;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2937 //printf("'%s' is SCfastpar\n",sp.Sident);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2938 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2939 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2940
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2941 if (func.fbody)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2942 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2943 block* b;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2944 Blockx bx;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2945 Statement sbody;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2946
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2947 localgot = null;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2948
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2949 sbody = func.fbody;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2950 ///memset(&bx, 0, (bx).sizeof);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2951 bx.startblock = block_calloc();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2952 bx.curblock = bx.startblock;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2953 bx.funcsym = s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2954 bx.scope_index = -1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2955 bx.classdec = cd;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2956 bx.member = func;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2957 bx.module_ = getModule();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2958 irs.blx = &bx;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2959
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2960 buildClosure(&irs);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2961
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2962 static if (false) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2963 if (func.isSynchronized())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2964 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2965 if (cd)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2966 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2967 elem *esync;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2968 if (func.isStatic())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2969 { // monitor is in ClassInfo
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2970 esync = el_ptr(cd.toSymbol());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2971 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2972 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2973 { // 'this' is the monitor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2974 esync = el_var(sthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2975 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2976
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2977 if (func.isStatic() || sbody.usesEH() ||
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2978 !(config.flags2 & CFG2.CFG2seh))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2979 { // BUG: what if frequire or fensure uses EH?
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2980
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2981 sbody = new SynchronizedStatement(func.loc, esync, sbody);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2982 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2983 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2984 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2985 version (TARGET_WINDOS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2986 if (config.flags2 & CFG2.CFG2seh)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2987 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2988 /* The "jmonitor" uses an optimized exception handling frame
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2989 * which is a little shorter than the more general EH frame.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2990 * It isn't strictly necessary.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2991 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2992 s.Sfunc.Fflags3 |= Fjmonitor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2993 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2994 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2995 el_free(esync);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2996 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2997 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2998 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2999 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3000 error("synchronized function %s must be a member of a class", func.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3001 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3002 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3003 } else version (TARGET_WINDOS) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3004 if (func.isSynchronized() && cd && config.flags2 & CFG2.CFG2seh &&
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3005 !func.isStatic() && !sbody.usesEH())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3006 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3007 /* The "jmonitor" hack uses an optimized exception handling frame
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3008 * which is a little shorter than the more general EH frame.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3009 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3010 s.Sfunc.Fflags3 |= F3.Fjmonitor;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3011 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3012 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3013
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3014 sbody.toIR(&irs);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3015 bx.curblock.BC = BC.BCret;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3016
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3017 f.Fstartblock = bx.startblock;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3018 // einit = el_combine(einit,bx.init);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3019
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3020 if (isCtorDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3021 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3022 assert(sthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3023 for (b = f.Fstartblock; b; b = b.Bnext)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3024 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3025 if (b.BC == BC.BCret)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3026 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3027 b.BC = BC.BCretexp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3028 b.Belem = el_combine(b.Belem, el_var(sthis));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3029 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3030 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3031 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3032 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3033
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3034 // If static constructor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3035 if (isStaticConstructor())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3036 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3037 elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3038 ector = el_combine(ector, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3039 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3040
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3041 // If static destructor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3042 if (isStaticDestructor())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3043 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3044 elem* e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3045
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3046 version (STATICCTOR) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3047 e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3048 ector = el_combine(ector, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3049 dtorcount++;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3050 } else {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3051 StaticDtorDeclaration f2 = isStaticDtorDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3052 assert(f2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3053 if (f2.vgate)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3054 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3055 /* Increment destructor's vgate at construction time
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3056 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3057 ectorgates.push(cast(void*)f2);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3058 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3059
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3060 e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3061 edtor = el_combine(e, edtor);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3062 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3063 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3064
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3065 // If unit test
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3066 if (isUnitTestDeclaration())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3067 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3068 elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3069 etest = el_combine(etest, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3070 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3071
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3072 if (global.errors)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3073 return;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3074
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3075 writefunc(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3076
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3077 if (isExport()) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3078 obj_export(s, Poffset);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3079 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3080
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3081 for (i = 0; i < irs.deferToObj.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3082 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3083 Dsymbol ss = cast(Dsymbol)irs.deferToObj.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3084 ss.toObjFile(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3085 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3086
22
fd4acc376c45 Implemented object file output and linking on linux.
Robert Clipsham <robert@octarineparrot.com>
parents: 17
diff changeset
3087 version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3088 // A hack to get a pointer to this function put in the .dtors segment
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3089 if (ident && ident.toChars() == "_STD") {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3090 obj_staticdtor(s);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3091 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3092 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3093 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3094 if (irs.startaddress)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3095 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3096 writef("Setting start address\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3097 obj_startaddress(irs.startaddress);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3098 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3099 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3100 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3101
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3102 int cvMember(ubyte* p)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3103 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3104 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3105 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3106
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3107 /*************************************
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3108 * Closures are implemented by taking the local variables that
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3109 * need to survive the scope of the function, and copying them
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3110 * into a gc allocated chuck of memory. That chunk, called the
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3111 * closure here, is inserted into the linked list of stack
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3112 * frames instead of the usual stack frame.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3113 *
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3114 * buildClosure() inserts code just after the function prolog
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3115 * is complete. It allocates memory for the closure, allocates
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3116 * a local variable (sclosure) to point to it, inserts into it
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3117 * the link to the enclosing frame, and copies into it the parameters
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3118 * that are referred to in nested functions.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3119 * In VarExp.toElem and SymOffExp.toElem, when referring to a
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3120 * variable that is in a closure, takes the offset from sclosure rather
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3121 * than from the frame pointer.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3122 *
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3123 * getEthis() and NewExp.toElem need to use sclosure, if set, rather
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3124 * than the current frame pointer.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3125 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3126 void buildClosure(IRState* irs)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3127 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3128 if (needsClosure())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3129 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3130 // Generate closure on the heap
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3131 // BUG: doesn't capture variadic arguments passed to this function
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3132
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3133 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3134 /* BUG: doesn't handle destructors for the local variables.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3135 * The way to do it is to make the closure variables the fields
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3136 * of a class object:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3137 * class Closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3138 * { vtbl[]
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3139 * monitor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3140 * ptr to destructor
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3141 * sthis
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3142 * ... closure variables ...
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3143 * ~this() { call destructor }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3144 * }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3145 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3146 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3147 //printf("FuncDeclaration.buildClosure()\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3148 Symbol* sclosure;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3149 sclosure = symbol_name("__closptr".ptr, SC.SCauto, Type.tvoidptr.toCtype());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3150 sclosure.Sflags |= SFL.SFLtrue | SFL.SFLfree;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3151 symbol_add(sclosure);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3152 irs.sclosure = sclosure;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3153
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3154 uint offset = PTRSIZE; // leave room for previous sthis
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3155 for (int i = 0; i < closureVars.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3156 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3157 VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3158 assert(v.isVarDeclaration());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3159
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3160 version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3161 if (v.needsAutoDtor())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3162 v.error("has scoped destruction, cannot build closure");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3163 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3164 /* Align and allocate space for v in the closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3165 * just like AggregateDeclaration.addField() does.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3166 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3167 uint memsize;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3168 uint memalignsize;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3169 uint xalign;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3170 /// version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3171 if (v.storage_class & STC.STClazy)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3172 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3173 /* Lazy variables are really delegates,
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3174 * so give same answers that TypeDelegate would
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3175 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3176 memsize = PTRSIZE * 2;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3177 memalignsize = memsize;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3178 xalign = global.structalign;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3179 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3180 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3181 /// }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3182 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3183 memsize = cast(uint)v.type.size();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3184 memalignsize = v.type.alignsize();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3185 xalign = v.type.memalign(global.structalign);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3186 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3187 AggregateDeclaration.alignmember(xalign, memalignsize, &offset);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3188 v.offset = offset;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3189 offset += memsize;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3190
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3191 /* Can't do nrvo if the variable is put in a closure, since
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3192 * what the shidden points to may no longer exist.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3193 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3194 if (nrvo_can && nrvo_var == v)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3195 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3196 nrvo_can = 0;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3197 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3198 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3199 // offset is now the size of the closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3200
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3201 // Allocate memory for the closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3202 elem* e;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3203 e = el_long(TYM.TYint, offset);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3204 e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[RTLSYM.RTLSYM_ALLOCMEMORY]), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3205
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3206 // Assign block of memory to sclosure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3207 // sclosure = allocmemory(sz);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3208 e = el_bin(OPER.OPeq, TYM.TYvoid, el_var(sclosure), e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3209
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3210 // Set the first element to sthis
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3211 // *(sclosure + 0) = sthis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3212 elem* ethis;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3213 if (irs.sthis)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3214 ethis = el_var(irs.sthis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3215 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3216 ethis = el_long(TYM.TYnptr, 0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3217 elem *ex = el_una(OPER.OPind, TYM.TYnptr, el_var(sclosure));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3218 ex = el_bin(OPER.OPeq, TYM.TYnptr, ex, ethis);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3219 e = el_combine(e, ex);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3220
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3221 // Copy function parameters into closure
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3222 for (int i = 0; i < closureVars.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3223 { VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3224
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3225 if (!v.isParameter())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3226 continue;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3227 TYM tym = v.type.totym();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3228 if (v.type.toBasetype().ty == TY.Tsarray || v.isOut() || v.isRef())
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3229 tym = TYM.TYnptr; // reference parameters are just pointers
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3230 /// version (DMDV2) {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3231 else if (v.storage_class & STC.STClazy)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3232 tym = TYM.TYdelegate;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3233 /// }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3234 ex = el_bin(OPER.OPadd, TYM.TYnptr, el_var(sclosure), el_long(TYM.TYint, v.offset));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3235 ex = el_una(OPER.OPind, tym, ex);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3236 if (ex.Ety == TYM.TYstruct)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3237 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3238 ex.Enumbytes = cast(uint)v.type.size();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3239 ex = el_bin(OPER.OPstreq, tym, ex, el_var(v.toSymbol()));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3240 ex.Enumbytes = cast(uint)v.type.size();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3241 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3242 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3243 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3244 ex = el_bin(OPER.OPeq, tym, ex, el_var(v.toSymbol()));
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3245 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3246
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3247 e = el_combine(e, ex);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3248 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3249
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3250 block_appendexp(irs.blx.curblock, e);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3251 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3252 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3253
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
3254 FuncDeclaration isFuncDeclaration() { return this; }
14
2cc604139636 Implemented Linux support for ddmd. Some parts are a bit hacky to just "get it working", that said, druntime and phobos compile, and unittests pass.
Robert Clipsham <robert@octarineparrot.com>
parents: 0
diff changeset
3255 }