Changeset 7f6a7c9 for src


Ignore:
Timestamp:
Sep 21, 2022, 11:02:15 AM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
95dab9e
Parents:
428adbc (diff), 0bd46fd (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' into pthread-emulation

Location:
src
Files:
3 added
83 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r428adbc r7f6a7c9  
    310310                        node->name,
    311311                        get<Attribute>().acceptL( node->attributes ),
     312                        false, // Temporary
    312313                        LinkageSpec::Spec( node->linkage.val ),
    313314                        get<Type>().accept1(node->base)
     
    731732        }
    732733
     734        const ast::Expr * visit( const ast::QualifiedNameExpr * node ) override final {
     735                auto temp = new QualifiedNameExpr(
     736                                get<Declaration>().accept1(node->type_decl),
     737                                node->name
     738                );
     739                temp->var = get<DeclarationWithType>().accept1(node->var);
     740                auto expr = visitBaseExpr( node,
     741                        temp
     742                );
     743                this->node = expr;
     744                return nullptr;
     745        }
     746
    733747        const ast::Expr * visit( const ast::AddressExpr * node ) override final {
    734748                auto expr = visitBaseExpr( node,
     
    17401754                        old->location,
    17411755                        old->name,
     1756                        old->isTyped,
    17421757                        GET_ACCEPT_V(attributes, Attribute),
    17431758                        { old->linkage.val },
     
    22662281        }
    22672282
     2283        /// xxx - type_decl should be DeclWithType in the final design
     2284        /// type_decl is set to EnumDecl as a temporary fix
     2285        virtual void visit( const QualifiedNameExpr * old ) override final {
     2286                this->node = visitBaseExpr( old,
     2287                        new ast::QualifiedNameExpr (
     2288                                old->location,
     2289                                GET_ACCEPT_1(type_decl, Decl),
     2290                                GET_ACCEPT_1(var, DeclWithType),
     2291                                old->name
     2292                        )
     2293                );
     2294        }
     2295
    22682296        virtual void visit( const CastExpr * old ) override final {
    22692297                this->node = visitBaseExpr( old,
  • src/AST/Decl.hpp

    r428adbc r7f6a7c9  
    217217
    218218        /// convenience accessor to match Type::isComplete()
    219         bool isComplete() { return sized; }
     219        bool isComplete() const { return sized; }
    220220
    221221        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
     
    312312class EnumDecl final : public AggregateDecl {
    313313public:
     314        bool isTyped;
    314315        ptr<Type> base;
    315316
    316         EnumDecl( const CodeLocation& loc, const std::string& name,
    317                 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall, Type const * base = nullptr,
     317        EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
     318                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
     319                Type const * base = nullptr,
    318320                std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() )
    319         : AggregateDecl( loc, name, std::move(attrs), linkage ), base(base), enumValues(enumValues) {}
     321        : AggregateDecl( loc, name, std::move(attrs), linkage ), isTyped(isTyped), base(base), enumValues(enumValues) {}
    320322
    321323        /// gets the integer value for this enumerator, returning true iff value found
     
    327329        const char * typeString() const override { return aggrString( Enum ); }
    328330
    329         bool isTyped() {return base && base.get();}
    330331
    331332private:
  • src/AST/DeclReplacer.cpp

    r428adbc r7f6a7c9  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May 8 13:00:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed May 8 13:00:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Sep 15 11:55:00 2022
     13// Update Count     : 2
    1414//
    1515
    1616#include "DeclReplacer.hpp"
     17
    1718#include "Expr.hpp"
     19#include "Pass.hpp"
    1820#include "Type.hpp"
    19 
    20 #include "Pass.hpp"
    2121
    2222namespace ast {
    2323
    2424namespace DeclReplacer {
    25         namespace {
    26                 struct DeclReplacer {
    27                 private:
    28                         const DeclMap & declMap;
    29                         const TypeMap & typeMap;
    30                         bool debug;
    3125
    32                 public:
    33                         DeclReplacer(const DeclMap & declMap, const TypeMap & typeMap, bool debug)
    34                                 : declMap( declMap ), typeMap( typeMap ), debug( debug )
    35                         {}
     26namespace {
     27        struct DeclReplacer {
     28        private:
     29                const DeclMap & declMap;
     30                const TypeMap & typeMap;
     31                bool debug;
    3632
    37                         const ast::VariableExpr * previsit( const ast::VariableExpr * );
    38                         const ast::TypeInstType * previsit( const ast::TypeInstType * );
    39                 };
     33        public:
     34                DeclReplacer( const DeclMap & declMap, const TypeMap & typeMap, bool debug )
     35                        : declMap( declMap ), typeMap( typeMap ), debug( debug )
     36                {}
    4037
    41                 struct VarExprReplacer {
    42                 private:
    43                         const ExprMap & exprMap;
    44                        
    45                 public:
    46                         VarExprReplacer(const ExprMap & exprMap): exprMap (exprMap) {}
     38                const ast::VariableExpr * previsit( const ast::VariableExpr * );
     39                const ast::TypeInstType * previsit( const ast::TypeInstType * );
     40        };
    4741
    48                         const Expr * postvisit (const VariableExpr *);
    49                 };
     42        struct VarExprReplacer {
     43        private:
     44                const ExprMap & exprMap;
     45
     46        public:
     47                VarExprReplacer( const ExprMap & exprMap ) : exprMap( exprMap ) {}
     48
     49                const Expr * postvisit( const VariableExpr * );
     50        };
     51} // namespace
     52
     53const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
     54        if(!node) return nullptr;
     55        Pass<DeclReplacer> replacer = { declMap, typeMap, debug };
     56        return node->accept( replacer );
     57}
     58
     59const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, bool debug ) {
     60        TypeMap typeMap;
     61        return replace( node, declMap, typeMap, debug );
     62}
     63
     64const ast::Node * replace( const ast::Node * node, const TypeMap & typeMap, bool debug ) {
     65        DeclMap declMap;
     66        return replace( node, declMap, typeMap, debug );
     67}
     68
     69const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap ) {
     70        Pass<VarExprReplacer> replacer = {exprMap};
     71        return node->accept( replacer );
     72}
     73
     74namespace {
     75        // replace variable with new node from decl map
     76        const ast::VariableExpr * DeclReplacer::previsit( const VariableExpr * varExpr ) {
     77                // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
     78                if ( !declMap.count( varExpr->var ) ) return varExpr;
     79
     80                auto replacement = declMap.at( varExpr->var );
     81                if ( debug ) {
     82                        std::cerr << "replacing variable reference: "
     83                                << (void*)varExpr->var.get() << " " << varExpr->var
     84                                << " with " << (void*)replacement << " " << replacement
     85                                << std::endl;
     86                }
     87                auto nexpr = mutate(varExpr);
     88                nexpr->var = replacement;
     89                return nexpr;
    5090        }
    5191
    52         const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug ) {
    53                 if(!node) return nullptr;
    54                 Pass<DeclReplacer> replacer = { declMap, typeMap, debug };
    55                 return node->accept( replacer );
     92        const TypeInstType * DeclReplacer::previsit( const TypeInstType * inst ) {
     93                if ( !typeMap.count( inst->base ) ) return inst;
     94
     95                auto replacement = typeMap.at( inst->base );
     96                if ( debug ) {
     97                        std::cerr << "replacing type reference: "
     98                                << (void*)inst->base.get() << " " << inst->base
     99                                << " with " << (void*)replacement << " " << replacement
     100                                << std::endl;
     101                }
     102                auto ninst = mutate(inst);
     103                ninst->base = replacement;
     104                return ninst;
    56105        }
    57106
    58         const ast::Node * replace( const ast::Node * node, const DeclMap & declMap, bool debug ) {
    59                 TypeMap typeMap;
    60                 return replace( node, declMap, typeMap, debug );
     107        const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
     108                if ( !exprMap.count( expr->var ) ) return expr;
     109                return exprMap.at( expr->var );
    61110        }
     111} // namespace
    62112
    63         const ast::Node * replace( const ast::Node * node, const TypeMap & typeMap, bool debug ) {
    64                 DeclMap declMap;
    65                 return replace( node, declMap, typeMap, debug );
    66         }
     113} // namespace DeclReplacer
    67114
    68         const ast::Node * replace( const ast::Node * node, const ExprMap & exprMap) {
    69                 Pass<VarExprReplacer> replacer = {exprMap};
    70                 return node->accept( replacer );
    71         }
    72 
    73         namespace {
    74                 // replace variable with new node from decl map
    75                 const ast::VariableExpr * DeclReplacer::previsit( const VariableExpr * varExpr ) {
    76                         // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are)
    77                         if ( !declMap.count( varExpr->var ) ) return varExpr;
    78 
    79                         auto replacement = declMap.at( varExpr->var );
    80                         if ( debug ) {
    81                                 std::cerr << "replacing variable reference: "
    82                                         << (void*)varExpr->var.get() << " " << varExpr->var
    83                                         << " with " << (void*)replacement << " " << replacement
    84                                         << std::endl;
    85                         }
    86                         auto nexpr = mutate(varExpr);
    87                         nexpr->var = replacement;
    88                         return nexpr;
    89                 }
    90 
    91                 const TypeInstType * DeclReplacer::previsit( const TypeInstType * inst ) {
    92                         if ( !typeMap.count( inst->base ) ) return inst;
    93 
    94                         auto replacement = typeMap.at( inst->base );
    95                         if ( debug ) {
    96                                 std::cerr << "replacing type reference: "
    97                                         << (void*)inst->base.get() << " " << inst->base
    98                                         << " with " << (void*)replacement << " " << replacement
    99                                         << std::endl;
    100                         }
    101                         auto ninst = mutate(inst);
    102                         ninst->base = replacement;
    103                         return ninst;
    104                 }
    105 
    106                 const Expr * VarExprReplacer::postvisit( const VariableExpr * expr ) {
    107                         if (!exprMap.count(expr->var)) return expr;
    108 
    109                         return exprMap.at(expr->var);
    110                 }
    111 
    112         }
    113 }
    114 
    115 }
     115} // namespace ast
    116116
    117117// Local Variables: //
  • src/AST/Expr.hpp

    r428adbc r7f6a7c9  
    254254};
    255255
     256class QualifiedNameExpr final : public Expr {
     257public:
     258        ptr<Decl> type_decl;
     259        ptr<DeclWithType> var;
     260        std::string name;
     261
     262        QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const DeclWithType * r, const std::string & n )
     263        : Expr( loc ), type_decl( d ), var(r), name( n ) {}
     264
     265        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     266private:
     267        QualifiedNameExpr * clone() const override { return new QualifiedNameExpr{ *this }; }
     268        MUTATE_FRIEND
     269};
     270
    256271/// A reference to a named variable.
    257272class VariableExpr final : public Expr {
  • src/AST/Fwd.hpp

    r428adbc r7f6a7c9  
    6767class UntypedExpr;
    6868class NameExpr;
     69class QualifiedNameExpr;
    6970class AddressExpr;
    7071class LabelAddressExpr;
  • src/AST/Pass.hpp

    r428adbc r7f6a7c9  
    167167        const ast::Expr *             visit( const ast::UntypedExpr          * ) override final;
    168168        const ast::Expr *             visit( const ast::NameExpr             * ) override final;
     169        const ast::Expr *                         visit( const ast::QualifiedNameExpr    * ) override final;
    169170        const ast::Expr *             visit( const ast::AddressExpr          * ) override final;
    170171        const ast::Expr *             visit( const ast::LabelAddressExpr     * ) override final;
     
    327328struct PureVisitor {};
    328329
     330/// Keep track of the nearest parent node's location field.
     331struct WithCodeLocation {
     332        const CodeLocation * location = nullptr;
     333};
     334
    329335/// Keep track of the polymorphic const TypeSubstitution * typeSubs for the current expression.
    330336struct WithConstTypeSubstitution {
  • src/AST/Pass.impl.hpp

    r428adbc r7f6a7c9  
    2525#define VISIT_START( node ) \
    2626        using namespace ast; \
     27        /* back-up the last known code location */ \
     28        __attribute__((unused)) auto loc_guard = ast::__pass::make_location_guard( core, node, 0 ); \
    2729        /* back-up the visit children */ \
    2830        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \
     
    11971199
    11981200//--------------------------------------------------------------------------
     1201// QualifiedNameExpr
     1202template< typename core_t >
     1203const ast::Expr * ast::Pass< core_t >::visit( const ast::QualifiedNameExpr * node ) {
     1204        VISIT_START( node );
     1205        if ( __visit_children() ) {
     1206                guard_symtab guard { *this };
     1207                maybe_accept( node, &QualifiedNameExpr::var );
     1208                maybe_accept( node, &QualifiedNameExpr::type_decl );
     1209        }
     1210        VISIT_END( Expr, node );
     1211}
     1212
     1213//--------------------------------------------------------------------------
    11991214// CastExpr
    12001215template< typename core_t >
  • src/AST/Pass.proto.hpp

    r428adbc r7f6a7c9  
    326326        }
    327327
     328        template< typename core_t, typename node_t >
     329        static auto make_location_guard( core_t & core, node_t * node, int )
     330                        -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) {
     331                ValueGuardPtr<const CodeLocation *> guard( &core.location );
     332                core.location = &node->location;
     333                return guard;
     334        }
     335
     336        template< typename core_t, typename node_t >
     337        static auto make_location_guard( core_t &, node_t *, long ) -> int {
     338                return 0;
     339        }
     340
    328341        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
    329342        // All passes which have such functions are assumed desire this behaviour
  • src/AST/Print.cpp

    r428adbc r7f6a7c9  
    3333{
    3434        return array<C,sizeof...(T)>{
    35                 forward<T>(values)...
     35                std::forward<T>(values)...
    3636        };
    3737}
     
    8686
    8787                static constexpr auto StorageClasses = make_array<const char*>(
    88                         "extern", "static", "auto", "register", "_Thread_local"
     88                        "extern", "static", "auto", "register", "__thread", "_Thread_local"
    8989                );
    9090
    9191                static constexpr auto Qualifiers = make_array<const char*>(
    92                         "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
     92                        "const", "restrict", "volatile", "mutex", "_Atomic"
    9393                );
    9494        };
     
    215215                        ++indent;
    216216                        ptrToEnum->base->accept( *this );
    217                         --indent; 
     217                        --indent;
    218218                }
    219219
     
    899899                postprint( node );
    900900
     901                return node;
     902        }
     903
     904        virtual const ast::Expr * visit( const ast::QualifiedNameExpr * node ) override final {
     905                os << "QualifiedNameExpr: " << std::endl;
     906                os << ++indent << "Type: ";
     907                safe_print( node->type_decl );
     908                os << std::endl;
     909                os <<  indent << "Name: " << node->name  << std::endl;
     910                --indent;
     911                postprint( node );
    901912                return node;
    902913        }
     
    16231634// if the wrong size is specified
    16241635constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
    1625 constexpr array<const char*, 5> Printer::Names::StorageClasses;
    1626 constexpr array<const char*, 6> Printer::Names::Qualifiers;
     1636constexpr array<const char*, 6> Printer::Names::StorageClasses;
     1637constexpr array<const char*, 5> Printer::Names::Qualifiers;
    16271638}
  • src/AST/StorageClasses.hpp

    r428adbc r7f6a7c9  
    2424        /// Bitflags for storage classes
    2525        enum {
    26                 Extern      = 1 << 0,
    27                 Static      = 1 << 1,
    28                 Auto        = 1 << 2,
    29                 Register    = 1 << 3,
    30                 ThreadLocal = 1 << 4,
    31                 NumClasses       = 5
     26                Extern         = 1 << 0,
     27                Static         = 1 << 1,
     28                Auto           = 1 << 2,
     29                Register       = 1 << 3,
     30                ThreadLocalGcc = 1 << 4,
     31                ThreadLocalC11 = 1 << 5,
     32                NumClasses          = 6
    3233        };
    3334
     
    3738                        unsigned int val;
    3839                        struct {
    39                                 bool is_extern      : 1;
    40                                 bool is_static      : 1;
    41                                 bool is_auto        : 1;
    42                                 bool is_register    : 1;
    43                                 bool is_threadlocal : 1;
     40                                bool is_extern         : 1;
     41                                bool is_static         : 1;
     42                                bool is_auto           : 1;
     43                                bool is_register       : 1;
     44                                bool is_threadlocalGcc : 1;
     45                                bool is_threadlocalC11 : 1;
    4446                        };
    4547
     
    4850
    4951                constexpr class_flags( unsigned int val = 0 ) : val(val) {}
     52
     53                bool is_threadlocal_any() { return this->is_threadlocalC11 || this->is_threadlocalGcc; }
    5054        };
    5155
  • src/AST/Type.cpp

    r428adbc r7f6a7c9  
    143143TraitInstType::TraitInstType(
    144144        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    145 : BaseInstType( b->name, q, move(as) ), base( b ) {}
     145: BaseInstType( b->name, q, std::move(as) ), base( b ) {}
    146146
    147147// --- TypeInstType
     
    149149TypeInstType::TypeInstType( const TypeDecl * b,
    150150        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
    151 : BaseInstType( b->name, q, move(as) ), base( b ), kind( b->kind ) {}
     151: BaseInstType( b->name, q, std::move(as) ), base( b ), kind( b->kind ) {}
    152152
    153153void TypeInstType::set_base( const TypeDecl * b ) {
     
    161161
    162162TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    163 : Type( q ), types( move(ts) ), members() {
     163: Type( q ), types( std::move(ts) ), members() {
    164164        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    165165        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r428adbc r7f6a7c9  
    8383template< enum Node::ref_type ref_t >
    8484void reset_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q = {} ) {
    85         if ( p->qualifiers.val != q.val ) p.get_and_mutate()->qualifiers = q;
     85        if ( p->qualifiers != q ) p.get_and_mutate()->qualifiers = q;
    8686}
    8787
     
    8989template< enum Node::ref_type ref_t >
    9090void add_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
    91         if ( ( p->qualifiers.val & q.val ) != q.val ) p.get_and_mutate()->qualifiers |= q;
     91        if ( ( p->qualifiers & q ) != q ) p.get_and_mutate()->qualifiers |= q;
    9292}
    9393
     
    9595template< enum Node::ref_type ref_t >
    9696void remove_qualifiers( ptr_base< Type, ref_t > & p, CV::Qualifiers q ) {
    97         if ( ( p->qualifiers.val & q.val ) != 0 ) p.get_and_mutate()->qualifiers -= q;
     97        if ( ( p->qualifiers & q ) != 0 ) p.get_and_mutate()->qualifiers -= q;
    9898}
    9999
     
    412412                std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
    413413                bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
    414 
    415414        };
    416415
  • src/AST/TypeEnvironment.hpp

    r428adbc r7f6a7c9  
    5656struct AssertCompare {
    5757        bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const {
     58                auto kind1 = ast::SymbolTable::getSpecialFunctionKind(d1->var->name);
     59                auto kind2 = ast::SymbolTable::getSpecialFunctionKind(d2->var->name);
     60                // heuristics optimization: force special functions to go last
     61                if (kind1 > kind2) return true;
     62                else if (kind1 < kind2) return false;
     63
    5864                int cmp = d1->var->name.compare( d2->var->name );
    5965                return cmp < 0 || ( cmp == 0 && d1->result < d2->result );
  • src/AST/Visitor.hpp

    r428adbc r7f6a7c9  
    5959    virtual const ast::Expr *             visit( const ast::UntypedExpr          * ) = 0;
    6060    virtual const ast::Expr *             visit( const ast::NameExpr             * ) = 0;
     61    virtual const ast::Expr *             visit( const ast::QualifiedNameExpr    * ) = 0;
    6162    virtual const ast::Expr *             visit( const ast::AddressExpr          * ) = 0;
    6263    virtual const ast::Expr *             visit( const ast::LabelAddressExpr     * ) = 0;
  • src/AST/module.mk

    r428adbc r7f6a7c9  
    2424        AST/Copy.cpp \
    2525        AST/Copy.hpp \
     26        AST/Create.cpp \
     27        AST/Create.hpp \
    2628        AST/CVQualifiers.hpp \
    2729        AST/Decl.cpp \
  • src/CodeGen/CodeGenerator.cc

    r428adbc r7f6a7c9  
    277277                std::list< Declaration* > &memb = enumDecl->get_members();
    278278                if (enumDecl->base && ! memb.empty()) {
    279                         unsigned long long last_val = -1;
     279                        unsigned long long last_val = -1; // if the first enum value has no explicit initializer,
     280                        // as other
    280281                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
    281282                                ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
    282283                                assert( obj );
    283                                 output << "static const ";
    284                                 output << genType(enumDecl->base, "", options) << " ";
     284                                output << "static ";
     285                                output << genType(enumDecl->base, "", options) << " const ";
    285286                                output << mangleName( obj ) << " ";
    286287                                output << " = ";
     
    493494                                        assert( false );
    494495                                } // switch
     496                        } else if( varExpr->get_var()->get_linkage() == LinkageSpec::BuiltinCFA && varExpr->get_var()->get_name() == "intptr" ) {
     497                                // THIS is a hack to make it a constant until a proper constexpr solution is created
     498                                output << "((void*)";
     499                                std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
     500                                (*arg++)->accept( *visitor );
     501                                output << ")";
    495502                        } else {
    496503                                varExpr->accept( *visitor );
     
    689696                        output << opInfo->symbol;
    690697                } else {
    691                         // if (dynamic_cast<EnumInstType *>(variableExpr->get_var()->get_type())
    692                         // && dynamic_cast<EnumInstType *>(variableExpr->get_var()->get_type())->baseEnum->base) {
    693                         //      output << '(' <<genType(dynamic_cast<EnumInstType *>(variableExpr->get_var()->get_type())->baseEnum->base, "", options) << ')';
    694                         // }
    695698                        output << mangleName( variableExpr->get_var() );
    696699                } // if
     
    911914        }
    912915
     916        // QualifiedNameExpr should not reach to CodeGen.
     917        // FixQualifiedName Convert QualifiedNameExpr to VariableExpr
     918        void CodeGenerator::postvisit( QualifiedNameExpr * expr ) {
     919                output << "/* label */" << mangleName(expr->var);
     920        }
    913921
    914922        // *** Statements
  • src/CodeGen/CodeGenerator.h

    r428adbc r7f6a7c9  
    103103                void postvisit( DefaultArgExpr * );
    104104                void postvisit( GenericExpr * );
     105                void postvisit( QualifiedNameExpr *);
    105106
    106107                //*** Statements
  • src/Common/CodeLocationTools.cpp

    r428adbc r7f6a7c9  
    137137    macro(UntypedExpr, Expr) \
    138138    macro(NameExpr, Expr) \
     139        macro(QualifiedNameExpr, Expr) \
    139140    macro(AddressExpr, Expr) \
    140141    macro(LabelAddressExpr, Expr) \
  • src/Common/Eval.cc

    r428adbc r7f6a7c9  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  1 08:41:03 2022
    13 // Update Count     : 117
     12// Last Modified On : Sat Aug  6 12:11:59 2022
     13// Update Count     : 119
    1414//
    1515
     
    217217                                value = arg1.first * arg2.first;
    218218                        } else if (fname == "?/?") {
    219                                 value = arg1.first / arg2.first;
     219                                if ( arg2.first ) value = arg1.first / arg2.first;
    220220                        } else if (fname == "?%?") {
    221                                 value = arg1.first % arg2.first;
     221                                if ( arg2.first ) value = arg1.first % arg2.first;
    222222                        } else if (fname == "?<<?") {
    223223                                value = arg1.first << arg2.first;
  • src/Common/PassVisitor.h

    r428adbc r7f6a7c9  
    133133        virtual void visit( NameExpr * nameExpr ) override final;
    134134        virtual void visit( const NameExpr * nameExpr ) override final;
     135        virtual void visit ( QualifiedNameExpr * qualifiedNameExpr ) override final;
     136        virtual void visit ( const QualifiedNameExpr * qualifiedNameExpr ) override final;
    135137        virtual void visit( CastExpr * castExpr ) override final;
    136138        virtual void visit( const CastExpr * castExpr ) override final;
     
    325327        virtual Expression * mutate( TupleExpr * tupleExpr ) override final;
    326328        virtual Expression * mutate( TupleIndexExpr * tupleExpr ) override final;
    327         virtual Expression * mutate( TupleAssignExpr * assignExpr ) override final;
     329        virtual Expression * mutate( TupleAssignExpr * assignExpr ) override final; 
    328330        virtual Expression * mutate( StmtExpr *  stmtExpr ) override final;
    329331        virtual Expression * mutate( UniqueExpr *  uniqueExpr ) override final;
     
    333335        virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
    334336        virtual Expression * mutate( GenericExpr * genExpr ) override final;
     337        virtual Expression * mutate( QualifiedNameExpr * qualifiedNameExpr ) override final;
    335338
    336339        virtual Type * mutate( VoidType * basicType ) override final;
  • src/Common/PassVisitor.impl.h

    r428adbc r7f6a7c9  
    19271927
    19281928//--------------------------------------------------------------------------
     1929// QualifiedNameExpr
     1930template< typename pass_type >
     1931void PassVisitor< pass_type >::visit( QualifiedNameExpr * node ) {
     1932        VISIT_START( node );
     1933
     1934        indexerScopedAccept( node->result, *this );
     1935        maybeAccept_impl( node->type_decl, *this );
     1936        maybeAccept_impl( node->var, *this );
     1937
     1938        VISIT_END( node );
     1939}
     1940
     1941template< typename pass_type >
     1942void PassVisitor< pass_type >::visit( const QualifiedNameExpr * node ) {
     1943        VISIT_START( node );
     1944
     1945        indexerScopedAccept( node->result, *this );
     1946        maybeAccept_impl( node->type_decl, *this );
     1947        maybeAccept_impl( node->var, *this );
     1948
     1949        VISIT_END( node );
     1950}
     1951
     1952template< typename pass_type >
     1953Expression * PassVisitor< pass_type >::mutate( QualifiedNameExpr * node ) {
     1954        MUTATE_START( node );
     1955
     1956    indexerScopedMutate( node->env   , *this );
     1957    indexerScopedMutate( node->result, *this );
     1958        maybeMutate_impl( node->type_decl, *this );
     1959        maybeAccept_impl( node->var, *this );
     1960
     1961        MUTATE_END( Expression, node );
     1962}
     1963
     1964//--------------------------------------------------------------------------
    19291965// CastExpr
    19301966template< typename pass_type >
  • src/Common/ScopedMap.h

    r428adbc r7f6a7c9  
    1010// Created On       : Wed Dec 2 11:37:00 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon May 21 15:22:40 2018
    13 // Update Count     : 3
     12// Last Modified On : Tue Feb 15 08:41:28 2022
     13// Update Count     : 5
    1414//
    1515
     
    3636
    3737                template<typename N>
    38                 Scope(N&& n) : map(), note(std::forward<N>(n)) {}
     38                Scope(N && n) : map(), note(std::forward<N>(n)) {}
    3939               
    4040                Scope() = default;
    41                 Scope(const Scope&) = default;
    42                 Scope(Scope&&) = default;
    43                 Scope& operator= (const Scope&) = default;
    44                 Scope& operator= (Scope&&) = default;
     41                Scope(const Scope &) = default;
     42                Scope(Scope &&) = default;
     43                Scope & operator= (const Scope &) = default;
     44                Scope & operator= (Scope &&) = default;
    4545        };
    4646        typedef std::vector< Scope > ScopeList;
     
    5858        typedef typename MapType::const_pointer const_pointer;
    5959
    60         class iterator : public std::iterator< std::bidirectional_iterator_tag,
    61                                                value_type > {
     60        class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > {
    6261        friend class ScopedMap;
    6362        friend class const_iterator;
     
    7271
    7372                /// Increments on invalid
    74                 iterator& next_valid() {
     73                iterator & next_valid() {
    7574                        if ( ! is_valid() ) { ++(*this); }
    7675                        return *this;
     
    7877
    7978                /// Decrements on invalid
    80                 iterator& prev_valid() {
     79                iterator & prev_valid() {
    8180                        if ( ! is_valid() ) { --(*this); }
    8281                        return *this;
    8382                }
    8483
    85                 iterator(scope_list &_scopes, const wrapped_iterator &_it, size_type inLevel)
     84                iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
    8685                        : scopes(&_scopes), it(_it), level(inLevel) {}
    8786        public:
    88                 iterator(const iterator &that) : scopes(that.scopes), it(that.it), level(that.level) {}
    89                 iterator& operator= (const iterator &that) {
     87                iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     88                iterator & operator= (const iterator & that) {
    9089                        scopes = that.scopes; level = that.level; it = that.it;
    9190                        return *this;
     
    9594                pointer operator-> () const { return it.operator->(); }
    9695
    97                 iterator& operator++ () {
     96                iterator & operator++ () {
    9897                        if ( it == (*scopes)[level].map.end() ) {
    9998                                if ( level == 0 ) return *this;
     
    107106                iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    108107
    109                 iterator& operator-- () {
     108                iterator & operator-- () {
    110109                        // may fail if this is the begin iterator; allowed by STL spec
    111110                        if ( it == (*scopes)[level].map.begin() ) {
     
    118117                iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    119118
    120                 bool operator== (const iterator &that) const {
     119                bool operator== (const iterator & that) const {
    121120                        return scopes == that.scopes && level == that.level && it == that.it;
    122121                }
    123                 bool operator!= (const iterator &that) const { return !( *this == that ); }
     122                bool operator!= (const iterator & that) const { return !( *this == that ); }
    124123
    125124                size_type get_level() const { return level; }
    126125
    127                 Note& get_note() { return (*scopes)[level].note; }
    128                 const Note& get_note() const { return (*scopes)[level].note; }
     126                Note & get_note() { return (*scopes)[level].note; }
     127                const Note & get_note() const { return (*scopes)[level].note; }
    129128
    130129        private:
     
    148147
    149148                /// Increments on invalid
    150                 const_iterator& next_valid() {
     149                const_iterator & next_valid() {
    151150                        if ( ! is_valid() ) { ++(*this); }
    152151                        return *this;
     
    154153
    155154                /// Decrements on invalid
    156                 const_iterator& prev_valid() {
     155                const_iterator & prev_valid() {
    157156                        if ( ! is_valid() ) { --(*this); }
    158157                        return *this;
    159158                }
    160159
    161                 const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type inLevel)
     160                const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
    162161                        : scopes(&_scopes), it(_it), level(inLevel) {}
    163162        public:
    164                 const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), level(that.level) {}
    165                 const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), level(that.level) {}
    166                 const_iterator& operator= (const iterator &that) {
     163                const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     164                const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     165                const_iterator & operator= (const iterator & that) {
    167166                        scopes = that.scopes; level = that.level; it = that.it;
    168167                        return *this;
    169168                }
    170                 const_iterator& operator= (const const_iterator &that) {
     169                const_iterator & operator= (const const_iterator & that) {
    171170                        scopes = that.scopes; level = that.level; it = that.it;
    172171                        return *this;
     
    176175                const_pointer operator-> () { return it.operator->(); }
    177176
    178                 const_iterator& operator++ () {
     177                const_iterator & operator++ () {
    179178                        if ( it == (*scopes)[level].map.end() ) {
    180179                                if ( level == 0 ) return *this;
     
    188187                const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    189188
    190                 const_iterator& operator-- () {
     189                const_iterator & operator-- () {
    191190                        // may fail if this is the begin iterator; allowed by STL spec
    192191                        if ( it == (*scopes)[level].map.begin() ) {
     
    199198                const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    200199
    201                 bool operator== (const const_iterator &that) const {
     200                bool operator== (const const_iterator & that) const {
    202201                        return scopes == that.scopes && level == that.level && it == that.it;
    203202                }
    204                 bool operator!= (const const_iterator &that) const { return !( *this == that ); }
     203                bool operator!= (const const_iterator & that) const { return !( *this == that ); }
    205204
    206205                size_type get_level() const { return level; }
    207206
    208                 const Note& get_note() const { return (*scopes)[level].note; }
     207                const Note & get_note() const { return (*scopes)[level].note; }
    209208
    210209        private:
     
    221220        // Starts a new scope with the given note
    222221        template<typename N>
    223         void beginScope( N&& n ) {
     222        void beginScope( N && n ) {
    224223                scopes.emplace_back( std::forward<N>(n) );
    225224        }
     
    236235        /// Constructs with a given note on the outermost scope
    237236        template<typename N>
    238         ScopedMap( N&& n ) : scopes() { beginScope(std::forward<N>(n)); }
     237        ScopedMap( N && n ) : scopes() { beginScope(std::forward<N>(n)); }
    239238
    240239        iterator begin() { return iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); }
     
    249248
    250249        /// Gets the note at the given scope
    251         Note& getNote() { return scopes.back().note; }
    252         const Note& getNote() const { return scopes.back().note; }
    253         Note& getNote( size_type i ) { return scopes[i].note; }
    254         const Note& getNote( size_type i ) const { return scopes[i].note; }
     250        Note & getNote() { return scopes.back().note; }
     251        const Note & getNote() const { return scopes.back().note; }
     252        Note & getNote( size_type i ) { return scopes[i].note; }
     253        const Note & getNote( size_type i ) const { return scopes[i].note; }
    255254
    256255        /// Finds the given key in the outermost scope it occurs; returns end() for none such
    257         iterator find( const Key &key ) {
     256        iterator find( const Key & key ) {
    258257                for ( size_type i = scopes.size() - 1; ; --i ) {
    259258                        typename MapType::iterator val = scopes[i].map.find( key );
     
    263262                return end();
    264263        }
    265         const_iterator find( const Key &key ) const {
     264        const_iterator find( const Key & key ) const {
    266265                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) );
    267266        }
    268267
    269268        /// Finds the given key in the provided scope; returns end() for none such
    270         iterator findAt( size_type scope, const Key& key ) {
     269        iterator findAt( size_type scope, const Key & key ) {
    271270                typename MapType::iterator val = scopes[scope].map.find( key );
    272271                if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope );
    273272                return end();
    274273        }
    275         const_iterator findAt( size_type scope, const Key& key ) const {
     274        const_iterator findAt( size_type scope, const Key & key ) const {
    276275                return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) );
    277276        }
    278277
    279278        /// Finds the given key in the outermost scope inside the given scope where it occurs
    280         iterator findNext( const_iterator &it, const Key &key ) {
     279        iterator findNext( const_iterator & it, const Key & key ) {
    281280                if ( it.level == 0 ) return end();
    282281                for ( size_type i = it.level - 1; ; --i ) {
     
    287286                return end();
    288287        }
    289         const_iterator findNext( const_iterator &it, const Key &key ) const {
     288        const_iterator findNext( const_iterator & it, const Key & key ) const {
    290289                        return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) );
    291290        }
     
    293292        /// Inserts the given key-value pair into the outermost scope
    294293        template< typename value_type_t >
    295         std::pair< iterator, bool > insert( value_type_t&& value ) {
     294        std::pair< iterator, bool > insert( value_type_t && value ) {
    296295                std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) );
    297296                return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) );
     
    299298
    300299        template< typename value_type_t >
    301         std::pair< iterator, bool > insert( iterator at, value_type_t&& value ) {
    302                 MapType& scope = (*at.scopes)[ at.level ].map;
     300        std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {
     301                MapType & scope = (*at.scopes)[ at.level ].map;
    303302                std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    304303                return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
     
    306305
    307306        template< typename value_t >
    308         std::pair< iterator, bool > insert( const Key &key, value_t&& value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
     307        std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
    309308
    310309        template< typename value_type_t >
    311         std::pair< iterator, bool > insertAt( size_type scope, value_type_t&& value ) {
     310        std::pair< iterator, bool > insertAt( size_type scope, value_type_t && value ) {
    312311                std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) );
    313312                return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) );
     
    315314
    316315        template< typename value_t >
    317         std::pair< iterator, bool > insertAt( size_type scope, const Key& key, value_t&& value ) {
     316        std::pair< iterator, bool > insertAt( size_type scope, const Key & key, value_t && value ) {
    318317                return insertAt( scope, std::make_pair( key, std::forward<value_t>( value ) ) );
    319318        }
    320319
    321         Value& operator[] ( const Key &key ) {
     320        Value & operator[] ( const Key & key ) {
    322321                iterator slot = find( key );
    323322                if ( slot != end() ) return slot->second;
     
    326325
    327326        iterator erase( iterator pos ) {
    328                 MapType& scope = (*pos.scopes)[ pos.level ].map;
    329                 const typename iterator::wrapped_iterator& new_it = scope.erase( pos.it );
     327                MapType & scope = (*pos.scopes)[ pos.level ].map;
     328                const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );
    330329                iterator it( *pos.scopes, new_it, pos.level );
    331330                return it.next_valid();
    332331        }
    333332
    334         size_type count( const Key &key ) const {
     333        size_type count( const Key & key ) const {
    335334                size_type c = 0;
    336335                auto it = find( key );
     
    344343                return c;
    345344        }
    346 
    347345};
    348346
  • src/Common/utility.h

    r428adbc r7f6a7c9  
    322322
    323323        ValueGuardPtr(T * inRef) : old( inRef ? *inRef : T() ), ref(inRef) {}
     324        ValueGuardPtr(const ValueGuardPtr& other) = delete;
     325        ValueGuardPtr(ValueGuardPtr&& other) : old(other.old), ref(other.ref) { other.ref = nullptr; }
    324326        ~ValueGuardPtr() { if( ref ) *ref = old; }
    325327};
  • src/CompilationState.cc

    r428adbc r7f6a7c9  
    3131        genproto = false,
    3232        deterministic_output = false,
    33         useNewAST = CFA_USE_NEW_AST,
     33        useNewAST = true,
    3434        nomainp = false,
    3535        parsep = false,
  • src/Concurrency/Keywords.cc

    r428adbc r7f6a7c9  
    508508                ObjectDecl * vtable_object = Virtual::makeVtableForward(
    509509                        "_default_vtable_object_declaration",
    510                         vtable_decl->makeInst( move( poly_args ) ) );
     510                        vtable_decl->makeInst( std::move( poly_args ) ) );
    511511                declsToAddBefore.push_back( vtable_object );
    512512                declsToAddBefore.push_back(
     
    681681                        void lock (monitor_t & this) {
    682682                                lock(get_monitor(this));
    683                         }       
     683                        }
    684684                */
    685685                FunctionDecl * lock_decl = new FunctionDecl(
     
    700700                CompoundStmt * lock_statement = new CompoundStmt();
    701701                lock_statement->push_back(
    702                         new ExprStmt( 
     702                        new ExprStmt(
    703703                                new UntypedExpr (
    704704                                        new NameExpr( "lock" ),
     
    716716                        void unlock (monitor_t & this) {
    717717                                unlock(get_monitor(this));
    718                         }       
     718                        }
    719719                */
    720720                FunctionDecl * unlock_decl = new FunctionDecl(
     
    736736
    737737                unlock_statement->push_back(
    738                         new ExprStmt( 
     738                        new ExprStmt(
    739739                                new UntypedExpr(
    740740                                        new NameExpr( "unlock" ),
     
    746746                );
    747747                unlock_decl->set_statements( unlock_statement );
    748                
     748
    749749                // pushes routines to declsToAddAfter to add at a later time
    750750                declsToAddAfter.push_back( lock_decl );
     
    10541054                        assert( !thread_guard_decl );
    10551055                        thread_guard_decl = decl;
    1056                 } 
     1056                }
    10571057                else if ( decl->name == "__mutex_stmt_lock_guard" && decl->body ) {
    10581058                        assert( !lock_guard_decl );
     
    12061206                                                        new NameExpr( "__get_mutexstmt_lock_type" ),
    12071207                                                        { args.front()->clone() }
    1208                                                 ) 
     1208                                                )
    12091209                                        )
    12101210                                ),
     
    12251225
    12261226                StructInstType * lock_guard_struct = new StructInstType( noQualifiers, lock_guard_decl );
    1227                 TypeExpr * lock_type_expr = new TypeExpr( 
     1227                TypeExpr * lock_type_expr = new TypeExpr(
    12281228                        new TypeofType( noQualifiers, new UntypedExpr(
    12291229                                new NameExpr( "__get_mutexstmt_lock_type" ),
    12301230                                { args.front()->clone() }
    1231                                 ) 
    1232                         ) 
     1231                                )
     1232                        )
    12331233                );
    12341234
  • src/Concurrency/Waitfor.cc

    r428adbc r7f6a7c9  
    402402
    403403                clause.target.function = nullptr;
    404                 clause.target.arguments.empty();
     404                clause.target.arguments.clear();
    405405                clause.condition = nullptr;
    406406        }
  • src/Concurrency/WaitforNew.cpp

    r428adbc r7f6a7c9  
    101101namespace {
    102102
    103 class GenerateWaitForCore :
     103class GenerateWaitForCore final :
    104104                public ast::WithSymbolTable, public ast::WithConstTranslationUnit {
    105105        const ast::FunctionDecl * decl_waitfor    = nullptr;
  • src/ControlStruct/ExceptTranslateNew.cpp

    r428adbc r7f6a7c9  
    3232        }
    3333
    34 class TranslateThrowsCore : public ast::WithGuards {
     34class TranslateThrowsCore final : public ast::WithGuards {
    3535        const ast::ObjectDecl * terminateHandlerExcept;
    3636        enum Context { NoHandler, TerHandler, ResHandler } currentContext;
     
    136136
    137137
    138 class TryMutatorCore {
     138class TryMutatorCore final {
    139139        // The built in types used in translation.
    140140        const ast::StructDecl * except_decl;
  • src/ControlStruct/LabelFixer.cc

    r428adbc r7f6a7c9  
    119119
    120120// Builds a table that maps a label to its defining statement.
    121 std::map<Label, Statement * > * LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
     121std::map<Label, Statement * > * LabelFixer::resolveJumps() {
    122122        std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
    123123        for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
  • src/ControlStruct/LabelFixer.h

    r428adbc r7f6a7c9  
    3333        LabelFixer( LabelGenerator *gen = 0 );
    3434
    35         std::map < Label, Statement * > *resolveJumps() throw ( SemanticErrorException );
     35        std::map < Label, Statement * > *resolveJumps();
    3636
    3737        // Declarations
  • src/ControlStruct/LabelGeneratorNew.cpp

    r428adbc r7f6a7c9  
    1414//
    1515
    16 using namespace std;
    17 
    1816#include "LabelGeneratorNew.hpp"
    1917
     
    2119#include "AST/Label.hpp"
    2220#include "AST/Stmt.hpp"
     21
     22using namespace std;
    2323using namespace ast;
    2424
  • src/ControlStruct/MLEMutator.cc

    r428adbc r7f6a7c9  
    141141
    142142
    143         Statement *MultiLevelExitMutator::postmutate( BranchStmt *branchStmt )
    144                         throw ( SemanticErrorException ) {
     143        Statement *MultiLevelExitMutator::postmutate( BranchStmt *branchStmt ) {
    145144                std::string originalTarget = branchStmt->originalTarget;
    146145
  • src/ControlStruct/MLEMutator.h

    r428adbc r7f6a7c9  
    4141
    4242                void premutate( CompoundStmt *cmpndStmt );
    43                 Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticErrorException );
     43                Statement * postmutate( BranchStmt *branchStmt );
    4444                void premutate( WhileDoStmt *whileDoStmt );
    4545                Statement * postmutate( WhileDoStmt *whileDoStmt );
  • src/ControlStruct/MultiLevelExit.cpp

    r428adbc r7f6a7c9  
    356356        vec.emplace_back( nullptr );
    357357        for ( size_t i = vec.size() - 1 ; 0 < i ; --i ) {
    358                 vec[ i ] = move( vec[ i - 1 ] );
     358                vec[ i ] = std::move( vec[ i - 1 ] );
    359359        }
    360360        vec[ 0 ] = element;
     
    511511
    512512void MultiLevelExitCore::previsit( const FinallyClause * ) {
    513         GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); });
     513        GuardAction([this, old = std::move( enclosing_control_structures)](){ enclosing_control_structures = std::move(old); });
    514514        enclosing_control_structures = vector<Entry>();
    515515        GuardValue( inFinally ) = true;
  • src/GenPoly/GenPoly.cc

    r428adbc r7f6a7c9  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 29 21:45:53 2016
    13 // Update Count     : 14
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Sep 14  9:24:00 2022
     13// Update Count     : 15
    1414//
    1515
     
    8383                }
    8484
     85                bool hasDynParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs ) {
     86                        for ( ast::ptr<ast::Expr> const & param : params ) {
     87                                auto paramType = param.as<ast::TypeExpr>();
     88                                assertf( paramType, "Aggregate parameters should be type expressions." );
     89                                if ( isDynType( paramType->type, tyVars, typeSubs ) ) {
     90                                        return true;
     91                                }
     92                        }
     93                        return false;
     94                }
     95
    8596                /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
    8697                bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
     
    198209                }
    199210                return 0;
     211        }
     212
     213        const ast::BaseInstType *isDynType( const ast::Type *type, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs ) {
     214                type = replaceTypeInst( type, typeSubs );
     215
     216                if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) {
     217                        auto var = tyVars.find( inst->name );
     218                        if ( var != tyVars.end() && var->second.isComplete ) {
     219                                return inst;
     220                        }
     221                } else if ( auto inst = dynamic_cast<ast::StructInstType const *>( type ) ) {
     222                        if ( hasDynParams( inst->params, tyVars, typeSubs ) ) {
     223                                return inst;
     224                        }
     225                } else if ( auto inst = dynamic_cast<ast::UnionInstType const *>( type ) ) {
     226                        if ( hasDynParams( inst->params, tyVars, typeSubs ) ) {
     227                                return inst;
     228                        }
     229                }
     230                return nullptr;
    200231        }
    201232
     
    378409                inline D* as( B* p ) { return reinterpret_cast<D*>(p); }
    379410
     411                template<typename D, typename B>
     412                inline D const * as( B const * p ) {
     413                        return reinterpret_cast<D const *>( p );
     414                }
     415
    380416                /// Flattens a declaration list
    381417                template<typename Output>
     
    391427                        for ( Type* ty : src ) {
    392428                                ResolvExpr::flatten( ty, out );
     429                        }
     430                }
     431
     432                void flattenList( vector<ast::ptr<ast::Type>> const & src,
     433                                vector<ast::ptr<ast::Type>> & out ) {
     434                        for ( auto const & type : src ) {
     435                                ResolvExpr::flatten( type, out );
    393436                        }
    394437                }
     
    409452                                // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
    410453                                if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
     454                        }
     455
     456                        return true;
     457                }
     458
     459                bool paramListsPolyCompatible(
     460                                std::vector<ast::ptr<ast::Expr>> const & lparams,
     461                                std::vector<ast::ptr<ast::Expr>> const & rparams ) {
     462                        if ( lparams.size() != rparams.size() ) {
     463                                return false;
     464                        }
     465
     466                        for ( auto lparam = lparams.begin(), rparam = rparams.begin() ;
     467                                        lparam != lparams.end() ; ++lparam, ++rparam ) {
     468                                ast::TypeExpr const * lexpr = lparam->as<ast::TypeExpr>();
     469                                assertf( lexpr, "Aggregate parameters should be type expressions" );
     470                                ast::TypeExpr const * rexpr = rparam->as<ast::TypeExpr>();
     471                                assertf( rexpr, "Aggregate parameters should be type expressions" );
     472
     473                                // xxx - might need to let VoidType be a wildcard here too; could have some voids
     474                                // stuffed in for dtype-statics.
     475                                // if ( is<VoidType>( lexpr->type() ) || is<VoidType>( bparam->get_type() ) ) continue;
     476                                if ( !typesPolyCompatible( lexpr->type, rexpr->type ) ) {
     477                                        return false;
     478                                }
    411479                        }
    412480
     
    505573        }
    506574
     575bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ) {
     576        type_index const lid = typeid(*lhs);
     577
     578        // Polymorphic types always match:
     579        if ( type_index(typeid(ast::TypeInstType)) == lid ) return true;
     580
     581        type_index const rid = typeid(*rhs);
     582        if ( type_index(typeid(ast::TypeInstType)) == rid ) return true;
     583
     584        // All other types only match if they are the same type:
     585        if ( lid != rid ) return false;
     586
     587        // So remaining types can be examined case by case.
     588        // Recurse through type structure (conditions borrowed from Unify.cc).
     589
     590        if ( type_index(typeid(ast::BasicType)) == lid ) {
     591                return as<ast::BasicType>(lhs)->kind == as<ast::BasicType>(rhs)->kind;
     592        } else if ( type_index(typeid(ast::PointerType)) == lid ) {
     593                ast::PointerType const * l = as<ast::PointerType>(lhs);
     594                ast::PointerType const * r = as<ast::PointerType>(rhs);
     595
     596                // void pointers should match any other pointer type.
     597                return is<ast::VoidType>( l->base.get() )
     598                        || is<ast::VoidType>( r->base.get() )
     599                        || typesPolyCompatible( l->base.get(), r->base.get() );
     600        } else if ( type_index(typeid(ast::ReferenceType)) == lid ) {
     601                ast::ReferenceType const * l = as<ast::ReferenceType>(lhs);
     602                ast::ReferenceType const * r = as<ast::ReferenceType>(rhs);
     603
     604                // void references should match any other reference type.
     605                return is<ast::VoidType>( l->base.get() )
     606                        || is<ast::VoidType>( r->base.get() )
     607                        || typesPolyCompatible( l->base.get(), r->base.get() );
     608        } else if ( type_index(typeid(ast::ArrayType)) == lid ) {
     609                ast::ArrayType const * l = as<ast::ArrayType>(lhs);
     610                ast::ArrayType const * r = as<ast::ArrayType>(rhs);
     611
     612                if ( l->isVarLen ) {
     613                        if ( !r->isVarLen ) return false;
     614                } else {
     615                        if ( r->isVarLen ) return false;
     616
     617                        auto lc = l->dimension.as<ast::ConstantExpr>();
     618                        auto rc = r->dimension.as<ast::ConstantExpr>();
     619                        if ( lc && rc && lc->intValue() != rc->intValue() ) {
     620                                return false;
     621                        }
     622                }
     623
     624                return typesPolyCompatible( l->base.get(), r->base.get() );
     625        } else if ( type_index(typeid(ast::FunctionType)) == lid ) {
     626                ast::FunctionType const * l = as<ast::FunctionType>(lhs);
     627                ast::FunctionType const * r = as<ast::FunctionType>(rhs);
     628
     629                std::vector<ast::ptr<ast::Type>> lparams, rparams;
     630                flattenList( l->params, lparams );
     631                flattenList( r->params, rparams );
     632                if ( lparams.size() != rparams.size() ) return false;
     633                for ( unsigned i = 0; i < lparams.size(); ++i ) {
     634                        if ( !typesPolyCompatible( lparams[i], rparams[i] ) ) return false;
     635                }
     636
     637                std::vector<ast::ptr<ast::Type>> lrets, rrets;
     638                flattenList( l->returns, lrets );
     639                flattenList( r->returns, rrets );
     640                if ( lrets.size() != rrets.size() ) return false;
     641                for ( unsigned i = 0; i < lrets.size(); ++i ) {
     642                        if ( !typesPolyCompatible( lrets[i], rrets[i] ) ) return false;
     643                }
     644                return true;
     645        } else if ( type_index(typeid(ast::StructInstType)) == lid ) {
     646                ast::StructInstType const * l = as<ast::StructInstType>(lhs);
     647                ast::StructInstType const * r = as<ast::StructInstType>(rhs);
     648
     649                if ( l->name != r->name ) return false;
     650                return paramListsPolyCompatible( l->params, r->params );
     651        } else if ( type_index(typeid(ast::UnionInstType)) == lid ) {
     652                ast::UnionInstType const * l = as<ast::UnionInstType>(lhs);
     653                ast::UnionInstType const * r = as<ast::UnionInstType>(rhs);
     654
     655                if ( l->name != r->name ) return false;
     656                return paramListsPolyCompatible( l->params, r->params );
     657        } else if ( type_index(typeid(ast::EnumInstType)) == lid ) {
     658                ast::EnumInstType const * l = as<ast::EnumInstType>(lhs);
     659                ast::EnumInstType const * r = as<ast::EnumInstType>(rhs);
     660
     661                return l->name == r->name;
     662        } else if ( type_index(typeid(ast::TraitInstType)) == lid ) {
     663                ast::TraitInstType const * l = as<ast::TraitInstType>(lhs);
     664                ast::TraitInstType const * r = as<ast::TraitInstType>(rhs);
     665
     666                return l->name == r->name;
     667        } else if ( type_index(typeid(ast::TupleType)) == lid ) {
     668                ast::TupleType const * l = as<ast::TupleType>(lhs);
     669                ast::TupleType const * r = as<ast::TupleType>(rhs);
     670
     671                std::vector<ast::ptr<ast::Type>> ltypes, rtypes;
     672                flattenList( l->types, ( ltypes ) );
     673                flattenList( r->types, ( rtypes ) );
     674                if ( ltypes.size() != rtypes.size() ) return false;
     675
     676                for ( unsigned i = 0 ; i < ltypes.size() ; ++i ) {
     677                        if ( !typesPolyCompatible( ltypes[i], rtypes[i] ) ) return false;
     678                }
     679                return true;
     680        // The remaining types (VoidType, VarArgsType, ZeroType & OneType)
     681        // have no variation so will always be equal.
     682        } else {
     683                return true;
     684        }
     685}
     686
    507687        namespace {
    508688                // temporary hack to avoid re-implementing anything related to TyVarMap
  • src/GenPoly/GenPoly.h

    r428adbc r7f6a7c9  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:22:57 2017
    13 // Update Count     : 7
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 16:03:00 2022
     13// Update Count     : 8
    1414//
    1515
     
    2727namespace GenPoly {
    2828
     29        // TODO Via some tricks this works for ast::TypeDecl::Data as well.
    2930        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
     31
    3032        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3133        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     
    4143        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
    4244        ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
     45        const ast::BaseInstType *isDynType( const ast::Type *type, const TyVarMap &tyVars, const ast::TypeSubstitution *typeSubs = 0 );
    4346
    4447        /// true iff function has dynamic-layout return type under the given type variable map
     
    8386        /// true iff types are structurally identical, where TypeInstType's match any type.
    8487        bool typesPolyCompatible( Type *aty, Type *bty );
     88        bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );
    8589
    8690        /// true if arg requires boxing given exprTyVars
  • src/GenPoly/InstantiateGeneric.h

    r428adbc r7f6a7c9  
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace GenPoly {
    23         /// Replaces all generic types that have static layout with concrete instantiations.
    24         /// Types with concrete values for otype parameters will be template-expanded, while
    25         /// dtype and ftype parameters will be replaced by the appropriate void type.
    26         void instantiateGeneric( std::list< Declaration* > &translationUnit );
     26/// Replaces all generic types that have static layout with concrete
     27/// instantiations. Types with concrete values for otype parameters will be
     28/// template-expanded, while dtype and ftype parameters will be replaced by
     29/// the appropriate void type.
     30void instantiateGeneric( std::list< Declaration* > &translationUnit );
     31void instantiateGeneric( ast::TranslationUnit & translationUnit );
    2732} // namespace GenPoly
    2833
  • src/GenPoly/Lvalue2.cc

    r428adbc r7f6a7c9  
    2323}
    2424
    25 
    2625}
  • src/GenPoly/ScrubTyVars.cc

    r428adbc r7f6a7c9  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 15:44:27 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 16:10:00 2022
     13// Update Count     : 4
    1414//
    1515
    1616#include <utility>                      // for pair
    1717
     18#include "AST/Pass.hpp"
    1819#include "GenPoly.h"                    // for mangleType, TyVarMap, alignof...
    1920#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2021#include "ScrubTyVars.h"
     22#include "SymTab/Mangler.h"             // for mangle, typeMode
    2123#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    2224#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
     
    112114                return pointer;
    113115        }
     116
     117namespace {
     118
     119enum class ScrubMode {
     120        FromMap,
     121        DynamicFromMap,
     122        All,
     123};
     124
     125struct ScrubTypeVars :
     126        public ast::WithGuards,
     127        public ast::WithShortCircuiting,
     128        public ast::WithVisitorRef<ScrubTypeVars> {
     129
     130        ScrubTypeVars( ScrubMode m, TyVarMap const * tv ) :
     131                        mode ( m ), typeVars( tv ) {}
     132
     133        void previsit( ast::TypeInstType const * ) { visit_children = false; }
     134        void previsit( ast::StructInstType const * ) { visit_children = false; }
     135        void previsit( ast::UnionInstType const * ) { visit_children = false; }
     136        void previsit( ast::SizeofExpr const * expr ) { primeBaseScrub( expr->type ); }
     137        void previsit( ast::AlignofExpr const * expr ) { primeBaseScrub( expr->type ); }
     138        void previsit( ast::PointerType const * type ) { primeBaseScrub( type->base ); }
     139
     140        ast::Type const * postvisit( ast::TypeInstType const * type );
     141        ast::Type const * postvisit( ast::StructInstType const * type );
     142        ast::Type const * postvisit( ast::UnionInstType const * type );
     143        ast::Expr const * postvisit( ast::SizeofExpr const * expr );
     144        ast::Expr const * postvisit( ast::AlignofExpr const * expr );
     145        ast::Type const * postvisit( ast::PointerType const * type );
     146
     147private:
     148        ScrubMode const mode;
     149        /// Type varriables to scrub.
     150        TyVarMap const * const typeVars;
     151        /// Value cached by primeBaseScrub.
     152        ast::Type const * dynType = nullptr;
     153
     154        /// Returns the type if it should be scrubbed, nullptr otherwise.
     155        ast::Type const * shouldScrub( ast::Type const * type ) {
     156                switch ( mode ) {
     157                case ScrubMode::FromMap:
     158                        return isPolyType( type, *typeVars );
     159                case ScrubMode::DynamicFromMap:
     160                        return isDynType( type, *typeVars );
     161                case ScrubMode::All:
     162                        return isPolyType( type );
     163                default:
     164                        assertf( false, "Invalid ScrubMode in shouldScrub." );
     165                        throw;
     166                }
     167        }
     168
     169        void primeBaseScrub( ast::Type const * type ) {
     170                // Need to determine whether type needs to be scrubbed to
     171                // determine whether automatic recursion is necessary.
     172                if ( ast::Type const * t = shouldScrub( type ) ) {
     173                        visit_children = false;
     174                        GuardValue( dynType ) = t;
     175                }
     176        }
     177
     178        ast::Type const * postvisitAggregateType(
     179                        ast::BaseInstType const * type ) {
     180                if ( !shouldScrub( type ) ) return type;
     181                return new ast::PointerType( new ast::VoidType( type->qualifiers ) );
     182        }
     183};
     184
     185ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
     186        // This implies that mode == ScrubMode::All.
     187        if ( !typeVars ) {
     188                if ( ast::TypeDecl::Ftype == type->kind ) {
     189                        return new ast::PointerType(
     190                                new ast::FunctionType( ast::FixedArgs ) );
     191                } else {
     192                        return new ast::PointerType(
     193                                new ast::VoidType( type->qualifiers ) );
     194                }
     195        }
     196
     197        auto typeVar = typeVars->find( type->name );
     198        if ( typeVar == typeVars->end() ) {
     199                return type;
     200        }
     201
     202        switch ( typeVar->second.kind ) {
     203        case ::TypeDecl::Dtype:
     204        case ::TypeDecl::Ttype:
     205                return new ast::PointerType(
     206                        new ast::VoidType( type->qualifiers ) );
     207        case ::TypeDecl::Ftype:
     208                return new ast::PointerType(
     209                        new ast::FunctionType( ast::VariableArgs ) );
     210        default:
     211                assertf( false,
     212                        "Unhandled type variable kind: %d", typeVar->second.kind );
     213                throw; // Just in case the assert is removed, stop here.
     214        }
     215}
     216
     217ast::Type const * ScrubTypeVars::postvisit( ast::StructInstType const * type ) {
     218        return postvisitAggregateType( type );
     219}
     220
     221ast::Type const * ScrubTypeVars::postvisit( ast::UnionInstType const * type ) {
     222        return postvisitAggregateType( type );
     223}
     224
     225ast::Expr const * ScrubTypeVars::postvisit( ast::SizeofExpr const * expr ) {
     226        // sizeof( T ) becomes the _sizeof_T parameter.
     227        if ( dynType ) {
     228                return new ast::NameExpr( expr->location,
     229                        sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     230        } else {
     231                return expr;
     232        }
     233}
     234
     235ast::Expr const * ScrubTypeVars::postvisit( ast::AlignofExpr const * expr ) {
     236        // alignof( T ) becomes the _alignof_T parameter.
     237        if ( dynType ) {
     238                return new ast::NameExpr( expr->location,
     239                        alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     240        } else {
     241                return expr;
     242        }
     243}
     244
     245ast::Type const * ScrubTypeVars::postvisit( ast::PointerType const * type ) {
     246        if ( dynType ) {
     247                ast::Type * ret = ast::mutate( dynType->accept( *visitor ) );
     248                ret->qualifiers |= type->qualifiers;
     249                return ret;
     250        } else {
     251                return type;
     252        }
     253}
     254
     255const ast::Node * scrubTypeVarsBase(
     256                const ast::Node * target,
     257                ScrubMode mode, const TyVarMap * typeVars ) {
     258        if ( ScrubMode::All == mode ) {
     259                assert( nullptr == typeVars );
     260        } else {
     261                assert( nullptr != typeVars );
     262        }
     263        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
     264        return target->accept( visitor );
     265}
     266
     267} // namespace
     268
     269template<>
     270ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
     271        return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
     272}
     273
    114274} // namespace GenPoly
    115275
  • src/GenPoly/ScrubTyVars.h

    r428adbc r7f6a7c9  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:21:47 2017
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Aug 19 14:14:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    1818#include <cassert>            // for assert
    1919
     20#include "AST/Fwd.hpp"        // for Node
    2021#include "Common/PassVisitor.h"
    2122#include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
     
    108109        }
    109110
     111/// For all polymorphic types, replaces generic types, with the appropriate
     112/// void type, and sizeof/alignof expressions with the proper variable.
     113template<typename node_t>
     114node_t const * scrubAllTypeVars( node_t const * target ) {
     115        return strict_dynamic_cast<node_t const *>( scrubAllTypeVars<ast::Node>( target ) );
     116}
     117
     118template<>
     119ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );
     120
    110121} // namespace GenPoly
    111122
  • src/GenPoly/SpecializeNew.cpp

    r428adbc r7f6a7c9  
    240240}
    241241
    242 namespace {
    243         struct TypeInstFixer : public ast::WithShortCircuiting {
    244                 std::map<const ast::TypeDecl *, std::pair<int, int>> typeMap;
    245 
    246                 void previsit(const ast::TypeDecl *) { visit_children = false; }
    247                 const ast::TypeInstType * postvisit(const ast::TypeInstType * typeInst) {
    248                         if (typeMap.count(typeInst->base)) {
    249                                 ast::TypeInstType * newInst = mutate(typeInst);
    250                                 auto const & pair = typeMap[typeInst->base];
    251                                 newInst->expr_id = pair.first;
    252                                 newInst->formal_usage = pair.second;
    253                                 return newInst;
    254                         }
    255                         return typeInst;
    256                 }
    257         };
    258 }
     242struct TypeInstFixer final : public ast::WithShortCircuiting {
     243        std::map<const ast::TypeDecl *, std::pair<int, int>> typeMap;
     244
     245        void previsit(const ast::TypeDecl *) { visit_children = false; }
     246        const ast::TypeInstType * postvisit(const ast::TypeInstType * typeInst) {
     247                if (typeMap.count(typeInst->base)) {
     248                        ast::TypeInstType * newInst = mutate(typeInst);
     249                        auto const & pair = typeMap[typeInst->base];
     250                        newInst->expr_id = pair.first;
     251                        newInst->formal_usage = pair.second;
     252                        return newInst;
     253                }
     254                return typeInst;
     255        }
     256};
    259257
    260258const ast::Expr * SpecializeCore::createThunkFunction(
  • src/GenPoly/module.mk

    r428adbc r7f6a7c9  
    2727        GenPoly/FindFunction.cc \
    2828        GenPoly/FindFunction.h \
     29        GenPoly/InstantiateGenericNew.cpp \
    2930        GenPoly/InstantiateGeneric.cc \
    3031        GenPoly/InstantiateGeneric.h \
  • src/InitTweak/InitTweak.cc

    r428adbc r7f6a7c9  
    12411241        static const char * const tlsd_section = ".tdata" ASM_COMMENT;
    12421242        void addDataSectionAttribute( ObjectDecl * objDecl ) {
    1243                 const bool is_tls = objDecl->get_storageClasses().is_threadlocal;
     1243                const bool is_tls = objDecl->get_storageClasses().is_threadlocal_any();
    12441244                const char * section = is_tls ? tlsd_section : data_section;
    12451245                objDecl->attributes.push_back(new Attribute("section", {
     
    12491249
    12501250        void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
    1251                 const bool is_tls = objDecl->storage.is_threadlocal;
     1251                const bool is_tls = objDecl->storage.is_threadlocal_any();
    12521252                const char * section = is_tls ? tlsd_section : data_section;
    12531253                objDecl->attributes.push_back(new ast::Attribute("section", {
  • src/Makefile.am

    r428adbc r7f6a7c9  
    7171EXTRA_DIST = include/cassert include/optional BasicTypes-gen.cc
    7272
    73 AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -Werror=return-type -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O3 -g -std=c++14 $(TCMALLOCFLAG)
     73AM_CXXFLAGS = @HOST_FLAGS@ -Wno-deprecated -Wall -Wextra -Werror=return-type -DDEBUG_ALL -I./Parser -I$(srcdir)/Parser -I$(srcdir)/include -DYY_NO_INPUT -O3 -g -std=c++17 $(TCMALLOCFLAG)
    7474AM_LDFLAGS  = @HOST_FLAGS@ -Xlinker -export-dynamic
    7575ARFLAGS     = cr
  • src/Parser/DeclarationNode.cc

    r428adbc r7f6a7c9  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 14 17:36:57 2021
    13 // Update Count     : 1154
     12// Last Modified On : Mon Aug  8 17:07:00 2022
     13// Update Count     : 1185
    1414//
    1515
     
    128128        if ( name ) {
    129129                os << *name << ": ";
    130         } else {
    131                 os << "unnamed: ";
    132130        } // if
    133131
     
    154152                initializer->printOneLine( os );
    155153                os << " maybe constructed? " << initializer->get_maybeConstructed();
    156 
    157         } // if
     154        } // if
     155
     156        for ( Attribute * attr: reverseIterate( attributes ) ) {
     157                os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str();
     158        } // for
    158159
    159160        os << endl;
     
    243244        newnode->type = new TypeData( TypeData::Aggregate );
    244245        newnode->type->aggregate.kind = kind;
    245         newnode->type->aggregate.name =  name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     246        newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
    246247        newnode->type->aggregate.actuals = actuals;
    247248        newnode->type->aggregate.fields = fields;
     
    253254} // DeclarationNode::newAggregate
    254255
    255 DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, DeclarationNode * base) {
     256DeclarationNode * DeclarationNode::newEnum( const string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base) {
    256257        DeclarationNode * newnode = new DeclarationNode;
    257258        newnode->type = new TypeData( TypeData::Enum );
     
    260261        newnode->type->enumeration.body = body;
    261262        newnode->type->enumeration.anon = name == nullptr;
     263        newnode->type->enumeration.typed = typed;
    262264        if ( base && base->type)  {
    263                 newnode->type->base = base->type;       
    264         } // if
    265 
    266         // Check: if base has TypeData
     265                newnode->type->base = base->type;
     266        } // if
     267
    267268        return newnode;
    268269} // DeclarationNode::newEnum
     
    284285
    285286DeclarationNode * DeclarationNode::newEnumValueGeneric( const string * name, InitializerNode * init ) {
    286         if ( init ) { // list init {} or a singleInit
    287                 if ( init->get_expression() ) { // singleInit
     287        if ( init ) {
     288                if ( init->get_expression() ) {
    288289                        return newEnumConstant( name, init->get_expression() );
    289                 } else { // TODO: listInit
     290                } else {
    290291                        DeclarationNode * newnode = newName( name );
    291292                        newnode->initializer = init;
     
    293294                } // if
    294295        } else {
    295                 return newName( name ); // Not explicitly inited enum value;
     296                return newName( name );
    296297        } // if
    297298} // DeclarationNode::newEnumValueGeneric
     
    504505                        } // for
    505506                        // src is the new item being added and has a single bit
    506                 } else if ( ! src->storageClasses.is_threadlocal ) { // conflict ?
     507                } else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ?
    507508                        appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] +
    508509                                                 " & " + Type::StorageClassesNames[src->storageClasses.ffs()] );
     
    518519        storageClasses |= q->storageClasses;
    519520
    520         for ( Attribute *attr: reverseIterate( q->attributes ) ) {
     521        for ( Attribute * attr: reverseIterate( q->attributes ) ) {
    521522                attributes.push_front( attr->clone() );
    522523        } // for
     
    683684        } // if
    684685        delete o;
     686
    685687        return this;
    686688}
  • src/Parser/ExpressionNode.cc

    r428adbc r7f6a7c9  
    509509} // build_varref
    510510
     511QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) {
     512        Declaration * newDecl = maybeBuild< Declaration >(decl_node);
     513        if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) {
     514                const Type * t = newDeclWithType->get_type();
     515                if ( t ) {
     516                        if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) {
     517                                newDecl= new EnumDecl( typeInst->name );
     518                        }
     519                }
     520        }
     521        auto ret =  new QualifiedNameExpr( newDecl, name->name );
     522        if ( auto e = dynamic_cast<EnumDecl*>(newDecl) ) {
     523                auto enumInst = new EnumInstType( Type::Qualifiers(), e );
     524                auto obj = new ObjectDecl( name->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, enumInst, nullptr );
     525                ret->set_var( obj );
     526        }
     527        return ret;
     528}
     529
     530QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) {
     531        EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node );
     532        return new QualifiedNameExpr( newDecl, name->name );
     533}
     534
    511535DimensionExpr * build_dimensionref( const string * name ) {
    512536        DimensionExpr * expr = new DimensionExpr( *name );
  • src/Parser/ParseNode.h

    r428adbc r7f6a7c9  
    183183
    184184NameExpr * build_varref( const std::string * name );
     185QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );
     186QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );
    185187DimensionExpr * build_dimensionref( const std::string * name );
    186188
     
    235237        static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    236238        static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    237         static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, DeclarationNode * base = nullptr );
     239        static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr );
    238240        static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
    239241        static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );
  • src/Parser/TypeData.cc

    r428adbc r7f6a7c9  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:12:51 2015
    11 // Last Modified By : Henry Xue
    12 // Last Modified On : Tue Jul 20 04:10:50 2021
    13 // Update Count     : 673
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue May 10 22:36:52 2022
     13// Update Count     : 677
    1414//
    1515
     
    283283                if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
    284284                if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
    285                 if ( complextype == DeclarationNode::NoComplexType ) { // basic type
    286                         assert( basictype != DeclarationNode::NoBasicType );
    287                         os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    288                 } else {                                                                                // complex type
    289                         // handle double _Complex
    290                         if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    291                         os << DeclarationNode::complexTypeNames[ complextype ] << " ";
    292                 } // if
     285                if ( complextype != DeclarationNode::NoComplexType ) os << DeclarationNode::complexTypeNames[ complextype ] << " ";
     286                if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    293287                break;
    294288          case Pointer:
     
    437431                        __attribute__((fallthrough));
    438432                #endif
     433                // FALL THROUGH
    439434          case Typeof:
    440435                os << "type-of expression ";
     
    442437                        typeexpr->print( os, indent + 2 );
    443438                } // if
     439                break;
     440          case Vtable:
     441                os << "vtable";
    444442                break;
    445443          case Builtin:
     
    548546                return buildAggInst( td );
    549547          case TypeData::EnumConstant:
    550                 // the name gets filled in later -- by SymTab::Validate
    551548                return new EnumInstType( buildQualifiers( td ), "" );
    552549          case TypeData::SymbolicInst:
     
    923920        assert( td->kind == TypeData::Enum );
    924921        Type * baseType = td->base ? typebuild(td->base) : nullptr;
    925         EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, linkage, baseType );
     922        EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType );
    926923        buildList( td->enumeration.constants, ret->get_members() );
    927924        list< Declaration * >::iterator members = ret->get_members().begin();
    928925        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
    929                 if ( cur->has_enumeratorValue() ) {
     926                if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
     927                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
     928                } else if ( cur->has_enumeratorValue() ) {
    930929                        ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
    931930                        member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) );
    932931                } else if ( !cur->initializer ) {
    933932                        if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isWholeNumber())) {
    934                                 SemanticError( td->location, "A non whole number enum value decl must be explicitly initialized." );
     933                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
    935934                        }
    936935                }
  • src/Parser/TypeData.h

    r428adbc r7f6a7c9  
    1010// Created On       : Sat May 16 15:18:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 14 17:44:05 2021
    13 // Update Count     : 202
     12// Last Modified On : Tue May 10 22:18:49 2022
     13// Update Count     : 203
    1414//
    1515
     
    2727struct TypeData {
    2828        enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic,
    29                                 SymbolicInst, Tuple, Typeof, Basetypeof, Vtable, Builtin, GlobalScope, Qualified, Unknown };
     29                                SymbolicInst, Tuple, Basetypeof, Typeof, Vtable, Builtin, GlobalScope, Qualified, Unknown };
    3030
    3131        struct Aggregate_t {
     
    5959                bool body;
    6060                bool anon;
     61                bool typed;
    6162        };
    6263
  • src/Parser/TypedefTable.cc

    r428adbc r7f6a7c9  
    1010// Created On       : Sat May 16 15:20:13 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May 19 08:30:14 2021
    13 // Update Count     : 262
     12// Last Modified On : Tue Feb 15 08:27:24 2022
     13// Update Count     : 275
    1414//
    1515
     
    1818#include <cassert>                                                                              // for assert
    1919#include <iostream>
     20using namespace std;
    2021
    2122#if 0
     
    2829
    2930debugPrint(
    30 static const char *kindName( int kind ) {
    31         switch ( kind ) {
    32           case IDENTIFIER: return "identifier";
    33           case TYPEDIMname: return "typedim";
    34           case TYPEDEFname: return "typedef";
    35           case TYPEGENname: return "typegen";
    36           default:
    37                 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
    38                 abort();
    39         } // switch
    40 } // kindName
    41 )
     31        static const char *kindName( int kind ) {
     32                switch ( kind ) {
     33                  case IDENTIFIER: return "identifier";
     34                  case TYPEDIMname: return "typedim";
     35                  case TYPEDEFname: return "typedef";
     36                  case TYPEGENname: return "typegen";
     37                  default:
     38                        cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
     39                        abort();
     40                } // switch
     41        } // kindName
     42);
    4243
    4344TypedefTable::~TypedefTable() {
     
    8081
    8182void TypedefTable::addToScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    82         auto scope = kindTable.currentScope();
     83        KindTable::size_type scope = kindTable.currentScope();
    8384        debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl );
    8485        kindTable.insertAt( scope, identifier, kind );
     
    8687
    8788void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) {
    88         auto scope = kindTable.currentScope() - 1 - kindTable.getNote( kindTable.currentScope() - 1 ).level;
    89 //      auto scope = level - kindTable.getNote( kindTable.currentScope() - 1 ).level;
     89        KindTable::size_type scope = kindTable.currentScope() - 1 - kindTable.getNote( kindTable.currentScope() - 1 ).level;
     90//      size_type scope = level - kindTable.getNote( kindTable.currentScope() - 1 ).level;
    9091        debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << " level " << level << " note " << kindTable.getNote( kindTable.currentScope() - 1 ).level << endl );
    91         auto ret = kindTable.insertAt( scope, identifier, kind );
     92        pair< KindTable::iterator, bool > ret = kindTable.insertAt( scope, identifier, kind );
    9293        if ( ! ret.second ) ret.first->second = kind;           // exists => update
    9394} // TypedefTable::addToEnclosingScope
  • src/Parser/lex.ll

    r428adbc r7f6a7c9  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Sun Jun 20 18:41:09 2021
    13  * Update Count     : 759
     12 * Last Modified On : Tue Sep 20 21:18:55 2022
     13 * Update Count     : 762
    1414 */
    1515
     
    2424
    2525//**************************** Includes and Defines ****************************
     26
     27#ifdef __clang__
     28#pragma GCC diagnostic ignored "-Wnull-conversion"
     29#endif
    2630
    2731// trigger before each matching rule's action
     
    8286// Stop warning due to incorrectly generated flex code.
    8387#pragma GCC diagnostic ignored "-Wsign-compare"
    84 
    85 // lex uses __null in a boolean context, it's fine.
    86 #pragma GCC diagnostic ignored "-Wnull-conversion"
    8788%}
    8889
     
    314315switch                  { KEYWORD_RETURN(SWITCH); }
    315316thread                  { KEYWORD_RETURN(THREAD); }                             // C11
    316 _Thread_local   { KEYWORD_RETURN(THREADLOCAL); }                // C11
     317__thread                { KEYWORD_RETURN(THREADLOCALGCC); }             // GCC
     318_Thread_local   { KEYWORD_RETURN(THREADLOCALC11); }             // C11
    317319throw                   { KEYWORD_RETURN(THROW); }                              // CFA
    318320throwResume             { KEYWORD_RETURN(THROWRESUME); }                // CFA
  • src/Parser/parser.yy

    r428adbc r7f6a7c9  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  1 15:35:08 2022
    13 // Update Count     : 5405
     12// Last Modified On : Sat Aug 27 13:21:28 2022
     13// Update Count     : 5661
    1414//
    1515
     
    5858
    5959// lex uses __null in a boolean context, it's fine.
     60#ifdef __clang__
    6061#pragma GCC diagnostic ignored "-Wparentheses-equality"
     62#endif
    6163
    6264extern DeclarationNode * parseTree;
     
    197199} // fieldDecl
    198200
     201#define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )
     202#define NEW_ONE  new ExpressionNode( build_constantInteger( *new string( "1" ) ) )
     203#define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
     204#define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
     205#define MISSING_LOW "Missing low value for up-to range so index is uninitialized."
     206#define MISSING_HIGH "Missing high value for down-to range so index is uninitialized."
     207
     208ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     209        if ( index->initializer ) {
     210                SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
     211        } // if
     212        if ( index->next ) {
     213                SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." );
     214        } // if
     215        return new ForCtrl( index->addInitializer( new InitializerNode( start ) ),
     216                // NULL comp/inc => leave blank
     217                comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr,
     218                inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
     219                                                        OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr );
     220} // forCtrl
     221
    199222ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    200223        ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());
     
    206229                distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
    207230                // NULL comp/inc => leave blank
    208                 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : 0,
     231                comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr,
    209232                inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
    210                                                         OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : 0 );
     233                                                        OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr );
    211234} // forCtrl
    212235
     
    272295%token TYPEDEF
    273296%token EXTERN STATIC AUTO REGISTER
    274 %token THREADLOCAL                                                                              // C11
     297%token THREADLOCALGCC THREADLOCALC11                                            // GCC, C11
    275298%token INLINE FORTRAN                                                                   // C99, extension ISO/IEC 9899:1999 Section J.5.9(1)
    276299%token NORETURN                                                                                 // C11
     
    346369%type<ifctl> conditional_declaration
    347370%type<fctl> for_control_expression              for_control_expression_list
    348 %type<compop> inclexcl
     371%type<compop> updown updowneq downupdowneq
    349372%type<en> subrange
    350373%type<decl> asm_name_opt
     
    614637                { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }
    615638        | type_name '.' identifier                                                      // CFA, nested type
    616                 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     639                { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); }
    617640        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    618641                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     
    12391262iteration_statement:
    12401263        WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
    1241                 { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
     1264                { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); }
    12421265        | WHILE '(' ')' statement ELSE statement                        // CFA
    12431266                {
    1244                         $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) );
     1267                        $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) );
    12451268                        SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
    12461269                }
     
    12501273                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
    12511274        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1252                 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
     1275                { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); }
    12531276        | DO statement WHILE '(' ')' ELSE statement                     // CFA
    12541277                {
    1255                         $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) );
     1278                        $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) );
    12561279                        SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
    12571280                }
     
    13041327                { $$ = new ForCtrl( $1, $2, $4 ); }
    13051328
    1306         | comma_expression                                                                      // CFA
    1307                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1308                                                 OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1309         | '=' comma_expression                                                          // CFA
    1310                 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1311                                                 OperKinds::LEThan, $2->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1312         | comma_expression inclexcl comma_expression            // CFA
    1313                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1314         | comma_expression inclexcl comma_expression '~' comma_expression // CFA
    1315                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); }
    1316         | comma_expression ';'                                                          // CFA
    1317                 { $$ = forCtrl( new ExpressionNode( build_constantInteger( *new string( "0u" ) ) ), $1, nullptr, OperKinds::LThan, nullptr, nullptr ); }
     1329        | '@' ';' comma_expression                                                      // CFA, empty loop-index
     1330                { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }
     1331        | '@' ';' comma_expression ';' comma_expression         // CFA, empty loop-index
     1332                { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }
     1333
     1334        | comma_expression                                                                      // CFA, anonymous loop-index
     1335                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
     1336        | downupdowneq comma_expression                                         // CFA, anonymous loop-index
     1337                { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
     1338
     1339        | comma_expression updowneq comma_expression            // CFA, anonymous loop-index
     1340                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
     1341        | '@' updowneq comma_expression                                         // CFA, anonymous loop-index
     1342                {
     1343                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1344                        else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
     1345                }
     1346        | comma_expression updowneq '@'                                         // CFA, anonymous loop-index
     1347                {
     1348                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1349                        else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1350                }
     1351        | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
     1352                { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
     1353        | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
     1354                {
     1355                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1356                        else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
     1357                }
     1358        | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
     1359                {
     1360                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1361                        else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1362                }
     1363        | comma_expression updowneq comma_expression '~' '@' // CFA, error
     1364                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1365        | '@' updowneq '@'                                                                      // CFA, error
     1366                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1367        | '@' updowneq comma_expression '~' '@'                         // CFA, error
     1368                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1369        | comma_expression updowneq '@' '~' '@'                         // CFA, error
     1370                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1371        | '@' updowneq '@' '~' '@'                                                      // CFA, error
     1372                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
     1373
    13181374        | comma_expression ';' comma_expression                         // CFA
    1319                 { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1320                                                 OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1321         | comma_expression ';' '=' comma_expression                     // CFA
    1322                 { $$ = forCtrl( $4, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ),
    1323                                                 OperKinds::LEThan, $4->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1324         | comma_expression ';' comma_expression inclexcl comma_expression // CFA
    1325                 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1326         | comma_expression ';' comma_expression inclexcl comma_expression '~' comma_expression // CFA
    1327                 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, $7 ); }
     1375                { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
     1376        | comma_expression ';' downupdowneq comma_expression // CFA
     1377                { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
     1378
     1379        | comma_expression ';' comma_expression updowneq comma_expression // CFA
     1380                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
     1381        | comma_expression ';' '@' updowneq comma_expression // CFA
     1382                {
     1383                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1384                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
     1385                }
     1386        | comma_expression ';' comma_expression updowneq '@' // CFA
     1387                {
     1388                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1389                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1390                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
     1391                }
     1392        | comma_expression ';' '@' updowneq '@'                         // CFA, error
     1393                { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
     1394
     1395        | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
     1396                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
     1397        | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
     1398                {
     1399                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1400                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );
     1401                }
     1402        | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
     1403                {
     1404                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1405                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1406                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );
     1407                }
     1408        | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
     1409                { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
     1410        | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
     1411                {
     1412                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1413                        else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );
     1414                }
     1415        | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
     1416                {
     1417                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1418                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1419                        else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );
     1420                }
     1421        | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
     1422                { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
     1423
     1424        | declaration comma_expression                                          // CFA
     1425                { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
     1426        | declaration downupdowneq comma_expression                     // CFA
     1427                { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
     1428
     1429        | declaration comma_expression updowneq comma_expression // CFA
     1430                { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
     1431        | declaration '@' updowneq comma_expression                     // CFA
     1432                {
     1433                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1434                        else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );
     1435                }
     1436        | declaration comma_expression updowneq '@'                     // CFA
     1437                {
     1438                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1439                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1440                        else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );
     1441                }
     1442
     1443        | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
     1444                { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
     1445        | declaration '@' updowneq comma_expression '~' comma_expression // CFA
     1446                {
     1447                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1448                        else $$ = forCtrl( $1, $4, $3, nullptr, $6 );
     1449                }
     1450        | declaration comma_expression updowneq '@' '~' comma_expression // CFA
     1451                {
     1452                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1453                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1454                        else $$ = forCtrl( $1, $2, $3, nullptr, $6 );
     1455                }
     1456        | declaration comma_expression updowneq comma_expression '~' '@' // CFA
     1457                { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
     1458        | declaration '@' updowneq comma_expression '~' '@' // CFA
     1459                {
     1460                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     1461                        else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );
     1462                }
     1463        | declaration comma_expression updowneq '@' '~' '@'     // CFA
     1464                {
     1465                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
     1466                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1467                        else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );
     1468                }
     1469        | declaration '@' updowneq '@' '~' '@'                          // CFA, error
     1470                { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
    13281471
    13291472        | comma_expression ';' TYPEDEFname                                      // CFA, array type
    13301473                {
    1331                         SemanticError( yylloc, "Array interator is currently unimplemented." ); $$ = nullptr;
    1332                         $$ = forCtrl( new ExpressionNode( build_varref( $3 ) ), $1, nullptr, OperKinds::Range, nullptr, nullptr );
    1333                 }
    1334 
    1335                 // There is a S/R conflicit if ~ and -~ are factored out.
    1336         | comma_expression ';' comma_expression '~' '@'         // CFA
    1337                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1338         | comma_expression ';' comma_expression ErangeDown '@' // CFA
    1339                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); }
    1340         | comma_expression ';' comma_expression '~' '@' '~' comma_expression // CFA
    1341                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, $7 ); }
    1342         | comma_expression ';' comma_expression ErangeDown '@' '~' comma_expression // CFA
    1343                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, $7 ); }
    1344         | comma_expression ';' comma_expression '~' '@' '~' '@' // CFA
    1345                 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, nullptr ); }
     1474                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
     1475                        //$$ = forCtrl( new ExpressionNode( build_varref( $3 ) ), $1, nullptr, OperKinds::Range, nullptr, nullptr );
     1476                }
     1477        | comma_expression ';' downupdowneq TYPEDEFname         // CFA, array type
     1478                {
     1479                        if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "All enumation ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; }
     1480                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
     1481                }
    13461482        ;
    13471483
    1348 inclexcl:
     1484downupdowneq:
     1485        ErangeDown
     1486                { $$ = OperKinds::GThan; }
     1487        | ErangeUpEq
     1488                { $$ = OperKinds::LEThan; }
     1489        | ErangeDownEq
     1490                { $$ = OperKinds::GEThan; }
     1491        ;
     1492
     1493updown:
    13491494        '~'
    13501495                { $$ = OperKinds::LThan; }
     1496        | ErangeDown
     1497                { $$ = OperKinds::GThan; }
     1498        ;
     1499
     1500updowneq:
     1501        updown
    13511502        | ErangeUpEq
    13521503                { $$ = OperKinds::LEThan; }
    1353         | ErangeDown
    1354                 { $$ = OperKinds::GThan; }
    13551504        | ErangeDownEq
    13561505                { $$ = OperKinds::GEThan; }
     
    19352084        | REGISTER
    19362085                { $$ = DeclarationNode::newStorageClass( Type::Register ); }
    1937         | THREADLOCAL                                                                           // C11
    1938                 { $$ = DeclarationNode::newStorageClass( Type::Threadlocal ); }
     2086        | THREADLOCALGCC                                                                                // GCC
     2087                { $$ = DeclarationNode::newStorageClass( Type::ThreadlocalGcc ); }
     2088        | THREADLOCALC11                                                                                // C11
     2089                { $$ = DeclarationNode::newStorageClass( Type::ThreadlocalC11 ); }
    19392090                // Put function specifiers here to simplify parsing rules, but separate them semantically.
    19402091        | INLINE                                                                                        // C99
     
    23872538enum_type:
    23882539        ENUM attribute_list_opt '{' enumerator_list comma_opt '}'
    2389                 { $$ = DeclarationNode::newEnum( nullptr, $4, true )->addQualifiers( $2 ); }
     2540                { $$ = DeclarationNode::newEnum( nullptr, $4, true, false )->addQualifiers( $2 ); }
    23902541        | ENUM attribute_list_opt identifier
    23912542                { typedefTable.makeTypedef( *$3 ); }
    23922543          '{' enumerator_list comma_opt '}'
    2393                 { $$ = DeclarationNode::newEnum( $3, $6, true )->addQualifiers( $2 ); }
     2544                { $$ = DeclarationNode::newEnum( $3, $6, true, false )->addQualifiers( $2 ); }
    23942545        | ENUM attribute_list_opt typedef_name                          // unqualified type name
    23952546          '{' enumerator_list comma_opt '}'
    2396                 { $$ = DeclarationNode::newEnum( $3->name, $5, true )->addQualifiers( $2 ); }
     2547                { $$ = DeclarationNode::newEnum( $3->name, $5, true, false )->addQualifiers( $2 ); }
    23972548        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    23982549                {
     
    24002551                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    24012552
    2402                         $$ = DeclarationNode::newEnum( nullptr, $7, true, $3 )->addQualifiers( $5 );
     2553                        $$ = DeclarationNode::newEnum( nullptr, $7, true, true, $3 )->addQualifiers( $5 );
     2554                }
     2555        | ENUM '(' ')' attribute_list_opt '{' enumerator_list comma_opt '}'
     2556                {
     2557                        $$ = DeclarationNode::newEnum( nullptr, $6, true, true )->addQualifiers( $4 );
    24032558                }
    24042559        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
     
    24092564          '{' enumerator_list comma_opt '}'
    24102565                {
    2411                         $$ = DeclarationNode::newEnum( $6, $10, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2566                        $$ = DeclarationNode::newEnum( $6, $10, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2567                }
     2568        | ENUM '(' ')' attribute_list_opt identifier attribute_list_opt
     2569          '{' enumerator_list comma_opt '}'
     2570                {
     2571                        $$ = DeclarationNode::newEnum( $5, $8, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
    24122572                }
    24132573        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
    24142574                {
    2415                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    2416                         typedefTable.makeTypedef( *$6->name );
    2417                         $$ = DeclarationNode::newEnum( $6->name, $9, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2575                        $$ = DeclarationNode::newEnum( $6->name, $9, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2576                }
     2577        | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
     2578                {
     2579                        $$ = DeclarationNode::newEnum( $5->name, $8, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
    24182580                }
    24192581        | enum_type_nobody
     
    24222584enum_type_nobody:                                                                               // enum - {...}
    24232585        ENUM attribute_list_opt identifier
    2424                 { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false )->addQualifiers( $2 ); }
    2425         | ENUM attribute_list_opt type_name                                     // qualified type name
    2426                 { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false )->addQualifiers( $2 ); }
     2586                { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false, false )->addQualifiers( $2 ); }
     2587        | ENUM attribute_list_opt type_name
     2588                { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false, false )->addQualifiers( $2 ); }
    24272589        ;
    24282590
  • src/ResolvExpr/AlternativeFinder.cc

    r428adbc r7f6a7c9  
    299299                                SemanticError( expr->location, stream.str() );
    300300                        }
    301                         alternatives = move(pruned);
     301                        alternatives = std::move(pruned);
    302302                        PRINT(
    303303                                std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
     
    573573                                unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0,
    574574                                unsigned explAlt = 0 )
    575                         : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)),
    576                           have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart),
     575                        : parent(parent), expr(expr->clone()), cost(cost), env(std::move(env)), need(std::move(need)),
     576                          have(std::move(have)), openVars(std::move(openVars)), nextArg(nextArg), tupleStart(tupleStart),
    577577                          nextExpl(nextExpl), explAlt(explAlt) {}
    578578
     
    580580                                OpenVarSet&& openVars, unsigned nextArg, Cost added )
    581581                        : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added),
    582                           env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)),
     582                          env(std::move(env)), need(std::move(need)), have(std::move(have)), openVars(std::move(openVars)),
    583583                          nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {}
    584584
     
    707707                                                if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have,
    708708                                                                newResult.openVars, indexer ) ) {
    709                                                         finalResults.push_back( move(newResult) );
     709                                                        finalResults.push_back( std::move(newResult) );
    710710                                                }
    711711
     
    726726                                                if ( expl.exprs.empty() ) {
    727727                                                        results.emplace_back(
    728                                                                 results[i], move(env), copy(results[i].need),
    729                                                                 copy(results[i].have), move(openVars), nextArg + 1, expl.cost );
     728                                                                results[i], std::move(env), copy(results[i].need),
     729                                                                copy(results[i].have), std::move(openVars), nextArg + 1, expl.cost );
    730730
    731731                                                        continue;
     
    734734                                                // add new result
    735735                                                results.emplace_back(
    736                                                         i, expl.exprs.front().get(), move(env), copy(results[i].need),
    737                                                         copy(results[i].have), move(openVars), nextArg + 1,
     736                                                        i, expl.exprs.front().get(), std::move(env), copy(results[i].need),
     737                                                        copy(results[i].have), std::move(openVars), nextArg + 1,
    738738                                                        nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    739739                                        }
     
    747747                        // splice final results onto results
    748748                        for ( std::size_t i = 0; i < finalResults.size(); ++i ) {
    749                                 results.push_back( move(finalResults[i]) );
     749                                results.push_back( std::move(finalResults[i]) );
    750750                        }
    751751                        return ! finalResults.empty();
     
    783783
    784784                                        results.emplace_back(
    785                                                 i, expr, move(env), move(need), move(have), move(openVars), nextArg,
     785                                                i, expr, std::move(env), std::move(need), std::move(have), std::move(openVars), nextArg,
    786786                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    787787                                }
     
    801801                                                                indexer ) ) {
    802802                                                        results.emplace_back(
    803                                                                 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    804                                                                 move(openVars), nextArg, nTuples );
     803                                                                i, new DefaultArgExpr( cnstExpr ), std::move(env), std::move(need), std::move(have),
     804                                                                std::move(openVars), nextArg, nTuples );
    805805                                                }
    806806                                        }
     
    824824                                if ( expl.exprs.empty() ) {
    825825                                        results.emplace_back(
    826                                                 results[i], move(env), move(need), move(have), move(openVars),
     826                                                results[i], std::move(env), std::move(need), std::move(have), std::move(openVars),
    827827                                                nextArg + 1, expl.cost );
    828828
     
    846846                                        // add new result
    847847                                        results.emplace_back(
    848                                                 i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1,
     848                                                i, expr, std::move(env), std::move(need), std::move(have), std::move(openVars), nextArg + 1,
    849849                                                nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    850850                                }
     
    962962                                                if ( expl.exprs.empty() ) {
    963963                                                        results.emplace_back(
    964                                                                 results[i], move(env), copy(results[i].need),
    965                                                                 copy(results[i].have), move(openVars), nextArg + 1, expl.cost );
     964                                                                results[i], std::move(env), copy(results[i].need),
     965                                                                copy(results[i].have), std::move(openVars), nextArg + 1, expl.cost );
    966966
    967967                                                        continue;
     
    970970                                                // add new result
    971971                                                results.emplace_back(
    972                                                         i, expl.exprs.front().get(), move(env), copy(results[i].need),
    973                                                         copy(results[i].have), move(openVars), nextArg + 1, 0,
     972                                                        i, expl.exprs.front().get(), std::move(env), copy(results[i].need),
     973                                                        copy(results[i].have), std::move(openVars), nextArg + 1, 0,
    974974                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    975975                                        }
     
    10671067                                funcE.emplace_back( actual, indexer );
    10681068                        }
    1069                         argExpansions.insert( argExpansions.begin(), move(funcE) );
     1069                        argExpansions.insert( argExpansions.begin(), std::move(funcE) );
    10701070
    10711071                        for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin();
     
    11161116                } // for
    11171117
    1118                 candidates = move(alternatives);
     1118                candidates = std::move(alternatives);
    11191119
    11201120                // use a new list so that alternatives are not examined by addAnonConversions twice.
  • src/ResolvExpr/CandidateFinder.cpp

    r428adbc r7f6a7c9  
    269269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    270270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    271                 : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    272                   have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
     271                : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),
     272                  have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    273273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    274274
     
    276276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    277277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    278                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
    279                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),
     279                  need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),
    280280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    281281
     
    301301                        // reset pack to appropriate tuple
    302302                        std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );
    303                         expr = new ast::TupleExpr{ expr->location, move( exprv ) };
     303                        expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };
    304304                        tupleStart = pack->tupleStart - 1;
    305305                        parent = pack->parent;
     
    404404                                                                newResult.open, symtab )
    405405                                                ) {
    406                                                         finalResults.emplace_back( move( newResult ) );
     406                                                        finalResults.emplace_back( std::move( newResult ) );
    407407                                                }
    408408
     
    423423                                                if ( expl.exprs.empty() ) {
    424424                                                        results.emplace_back(
    425                                                                 results[i], move( env ), copy( results[i].need ),
    426                                                                 copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
     425                                                                results[i], std::move( env ), copy( results[i].need ),
     426                                                                copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );
    427427
    428428                                                        continue;
     
    431431                                                // add new result
    432432                                                results.emplace_back(
    433                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ),
    434                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples,
     433                                                        i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,
    435435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    436436                                        }
     
    444444                        // splice final results onto results
    445445                        for ( std::size_t i = 0; i < finalResults.size(); ++i ) {
    446                                 results.emplace_back( move( finalResults[i] ) );
     446                                results.emplace_back( std::move( finalResults[i] ) );
    447447                        }
    448448                        return ! finalResults.empty();
     
    478478
    479479                                        results.emplace_back(
    480                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
     480                                                i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,
    481481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    482482                                }
     
    494494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    495495                                                results.emplace_back(
    496                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    497                                                         move( need ), move( have ), move( open ), nextArg, nTuples );
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
     497                                                        std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );
    498498                                        }
    499499                                }
     
    516516                                if ( expl.exprs.empty() ) {
    517517                                        results.emplace_back(
    518                                                 results[i], move( env ), move( need ), move( have ), move( open ),
     518                                                results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    519519                                                nextArg + 1, expl.cost );
    520520
     
    538538                                        // add new result
    539539                                        results.emplace_back(
    540                                                 i, expr, move( env ), move( need ), move( have ), move( open ),
     540                                                i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    541541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    542542                                }
     
    576576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    577577                        }
    578                         return new ast::TupleExpr{ arg->location, move( components ) };
     578                        return new ast::TupleExpr{ arg->location, std::move( components ) };
    579579                } else {
    580580                        // handle normally
     
    672672                        }
    673673                        std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );
    674                         appExpr->args = move( vargs );
     674                        appExpr->args = std::move( vargs );
    675675                        // build and validate new candidate
    676676                        auto newCand =
     
    783783                                                        if ( expl.exprs.empty() ) {
    784784                                                                results.emplace_back(
    785                                                                         results[i], move( env ), copy( results[i].need ),
    786                                                                         copy( results[i].have ), move( open ), nextArg + 1,
     785                                                                        results[i], std::move( env ), copy( results[i].need ),
     786                                                                        copy( results[i].have ), std::move( open ), nextArg + 1,
    787787                                                                        expl.cost );
    788788
     
    792792                                                        // add new result
    793793                                                        results.emplace_back(
    794                                                                 i, expl.exprs.front(), move( env ), copy( results[i].need ),
    795                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
     794                                                                i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
     795                                                                copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,
    796796                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    797797                                                }
     
    843843                                // as a member expression
    844844                                addAnonConversions( newCand );
    845                                 candidates.emplace_back( move( newCand ) );
     845                                candidates.emplace_back( std::move( newCand ) );
    846846                        }
    847847                }
     
    864864                }
    865865
     866                void postvisit( const ast::QualifiedNameExpr * qualifiedNameExpr ) {
     867                        auto mangleName = Mangle::mangle(qualifiedNameExpr->var);
     868                        addCandidate( qualifiedNameExpr, tenv );
     869                }
     870
    866871                void postvisit( const ast::UntypedExpr * untypedExpr ) {
    867872                        std::vector< CandidateFinder > argCandidates =
     
    897902                                                }
    898903
    899                                                 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);
    900                                                 else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
    901                                                         const ast::EnumDecl * enumDecl = enumInst->base;
    902                                                         if ( const ast::Type* enumType = enumDecl->base ) {
    903                                                                 // instance of enum (T) is a instance of type (T)
    904                                                                 funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
    905                                                         } else {
    906                                                                 // instance of an untyped enum is techically int
    907                                                                 funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
    908                                                         }
    909                                                 }
     904                                                if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);                                             
     905                                                // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
     906                                                //      const ast::EnumDecl * enumDecl = enumInst->base; // Here
     907                                                //      if ( const ast::Type* enumType = enumDecl->base ) {
     908                                                //              // instance of enum (T) is a instance of type (T)
     909                                                //              funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
     910                                                //      } else {
     911                                                //              // instance of an untyped enum is techically int
     912                                                //              funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
     913                                                //      }
     914                                                // }
    910915                                                else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
    911916                                        }
     
    986991                                        funcE.emplace_back( *func, symtab );
    987992                                }
    988                                 argExpansions.emplace_front( move( funcE ) );
     993                                argExpansions.emplace_front( std::move( funcE ) );
    989994
    990995                                for ( const CandidateRef & op : opFinder ) {
     
    10301035                                if ( cvtCost != Cost::infinity ) {
    10311036                                        withFunc->cvtCost = cvtCost;
    1032                                         candidates.emplace_back( move( withFunc ) );
    1033                                 }
    1034                         }
    1035                         found = move( candidates );
     1037                                        candidates.emplace_back( std::move( withFunc ) );
     1038                                }
     1039                        }
     1040                        found = std::move( candidates );
    10361041
    10371042                        // use a new list so that candidates are not examined by addAnonConversions twice
     
    11311136                                        CandidateRef newCand = std::make_shared<Candidate>(
    11321137                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1133                                                 copy( cand->env ), move( open ), move( need ), cand->cost,
     1138                                                copy( cand->env ), std::move( open ), std::move( need ), cand->cost,
    11341139                                                cand->cost + thisCost );
    11351140                                        inferParameters( newCand, matches );
     
    12851290                                // as a name expression
    12861291                                addAnonConversions( newCand );
    1287                                 candidates.emplace_back( move( newCand ) );
     1292                                candidates.emplace_back( std::move( newCand ) );
    12881293                        }
    12891294                }
     
    13941399                                                new ast::LogicalExpr{
    13951400                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    1396                                                 move( env ), move( open ), move( need ), r1->cost + r2->cost );
     1401                                                std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );
    13971402                                }
    13981403                        }
     
    14521457                                                        // output candidate
    14531458                                                        CandidateRef newCand = std::make_shared<Candidate>(
    1454                                                                 newExpr, move( env ), move( open ), move( need ), cost );
     1459                                                                newExpr, std::move( env ), std::move( open ), std::move( need ), cost );
    14551460                                                        inferParameters( newCand, candidates );
    14561461                                                }
     
    15191524                                                // add candidate
    15201525                                                CandidateRef newCand = std::make_shared<Candidate>(
    1521                                                         newExpr, move( env ), move( open ), move( need ),
     1526                                                        newExpr, std::move( env ), std::move( open ), std::move( need ),
    15221527                                                        r1->cost + r2->cost );
    15231528                                                inferParameters( newCand, candidates );
     
    15481553
    15491554                                addCandidate(
    1550                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    1551                                         move( env ), move( open ), move( need ), sumCost( subs ) );
     1555                                        new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },
     1556                                        std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );
    15521557                        }
    15531558                }
     
    16351640                                                                initExpr->location, restructureCast( cand->expr, toType ),
    16361641                                                                initAlt.designation },
    1637                                                         move(env), move( open ), move( need ), cand->cost, thisCost );
     1642                                                        std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );
    16381643                                                inferParameters( newCand, matches );
    16391644                                        }
     
    17681773                cand->env.applyFree( newResult );
    17691774                cand->expr = ast::mutate_field(
    1770                         cand->expr.get(), &ast::Expr::result, move( newResult ) );
     1775                        cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
    17711776
    17721777                out.emplace_back( cand );
     
    18541859
    18551860                auto oldsize = candidates.size();
    1856                 candidates = move( pruned );
     1861                candidates = std::move( pruned );
    18571862
    18581863                PRINT(
  • src/ResolvExpr/CommonType.cc

    r428adbc r7f6a7c9  
    2828#include "Unify.h"                       // for unifyExact, WidenMode
    2929#include "typeops.h"                     // for isFtype
     30#include "Tuples/Tuples.h"
    3031
    3132// #define DEBUG
     
    675676                ast::TypeEnvironment & tenv;
    676677                const ast::OpenVarSet & open;
     678                ast::AssertionSet & need;
     679                ast::AssertionSet & have;
    677680        public:
    678681                static size_t traceId;
     
    681684                CommonType_new(
    682685                        const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
    683                         ast::TypeEnvironment & env, const ast::OpenVarSet & o )
    684                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {}
     686                        ast::TypeEnvironment & env, const ast::OpenVarSet & o,
     687                        ast::AssertionSet & need, ast::AssertionSet & have )
     688                : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {}
    685689
    686690                void previsit( const ast::Node * ) { visit_children = false; }
     
    753757                bool tryResolveWithTypedEnum( const ast::Type * type1 ) {
    754758                        if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {
    755                                 ast::AssertionSet have, need; // unused
    756759                                ast::OpenVarSet newOpen{ open };
    757760                                if (enumInst->base->base
     
    792795                                        reset_qualifiers( t2 );
    793796
    794                                         ast::AssertionSet have, need;
    795797                                        ast::OpenVarSet newOpen{ open };
    796798                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    803805                                                }
    804806                                        }
     807                                        else if ( isFtype (t1) && isFtype (t2) ) {
     808                                                auto f1 = t1.as<ast::FunctionType>();
     809                                                if (!f1) return;
     810                                                auto f2 = t2.strict_as<ast::FunctionType>();
     811
     812                                                assertf(f1->returns.size() <= 1, "Function return should not be a list");
     813                                                assertf(f2->returns.size() <= 1, "Function return should not be a list");
     814
     815                                                if (
     816                                                        ( f1->params.size() != f2->params.size() || f1->returns.size() != f2->returns.size() )
     817                                                        && ! f1->isTtype()
     818                                                        && ! f2->isTtype()
     819                                                ) return;
     820
     821                                                auto params1 = flattenList( f1->params, tenv );
     822                                                auto params2 = flattenList( f2->params, tenv );
     823
     824                                                auto crnt1 = params1.begin();
     825                                                auto crnt2 = params2.begin();
     826                                                auto end1 = params1.end();
     827                                                auto end2 = params2.end();
     828
     829                                                while (crnt1 != end1 && crnt2 != end2 ) {
     830                                                        const ast::Type * arg1 = *crnt1;
     831                                                        const ast::Type * arg2 = *crnt2;
     832
     833                                                        bool isTuple1 = Tuples::isTtype( t1 );
     834                                                        bool isTuple2 = Tuples::isTtype( t2 );
     835
     836                                                        // assumes here that ttype *must* be last parameter
     837                                                        if ( isTuple1 && ! isTuple2 ) {
     838                                                                // combine remainder of list2, then unify
     839                                                                if (unifyExact(
     840                                                                        arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
     841                                                                        noWiden(), symtab )) {
     842                                                                                break;
     843
     844                                                                }
     845                                                                else return;
     846                                                        } else if ( ! isTuple1 && isTuple2 ) {
     847                                                                // combine remainder of list1, then unify
     848                                                                if (unifyExact(
     849                                                                        tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open,
     850                                                                        noWiden(), symtab )) {
     851                                                                                break;
     852
     853                                                                }
     854                                                                else return;
     855                                                        }
     856
     857                                                        // allow qualifiers of pointer and reference base to become more specific
     858                                                        if (auto ref1 = dynamic_cast<const ast::ReferenceType *> (arg1)) {
     859                                                                if (auto ref2 = dynamic_cast<const ast::ReferenceType *> (arg2)) {
     860                                                                        ast::ptr<ast::Type> base1 = ref1->base;
     861                                                                        ast::ptr<ast::Type> base2 = ref2->base;
     862
     863                                                                        // xxx - assume LHS is always the target type
     864
     865                                                                        if ( ! ((widen.second && ref2->qualifiers.is_mutex)
     866                                                                        || (ref1->qualifiers.is_mutex == ref2->qualifiers.is_mutex ))) return;
     867
     868                                                                        if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) {
     869
     870                                                                                reset_qualifiers(base1);
     871                                                                                reset_qualifiers(base2);
     872
     873                                                                                if ( ! unifyExact(
     874                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
     875                                                                                ) return;
     876                                                                        }       
     877                                                                }
     878                                                                else return;
     879                                                        }
     880                                                        else if (auto ptr1 = dynamic_cast<const ast::PointerType *> (arg1)) {
     881                                                                if (auto ptr2 = dynamic_cast<const ast::PointerType *> (arg2)) {
     882                                                                        ast::ptr<ast::Type> base1 = ptr1->base;
     883                                                                        ast::ptr<ast::Type> base2 = ptr2->base;
     884
     885                                                                        // xxx - assume LHS is always the target type
     886                                                                        // a function accepting const can always be called by non-const arg
     887
     888                                                                        if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) {
     889
     890                                                                                reset_qualifiers(base1);
     891                                                                                reset_qualifiers(base2);
     892
     893                                                                                if ( ! unifyExact(
     894                                                                                        base1, base2, tenv, need, have, open, noWiden(), symtab )
     895                                                                                ) return;
     896                                                                        }       
     897                                                                }
     898                                                                else return;
     899
     900                                                        }
     901                                                        else if (! unifyExact(
     902                                                                arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return;
     903
     904                                                        ++crnt1; ++crnt2;
     905                                                }
     906                                                if ( crnt1 != end1 ) {
     907                                                        // try unifying empty tuple with ttype
     908                                                        const ast::Type * t1 = *crnt1;
     909                                                        if (! Tuples::isTtype( t1 ) ) return;
     910                                                        if (! unifyExact(
     911                                                                t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
     912                                                                noWiden(), symtab )) return;
     913                                                } else if ( crnt2 != end2 ) {
     914                                                        // try unifying empty tuple with ttype
     915                                                        const ast::Type * t2 = *crnt2;
     916                                                        if (! Tuples::isTtype( t2 ) ) return;
     917                                                        if (! unifyExact(
     918                                                                tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open,
     919                                                                noWiden(), symtab )) return;
     920                                                }
     921                                                if ((f1->returns.size() == 0 && f2->returns.size() == 0)
     922                                                  || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) {
     923                                                        result = pointer;
     924
     925                                                        for (auto & assn : f1->assertions) {
     926                                                                auto i = need.find(assn);
     927                                                                if (i != need.end()) i->second.isUsed = true;
     928                                                                auto j = have.find(assn);
     929                                                                if (j != have.end()) j->second.isUsed = true;
     930                                                        }
     931
     932                                                        for (auto & assn : f2->assertions) {
     933                                                                auto i = need.find(assn);
     934                                                                if (i != need.end()) i->second.isUsed = true;
     935                                                                auto j = have.find(assn);
     936                                                                if (j != have.end()) j->second.isUsed = true;
     937                                                        }
     938
     939                                                }
     940                                        } // if ftype
     941                                       
    805942                                }
    806943                        } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) {
     
    839976                                        reset_qualifiers( t2 );
    840977
    841                                         ast::AssertionSet have, need;
    842978                                        ast::OpenVarSet newOpen{ open };
    843979                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    857993                                // xxx - does unifying a ref with typed enumInst makes sense?
    858994                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    859                                         result = commonType( type2, ref, widen, symtab, tenv, open );
     995                                        result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
    860996                        }
    861997                }
     
    8771013                        // xxx - is this already handled by unify?
    8781014                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    879                                 result = commonType( type2, enumInst, widen, symtab, tenv, open );
     1015                                result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
    8801016                }
    8811017
     
    8951031                                        reset_qualifiers( t2 );
    8961032
    897                                         ast::AssertionSet have, need;
    8981033                                        ast::OpenVarSet newOpen{ open };
    8991034                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     
    9991134        ast::ptr< ast::Type > commonType(
    10001135                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    1001                         WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
    1002                         const ast::OpenVarSet & open
     1136                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     1137                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
    10031138        ) {
    10041139                unsigned depth1 = type1->referenceDepth();
     
    10361171                }
    10371172                // otherwise both are reference types of the same depth and this is handled by the visitor
    1038                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
     1173                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have };
    10391174                type1->accept( visitor );
    10401175                ast::ptr< ast::Type > result = visitor.core.result;
     
    10471182                                        if ( type->base ) {
    10481183                                                ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    1049                                                 ast::AssertionSet have, need;
    10501184                                                ast::OpenVarSet newOpen{ open };
    10511185
  • src/ResolvExpr/ConversionCost.cc

    r428adbc r7f6a7c9  
    2222#include "ResolvExpr/Cost.h"             // for Cost
    2323#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
     24#include "ResolvExpr/Unify.h"
    2425#include "SymTab/Indexer.h"              // for Indexer
    2526#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    2627#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
    2728#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
     29
    2830
    2931namespace ResolvExpr {
     
    338340                } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
    339341                        const EnumDecl * base_enum = enumInst->baseEnum;
    340                         if ( const Type * base = base_enum->base ) { // if the base enum has a base (if it is typed)
     342                        if ( const Type * base = base_enum->base ) {
    341343                                if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
    342344                                        conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
     
    632634        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    633635                const ast::EnumDecl * enumDecl = enumInst->base.get();
    634                 if ( const ast::Type * enumType = enumDecl->base.get() ) {
     636                if ( enumDecl->isTyped && !enumDecl->base.get() ) {
     637                        cost = Cost::infinity;
     638                } else if ( const ast::Type * enumType = enumDecl->base.get() ) {
    635639                        if ( const ast::BasicType * enumTypeAsBasic = dynamic_cast<const ast::BasicType *>(enumType) ) {
    636640                                conversionCostFromBasicToBasic( basicType, enumTypeAsBasic );
     
    655659                                cost = Cost::safe;
    656660                        }
    657                 } else {
     661                }
     662                /*
     663                else if ( const ast::FunctionType * dstFunc = dstAsPtr->base.as<ast::FunctionType>()) {
     664                        if (const ast::FunctionType * srcFunc = pointerType->base.as<ast::FunctionType>()) {
     665                                if (dstFunc->params.empty() && dstFunc->isVarArgs ) {
     666                                        cost = Cost::unsafe; // assign any function to variadic fptr
     667                                }
     668                        }
     669                        else {
     670                                ast::AssertionSet need, have; // unused
     671                                ast::OpenVarSet open;
     672                                env.extractOpenVars(open);
     673                                ast::TypeEnvironment tenv = env;
     674                                if ( unify(dstAsPtr->base, pointerType->base, tenv, need, have, open, symtab) ) {
     675                                        cost = Cost::safe;
     676                                }
     677                        }
     678                        // else infinity
     679                }
     680                */
     681                else {
    658682                        int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
    659683                        if ( 0 < assignResult && tq1 <= tq2 ) {
     
    694718        const ast::EnumDecl * baseEnum = enumInstType->base;
    695719        if ( const ast::Type * baseType = baseEnum->base ) {
    696                 cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
     720                costCalc( baseType, dst, srcIsLvalue, symtab, env );
    697721        } else {
    698722                (void)enumInstType;
  • src/ResolvExpr/Resolver.cc

    r428adbc r7f6a7c9  
    14781478                        // enum type is still incomplete at this point. Use `int` instead.
    14791479
    1480                         if (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base) {
     1480                        if ( auto enumBase = dynamic_cast< const ast::EnumInstType * >
     1481                                ( objectDecl->get_type() )->base->base ) {
    14811482                                objectDecl = fixObjectType( objectDecl, context );
    1482                                 const ast::Type * enumBase =  (dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() )->base->base.get());
    14831483                                currentObject = ast::CurrentObject{
    14841484                                        objectDecl->location,
     
    14931493                }
    14941494                else {
    1495                         if (!objectDecl->isTypeFixed) {
     1495                        if ( !objectDecl->isTypeFixed ) {
    14961496                                auto newDecl = fixObjectType(objectDecl, context);
    14971497                                auto mutDecl = mutate(newDecl);
  • src/ResolvExpr/SatisfyAssertions.cpp

    r428adbc r7f6a7c9  
    3636#include "AST/SymbolTable.hpp"
    3737#include "AST/TypeEnvironment.hpp"
     38#include "FindOpenVars.h"
    3839#include "Common/FilterCombos.h"
    3940#include "Common/Indenter.h"
     
    161162
    162163        /// Satisfy a single assertion
    163         bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat ) {
     164        bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) {
    164165                // skip unused assertions
    165166                if ( ! assn.second.isUsed ) return true;
     
    180181                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
    181182                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
     183                        else if (skipUnbound) return false;
    182184
    183185                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     
    205207
    206208                        // only keep candidates which unify
    207                         if ( unify( toType, adjType, newEnv, newNeed, have, newOpen, sat.symtab ) ) {
    208                                 // set up binding slot for recursive assertions
    209                                 ast::UniqueId crntResnSlot = 0;
    210                                 if ( ! newNeed.empty() ) {
    211                                         crntResnSlot = ++globalResnSlot;
    212                                         for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
    213                                 }
    214 
    215                                 matches.emplace_back(
    216                                         cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    217                                         std::move( newOpen ), crntResnSlot );
     209
     210                        ast::OpenVarSet closed;
     211                        findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed );
     212                        findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
     213                        if ( allowConversion ) {
     214                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     215                                        // set up binding slot for recursive assertions
     216                                        ast::UniqueId crntResnSlot = 0;
     217                                        if ( ! newNeed.empty() ) {
     218                                                crntResnSlot = ++globalResnSlot;
     219                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     220                                        }
     221
     222                                        matches.emplace_back(
     223                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     224                                                std::move( newOpen ), crntResnSlot );
     225                                }
     226                        }
     227                        else {
     228                                if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     229                                        // set up binding slot for recursive assertions
     230                                        ast::UniqueId crntResnSlot = 0;
     231                                        if ( ! newNeed.empty() ) {
     232                                                crntResnSlot = ++globalResnSlot;
     233                                                for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; }
     234                                        }
     235
     236                                        matches.emplace_back(
     237                                                cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     238                                                std::move( newOpen ), crntResnSlot );
     239                                }
    218240                        }
    219241                }
     
    413435                // for each current mutually-compatible set of assertions
    414436                for ( SatState & sat : sats ) {
     437                        bool allowConversion = false;
    415438                        // stop this branch if a better option is already found
    416439                        auto it = thresholds.find( pruneKey( *sat.cand ) );
     
    418441
    419442                        // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen.
     443
    420444                        for (unsigned resetCount = 0; ; ++resetCount) {
    421445                                ast::AssertionList next;
     
    424448                                for ( auto & assn : sat.need ) {
    425449                                        // fail early if any assertion is not satisfiable
    426                                         if ( ! satisfyAssertion( assn, sat ) ) {
     450                                        if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) {
    427451                                                next.emplace_back(assn);
    428452                                                // goto nextSat;
     
    433457                                // fail if nothing resolves
    434458                                else if (next.size() == sat.need.size()) {
    435                                         Indenter tabs{ 3 };
    436                                         std::ostringstream ss;
    437                                         ss << tabs << "Unsatisfiable alternative:\n";
    438                                         print( ss, *sat.cand, ++tabs );
    439                                         ss << (tabs-1) << "Could not satisfy assertion:\n";
    440                                         ast::print( ss, next[0].first, tabs );
    441 
    442                                         errors.emplace_back( ss.str() );
    443                                         goto nextSat;
    444                                 }
     459                                        if (allowConversion) {
     460                                                Indenter tabs{ 3 };
     461                                                std::ostringstream ss;
     462                                                ss << tabs << "Unsatisfiable alternative:\n";
     463                                                print( ss, *sat.cand, ++tabs );
     464                                                ss << (tabs-1) << "Could not satisfy assertion:\n";
     465                                                ast::print( ss, next[0].first, tabs );
     466
     467                                                errors.emplace_back( ss.str() );
     468                                                goto nextSat;
     469                                        }
     470
     471                                        else {
     472                                                allowConversion = true;
     473                                                continue;
     474                                        }
     475                                }
     476                                allowConversion = false;
    445477                                sat.need = std::move(next);
    446478                        }
  • src/ResolvExpr/Unify.cc

    r428adbc r7f6a7c9  
    165165                ast::Type * newFirst  = shallowCopy( first  );
    166166                ast::Type * newSecond = shallowCopy( second );
     167                if ( auto temp = dynamic_cast<const ast::EnumInstType *>(first) ) {
     168                        if ( !dynamic_cast< const ast::EnumInstType * >( second ) ) {
     169                                const ast::EnumDecl * baseEnum = dynamic_cast<const ast::EnumDecl *>(temp->base.get());
     170                                if ( auto t = baseEnum->base.get() ) {
     171                                        newFirst = ast::shallowCopy( t );
     172                                }
     173                        }
     174                } else if ( auto temp = dynamic_cast<const ast::EnumInstType *>(second) ) {
     175                        const ast::EnumDecl * baseEnum = dynamic_cast<const ast::EnumDecl *>(temp->base.get());
     176                        if ( auto t = baseEnum->base.get() ) {
     177                                newSecond = ast::shallowCopy( t );
     178                        }
     179                }
     180
    167181                newFirst ->qualifiers = {};
    168182                newSecond->qualifiers = {};
     
    693707        }
    694708
     709        namespace {
     710                                /// Replaces ttype variables with their bound types.
     711                /// If this isn't done when satifying ttype assertions, then argument lists can have
     712                /// different size and structure when they should be compatible.
     713                struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
     714                        ast::TypeEnvironment & tenv;
     715
     716                        TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
     717
     718                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     719                                if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
     720                                        // expand ttype parameter into its actual type
     721                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     722                                                return clz->bound;
     723                                        }
     724                                }
     725                                return typeInst;
     726                        }
     727                };
     728        }
     729
     730        std::vector< ast::ptr< ast::Type > > flattenList(
     731                const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     732        ) {
     733                std::vector< ast::ptr< ast::Type > > dst;
     734                dst.reserve( src.size() );
     735                for ( const auto & d : src ) {
     736                        ast::Pass<TtypeExpander_new> expander{ env };
     737                        // TtypeExpander pass is impure (may mutate nodes in place)
     738                        // need to make nodes shared to prevent accidental mutation
     739                        ast::ptr<ast::Type> dc = d->accept(expander);
     740                        auto types = flatten( dc );
     741                        for ( ast::ptr< ast::Type > & t : types ) {
     742                                // outermost const, volatile, _Atomic qualifiers in parameters should not play
     743                                // a role in the unification of function types, since they do not determine
     744                                // whether a function is callable.
     745                                // NOTE: **must** consider at least mutex qualifier, since functions can be
     746                                // overloaded on outermost mutex and a mutex function has different
     747                                // requirements than a non-mutex function
     748                                remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
     749                                dst.emplace_back( t );
     750                        }
     751                }
     752                return dst;
     753        }
     754
    695755        class Unify_new final : public ast::WithShortCircuiting {
    696756                const ast::Type * type2;
     
    764824
    765825        private:
    766                 /// Replaces ttype variables with their bound types.
    767                 /// If this isn't done when satifying ttype assertions, then argument lists can have
    768                 /// different size and structure when they should be compatible.
    769                 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
    770                         ast::TypeEnvironment & tenv;
    771 
    772                         TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}
    773 
    774                         const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    775                                 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
    776                                         // expand ttype parameter into its actual type
    777                                         if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
    778                                                 return clz->bound;
    779                                         }
    780                                 }
    781                                 return typeInst;
    782                         }
    783                 };
    784 
    785                 /// returns flattened version of `src`
    786                 static std::vector< ast::ptr< ast::Type > > flattenList(
    787                         const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    788                 ) {
    789                         std::vector< ast::ptr< ast::Type > > dst;
    790                         dst.reserve( src.size() );
    791                         for ( const auto & d : src ) {
    792                                 ast::Pass<TtypeExpander_new> expander{ env };
    793                                 // TtypeExpander pass is impure (may mutate nodes in place)
    794                                 // need to make nodes shared to prevent accidental mutation
    795                                 ast::ptr<ast::Type> dc = d->accept(expander);
    796                                 auto types = flatten( dc );
    797                                 for ( ast::ptr< ast::Type > & t : types ) {
    798                                         // outermost const, volatile, _Atomic qualifiers in parameters should not play
    799                                         // a role in the unification of function types, since they do not determine
    800                                         // whether a function is callable.
    801                                         // NOTE: **must** consider at least mutex qualifier, since functions can be
    802                                         // overloaded on outermost mutex and a mutex function has different
    803                                         // requirements than a non-mutex function
    804                                         remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    805                                         dst.emplace_back( t );
    806                                 }
    807                         }
    808                         return dst;
    809                 }
    810 
    811                 /// Creates a tuple type based on a list of DeclWithType
    812                 template< typename Iter >
    813                 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
    814                         std::vector< ast::ptr< ast::Type > > types;
    815                         while ( crnt != end ) {
    816                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    817                                 // that this results in a flat tuple
    818                                 flatten( *crnt, types );
    819 
    820                                 ++crnt;
    821                         }
    822 
    823                         return new ast::TupleType{ std::move(types) };
    824                 }
    825826
    826827                template< typename Iter >
     
    10341035        private:
    10351036                /// Creates a tuple type based on a list of Type
    1036                 static const ast::Type * tupleFromTypes(
    1037                         const std::vector< ast::ptr< ast::Type > > & tys
    1038                 ) {
    1039                         std::vector< ast::ptr< ast::Type > > out;
    1040                         for ( const ast::Type * ty : tys ) {
    1041                                 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    1042                                 // that this results in a flat tuple
    1043                                 flatten( ty, out );
    1044                         }
    1045 
    1046                         return new ast::TupleType{ std::move(out) };
    1047                 }
     1037
    10481038
    10491039                static bool unifyList(
     
    12171207                        }
    12181208
    1219                 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1209                } else if (( common = commonType( t1, t2, env, need, have, open, widen, symtab ))) {
    12201210                        // no exact unification, but common type
    12211211                        auto c = shallowCopy(common.get());
  • src/ResolvExpr/typeops.h

    r428adbc r7f6a7c9  
    138138        Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
    139139        ast::ptr< ast::Type > commonType(
    140                 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
    141                 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
     140                const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
     141                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     142                        const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
     143        );
     144        // in Unify.cc
     145        std::vector< ast::ptr< ast::Type > > flattenList(
     146                const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
     147        );
    142148
    143149        // in PolyCost.cc
     
    181187
    182188        /// flatten tuple type into existing list of types
    183         static inline void flatten(
     189        inline void flatten(
    184190                const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
    185191        ) {
     
    194200
    195201        /// flatten tuple type into list of types
    196         static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
     202        inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {
    197203                std::vector< ast::ptr< ast::Type > > out;
    198204                out.reserve( type->size() );
     
    200206                return out;
    201207        }
     208
     209        template< typename Iter >
     210        const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
     211                std::vector< ast::ptr< ast::Type > > types;
     212                while ( crnt != end ) {
     213                        // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
     214                        // that this results in a flat tuple
     215                        flatten( *crnt, types );
     216
     217                        ++crnt;
     218                }
     219
     220
     221                return new ast::TupleType{ std::move(types) };
     222        }
     223
     224        inline const ast::Type * tupleFromTypes(
     225                const std::vector< ast::ptr< ast::Type > > & tys
     226        ) {
     227                return tupleFromTypes( tys.begin(), tys.end() );
     228        }
     229
     230       
    202231
    203232        // in TypeEnvironment.cc
  • src/SymTab/Mangler.cc

    r428adbc r7f6a7c9  
    6565                                void postvisit( const QualifiedType * qualType );
    6666
     67                                void postvisit( const QualifiedNameExpr * qualNameExpr );
     68
    6769                                std::string get_mangleName() { return mangleName; }
    6870                          private:
     
    305307                                        mangleName += Encoding::qualifiedTypeEnd;
    306308                                }
     309                        }
     310
     311                        void Mangler_old::postvisit( const QualifiedNameExpr * qual ) {
     312                                maybeAccept( qual->var, *visitor );
    307313                        }
    308314
     
    417423                        void postvisit( const ast::OneType * oneType );
    418424                        void postvisit( const ast::QualifiedType * qualType );
     425                        void postvisit( const ast::QualifiedNameExpr * qualNameExpr );
    419426
    420427                        std::string get_mangleName() { return mangleName; }
     
    645652                                mangleName += Encoding::qualifiedTypeEnd;
    646653                        }
     654                }
     655                void Mangler_new::postvisit( const ast::QualifiedNameExpr * qual ) {
     656                        maybeAccept( qual->var.get(), *visitor );
    647657                }
    648658
  • src/SymTab/Validate.cc

    r428adbc r7f6a7c9  
    857857                } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
    858858                        declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
    859                 } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
     859                } else if ( EnumInstType * enumInst = dynamic_cast< EnumInstType * >( designatorType ) ) {
    860860                        // declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage, enumDecl->baseEnum->base ) );
    861                         if (enumDecl->baseEnum) {
    862                                 declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage, enumDecl->baseEnum->base ) );
     861                        if ( enumInst->baseEnum ) {
     862                                const EnumDecl * enumDecl = enumInst->baseEnum;
     863                                declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, enumDecl->isTyped, tyDecl->linkage, enumDecl->base ) );
    863864                        } else {
    864                                 declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) );
     865                                declsToAddBefore.push_back( new EnumDecl( enumInst->name, noAttributes, tyDecl->linkage ) );
    865866                        }
    866867                } // if
  • src/SymTab/ValidateType.cc

    r428adbc r7f6a7c9  
    8282        void postvisit( QualifiedType * qualType );
    8383
     84        void postvisit( QualifiedNameExpr * qualExpr );
     85
    8486        void postvisit( EnumDecl * enumDecl );
    8587        void postvisit( StructDecl * structDecl );
     
    157159        // linking only makes sense for the 'oldest ancestor' of the qualified type
    158160        qualType->parent->accept( * visitor );
     161}
     162
     163void LinkReferenceToTypes_old::postvisit( QualifiedNameExpr * qualExpr ) {
     164        const EnumDecl * st = local_indexer->lookupEnum( qualExpr->type_decl->name );
     165        qualExpr->type_decl = const_cast<EnumDecl *>(st);
    159166}
    160167
  • src/SynTree/Declaration.h

    r428adbc r7f6a7c9  
    145145        virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
    146146
    147         // TODO: Move to the right place
    148147        void checkAssignedValue() const;
    149148};
     
    338337        typedef AggregateDecl Parent;
    339338  public:
     339        bool isTyped;
     340        Type * base;
     341
    340342        EnumDecl( const std::string & name,
    341343         const std::list< Attribute * > & attributes = std::list< class Attribute * >(),
    342           LinkageSpec::Spec linkage = LinkageSpec::Cforall,
    343           Type * baseType = nullptr ) : Parent( name, attributes, linkage ) , base( baseType ){}
    344         EnumDecl( const EnumDecl & other ) : Parent( other ), base( other.base ) {}
    345 
     344          bool isTyped = false, LinkageSpec::Spec linkage = LinkageSpec::Cforall,
     345          Type * baseType = nullptr )
     346          : Parent( name, attributes, linkage ),isTyped(isTyped), base( baseType ) {}
     347        EnumDecl( const EnumDecl & other )
     348          : Parent( other ), isTyped( other.isTyped), base( other.base ) {}
    346349        bool valueOf( Declaration * enumerator, long long int & value );
    347 
    348350        virtual EnumDecl * clone() const override { return new EnumDecl( *this ); }
    349351        virtual void accept( Visitor & v ) override { v.visit( this ); }
    350352        virtual void accept( Visitor & v ) const override { v.visit( this ); }
    351353        virtual Declaration * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
    352         Type * base;
    353         std::unordered_map< std::string, long long int > enumValues;
     354
     355        std::unordered_map< std::string, long long int > enumValues; // This attribute is unused
    354356        virtual void print( std::ostream & os, Indenter indent = {} ) const override final;
    355357  private:
  • src/SynTree/Expression.h

    r428adbc r7f6a7c9  
    163163};
    164164
     165// [Qualifier].name; Qualifier is the type_name from the parser
     166class QualifiedNameExpr : public Expression {
     167  public:
     168        Declaration * type_decl;
     169        std::string name;
     170        DeclarationWithType * var;
     171
     172        QualifiedNameExpr( Declaration * decl, std::string name): Expression(), type_decl(decl), name(name) {}
     173        QualifiedNameExpr( const QualifiedNameExpr & other): Expression(other), type_decl(other.type_decl), name(other.name), var(other.var) {}
     174        DeclarationWithType * get_var() const { return var; }
     175        void set_var( DeclarationWithType * newValue ) { var = newValue; }
     176
     177        virtual ~QualifiedNameExpr() {
     178                delete var;
     179                delete type_decl;
     180        }
     181
     182        virtual QualifiedNameExpr * clone() const override {
     183                return new QualifiedNameExpr( * this );
     184        }
     185        virtual void accept( Visitor & v ) override { v.visit(this); }
     186        virtual void accept( Visitor & v ) const override { v.visit(this); }
     187        virtual Expression * acceptMutator( Mutator & m ) override {
     188                return m.mutate( this );
     189        }
     190       
     191        virtual void print( std::ostream & os, Indenter indent = {} ) const override {
     192                type_decl->print( os, indent );
     193                os << name << std::endl;
     194        }
     195};
     196
    165197/// VariableExpr represents an expression that simply refers to the value of a named variable.
    166198/// Does not take ownership of var.
  • src/SynTree/Mutator.h

    r428adbc r7f6a7c9  
    9898        virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
    9999        virtual Expression * mutate( GenericExpr * genExpr ) = 0;
     100        virtual Expression * mutate( QualifiedNameExpr * qualifiedNameExpr ) = 0;
    100101
    101102        virtual Type * mutate( VoidType * basicType ) = 0;
  • src/SynTree/Statement.cc

    r428adbc r7f6a7c9  
    105105};
    106106
    107 BranchStmt::BranchStmt( Label target, Type type ) throw ( SemanticErrorException ) :
     107BranchStmt::BranchStmt( Label target, Type type ) :
    108108        Statement(), originalTarget( target ), target( target ), computedTarget( nullptr ), type( type ) {
    109109        //actually this is a syntactic error signaled by the parser
     
    113113}
    114114
    115 BranchStmt::BranchStmt( Expression * computedTarget, Type type ) throw ( SemanticErrorException ) :
     115BranchStmt::BranchStmt( Expression * computedTarget, Type type ) :
    116116        Statement(), computedTarget( computedTarget ), type( type ) {
    117117        if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
     
    211211}
    212212
    213 CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :
     213CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) :
    214214                Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
    215215        if ( isDefault() && condition != nullptr ) SemanticError( condition, "default case with condition: " );
     
    575575}
    576576
    577 MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs ) 
     577MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs )
    578578        : Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
    579579
  • src/SynTree/Statement.h

    r428adbc r7f6a7c9  
    200200        std::list<Statement *> stmts;
    201201
    202         CaseStmt( Expression * conditions, const std::list<Statement *> & stmts, bool isdef = false ) throw (SemanticErrorException);
     202        CaseStmt( Expression * conditions, const std::list<Statement *> & stmts, bool isdef = false );
    203203        CaseStmt( const CaseStmt & other );
    204204        virtual ~CaseStmt();
     
    289289        Type type;
    290290
    291         BranchStmt( Label target, Type ) throw (SemanticErrorException);
    292         BranchStmt( Expression * computedTarget, Type ) throw (SemanticErrorException);
     291        BranchStmt( Label target, Type );
     292        BranchStmt( Expression * computedTarget, Type );
    293293
    294294        Label get_originalTarget() { return originalTarget; }
  • src/SynTree/SynTree.h

    r428adbc r7f6a7c9  
    103103class DefaultArgExpr;
    104104class GenericExpr;
     105class QualifiedNameExpr;
    105106
    106107class Type;
  • src/SynTree/Type.cc

    r428adbc r7f6a7c9  
    8080// These must remain in the same order as the corresponding bit fields.
    8181const char * Type::FuncSpecifiersNames[] = { "inline", "_Noreturn", "fortran" };
    82 const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "_Thread_local" };
     82const char * Type::StorageClassesNames[] = { "extern", "static", "auto", "register", "__thread", "_Thread_local" };
    8383const char * Type::QualifiersNames[] = { "const", "restrict", "volatile", "mutex", "_Atomic" };
    8484
  • src/SynTree/Type.h

    r428adbc r7f6a7c9  
    8484        }; // FuncSpecifiers
    8585
    86         enum { Extern = 1 << 0, Static = 1 << 1, Auto = 1 << 2, Register = 1 << 3, Threadlocal = 1 << 4, NumStorageClass = 5 };
     86        enum { Extern = 1 << 0, Static = 1 << 1, Auto = 1 << 2, Register = 1 << 3, ThreadlocalGcc = 1 << 4, ThreadlocalC11 = 1 << 5, NumStorageClass = 6 };
    8787        static const char * StorageClassesNames[];
    8888        union StorageClasses {
     
    9393                        bool is_auto : 1;
    9494                        bool is_register : 1;
    95                         bool is_threadlocal : 1;
     95                        bool is_threadlocalGcc : 1;
     96                        bool is_threadlocalC11 : 1;
    9697                };
    9798
     
    100101                // equality (==, !=) works implicitly on first field "val", relational operations are undefined.
    101102                BFCommon( StorageClasses, NumStorageClass )
     103
     104                bool is_threadlocal_any() { return this->is_threadlocalC11 || this->is_threadlocalGcc; }
    102105        }; // StorageClasses
    103106
     
    342345        Type * parent;
    343346        Type * child;
    344 
    345347        QualifiedType( const Type::Qualifiers & tq, Type * parent, Type * child );
    346348        QualifiedType( const QualifiedType & tq );
  • src/SynTree/Visitor.h

    r428adbc r7f6a7c9  
    101101        virtual void visit( NameExpr * node ) { visit( const_cast<const NameExpr *>(node) ); }
    102102        virtual void visit( const NameExpr * nameExpr ) = 0;
     103        virtual void visit( QualifiedNameExpr * node ) { visit( const_cast<const QualifiedNameExpr*>(node) );}
     104        virtual void visit( const QualifiedNameExpr* qualifiednameExpr ) = 0;
    103105        virtual void visit( CastExpr * node ) { visit( const_cast<const CastExpr *>(node) ); }
    104106        virtual void visit( const CastExpr * castExpr ) = 0;
  • src/Tuples/TupleExpansionNew.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Mon Aug 23 15:36:09 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 29 14:06:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Tue Sep 20 16:17:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    100100}
    101101
    102 struct TupleAssignExpander {
     102/// Replaces Tuple Assign & Index Expressions, and Tuple Types.
     103struct TupleMainExpander final :
     104                public ast::WithCodeLocation,
     105                public ast::WithDeclsToAdd<>,
     106                public ast::WithGuards,
     107                public ast::WithVisitorRef<TupleMainExpander> {
    103108        ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ) {
    104109                // Just move the env on the new top level expression.
     
    106111                        &ast::TupleAssignExpr::env, expr->env.get() );
    107112        }
    108 };
    109 
    110 struct TupleTypeReplacer :
    111                 public ast::WithGuards,
    112                 public ast::WithVisitorRef<TupleTypeReplacer>,
    113                 public ast::WithDeclsToAdd<> {
    114         void previsit( ast::ParseNode const * node ) {
    115                 GuardValue( location ) = &node->location;
    116         }
    117 
    118         void previsit( ast::CompoundStmt const * stmt ) {
    119                 previsit( (ast::ParseNode const *)stmt );
     113
     114        void previsit( ast::CompoundStmt const * ) {
    120115                GuardScope( typeMap );
    121116        }
     
    185180                return newType;
    186181        }
    187 private:
    188         ScopedMap< int, ast::StructDecl const * > typeMap;
    189         CodeLocation const * location = nullptr;
    190 };
    191 
    192 struct TupleIndexExpander {
     182
    193183        ast::Expr const * postvisit( ast::TupleIndexExpr const * expr ) {
    194184                CodeLocation const & location = expr->location;
     
    221211                return memberExpr;
    222212        }
     213private:
     214        ScopedMap< int, ast::StructDecl const * > typeMap;
    223215};
    224216
     
    257249}
    258250
    259 struct TupleExprExpander {
     251struct TupleExprExpander final {
    260252        ast::Expr const * postvisit( ast::TupleExpr const * expr ) {
    261253                return replaceTupleExpr( expr->location,
     
    275267
    276268void expandTuples( ast::TranslationUnit & translationUnit ) {
    277         // These may not have to be seperate passes.
    278         ast::Pass<TupleAssignExpander>::run( translationUnit );
    279         ast::Pass<TupleTypeReplacer>::run( translationUnit );
    280         ast::Pass<TupleIndexExpander>::run( translationUnit );
     269        // These can't just be combined simply (there might be a way with work).
     270        ast::Pass<TupleMainExpander>::run( translationUnit );
    281271        ast::Pass<TupleExprExpander>::run( translationUnit );
    282272}
  • src/Validate/Autogen.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Thu Dec  2 13:44:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Jan 27  9:29:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep 20 16:00:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    2525
    2626#include "AST/Attribute.hpp"
     27#include "AST/Create.hpp"
    2728#include "AST/Decl.hpp"
    2829#include "AST/DeclReplacer.hpp"
     
    236237        if ( !enumDecl->body ) return;
    237238
     239        // if ( auto enumBaseType = enumDecl->base ) {
     240        //      if ( auto enumBaseTypeAsStructInst = dynamic_cast<const ast::StructInstType *>(enumBaseType.get()) ) {
     241        //              const ast::StructDecl * structDecl = enumBaseTypeAsStructInst->base.get();
     242        //              this->previsit( structDecl );
     243        //      }
     244        // }
     245
    238246        ast::EnumInstType enumInst( enumDecl->name );
    239247        enumInst.base = enumDecl;
     
    321329void FuncGenerator::produceForwardDecl( const ast::FunctionDecl * decl ) {
    322330        if (0 != functionNesting) return;
    323         ast::FunctionDecl * fwd = ast::deepCopy( decl );
    324         fwd->stmts = nullptr;
     331        ast::FunctionDecl * fwd =
     332                ( decl->stmts ) ? ast::asForward( decl ) : ast::deepCopy( decl ) ;
    325333        fwd->fixUniqueId();
    326334        forwards.push_back( fwd );
  • src/Validate/EnumAndPointerDecay.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Tue Jun 28 15:50:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jul 12 14:45:00 2022
    13 // Update Count     : 0
     12// Last Modified On : Tue Sep 20 16:14:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    2626namespace {
    2727
    28 struct EnumAndPointerDecayCore final : public ast::WithGuards {
    29         CodeLocation const * location = nullptr;
    30         void previsit( ast::ParseNode const * node );
     28struct EnumAndPointerDecayCore final : public ast::WithCodeLocation {
    3129        ast::EnumDecl const * previsit( ast::EnumDecl const * decl );
    3230        ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl );
    3331        ast::FunctionType const * previsit( ast::FunctionType const * type );
    3432};
    35 
    36 void EnumAndPointerDecayCore::previsit( ast::ParseNode const * node ) {
    37         GuardValue( location ) = &node->location;
    38 }
    3933
    4034ast::EnumDecl const * EnumAndPointerDecayCore::previsit(
     
    5044                        new ast::EnumInstType( decl, ast::CV::Const ) );
    5145        }
    52         GuardValue( location ) = &decl->location;
    5346        return mut;
    5447}
     
    7972                ast::FunctionDecl const * decl ) {
    8073        auto mut = ast::mutate( decl );
    81         GuardValue( location ) = &decl->location;
    8274        ast::ArgumentFlag isVarArgs = mut->type->isVarArgs;
    8375        // It seems fixFunction (via fixFunctionList) does the pointer decay part.
  • src/Validate/FixQualifiedTypes.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Thr Apr 21 11:13:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 22 11:36:00 2022
    13 // Update Count     : 0
     12// Last Modified On : Tue Sep 20 16:15:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    1919#include "AST/TranslationUnit.hpp"
    2020#include "Validate/NoIdSymbolTable.hpp"
     21#include "SymTab/Mangler.h"            // for Mangler
     22#include "AST/LinkageSpec.hpp"                     // for Linkage
    2123
    2224namespace Validate {
     
    2527
    2628struct FixQualifiedTypesCore :
    27                 public WithNoIdSymbolTable, public ast::WithGuards {
    28         CodeLocation const * location = nullptr;
    29 
    30         void previsit( ast::ParseNode const * node ) {
    31                 GuardValue( location ) = &node->location;
    32         }
    33 
     29                public WithNoIdSymbolTable,
     30                public ast::WithCodeLocation {
    3431        ast::Type const * postvisit( ast::QualifiedType const * type ) {
    3532                assert( location );
     
    8986                }
    9087        }
     88
     89        ast::Expr const * postvisit( ast::QualifiedNameExpr const * t) {
     90                assert( location );
     91                if ( t->type_decl ) {
     92                auto enumName = t->type_decl->name;
     93                const ast::EnumDecl * enumDecl = symtab.lookupEnum( enumName );
     94                        for ( ast::ptr<ast::Decl> const & member : enumDecl->members ) {
     95                                if ( auto memberAsObj = member.as<ast::ObjectDecl>() ) {
     96                                        if ( memberAsObj->name == t->name ) {
     97                                                return new ast::VariableExpr( t->location, memberAsObj );
     98                                        }
     99                                } else {
     100                                        assertf( false, "unhandled qualified child type");
     101                                }
     102                        }
     103
     104
     105                auto var = new ast::ObjectDecl( t->var->location, t->name,
     106                         new ast::EnumInstType(enumDecl, ast::CV::Const), nullptr, {}, ast::Linkage::Cforall );
     107                        var->scopeLevel = 1; // 1 for now; should copy the scopeLevel of the enumValue
     108                        var->mangleName = Mangle::mangle( var );
     109                        return new ast::VariableExpr( t->location, var );
     110                // return ret;
     111        }
     112
     113                return t;
     114        }
     115
    91116};
    92117
  • src/Validate/GenericParameter.cpp

    r428adbc r7f6a7c9  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // GenericParameter.hpp -- Generic parameter related passes.
     7// GenericParameter.cpp -- Generic parameter related passes.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Fri Mar 21 10:02:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 22 16:43:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep 20 16:28:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    119119}
    120120
    121 struct ValidateGenericParamsCore : public ast::WithGuards {
    122         const CodeLocation * locationPtr = nullptr;
    123 
    124         void previsit( const ast::ParseNode * node ) {
    125                 GuardValue( locationPtr ) = &node->location;
    126         }
    127 
     121struct ValidateGenericParamsCore : public ast::WithCodeLocation {
    128122        const ast::StructInstType * previsit( const ast::StructInstType * type ) {
    129                 assert( locationPtr );
    130                 return validateGeneric( *locationPtr, type );
     123                assert( location );
     124                return validateGeneric( *location, type );
    131125        }
    132126
    133127        const ast::UnionInstType * previsit( const ast::UnionInstType * type ) {
    134                 assert( locationPtr );
    135                 return validateGeneric( *locationPtr, type );
     128                assert( location );
     129                return validateGeneric( *location, type );
    136130        }
    137131};
  • src/Validate/LinkReferenceToTypes.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Thr Apr 21 11:41:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun 28 14:58:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep 20 16:17:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    2626
    2727struct LinkTypesCore : public WithNoIdSymbolTable,
     28                public ast::WithCodeLocation,
    2829                public ast::WithGuards,
    29                 public ast::WithVisitorRef<LinkTypesCore>,
    30                 public ast::WithShortCircuiting {
    31 
     30                public ast::WithShortCircuiting,
     31                public ast::WithVisitorRef<LinkTypesCore> {
    3232        ast::TypeInstType const * postvisit( ast::TypeInstType const * type );
    3333        ast::EnumInstType const * postvisit( ast::EnumInstType const * type );
     
    3838        void postvisit( ast::QualifiedType const * type );
    3939
    40         void previsit( ast::ParseNode const * node );
    41 
    4240        ast::EnumDecl const * postvisit( ast::EnumDecl const * decl );
    4341        ast::StructDecl const * previsit( ast::StructDecl const * decl );
     
    4644        void postvisit( ast::UnionDecl const * decl );
    4745        ast::TraitDecl const * postvisit( ast::TraitDecl const * decl );
     46        ast::QualifiedNameExpr const * previsit( ast::QualifiedNameExpr const * decl);
    4847
    4948private:
     
    5958        ForwardEnumsType forwardEnums;
    6059
    61         const CodeLocation * location = nullptr;
    6260        /// true if currently in a generic type body,
    6361        /// so that type parameter instances can be renamed appropriately
     
    176174        // Linking only makes sense for the 'oldest ancestor' of the qualified type.
    177175        type->parent->accept( *visitor );
    178 }
    179 
    180 void LinkTypesCore::previsit( ast::ParseNode const * node ) {
    181         GuardValue( location ) = &node->location;
    182176}
    183177
     
    224218        GuardValue( inGeneric ) = !decl->params.empty();
    225219        if ( !inGeneric ) {
    226                 GuardValue( location ) = &decl->location;
    227220                return decl;
    228221        }
    229222        auto mut = ast::mutate( decl );
    230         GuardValue( location ) = &mut->location;
    231223        for ( ast::ptr<ast::TypeDecl> & typeDecl : mut->params ) {
    232224                typeDecl.get_and_mutate()->name = "__" + typeDecl->name + "_generic_";
     
    292284}
    293285
     286ast::QualifiedNameExpr const * LinkTypesCore::previsit( ast::QualifiedNameExpr const * decl ) {
     287        // Try to lookup type
     288        if ( auto objDecl = decl->type_decl.as<ast::ObjectDecl>() ) {
     289                if ( auto inst = objDecl->type.as<ast::TypeInstType>()) {
     290                        if ( auto enumDecl = symtab.lookupEnum ( inst->name ) ) {
     291                                auto mut = ast::mutate( decl );
     292                                mut->type_decl = enumDecl;
     293                                auto enumInst = new ast::EnumInstType( enumDecl );
     294                                enumInst->name = decl->name;
     295                                // Adding result; addCandidate() use result
     296                                mut->result = enumInst;
     297                                decl = mut;
     298                        }
     299                }
     300        } else if ( auto enumDecl = decl->type_decl.as<ast::EnumDecl>() ) {
     301                auto mut = ast::mutate( decl );
     302                auto enumInst = new ast::EnumInstType( enumDecl );
     303                enumInst->name = decl->name;
     304                // Adding result; addCandidate() use result
     305                mut->result = enumInst;
     306                decl = mut;
     307        }
     308        // ast::EnumDecl const * decl = symtab.lookupEnum( type->name );
     309        // // It's not a semantic error if the enum is not found, just an implicit forward declaration.
     310        // if ( decl ) {
     311        //      // Just linking in the node.
     312        //      auto mut = ast::mutate( type );
     313        //      mut->base = const_cast<ast::EnumDecl *>( decl );
     314        //      type = mut;
     315        // }
     316        return decl;
     317}
     318
    294319} // namespace
    295320
  • src/Validate/ReplaceTypedef.cpp

    r428adbc r7f6a7c9  
    1010// Created On       : Tue Jun 29 14:59:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 13 14:45:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep 20 17:00:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    3939
    4040struct ReplaceTypedefCore final :
    41                 public ast::WithVisitorRef<ReplaceTypedefCore>,
     41                public ast::WithCodeLocation,
     42                public ast::WithDeclsToAdd<>,
    4243                public ast::WithGuards,
    4344                public ast::WithShortCircuiting,
    44                 public ast::WithDeclsToAdd<> {
    45 
    46         void previsit( ast::ParseNode const * node );
     45                public ast::WithVisitorRef<ReplaceTypedefCore> {
     46
    4747        void previsit( ast::QualifiedType const * );
    4848        ast::Type const * postvisit( ast::QualifiedType const * );
     
    7474        TypedefMap typedefNames;
    7575        TypeDeclMap typedeclNames;
    76         CodeLocation const * nearestLocation = nullptr;
    7776        int scopeLevel;
    7877        bool isAtFunctionTop = false;
    7978};
    80 
    81 void ReplaceTypedefCore::previsit( ast::ParseNode const * node ) {
    82         GuardValue( nearestLocation ) = &node->location;
    83 }
    8479
    8580void ReplaceTypedefCore::previsit( ast::QualifiedType const * ) {
     
    115110                        auto rtt = dynamic_cast<ast::BaseInstType *>( ret );
    116111                        if ( !rtt ) {
    117                                 assert( nearestLocation );
    118                                 SemanticError( *nearestLocation, "Cannot apply type parameters to base type of " + type->name );
     112                                assert( location );
     113                                SemanticError( *location, "Cannot apply type parameters to base type of " + type->name );
    119114                        }
    120115                        rtt->params.clear();
     
    129124                TypeDeclMap::const_iterator base = typedeclNames.find( type->name );
    130125                if ( base == typedeclNames.end() ) {
    131                         assert( nearestLocation );
    132                         SemanticError( *nearestLocation, toString( "Use of undefined type ", type->name ) );
     126                        assert( location );
     127                        SemanticError( *location, toString( "Use of undefined type ", type->name ) );
    133128                }
    134129                return ast::mutate_field( type, &ast::TypeInstType::base, base->second );
     
    183178        } else if ( auto enumType = dynamic_cast<ast::EnumInstType const *>( designatorType ) ) {
    184179                declsToAddBefore.push_back( new ast::EnumDecl(
    185                         decl->location, enumType->name, {}, decl->linkage,
     180                        decl->location, enumType->name, false, {}, decl->linkage,
    186181                        ( (enumType->base) ? enumType->base->base : nullptr )
    187182                        ) );
     
    191186
    192187void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
    193         previsit( (ast::ParseNode const *)decl );
    194188        TypedefMap::iterator iter = typedefNames.find( decl->name );
    195189        if ( iter != typedefNames.end() ) {
     
    199193}
    200194
    201 void ReplaceTypedefCore::previsit( ast::FunctionDecl const * decl ) {
    202         previsit( (ast::ParseNode const *)decl );
     195void ReplaceTypedefCore::previsit( ast::FunctionDecl const * ) {
    203196        GuardScope( typedefNames );
    204197        GuardScope( typedeclNames );
     
    206199}
    207200
    208 void ReplaceTypedefCore::previsit( ast::ObjectDecl const * decl ) {
    209         previsit( (ast::ParseNode const *)decl );
     201void ReplaceTypedefCore::previsit( ast::ObjectDecl const * ) {
    210202        GuardScope( typedefNames );
    211203        GuardScope( typedeclNames );
     
    217209                using DWTVector = std::vector<ast::ptr<ast::DeclWithType>>;
    218210                using DeclVector = std::vector<ast::ptr<ast::TypeDecl>>;
    219                 CodeLocation const & location = decl->location;
     211                CodeLocation const & declLocation = decl->location;
    220212                UniqueName paramNamer( decl->name + "Param" );
    221213
    222214                // Replace the current object declaration with a function declaration.
    223215                ast::FunctionDecl const * newDecl = new ast::FunctionDecl(
    224                         location,
     216                        declLocation,
    225217                        decl->name,
    226218                        map_range<DeclVector>( type->forall, []( const ast::TypeInstType * inst ) {
     
    230222                                return ast::deepCopy( expr->var );
    231223                        } ),
    232                         map_range<DWTVector>( type->params, [&location, &paramNamer]( const ast::Type * type ) {
     224                        map_range<DWTVector>( type->params, [&declLocation, &paramNamer]( const ast::Type * type ) {
    233225                                assert( type );
    234                                 return new ast::ObjectDecl( location, paramNamer.newName(), ast::deepCopy( type ) );
     226                                return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
    235227                        } ),
    236                         map_range<DWTVector>( type->returns, [&location, &paramNamer]( const ast::Type * type ) {
     228                        map_range<DWTVector>( type->returns, [&declLocation, &paramNamer]( const ast::Type * type ) {
    237229                                assert( type );
    238                                 return new ast::ObjectDecl( location, paramNamer.newName(), ast::deepCopy( type ) );
     230                                return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
    239231                        } ),
    240232                        nullptr,
     
    249241}
    250242
    251 void ReplaceTypedefCore::previsit( ast::CastExpr const * expr ) {
    252         previsit( (ast::ParseNode const *)expr );
    253         GuardScope( typedefNames );
    254         GuardScope( typedeclNames );
    255 }
    256 
    257 void ReplaceTypedefCore::previsit( ast::CompoundStmt const * expr ) {
    258         previsit( (ast::ParseNode const *)expr );
     243void ReplaceTypedefCore::previsit( ast::CastExpr const * ) {
     244        GuardScope( typedefNames );
     245        GuardScope( typedeclNames );
     246}
     247
     248void ReplaceTypedefCore::previsit( ast::CompoundStmt const * ) {
    259249        GuardScope( typedefNames );
    260250        GuardScope( typedeclNames );
     
    268258
    269259ast::StructDecl const * ReplaceTypedefCore::previsit( ast::StructDecl const * decl ) {
    270         previsit( (ast::ParseNode const *)decl );
    271260        visit_children = false;
    272261        addImplicitTypedef( decl );
     
    275264
    276265ast::UnionDecl const * ReplaceTypedefCore::previsit( ast::UnionDecl const * decl ) {
    277         previsit( (ast::ParseNode const *)decl );
    278266        visit_children = false;
    279267        addImplicitTypedef( decl );
     
    282270
    283271void ReplaceTypedefCore::previsit( ast::EnumDecl const * decl ) {
    284         previsit( (ast::ParseNode const *)decl );
    285272        addImplicitTypedef( decl );
    286273}
    287274
    288 void ReplaceTypedefCore::previsit( ast::TraitDecl const * decl ) {
    289         previsit( (ast::ParseNode const *)decl );
     275void ReplaceTypedefCore::previsit( ast::TraitDecl const * ) {
    290276        GuardScope( typedefNames );
    291277        GuardScope( typedeclNames );
  • src/Virtual/ExpandCasts.cc

    r428adbc r7f6a7c9  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 31 10:29:00 2020
    13 // Update Count     : 4
     12// Last Modified On : Thu Aug 11 12:06:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    2020#include <string>                  // for string, allocator, operator==, ope...
    2121
     22#include "AST/Decl.hpp"
     23#include "AST/Expr.hpp"
     24#include "AST/Pass.hpp"
    2225#include "Common/PassVisitor.h"    // for PassVisitor
    2326#include "Common/ScopedMap.h"      // for ScopedMap
     
    3235namespace Virtual {
    3336
    34 static bool is_prefix( const std::string & prefix, const std::string& entire ) {
     37namespace {
     38
     39bool is_prefix( const std::string & prefix, const std::string& entire ) {
    3540        size_t const p_size = prefix.size();
    3641        return (p_size < entire.size() && prefix == entire.substr(0, p_size));
    3742}
    3843
    39 static bool is_type_id_object( const ObjectDecl * objectDecl ) {
     44bool is_type_id_object( const ObjectDecl * objectDecl ) {
    4045        const std::string & objectName = objectDecl->name;
    4146        return is_prefix( "__cfatid_", objectName );
     47}
     48
     49bool is_type_id_object( const ast::ObjectDecl * decl ) {
     50        return is_prefix( "__cfatid_", decl->name );
    4251}
    4352
     
    124133                }
    125134        }
    126 
    127         namespace {
    128135
    129136        /// Better error locations for generated casts.
     
    229236        }
    230237
    231         } // namespace
    232 
    233238        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    234239                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
     
    265270        }
    266271
    267         void expandCasts( std::list< Declaration * > & translationUnit ) {
    268                 PassVisitor<VirtualCastCore> translator;
    269                 mutateAll( translationUnit, translator );
    270         }
    271 }
     272/// Better error locations for generated casts.
     273// TODO: Does the improved distribution of code locations make this unneeded?
     274CodeLocation castLocation( const ast::VirtualCastExpr * castExpr ) {
     275        if ( castExpr->location.isSet() ) {
     276                return castExpr->location;
     277        } else if ( castExpr->arg->location.isSet() ) {
     278                return castExpr->arg->location;
     279        } else {
     280                return CodeLocation();
     281        }
     282}
     283
     284[[noreturn]] void castError( ast::VirtualCastExpr const * castExpr, std::string const & message ) {
     285        SemanticError( castLocation( castExpr ), message );
     286}
     287
     288class TypeIdTable final {
     289        ScopedMap<std::string, ast::ObjectDecl const *> instances;
     290public:
     291        void enterScope() { instances.beginScope(); }
     292        void leaveScope() { instances.endScope(); }
     293
     294        // Attempt to insert an instance into the map. If there is a conflict,
     295        // returns the previous declaration for error messages.
     296        ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) {
     297                std::string const & mangledName =
     298                                Mangle::mangle( typeIdDecl->type, Mangle::typeMode() );
     299                ast::ObjectDecl const *& value = instances[ mangledName ];
     300                if ( value ) {
     301                        if ( typeIdDecl->storage.is_extern ) {
     302                                return nullptr;
     303                        } else if ( !value->storage.is_extern ) {
     304                                return value;
     305                        }
     306                }
     307                value = typeIdDecl;
     308                return nullptr;
     309        }
     310
     311        ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) {
     312                std::string const & mangledName =
     313                                Mangle::mangle( typeIdType, Mangle::typeMode() );
     314                auto const it = instances.find( mangledName );
     315                return ( instances.end() == it ) ? nullptr : it->second;
     316        }
     317};
     318
     319struct ExpandCastsCore final {
     320        void previsit( ast::FunctionDecl const * decl );
     321        void previsit( ast::StructDecl const * decl );
     322        void previsit( ast::ObjectDecl const * decl );
     323        ast::Expr const * postvisit( ast::VirtualCastExpr const * expr );
     324
     325        ast::CastExpr const * cast_to_type_id(
     326                ast::Expr const * expr, unsigned int level_of_indirection );
     327
     328        ast::FunctionDecl const * vcast_decl = nullptr;
     329        ast::StructDecl const * info_decl = nullptr;
     330
     331        TypeIdTable symtab;
     332};
     333
     334void ExpandCastsCore::previsit( ast::FunctionDecl const * decl ) {
     335        if ( !vcast_decl && "__cfavir_virtual_cast" == decl->name ) {
     336                vcast_decl = decl;
     337        }
     338}
     339
     340void ExpandCastsCore::previsit( ast::StructDecl const * decl ) {
     341        if ( !info_decl && decl->body && "__cfavir_type_info" == decl->name ) {
     342                info_decl = decl;
     343        }
     344}
     345
     346void ExpandCastsCore::previsit( ast::ObjectDecl const * decl ) {
     347        if ( is_type_id_object( decl ) ) {
     348                // Multiple definitions should be fine because of linkonce.
     349                symtab.insert( decl );
     350        }
     351}
     352
     353/// Get the base type from a pointer or reference.
     354ast::Type const * getBaseType( ast::ptr<ast::Type> const & type ) {
     355        if ( auto target = type.as<ast::PointerType>() ) {
     356                return target->base.get();
     357        } else if ( auto target = type.as<ast::ReferenceType>() ) {
     358                return target->base.get();
     359        } else {
     360                return nullptr;
     361        }
     362}
     363
     364/// Copy newType, but give the copy the params of the oldType.
     365ast::StructInstType * polyCopy(
     366                ast::StructInstType const * oldType,
     367                ast::StructInstType const * newType ) {
     368        assert( oldType->params.size() == newType->params.size() );
     369        ast::StructInstType * retType = ast::deepCopy( newType );
     370        if ( ! oldType->params.empty() ) {
     371                retType->params.clear();
     372                for ( auto oldParams : oldType->params ) {
     373                        retType->params.push_back( ast::deepCopy( oldParams ) );
     374                }
     375        }
     376        return retType;
     377}
     378
     379/// Follow the "head" field of the structure to get the type that is pointed
     380/// to by that field.
     381ast::StructInstType const * followHeadPointerType(
     382                CodeLocation const & errorLocation,
     383                ast::StructInstType const * oldType,
     384                std::string const & fieldName ) {
     385        ast::StructDecl const * oldDecl = oldType->base;
     386        assert( oldDecl );
     387
     388        // Helper function for throwing semantic errors.
     389        auto throwError = [&fieldName, &errorLocation, &oldDecl](
     390                        std::string const & message ) {
     391                std::string const & context = "While following head pointer of " +
     392                        oldDecl->name + " named '" + fieldName + "': ";
     393                SemanticError( errorLocation, context + message );
     394        };
     395
     396        if ( oldDecl->members.empty() ) {
     397                throwError( "Type has no fields." );
     398        }
     399        ast::ptr<ast::Decl> const & memberDecl = oldDecl->members.front();
     400        assert( memberDecl );
     401        ast::ObjectDecl const * fieldDecl = memberDecl.as<ast::ObjectDecl>();
     402        assert( fieldDecl );
     403        if ( fieldName != fieldDecl->name ) {
     404                throwError( "Head field did not have expected name." );
     405        }
     406
     407        ast::ptr<ast::Type> const & fieldType = fieldDecl->type;
     408        if ( nullptr == fieldType ) {
     409                throwError( "Could not get head field." );
     410        }
     411        auto ptrType = fieldType.as<ast::PointerType>();
     412        if ( nullptr == ptrType ) {
     413                throwError( "First field is not a pointer type." );
     414        }
     415        assert( ptrType->base );
     416        auto newType = ptrType->base.as<ast::StructInstType>();
     417        if ( nullptr == newType ) {
     418                throwError( "First field does not point to a structure type." );
     419        }
     420
     421        return polyCopy( oldType, newType );
     422}
     423
     424/// Get the type-id type from a virtual type.
     425ast::StructInstType const * getTypeIdType(
     426                CodeLocation const & errorLocation,
     427                ast::Type const * type ) {
     428        auto typeInst = dynamic_cast<ast::StructInstType const *>( type );
     429        if ( nullptr == typeInst ) {
     430                return nullptr;
     431        }
     432        ast::ptr<ast::StructInstType> tableInst =
     433                followHeadPointerType( errorLocation, typeInst, "virtual_table" );
     434        if ( nullptr == tableInst ) {
     435                return nullptr;
     436        }
     437        ast::StructInstType const * typeIdInst =
     438                followHeadPointerType( errorLocation, tableInst, "__cfavir_typeid" );
     439        return typeIdInst;
     440}
     441
     442ast::Expr const * ExpandCastsCore::postvisit(
     443                ast::VirtualCastExpr const * expr ) {
     444        assertf( expr->result, "Virtual cast target not found before expansion." );
     445
     446        assert( vcast_decl );
     447        assert( info_decl );
     448
     449        ast::Type const * base_type = getBaseType( expr->result );
     450        if ( nullptr == base_type ) {
     451                castError( expr, "Virtual cast target must be a pointer or reference type." );
     452        }
     453        ast::StructInstType const * type_id_type =
     454                        getTypeIdType( castLocation( expr ), base_type );
     455        if ( nullptr == type_id_type ) {
     456                castError( expr, "Ill formed virtual cast target type." );
     457        }
     458        ast::ObjectDecl const * type_id = symtab.lookup( type_id_type );
     459        if ( nullptr == type_id ) {
     460                // I'm trying to give a different error for polymorpic types as
     461                // different things can go wrong there.
     462                if ( type_id_type->params.empty() ) {
     463                        castError( expr, "Virtual cast does not target a virtual type." );
     464                } else {
     465                        castError( expr, "Virtual cast does not target a type with a "
     466                                "type id (possible missing virtual table)." );
     467                }
     468        }
     469
     470        return new ast::CastExpr( expr->location,
     471                new ast::ApplicationExpr( expr->location,
     472                        ast::VariableExpr::functionPointer( expr->location, vcast_decl ),
     473                        {
     474                                cast_to_type_id(
     475                                        new ast::AddressExpr( expr->location,
     476                                                new ast::VariableExpr( expr->location, type_id ) ),
     477                                        1 ),
     478                                cast_to_type_id( expr->arg, 2 ),
     479                        }
     480                ),
     481                ast::deepCopy( expr->result )
     482        );
     483}
     484
     485ast::CastExpr const * ExpandCastsCore::cast_to_type_id(
     486                ast::Expr const * expr, unsigned int level_of_indirection ) {
     487        assert( info_decl );
     488        ast::Type * type = new ast::StructInstType( info_decl, ast::CV::Const );
     489        for ( unsigned int i = 0 ; i < level_of_indirection ; ++i ) {
     490                type = new ast::PointerType( type );
     491        }
     492        return new ast::CastExpr( expr->location, expr, type );
     493}
     494
     495} // namespace
     496
     497void expandCasts( std::list< Declaration * > & translationUnit ) {
     498        PassVisitor<VirtualCastCore> translator;
     499        mutateAll( translationUnit, translator );
     500}
     501
     502void expandCasts( ast::TranslationUnit & translationUnit ) {
     503        ast::Pass<ExpandCastsCore>::run( translationUnit );
     504}
     505
     506} // namespace Virtual
  • src/Virtual/ExpandCasts.h

    r428adbc r7f6a7c9  
    1010// Created On       : Mon Jul 24 13:54:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Jul 25 14:51:00 2017
    13 // Update Count     : 0
     12// Last Modified On : Fri Jul 29 14:40:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace Virtual {
    23         void expandCasts( std::list< Declaration * > & translationUnit );
    24         // Breaks all virtual cast nodes up into translatable nodes.
     26void expandCasts( std::list< Declaration * > & translationUnit );
     27void expandCasts( ast::TranslationUnit & translationUnit );
     28// Breaks all virtual cast nodes up into translatable nodes.
    2529
    26         // Later this might just set some information so it can happen at CodeGen.
     30// Later this might just set some information so it can happen at CodeGen.
    2731
    2832}
  • src/config.h.in

    r428adbc r7f6a7c9  
    2727/* Location of cfa install. */
    2828#undef CFA_PREFIX
    29 
    30 /* Sets whether or not to use the new-ast, this is adefault value and can be
    31    overrided by --old-ast and --new-ast */
    32 #undef CFA_USE_NEW_AST
    3329
    3430/* Major.Minor */
  • src/main.cc

    r428adbc r7f6a7c9  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jul 18 11:08:00 2022
    13 // Update Count     : 676
     12// Last Modified On : Thu Sep 15 13:58:00 2022
     13// Update Count     : 678
    1414//
    1515
     
    3838#include "CodeGen/Generate.h"               // for generate
    3939#include "CodeGen/LinkOnce.h"               // for translateLinkOnce
    40 #include "CodeTools/DeclStats.h"            // for printDeclStats
    41 #include "CodeTools/ResolvProtoDump.h"      // for dumpAsResolvProto
    4240#include "CodeTools/TrackLoc.h"             // for fillLocations
    4341#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
     
    4543#include "Common/DeclStats.hpp"             // for printDeclStats
    4644#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    47 #include "Common/Stats.h"
    48 #include "Common/PassVisitor.h"
    49 #include "Common/SemanticError.h"           // for SemanticError
     45#include "Common/Stats.h"                   // for Stats
    5046#include "Common/UnimplementedError.h"      // for UnimplementedError
    5147#include "Common/utility.h"                 // for deleteAll, filter, printAll
     
    5349#include "Concurrency/Waitfor.h"            // for generateWaitfor
    5450#include "ControlStruct/ExceptDecl.h"       // for translateExcept
    55 #include "ControlStruct/ExceptTranslate.h"  // for translateEHM
     51#include "ControlStruct/ExceptTranslate.h"  // for translateThrows, translat...
    5652#include "ControlStruct/FixLabels.hpp"      // for fixLabels
    5753#include "ControlStruct/HoistControlDecls.hpp" //  hoistControlDecls
    58 #include "ControlStruct/Mutate.h"           // for mutate
    5954#include "GenPoly/Box.h"                    // for box
    6055#include "GenPoly/InstantiateGeneric.h"     // for instantiateGeneric
     
    6661#include "Parser/ParseNode.h"               // for DeclarationNode, buildList
    6762#include "Parser/TypedefTable.h"            // for TypedefTable
    68 #include "ResolvExpr/AlternativePrinter.h"  // for AlternativePrinter
    6963#include "ResolvExpr/CandidatePrinter.hpp"  // for printCandidates
    7064#include "ResolvExpr/Resolver.h"            // for resolve
    71 #include "SymTab/Validate.h"                // for validate
    72 #include "SymTab/ValidateType.h"            // for linkReferenceToTypes
    7365#include "SynTree/LinkageSpec.h"            // for Spec, Cforall, Intrinsic
    7466#include "SynTree/Declaration.h"            // for Declaration
    75 #include "SynTree/Visitor.h"                // for acceptAll
    7667#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    7768#include "Validate/Autogen.hpp"             // for autogenerateRoutines
     
    330321                Stats::Time::StopBlock();
    331322
    332                 if( useNewAST ) {
    333                         if (Stats::Counters::enabled) {
    334                                 ast::pass_visitor_stats.avg = Stats::Counters::build<Stats::Counters::AverageCounter<double>>("Average Depth - New");
    335                                 ast::pass_visitor_stats.max = Stats::Counters::build<Stats::Counters::MaxCounter<double>>("Max depth - New");
    336                         }
    337                         auto transUnit = convert( move( translationUnit ) );
    338 
    339                         forceFillCodeLocations( transUnit );
    340 
    341                         PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) );
    342                         if ( exdeclp ) {
    343                                 dump( move( transUnit ) );
    344                                 return EXIT_SUCCESS;
    345                         }
    346 
    347                         PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) );
    348                         PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) );
    349                         // Hoist Type Decls pulls some declarations out of contexts where
    350                         // locations are not tracked. Perhaps they should be, but for now
    351                         // the full fill solves it.
    352                         forceFillCodeLocations( transUnit );
    353 
    354                         PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) );
    355                         PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) );
    356                         PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) );
    357 
    358                         PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) );
    359 
    360                         PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
    361                         PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
    362                         PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
    363                         PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) );
    364                         PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) );
    365                         PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) );
    366                         PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) );
    367                         PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
    368                         PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
    369                         PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
    370 
    371                         PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
    372 
    373                         PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
    374                         PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
    375                         PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
    376                         PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
    377                         PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
    378                         PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
    379 
    380                         if ( symtabp ) {
    381                                 return EXIT_SUCCESS;
    382                         } // if
    383 
    384                         if ( expraltp ) {
    385                                 ResolvExpr::printCandidates( transUnit );
    386                                 return EXIT_SUCCESS;
    387                         } // if
    388 
    389                         if ( validp ) {
    390                                 dump( move( transUnit ) );
    391                                 return EXIT_SUCCESS;
    392                         } // if
    393 
    394                         PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
    395                         PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
    396                         PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
    397                         PASS( "Gen Init", InitTweak::genInit( transUnit ) );
    398                         PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
    399 
    400                         if ( libcfap ) {
    401                                 // Generate the bodies of cfa library functions.
    402                                 LibCfa::makeLibCfa( transUnit );
    403                         } // if
    404 
    405                         if ( declstatsp ) {
    406                                 printDeclStats( transUnit );
    407                                 return EXIT_SUCCESS;
    408                         } // if
    409 
    410                         if ( bresolvep ) {
    411                                 dump( move( transUnit ) );
    412                                 return EXIT_SUCCESS;
    413                         } // if
    414 
    415                         if ( resolvprotop ) {
    416                                 dumpAsResolverProto( transUnit );
    417                                 return EXIT_SUCCESS;
    418                         } // if
    419 
    420                         PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    421                         if ( exprp ) {
    422                                 dump( move( transUnit ) );
    423                                 return EXIT_SUCCESS;
    424                         } // if
    425 
    426                         forceFillCodeLocations( transUnit );
    427 
    428                         PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
    429 
    430                         // fix ObjectDecl - replaces ConstructorInit nodes
    431                         if ( ctorinitp ) {
    432                                 dump( move( transUnit ) );
    433                                 return EXIT_SUCCESS;
    434                         } // if
    435 
    436                         // Currently not working due to unresolved issues with UniqueExpr
    437                         PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    438 
    439                         PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) );
    440                         PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) );
    441 
    442                         // Needs to happen before tuple types are expanded.
    443                         PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
    444 
    445                         PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
    446 
    447                         translationUnit = convert( move( transUnit ) );
    448                 } else {
    449                         PASS( "Translate Exception Declarations", ControlStruct::translateExcept( translationUnit ) );
    450                         if ( exdeclp ) {
    451                                 dump( translationUnit );
    452                                 return EXIT_SUCCESS;
    453                         } // if
    454 
    455                         // add the assignment statement after the initialization of a type parameter
    456                         PASS( "Validate", SymTab::validate( translationUnit ) );
    457 
    458                         if ( symtabp ) {
    459                                 deleteAll( translationUnit );
    460                                 return EXIT_SUCCESS;
    461                         } // if
    462 
    463                         if ( expraltp ) {
    464                                 PassVisitor<ResolvExpr::AlternativePrinter> printer( cout );
    465                                 acceptAll( translationUnit, printer );
    466                                 return EXIT_SUCCESS;
    467                         } // if
    468 
    469                         if ( validp ) {
    470                                 dump( translationUnit );
    471                                 return EXIT_SUCCESS;
    472                         } // if
    473 
    474                         PASS( "Translate Throws", ControlStruct::translateThrows( translationUnit ) );
    475                         PASS( "Fix Labels", ControlStruct::fixLabels( translationUnit ) );
    476                         PASS( "Fix Names", CodeGen::fixNames( translationUnit ) );
    477                         PASS( "Gen Init", InitTweak::genInit( translationUnit ) );
    478                         PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( translationUnit ) );
    479 
    480                         if ( libcfap ) {
    481                                 // Generate the bodies of cfa library functions.
    482                                 LibCfa::makeLibCfa( translationUnit );
    483                         } // if
    484 
    485                         if ( declstatsp ) {
    486                                 CodeTools::printDeclStats( translationUnit );
    487                                 deleteAll( translationUnit );
    488                                 return EXIT_SUCCESS;
    489                         } // if
    490 
    491                         if ( bresolvep ) {
    492                                 dump( translationUnit );
    493                                 return EXIT_SUCCESS;
    494                         } // if
    495 
    496                         CodeTools::fillLocations( translationUnit );
    497 
    498                         if ( resolvprotop ) {
    499                                 CodeTools::dumpAsResolvProto( translationUnit );
    500                                 return EXIT_SUCCESS;
    501                         } // if
    502 
    503                         PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    504                         if ( exprp ) {
    505                                 dump( translationUnit );
    506                                 return EXIT_SUCCESS;
    507                         }
    508 
    509                         PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
    510 
    511                         // fix ObjectDecl - replaces ConstructorInit nodes
    512                         if ( ctorinitp ) {
    513                                 dump ( translationUnit );
    514                                 return EXIT_SUCCESS;
    515                         } // if
    516 
    517                         PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    518                         PASS( "Translate Tries", ControlStruct::translateTries( translationUnit ) );
    519                         PASS( "Gen Waitfor", Concurrency::generateWaitFor( translationUnit ) );
    520                         PASS( "Convert Specializations",  GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded
    521                         PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?
     323                if (Stats::Counters::enabled) {
     324                        ast::pass_visitor_stats.avg = Stats::Counters::build<Stats::Counters::AverageCounter<double>>("Average Depth - New");
     325                        ast::pass_visitor_stats.max = Stats::Counters::build<Stats::Counters::MaxCounter<double>>("Max depth - New");
    522326                }
     327                auto transUnit = convert( std::move( translationUnit ) );
     328
     329                forceFillCodeLocations( transUnit );
     330
     331                PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) );
     332                if ( exdeclp ) {
     333                        dump( std::move( transUnit ) );
     334                        return EXIT_SUCCESS;
     335                }
     336
     337                PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) );
     338                PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) );
     339                // Hoist Type Decls pulls some declarations out of contexts where
     340                // locations are not tracked. Perhaps they should be, but for now
     341                // the full fill solves it.
     342                forceFillCodeLocations( transUnit );
     343
     344                PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) );
     345                PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) );
     346                PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) );
     347
     348                PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) );
     349
     350                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
     351                PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
     352                PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
     353                PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) );
     354                PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) );
     355                PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) );
     356                PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) );
     357                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
     358                PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
     359                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
     360
     361                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
     362
     363                PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
     364                PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
     365                PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
     366                PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
     367                PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
     368                PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
     369
     370                if ( symtabp ) {
     371                        return EXIT_SUCCESS;
     372                } // if
     373
     374                if ( expraltp ) {
     375                        ResolvExpr::printCandidates( transUnit );
     376                        return EXIT_SUCCESS;
     377                } // if
     378
     379                if ( validp ) {
     380                        dump( std::move( transUnit ) );
     381                        return EXIT_SUCCESS;
     382                } // if
     383
     384                PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
     385                PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
     386                PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
     387                PASS( "Gen Init", InitTweak::genInit( transUnit ) );
     388                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
     389
     390                if ( libcfap ) {
     391                        // Generate the bodies of cfa library functions.
     392                        LibCfa::makeLibCfa( transUnit );
     393                } // if
     394
     395                if ( declstatsp ) {
     396                        printDeclStats( transUnit );
     397                        return EXIT_SUCCESS;
     398                } // if
     399
     400                if ( bresolvep ) {
     401                        dump( std::move( transUnit ) );
     402                        return EXIT_SUCCESS;
     403                } // if
     404
     405                if ( resolvprotop ) {
     406                        dumpAsResolverProto( transUnit );
     407                        return EXIT_SUCCESS;
     408                } // if
     409
     410                PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     411                if ( exprp ) {
     412                        dump( std::move( transUnit ) );
     413                        return EXIT_SUCCESS;
     414                } // if
     415
     416                forceFillCodeLocations( transUnit );
     417
     418                PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
     419
     420                // fix ObjectDecl - replaces ConstructorInit nodes
     421                if ( ctorinitp ) {
     422                        dump( std::move( transUnit ) );
     423                        return EXIT_SUCCESS;
     424                } // if
     425
     426                // Currently not working due to unresolved issues with UniqueExpr
     427                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     428
     429                PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) );
     430                PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) );
     431
     432                // Needs to happen before tuple types are expanded.
     433                PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
     434
     435                PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
    523436
    524437                if ( tuplep ) {
    525                         dump( translationUnit );
    526                         return EXIT_SUCCESS;
    527                 } // if
    528 
    529                 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM
    530 
    531                 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( translationUnit ) );
     438                        dump( std::move( transUnit ) );
     439                        return EXIT_SUCCESS;
     440                } // if
     441
     442                // Must come after Translate Tries.
     443                PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) );
     444
     445                PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) );
     446
     447                translationUnit = convert( std::move( transUnit ) );
     448
    532449                if ( genericsp ) {
    533450                        dump( translationUnit );
     
    612529
    613530
    614 static const char optstring[] = ":c:ghlLmNnpdOAP:S:twW:D:";
     531static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
    615532
    616533enum { PreludeDir = 128 };
     
    626543        { "prototypes", no_argument, nullptr, 'p' },
    627544        { "deterministic-out", no_argument, nullptr, 'd' },
    628         { "old-ast", no_argument, nullptr, 'O'},
    629         { "new-ast", no_argument, nullptr, 'A'},
    630545        { "print", required_argument, nullptr, 'P' },
    631546        { "prelude-dir", required_argument, nullptr, PreludeDir },
     
    649564        "do not generate prelude prototypes => prelude not printed", // -p
    650565        "only print deterministic output",                  // -d
    651         "Use the old-ast",                                                                      // -O
    652         "Use the new-ast",                                                                      // -A
    653566        "print",                                                                                        // -P
    654567        "<directory> prelude directory for debug/nodebug",      // no flag
     
    759672                        deterministic_output = true;
    760673                        break;
    761                   case 'O':                                     // don't print non-deterministic output
    762                         useNewAST = false;
    763                         break;
    764                   case 'A':                                     // don't print non-deterministic output
    765                         useNewAST = true;
    766                         break;
    767674                  case 'P':                                                                             // print options
    768675                        for ( int i = 0;; i += 1 ) {
     
    881788
    882789static void dump( ast::TranslationUnit && transUnit, ostream & out ) {
    883         std::list< Declaration * > translationUnit = convert( move( transUnit ) );
     790        std::list< Declaration * > translationUnit = convert( std::move( transUnit ) );
    884791        dump( translationUnit, out );
    885792}
Note: See TracChangeset for help on using the changeset viewer.