Changeset 866545b for src


Ignore:
Timestamp:
Jun 6, 2019, 10:23:59 PM (3 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
arm-eh, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
46438e4
Parents:
c6a1e8a (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
15 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    rc6a1e8a r866545b  
    1010// Created On       : Thu May 09 15::37::05 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed May 29 17:05:00 2019
    13 // Update Count     : 9
     12// Last Modified On : Thu May 06 19:51:00 2019
     13// Update Count     : 10
    1414//
    1515
     
    4949// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    5050// allow us to use the same stratagy in the new ast.
     51ast::Type * sizeType = nullptr;
    5152ast::FunctionDecl * dereferenceOperator = nullptr;
    5253ast::StructDecl   * dtorStruct = nullptr;
     
    147148
    148149        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
    149                 if ( inCache( node ) ) return nullptr;
     150                auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
     151                auto&& type = get<Type>().accept1( node->type );
     152                auto&& init = get<Initializer>().accept1( node->init );
     153                auto&& attr = get<Attribute>().acceptL( node->attributes );
     154                if ( inCache( node ) ) {
     155                        if(node->name == "tmp") {
     156                                std::cerr << (void*)node << "(new) in cache " << (void*)this->node << "(old)" << std::endl;
     157                        }
     158                        return nullptr;
     159                }
    150160                auto decl = new ObjectDecl(
    151161                        node->name,
    152162                        Type::StorageClasses( node->storage.val ),
    153163                        LinkageSpec::Spec( node->linkage.val ),
    154                         get<Expression>().accept1( node->bitfieldWidth ),
    155                         get<Type>().accept1( node->type ),
    156                         get<Initializer>().accept1( node->init ),
    157                         get<Attribute>().acceptL( node->attributes ),
     164                        bfwd,
     165                        type,
     166                        init,
     167                        attr,
    158168                        Type::FuncSpecifiers( node->funcSpec.val )
    159169                );
     170                if(node->name == "tmp") {
     171                        std::cerr << (void*)node << "(new) created " << (void*)decl << "(old)" << std::endl;
     172                }
    160173                return declWithTypePostamble( decl, node );
    161174        }
     
    709722                auto expr = visitBaseExpr( node,
    710723                        new MemberExpr(
    711                                 inCache(node->member) ?
    712                                         dynamic_cast<DeclarationWithType *>(this->node) :
    713                                         get<DeclarationWithType>().accept1(node->member),
     724                                get<DeclarationWithType>().accept1(node->member),
    714725                                get<Expression>().accept1(node->aggregate)
    715726                        )
     
    720731
    721732        const ast::Expr * visit( const ast::VariableExpr * node ) override final {
    722                 auto expr = visitBaseExpr( node,
    723                         new VariableExpr(
    724                                 inCache(node->var) ?
    725                                         dynamic_cast<DeclarationWithType *>(this->node) :
    726                                         get<DeclarationWithType>().accept1(node->var)
    727                         )
    728                 );
     733                auto expr = new VariableExpr();
     734                visitBaseExpr( node, expr );
     735                expr->var = get<DeclarationWithType>().accept1(node->var);
     736                Type * type = expr->var->get_type()->clone();
     737                type->set_lvalue( true );
     738                expr->set_result( type );
    729739                this->node = expr;
    730740                return nullptr;
     
    819829                        new OffsetofExpr(
    820830                                get<Type>().accept1(node->type),
    821                                 inCache(node->member) ?
    822                                         dynamic_cast<DeclarationWithType *>(this->node) :
    823                                         get<DeclarationWithType>().accept1(node->member)
     831                                get<DeclarationWithType>().accept1(node->member)
    824832                        )
    825833                );
     
    10821090
    10831091        const ast::Type * visit( const ast::BasicType * node ) override final {
    1084                 this->node = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
     1092                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
     1093                // I believe this should always be a BasicType.
     1094                if ( sizeType == node ) {
     1095                        Validate::SizeType = type;
     1096                }
     1097                this->node = type;
    10851098                return nullptr;
    10861099        }
     
    13561369                return strict_dynamic_cast< ast::Decl * >( node );
    13571370        }
     1371
     1372        ConverterOldToNew() = default;
     1373        ConverterOldToNew(const ConverterOldToNew &) = delete;
     1374        ConverterOldToNew(ConverterOldToNew &&) = delete;
    13581375private:
    13591376        /// conversion output
    1360         ast::Node * node;
     1377        ast::Node * node = nullptr;
    13611378        /// cache of nodes that might be referenced by readonly<> for de-duplication
    1362         std::unordered_map< BaseSyntaxNode *, ast::Node * > cache;
     1379        std::unordered_map< BaseSyntaxNode *, ast::Node * > cache = {};
    13631380
    13641381        // Local Utilities:
     1382
     1383        #define construct(T, key, ...) ({ \
     1384                void * data = ::operator new(sizeof(T)); \
     1385                cache.emplace( key, (T*)data ); \
     1386                new (data) T( __VA_ARGS__ ); \
     1387        })
    13651388
    13661389        template<typename NewT, typename OldT>
     
    14241447
    14251448        virtual void visit( ObjectDecl * old ) override final {
    1426                 if ( inCache( old ) ) return;
     1449                if( old->name == "tmp" ) {
     1450                        std::cerr << "building parameters for" << (void*)old << std::endl;
     1451                }
     1452                auto&& type = GET_ACCEPT_1(type, Type);
     1453                auto&& init = GET_ACCEPT_1(init, Init);
     1454                auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr);
     1455                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
     1456                if( old->name == "tmp" ) {
     1457                        std::cerr << "checking cache for " << (void*)old << std::endl;
     1458                }
     1459                if ( inCache( old ) ) {
     1460                        if( old->name == "tmp" ) {
     1461                                std::cerr << (void*)old << "(old) in cache " << (void*)this->node << "(new)" << std::endl;
     1462                        }
     1463                        return;
     1464                }
    14271465                auto decl = new ast::ObjectDecl(
    14281466                        old->location,
    14291467                        old->name,
    1430                         GET_ACCEPT_1(type, Type),
    1431                         GET_ACCEPT_1(init, Init),
     1468                        type,
     1469                        init,
    14321470                        { old->get_storageClasses().val },
    14331471                        { old->linkage.val },
    1434                         GET_ACCEPT_1(bitfieldWidth, Expr),
    1435                         GET_ACCEPT_V(attributes, Attribute),
     1472                        bfwd,
     1473                        std::move(attr),
    14361474                        { old->get_funcSpec().val }
    14371475                );
    1438                 cache.emplace( old, decl );
     1476                cache.emplace(old, decl);
     1477                if( old->name == "tmp" ) {
     1478                        std::cerr << (void*)old << "(old) added to cache with " << (void*)decl << "(new)" << std::endl;
     1479                }
     1480                assert(cache.find( old ) != cache.end());
    14391481                decl->scopeLevel = old->scopeLevel;
    14401482                decl->mangleName = old->mangleName;
     
    14441486
    14451487                this->node = decl;
     1488
     1489                if( old->name == "tmp" ) {
     1490                        std::cerr << (void*)old << "(old) created " << (void*)this->node << "(new)" << std::endl;
     1491                }
    14461492        }
    14471493
     
    20922138                        new ast::MemberExpr(
    20932139                                old->location,
    2094                                 inCache(old->member) ?
    2095                                         dynamic_cast<ast::DeclWithType *>(this->node) :
    2096                                         GET_ACCEPT_1(member, DeclWithType),
     2140                                GET_ACCEPT_1(member, DeclWithType),
    20972141                                GET_ACCEPT_1(aggregate, Expr)
    20982142                        )
     
    21012145
    21022146        virtual void visit( VariableExpr * old ) override final {
    2103                 this->node = visitBaseExpr( old,
    2104                         new ast::VariableExpr(
    2105                                 old->location,
    2106                                 inCache(old->var) ?
    2107                                         dynamic_cast<ast::DeclWithType *>(this->node) :
    2108                                         GET_ACCEPT_1(var, DeclWithType)
    2109                         )
    2110                 );
     2147                auto expr = new ast::VariableExpr(
     2148                        old->location
     2149                );
     2150
     2151                visitBaseExpr( old,
     2152                        expr
     2153                );
     2154
     2155                expr->var = GET_ACCEPT_1(var, DeclWithType);
     2156                expr->result = expr->var->get_type();
     2157                add_qualifiers( expr->result, ast::CV::Lvalue );
     2158                this->node = expr;
    21112159        }
    21122160
     
    22342282                                old->location,
    22352283                                GET_ACCEPT_1(type, Type),
    2236                                 inCache(old->member) ?
    2237                                         dynamic_cast<ast::DeclWithType *>(this->node) :
    2238                                         GET_ACCEPT_1(member, DeclWithType)
     2284                                GET_ACCEPT_1(member, DeclWithType)
    22392285                        )
    22402286                );
     
    24722518
    24732519        virtual void visit( BasicType * old ) override final {
    2474                 this->node = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
     2520                auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
     2521                // I believe this should always be a BasicType.
     2522                if ( Validate::SizeType == old ) {
     2523                        sizeType = type;
     2524                }
     2525                this->node = type;
    24752526        }
    24762527
  • src/AST/Expr.cpp

    rc6a1e8a r866545b  
    170170// --- VariableExpr
    171171
     172VariableExpr::VariableExpr( const CodeLocation & loc )
     173: Expr( loc ), var( nullptr ) {}
     174
    172175VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    173176: Expr( loc ), var( v ) {
  • src/AST/Expr.hpp

    rc6a1e8a r866545b  
    315315        readonly<DeclWithType> var;
    316316
     317        VariableExpr( const CodeLocation & loc );
    317318        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    318319
  • src/AST/Node.hpp

    rc6a1e8a r866545b  
    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
     
    191206        /// wrapper for convenient access to strict_dynamic_cast
    192207        template<typename o_node_t>
    193         const o_node_t * strict_as() const { return strict_dynamic_cast<const o_node_t *>(node); }
     208        const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); }
    194209
    195210        /// Returns a mutable version of the pointer in this node.
  • src/AST/Pass.hpp

    rc6a1e8a r866545b  
    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

    rc6a1e8a r866545b  
    1616
    1717SRC_AST = \
     18        AST/AssertAcyclic.cpp \
    1819        AST/Attribute.cpp \
    1920        AST/Convert.cpp \
  • src/InitTweak/FixInit.cc

    rc6a1e8a r866545b  
    262262                        // unwrap implicit statement wrapper
    263263                        Statement * dtor = input;
    264                         if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) {
    265                                 // dtor = implicit->callStmt;
    266                                 // implicit->callStmt = nullptr;
    267                         }
    268264                        assert( dtor );
    269265                        std::list< Expression * > matches;
     
    291287                        // wraps the more complicated code.
    292288                        static UniqueName dtorNamer( "__cleanup_dtor" );
    293                         FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
     289                        std::string name = dtorNamer.newName();
     290                        FunctionDecl * dtorFunc = FunctionDecl::newFunction( name, SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
    294291                        stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );
    295292
     
    304301                                replacement = new CastExpr( replacement, base->clone() );
    305302                        }
    306                         DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
     303                        size_t replaced = DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
     304                        if(replaced == 0) {
     305                                objDecl->print(std::cerr);
     306                                std::cerr << "-----" << std::endl;
     307                                dtor->print(std::cerr);
     308                                std::cerr << "Failed to replace " << objDecl << std::endl;
     309                                abort();
     310                        }
    307311                        dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );
    308312
  • src/Makefile.in

    rc6a1e8a r866545b  
    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

    rc6a1e8a r866545b  
    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

    rc6a1e8a r866545b  
    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

    rc6a1e8a r866545b  
    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

    rc6a1e8a r866545b  
    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
  • src/SynTree/DeclReplacer.h

    rc6a1e8a r866545b  
    3333
    3434        size_t replace( BaseSyntaxNode *& node, const ExprMap & exprMap, bool debug = false);
     35
    3536        template<typename T>
    36                 void replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
    37                 if ( ! node ) return;
     37        size_t replace( T *& node, const ExprMap & exprMap, bool debug = false ) {
     38                if ( ! node ) return 0ul;
    3839                BaseSyntaxNode * arg = node;
    39                 replace( arg, exprMap, debug );
     40                size_t replaced = replace( arg, exprMap, debug );
    4041                node = dynamic_cast<T *>( arg );
    4142                assertf( node, "DeclReplacer fundamentally changed the type of its argument." );
     43                return replaced;
    4244        }
    4345}
  • src/SynTree/Expression.cc

    rc6a1e8a r866545b  
    102102        SemanticError( this, "Constant expression of non-integral type " );
    103103}
     104
     105VariableExpr::VariableExpr() : Expression(), var( nullptr ) {}
    104106
    105107VariableExpr::VariableExpr( DeclarationWithType *_var ) : Expression(), var( _var ) {
  • src/SynTree/Expression.h

    rc6a1e8a r866545b  
    299299        DeclarationWithType * var;
    300300
     301        VariableExpr();
    301302        VariableExpr( DeclarationWithType * var );
    302303        VariableExpr( const VariableExpr & other );
Note: See TracChangeset for help on using the changeset viewer.