@@ -29,6 +29,10 @@ import dmd.globals;
2929import dmd.mangle;
3030import dmd.dscope;
3131import dmd.dsymbol;
32+ import dmd.attribsem;
33+ import dmd.expression;
34+ import dmd.id;
35+ import dmd.timetrace;
3236import core.stdc.stdio ;
3337import core.stdc.string ;
3438
@@ -78,6 +82,7 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
7882 import dmd.dfa.fast.statement;
7983 import dmd.dfa.fast.analysis;
8084 import dmd.dfa.fast.report;
85+ import dmd.dfa.utils;
8186
8287 if (fd.skipCodegen)
8388 {
@@ -95,11 +100,23 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
95100 }
96101
97102 // Use these if statements for debugging specific things.
98- // if (fd.ident.toString != "checkFloatInit5 ") return;
99- // if (!(fd.ident.toString == "replaceReferenceDefinition " || fd.ident.toString == "extractReferences ")) return;
103+ // if (fd.ident.toString != "escapeToGlobalSystem2 ") return;
104+ // if (!(fd.ident.toString == "escapeByRef2 " || fd.ident.toString == "escapeByRef3 ")) return;
100105 // if (fd.loc.linnum != 54) return;
101106 // if (fd.getModule.ident.toString != "start") return;
102- // if (strcmp(mangleExact(fd), "_D4core9exception15ArraySliceError6__ctorMFNaNbNiNfmmmAyamC6object9ThrowableZCQCyQCwQCp") != 0) return;
107+ // if (strcmp(mangleExact(fd), "_D5ocean4util9container5cache16ExpiringLRUCache__TQvTSQCaQBxQBvQBo20ExpiredCacheReloader__TQzTSQDpQDmQDkQDd25ExpiredCacheReloader_test7TrivialZQCz10CacheValueZQFa19getExpiringOrCreateMFmJbbZPQFi") != 0) return;
108+ // if (!(strcmp(mangleExact(fd), "?visit@DeduceType@deduceType@@UEAAXPEAVType@@@Z") == 0 || fd.ident.toString == "deduceWildHelper") )return;
109+
110+ // used in CI to skip tests that do need to error
111+ version (all )
112+ {
113+ if (fd.getModule.ident.toString == " testassert" )
114+ return ;
115+ else if (fd.getModule.ident.toString == " xtest46" )
116+ return ;
117+ else if (fd.getModule.ident.toString == " xtest46_gc" )
118+ return ;
119+ }
103120
104121 // Protect functions based upon safetiness of it.
105122 // It may be desirable to disable some behaviors in @system code, or completely.
@@ -118,6 +135,13 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
118135 DFAReporter reporter;
119136
120137 dfaCommon.allocator.dfaCommon = &dfaCommon;
138+ dfaCommon.currentFunction = fd;
139+
140+ if (auto ag = fd.isThis)
141+ {
142+ if (ag.isClassDeclaration)
143+ dfaCommon.isCurrentFunctionClassConstructor = fd.ident is Id.ctor;
144+ }
121145
122146 stmtWalker.dfaCommon = &dfaCommon;
123147 expWalker.dfaCommon = &dfaCommon;
@@ -133,6 +157,49 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
133157 analyzer.reporter = &reporter;
134158 reporter.errorSink = global.errorSink;
135159
160+ bool errorsPrinted;
161+
162+ void printOnError ()
163+ {
164+ if (errorsPrinted)
165+ return ;
166+ errorsPrinted = true ;
167+
168+ dfaCommon.printIfStructure((ref OutBuffer ob, scope void delegate (const (char )* ) prefix) {
169+ prefix(" " );
170+ ob.printf(" function dfa %s : %s = %s at %s\n " , fd.getModule.ident.toChars,
171+ mangleExact(fd), fd.toFullSignature, fd.loc.toChars);
172+
173+ dfaCommon.allocator.allVariables((DFAVar* var) {
174+ prefix(" var" );
175+ ob.printf(" %p base1=%p, base2=%p, dereferenceVar=%p, lifeTimeDepth=%d, writeCount=%d, unmodel=%d, isScope=%d, isByRef=%d, mayEscapeInitialValue=%d" ,
176+ var, var.base1, var.base2, var.dereferenceVar, var.lifeTimeDepth,
177+ var.writeCount, var.unmodellable, var.isScope, var.isByRef,
178+ var.mayEscapeInitialValue);
179+
180+ if (var.var ! is null )
181+ {
182+ ob.printf(" , `%s` at " , var.var.ident.toChars);
183+ appendLoc(ob, var.var.loc);
184+ }
185+
186+ ob.printf(" \n " );
187+ });
188+ dfaCommon.allocator.allObjects((DFAObject* obj) {
189+ prefix(" object" );
190+ ob.printf(" %p base1=%p, base2=%p, storageFor=%p, derivedFrom=%p, inCell=%p, constrainedBy=%p, mayNotBeExactPointer=%d, minimumDeclaredAtDepth=%d, onTheStack=%d, lifeTimeUnderstood=%d, delayOnReadErrorOfEscape=%d\n " ,
191+ obj, obj.base1, obj.base2, obj.storageFor, obj.derivedFrom,
192+ obj.inCell, obj.constrainedBy, obj.mayNotBeExactPointer, obj.minimumDeclaredAtDepth,
193+ obj.onTheStack, obj.lifeTimeUnderstood, obj.delayOnReadErrorOfEscape);
194+ });
195+ });
196+
197+ dfaCommon.printIfStructure((ref OutBuffer ob, scope PrintPrefixType prefix) {
198+ if (fd.parametersDFAInfo ! is null )
199+ printDFAParameters(fd.parametersDFAInfo);
200+ });
201+ }
202+
136203 dfaCommon.printIfStructure((ref OutBuffer ob, scope PrintPrefixType prefix) {
137204 ob.printf(" ============================== %s : %s = %s at " ,
138205 fd.getModule.ident.toChars, mangleExact (fd), fd.toFullSignature);
@@ -151,13 +218,6 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
151218 }
152219 }
153220
154- version (none )
155- {
156- printf(" function s %s : %s = %s at %s\n " , fd.getModule.ident.toChars,
157- mangleExact(fd), fd.toFullSignature, fd.loc.toChars);
158- fflush(stdout);
159- }
160-
161221 version (none )
162222 {
163223 import dmd.hdrgen;
@@ -169,20 +229,146 @@ void fastDFA(FuncDeclaration fd, Scope* sc)
169229 printf(buf.extractChars);
170230 }
171231
172- stmtWalker.start(fd);
232+ int currentErrors = global.errors;
233+
234+ try
235+ {
236+ timeTraceBeginEvent(TimeTraceEventType.dfa);
237+ stmtWalker.start(fd);
238+ }
239+ finally
240+ {
241+ timeTraceEndEvent(TimeTraceEventType.dfa, fd);
242+ }
243+
244+ version (all )
245+ {
246+ if (currentErrors != global.errors)
247+ printOnError;
248+ }
173249
174250 version (none )
251+ printOnError;
252+
253+ version (all )
175254 {
176- printf(" function e %s : %s = %s at %s\n " , fd.getModule.ident.toChars,
177- mangleExact(fd), fd.toFullSignature, fd.loc.toChars);
178- fflush(stdout);
255+ if (checkEscapes(fd, sc))
256+ printOnError;
179257 }
258+ }
180259
181- dfaCommon.printIfStructure((ref OutBuffer ob, scope PrintPrefixType prefix) {
182- ob.printf(" ------------------------------ %s : %s = %s at " ,
183- fd.getModule.ident.toChars, mangleExact (fd), fd.toFullSignature);
260+ bool checkEscapes (FuncDeclaration fd, Scope* sc)
261+ {
262+ import dmd.dfa.utils;
263+ import dmd.printast;
184264
185- appendLoc(ob, fd.loc);
186- ob.writestring(" \n " );
265+ if (fd.getModule.ident.toString != " __fastdfa_escape_test" )
266+ return false ;
267+
268+ Expression[] expecteds;
269+ bool found, error;
270+
271+ foreachUda(fd, sc, (Expression uda) {
272+ if (auto sl = uda.isStructLiteralExp)
273+ {
274+ ArrayLiteralExp al;
275+
276+ if (sl.sd.ident.toString() == " __FastDFAEscapeTest" )
277+ {
278+ if ((al = (* sl.elements)[0 ].isArrayLiteralExp) ! is null )
279+ {
280+ if (al.elements ! is null )
281+ expecteds = (* al.elements)[];
282+ }
283+
284+ found = true ;
285+ }
286+ }
287+
288+ return 0 ;
187289 });
290+
291+ if (found)
292+ {
293+ struct TestParam
294+ {
295+ bool present;
296+ bool escapeIntoNothing;
297+ bool escapeIntoUnknown;
298+ ParameterDFAInfo.Inferrable inferrable;
299+ }
300+
301+ TestParam nextTestParam ()
302+ {
303+ if (expecteds.length == 0 )
304+ return TestParam (false );
305+
306+ TestParam ret = TestParam(true );
307+
308+ StructLiteralExp sl = expecteds[0 ].isStructLiteralExp;
309+ expecteds = expecteds[1 .. $];
310+ if (sl is null || sl.elements is null )
311+ return TestParam (true );
312+ else if (sl.elements.length != 2 )
313+ return TestParam (false );
314+
315+ IntegerExp ie;
316+
317+ ret.escapeIntoNothing = (ie = (* sl.elements)[0 ].isIntegerExp) ! is null && ie.value == 1 ;
318+ ret.inferrable.escapesInto = (ie = (* sl.elements)[1 ].isIntegerExp) ! is null ? ie.value
319+ : 0 ;
320+
321+ return ret;
322+ }
323+
324+ void checkEscapeTest (ref ParameterDFAInfo paramDFAInfo)
325+ {
326+ TestParam tp = nextTestParam();
327+ if (! tp.present)
328+ {
329+ printf(" Missing UDA param info for param %d\n " , paramDFAInfo.parameterId);
330+ error = true ;
331+ return ;
332+ }
333+
334+ if (tp.escapeIntoNothing && ! paramDFAInfo.inferred.escapeIntoNothing)
335+ {
336+ printf(" UDA param info param %d missing escapeIntoNothing\n " ,
337+ paramDFAInfo.parameterId);
338+ error = true ;
339+ }
340+
341+ if (tp.inferrable.escapesInto != 0 && paramDFAInfo.inferred.escapesInto == 0 )
342+ {
343+ printf(" UDA param info param %d missing escapesInto\n " , paramDFAInfo.parameterId);
344+ error = true ;
345+ }
346+ else if (tp.inferrable.escapesInto != paramDFAInfo.inferred.escapesInto)
347+ {
348+ printf(" UDA param info param %d incorrect escapesInto\n " , paramDFAInfo.parameterId);
349+ error = true ;
350+ }
351+ }
352+
353+ if (fd.parametersDFAInfo.thisPointer.parameterId == - 2 )
354+ checkEscapeTest(fd.parametersDFAInfo.thisPointer);
355+
356+ foreach (ref paramDFAInfo; fd.parametersDFAInfo.parameters)
357+ checkEscapeTest(paramDFAInfo);
358+
359+ foreach (expected; expecteds)
360+ printAST(expected);
361+ }
362+ else
363+ error = true ;
364+
365+ if (error && ! fd.isGenerated && fd.loc.linnum > 999 )
366+ {
367+ printf(" %s test UDA: function %s : %s = %s at #%d\n " , found ? " Incompatible" .ptr : " Missing" .ptr,
368+ fd.getModule.ident.toChars, mangleExact (fd), fd.toFullSignature, fd.loc.linnum);
369+ printDFAParameters(fd.parametersDFAInfo);
370+ return true ;
371+ }
372+ else
373+ return false ;
188374}
0 commit comments