@@ -24,7 +24,11 @@ private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
24
24
*/
25
25
TranslatedExpr getTranslatedExpr ( Expr expr ) {
26
26
result .getExpr ( ) = expr and
27
- result .producesExprResult ( )
27
+ result .producesExprResult ( ) and
28
+ // When a constructor call is needed, we fetch it manually.
29
+ // This is because of how we translate object creations: the translated expression
30
+ // and the translated constructor call are attached to the same element.
31
+ ( expr instanceof ObjectCreation implies not result instanceof TranslatedConstructorCall )
28
32
}
29
33
30
34
/**
@@ -481,11 +485,7 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
481
485
}
482
486
483
487
override TranslatedElement getChild ( int id ) {
484
- exists ( AssignExpr assign |
485
- result = getTranslatedExpr ( expr .getChild ( id ) ) and
486
- expr .getAChild ( ) = assign and
487
- assign .getIndex ( ) = id
488
- )
488
+ result = getTranslatedExpr ( expr .getMemberInitializer ( id ) )
489
489
}
490
490
491
491
override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
@@ -499,9 +499,57 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
499
499
)
500
500
}
501
501
502
- override Instruction getTargetAddress ( ) { result = this .getParent ( ) .getInstruction ( NewObjTag ( ) ) }
502
+ override Instruction getTargetAddress ( ) {
503
+ // The target address is the address of the newly allocated object,
504
+ // which can be retrieved from the parent `TranslatedObjectCreation`.
505
+ result = this .getParent ( ) .getInstruction ( NewObjTag ( ) )
506
+ }
507
+
508
+ override Type getTargetType ( ) {
509
+ result = this .getParent ( ) .getInstruction ( NewObjTag ( ) ) .getResultType ( )
510
+ }
511
+ }
512
+
513
+ class TranslatedCollectionInitializer extends TranslatedNonConstantExpr , InitializationContext {
514
+ override CollectionInitializer expr ;
515
+
516
+ override Instruction getResult ( ) { none ( ) }
517
+
518
+ override Instruction getFirstInstruction ( ) { result = this .getChild ( 0 ) .getFirstInstruction ( ) }
519
+
520
+ override predicate hasInstruction (
521
+ Opcode opcode , InstructionTag tag , Type resultType , boolean isLValue
522
+ ) {
523
+ none ( )
524
+ }
525
+
526
+ override TranslatedElement getChild ( int id ) {
527
+ result = getTranslatedExpr ( expr .getElementInitializer ( id ) )
528
+ }
529
+
530
+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
531
+
532
+ override Instruction getChildSuccessor ( TranslatedElement child ) {
533
+ exists ( int index |
534
+ child = this .getChild ( index ) and
535
+ (
536
+ result = this .getChild ( index + 1 ) .getFirstInstruction ( )
537
+ or
538
+ not exists ( this .getChild ( index + 1 ) ) and
539
+ result = this .getParent ( ) .getChildSuccessor ( this )
540
+ )
541
+ )
542
+ }
543
+
544
+ override Instruction getTargetAddress ( ) {
545
+ // The target address is the address of the newly allocated object,
546
+ // which can be retrieved from the parent `TranslatedObjectCreation`.
547
+ result = this .getParent ( ) .getInstruction ( NewObjTag ( ) )
548
+ }
503
549
504
- override Type getTargetType ( ) { none ( ) }
550
+ override Type getTargetType ( ) {
551
+ result = this .getParent ( ) .getInstruction ( NewObjTag ( ) ) .getResultType ( )
552
+ }
505
553
}
506
554
507
555
/**
@@ -1918,3 +1966,88 @@ class TranslatedDelegateCall extends TranslatedNonConstantExpr {
1918
1966
result = DelegateElements:: getInvoke ( expr )
1919
1967
}
1920
1968
}
1969
+
1970
+ /**
1971
+ * Represents the IR translation of creation expression. Can be the translation of an
1972
+ * `ObjectCreation` or a `DelegateCreation`.
1973
+ * The `NewObj` instruction denotes the fact that during initialization a new
1974
+ * object is allocated, which is then initialized by the constructor.
1975
+ */
1976
+ abstract class TranslatedCreation extends TranslatedCoreExpr , TTranslatedCreationExpr ,
1977
+ ConstructorCallContext {
1978
+ TranslatedCreation ( ) { this = TTranslatedCreationExpr ( expr ) }
1979
+
1980
+ override TranslatedElement getChild ( int id ) {
1981
+ id = 0 and result = this .getConstructorCall ( )
1982
+ or
1983
+ id = 1 and result = this .getInitializerExpr ( )
1984
+ }
1985
+
1986
+ override predicate hasInstruction (
1987
+ Opcode opcode , InstructionTag tag , Type resultType , boolean isLValue
1988
+ ) {
1989
+ // Instruction that allocated space for a new object,
1990
+ // and returns its address
1991
+ tag = NewObjTag ( ) and
1992
+ opcode instanceof Opcode:: NewObj and
1993
+ resultType = expr .getType ( ) and
1994
+ isLValue = false
1995
+ }
1996
+
1997
+ final override Instruction getFirstInstruction ( ) { result = this .getInstruction ( NewObjTag ( ) ) }
1998
+
1999
+ override Instruction getResult ( ) { result = getInstruction ( NewObjTag ( ) ) }
2000
+
2001
+ override Instruction getReceiver ( ) { result = getInstruction ( NewObjTag ( ) ) }
2002
+
2003
+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
2004
+ kind instanceof GotoEdge and
2005
+ tag = NewObjTag ( ) and
2006
+ result = this .getConstructorCall ( ) .getFirstInstruction ( )
2007
+ }
2008
+
2009
+ override Instruction getChildSuccessor ( TranslatedElement child ) {
2010
+ (
2011
+ child = this .getConstructorCall ( ) and
2012
+ if exists ( this .getInitializerExpr ( ) )
2013
+ then result = this .getInitializerExpr ( ) .getFirstInstruction ( )
2014
+ else result = this .getParent ( ) .getChildSuccessor ( this )
2015
+ )
2016
+ or
2017
+ child = this .getInitializerExpr ( ) and
2018
+ result = this .getParent ( ) .getChildSuccessor ( this )
2019
+ }
2020
+
2021
+ abstract TranslatedElement getConstructorCall ( ) ;
2022
+
2023
+ abstract TranslatedExpr getInitializerExpr ( ) ;
2024
+ }
2025
+
2026
+ /**
2027
+ * Represents the IR translation of an `ObjectCreation`.
2028
+ */
2029
+ class TranslatedObjectCreation extends TranslatedCreation {
2030
+ override ObjectCreation expr ;
2031
+
2032
+ override TranslatedExpr getInitializerExpr ( ) { result = getTranslatedExpr ( expr .getInitializer ( ) ) }
2033
+
2034
+ override TranslatedConstructorCall getConstructorCall ( ) {
2035
+ // Since calls are also expressions, we can't
2036
+ // use the predicate getTranslatedExpr (since that would
2037
+ // also return `this`).
2038
+ result .getAST ( ) = this .getAST ( )
2039
+ }
2040
+ }
2041
+
2042
+ /**
2043
+ * Represents the IR translation of a `DelegateCreation`.
2044
+ */
2045
+ class TranslatedDelegateCreation extends TranslatedCreation {
2046
+ override DelegateCreation expr ;
2047
+
2048
+ override TranslatedExpr getInitializerExpr ( ) { none ( ) }
2049
+
2050
+ override TranslatedElement getConstructorCall ( ) {
2051
+ result = DelegateElements:: getConstructor ( expr )
2052
+ }
2053
+ }
0 commit comments