@@ -24,7 +24,11 @@ private import semmle.code.csharp.ir.internal.IRCSharpLanguage as Language
2424 */
2525TranslatedExpr getTranslatedExpr ( Expr expr ) {
2626 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 )
2832}
2933
3034/**
@@ -481,11 +485,7 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
481485 }
482486
483487 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 ) )
489489 }
490490
491491 override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
@@ -499,9 +499,57 @@ class TranslatedObjectInitializerExpr extends TranslatedNonConstantExpr, Initial
499499 )
500500 }
501501
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+ }
503549
504- override Type getTargetType ( ) { none ( ) }
550+ override Type getTargetType ( ) {
551+ result = this .getParent ( ) .getInstruction ( NewObjTag ( ) ) .getResultType ( )
552+ }
505553}
506554
507555/**
@@ -1918,3 +1966,88 @@ class TranslatedDelegateCall extends TranslatedNonConstantExpr {
19181966 result = DelegateElements:: getInvoke ( expr )
19191967 }
19201968}
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