Changeset 63be3387 for src


Ignore:
Timestamp:
Nov 14, 2022, 11:52:44 AM (3 years ago)
Author:
caparson <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
7d9598d8
Parents:
b77f0e1 (diff), 19a8c40 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
src
Files:
1 added
39 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    rb77f0e1 r63be3387  
    234234                }
    235235                return declWithTypePostamble( decl, node );
     236        }
     237
     238        // InlineMemberDecl vanish after EnumAndPointerDecay pass so no necessary to implement NewToOld
     239        const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final { 
     240                assert( false );
     241                (void) node;
     242                return nullptr;
    236243        }
    237244
     
    16141621                        { old->get_funcSpec().val }
    16151622                );
    1616                 decl->enumInLine = old->enumInLine;
    16171623                cache.emplace(old, decl);
    16181624                assert(cache.find( old ) != cache.end());
     
    18591865                decl->uniqueId   = old->uniqueId;
    18601866                decl->storage    = { old->storageClasses.val };
     1867
     1868                this->node = decl;
     1869        }
     1870
     1871        virtual void visit( const InlineMemberDecl * old ) override final {
     1872                if ( inCache( old ) ) {
     1873                        return;
     1874                }
     1875                auto&& type = GET_ACCEPT_1(type, Type);
     1876                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
     1877
     1878                auto decl = new ast::InlineMemberDecl(
     1879                        old->location,
     1880                        old->name,
     1881                        type,
     1882                        { old->get_storageClasses().val },
     1883                        { old->linkage.val },
     1884                        std::move(attr),
     1885                        { old->get_funcSpec().val }
     1886                );
     1887                cache.emplace(old, decl);
     1888                assert(cache.find( old ) != cache.end());
     1889                decl->scopeLevel = old->scopeLevel;
     1890                decl->mangleName = old->mangleName;
     1891                decl->isDeleted  = old->isDeleted;
     1892                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
     1893                decl->uniqueId   = old->uniqueId;
     1894                decl->extension  = old->extension;
    18611895
    18621896                this->node = decl;
  • src/AST/Decl.hpp

    rb77f0e1 r63be3387  
    105105        ptr<Init> init;
    106106        ptr<Expr> bitfieldWidth;
    107         bool enumInLine = false; // enum inline is not a real object declaration.
    108         // It is a place holder for a set of enum value (ObjectDecl)
    109         bool importValue = false; // if the value copied from somewhere else
    110107
    111108        ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
     
    400397};
    401398
     399/// Static Assertion `_Static_assert( ... , ... );`
    402400class StaticAssertDecl : public Decl {
    403401public:
     
    411409private:
    412410        StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
     411        MUTATE_FRIEND
     412};
     413
     414/// Inline Member Declaration `inline TypeName;`
     415class InlineMemberDecl final : public DeclWithType {
     416public:
     417        ptr<Type> type;
     418
     419        InlineMemberDecl( const CodeLocation & loc, const std::string & name, const Type * type,
     420                Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
     421                std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
     422        : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ) {}
     423
     424        const Type * get_type() const override { return type; }
     425        void set_type( const Type * ty ) override { type = ty; }
     426
     427        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     428private:
     429        InlineMemberDecl * clone() const override { return new InlineMemberDecl{ *this }; }
    413430        MUTATE_FRIEND
    414431};
  • src/AST/Fwd.hpp

    rb77f0e1 r63be3387  
    3737class DirectiveDecl;
    3838class StaticAssertDecl;
     39class InlineMemberDecl;
    3940
    4041class Stmt;
  • src/AST/Pass.hpp

    rb77f0e1 r63be3387  
    141141        const ast::DirectiveDecl *    visit( const ast::DirectiveDecl        * ) override final;
    142142        const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) override final;
     143        const ast::DeclWithType *     visit( const ast::InlineMemberDecl     * ) override final;
    143144        const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) override final;
    144145        const ast::Stmt *             visit( const ast::ExprStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    rb77f0e1 r63be3387  
    617617                                maybe_accept( node, &FunctionDecl::returns );
    618618                                maybe_accept( node, &FunctionDecl::type );
     619                                maybe_accept( node, &FunctionDecl::attributes );
    619620                                // First remember that we are now within a function.
    620621                                ValueGuard< bool > oldInFunction( inFunction );
     
    625626                                atFunctionTop = true;
    626627                                maybe_accept( node, &FunctionDecl::stmts );
    627                                 maybe_accept( node, &FunctionDecl::attributes );
    628628                        }
    629629                }
     
    800800
    801801        VISIT_END( StaticAssertDecl, node );
     802}
     803
     804//--------------------------------------------------------------------------
     805// InlineMemberDecl
     806template< typename core_t >
     807const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::InlineMemberDecl * node ) {
     808        VISIT_START( node );
     809
     810        if ( __visit_children() ) {
     811                {
     812                        guard_symtab guard { *this };
     813                        maybe_accept( node, &InlineMemberDecl::type );
     814                }
     815        }
     816
     817        VISIT_END( DeclWithType, node );
    802818}
    803819
  • src/AST/Print.cpp

    rb77f0e1 r63be3387  
    398398        virtual const ast::Decl * visit( const ast::StructDecl * node ) override final {
    399399                print(node);
     400                return node;
     401        }
     402
     403        virtual const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final {
     404                os << "inline ";
     405                if ( ! node->name.empty() ) os << node->name;
     406
    400407                return node;
    401408        }
  • src/AST/Type.cpp

    rb77f0e1 r63be3387  
    147147// --- TypeInstType
    148148
     149bool TypeInstType::operator==( const TypeInstType & other ) const {
     150        return base == other.base
     151                && formal_usage == other.formal_usage
     152                && expr_id == other.expr_id;
     153}
     154
    149155TypeInstType::TypeInstType( const TypeDecl * b,
    150156        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
     
    157163
    158164bool TypeInstType::isComplete() const { return base->sized; }
     165
     166std::string TypeInstType::TypeEnvKey::typeString() const {
     167        return std::string("_") + std::to_string(formal_usage)
     168                + "_" + std::to_string(expr_id) + "_" + base->name;
     169}
     170
     171bool TypeInstType::TypeEnvKey::operator==(
     172                const TypeInstType::TypeEnvKey & other ) const {
     173        return base == other.base
     174                && formal_usage == other.formal_usage
     175                && expr_id == other.expr_id;
     176}
     177
     178bool TypeInstType::TypeEnvKey::operator<(
     179                const TypeInstType::TypeEnvKey & other ) const {
     180        // TypeEnvKey ordering is an arbitrary total ordering.
     181        // It doesn't mean anything but allows for a sorting.
     182        if ( base < other.base ) {
     183                return true;
     184        } else if ( other.base < base ) {
     185                return false;
     186        } else if ( formal_usage < other.formal_usage ) {
     187                return true;
     188        } else if ( other.formal_usage < formal_usage ) {
     189                return false;
     190        } else {
     191                return expr_id < other.expr_id;
     192        }
     193}
    159194
    160195// --- TupleType
  • src/AST/Type.hpp

    rb77f0e1 r63be3387  
    408408
    409409                TypeEnvKey() = default;
    410                 TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0): base(base), formal_usage(formal_usage), expr_id(expr_id) {}
    411                 TypeEnvKey(const TypeInstType & inst): base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
    412                 std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; }
    413                 bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     410                TypeEnvKey(const TypeDecl * base, int formal_usage = 0, int expr_id = 0)
     411                : base(base), formal_usage(formal_usage), expr_id(expr_id) {}
     412                TypeEnvKey(const TypeInstType & inst)
     413                : base(inst.base), formal_usage(inst.formal_usage), expr_id(inst.expr_id) {}
     414                std::string typeString() const;
     415                bool operator==(const TypeEnvKey & other) const;
     416                bool operator<(const TypeEnvKey & other) const;
    414417        };
    415418
    416         bool operator==(const TypeInstType & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; }
     419        bool operator==(const TypeInstType & other) const;
    417420
    418421        TypeInstType(
  • src/AST/Visitor.hpp

    rb77f0e1 r63be3387  
    3333    virtual const ast::DirectiveDecl *    visit( const ast::DirectiveDecl        * ) = 0;
    3434    virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * ) = 0;
     35    virtual const ast::DeclWithType *     visit( const ast::InlineMemberDecl     * ) = 0;
    3536    virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * ) = 0;
    3637    virtual const ast::Stmt *             visit( const ast::ExprStmt             * ) = 0;
  • src/Common/CodeLocationTools.cpp

    rb77f0e1 r63be3387  
    111111    macro(DirectiveDecl, DirectiveDecl) \
    112112    macro(StaticAssertDecl, StaticAssertDecl) \
     113    macro(InlineMemberDecl, DeclWithType) \
    113114    macro(CompoundStmt, CompoundStmt) \
    114115    macro(ExprStmt, Stmt) \
  • src/Common/PassVisitor.h

    rb77f0e1 r63be3387  
    8181        virtual void visit( StaticAssertDecl * assertDecl ) override final;
    8282        virtual void visit( const StaticAssertDecl * assertDecl ) override final;
     83        virtual void visit( InlineMemberDecl * valueDecl ) override final;
     84        virtual void visit( const InlineMemberDecl * valueDecl ) override final;
    8385
    8486        virtual void visit( CompoundStmt * compoundStmt ) override final;
     
    273275        virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) override final;
    274276        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) override final;
     277        virtual DeclarationWithType * mutate( InlineMemberDecl * valueDecl ) override final;
    275278
    276279        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override final;
  • src/Common/PassVisitor.impl.h

    rb77f0e1 r63be3387  
    607607                        indexerAddId( &func );
    608608                        maybeMutate_impl( node->type, *this );
     609                        maybeMutate_impl( node->attributes, *this );
    609610                        // First remember that we are now within a function.
    610611                        ValueGuard< bool > oldInFunction( inFunction );
     
    615616                        atFunctionTop = true;
    616617                        maybeMutate_impl( node->statements, *this );
    617                         maybeMutate_impl( node->attributes, *this );
    618618                }
    619619        }
     
    10441044
    10451045        MUTATE_END( StaticAssertDecl, node );
     1046}
     1047
     1048//--------------------------------------------------------------------------
     1049// InlineMemberDecl
     1050template< typename pass_type >
     1051void PassVisitor< pass_type >::visit( InlineMemberDecl * node ) {
     1052        VISIT_START( node );
     1053
     1054        maybeAccept_impl( node->type, *this );
     1055
     1056        VISIT_END( node );
     1057}
     1058
     1059template< typename pass_type >
     1060void PassVisitor< pass_type >::visit( const InlineMemberDecl * node ) {
     1061        VISIT_START( node );
     1062
     1063        maybeAccept_impl( node->type, *this );
     1064
     1065        VISIT_END( node );
     1066}
     1067
     1068template< typename pass_type >
     1069DeclarationWithType * PassVisitor< pass_type >::mutate( InlineMemberDecl * node ) {
     1070        MUTATE_START( node );
     1071
     1072        maybeMutate_impl( node->type, *this );
     1073
     1074        MUTATE_END( DeclarationWithType, node );
    10461075}
    10471076
  • src/Common/utility.h

    rb77f0e1 r63be3387  
    452452
    453453// -----------------------------------------------------------------------------
    454 // Helper struct and function to support
    455 // for ( val : group_iterate( container1, container2, ... ) ) {}
    456 // syntax to have a for each that iterates multiple containers of the same length
    457 // TODO: update to use variadic arguments
    458 
    459 template< typename T1, typename T2 >
    460 struct group_iterate_t {
    461 private:
    462         std::tuple<T1, T2> args;
     454// Helper struct and function to support:
     455// for ( auto val : group_iterate( container1, container2, ... ) ) { ... }
     456// This iteraters through multiple containers of the same size.
     457
     458template<typename... Args>
     459class group_iterate_t {
     460        using Iterables = std::tuple<Args...>;
     461        Iterables iterables;
     462
     463        // Getting the iterator and value types this way preserves const.
     464        template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
     465        template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
     466        template<typename> struct base_iterator;
     467
     468        // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`
     469        // into a pack. These are the indexes into the tuples, so unpacking can
     470        // go over each element of the tuple.
     471        // The std::integer_sequence is just used to build that sequence.
     472        // A library reference will probably explain it better than I can.
     473        template<std::size_t... Indices>
     474        struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {
     475                using value_type = std::tuple< Data<Indices>... >;
     476                std::tuple<Iter<Indices>...> iterators;
     477
     478                base_iterator( Iter<Indices>... is ) : iterators( is... ) {}
     479                base_iterator operator++() {
     480                        return base_iterator( ++std::get<Indices>( iterators )... );
     481                }
     482                bool operator!=( const base_iterator& other ) const {
     483                        return iterators != other.iterators;
     484                }
     485                value_type operator*() const {
     486                        return std::tie( *std::get<Indices>( iterators )... );
     487                }
     488
     489                static base_iterator make_begin( Iterables & data ) {
     490                        return base_iterator( std::get<Indices>( data ).begin()... );
     491                }
     492                static base_iterator make_end( Iterables & data ) {
     493                        return base_iterator( std::get<Indices>( data ).end()... );
     494                }
     495        };
     496
    463497public:
    464         group_iterate_t( bool skipBoundsCheck, const T1 & v1, const T2 & v2 ) : args(v1, v2) {
    465                 assertf(skipBoundsCheck || v1.size() == v2.size(), "group iteration requires containers of the same size: <%zd, %zd>.", v1.size(), v2.size());
    466         };
    467 
    468         typedef std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin())> value_type;
    469         typedef decltype(std::get<0>(args).begin()) T1Iter;
    470         typedef decltype(std::get<1>(args).begin()) T2Iter;
    471 
    472         struct iterator {
    473                 typedef std::tuple<T1Iter, T2Iter> IterTuple;
    474                 IterTuple it;
    475                 iterator( T1Iter i1, T2Iter i2 ) : it( i1, i2 ) {}
    476                 iterator operator++() {
    477                         return iterator( ++std::get<0>(it), ++std::get<1>(it) );
    478                 }
    479                 bool operator!=( const iterator &other ) const { return it != other.it; }
    480                 value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it) ); }
    481         };
    482 
    483         iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); }
    484         iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); }
    485 };
    486 
    487 /// performs bounds check to ensure that all arguments are of the same length.
     498        group_iterate_t( const Args &... args ) : iterables( args... ) {}
     499
     500        using iterator = base_iterator<decltype(
     501                std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;
     502
     503        iterator begin() { return iterator::make_begin( iterables ); }
     504        iterator end() { return iterator::make_end( iterables ); }
     505};
     506
     507// Helpers for the bounds checks (the non-varatic part of group_iterate):
     508static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
     509        assertf( size0 == size1,
     510                "group iteration requires containers of the same size: <%zd, %zd>.",
     511                size0, size1 );
     512}
     513
     514static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {
     515        assertf( size0 == size1 && size1 == size2,
     516                "group iteration requires containers of the same size: <%zd, %zd, %zd>.",
     517                size0, size1, size2 );
     518}
     519
     520/// Performs bounds check to ensure that all arguments are of the same length.
    488521template< typename... Args >
    489522group_iterate_t<Args...> group_iterate( Args &&... args ) {
    490         return group_iterate_t<Args...>(false, std::forward<Args>( args )...);
    491 }
    492 
    493 /// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
     523        runGroupBoundsCheck( args.size()... );
     524        return group_iterate_t<Args...>( std::forward<Args>( args )... );
     525}
     526
     527/// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
    494528template< typename... Args >
    495529group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
    496         return group_iterate_t<Args...>(true, std::forward<Args>( args )...);
     530        return group_iterate_t<Args...>( std::forward<Args>( args )... );
    497531}
    498532
  • src/GenPoly/Box.cc

    rb77f0e1 r63be3387  
    5858namespace GenPoly {
    5959        namespace {
    60                 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
     60                FunctionType *makeAdapterType( FunctionType const *adaptee, const TyVarMap &tyVars );
    6161
    6262                class BoxPass {
     
    6868                /// Adds layout-generation functions to polymorphic types.
    6969                class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting {
    70                         // Current level of nested functions:
    71                         unsigned int functionNesting = 0;
    7270                public:
    73                         void previsit( FunctionDecl *functionDecl );
    7471                        void previsit( StructDecl *structDecl );
    7572                        void previsit( UnionDecl *unionDecl );
     
    10097                        void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
    10198                        /// passes extra type parameters into a polymorphic function application
    102                         void passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
     99                        /// Returns an iterator to the first argument after the added
     100                        /// arguments, which are added at the beginning.
     101                        std::list< Expression *>::iterator passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars );
    103102                        /// wraps a function application with a new temporary for the out-parameter return value
    104                         Expression *addRetParam( ApplicationExpr *appExpr, Type *retType, std::list< Expression *>::iterator &arg );
    105                         /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
    106                         void replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params );
    107                         /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
    108                         /// If `doClone` is set to false, will not clone interior types
    109                         Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
     103                        /// The new out-parameter is the new first parameter.
     104                        Expression *addRetParam( ApplicationExpr *appExpr, Type *retType );
    110105                        /// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
    111                         Expression *addDynRetParam( ApplicationExpr *appExpr, Type *polyType, std::list< Expression *>::iterator &arg );
    112                         Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    113                         void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
    114                         void boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
    115                         void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars );
     106                        Expression *addDynRetParam( ApplicationExpr *appExpr, Type *polyType );
     107                        /// Converts a function call into a call of the adapter with the
     108                        /// original function as the first argument (all other arguments
     109                        /// are pushed back). May adjust return value.
     110                        Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function );
     111                        /// Modifies the `arg`, replacing it with a boxed expression
     112                        /// that matches `formal` under the current TyVarMap.
     113                        void boxParam( Expression *&arg, Type *formal, const TyVarMap &exprTyVars );
     114                        /// Box an argument of `appExpr` for each parameter in `function`
     115                        /// starting at `arg`.
     116                        /// `exprTyVars` is the function's type variables.
     117                        void boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars );
     118                        /// Boxes each assertion and inserts them into `appExpr` at
     119                        /// `arg`. `exprTyVars` is the function's type variables.
     120                        void addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars );
    116121                        /// Stores assignment operators from assertion list in local map of assignment operations
    117122                        void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars );
    118                         FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
     123                        /// Creates an adapter definition from `adaptee` to `realType`, using
     124                        /// `mangleName` as the base name for the adapter. `tyVars` is the map of
     125                        /// type variables for the function type of the adapted expression.
     126                        FunctionDecl *makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars );
    119127                        /// Replaces intrinsic operator functions with their arithmetic desugaring
    120128                        Expression *handleIntrinsics( ApplicationExpr *appExpr );
     
    182190                        ObjectDecl *makeVar( const std::string &name, Type *type, Initializer *init = 0 );
    183191                        /// returns true if the type has a dynamic layout; such a layout will be stored in appropriately-named local variables when the function returns
    184                         bool findGeneric( Type *ty );
     192                        bool findGeneric( Type const *ty );
    185193                        /// adds type parameters to the layout call; will generate the appropriate parameters if needed
    186194                        void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
     
    221229        } // anonymous namespace
    222230
    223         /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
    224         template< typename MutatorType >
    225         inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
    226                 bool seenIntrinsic = false;
    227                 SemanticErrorException errors;
    228                 for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    229                         try {
    230                                 if ( *i ) {
    231                                         if ( (*i)->get_linkage() == LinkageSpec::Intrinsic ) {
    232                                                 seenIntrinsic = true;
    233                                         } else if ( seenIntrinsic ) {
    234                                                 seenIntrinsic = false; // break on this line when debugging for end of prelude
    235                                         }
    236 
    237                                         *i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
    238                                         assert( *i );
    239                                 } // if
    240                         } catch( SemanticErrorException &e ) {
    241                                 errors.append( e );
    242                         } // try
    243                 } // for
    244                 if ( ! errors.isEmpty() ) {
    245                         throw errors;
    246                 } // if
    247         }
    248 
    249231        void box( std::list< Declaration *>& translationUnit ) {
    250232                PassVisitor<LayoutFunctionBuilder> layoutBuilder;
     
    263245        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
    264246
    265         void LayoutFunctionBuilder::previsit( FunctionDecl *functionDecl ) {
    266                 visit_children = false;
    267                 maybeAccept( functionDecl->get_functionType(), *visitor );
    268                 ++functionNesting;
    269                 maybeAccept( functionDecl->get_statements(), *visitor );
    270                 --functionNesting;
    271         }
    272 
    273247        /// Get a list of type declarations that will affect a layout function
    274248        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
    275249                std::list< TypeDecl * > otypeDecls;
    276250
    277                 for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
    278                         if ( (*decl)->isComplete() ) {
    279                                 otypeDecls.push_back( *decl );
     251                for ( TypeDecl * const decl : decls ) {
     252                        if ( decl->isComplete() ) {
     253                                otypeDecls.push_back( decl );
    280254                        }
    281255                }
     
    288262                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    289263
    290                 for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
    291                         TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
     264                for ( TypeDecl * const param : otypeParams ) {
     265                        TypeInstType paramType( Type::Qualifiers(), param->get_name(), param );
    292266                        std::string paramName = mangleType( &paramType );
    293267                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( paramName ), Type::StorageClasses(), LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     
    297271
    298272        /// Builds a layout function declaration
    299         FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, unsigned int functionNesting, FunctionType *layoutFnType ) {
     273        FunctionDecl *buildLayoutFunctionDecl( AggregateDecl *typeDecl, bool isInFunction, FunctionType *layoutFnType ) {
    300274                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    301275                // because each unit generates copies of the default routines for each aggregate.
    302276                FunctionDecl *layoutDecl = new FunctionDecl( layoutofName( typeDecl ),
    303                                                                                                          functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static ),
     277                                                                                                         isInFunction ? Type::StorageClasses() : Type::StorageClasses( Type::Static ),
    304278                                                                                                         LinkageSpec::AutoGen, layoutFnType, new CompoundStmt(),
    305279                                                                                                         std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
    306280                layoutDecl->fixUniqueId();
    307281                return layoutDecl;
    308         }
    309 
    310         /// Makes a unary operation
    311         Expression *makeOp( const std::string &name, Expression *arg ) {
    312                 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
    313                 expr->args.push_back( arg );
    314                 return expr;
    315282        }
    316283
     
    380347
    381348                // build function decl
    382                 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, functionNesting, layoutFnType );
     349                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl, isInFunction(), layoutFnType );
    383350
    384351                // calculate struct layout in function body
     
    387354                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant::from_ulong( 0 ) ) ) );
    388355                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
    389                 unsigned long n_members = 0;
    390                 bool firstMember = true;
    391                 for ( Declaration* member : structDecl->get_members() ) {
    392                         DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( member );
     356                for ( auto index_member : enumerate( structDecl->members ) ) {
     357                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( index_member.val );
    393358                        assert( dwt );
    394359                        Type *memberType = dwt->get_type();
    395360
    396                         if ( firstMember ) {
    397                                 firstMember = false;
    398                         } else {
     361                        if ( 0 < index_member.idx ) {
    399362                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
    400363                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
     
    402365
    403366                        // place current size in the current offset index
    404                         addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ),
     367                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( index_member.idx ) ) ),
    405368                                                                              derefVar( sizeParam ) ) );
    406                         ++n_members;
    407369
    408370                        // add member size to current size
     
    439401
    440402                // build function decl
    441                 FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, functionNesting, layoutFnType );
     403                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl, isInFunction(), layoutFnType );
    442404
    443405                // calculate union layout in function body
    444406                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
    445407                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
    446                 for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
    447                         DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     408                for ( Declaration * const member : unionDecl->members ) {
     409                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( member );
    448410                        assert( dwt );
    449411                        Type *memberType = dwt->get_type();
     
    464426
    465427        namespace {
    466                 std::string makePolyMonoSuffix( FunctionType * function, const TyVarMap &tyVars ) {
     428                std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) {
    467429                        std::stringstream name;
    468430
     
    473435                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
    474436                        // with the same mangled name, so we need to further mangle the names.
    475                         for ( std::list< DeclarationWithType *>::iterator retval = function->get_returnVals().begin(); retval != function->get_returnVals().end(); ++retval ) {
    476                                 if ( isPolyType( (*retval)->get_type(), tyVars ) ) {
     437                        for ( DeclarationWithType const * const ret : function->returnVals ) {
     438                                if ( isPolyType( ret->get_type(), tyVars ) ) {
    477439                                        name << "P";
    478440                                } else {
     
    481443                        }
    482444                        name << "_";
    483                         std::list< DeclarationWithType *> &paramList = function->get_parameters();
    484                         for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
    485                                 if ( isPolyType( (*arg)->get_type(), tyVars ) ) {
     445                        for ( DeclarationWithType const * const arg : function->parameters ) {
     446                                if ( isPolyType( arg->get_type(), tyVars ) ) {
    486447                                        name << "P";
    487448                                } else {
     
    492453                }
    493454
    494                 std::string mangleAdapterName( FunctionType * function, const TyVarMap &tyVars ) {
     455                std::string mangleAdapterName( FunctionType const * function, const TyVarMap &tyVars ) {
    495456                        return SymTab::Mangler::mangle( function ) + makePolyMonoSuffix( function, tyVars );
    496457                }
     
    499460                        return "_adapter" + mangleName;
    500461                }
     462
     463                /// Replaces a polymorphic type with its concrete equivalant under the current environment (returns itself if concrete).
     464                /// If `doClone` is set to false, will not clone interior types
     465                Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true );
    501466
    502467                Pass1::Pass1() : tempNamer( "_temp" ) {}
     
    524489
    525490                                std::list< DeclarationWithType *> &paramList = functionType->parameters;
    526                                 std::list< FunctionType *> functions;
    527                                 for ( Type::ForallList::iterator tyVar = functionType->forall.begin(); tyVar != functionType->forall.end(); ++tyVar ) {
    528                                         for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
    529                                                 findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
     491                                std::list< FunctionType const *> functions;
     492                                for ( TypeDecl * const tyVar : functionType->forall ) {
     493                                        for ( DeclarationWithType * const assert : tyVar->assertions ) {
     494                                                findFunction( assert->get_type(), functions, scopeTyVars, needsAdapter );
    530495                                        } // for
    531496                                } // for
    532                                 for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
    533                                         findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
     497                                for ( DeclarationWithType * const arg : paramList ) {
     498                                        findFunction( arg->get_type(), functions, scopeTyVars, needsAdapter );
    534499                                } // for
    535500
    536                                 for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    537                                         std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     501                                for ( FunctionType const * const funType : functions ) {
     502                                        std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    538503                                        if ( adapters.find( mangleName ) == adapters.end() ) {
    539504                                                std::string adapterName = makeAdapterName( mangleName );
    540                                                 adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), nullptr ) ) );
     505                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
    541506                                        } // if
    542507                                } // for
     
    593558                }
    594559
    595                 void Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
     560                std::list< Expression *>::iterator Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
     561                        assert( env );
     562                        std::list< Expression *>::iterator arg = appExpr->args.begin();
    596563                        // pass size/align for type variables
    597                         for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
     564                        for ( std::pair<std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
    598565                                ResolvExpr::EqvClass eqvClass;
    599                                 assert( env );
    600                                 if ( tyParm->second.isComplete ) {
    601                                         Type *concrete = env->lookup( tyParm->first );
    602                                         if ( concrete ) {
    603                                                 arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
    604                                                 arg++;
    605                                                 arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
    606                                                 arg++;
    607                                         } else {
    608                                                 // xxx - should this be an assertion?
    609                                                 SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
    610                                         } // if
     566                                if ( tyParam.second.isComplete ) {
     567                                        Type *concrete = env->lookup( tyParam.first );
     568                                        // If there is an unbound type variable, it should have detected already.
     569                                        assertf( concrete, "Unbound type variable: %s in: %s",
     570                                                toCString( tyParam.first ), toCString( *env ) );
     571
     572                                        arg = appExpr->get_args().insert( arg, new SizeofExpr( concrete->clone() ) );
     573                                        arg++;
     574                                        arg = appExpr->get_args().insert( arg, new AlignofExpr( concrete->clone() ) );
     575                                        arg++;
    611576                                } // if
    612577                        } // for
    613578
    614579                        // add size/align for generic types to parameter list
    615                         if ( ! appExpr->get_function()->result ) return;
     580                        if ( ! appExpr->get_function()->result ) return arg;
    616581                        FunctionType *funcType = getFunctionType( appExpr->get_function()->get_result() );
    617582                        assert( funcType );
    618583
     584                        // These iterators don't advance in unison.
    619585                        std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin();
    620586                        std::list< Expression* >::const_iterator fnArg = arg;
     
    623589                        // a polymorphic return type may need to be added to the argument list
    624590                        if ( polyRetType ) {
    625                                 Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
     591                                Type *concRetType = replaceWithConcrete( polyRetType, env );
    626592                                passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
    627593                                ++fnArg; // skip the return parameter in the argument list
     
    634600                                passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes );
    635601                        }
     602                        return arg;
    636603                }
    637604
     
    642609                }
    643610
    644                 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType, std::list< Expression *>::iterator &arg ) {
     611                Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
    645612                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
    646613                        // using a comma expression.
     
    662629                                paramExpr = new AddressExpr( paramExpr );
    663630                        } // if
    664                         arg = appExpr->args.insert( arg, paramExpr ); // add argument to function call
    665                         arg++;
     631                        // Add argument to function call.
     632                        appExpr->args.push_front( paramExpr );
    666633                        // Build a comma expression to call the function and emulate a normal return.
    667634                        CommaExpr *commaExpr = new CommaExpr( appExpr, retExpr );
     
    671638                }
    672639
    673                 void Pass1::replaceParametersWithConcrete( ApplicationExpr *appExpr, std::list< Expression* >& params ) {
    674                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    675                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     640                /// Replaces all the type parameters of a generic type with their concrete equivalents under the current environment
     641                void replaceParametersWithConcrete( std::list< Expression* >& params, TypeSubstitution const * env ) {
     642                        for ( Expression * const param : params ) {
     643                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( param );
    676644                                assertf(paramType, "Aggregate parameters should be type expressions");
    677                                 paramType->set_type( replaceWithConcrete( appExpr, paramType->get_type(), false ) );
    678                         }
    679                 }
    680 
    681                 Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
     645                                paramType->set_type( replaceWithConcrete( paramType->get_type(), env, false ) );
     646                        }
     647                }
     648
     649                // See forward definition.
     650                Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone ) {
     651                        assert( env );
    682652                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    683653                                Type *concrete = env->lookup( typeInst->get_name() );
     
    690660                                        structType = structType->clone();
    691661                                }
    692                                 replaceParametersWithConcrete( appExpr, structType->get_parameters() );
     662                                replaceParametersWithConcrete( structType->get_parameters(), env );
    693663                                return structType;
    694664                        } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
     
    696666                                        unionType = unionType->clone();
    697667                                }
    698                                 replaceParametersWithConcrete( appExpr, unionType->get_parameters() );
     668                                replaceParametersWithConcrete( unionType->get_parameters(), env );
    699669                                return unionType;
    700670                        }
     
    702672                }
    703673
    704                 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType, std::list< Expression *>::iterator &arg ) {
    705                         assert( env );
    706                         Type *concrete = replaceWithConcrete( appExpr, dynType );
     674                Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
     675                        Type *concrete = replaceWithConcrete( dynType, env );
    707676                        // add out-parameter for return value
    708                         return addRetParam( appExpr, concrete, arg );
    709                 }
    710 
    711                 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
     677                        return addRetParam( appExpr, concrete );
     678                }
     679
     680                Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
    712681                        Expression *ret = appExpr;
    713682//                      if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
    714                         if ( isDynRet( function, tyVars ) ) {
    715                                 ret = addRetParam( appExpr, function->returnVals.front()->get_type(), arg );
     683                        if ( isDynRet( function, scopeTyVars ) ) {
     684                                ret = addRetParam( appExpr, function->returnVals.front()->get_type() );
    716685                        } // if
    717                         std::string mangleName = mangleAdapterName( function, tyVars );
     686                        std::string mangleName = mangleAdapterName( function, scopeTyVars );
    718687                        std::string adapterName = makeAdapterName( mangleName );
    719688
     
    724693
    725694                        return ret;
    726                 }
    727 
    728                 void Pass1::boxParam( Type *param, Expression *&arg, const TyVarMap &exprTyVars ) {
    729                         assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
    730                         if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
    731 
    732                         if ( arg->get_lvalue() ) {
    733                                 // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
    734                                 // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
    735                                 //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
    736                                 //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
    737                                 //              return;
    738                                 //      }
    739                                 // }
    740                                 arg =  generalizedLvalue( new AddressExpr( arg ) );
    741                                 if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
    742                                         // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
    743                                         arg = new CastExpr( arg, param->clone() );
    744                                 }
    745                         } else {
    746                                 // use type computed in unification to declare boxed variables
    747                                 Type * newType = param->clone();
    748                                 if ( env ) env->apply( newType );
    749                                 ObjectDecl *newObj = ObjectDecl::newObject( tempNamer.newName(), newType, nullptr );
    750                                 newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
    751                                 stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
    752                                 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
    753                                 assign->get_args().push_back( new VariableExpr( newObj ) );
    754                                 assign->get_args().push_back( arg );
    755                                 stmtsToAddBefore.push_back( new ExprStmt( assign ) );
    756                                 arg = new AddressExpr( new VariableExpr( newObj ) );
    757                         } // if
    758695                }
    759696
     
    791728                }
    792729
    793                 void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
    794                         for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->parameters.end(); ++param, ++arg ) {
    795                                 assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( *param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
    796                                 addCast( *arg, (*param)->get_type(), exprTyVars );
    797                                 boxParam( (*param)->get_type(), *arg, exprTyVars );
     730                void Pass1::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
     731                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
     732                        addCast( arg, param, exprTyVars );
     733                        if ( ! needsBoxing( param, arg->result, exprTyVars, env ) ) return;
     734
     735                        if ( arg->get_lvalue() ) {
     736                                // argument expression may be CFA lvalue, but not C lvalue -- apply generalizedLvalue transformations.
     737                                // if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( arg ) ) {
     738                                //      if ( dynamic_cast<ArrayType *>( varExpr->var->get_type() ) ){
     739                                //              // temporary hack - don't box arrays, because &arr is not the same as &arr[0]
     740                                //              return;
     741                                //      }
     742                                // }
     743                                arg = generalizedLvalue( new AddressExpr( arg ) );
     744                                if ( ! ResolvExpr::typesCompatible( param, arg->get_result(), SymTab::Indexer() ) ) {
     745                                        // silence warnings by casting boxed parameters when the actual type does not match up with the formal type.
     746                                        arg = new CastExpr( arg, param->clone() );
     747                                }
     748                        } else {
     749                                // use type computed in unification to declare boxed variables
     750                                Type * newType = param->clone();
     751                                if ( env ) env->apply( newType );
     752                                ObjectDecl *newObj = makeTemporary( newType );
     753                                // TODO: is this right??? (Why wouldn't it be?)
     754                                newObj->get_type()->get_qualifiers() = Type::Qualifiers();
     755                                // TODO: why doesn't this just use initialization syntax?
     756                                // (Possibly to ensure code is run at the right time.)
     757                                UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
     758                                assign->get_args().push_back( new VariableExpr( newObj ) );
     759                                assign->get_args().push_back( arg );
     760                                stmtsToAddBefore.push_back( new ExprStmt( assign ) );
     761                                arg = new AddressExpr( new VariableExpr( newObj ) );
     762                        } // if
     763                }
     764
     765                void Pass1::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
     766                        for ( DeclarationWithType * param : function->parameters ) {
     767                                assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
     768                                boxParam( *arg, param->get_type(), exprTyVars );
     769                                ++arg;
    798770                        } // for
    799771                }
    800772
    801                 void Pass1::addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
     773                void Pass1::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
    802774                        std::list< Expression *>::iterator cur = arg;
    803                         for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    804                                 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
    805                                         InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() );
    806                                         assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
     775                        for ( TypeDecl * const tyVar : functionType->forall ) {
     776                                for ( DeclarationWithType * const assert : tyVar->assertions ) {
     777                                        InferredParams::const_iterator inferParam = appExpr->inferParams.find( assert->get_uniqueId() );
     778                                        assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( assert ).c_str(), toString( appExpr ).c_str() );
    807779                                        Expression *newExpr = inferParam->second.expr->clone();
    808                                         addCast( newExpr, (*assert)->get_type(), tyVars );
    809                                         boxParam( (*assert)->get_type(), newExpr, tyVars );
     780                                        boxParam( newExpr, assert->get_type(), tyVars );
    810781                                        appExpr->get_args().insert( cur, newExpr );
    811782                                } // for
     
    824795                }
    825796
    826                 FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars ) {
     797                FunctionType *makeAdapterType( FunctionType const *adaptee, const TyVarMap &tyVars ) {
    827798                        // actually make the adapter type
    828799                        FunctionType *adapter = adaptee->clone();
     
    834805                }
    835806
    836                 Expression *makeAdapterArg( DeclarationWithType *param, DeclarationWithType *arg, DeclarationWithType *realParam, const TyVarMap &tyVars ) {
     807                Expression *makeAdapterArg(
     808                                DeclarationWithType *param,
     809                                DeclarationWithType const *arg,
     810                                DeclarationWithType const *realParam,
     811                                const TyVarMap &tyVars ) {
    837812                        assert( param );
    838813                        assert( arg );
    839                         if ( isPolyType( realParam->get_type(), tyVars ) ) {
    840                                 if ( ! isPolyType( arg->get_type() ) ) {
    841                                         UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
    842                                         deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
    843                                         deref->result = arg->get_type()->clone();
    844                                         return deref;
    845                                 } // if
     814                        if ( isPolyType( realParam->get_type(), tyVars )
     815                                        && ! isPolyType( arg->get_type() ) ) {
     816                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
     817                                deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) );
     818                                deref->result = arg->get_type()->clone();
     819                                return deref;
    846820                        } // if
    847821                        return new VariableExpr( param );
    848822                }
    849823
    850                 void addAdapterParams( ApplicationExpr *adapteeApp, std::list< DeclarationWithType *>::iterator arg, std::list< DeclarationWithType *>::iterator param, std::list< DeclarationWithType *>::iterator paramEnd, std::list< DeclarationWithType *>::iterator realParam, const TyVarMap &tyVars ) {
     824                void addAdapterParams(
     825                                ApplicationExpr *adapteeApp,
     826                                std::list< DeclarationWithType *>::const_iterator arg,
     827                                std::list< DeclarationWithType *>::const_iterator param,
     828                                std::list< DeclarationWithType *>::const_iterator paramEnd,
     829                                std::list< DeclarationWithType *>::const_iterator realParam,
     830                                const TyVarMap &tyVars ) {
    851831                        UniqueName paramNamer( "_p" );
    852832                        for ( ; param != paramEnd; ++param, ++arg, ++realParam ) {
     
    859839                }
    860840
    861                 FunctionDecl *Pass1::makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     841                FunctionDecl *Pass1::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
    862842                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
    863843                        adapterType = ScrubTyVars::scrub( adapterType, tyVars );
     
    876856                        Statement *bodyStmt;
    877857
    878                         Type::ForallList::iterator tyArg = realType->get_forall().begin();
    879                         Type::ForallList::iterator tyParam = adapterType->get_forall().begin();
    880                         Type::ForallList::iterator realTyParam = adaptee->get_forall().begin();
    881                         for ( ; tyParam != adapterType->get_forall().end(); ++tyArg, ++tyParam, ++realTyParam ) {
    882                                 assert( tyArg != realType->get_forall().end() );
    883                                 std::list< DeclarationWithType *>::iterator assertArg = (*tyArg)->get_assertions().begin();
    884                                 std::list< DeclarationWithType *>::iterator assertParam = (*tyParam)->get_assertions().begin();
    885                                 std::list< DeclarationWithType *>::iterator realAssertParam = (*realTyParam)->get_assertions().begin();
    886                                 for ( ; assertParam != (*tyParam)->get_assertions().end(); ++assertArg, ++assertParam, ++realAssertParam ) {
    887                                         assert( assertArg != (*tyArg)->get_assertions().end() );
    888                                         adapteeApp->get_args().push_back( makeAdapterArg( *assertParam, *assertArg, *realAssertParam, tyVars ) );
     858                        for ( auto tys : group_iterate( realType->forall, adapterType->forall, adaptee->forall ) ) {
     859                                TypeDecl * tyArg = std::get<0>( tys );
     860                                TypeDecl * tyParam = std::get<1>( tys );
     861                                TypeDecl * realTyParam = std::get<2>( tys );
     862                                for ( auto asserts : group_iterate( tyArg->assertions, tyParam->assertions, realTyParam->assertions ) ) {
     863                                        DeclarationWithType * assertArg = std::get<0>( asserts );
     864                                        DeclarationWithType * assertParam = std::get<1>( asserts );
     865                                        DeclarationWithType * realAssertParam = std::get<2>( asserts );
     866                                        adapteeApp->args.push_back( makeAdapterArg( assertParam, assertArg, realAssertParam, tyVars ) );
    889867                                } // for
    890868                        } // for
    891869
    892                         std::list< DeclarationWithType *>::iterator arg = realType->get_parameters().begin();
    893                         std::list< DeclarationWithType *>::iterator param = adapterType->get_parameters().begin();
    894                         std::list< DeclarationWithType *>::iterator realParam = adaptee->get_parameters().begin();
     870                        std::list< DeclarationWithType *>::const_iterator arg = realType->parameters.begin();
     871                        std::list< DeclarationWithType *>::const_iterator param = adapterType->parameters.begin();
     872                        std::list< DeclarationWithType *>::const_iterator realParam = adaptee->parameters.begin();
    895873                        param++;                // skip adaptee parameter in the adapter type
    896874                        if ( realType->get_returnVals().empty() ) {
     
    898876                                addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
    899877                                bodyStmt = new ExprStmt( adapteeApp );
    900                         } else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
     878                        } else if ( isDynType( adaptee->returnVals.front()->get_type(), tyVars ) ) {
    901879                                // return type T
    902880                                if ( (*param)->get_name() == "" ) {
     
    923901                void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
    924902                        // collect a list of function types passed as parameters or implicit parameters (assertions)
    925                         std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
    926                         std::list< FunctionType *> functions;
    927                         for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    928                                 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
    929                                         findFunction( (*assert)->get_type(), functions, exprTyVars, needsAdapter );
     903                        std::list<FunctionType const *> functions;
     904                        for ( TypeDecl * const tyVar : functionType->get_forall() ) {
     905                                for ( DeclarationWithType * const assert : tyVar->get_assertions() ) {
     906                                        findFunction( assert->get_type(), functions, exprTyVars, needsAdapter );
    930907                                } // for
    931908                        } // for
    932                         for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
    933                                 findFunction( (*arg)->get_type(), functions, exprTyVars, needsAdapter );
     909                        for ( DeclarationWithType * const arg : functionType->get_parameters() ) {
     910                                findFunction( arg->get_type(), functions, exprTyVars, needsAdapter );
    934911                        } // for
    935912
     
    938915                        std::set< std::string > adaptersDone;
    939916
    940                         for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    941                                 FunctionType *originalFunction = (*funType)->clone();
    942                                 FunctionType *realFunction = (*funType)->clone();
     917                        for ( FunctionType const * const funType : functions ) {
     918                                FunctionType *originalFunction = funType->clone();
     919                                FunctionType *realFunction = funType->clone();
    943920                                std::string mangleName = SymTab::Mangler::mangle( realFunction );
    944921
     
    958935                                        if ( adapter == adapters.end() ) {
    959936                                                // adapter has not been created yet in the current scope, so define it
    960                                                 FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
     937                                                FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
    961938                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
    962939                                                adapter = answer.first;
     
    972949
    973950                Expression *makeIncrDecrExpr( ApplicationExpr *appExpr, Type *polyType, bool isIncr ) {
    974                         NameExpr *opExpr;
    975                         if ( isIncr ) {
    976                                 opExpr = new NameExpr( "?+=?" );
    977                         } else {
    978                                 opExpr = new NameExpr( "?-=?" );
    979                         } // if
     951                        NameExpr *opExpr = new NameExpr( ( isIncr ) ? "?+=?" : "?-=?" );
    980952                        UntypedExpr *addAssign = new UntypedExpr( opExpr );
    981953                        if ( AddressExpr *address = dynamic_cast< AddressExpr *>( appExpr->get_args().front() ) ) {
     
    11201092                Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
    11211093                        // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
    1122                         // for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
    1123                         //      std::cerr << i->first << " ";
     1094                        // for ( auto tyVar : scopeTyVars ) {
     1095                        //      std::cerr << tyVar.first << " ";
    11241096                        // }
    11251097                        // std::cerr << "\n";
     
    11341106
    11351107                        Expression *ret = appExpr;
    1136 
    1137                         std::list< Expression *>::iterator arg = appExpr->get_args().begin();
    11381108                        std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
    11391109
     
    11561126                                // std::cerr << "dynRetType: " << dynRetType << std::endl;
    11571127                                Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
    1158                                 ret = addDynRetParam( appExpr, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
     1128                                ret = addDynRetParam( appExpr, concRetType ); // xxx - used to use dynRetType instead of concRetType
    11591129                        } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...?
    11601130                                // xxx - the ! needsAdapter check may be incorrect. It seems there is some situation where an adapter is applied where it shouldn't be, and this fixes it for some cases. More investigation is needed.
     
    11641134                                // std::cerr << *env << std::endl;
    11651135                                // change the application so it calls the adapter rather than the passed function
    1166                                 ret = applyAdapter( appExpr, function, arg, scopeTyVars );
     1136                                ret = applyAdapter( appExpr, function );
    11671137                        } // if
    1168                         arg = appExpr->get_args().begin();
    1169 
    1170                         Type *concRetType = replaceWithConcrete( appExpr, dynRetType );
    1171                         passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
    1172                         addInferredParams( appExpr, function, arg, exprTyVars );
    1173 
    1174                         arg = paramBegin;
    1175 
    1176                         boxParams( appExpr, function, arg, exprTyVars );
     1138
     1139                        Type *concRetType = replaceWithConcrete( dynRetType, env );
     1140                        std::list< Expression *>::iterator arg =
     1141                                passTypeVars( appExpr, concRetType, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's)
     1142                        addInferredParams( appExpr, arg, function, exprTyVars );
     1143
     1144                        // This needs to point at the original first argument.
     1145                        boxParams( appExpr, paramBegin, function, exprTyVars );
     1146
    11771147                        passAdapters( appExpr, function, exprTyVars );
    11781148
     
    11801150                }
    11811151
    1182                 Expression * Pass1::postmutate( UntypedExpr *expr ) {
     1152                bool isPolyDeref( UntypedExpr const * expr, TyVarMap const & scopeTyVars, TypeSubstitution const * env ) {
    11831153                        if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
    1184                                 if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
     1154                                if ( auto name = dynamic_cast<NameExpr const *>( expr->function ) ) {
    11851155                                        if ( name->name == "*?" ) {
    1186                                                 Expression *ret = expr->args.front();
    1187                                                 expr->args.clear();
    1188                                                 delete expr;
    1189                                                 return ret;
     1156                                                return true;
    11901157                                        } // if
    11911158                                } // if
    11921159                        } // if
     1160                        return false;
     1161                }
     1162
     1163                Expression * Pass1::postmutate( UntypedExpr *expr ) {
     1164                        if ( isPolyDeref( expr, scopeTyVars, env ) ) {
     1165                                Expression *ret = expr->args.front();
     1166                                expr->args.clear();
     1167                                delete expr;
     1168                                return ret;
     1169                        }
    11931170                        return expr;
    11941171                }
     
    12001177                        bool needs = false;
    12011178                        if ( UntypedExpr *expr = dynamic_cast< UntypedExpr *>( addrExpr->arg ) ) {
    1202                                 if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
    1203                                         if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
    1204                                                 if ( name->name == "*?" ) {
    1205                                                         if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
    1206                                                                 assert( appExpr->function->result );
    1207                                                                 FunctionType *function = getFunctionType( appExpr->function->result );
    1208                                                                 assert( function );
    1209                                                                 needs = needsAdapter( function, scopeTyVars );
    1210                                                         } // if
    1211                                                 } // if
     1179                                if ( isPolyDeref( expr, scopeTyVars, env ) ) {
     1180                                        if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr->args.front() ) ) {
     1181                                                assert( appExpr->function->result );
     1182                                                FunctionType *function = getFunctionType( appExpr->function->result );
     1183                                                assert( function );
     1184                                                needs = needsAdapter( function, scopeTyVars );
    12121185                                        } // if
    12131186                                } // if
     
    12601233                void Pass2::addAdapters( FunctionType *functionType ) {
    12611234                        std::list< DeclarationWithType *> &paramList = functionType->parameters;
    1262                         std::list< FunctionType *> functions;
    1263                         for ( std::list< DeclarationWithType *>::iterator arg = paramList.begin(); arg != paramList.end(); ++arg ) {
    1264                                 Type *orig = (*arg)->get_type();
     1235                        std::list< FunctionType const *> functions;
     1236                        for ( DeclarationWithType * const arg : functionType->parameters ) {
     1237                                Type *orig = arg->get_type();
    12651238                                findAndReplaceFunction( orig, functions, scopeTyVars, needsAdapter );
    1266                                 (*arg)->set_type( orig );
     1239                                arg->set_type( orig );
    12671240                        }
    12681241                        std::set< std::string > adaptersDone;
    1269                         for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    1270                                 std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     1242                        for ( FunctionType const * const funType : functions ) {
     1243                                std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    12711244                                if ( adaptersDone.find( mangleName ) == adaptersDone.end() ) {
    12721245                                        std::string adapterName = makeAdapterName( mangleName );
    12731246                                        // adapter may not be used in body, pass along with unused attribute.
    1274                                         paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( *funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
     1247                                        paramList.push_front( new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), 0, { new Attribute( "unused" ) } ) );
    12751248                                        adaptersDone.insert( adaptersDone.begin(), mangleName );
    12761249                                }
     
    13491322                        ObjectDecl newPtr( "", Type::StorageClasses(), LinkageSpec::C, 0,
    13501323                                           new PointerType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ) ), 0 );
    1351                         for ( Type::ForallList::const_iterator tyParm = funcType->get_forall().begin(); tyParm != funcType->get_forall().end(); ++tyParm ) {
     1324                        for ( TypeDecl * const tyParam : funcType->get_forall() ) {
    13521325                                ObjectDecl *sizeParm, *alignParm;
    13531326                                // add all size and alignment parameters to parameter list
    1354                                 if ( (*tyParm)->isComplete() ) {
    1355                                         TypeInstType parmType( Type::Qualifiers(), (*tyParm)->get_name(), *tyParm );
     1327                                if ( tyParam->isComplete() ) {
     1328                                        TypeInstType parmType( Type::Qualifiers(), tyParam->get_name(), tyParam );
    13561329                                        std::string parmName = mangleType( &parmType );
    13571330
     
    13671340                                }
    13681341                                // move all assertions into parameter list
    1369                                 for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
     1342                                for ( DeclarationWithType * const assert : tyParam->get_assertions() ) {
    13701343                                        // assertion parameters may not be used in body, pass along with unused attribute.
    1371                                         (*assert)->get_attributes().push_back( new Attribute( "unused" ) );
    1372                                         inferredParams.push_back( *assert );
    1373                                 }
    1374                                 (*tyParm)->get_assertions().clear();
     1344                                        assert->get_attributes().push_back( new Attribute( "unused" ) );
     1345                                        inferredParams.push_back( assert );
     1346                                }
     1347                                tyParam->get_assertions().clear();
    13751348                        }
    13761349
    13771350                        // add size/align for generic parameter types to parameter list
    13781351                        std::set< std::string > seenTypes; // sizeofName for generic types we've seen
    1379                         for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
    1380                                 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1352                        for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
     1353                                Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
    13811354                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
    13821355                                        std::string typeName = mangleType( polyType );
     
    14821455
    14831456                        if(!expect_func_type) {
    1484                                 GuardAction( [this]() {
    1485                                         knownLayouts.endScope();
    1486                                         knownOffsets.endScope();
    1487                                 });
    14881457                                // If this is the first function type we see
    14891458                                // Then it's the type of the declaration and we care about it
    1490                                 knownLayouts.beginScope();
    1491                                 knownOffsets.beginScope();
     1459                                GuardScope( *this );
    14921460                        }
    14931461
     
    14971465
    14981466                        // make sure that any type information passed into the function is accounted for
    1499                         for ( std::list< DeclarationWithType* >::const_iterator fnParm = funcType->get_parameters().begin(); fnParm != funcType->get_parameters().end(); ++fnParm ) {
     1467                        for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
    15001468                                // condition here duplicates that in Pass2::mutate( FunctionType* )
    1501                                 Type *polyType = isPolyType( (*fnParm)->get_type(), scopeTyVars );
     1469                                Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
    15021470                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
    15031471                                        knownLayouts.insert( mangleType( polyType ) );
     
    15071475
    15081476                /// converts polymorphic type T into a suitable monomorphic representation, currently: __attribute__((aligned(8)) char[size_T]
    1509                 Type * polyToMonoType( Type * declType ) {
     1477                Type * polyToMonoType( Type const * declType ) {
    15101478                        Type * charType = new BasicType( Type::Qualifiers(), BasicType::Kind::Char);
    15111479                        Expression * size = new NameExpr( sizeofName( mangleType(declType) ) );
     
    15721540                /// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
    15731541                long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
    1574                         long i = 0;
    1575                         for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
    1576                                 if ( memberDecl->get_name() != (*decl)->get_name() )
     1542                        for ( auto pair : enumerate( baseDecls ) ) {
     1543                                Declaration * decl = pair.val;
     1544                                size_t i = pair.idx;
     1545                                if ( memberDecl->get_name() != decl->get_name() )
    15771546                                        continue;
    15781547
    15791548                                if ( memberDecl->get_name().empty() ) {
    15801549                                        // plan-9 field: match on unique_id
    1581                                         if ( memberDecl->get_uniqueId() == (*decl)->get_uniqueId() )
     1550                                        if ( memberDecl->get_uniqueId() == decl->get_uniqueId() )
    15821551                                                return i;
    15831552                                        else
     
    15851554                                }
    15861555
    1587                                 DeclarationWithType *declWithType = strict_dynamic_cast< DeclarationWithType* >( *decl );
     1556                                DeclarationWithType *declWithType = strict_dynamic_cast< DeclarationWithType* >( decl );
    15881557
    15891558                                if ( memberDecl->get_mangleName().empty() || declWithType->get_mangleName().empty() ) {
     
    16031572
    16041573                /// Returns an index expression into the offset array for a type
    1605                 Expression *makeOffsetIndex( Type *objectType, long i ) {
     1574                Expression *makeOffsetIndex( Type const *objectType, long i ) {
    16061575                        ConstantExpr *fieldIndex = new ConstantExpr( Constant::from_ulong( i ) );
    16071576                        UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
     
    16961665
    16971666                void PolyGenericCalculator::addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams ) {
    1698                         for ( std::list< Type* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
    1699                                 if ( findGeneric( *param ) ) {
     1667                        for ( Type * const param : otypeParams ) {
     1668                                if ( findGeneric( param ) ) {
    17001669                                        // push size/align vars for a generic parameter back
    1701                                         std::string paramName = mangleType( *param );
     1670                                        std::string paramName = mangleType( param );
    17021671                                        layoutCall->get_args().push_back( new NameExpr( sizeofName( paramName ) ) );
    17031672                                        layoutCall->get_args().push_back( new NameExpr( alignofName( paramName ) ) );
    17041673                                } else {
    1705                                         layoutCall->get_args().push_back( new SizeofExpr( (*param)->clone() ) );
    1706                                         layoutCall->get_args().push_back( new AlignofExpr( (*param)->clone() ) );
     1674                                        layoutCall->get_args().push_back( new SizeofExpr( param->clone() ) );
     1675                                        layoutCall->get_args().push_back( new AlignofExpr( param->clone() ) );
    17071676                                }
    17081677                        }
     
    17101679
    17111680                /// returns true if any of the otype parameters have a dynamic layout and puts all otype parameters in the output list
    1712                 bool findGenericParams( std::list< TypeDecl* > &baseParams, std::list< Expression* > &typeParams, std::list< Type* > &out ) {
     1681                bool findGenericParams( std::list< TypeDecl* > const &baseParams, std::list< Expression* > const &typeParams, std::list< Type* > &out ) {
    17131682                        bool hasDynamicLayout = false;
    17141683
    1715                         std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
    1716                         std::list< Expression* >::const_iterator typeParam = typeParams.begin();
    1717                         for ( ; baseParam != baseParams.end() && typeParam != typeParams.end(); ++baseParam, ++typeParam ) {
     1684                        for ( auto paramPair : group_iterate( baseParams, typeParams ) ) {
     1685                                TypeDecl * baseParam = std::get<0>( paramPair );
     1686                                Expression * typeParam = std::get<1>( paramPair );
    17181687                                // skip non-otype parameters
    1719                                 if ( ! (*baseParam)->isComplete() ) continue;
    1720                                 TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( *typeParam );
     1688                                if ( ! baseParam->isComplete() ) continue;
     1689                                TypeExpr *typeExpr = dynamic_cast< TypeExpr* >( typeParam );
    17211690                                assert( typeExpr && "all otype parameters should be type expressions" );
    17221691
     
    17251694                                if ( isPolyType( type ) ) hasDynamicLayout = true;
    17261695                        }
    1727                         assert( baseParam == baseParams.end() && typeParam == typeParams.end() );
    17281696
    17291697                        return hasDynamicLayout;
    17301698                }
    17311699
    1732                 bool PolyGenericCalculator::findGeneric( Type *ty ) {
     1700                bool PolyGenericCalculator::findGeneric( Type const *ty ) {
    17331701                        ty = replaceTypeInst( ty, env );
    17341702
    1735                         if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
     1703                        if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
    17361704                                if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
    17371705                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
     
    17391707                                }
    17401708                                return false;
    1741                         } else if ( StructInstType *structTy = dynamic_cast< StructInstType* >( ty ) ) {
     1709                        } else if ( auto structTy = dynamic_cast< StructInstType const * >( ty ) ) {
    17421710                                // check if this type already has a layout generated for it
    17431711                                std::string typeName = mangleType( ty );
     
    17461714                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
    17471715                                std::list< Type* > otypeParams;
    1748                                 if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->get_parameters(), otypeParams ) ) return false;
     1716                                if ( ! findGenericParams( *structTy->get_baseParameters(), structTy->parameters, otypeParams ) ) return false;
    17491717
    17501718                                // insert local variables for layout and generate call to layout function
     
    17761744
    17771745                                return true;
    1778                         } else if ( UnionInstType *unionTy = dynamic_cast< UnionInstType* >( ty ) ) {
     1746                        } else if ( auto unionTy = dynamic_cast< UnionInstType const * >( ty ) ) {
    17791747                                // check if this type already has a layout generated for it
    17801748                                std::string typeName = mangleType( ty );
     
    17831751                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
    17841752                                std::list< Type* > otypeParams;
    1785                                 if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->get_parameters(), otypeParams ) ) return false;
     1753                                if ( ! findGenericParams( *unionTy->get_baseParameters(), unionTy->parameters, otypeParams ) ) return false;
    17861754
    17871755                                // insert local variables for layout and generate call to layout function
     
    18811849                                        // build initializer list for offset array
    18821850                                        std::list< Initializer* > inits;
    1883                                         for ( std::list< Declaration* >::const_iterator member = baseMembers.begin(); member != baseMembers.end(); ++member ) {
    1884                                                 if ( DeclarationWithType *memberDecl = dynamic_cast< DeclarationWithType* >( *member ) ) {
    1885                                                         inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
    1886                                                 } else {
    1887                                                         assertf( false, "Requesting offset of Non-DWT member: %s", toString( *member ).c_str() );
    1888                                                 }
     1851                                        for ( Declaration * const member : baseMembers ) {
     1852                                                DeclarationWithType *memberDecl = dynamic_cast< DeclarationWithType* >( member );
     1853                                                assertf( memberDecl, "Requesting offset of Non-DWT member: %s", toString( member ).c_str() );
     1854                                                inits.push_back( new SingleInit( new OffsetofExpr( ty->clone(), memberDecl ) ) );
    18891855                                        }
    18901856
     
    19651931// compile-command: "make install" //
    19661932// End: //
     1933
  • src/GenPoly/FindFunction.cc

    rb77f0e1 r63be3387  
    2929        class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {
    3030          public:
    31                 FindFunction( std::list< FunctionType* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
     31                FindFunction( std::list< FunctionType const* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
    3232
    3333                void premutate( FunctionType * functionType );
     
    3737                void handleForall( const Type::ForallList &forall );
    3838
    39                 std::list< FunctionType* > &functions;
     39                std::list< FunctionType const * > & functions;
    4040                TyVarMap tyVars;
    4141                bool replaceMode;
     
    4343        };
    4444
    45         void findFunction( Type *type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
     45        void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    4646                PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );
    4747                type->acceptMutator( finder );
    4848        }
    4949
    50         void findAndReplaceFunction( Type *&type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
     50        void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    5151                PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );
    5252                type = type->acceptMutator( finder );
    5353        }
    5454
    55         FindFunction::FindFunction( std::list< FunctionType* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate )
     55        FindFunction::FindFunction( std::list< FunctionType const * > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate )
    5656                : functions( functions ), tyVars( tyVars ), replaceMode( replaceMode ), predicate( predicate ) {
    5757        }
  • src/GenPoly/FindFunction.h

    rb77f0e1 r63be3387  
    2727
    2828        /// recursively walk `type`, placing all functions that match `predicate` under `tyVars` into `functions`
    29         void findFunction( Type *type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
     29        void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
    3030        /// like `findFunction`, but also replaces the function type with void ()(void)
    31         void findAndReplaceFunction( Type *&type, std::list< FunctionType* > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
     31        void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
    3232} // namespace GenPoly
    3333
  • src/GenPoly/GenPoly.cc

    rb77f0e1 r63be3387  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:25:00 2022
    13 // Update Count     : 16
     12// Last Modified On : Mon Oct 24 15:19:00 2022
     13// Update Count     : 17
    1414//
    1515
     
    118118        }
    119119
     120        const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env ) {
     121                if ( ! env ) return type;
     122                if ( auto typeInst = dynamic_cast< const TypeInstType* >( type ) ) {
     123                        Type *newType = env->lookup( typeInst->get_name() );
     124                        if ( newType ) return newType;
     125                }
     126                return type;
     127        }
     128
    120129        const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) {
    121130                if (!env) return type;
    122                 if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) {
     131                if ( auto typeInst = dynamic_cast<const ast::TypeInstType*>(type) ) {
    123132                        auto newType = env->lookup(typeInst);
    124133                        if (newType) return newType;
     
    194203
    195204        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    196                 if ( typeVars.find( inst->typeString() ) != typeVars.end() ) return type;
     205                if ( typeVars.find( *inst ) != typeVars.end() ) return type;
    197206        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    198207                return isPolyType( array->base, subst );
     
    227236
    228237        if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) {
    229                 auto var = typeVars.find( inst->name );
     238                auto var = typeVars.find( *inst );
    230239                if ( var != typeVars.end() && var->second.isComplete ) {
    231 
     240                        return inst;
    232241                }
    233242        } else if ( auto inst = dynamic_cast<ast::StructInstType const *>( type ) ) {
     
    784793
    785794void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    786         typeVars.insert( type->typeString(), ast::TypeDecl::Data( type->base ) );
     795        typeVars.insert( *type, ast::TypeDecl::Data( type->base ) );
    787796}
    788797
     
    816825        }
    817826
    818 void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars ) {
    819         for ( auto const & pair : typeVars ) {
    820                 os << pair.first << " (" << pair.second << ") ";
    821         } // for
    822         os << std::endl;
    823 }
    824 
    825827} // namespace GenPoly
    826828
  • src/GenPoly/GenPoly.h

    rb77f0e1 r63be3387  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:06:00 2022
    13 // Update Count     : 9
     12// Last Modified On : Mon Oct 24 15:18:00 2022
     13// Update Count     : 11
    1414//
    1515
     
    2222#include "AST/Decl.hpp"           // for TypeDecl::Data
    2323#include "AST/Fwd.hpp"            // for ApplicationExpr, BaseInstType, Func...
     24#include "AST/Type.hpp"           // for TypeInstType::TypeEnvKey
    2425#include "SymTab/Mangler.h"       // for Mangler
    2526#include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
     
    2829namespace GenPoly {
    2930
    30         // TODO Via some tricks this works for ast::TypeDecl::Data as well.
    3131        typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    32         using TypeVarMap = ErasableScopedMap< std::string, ast::TypeDecl::Data >;
     32        using TypeVarMap = ErasableScopedMap< ast::TypeInstType::TypeEnvKey, ast::TypeDecl::Data >;
    3333
    3434        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    3535        Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
     36        const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env );
     37        const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * );
    3638
    3739        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
     
    5355        /// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
    5456        ReferenceToType *isDynRet( FunctionType *function );
     57        const ast::BaseInstType *isDynRet( const ast::FunctionType * func );
    5558
    5659        /// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
     
    112115        /// Prints type variable map
    113116        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
    114         void printTypeVarMap( std::ostream &os, const TypeVarMap & typeVars );
    115117
    116118        /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
    117         inline std::string mangleType( Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
     119        inline std::string mangleType( const Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
    118120
    119121        /// Gets the name of the sizeof parameter for the type, given its mangled name
     
    128130        /// Gets the name of the layout function for a given aggregate type, given its declaration
    129131        inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
     132        inline std::string layoutofName( ast::AggregateDecl const * decl ) {
     133                return std::string( "_layoutof_" ) + decl->name;
     134        }
    130135
    131136} // namespace GenPoly
  • src/GenPoly/InstantiateGenericNew.cpp

    rb77f0e1 r63be3387  
    1010// Created On       : Tue Aug 16 10:51:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep 13 16:03:00 2022
    13 // Update Count     : 0
     12// Last Modified On : Mon Oct 31 16:48:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    378378                //   Ptr(int) p;
    379379                //   int i;
     380                // The original expression:
    380381                //   p.x = &i;
    381                 // becomes
    382                 //   int *& _dtype_static_member_0 = (int **)&p.x;
    383                 //   _dtype_static_member_0 = &i;
     382                // Becomes the expression/declaration:
     383                //   int *& _dtype_static_member_0;
     384                //   (_dtype_static_member_0 = (int**)&p.x,
     385                //    _dtype_static_member_0) = &i;
     386
     387                // The declaration is simple:
    384388                static UniqueName tmpNamer( "_dtype_static_member_" );
    385                 ast::Expr * init = new ast::CastExpr( location,
    386                         new ast::AddressExpr( location, memberExpr ),
    387                         new ast::PointerType( ast::deepCopy( concType ) ),
    388                         ast::ExplicitCast
    389                 );
    390389                ast::ObjectDecl * tmp = new ast::ObjectDecl( location,
    391390                        tmpNamer.newName(),
    392391                        new ast::ReferenceType( concType ),
    393                         new ast::SingleInit( location, init ),
     392                        nullptr,
    394393                        ast::Storage::Classes(),
    395394                        ast::Linkage::C
    396395                );
    397396                stmtsToAddBefore.push_back( new ast::DeclStmt( location, tmp ) );
    398                 return new ast::VariableExpr( location, tmp );
     397
     398                // The expression is more complex, uses references and reference /
     399                // pointer parity. But breaking it up risks reordering.
     400                return new ast::CommaExpr( location,
     401                        ast::UntypedExpr::createAssign( location,
     402                                new ast::VariableExpr( location, tmp ),
     403                                new ast::CastExpr( location,
     404                                        new ast::AddressExpr( location, memberExpr ),
     405                                        new ast::PointerType( ast::deepCopy( concType ) ),
     406                                        ast::ExplicitCast
     407                                )
     408                        ),
     409                        new ast::VariableExpr( location, tmp )
     410                );
    399411        } else {
    400412                // Here, it can simply add a cast to actual types.
     
    476488};
    477489
    478 // I think this and the UnionInstType can be made into a template function.
    479490ast::Type const * GenericInstantiator::postvisit(
    480491                ast::StructInstType const * inst ) {
  • src/GenPoly/ScrubTyVars.cc

    rb77f0e1 r63be3387  
    2020#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2121#include "ScrubTyVars.h"
    22 #include "SymTab/Mangler.h"             // for mangle, typeMode
     22#include "SymTab/Mangler.h"             // for mangleType
    2323#include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    2424#include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
     
    195195        }
    196196
    197         auto typeVar = typeVars->find( type->name );
     197        auto typeVar = typeVars->find( *type );
    198198        if ( typeVar == typeVars->end() ) {
    199199                return type;
     
    227227        if ( dynType ) {
    228228                return new ast::NameExpr( expr->location,
    229                         sizeofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     229                        sizeofName( Mangle::mangleType( dynType ) ) );
    230230        } else {
    231231                return expr;
     
    237237        if ( dynType ) {
    238238                return new ast::NameExpr( expr->location,
    239                         alignofName( Mangle::mangle( dynType, Mangle::typeMode() ) ) );
     239                        alignofName( Mangle::mangleType( dynType ) ) );
    240240        } else {
    241241                return expr;
  • src/Parser/DeclarationNode.cc

    rb77f0e1 r63be3387  
    2727#include "SynTree/LinkageSpec.h"   // for Spec, linkageName, Cforall
    2828#include "SynTree/Attribute.h"     // for Attribute
    29 #include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, Declaration
     29#include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration
    3030#include "SynTree/Expression.h"    // for Expression, ConstantExpr
    3131#include "SynTree/Statement.h"     // for AsmStmt
     
    11651165                SemanticError( this, "invalid function specifier for " );
    11661166        } // if
     1167        if ( enumInLine ) {
     1168                return new InlineMemberDecl( *name, storageClasses, linkage, nullptr );
     1169        } // if
    11671170        assertf( name, "ObjectDecl must a have name\n" );
    11681171        return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension );
  • src/Parser/ExpressionNode.cc

    rb77f0e1 r63be3387  
    519519                }
    520520        }
    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         }
    526         return ret;
     521        return new QualifiedNameExpr( newDecl, name->name );
    527522}
    528523
  • src/Parser/ParseNode.h

    rb77f0e1 r63be3387  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Oct 18 16:22:15 2022
    13 // Update Count     : 937
     12// Last Modified On : Wed Nov  2 21:27:07 2022
     13// Update Count     : 939
    1414//
    1515
     
    168168        Ctor, Dtor,
    169169}; // OperKinds
     170
     171enum class EnumHiding { Visible, Hide };
    170172
    171173struct LabelNode {
  • src/Parser/TypeData.cc

    rb77f0e1 r63be3387  
    925925        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
    926926                if ( cur->enumInLine ) {
    927                         // Tell the compiler this is a inline value placeholder
    928                         ObjectDecl * member = dynamic_cast< ObjectDecl* >(* members);
    929                         member->enumInLine = true;
    930                 }
    931                 if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
     927                        // Do Nothing
     928                } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) {
    932929                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
    933930                } else if ( cur->has_enumeratorValue() ) {
  • src/Parser/parser.yy

    rb77f0e1 r63be3387  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Oct 14 14:04:43 2022
    13 // Update Count     : 5751
     12// Last Modified On : Wed Nov  2 21:31:21 2022
     13// Update Count     : 5810
    1414//
    1515
     
    278278
    279279// Types declaration for productions
     280
    280281%union {
    281282        Token tok;
     
    290291        CondCtl * ifctl;
    291292        ForCtrl * fctl;
    292         enum OperKinds compop;
     293        OperKinds compop;
    293294        LabelNode * label;
    294295        InitializerNode * in;
     
    296297        std::string * str;
    297298        bool flag;
     299        EnumHiding hide;
    298300        CatchStmt::Kind catch_kind;
    299301        GenericExpr * genexpr;
     
    364366%type<constant> string_literal
    365367%type<str> string_literal_list
     368
     369%type<hide> hide_opt                                    visible_hide_opt
    366370
    367371// expressions
     
    25532557        | ENUM attribute_list_opt identifier
    25542558                { typedefTable.makeTypedef( *$3 ); }
    2555           '{' enumerator_list comma_opt '}'
    2556                 { $$ = DeclarationNode::newEnum( $3, $6, true, false )->addQualifiers( $2 ); }
     2559          hide_opt '{' enumerator_list comma_opt '}'
     2560          { $$ = DeclarationNode::newEnum( $3, $7, true, false )->addQualifiers( $2 ); }
    25572561        | ENUM attribute_list_opt typedef_name                          // unqualified type name
    2558           '{' enumerator_list comma_opt '}'
    2559                 { $$ = DeclarationNode::newEnum( $3->name, $5, true, false )->addQualifiers( $2 ); }
     2562          hide_opt '{' enumerator_list comma_opt '}'
     2563                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false )->addQualifiers( $2 ); }
    25602564        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    25612565                {
     
    25742578                        typedefTable.makeTypedef( *$6 );
    25752579                }
    2576           '{' enumerator_list comma_opt '}'
    2577                 {
    2578                         $$ = DeclarationNode::newEnum( $6, $10, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2580          hide_opt '{' enumerator_list comma_opt '}'
     2581                {
     2582                        $$ = DeclarationNode::newEnum( $6, $11, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
    25792583                }
    25802584        | ENUM '(' ')' attribute_list_opt identifier attribute_list_opt
    2581           '{' enumerator_list comma_opt '}'
    2582                 {
    2583                         $$ = DeclarationNode::newEnum( $5, $8, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
    2584                 }
    2585         | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
    2586                 {
    2587                         $$ = DeclarationNode::newEnum( $6->name, $9, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
    2588                 }
    2589         | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt '{' enumerator_list comma_opt '}'
    2590                 {
    2591                         $$ = DeclarationNode::newEnum( $5->name, $8, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
     2585          hide_opt '{' enumerator_list comma_opt '}'
     2586                {
     2587                        $$ = DeclarationNode::newEnum( $5, $9, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
     2588                }
     2589        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt typedef_name attribute_list_opt
     2590          hide_opt '{' enumerator_list comma_opt '}'
     2591                {
     2592                        $$ = DeclarationNode::newEnum( $6->name, $10, true, true, $3 )->addQualifiers( $5 )->addQualifiers( $7 );
     2593                }
     2594        | ENUM '(' ')' attribute_list_opt typedef_name attribute_list_opt
     2595          hide_opt '{' enumerator_list comma_opt '}'
     2596                {
     2597                        $$ = DeclarationNode::newEnum( $5->name, $9, true, true, nullptr )->addQualifiers( $4 )->addQualifiers( $6 );
    25922598                }
    25932599        | enum_type_nobody
     2600        ;
     2601
     2602hide_opt:
     2603        // empty
     2604                { $$ = EnumHiding::Visible; }
     2605        | '!'
     2606                { $$ = EnumHiding::Hide; }
    25942607        ;
    25952608
     
    26022615
    26032616enumerator_list:
    2604         identifier_or_type_name enumerator_value_opt
    2605                 { $$ = DeclarationNode::newEnumValueGeneric( $1, $2 ); }
     2617        visible_hide_opt identifier_or_type_name enumerator_value_opt
     2618                { $$ = DeclarationNode::newEnumValueGeneric( $2, $3 ); }
    26062619        | INLINE type_name
    26072620                { $$ = DeclarationNode::newEnumInLine( *$2->type->symbolic.name ); }
    2608         | enumerator_list ',' identifier_or_type_name enumerator_value_opt
    2609                 { $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( $3, $4 ) ); }
     2621        | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt
     2622                { $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); }
    26102623        | enumerator_list ',' INLINE type_name enumerator_value_opt
    26112624                { $$ = $1->appendList( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); }
     2625        ;
     2626
     2627visible_hide_opt:
     2628        hide_opt
     2629        | '^'
     2630                { $$ = EnumHiding::Visible; }
    26122631        ;
    26132632
  • src/ResolvExpr/CommonType.cc

    rb77f0e1 r63be3387  
    991991                                add_qualifiers( result, type2->qualifiers );
    992992                        } else {
    993                                 // xxx - does unifying a ref with typed enumInst makes sense?
    994993                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    995994                                        result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
     
    10101009
    10111010                void postvisit( const ast::EnumInstType * enumInst ) {
    1012                         // reuse BasicType/EnumInstType common type by swapping
    1013                         // xxx - is this already handled by unify?
    10141011                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    10151012                                result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
  • src/ResolvExpr/ConversionCost.cc

    rb77f0e1 r63be3387  
    720720                costCalc( baseType, dst, srcIsLvalue, symtab, env );
    721721        } else {
    722                 (void)enumInstType;
    723722                static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    724723                cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
  • src/ResolvExpr/SatisfyAssertions.cpp

    rb77f0e1 r63be3387  
    268268                ast::ptr< ast::Type > resType = cand.expr->result;
    269269                cand.env.apply( resType );
    270                 return Mangle::mangle( resType, Mangle::typeMode() );
     270                return Mangle::mangleType( resType );
    271271        }
    272272
  • src/SymTab/Mangler.cc

    rb77f0e1 r63be3387  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:40:29 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 11 21:56:06 2021
    13 // Update Count     : 74
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct 21 16:18:00 2022
     13// Update Count     : 75
    1414//
    1515#include "Mangler.h"
     
    418418                        void postvisit( const ast::QualifiedType * qualType );
    419419
    420                         std::string get_mangleName() { return mangleName; }
     420                        /// The result is the current constructed mangled name.
     421                        std::string result() const { return mangleName; }
    421422                  private:
    422423                        std::string mangleName;         ///< Mangled name being constructed
     
    444445        } // namespace
    445446
    446 
    447447        std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
    448                 ast::Pass<Mangler_new> mangler( mode );
    449                 maybeAccept( decl, mangler );
    450                 return mangler.core.get_mangleName();
     448                return ast::Pass<Mangler_new>::read( decl, mode );
    451449        }
    452450
     
    689687                                        } // for
    690688                                        for ( auto & assert : ptype->assertions ) {
    691                                                 ast::Pass<Mangler_new> sub_mangler(
    692                                                         mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    693                                                 assert->var->accept( sub_mangler );
    694                                                 assertionNames.push_back( sub_mangler.core.get_mangleName() );
     689                                                assertionNames.push_back( ast::Pass<Mangler_new>::read(
     690                                                        assert->var.get(),
     691                                                        mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
    695692                                                acount++;
    696693                                        } // for
  • src/SymTab/Mangler.h

    rb77f0e1 r63be3387  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:44:03 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:45:30 2017
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Oct 27 11:58:00 2022
     13// Update Count     : 16
    1414//
    1515
     
    2222
    2323#include "AST/Bitfield.hpp"
    24 #include "AST/Fwd.hpp"
    2524#include "SynTree/SynTree.h"  // for Types
    2625#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
     
    3332// * Currently name compression is not implemented.
    3433
     34namespace ast {
     35        class Node;
     36}
    3537namespace ResolvExpr {
    3638        class TypeEnvironment;
     
    101103        using Mode = bitfield<mangle_flags>;
    102104
    103         static inline Mode typeMode() { return NoOverrideable | Type; }
     105        /// Mangle declaration name.
     106        std::string mangle( const ast::Node * decl, Mode mode = {} );
    104107
    105         /// Mangle declaration name
    106         std::string mangle( const ast::Node * decl, Mode mode = {} );
     108        /// Most common mangle configuration for types.
     109        static inline std::string mangleType( const ast::Node * type ) {
     110                return mangle( type, { NoOverrideable | Type } );
     111        }
    107112
    108113        namespace Encoding {
  • src/SymTab/Validate.cc

    rb77f0e1 r63be3387  
    4747#include <utility>                     // for pair
    4848
    49 #include "AST/Chain.hpp"
    50 #include "AST/Decl.hpp"
    51 #include "AST/Node.hpp"
    52 #include "AST/Pass.hpp"
    53 #include "AST/SymbolTable.hpp"
    54 #include "AST/Type.hpp"
    55 #include "AST/TypeSubstitution.hpp"
    5649#include "CodeGen/CodeGenerator.h"     // for genName
    5750#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
     
    13261319        }
    13271320
    1328 namespace {
    1329         /// Replaces enum types by int, and function/array types in function parameter and return
    1330         /// lists by appropriate pointers
    1331         /*
    1332         struct EnumAndPointerDecay_new {
    1333                 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
    1334                         // set the type of each member of the enumeration to be EnumConstant
    1335                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1336                                 // build new version of object with EnumConstant
    1337                                 ast::ptr< ast::ObjectDecl > obj =
    1338                                         enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1339                                 obj.get_and_mutate()->type =
    1340                                         new ast::EnumInstType{ enumDecl->name, ast::CV::Const };
    1341 
    1342                                 // set into decl
    1343                                 ast::EnumDecl * mut = mutate( enumDecl );
    1344                                 mut->members[i] = obj.get();
    1345                                 enumDecl = mut;
    1346                         }
    1347                         return enumDecl;
    1348                 }
    1349 
    1350                 static const ast::FunctionType * fixFunctionList(
    1351                         const ast::FunctionType * func,
    1352                         std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field,
    1353                         ast::ArgumentFlag isVarArgs = ast::FixedArgs
    1354                 ) {
    1355                         const auto & dwts = func->* field;
    1356                         unsigned nvals = dwts.size();
    1357                         bool hasVoid = false;
    1358                         for ( unsigned i = 0; i < nvals; ++i ) {
    1359                                 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) );
    1360                         }
    1361 
    1362                         // the only case in which "void" is valid is where it is the only one in the list
    1363                         if ( hasVoid && ( nvals > 1 || isVarArgs ) ) {
    1364                                 SemanticError(
    1365                                         dwts.front()->location, func, "invalid type void in function type" );
    1366                         }
    1367 
    1368                         // one void is the only thing in the list, remove it
    1369                         if ( hasVoid ) {
    1370                                 func = ast::mutate_field(
    1371                                         func, field, std::vector< ast::ptr< ast::DeclWithType > >{} );
    1372                         }
    1373 
    1374                         return func;
    1375                 }
    1376 
    1377                 const ast::FunctionType * previsit( const ast::FunctionType * func ) {
    1378                         func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs );
    1379                         return fixFunctionList( func, &ast::FunctionType::returns );
    1380                 }
    1381         };
    1382 
    1383         /// expand assertions from a trait instance, performing appropriate type variable substitutions
    1384         void expandAssertions(
    1385                 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out
    1386         ) {
    1387                 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) );
    1388 
    1389                 // build list of trait members, substituting trait decl parameters for instance parameters
    1390                 ast::TypeSubstitution sub{
    1391                         inst->base->params.begin(), inst->base->params.end(), inst->params.begin() };
    1392                 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base
    1393                 for ( ast::ptr< ast::Decl > decl : inst->base->members ) {
    1394                         auto member = decl.strict_as< ast::DeclWithType >();
    1395                         sub.apply( member );
    1396                         out.emplace_back( member );
    1397                 }
    1398         }
    1399 
    1400         /// Associates forward declarations of aggregates with their definitions
    1401         class LinkReferenceToTypes_new final
    1402         : public ast::WithSymbolTable, public ast::WithGuards, public
    1403           ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    1404 
    1405                 // these maps of uses of forward declarations of types need to have the actual type
    1406                 // declaration switched in * after * they have been traversed. To enable this in the
    1407                 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
    1408                 // before it is placed in the map, properly updating its parents in the usual traversal,
    1409                 // then can have the actual mutation applied later
    1410                 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
    1411                 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
    1412                 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
    1413 
    1414                 const CodeLocation & location;
    1415                 const ast::SymbolTable * localSymtab;
    1416 
    1417                 ForwardEnumsType forwardEnums;
    1418                 ForwardStructsType forwardStructs;
    1419                 ForwardUnionsType forwardUnions;
    1420 
    1421                 /// true if currently in a generic type body, so that type parameter instances can be
    1422                 /// renamed appropriately
    1423                 bool inGeneric = false;
    1424 
    1425         public:
    1426                 /// contstruct using running symbol table
    1427                 LinkReferenceToTypes_new( const CodeLocation & loc )
    1428                 : location( loc ), localSymtab( &symtab ) {}
    1429 
    1430                 /// construct using provided symbol table
    1431                 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
    1432                 : location( loc ), localSymtab( &syms ) {}
    1433 
    1434                 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    1435                         // ensure generic parameter instances are renamed like the base type
    1436                         if ( inGeneric && typeInst->base ) {
    1437                                 typeInst = ast::mutate_field(
    1438                                         typeInst, &ast::TypeInstType::name, typeInst->base->name );
    1439                         }
    1440 
    1441                         if (
    1442                                 auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
    1443                                         localSymtab->lookupType( typeInst->name ) )
    1444                         ) {
    1445                                 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
    1446                         }
    1447 
    1448                         return typeInst;
    1449                 }
    1450 
    1451                 const ast::Type * postvisit( const ast::EnumInstType * inst ) {
    1452                         const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
    1453                         // not a semantic error if the enum is not found, just an implicit forward declaration
    1454                         if ( decl ) {
    1455                                 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
    1456                         }
    1457                         if ( ! decl || ! decl->body ) {
    1458                                 // forward declaration
    1459                                 auto mut = mutate( inst );
    1460                                 forwardEnums.emplace( inst->name, mut );
    1461                                 inst = mut;
    1462                         }
    1463                         return inst;
    1464                 }
    1465 
    1466                 void checkGenericParameters( const ast::BaseInstType * inst ) {
    1467                         for ( const ast::Expr * param : inst->params ) {
    1468                                 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
    1469                                         SemanticError(
    1470                                                 location, inst, "Expression parameters for generic types are currently "
    1471                                                 "unsupported: " );
    1472                                 }
    1473                         }
    1474                 }
    1475 
    1476                 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
    1477                         const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
    1478                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1479                         if ( decl ) {
    1480                                 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
    1481                         }
    1482                         if ( ! decl || ! decl->body ) {
    1483                                 // forward declaration
    1484                                 auto mut = mutate( inst );
    1485                                 forwardStructs.emplace( inst->name, mut );
    1486                                 inst = mut;
    1487                         }
    1488                         checkGenericParameters( inst );
    1489                         return inst;
    1490                 }
    1491 
    1492                 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
    1493                         const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
    1494                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1495                         if ( decl ) {
    1496                                 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
    1497                         }
    1498                         if ( ! decl || ! decl->body ) {
    1499                                 // forward declaration
    1500                                 auto mut = mutate( inst );
    1501                                 forwardUnions.emplace( inst->name, mut );
    1502                                 inst = mut;
    1503                         }
    1504                         checkGenericParameters( inst );
    1505                         return inst;
    1506                 }
    1507 
    1508                 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
    1509                         // handle other traits
    1510                         const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
    1511                         if ( ! traitDecl )       {
    1512                                 SemanticError( location, "use of undeclared trait " + traitInst->name );
    1513                         }
    1514                         if ( traitDecl->params.size() != traitInst->params.size() ) {
    1515                                 SemanticError( location, traitInst, "incorrect number of trait parameters: " );
    1516                         }
    1517                         traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
    1518 
    1519                         // need to carry over the "sized" status of each decl in the instance
    1520                         for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
    1521                                 auto expr = traitInst->params[i].as< ast::TypeExpr >();
    1522                                 if ( ! expr ) {
    1523                                         SemanticError(
    1524                                                 traitInst->params[i].get(), "Expression parameters for trait instances "
    1525                                                 "are currently unsupported: " );
    1526                                 }
    1527 
    1528                                 if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
    1529                                         if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
    1530                                                 // traitInst = ast::mutate_field_index(
    1531                                                 //      traitInst, &ast::TraitInstType::params, i,
    1532                                                 //      ...
    1533                                                 // );
    1534                                                 ast::TraitInstType * mut = ast::mutate( traitInst );
    1535                                                 ast::chain_mutate( mut->params[i] )
    1536                                                         ( &ast::TypeExpr::type )
    1537                                                                 ( &ast::TypeInstType::base )->sized = true;
    1538                                                 traitInst = mut;
    1539                                         }
    1540                                 }
    1541                         }
    1542 
    1543                         return traitInst;
    1544                 }
    1545 
    1546                 void previsit( const ast::QualifiedType * ) { visit_children = false; }
    1547 
    1548                 const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
    1549                         // linking only makes sense for the "oldest ancestor" of the qualified type
    1550                         return ast::mutate_field(
    1551                                 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) );
    1552                 }
    1553 
    1554                 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
    1555                         // visit enum members first so that the types of self-referencing members are updated
    1556                         // properly
    1557                         if ( ! enumDecl->body ) return enumDecl;
    1558 
    1559                         // update forward declarations to point here
    1560                         auto fwds = forwardEnums.equal_range( enumDecl->name );
    1561                         if ( fwds.first != fwds.second ) {
    1562                                 auto inst = fwds.first;
    1563                                 do {
    1564                                         // forward decl is stored * mutably * in map, can thus be updated
    1565                                         inst->second->base = enumDecl;
    1566                                 } while ( ++inst != fwds.second );
    1567                                 forwardEnums.erase( fwds.first, fwds.second );
    1568                         }
    1569 
    1570                         // ensure that enumerator initializers are properly set
    1571                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1572                                 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1573                                 if ( field->init ) {
    1574                                         // need to resolve enumerator initializers early so that other passes that
    1575                                         // determine if an expression is constexpr have appropriate information
    1576                                         auto init = field->init.strict_as< ast::SingleInit >();
    1577 
    1578                                         enumDecl = ast::mutate_field_index(
    1579                                                 enumDecl, &ast::EnumDecl::members, i,
    1580                                                 ast::mutate_field( field, &ast::ObjectDecl::init,
    1581                                                         ast::mutate_field( init, &ast::SingleInit::value,
    1582                                                                 ResolvExpr::findSingleExpression(
    1583                                                                         init->value, new ast::BasicType{ ast::BasicType::SignedInt },
    1584                                                                         symtab ) ) ) );
    1585                                 }
    1586                         }
    1587 
    1588                         return enumDecl;
    1589                 }
    1590 
    1591                 /// rename generic type parameters uniquely so that they do not conflict with user defined
    1592                 /// function forall parameters, e.g. the T in Box and the T in f, below
    1593                 ///   forall(otype T)
    1594                 ///   struct Box {
    1595                 ///     T x;
    1596                 ///   };
    1597                 ///   forall(otype T)
    1598                 ///   void f(Box(T) b) {
    1599                 ///     ...
    1600                 ///   }
    1601                 template< typename AggrDecl >
    1602                 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
    1603                         GuardValue( inGeneric );
    1604                         inGeneric = ! aggr->params.empty();
    1605 
    1606                         for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
    1607                                 const ast::TypeDecl * td = aggr->params[i];
    1608 
    1609                                 aggr = ast::mutate_field_index(
    1610                                         aggr, &AggrDecl::params, i,
    1611                                         ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
    1612                         }
    1613                         return aggr;
    1614                 }
    1615 
    1616                 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
    1617                         return renameGenericParams( structDecl );
    1618                 }
    1619 
    1620                 void postvisit( const ast::StructDecl * structDecl ) {
    1621                         // visit struct members first so that the types of self-referencing members are
    1622                         // updated properly
    1623                         if ( ! structDecl->body ) return;
    1624 
    1625                         // update forward declarations to point here
    1626                         auto fwds = forwardStructs.equal_range( structDecl->name );
    1627                         if ( fwds.first != fwds.second ) {
    1628                                 auto inst = fwds.first;
    1629                                 do {
    1630                                         // forward decl is stored * mutably * in map, can thus be updated
    1631                                         inst->second->base = structDecl;
    1632                                 } while ( ++inst != fwds.second );
    1633                                 forwardStructs.erase( fwds.first, fwds.second );
    1634                         }
    1635                 }
    1636 
    1637                 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
    1638                         return renameGenericParams( unionDecl );
    1639                 }
    1640 
    1641                 void postvisit( const ast::UnionDecl * unionDecl ) {
    1642                         // visit union members first so that the types of self-referencing members are updated
    1643                         // properly
    1644                         if ( ! unionDecl->body ) return;
    1645 
    1646                         // update forward declarations to point here
    1647                         auto fwds = forwardUnions.equal_range( unionDecl->name );
    1648                         if ( fwds.first != fwds.second ) {
    1649                                 auto inst = fwds.first;
    1650                                 do {
    1651                                         // forward decl is stored * mutably * in map, can thus be updated
    1652                                         inst->second->base = unionDecl;
    1653                                 } while ( ++inst != fwds.second );
    1654                                 forwardUnions.erase( fwds.first, fwds.second );
    1655                         }
    1656                 }
    1657 
    1658                 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
    1659                         // set the "sized" status for the special "sized" trait
    1660                         if ( traitDecl->name == "sized" ) {
    1661                                 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect "
    1662                                         "number of parameters: %zd", traitDecl->params.size() );
    1663 
    1664                                 traitDecl = ast::mutate_field_index(
    1665                                         traitDecl, &ast::TraitDecl::params, 0,
    1666                                         ast::mutate_field(
    1667                                                 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
    1668                         }
    1669 
    1670                         // move assertions from type parameters into the body of the trait
    1671                         std::vector< ast::ptr< ast::DeclWithType > > added;
    1672                         for ( const ast::TypeDecl * td : traitDecl->params ) {
    1673                                 for ( const ast::DeclWithType * assn : td->assertions ) {
    1674                                         auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1675                                         if ( inst ) {
    1676                                                 expandAssertions( inst, added );
    1677                                         } else {
    1678                                                 added.emplace_back( assn );
    1679                                         }
    1680                                 }
    1681                         }
    1682                         if ( ! added.empty() ) {
    1683                                 auto mut = mutate( traitDecl );
    1684                                 for ( const ast::DeclWithType * decl : added ) {
    1685                                         mut->members.emplace_back( decl );
    1686                                 }
    1687                                 traitDecl = mut;
    1688                         }
    1689 
    1690                         return traitDecl;
    1691                 }
    1692         };
    1693 
    1694         /// Replaces array and function types in forall lists by appropriate pointer type and assigns
    1695         /// each object and function declaration a unique ID
    1696         class ForallPointerDecay_new {
    1697                 const CodeLocation & location;
    1698         public:
    1699                 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {}
    1700 
    1701                 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) {
    1702                         // ensure that operator names only apply to functions or function pointers
    1703                         if (
    1704                                 CodeGen::isOperator( obj->name )
    1705                                 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() )
    1706                         ) {
    1707                                 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not "
    1708                                         "a function or function pointer." )  );
    1709                         }
    1710 
    1711                         // ensure object has unique ID
    1712                         if ( obj->uniqueId ) return obj;
    1713                         auto mut = mutate( obj );
    1714                         mut->fixUniqueId();
    1715                         return mut;
    1716                 }
    1717 
    1718                 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) {
    1719                         // ensure function has unique ID
    1720                         if ( func->uniqueId ) return func;
    1721                         auto mut = mutate( func );
    1722                         mut->fixUniqueId();
    1723                         return mut;
    1724                 }
    1725 
    1726                 /// Fix up assertions -- flattens assertion lists, removing all trait instances
    1727                 template< typename node_t, typename parent_t >
    1728                 static const node_t * forallFixer(
    1729                         const CodeLocation & loc, const node_t * node,
    1730                         ast::FunctionType::ForallList parent_t::* forallField
    1731                 ) {
    1732                         for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {
    1733                                 const ast::TypeDecl * type = (node->* forallField)[i];
    1734                                 if ( type->assertions.empty() ) continue;
    1735 
    1736                                 std::vector< ast::ptr< ast::DeclWithType > > asserts;
    1737                                 asserts.reserve( type->assertions.size() );
    1738 
    1739                                 // expand trait instances into their members
    1740                                 for ( const ast::DeclWithType * assn : type->assertions ) {
    1741                                         auto traitInst =
    1742                                                 dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1743                                         if ( traitInst ) {
    1744                                                 // expand trait instance to all its members
    1745                                                 expandAssertions( traitInst, asserts );
    1746                                         } else {
    1747                                                 // pass other assertions through
    1748                                                 asserts.emplace_back( assn );
    1749                                         }
    1750                                 }
    1751 
    1752                                 // apply FixFunction to every assertion to check for invalid void type
    1753                                 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) {
    1754                                         bool isVoid = false;
    1755                                         assn = fixFunction( assn, isVoid );
    1756                                         if ( isVoid ) {
    1757                                                 SemanticError( loc, node, "invalid type void in assertion of function " );
    1758                                         }
    1759                                 }
    1760 
    1761                                 // place mutated assertion list in node
    1762                                 auto mut = mutate( type );
    1763                                 mut->assertions = move( asserts );
    1764                                 node = ast::mutate_field_index( node, forallField, i, mut );
    1765                         }
    1766                         return node;
    1767                 }
    1768 
    1769                 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) {
    1770                         return forallFixer( location, ftype, &ast::FunctionType::forall );
    1771                 }
    1772 
    1773                 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) {
    1774                         return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params );
    1775                 }
    1776 
    1777                 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) {
    1778                         return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params );
    1779                 }
    1780         };
    1781         */
    1782 } // anonymous namespace
    1783 
    1784 /*
    1785 const ast::Type * validateType(
    1786                 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1787         // ast::Pass< EnumAndPointerDecay_new > epc;
    1788         ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    1789         ast::Pass< ForallPointerDecay_new > fpd{ loc };
    1790 
    1791         return type->accept( lrt )->accept( fpd );
    1792 }
    1793 */
    1794 
    17951321} // namespace SymTab
    17961322
  • src/SynTree/Declaration.h

    rb77f0e1 r63be3387  
    449449};
    450450
     451
     452class InlineMemberDecl : public DeclarationWithType {
     453        typedef DeclarationWithType Parent;
     454  public:
     455        Type * type;
     456
     457        InlineMemberDecl( const std::string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage, Type * type,
     458                                const std::list< Attribute * > attributes = std::list< Attribute * >(), Type::FuncSpecifiers fs = Type::FuncSpecifiers() );
     459        InlineMemberDecl( const InlineMemberDecl & other );
     460        virtual ~InlineMemberDecl();
     461
     462        virtual Type * get_type() const override { return type; }
     463        virtual void set_type(Type * newType) override { type = newType; }
     464
     465        static InlineMemberDecl * newInlineMemberDecl( const std::string & name, Type * type );
     466
     467        virtual InlineMemberDecl * clone() const override { return new InlineMemberDecl( *this ); }
     468        virtual void accept( Visitor & v ) override { v.visit( this ); }
     469        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     470        virtual DeclarationWithType * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
     471        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     472        virtual void printShort( std::ostream & os, Indenter indent = {} ) const override;
     473
     474};
     475
    451476std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data );
    452477
  • src/SynTree/Mutator.h

    rb77f0e1 r63be3387  
    3636        virtual DirectiveDecl * mutate( DirectiveDecl * directiveDecl ) = 0;
    3737        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) = 0;
     38        virtual DeclarationWithType * mutate( InlineMemberDecl * InlineMemberDecl ) = 0;
    3839
    3940        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) = 0;
  • src/SynTree/SynTree.h

    rb77f0e1 r63be3387  
    3838class DirectiveDecl;
    3939class StaticAssertDecl;
     40class InlineMemberDecl;
    4041
    4142class Statement;
  • src/SynTree/Visitor.h

    rb77f0e1 r63be3387  
    4949        virtual void visit( StaticAssertDecl * node ) { visit( const_cast<const StaticAssertDecl *>(node) ); }
    5050        virtual void visit( const StaticAssertDecl * assertDecl ) = 0;
     51        virtual void visit( InlineMemberDecl * node ) { visit( const_cast<const InlineMemberDecl *>(node) ); }
     52        virtual void visit( const InlineMemberDecl * valueDecl ) = 0;
    5153
    5254        virtual void visit( CompoundStmt * node ) { visit( const_cast<const CompoundStmt *>(node) ); }
  • src/SynTree/module.mk

    rb77f0e1 r63be3387  
    4242      SynTree/Initializer.cc \
    4343      SynTree/Initializer.h \
     44      SynTree/InlineMemberDecl.cc \
    4445      SynTree/Label.h \
    4546      SynTree/LinkageSpec.cc \
  • src/Validate/EnumAndPointerDecay.cpp

    rb77f0e1 r63be3387  
    2121#include "AST/Type.hpp"
    2222#include "SymTab/FixFunction.h"
     23#include "Validate/NoIdSymbolTable.hpp"
    2324
    2425namespace Validate {
     
    2627namespace {
    2728
    28 struct EnumAndPointerDecayCore final : public ast::WithCodeLocation {
     29struct EnumAndPointerDecayCore final : public WithNoIdSymbolTable, public ast::WithCodeLocation {
    2930        ast::EnumDecl const * previsit( ast::EnumDecl const * decl );
    3031        ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl );
     
    3940        // Set the type of each member of the enumeration to be EnumContant.
    4041        auto mut = ast::mutate( decl );
    41         for ( ast::ptr<ast::Decl> & member : mut->members ) {
    42                 ast::ObjectDecl const * object = member.strict_as<ast::ObjectDecl>();
    43                 member = ast::mutate_field( object, &ast::ObjectDecl::type,
    44                         new ast::EnumInstType( decl, ast::CV::Const ) );
     42        std::vector<ast::ptr<ast::Decl>> buffer;
     43        for ( auto member : decl->members ) {
     44                if ( ast::ObjectDecl const * object = member.as<ast::ObjectDecl>() ) {
     45                        buffer.push_back( ast::mutate_field( object,
     46                                &ast::ObjectDecl::type,
     47                                new ast::EnumInstType( decl, ast::CV::Const ) ) );
     48                } else if ( auto value = member.as<ast::InlineMemberDecl>() ) {
     49                        if ( auto targetEnum = symtab.lookupEnum( value->name ) ) {
     50                                for ( auto enumMember : targetEnum->members ) {
     51                                        auto enumObject = enumMember.strict_as<ast::ObjectDecl>();
     52                                        buffer.push_back( new ast::ObjectDecl(
     53                                                // Get the location from the "inline" declaration.
     54                                                value->location,
     55                                                enumObject->name,
     56                                                // Construct a new EnumInstType as the type.
     57                                                new ast::EnumInstType( decl, ast::CV::Const ),
     58                                                enumObject->init,
     59                                                enumObject->storage,
     60                                                enumObject->linkage,
     61                                                enumObject->bitfieldWidth,
     62                                                {},
     63                                                enumObject->funcSpec
     64                                        ) );
     65                                }
     66                        }
     67                }
    4568        }
     69        mut->members = buffer;
    4670        return mut;
    4771}
  • src/Validate/LinkReferenceToTypes.cpp

    rb77f0e1 r63be3387  
    185185                                decl = mut;
    186186                        }
     187                        // visit the base
    187188                } else if ( auto ptr = decl->base.as<ast::PointerType>() ) {
    188189                        if ( auto base = ptr->base.as<ast::TypeInstType>() ) {
     
    203204
    204205        // The following section
    205         auto mut = ast::mutate( decl );
    206         std::vector<ast::ptr<ast::Decl>> buffer;
    207         for ( auto it = decl->members.begin(); it != decl->members.end(); ++it) {
    208                 auto member = (*it).as<ast::ObjectDecl>();
    209                 if ( member->enumInLine ) {
    210                         auto targetEnum = symtab.lookupEnum( member->name );
    211                         if ( targetEnum ) {                     
    212                                 for ( auto singleMamber : targetEnum->members ) {
    213                                         auto tm = singleMamber.as<ast::ObjectDecl>();
    214                                         auto t = new ast::ObjectDecl(
    215                                                 member->location, // use the "inline" location
    216                                                 tm->name,
    217                                                 new ast::EnumInstType( decl, ast::CV::Const ),
    218                                                 // Construct a new EnumInstType as the type
    219                                                 tm->init,
    220                                                 tm->storage,
    221                                                 tm->linkage,
    222                                                 tm->bitfieldWidth,
    223                                                 {}, // enum member doesn't have attribute
    224                                                 tm->funcSpec
    225                                         );
    226                                         t->importValue = true;
    227                                         buffer.push_back(t);
    228                                 }
    229                         }
    230                 } else {
    231                         auto search_it = std::find_if( buffer.begin(), buffer.end(), [member](ast::ptr<ast::Decl> cur) {
    232                                 auto curAsObjDecl = cur.as<ast::ObjectDecl>();
    233                                 return (curAsObjDecl->importValue) && (curAsObjDecl->name == member->name);
    234                         });
    235                         if ( search_it != buffer.end() ) {
    236                                 buffer.erase( search_it ); // Found an import enum value that has the same name
    237                                 // override the imported value
    238                         }
    239                         buffer.push_back( *it );
    240                 }
    241         }
    242         mut->members = buffer;
    243         decl = mut;
    244206
    245207        ForwardEnumsType::iterator fwds = forwardEnums.find( decl->name );
  • src/Virtual/ExpandCasts.cc

    rb77f0e1 r63be3387  
    295295        // returns the previous declaration for error messages.
    296296        ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) {
    297                 std::string const & mangledName =
    298                                 Mangle::mangle( typeIdDecl->type, Mangle::typeMode() );
     297                std::string mangledName = Mangle::mangleType( typeIdDecl->type );
    299298                ast::ObjectDecl const *& value = instances[ mangledName ];
    300299                if ( value ) {
     
    310309
    311310        ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) {
    312                 std::string const & mangledName =
    313                                 Mangle::mangle( typeIdType, Mangle::typeMode() );
     311                std::string mangledName = Mangle::mangleType( typeIdType );
    314312                auto const it = instances.find( mangledName );
    315313                return ( instances.end() == it ) ? nullptr : it->second;
Note: See TracChangeset for help on using the changeset viewer.