@@ -13,6 +13,222 @@ private import TranslatedInitialization
1313
1414TranslatedStmt getTranslatedStmt ( Stmt stmt ) { result .getAst ( ) = stmt }
1515
16+ TranslatedMicrosoftTryExceptHandler getTranslatedMicrosoftTryExceptHandler (
17+ MicrosoftTryExceptStmt tryExcept
18+ ) {
19+ result .getAst ( ) = tryExcept .getExcept ( )
20+ }
21+
22+ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement ,
23+ TTranslatedMicrosoftTryExceptHandler {
24+ MicrosoftTryExceptStmt tryExcept ;
25+
26+ TranslatedMicrosoftTryExceptHandler ( ) { this = TTranslatedMicrosoftTryExceptHandler ( tryExcept ) }
27+
28+ final override string toString ( ) { result = tryExcept .toString ( ) }
29+
30+ final override Locatable getAst ( ) { result = tryExcept .getExcept ( ) }
31+
32+ override Instruction getFirstInstruction ( ) { result = this .getChild ( 0 ) .getFirstInstruction ( ) }
33+
34+ override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
35+ // t1 = -1
36+ tag = TryExceptGenerateNegativeOne ( ) and
37+ opcode instanceof Opcode:: Constant and
38+ resultType = getIntType ( )
39+ or
40+ // t2 = cmp t1, condition
41+ tag = TryExceptCompareNegativeOne ( ) and
42+ opcode instanceof Opcode:: CompareEQ and
43+ resultType = getBoolType ( )
44+ or
45+ // if t2 goto ... else goto ...
46+ tag = TryExceptCompareNegativeOneBranch ( ) and
47+ opcode instanceof Opcode:: ConditionalBranch and
48+ resultType = getVoidType ( )
49+ or
50+ // t1 = 0
51+ tag = TryExceptGenerateZero ( ) and
52+ opcode instanceof Opcode:: Constant and
53+ resultType = getIntType ( )
54+ or
55+ // t2 = cmp t1, condition
56+ tag = TryExceptCompareZero ( ) and
57+ opcode instanceof Opcode:: CompareEQ and
58+ resultType = getBoolType ( )
59+ or
60+ // if t2 goto ... else goto ...
61+ tag = TryExceptCompareZeroBranch ( ) and
62+ opcode instanceof Opcode:: ConditionalBranch and
63+ resultType = getVoidType ( )
64+ or
65+ // t1 = 1
66+ tag = TryExceptGenerateOne ( ) and
67+ opcode instanceof Opcode:: Constant and
68+ resultType = getIntType ( )
69+ or
70+ // t2 = cmp t1, condition
71+ tag = TryExceptCompareOne ( ) and
72+ opcode instanceof Opcode:: CompareEQ and
73+ resultType = getBoolType ( )
74+ or
75+ // if t2 goto ... else goto ...
76+ tag = TryExceptCompareOneBranch ( ) and
77+ opcode instanceof Opcode:: ConditionalBranch and
78+ resultType = getVoidType ( )
79+ or
80+ // unwind stack
81+ tag = UnwindTag ( ) and
82+ opcode instanceof Opcode:: Unwind and
83+ resultType = getVoidType ( )
84+ }
85+
86+ final override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
87+ tag = TryExceptCompareNegativeOne ( ) and
88+ (
89+ operandTag instanceof LeftOperandTag and
90+ result = this .getTranslatedCondition ( ) .getResult ( )
91+ or
92+ operandTag instanceof RightOperandTag and
93+ result = this .getInstruction ( TryExceptGenerateNegativeOne ( ) )
94+ )
95+ or
96+ tag = TryExceptCompareNegativeOneBranch ( ) and
97+ operandTag instanceof ConditionOperandTag and
98+ result = this .getInstruction ( TryExceptCompareNegativeOne ( ) )
99+ or
100+ tag = TryExceptCompareZero ( ) and
101+ (
102+ operandTag instanceof LeftOperandTag and
103+ result = this .getTranslatedCondition ( ) .getResult ( )
104+ or
105+ operandTag instanceof RightOperandTag and
106+ result = this .getInstruction ( TryExceptGenerateZero ( ) )
107+ )
108+ or
109+ tag = TryExceptCompareZeroBranch ( ) and
110+ operandTag instanceof ConditionOperandTag and
111+ result = this .getInstruction ( TryExceptCompareZero ( ) )
112+ or
113+ tag = TryExceptCompareOne ( ) and
114+ (
115+ operandTag instanceof LeftOperandTag and
116+ result = this .getTranslatedCondition ( ) .getResult ( )
117+ or
118+ operandTag instanceof RightOperandTag and
119+ result = this .getInstruction ( TryExceptGenerateOne ( ) )
120+ )
121+ or
122+ tag = TryExceptCompareOneBranch ( ) and
123+ operandTag instanceof ConditionOperandTag and
124+ result = this .getInstruction ( TryExceptCompareOne ( ) )
125+ }
126+
127+ override string getInstructionConstantValue ( InstructionTag tag ) {
128+ tag = TryExceptGenerateNegativeOne ( ) and
129+ result = "-1"
130+ or
131+ tag = TryExceptGenerateZero ( ) and
132+ result = "0"
133+ or
134+ tag = TryExceptGenerateOne ( ) and
135+ result = "1"
136+ }
137+
138+ override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
139+ // Generate -1 -> Compare condition
140+ tag = TryExceptGenerateNegativeOne ( ) and
141+ kind instanceof GotoEdge and
142+ result = this .getInstruction ( TryExceptCompareNegativeOne ( ) )
143+ or
144+ // Compare condition -> Branch
145+ tag = TryExceptCompareNegativeOne ( ) and
146+ kind instanceof GotoEdge and
147+ result = this .getInstruction ( TryExceptCompareNegativeOneBranch ( ) )
148+ or
149+ // Branch -> Unwind or Generate 0
150+ tag = TryExceptCompareNegativeOneBranch ( ) and
151+ (
152+ kind instanceof TrueEdge and
153+ // TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
154+ // we should continue execution at the point where the exception occurred. But we don't have
155+ // any instruction to model this behavior.
156+ result = this .getInstruction ( UnwindTag ( ) )
157+ or
158+ kind instanceof FalseEdge and
159+ result = this .getInstruction ( TryExceptGenerateZero ( ) )
160+ )
161+ or
162+ // Generate 0 -> Compare condition
163+ tag = TryExceptGenerateZero ( ) and
164+ kind instanceof GotoEdge and
165+ result = this .getInstruction ( TryExceptCompareZero ( ) )
166+ or
167+ // Compare condition -> Branch
168+ tag = TryExceptCompareZero ( ) and
169+ kind instanceof GotoEdge and
170+ result = this .getInstruction ( TryExceptCompareZeroBranch ( ) )
171+ or
172+ // Branch -> Unwind or Generate 1
173+ tag = TryExceptCompareZeroBranch ( ) and
174+ (
175+ kind instanceof TrueEdge and
176+ result = this .getInstruction ( UnwindTag ( ) )
177+ or
178+ kind instanceof FalseEdge and
179+ result = this .getInstruction ( TryExceptGenerateOne ( ) )
180+ )
181+ or
182+ // Generate 1 -> Compare condition
183+ tag = TryExceptGenerateOne ( ) and
184+ kind instanceof GotoEdge and
185+ result = this .getInstruction ( TryExceptCompareOne ( ) )
186+ or
187+ // Compare condition -> Branch
188+ tag = TryExceptCompareOne ( ) and
189+ kind instanceof GotoEdge and
190+ result = this .getInstruction ( TryExceptCompareOneBranch ( ) )
191+ or
192+ // Branch -> Handler (the condition value is always 0, -1 or 1, and we've checked for 0 or -1 already.)
193+ tag = TryExceptCompareOneBranch ( ) and
194+ (
195+ kind instanceof TrueEdge and
196+ result = this .getTranslatedHandler ( ) .getFirstInstruction ( )
197+ )
198+ or
199+ // Unwind -> Parent
200+ tag = UnwindTag ( ) and
201+ kind instanceof GotoEdge and
202+ result = this .getParent ( ) .getChildSuccessor ( this )
203+ }
204+
205+ override Instruction getChildSuccessor ( TranslatedElement child ) {
206+ child = this .getTranslatedCondition ( ) and
207+ result = this .getInstruction ( TryExceptGenerateNegativeOne ( ) )
208+ or
209+ child = this .getTranslatedHandler ( ) and
210+ result = this .getParent ( ) .getChildSuccessor ( this )
211+ }
212+
213+ private TranslatedExpr getTranslatedCondition ( ) {
214+ result = getTranslatedExpr ( tryExcept .getCondition ( ) )
215+ }
216+
217+ private TranslatedStmt getTranslatedHandler ( ) {
218+ result = getTranslatedStmt ( tryExcept .getExcept ( ) )
219+ }
220+
221+ override TranslatedElement getChild ( int id ) {
222+ id = 0 and
223+ result = this .getTranslatedCondition ( )
224+ or
225+ id = 1 and
226+ result = this .getTranslatedHandler ( )
227+ }
228+
229+ final override Function getFunction ( ) { result = tryExcept .getEnclosingFunction ( ) }
230+ }
231+
16232abstract class TranslatedStmt extends TranslatedElement , TTranslatedStmt {
17233 Stmt stmt ;
18234
@@ -249,15 +465,57 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
249465}
250466
251467/**
252- * The IR translation of a C++ `try` statement.
468+ * A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
469+ */
470+ private class TryOrMicrosoftTryStmt extends Stmt {
471+ TryOrMicrosoftTryStmt ( ) {
472+ this instanceof TryStmt or
473+ this instanceof MicrosoftTryStmt
474+ }
475+
476+ /** Gets the number of `catch block`s of this statement. */
477+ int getNumberOfCatchClauses ( ) {
478+ result = this .( TryStmt ) .getNumberOfCatchClauses ( )
479+ or
480+ this instanceof MicrosoftTryExceptStmt and
481+ result = 1
482+ or
483+ this instanceof MicrosoftTryFinallyStmt and
484+ result = 0
485+ }
486+
487+ /** Gets the `body` statement of this statement. */
488+ Stmt getStmt ( ) {
489+ result = this .( TryStmt ) .getStmt ( )
490+ or
491+ result = this .( MicrosoftTryStmt ) .getStmt ( )
492+ }
493+
494+ /** Gets the `i`th translated handler of this statement. */
495+ TranslatedElement getTranslatedHandler ( int index ) {
496+ result = getTranslatedStmt ( this .( TryStmt ) .getChild ( index + 1 ) )
497+ or
498+ index = 0 and
499+ result = getTranslatedMicrosoftTryExceptHandler ( this )
500+ }
501+
502+ /** Gets the `finally` statement (usually a BlockStmt), if any. */
503+ Stmt getFinally ( ) { result = this .( MicrosoftTryFinallyStmt ) .getFinally ( ) }
504+ }
505+
506+ /**
507+ * The IR translation of a C++ `try` (or a `__try __except` or `__try __finally`) statement.
253508 */
254509class TranslatedTryStmt extends TranslatedStmt {
255- override TryStmt stmt ;
510+ override TryOrMicrosoftTryStmt stmt ;
256511
257512 override TranslatedElement getChild ( int id ) {
258513 id = 0 and result = getBody ( )
259514 or
260515 result = getHandler ( id - 1 )
516+ or
517+ id = stmt .getNumberOfCatchClauses ( ) + 1 and
518+ result = this .getFinally ( )
261519 }
262520
263521 override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
@@ -269,8 +527,20 @@ class TranslatedTryStmt extends TranslatedStmt {
269527 override Instruction getFirstInstruction ( ) { result = getBody ( ) .getFirstInstruction ( ) }
270528
271529 override Instruction getChildSuccessor ( TranslatedElement child ) {
272- // All children go to the successor of the `try`.
273- child = getAChild ( ) and result = getParent ( ) .getChildSuccessor ( this )
530+ // All non-finally children go to the successor of the `try` if
531+ // there is no finally block, but if there is a finally block
532+ // then we go to that one.
533+ child = [ this .getBody ( ) , this .getHandler ( _) ] and
534+ (
535+ not exists ( this .getFinally ( ) ) and
536+ result = this .getParent ( ) .getChildSuccessor ( this )
537+ or
538+ result = this .getFinally ( ) .getFirstInstruction ( )
539+ )
540+ or
541+ // And after the finally block we go to the successor of the `try`.
542+ child = this .getFinally ( ) and
543+ result = this .getParent ( ) .getChildSuccessor ( this )
274544 }
275545
276546 final Instruction getNextHandler ( TranslatedHandler handler ) {
@@ -290,9 +560,9 @@ class TranslatedTryStmt extends TranslatedStmt {
290560 result = getHandler ( 0 ) .getFirstInstruction ( )
291561 }
292562
293- private TranslatedHandler getHandler ( int index ) {
294- result = getTranslatedStmt ( stmt . getChild ( index + 1 ) )
295- }
563+ private TranslatedElement getHandler ( int index ) { result = stmt . getTranslatedHandler ( index ) }
564+
565+ private TranslatedStmt getFinally ( ) { result = getTranslatedStmt ( stmt . getFinally ( ) ) }
296566
297567 private TranslatedStmt getBody ( ) { result = getTranslatedStmt ( stmt .getStmt ( ) ) }
298568}
0 commit comments