@@ -25,7 +25,7 @@ private module Ast implements AstSig<Location> {
2525
2626 class AstNode = ControlFlowElementOrCallable ;
2727
28- private predicate skipControlFlow ( AstNode e ) {
28+ additional predicate skipControlFlow ( AstNode e ) {
2929 e instanceof TypeAccess and
3030 not e instanceof TypeAccessPatternExpr
3131 or
@@ -82,13 +82,8 @@ private module Ast implements AstSig<Location> {
8282
8383 AstNode callableGetBody ( Callable c ) {
8484 not skipControlFlow ( result ) and
85- (
86- result = c .getBody ( ) or
87- result = c .( Constructor ) .getObjectInitializerCall ( ) or
88- result = c .( Constructor ) .getInitializer ( ) or
89- c .( ObjectInitMethod ) .initializes ( result ) or
90- Initializers:: staticMemberInitializer ( c , result )
91- )
85+ result = c .getBody ( ) and
86+ not c instanceof Constructor // handled in `callableGetBodyPart`
9287 }
9388
9489 class Stmt = CS:: Stmt ;
@@ -222,10 +217,21 @@ private module Ast implements AstSig<Location> {
222217 * Unlike the standard `Compilation` class, this class also supports buildless
223218 * extraction.
224219 */
225- private newtype CompilationExt =
220+ private newtype TCompilationExt =
226221 TCompilation ( Compilation c ) { not extractionIsStandalone ( ) } or
227222 TBuildless ( ) { extractionIsStandalone ( ) }
228223
224+ private class CompilationExt extends TCompilationExt {
225+ string toString ( ) {
226+ exists ( Compilation c |
227+ this = TCompilation ( c ) and
228+ result = c .toString ( )
229+ )
230+ or
231+ this = TBuildless ( ) and result = "buildless compilation"
232+ }
233+ }
234+
229235/** Gets the compilation that source file `f` belongs to. */
230236private CompilationExt getCompilation ( File f ) {
231237 exists ( Compilation c |
@@ -274,12 +280,13 @@ private module Initializers {
274280 /**
275281 * Gets the `i`th static member initializer expression for static constructor `staticCtor`.
276282 */
277- Expr initializedStaticMemberOrder ( Constructor staticCtor , int i ) {
283+ Expr initializedStaticMemberOrder ( Constructor staticCtor , CompilationExt comp , int i ) {
278284 result =
279285 rank [ i + 1 ] ( Expr init , Location l , string filepath , int startline , int startcolumn |
280286 staticMemberInitializer ( staticCtor , init ) and
281287 l = init .getLocation ( ) and
282- l .hasLocationInfo ( filepath , startline , startcolumn , _, _)
288+ l .hasLocationInfo ( filepath , startline , startcolumn , _, _) and
289+ getCompilation ( l .getFile ( ) ) = comp
283290 |
284291 init order by startline , startcolumn , filepath
285292 )
@@ -301,17 +308,6 @@ private module Initializers {
301308 ae0 order by startline , startcolumn , filepath
302309 )
303310 }
304-
305- /**
306- * Gets the last member initializer expression for object initializer method `obinit`
307- * in compilation `comp`.
308- */
309- AssignExpr lastInitializer ( ObjectInitMethod obinit , CompilationExt comp ) {
310- exists ( int i |
311- result = initializedInstanceMemberOrder ( obinit , comp , i ) and
312- not exists ( initializedInstanceMemberOrder ( obinit , comp , i + 1 ) )
313- )
314- }
315311}
316312
317313private module Exceptions {
@@ -424,6 +420,54 @@ private module Input implements InputSig1, InputSig2 {
424420 l = TLblGoto ( n .( LabelStmt ) .getLabel ( ) )
425421 }
426422
423+ pragma [ noinline]
424+ private MethodCall getObjectInitializerCall ( Constructor ctor , CompilationExt comp ) {
425+ result = ctor .getObjectInitializerCall ( ) and
426+ comp = getCompilation ( result .getFile ( ) )
427+ }
428+
429+ pragma [ noinline]
430+ private ConstructorInitializer getInitializer ( Constructor ctor , CompilationExt comp ) {
431+ result = ctor .getInitializer ( ) and
432+ comp = getCompilation ( result .getFile ( ) )
433+ }
434+
435+ pragma [ noinline]
436+ private Ast:: AstNode getBody ( Constructor ctor , CompilationExt comp ) {
437+ result = ctor .getBody ( ) and
438+ comp = getCompilation ( result .getFile ( ) )
439+ }
440+
441+ class CallableBodyPartContext = CompilationExt ;
442+
443+ Ast:: AstNode callableGetBodyPart ( Callable c , CallableBodyPartContext ctx , int index ) {
444+ not Ast:: skipControlFlow ( result ) and
445+ (
446+ result = Initializers:: initializedInstanceMemberOrder ( c , ctx , index )
447+ or
448+ result =
449+ rank [ index + 1 ] ( Ast:: AstNode child , int i , int j |
450+ i = 0 and
451+ child = Initializers:: initializedStaticMemberOrder ( c , ctx , j )
452+ or
453+ i = 1 and
454+ j = 0 and
455+ child = getObjectInitializerCall ( c , ctx )
456+ or
457+ i = 2 and
458+ (
459+ j = 0 and
460+ child = getInitializer ( c , ctx )
461+ or
462+ j = 1 and
463+ child = getBody ( c , ctx )
464+ )
465+ |
466+ child order by i , j
467+ )
468+ )
469+ }
470+
427471 private Expr getQualifier ( QualifiableExpr qe ) {
428472 result = qe .getQualifier ( ) or
429473 result = qe .( ExtensionMethodCall ) .getArgument ( 0 )
@@ -474,80 +518,7 @@ private module Input implements InputSig1, InputSig2 {
474518 )
475519 }
476520
477- pragma [ noinline]
478- private MethodCall getObjectInitializerCall ( Constructor ctor , CompilationExt comp ) {
479- result = ctor .getObjectInitializerCall ( ) and
480- comp = getCompilation ( result .getFile ( ) )
481- }
482-
483- pragma [ noinline]
484- private ConstructorInitializer getInitializer ( Constructor ctor , CompilationExt comp ) {
485- result = ctor .getInitializer ( ) and
486- comp = getCompilation ( result .getFile ( ) )
487- }
488-
489- pragma [ noinline]
490- private Ast:: AstNode getBody ( Constructor ctor , CompilationExt comp ) {
491- result = ctor .getBody ( ) and
492- comp = getCompilation ( result .getFile ( ) )
493- }
494-
495521 predicate step ( PreControlFlowNode n1 , PreControlFlowNode n2 ) {
496- exists ( Constructor ctor |
497- n1 .( EntryNodeImpl ) .getEnclosingCallable ( ) = ctor and
498- if Initializers:: staticMemberInitializer ( ctor , _)
499- then n2 .isBefore ( Initializers:: initializedStaticMemberOrder ( ctor , 0 ) )
500- else
501- if exists ( ctor .getObjectInitializerCall ( ) )
502- then n2 .isBefore ( ctor .getObjectInitializerCall ( ) )
503- else
504- if exists ( ctor .getInitializer ( ) )
505- then n2 .isBefore ( ctor .getInitializer ( ) )
506- else n2 .isBefore ( ctor .getBody ( ) )
507- or
508- exists ( int i | n1 .isAfter ( Initializers:: initializedStaticMemberOrder ( ctor , i ) ) |
509- n2 .isBefore ( Initializers:: initializedStaticMemberOrder ( ctor , i + 1 ) )
510- or
511- not exists ( Initializers:: initializedStaticMemberOrder ( ctor , i + 1 ) ) and
512- n2 .isBefore ( ctor .getBody ( ) )
513- )
514- or
515- exists ( CompilationExt comp |
516- n1 .isAfter ( getObjectInitializerCall ( ctor , comp ) ) and
517- if exists ( getInitializer ( ctor , comp ) )
518- then n2 .isBefore ( getInitializer ( ctor , comp ) )
519- else
520- // This is only relevant in the context of compilation errors, since
521- // normally the existence of an object initializer call implies the
522- // existence of an initializer.
523- if exists ( getBody ( ctor , comp ) )
524- then n2 .isBefore ( getBody ( ctor , comp ) )
525- else n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
526- or
527- n1 .isAfter ( getInitializer ( ctor , comp ) ) and
528- if exists ( getBody ( ctor , comp ) )
529- then n2 .isBefore ( getBody ( ctor , comp ) )
530- else n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
531- )
532- or
533- n1 .isAfter ( ctor .getBody ( ) ) and
534- n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = ctor
535- )
536- or
537- exists ( ObjectInitMethod obinit |
538- n1 .( EntryNodeImpl ) .getEnclosingCallable ( ) = obinit and
539- n2 .isBefore ( Initializers:: initializedInstanceMemberOrder ( obinit , _, 0 ) )
540- or
541- exists ( CompilationExt comp , int i |
542- // Flow from one member initializer to the next
543- n1 .isAfter ( Initializers:: initializedInstanceMemberOrder ( obinit , comp , i ) ) and
544- n2 .isBefore ( Initializers:: initializedInstanceMemberOrder ( obinit , comp , i + 1 ) )
545- )
546- or
547- n1 .isAfter ( Initializers:: lastInitializer ( obinit , _) ) and
548- n2 .( NormalExitNodeImpl ) .getEnclosingCallable ( ) = obinit
549- )
550- or
551522 exists ( QualifiableExpr qe | qe .isConditional ( ) |
552523 n1 .isBefore ( qe ) and n2 .isBefore ( getQualifier ( qe ) )
553524 or
0 commit comments