@@ -93,6 +93,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
9393 bool else_pop = false ;
9494 bool need_try = false ;
9595 bool variable_annotations = false ;
96+ std::vector<PycExceptionTableEntry> exception_entries;
97+ size_t next_exception_entry = 0 ;
98+
99+ if (mod->verCompare (3 , 11 ) >= 0 ) {
100+ exception_entries = code->exceptionTableEntries ();
101+ }
96102
97103 while (!source.atEof ()) {
98104#if defined(BLOCK_DEBUG) || defined(STACK_DEBUG)
@@ -108,6 +114,84 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
108114 fprintf (stderr, " \n " );
109115#endif
110116
117+ while (next_exception_entry < exception_entries.size ()
118+ && exception_entries[next_exception_entry].start_offset < pos) {
119+ next_exception_entry++;
120+ }
121+
122+ if (next_exception_entry < exception_entries.size ()) {
123+ const auto & entry = exception_entries[next_exception_entry];
124+ if (entry.start_offset == pos
125+ && entry.stack_depth == 0
126+ && !entry.push_lasti ) {
127+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER) {
128+ curblock.cast <ASTContainerBlock>()->setExcept (entry.target );
129+ } else {
130+ PycRef<ASTBlock> next = new ASTContainerBlock (0 , entry.target );
131+ blocks.push (next.cast <ASTBlock>());
132+ curblock = blocks.top ();
133+ }
134+
135+ stack_hist.push (stack);
136+ PycRef<ASTBlock> tryblock = new ASTBlock (ASTBlock::BLK_TRY, entry.target , true );
137+ blocks.push (tryblock.cast <ASTBlock>());
138+ curblock = blocks.top ();
139+ next_exception_entry++;
140+ }
141+ }
142+
143+ if (curblock->blktype () == ASTBlock::BLK_TRY
144+ && curblock->end () == pos
145+ && blocks.size () > 1 ) {
146+ PycRef<ASTBlock> prev = curblock;
147+ blocks.pop ();
148+ curblock = blocks.top ();
149+
150+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER
151+ && curblock.cast <ASTContainerBlock>()->hasExcept ()) {
152+ if (!stack_hist.empty ()) {
153+ stack = stack_hist.top ();
154+ stack_hist.pop ();
155+ }
156+
157+ curblock->append (prev.cast <ASTNode>());
158+ stack_hist.push (stack);
159+
160+ PycRef<ASTBlock> except = new ASTCondBlock (ASTBlock::BLK_EXCEPT, 0 , NULL , false );
161+ except->init ();
162+ blocks.push (except);
163+ curblock = blocks.top ();
164+ } else {
165+ blocks.push (prev);
166+ curblock = prev;
167+ }
168+ }
169+
170+ if (curblock->blktype () == ASTBlock::BLK_EXCEPT
171+ && curblock->end () == pos
172+ && blocks.size () > 1 ) {
173+ PycRef<ASTBlock> prev = curblock;
174+ blocks.pop ();
175+ curblock = blocks.top ();
176+
177+ if (!stack_hist.empty ()) {
178+ stack = stack_hist.top ();
179+ stack_hist.pop ();
180+ }
181+
182+ if (prev->size () != 0 ) {
183+ curblock->append (prev.cast <ASTNode>());
184+ }
185+
186+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER
187+ && !curblock.cast <ASTContainerBlock>()->hasFinally ()) {
188+ PycRef<ASTBlock> cont = curblock;
189+ blocks.pop ();
190+ curblock = blocks.top ();
191+ curblock->append (cont.cast <ASTNode>());
192+ }
193+ }
194+
111195 curpos = pos;
112196 bc_next (source, mod, opcode, operand, pos);
113197
@@ -1093,15 +1177,17 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
10931177
10941178 if (cond.type () == ASTNode::NODE_COMPARE
10951179 && cond.cast <ASTCompare>()->op () == ASTCompare::CMP_EXCEPTION) {
1180+ int except_end = offs;
10961181 if (curblock->blktype () == ASTBlock::BLK_EXCEPT
10971182 && curblock.cast <ASTCondBlock>()->cond () == NULL ) {
1183+ except_end = curblock->end ();
10981184 blocks.pop ();
10991185 curblock = blocks.top ();
11001186
11011187 stack_hist.pop ();
11021188 }
11031189
1104- ifblk = new ASTCondBlock (ASTBlock::BLK_EXCEPT, offs , cond.cast <ASTCompare>()->right (), false );
1190+ ifblk = new ASTCondBlock (ASTBlock::BLK_EXCEPT, except_end , cond.cast <ASTCompare>()->right (), false );
11051191 } else if (curblock->blktype () == ASTBlock::BLK_ELSE
11061192 && curblock->size () == 0 ) {
11071193 /* Collapse into elif statement */
@@ -1370,8 +1456,10 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
13701456 } else if (prev->blktype () == ASTBlock::BLK_TRY
13711457 && prev->end () < pos+offs) {
13721458 /* Need to add an except/finally block */
1373- stack = stack_hist.top ();
1374- stack.pop ();
1459+ if (!stack_hist.empty ()) {
1460+ stack = stack_hist.top ();
1461+ stack_hist.pop ();
1462+ }
13751463
13761464 if (blocks.top ()->blktype () == ASTBlock::BLK_CONTAINER) {
13771465 PycRef<ASTContainerBlock> cont = blocks.top ().cast <ASTContainerBlock>();
@@ -1689,6 +1777,19 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
16891777 case Pyc::POP_EXCEPT:
16901778 /* Do nothing. */
16911779 break ;
1780+ case Pyc::PUSH_EXC_INFO:
1781+ /* Python 3.11+: pushes exception info tuple. We ignore here to keep decompilation going. */
1782+ break ;
1783+ case Pyc::CHECK_EXC_MATCH:
1784+ {
1785+ /* Python 3.11+: compares exception against handler type. */
1786+ PycRef<ASTNode> right = stack.top ();
1787+ stack.pop ();
1788+ PycRef<ASTNode> left = stack.top ();
1789+ stack.pop ();
1790+ stack.push (new ASTCompare (left, right, ASTCompare::CMP_EXCEPTION));
1791+ }
1792+ break ;
16921793 case Pyc::END_FOR:
16931794 {
16941795 stack.pop ();
@@ -1830,6 +1931,10 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
18301931 }
18311932 }
18321933 break ;
1934+ case Pyc::RERAISE:
1935+ case Pyc::RERAISE_A:
1936+ /* Python 3.11 cleanup opcode. */
1937+ break ;
18331938 case Pyc::RETURN_VALUE:
18341939 case Pyc::INSTRUMENTED_RETURN_VALUE_A:
18351940 {
@@ -1920,6 +2025,9 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
19202025 curblock = blocks.top ();
19212026 }
19222027 break ;
2028+ case Pyc::BEFORE_WITH:
2029+ /* Python 3.11: setup for with block; ignore. */
2030+ break ;
19232031 case Pyc::WITH_CLEANUP:
19242032 case Pyc::WITH_CLEANUP_START:
19252033 {
0 commit comments