source: src/ControlStruct/ExceptTranslateNew.cpp @ 85a2c3f

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since 85a2c3f was 0fba0d4, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

remove anonymous namespace

  • Property mode set to 100644
File size: 4.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExceptTranslateNew.cpp -- Conversion of exception control flow structures.
8//
9// Author           : Andrew Beach
10// Created On       : Mon Nov  8 11:53:00 2021
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Mon Jan 31 18:49:58 2022
13// Update Count     : 1
14//
15
16#include "ExceptTranslate.h"
17
18#include "AST/Expr.hpp"
19#include "AST/Pass.hpp"
20#include "AST/Stmt.hpp"
21#include "AST/TranslationUnit.hpp"
22
23namespace ControlStruct {
24
25class TranslateThrowsCore : public ast::WithGuards {
26        const ast::ObjectDecl * terminateHandlerExcept;
27        enum Context { NoHandler, TerHandler, ResHandler } currentContext;
28
29        const ast::Stmt * createEitherThrow(
30                const ast::ThrowStmt * throwStmt, const char * funcName );
31        const ast::Stmt * createTerminateRethrow( const ast::ThrowStmt * );
32
33public:
34        TranslateThrowsCore() :
35                terminateHandlerExcept( nullptr ), currentContext( NoHandler )
36        {}
37
38        void previsit( const ast::CatchStmt * stmt );
39        const ast::Stmt * postvisit( const ast::ThrowStmt * stmt );
40};
41
42const ast::Stmt * TranslateThrowsCore::createEitherThrow(
43                const ast::ThrowStmt * throwStmt, const char * funcName ) {
44        // `throwFunc`( `throwStmt->name` );
45        ast::UntypedExpr * call = new ast::UntypedExpr( throwStmt->location,
46                new ast::NameExpr( throwStmt->location, funcName )
47        );
48        call->args.push_back( throwStmt->expr );
49        return new ast::ExprStmt( throwStmt->location, call );
50}
51
52ast::VariableExpr * varOf( const ast::DeclWithType * decl ) {
53        return new ast::VariableExpr( decl->location, decl );
54}
55
56const ast::Stmt * TranslateThrowsCore::createTerminateRethrow(
57                const ast::ThrowStmt * stmt ) {
58        // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
59        assert( nullptr == stmt->expr );
60        assert( terminateHandlerExcept );
61
62        ast::CompoundStmt * result = new ast::CompoundStmt(
63                stmt->location, {}, std::vector<ast::Label>( stmt->labels ) );
64        result->push_back( new ast::ExprStmt( stmt->location,
65                ast::UntypedExpr::createAssign(
66                        stmt->location,
67                        varOf( terminateHandlerExcept ),
68                        ast::ConstantExpr::null(
69                                stmt->location,
70                                terminateHandlerExcept->type
71                        )
72                )
73        ) );
74        result->push_back( new ast::ExprStmt( stmt->location, new ast::UntypedExpr(
75                stmt->location,
76                new ast::NameExpr( stmt->location, "__cfaehm_rethrow_terminate" )
77        ) ) );
78        return result;
79}
80
81void TranslateThrowsCore::previsit( const ast::CatchStmt * stmt ) {
82        // Validate the statement's form.
83        const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>();
84        // Also checking the type would be nice.
85        if ( !decl || !decl->type.as<ast::PointerType>() ) {
86                std::string kind = (ast::Terminate == stmt->kind) ? "catch" : "catchResume";
87                SemanticError( stmt->location, kind + " must have pointer to an exception type" );
88        }
89
90        // Track the handler context.
91        if ( ast::Terminate == stmt->kind ) {
92                GuardValue( currentContext ) = TerHandler;
93                GuardValue( terminateHandlerExcept ) = decl;
94        } else {
95                GuardValue( currentContext ) = ResHandler;
96        }
97}
98
99const ast::Stmt * TranslateThrowsCore::postvisit(
100                const ast::ThrowStmt * stmt ) {
101        // Ignoring ThrowStmt::target for now.
102        // Handle Termination (Raise, Reraise, Error):
103        if ( ast::Terminate == stmt->kind ) {
104                if ( stmt->expr ) {
105                        return createEitherThrow( stmt, "$throw" );
106                } else if ( TerHandler == currentContext ) {
107                        return createTerminateRethrow( stmt );
108                } else {
109                        abort( "Invalid throw in %s at %i\n",
110                                stmt->location.filename.c_str(),
111                                stmt->location.first_line);
112                }
113        // Handle Resumption (Raise, Reraise, Error):
114        } else {
115                if ( stmt->expr ) {
116                        return createEitherThrow( stmt, "$throwResume" );
117                } else if ( ResHandler == currentContext ) {
118                        // This has to be handled later.
119                        return stmt;
120                } else {
121                        abort( "Invalid throwResume in %s at %i\n",
122                                stmt->location.filename.c_str(),
123                                stmt->location.first_line);
124                }
125        }
126}
127
128void translateThrows( ast::TranslationUnit & transUnit ) {
129        ast::Pass<TranslateThrowsCore>::run( transUnit );
130}
131
132} // namespace ControlStruct
133
134// Local Variables: //
135// tab-width: 4 //
136// mode: c++ //
137// compile-command: "make install" //
138// End: //
Note: See TracBrowser for help on using the repository browser.