Changeset 9151fcb


Ignore:
Timestamp:
Jun 7, 2019, 12:00:17 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr
Children:
e16e27e1, ef75948
Parents:
0b73f0c (diff), 5684736 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Node.hpp

    r0b73f0c r9151fcb  
    1818#include <cassert>
    1919#include <iosfwd>
     20#include <type_traits> // for remove_reference
    2021
    2122#include "Common/ErrorObjects.h"  // for SemanticErrorException
     
    8283};
    8384
    84 // Mutate a node, non-member function to avoid static type
    85 // problems and be able to use auto return
     85/// Mutate a node, non-member function to avoid static type
     86/// problems and be able to use auto return
    8687template<typename node_t>
    8788node_t * mutate( const node_t * node ) {
     
    9596        );
    9697        return node->clone();
     98}
     99
     100/// Mutate a node field (only clones if not equal to existing value)
     101template<typename node_t, typename field_t>
     102const node_t * mutate_field(
     103        const node_t * node,
     104        typename std::remove_const<typename std::remove_reference<field_t>::type>::type node_t::* field,
     105        field_t&& val
     106) {
     107        if ( node->*field == val ) return node;
     108       
     109        node_t * ret = mutate( node );
     110        ret->*field = std::forward< field_t >( val );
     111        return ret;
    97112}
    98113
  • src/AST/Pass.hpp

    r0b73f0c r9151fcb  
    201201        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    202202
     203public:
    203204        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
    204205        template<typename node_t, typename parent_t, typename child_t>
  • src/AST/module.mk

    r0b73f0c r9151fcb  
    1616
    1717SRC_AST = \
     18        AST/AssertAcyclic.cpp \
    1819        AST/Attribute.cpp \
    1920        AST/Convert.cpp \
  • src/Makefile.in

    r0b73f0c r9151fcb  
    165165libdemangle_a_LIBADD =
    166166am__dirstamp = $(am__leading_dot)dirstamp
    167 am__objects_1 = AST/Attribute.$(OBJEXT) AST/Convert.$(OBJEXT) \
    168         AST/Decl.$(OBJEXT) AST/DeclReplacer.$(OBJEXT) \
    169         AST/Expr.$(OBJEXT) AST/GenericSubstitution.$(OBJEXT) \
    170         AST/Init.$(OBJEXT) AST/LinkageSpec.$(OBJEXT) \
    171         AST/Node.$(OBJEXT) AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) \
    172         AST/Stmt.$(OBJEXT) AST/SymbolTable.$(OBJEXT) \
    173         AST/Type.$(OBJEXT) AST/TypeEnvironment.$(OBJEXT) \
    174         AST/TypeSubstitution.$(OBJEXT)
     167am__objects_1 = AST/AssertAcyclic.$(OBJEXT) AST/Attribute.$(OBJEXT) \
     168        AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
     169        AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
     170        AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
     171        AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
     172        AST/Pass.$(OBJEXT) AST/Print.$(OBJEXT) AST/Stmt.$(OBJEXT) \
     173        AST/SymbolTable.$(OBJEXT) AST/Type.$(OBJEXT) \
     174        AST/TypeEnvironment.$(OBJEXT) AST/TypeSubstitution.$(OBJEXT)
    175175am__objects_2 = CodeGen/CodeGenerator.$(OBJEXT) \
    176176        CodeGen/FixMain.$(OBJEXT) CodeGen/GenType.$(OBJEXT) \
     
    577577@WITH_LIBTCMALLOC_TRUE@TCMALLOCFLAG = -DTCMALLOC
    578578SRC_AST = \
     579        AST/AssertAcyclic.cpp \
    579580        AST/Attribute.cpp \
    580581        AST/Convert.cpp \
     
    744745        @$(MKDIR_P) AST/$(DEPDIR)
    745746        @: > AST/$(DEPDIR)/$(am__dirstamp)
     747AST/AssertAcyclic.$(OBJEXT): AST/$(am__dirstamp) \
     748        AST/$(DEPDIR)/$(am__dirstamp)
    746749AST/Attribute.$(OBJEXT): AST/$(am__dirstamp) \
    747750        AST/$(DEPDIR)/$(am__dirstamp)
     
    11931196@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MakeLibCfa.Po@am__quote@
    11941197@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
     1198@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/AssertAcyclic.Po@am__quote@
    11951199@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Attribute.Po@am__quote@
    11961200@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Convert.Po@am__quote@
  • src/ResolvExpr/CurrentObject.cc

    r0b73f0c r9151fcb  
    2020#include <string>                      // for string, operator<<, allocator
    2121
     22#include "AST/Expr.hpp"                // for InitAlternative
     23#include "AST/Init.hpp"                // for Designation
     24#include "AST/Node.hpp"                // for readonly
    2225#include "Common/Indenter.h"           // for Indenter, operator<<
    2326#include "Common/SemanticError.h"      // for SemanticError
     
    579582} // namespace ResolvExpr
    580583
     584namespace ast {
     585
     586        /// Iterates members of a type by initializer
     587        class MemberIterator {
     588        public:
     589                virtual ~MemberIterator() {}
     590
     591                /// retrieve the list of possible (Type,Designation) pairs for the current position in the
     592                /// current object
     593                virtual std::vector< InitAlternative > operator* () const = 0;
     594       
     595        protected:
     596                /// helper for operator*; aggregates must add designator to each init alternative, but
     597                /// adding designators in operator* creates duplicates
     598                virtual std::vector< InitAlternative > first() const = 0;
     599        };
     600
     601        /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
     602        class SimpleIterator final : public MemberIterator {
     603                CodeLocation location;
     604                readonly< Type > type = nullptr;
     605        public:
     606                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
     607
     608                std::vector< InitAlternative > operator* () const override { return first(); }
     609
     610        protected:
     611                std::vector< InitAlternative > first() const override {
     612                        if ( type ) return { InitAlternative{ type, new Designation{ location } } };
     613                        return {};
     614                }
     615        };
     616
     617        CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
     618                objStack.emplace_back( new SimpleIterator{ loc, type } );
     619        }
     620
     621        std::vector< InitAlternative > CurrentObject::getOptions() {
     622                PRINT( std::cerr << "____getting current options" << std::endl; )
     623                assertf( ! objStack.empty(), "objstack empty in getOptions" );
     624                return **objStack.back();
     625        }
     626}
     627
    581628// Local Variables: //
    582629// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.h

    r0b73f0c r9151fcb  
    1717
    1818#include <list>   // for list
     19#include <memory> // for unique_ptr
    1920#include <stack>  // for stack
     21#include <vector>
     22
     23#include "Common/CodeLocation.h"
    2024
    2125class Designation;
     
    5256} // namespace ResolvExpr
    5357
     58namespace ast {
     59        // AST class types
     60        class Designation;
     61        class InitAlternative;
     62        class Type;
     63
     64        // forward declaration of internal detail
     65        class MemberIterator;
     66
     67        /// Builds initializer lists in resolution
     68        class CurrentObject final {
     69                std::vector< std::shared_ptr<MemberIterator> > objStack;
     70       
     71        public:
     72                CurrentObject() = default;
     73                CurrentObject( const CodeLocation & loc, const Type * type );
     74
     75                /// produces a list of alternatives (Type *, Designation *) for the current sub-object's
     76                /// initializer.
     77                std::vector< InitAlternative > getOptions();
     78        };
     79} // namespace ast
     80
    5481// Local Variables: //
    5582// tab-width: 4 //
  • src/ResolvExpr/ResolveAssertions.cc

    r0b73f0c r9151fcb  
    342342
    343343        /// Limit to depth of recursion of assertion satisfaction
    344         static const int recursionLimit = /* 10 */ 4;
     344        static const int recursionLimit = 4;
     345        /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
     346        static const int deferLimit = 10;
    345347
    346348        void resolveAssertions( Alternative& alt, const SymTab::Indexer& indexer, AltList& out, std::list<std::string>& errors ) {
     
    369371                                                ss << tabs << "Unsatisfiable alternative:\n";
    370372                                                resn.alt.print( ss, ++tabs );
    371                                                 ss << --tabs << "Could not satisfy assertion:\n";
    372                                                 assn.decl->print( ss, ++tabs );
     373                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
     374                                                assn.decl->print( ss, tabs );
    373375                                               
    374376                                                errors.emplace_back( ss.str() );
     
    384386                                                new_resns.emplace_back( std::move(resn), IterateState );
    385387                                        }
     388                                } else if ( resn.deferred.size() > deferLimit ) {
     389                                        // too many deferred assertions to attempt mutual compatibility
     390                                        Indenter tabs{ 3 };
     391                                        std::ostringstream ss;
     392                                        ss << tabs << "Unsatisfiable alternative:\n";
     393                                        resn.alt.print( ss, ++tabs );
     394                                        ss << (tabs-1) << "Too many non-unique satisfying assignments for "
     395                                                "assertions:\n";
     396                                        for ( const auto& d : resn.deferred ) {
     397                                                d.decl->print( ss, tabs );
     398                                        }
     399
     400                                        errors.emplace_back( ss.str() );
     401                                        goto nextResn;
    386402                                } else {
    387403                                        // resolve deferred assertions by mutual compatibility
     
    395411                                                ss << tabs << "Unsatisfiable alternative:\n";
    396412                                                resn.alt.print( ss, ++tabs );
    397                                                 ss << --tabs << "No mutually-compatible satisfaction for assertions:\n";
    398                                                 ++tabs;
     413                                                ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
    399414                                                for ( const auto& d : resn.deferred ) {
    400415                                                        d.decl->print( ss, tabs );
  • src/ResolvExpr/Resolver.cc

    r0b73f0c r9151fcb  
    165165                void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    166166                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    167                                 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
     167                                if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    168168                                        // cast is to the same type as its argument, so it's unnecessary -- remove it
    169169                                        expr = castExpr->arg;
     
    965965                }
    966966
     967                /// always-accept candidate filter
     968                bool anyCandidate( const Candidate & ) { return true; }
     969
    967970                /// Calls the CandidateFinder and finds the single best candidate
    968971                CandidateRef findUnfinishedKindExpression(
    969972                        const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    970                         std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
     973                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    971974                ) {
    972975                        if ( ! untyped ) return nullptr;
     
    10561059                                ) {
    10571060                                        // generated cast is the same type as its argument, remove it after keeping env
    1058                                         ast::ptr<ast::Expr> arg = castExpr->arg;
    1059                                         arg.get_and_mutate()->env = castExpr->env;
    1060                                         return arg;
     1061                                        return ast::mutate_field(
     1062                                                castExpr->arg.get(), &ast::Expr::env, castExpr->env );
    10611063                                }
    10621064                                return castExpr;
     
    10681070                        }
    10691071                };
     1072
     1073                /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
     1074                void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
     1075                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
     1076                                if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
     1077                                        // cast is to the same type as its argument, remove it
     1078                                        ast::ptr< ast::TypeSubstitution > env = castExpr->env;
     1079                                        expr.set_and_mutate( castExpr->arg )->env = env;
     1080                                }
     1081                        }
     1082                }
    10701083
    10711084                /// Establish post-resolver invariants for expressions
     
    10821095                        StripCasts_new::strip( expr );
    10831096                }
    1084                
     1097
     1098                /// Find the expression candidate that is the unique best match for `untyped` in a `void`
     1099                /// context.
     1100                ast::ptr< ast::Expr > resolveInVoidContext(
     1101                        const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
     1102                ) {
     1103                        assertf( expr, "expected a non-null expression" );
     1104                       
     1105                        // set up and resolve expression cast to void
     1106                        ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr };
     1107                        CandidateRef choice = findUnfinishedKindExpression(
     1108                                untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     1109                       
     1110                        // a cast expression has either 0 or 1 interpretations (by language rules);
     1111                        // if 0, an exception has already been thrown, and this code will not run
     1112                        const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
     1113                        env = std::move( choice->env );
     1114
     1115                        return castExpr->arg;
     1116                }
     1117
     1118                /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
     1119                /// context.
     1120                ast::ptr< ast::Expr > findVoidExpression(
     1121                        const ast::Expr * untyped, const ast::SymbolTable & symtab
     1122                ) {
     1123                        resetTyVarRenaming();
     1124                        ast::TypeEnvironment env;
     1125                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
     1126                        finishExpr( newExpr, env, untyped->env );
     1127                        return newExpr;
     1128                }
     1129
    10851130                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
    10861131                /// lowest cost, returning the resolved version
    10871132                ast::ptr< ast::Expr > findKindExpression(
    1088                         const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
    1089                         std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
     1133                        const ast::Expr * untyped, const ast::SymbolTable & symtab,
     1134                        std::function<bool(const Candidate &)> pred = anyCandidate,
     1135                        const std::string & kind = "", ResolvMode mode = {}
    10901136                ) {
    10911137                        if ( ! untyped ) return {};
     
    10941140                        finishExpr( choice->expr, choice->env, untyped->env );
    10951141                        return std::move( choice->expr );
     1142                }
     1143
     1144                /// Resolve `untyped` to the single expression whose candidate is the best match for the
     1145                /// given type.
     1146                ast::ptr< ast::Expr > findSingleExpression(
     1147                        const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1148                ) {
     1149                        assert( untyped && type );
     1150                        const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
     1151                        ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab );
     1152                        removeExtraneousCast( newExpr, symtab );
     1153                        return newExpr;
    10961154                }
    10971155
     
    11151173                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11161174                ) {
    1117                         return findKindExpression( untyped, symtab, "condition", hasIntegralType );
     1175                        return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
    11181176                }
    11191177        }
     
    11251183
    11261184                ast::ptr< ast::Type > functionReturn = nullptr;
    1127                 // ast::CurrentObject currentObject = nullptr;
     1185                ast::CurrentObject currentObject;
    11281186                bool inEnumDecl = false;
    11291187
     
    11411199                void previsit( const ast::PointerType * );
    11421200
    1143                 void previsit( const ast::ExprStmt * );
    1144                 void previsit( const ast::AsmExpr * );
    1145                 void previsit( const ast::AsmStmt * );
    1146                 void previsit( const ast::IfStmt * );
    1147                 void previsit( const ast::WhileStmt * );
    1148                 void previsit( const ast::ForStmt * );
    1149                 void previsit( const ast::SwitchStmt * );
    1150                 void previsit( const ast::CaseStmt * );
    1151                 void previsit( const ast::BranchStmt * );
    1152                 void previsit( const ast::ReturnStmt * );
    1153                 void previsit( const ast::ThrowStmt * );
    1154                 void previsit( const ast::CatchStmt * );
     1201                const ast::ExprStmt *  previsit( const ast::ExprStmt * );
     1202                const ast::AsmExpr *    previsit( const ast::AsmExpr * );
     1203                const ast::AsmStmt *    previsit( const ast::AsmStmt * );
     1204                const ast::IfStmt *    previsit( const ast::IfStmt * );
     1205                const ast::WhileStmt * previsit( const ast::WhileStmt * );
     1206                const ast::ForStmt *    previsit( const ast::ForStmt * );
     1207                const ast::SwitchStmt * previsit( const ast::SwitchStmt * );
     1208                const ast::CaseStmt *  previsit( const ast::CaseStmt * );
     1209                const ast::BranchStmt * previsit( const ast::BranchStmt * );
     1210                const ast::ReturnStmt * previsit( const ast::ReturnStmt * );
     1211                const ast::ThrowStmt * previsit( const ast::ThrowStmt * );
     1212                const ast::CatchStmt * previsit( const ast::CatchStmt * );
    11551213                void previsit( const ast::WaitForStmt * );
    11561214
     
    11961254
    11971255        void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    1198                 #warning unimplemented; Resolver port in progress
    1199                 (void)objectDecl;
    1200                 assert(false);
     1256                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
     1257                // class-variable `initContext` is changed multiple times because the LHS is analyzed
     1258                // twice. The second analysis changes `initContext` because a function type can contain
     1259                // object declarations in the return and parameter types. Therefore each value of
     1260                // `initContext` is retained so the type on the first analysis is preserved and used for
     1261                // selecting the RHS.
     1262                GuardValue( currentObject );
     1263                currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1264                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
     1265                        // enumerator initializers should not use the enum type to initialize, since the
     1266                        // enum type is still incomplete at this point. Use `int` instead.
     1267                        currentObject = ast::CurrentObject{
     1268                                objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
     1269                }
    12011270        }
    12021271
     
    12101279                const ast::StaticAssertDecl * assertDecl
    12111280        ) {
    1212                 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
    1213                 if ( cond == assertDecl->cond ) return assertDecl;
     1281                return ast::mutate_field(
     1282                        assertDecl, &ast::StaticAssertDecl::cond,
     1283                        findIntegralExpression( assertDecl->cond, symtab ) );
     1284        }
     1285
     1286        template< typename PtrType >
     1287        void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
     1288                #warning unimplemented; needs support for new Validate::SizeType global
     1289                (void)type; (void)symtab;
     1290                assert( false );
     1291        }
     1292
     1293        void Resolver_new::previsit( const ast::ArrayType * at ) {
     1294                handlePtrType( at, symtab );
     1295        }
     1296
     1297        void Resolver_new::previsit( const ast::PointerType * pt ) {
     1298                handlePtrType( pt, symtab );
     1299        }
     1300
     1301        const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
     1302                visit_children = false;
     1303                assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
    12141304               
    1215                 ast::StaticAssertDecl * ret = mutate( assertDecl );
    1216                 ret->cond = cond;
    1217                 return ret;
    1218         }
    1219 
    1220         void Resolver_new::previsit( const ast::ArrayType * at ) {
    1221                 #warning unimplemented; Resolver port in progress
    1222                 (void)at;
    1223                 assert(false);
    1224         }
    1225 
    1226         void Resolver_new::previsit( const ast::PointerType * pt ) {
    1227                 #warning unimplemented; Resolver port in progress
    1228                 (void)pt;
    1229                 assert(false);
    1230         }
    1231 
    1232         void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
    1233                 #warning unimplemented; Resolver port in progress
    1234                 (void)exprStmt;
    1235                 assert(false);
    1236         }
    1237 
    1238         void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
    1239                 #warning unimplemented; Resolver port in progress
    1240                 (void)asmExpr;
    1241                 assert(false);
    1242         }
    1243 
    1244         void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
    1245                 #warning unimplemented; Resolver port in progress
    1246                 (void)asmStmt;
    1247                 assert(false);
    1248         }
    1249 
    1250         void Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    1251                 #warning unimplemented; Resolver port in progress
    1252                 (void)ifStmt;
    1253                 assert(false);
    1254         }
    1255 
    1256         void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
    1257                 #warning unimplemented; Resolver port in progress
    1258                 (void)whileStmt;
    1259                 assert(false);
    1260         }
    1261 
    1262         void Resolver_new::previsit( const ast::ForStmt * forStmt ) {
    1263                 #warning unimplemented; Resolver port in progress
    1264                 (void)forStmt;
    1265                 assert(false);
    1266         }
    1267 
    1268         void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
    1269                 #warning unimplemented; Resolver port in progress
    1270                 (void)switchStmt;
    1271                 assert(false);
    1272         }
    1273 
    1274         void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
    1275                 #warning unimplemented; Resolver port in progress
    1276                 (void)caseStmt;
    1277                 assert(false);
    1278         }
    1279 
    1280         void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
    1281                 #warning unimplemented; Resolver port in progress
    1282                 (void)branchStmt;
    1283                 assert(false);
    1284         }
    1285 
    1286         void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
    1287                 #warning unimplemented; Resolver port in progress
    1288                 (void)returnStmt;
    1289                 assert(false);
    1290         }
    1291 
    1292         void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
    1293                 #warning unimplemented; Resolver port in progress
    1294                 (void)throwStmt;
    1295                 assert(false);
    1296         }
    1297 
    1298         void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1299                 #warning unimplemented; Resolver port in progress
    1300                 (void)catchStmt;
    1301                 assert(false);
     1305                return ast::mutate_field(
     1306                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
     1307        }
     1308
     1309        const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
     1310                visit_children = false;
     1311
     1312                asmExpr = ast::mutate_field(
     1313                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
     1314               
     1315                if ( asmExpr->inout ) {
     1316                        asmExpr = ast::mutate_field(
     1317                                asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
     1318                }
     1319               
     1320                return asmExpr;
     1321        }
     1322
     1323        const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {
     1324                visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );
     1325                visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );
     1326                visit_children = false;
     1327                return asmStmt;
     1328        }
     1329
     1330        const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
     1331                return ast::mutate_field(
     1332                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
     1333        }
     1334
     1335        const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
     1336                return ast::mutate_field(
     1337                        whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
     1338        }
     1339
     1340        const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
     1341                if ( forStmt->cond ) {
     1342                        forStmt = ast::mutate_field(
     1343                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
     1344                }
     1345
     1346                if ( forStmt->inc ) {
     1347                        forStmt = ast::mutate_field(
     1348                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
     1349                }
     1350
     1351                return forStmt;
     1352        }
     1353
     1354        const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
     1355                GuardValue( currentObject );
     1356                switchStmt = ast::mutate_field(
     1357                        switchStmt, &ast::SwitchStmt::cond,
     1358                        findIntegralExpression( switchStmt->cond, symtab ) );
     1359                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
     1360                return switchStmt;
     1361        }
     1362
     1363        const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
     1364                if ( caseStmt->cond ) {
     1365                        std::vector< ast::InitAlternative > initAlts = currentObject.getOptions();
     1366                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "
     1367                                "expression." );
     1368                       
     1369                        const ast::Expr * untyped =
     1370                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
     1371                        ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab );
     1372                       
     1373                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     1374                        // whether it would perform a conversion.
     1375                        if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {
     1376                                ast::ptr< ast::TypeSubstitution > env = castExpr->env;
     1377                                newExpr.set_and_mutate( castExpr->arg )->env = env;
     1378                        }
     1379                       
     1380                        caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
     1381                }
     1382                return caseStmt;
     1383        }
     1384
     1385        const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
     1386                visit_children = false;
     1387                // must resolve the argument of a computed goto
     1388                if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
     1389                        // computed goto argument is void*
     1390                        branchStmt = ast::mutate_field(
     1391                                branchStmt, &ast::BranchStmt::computedTarget,
     1392                                findSingleExpression(
     1393                                        branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} },
     1394                                        symtab ) );
     1395                }
     1396                return branchStmt;
     1397        }
     1398
     1399        const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {
     1400                visit_children = false;
     1401                if ( returnStmt->expr ) {
     1402                        returnStmt = ast::mutate_field(
     1403                                returnStmt, &ast::ReturnStmt::expr,
     1404                                findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
     1405                }
     1406                return returnStmt;
     1407        }
     1408
     1409        const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {
     1410                visit_children = false;
     1411                if ( throwStmt->expr ) {
     1412                        const ast::StructDecl * exceptionDecl =
     1413                                symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     1414                        assert( exceptionDecl );
     1415                        ast::ptr< ast::Type > exceptType =
     1416                                new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };
     1417                        throwStmt = ast::mutate_field(
     1418                                throwStmt, &ast::ThrowStmt::expr,
     1419                                findSingleExpression( throwStmt->expr, exceptType, symtab ) );
     1420                }
     1421                return throwStmt;
     1422        }
     1423
     1424        const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
     1425                if ( catchStmt->cond ) {
     1426                        ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
     1427                        catchStmt = ast::mutate_field(
     1428                                catchStmt, &ast::CatchStmt::cond,
     1429                                findSingleExpression( catchStmt->cond, boolType, symtab ) );
     1430                }
     1431                return catchStmt;
    13021432        }
    13031433
Note: See TracChangeset for help on using the changeset viewer.