@@ -2833,6 +2833,68 @@ class TranslatedReuseExpr extends TranslatedNonConstantExpr {
28332833 }
28342834}
28352835
2836+ /**
2837+ * The IR translation of the destructor calls of the parent `TranslatedThrow`.
2838+ *
2839+ * This object does not itself generate the destructor calls. Instead, its
2840+ * children provide the actual calls, and this object ensures that we correctly
2841+ * exit with an `ExceptionEdge` after executing all the destructor calls.
2842+ */
2843+ class TranslatedDestructorsAfterThrow extends TranslatedElement , TTranslatedDestructorsAfterThrow {
2844+ ThrowExpr throw ;
2845+
2846+ TranslatedDestructorsAfterThrow ( ) { this = TTranslatedDestructorsAfterThrow ( throw ) }
2847+
2848+ override string toString ( ) { result = "Destructor calls after throw: " + throw }
2849+
2850+ private TranslatedCall getTranslatedImplicitDestructorCall ( int id ) {
2851+ result .getExpr ( ) = throw .getImplicitDestructorCall ( id )
2852+ }
2853+
2854+ override Instruction getFirstInstruction ( EdgeKind kind ) {
2855+ result = this .getChild ( 0 ) .getFirstInstruction ( kind )
2856+ }
2857+
2858+ override ThrowExpr getAst ( ) { result = throw }
2859+
2860+ override Instruction getInstructionSuccessorInternal ( InstructionTag tag , EdgeKind kind ) { none ( ) }
2861+
2862+ override TranslatedElement getChild ( int id ) {
2863+ result = this .getTranslatedImplicitDestructorCall ( id )
2864+ }
2865+
2866+ override predicate handlesDestructorsExplicitly ( ) { any ( ) }
2867+
2868+ override Declaration getFunction ( ) { result = throw .getEnclosingFunction ( ) }
2869+
2870+ override Instruction getChildSuccessorInternal ( TranslatedElement child , EdgeKind kind ) {
2871+ exists ( int id | child = this .getChild ( id ) |
2872+ // Transition to the next child, if any.
2873+ result = this .getChild ( id + 1 ) .getFirstInstruction ( kind )
2874+ or
2875+ // And otherwise, exit this element with an exceptional edge
2876+ not exists ( this .getChild ( id + 1 ) ) and
2877+ kind instanceof ExceptionEdge and
2878+ result = this .getParent ( ) .getExceptionSuccessorInstruction ( any ( GotoEdge edge ) )
2879+ )
2880+ }
2881+
2882+ override TranslatedElement getLastChild ( ) {
2883+ result =
2884+ this .getTranslatedImplicitDestructorCall ( max ( int id |
2885+ exists ( throw .getImplicitDestructorCall ( id ) )
2886+ ) )
2887+ }
2888+
2889+ override Instruction getALastInstructionInternal ( ) {
2890+ result = this .getLastChild ( ) .getALastInstruction ( )
2891+ }
2892+
2893+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
2894+ none ( )
2895+ }
2896+ }
2897+
28362898/**
28372899 * IR translation of a `throw` expression.
28382900 */
@@ -2847,13 +2909,22 @@ abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr {
28472909
28482910 override Instruction getInstructionSuccessorInternal ( InstructionTag tag , EdgeKind kind ) {
28492911 tag = ThrowTag ( ) and
2850- kind instanceof ExceptionEdge and
2851- result = this .getParent ( ) .getExceptionSuccessorInstruction ( any ( GotoEdge edge ) )
2912+ (
2913+ result = this .getDestructors ( ) .getFirstInstruction ( kind )
2914+ or
2915+ not exists ( this .getDestructors ( ) ) and
2916+ kind instanceof ExceptionEdge and
2917+ result = this .getParent ( ) .getExceptionSuccessorInstruction ( any ( GotoEdge edge ) )
2918+ )
28522919 }
28532920
28542921 override Instruction getResult ( ) { none ( ) }
28552922
28562923 abstract Opcode getThrowOpcode ( ) ;
2924+
2925+ override predicate handlesDestructorsExplicitly ( ) { any ( ) }
2926+
2927+ TranslatedDestructorsAfterThrow getDestructors ( ) { result .getAst ( ) = expr }
28572928}
28582929
28592930/**
@@ -2865,6 +2936,9 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableIn
28652936
28662937 final override TranslatedElement getChildInternal ( int id ) {
28672938 result = TranslatedVariableInitialization .super .getChildInternal ( id )
2939+ or
2940+ id = max ( int i | exists ( TranslatedVariableInitialization .super .getChildInternal ( i ) ) ) + 1 and
2941+ result = this .getDestructors ( )
28682942 }
28692943
28702944 final override Instruction getChildSuccessorInternal ( TranslatedElement elem , EdgeKind kind ) {
@@ -2930,14 +3004,22 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableIn
29303004class TranslatedReThrowExpr extends TranslatedThrowExpr {
29313005 override ReThrowExpr expr ;
29323006
2933- override TranslatedElement getChildInternal ( int id ) { none ( ) }
3007+ override TranslatedElement getChildInternal ( int id ) {
3008+ id = 0 and
3009+ result = this .getDestructors ( )
3010+ }
29343011
29353012 override Instruction getFirstInstruction ( EdgeKind kind ) {
29363013 result = this .getInstruction ( ThrowTag ( ) ) and
29373014 kind instanceof GotoEdge
29383015 }
29393016
2940- override Instruction getALastInstructionInternal ( ) { result = this .getInstruction ( ThrowTag ( ) ) }
3017+ override Instruction getALastInstructionInternal ( ) {
3018+ result = this .getDestructors ( ) .getALastInstruction ( )
3019+ or
3020+ not this .hasAnImplicitDestructorCall ( ) and
3021+ result = this .getInstruction ( ThrowTag ( ) )
3022+ }
29413023
29423024 override Instruction getChildSuccessorInternal ( TranslatedElement child , EdgeKind kind ) { none ( ) }
29433025
0 commit comments