Changeset b067d9b for src/SymTab


Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (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/SymTab
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    r7951100 rb067d9b  
    2424#include <vector>                  // for vector
    2525
     26#include "AST/Decl.hpp"
    2627#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2728#include "Common/PassVisitor.h"    // for PassVisitor
     
    4142
    4243namespace SymTab {
    43         Type * SizeType = 0;
    44 
    4544        /// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
    4645        struct FuncData {
    47                 typedef FunctionType * (*TypeGen)( Type * );
     46                typedef FunctionType * (*TypeGen)( Type *, bool );
    4847                FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
    4948                std::string fname;
     
    211210        }
    212211
     212        bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
     213                return obj && obj->name.empty() && obj->bitfieldWidth;
     214        }
     215
    213216        /// inserts a forward declaration for functionDecl into declsToAdd
    214217        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     
    231234
    232235        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    233         FunctionType * genDefaultType( Type * paramType ) {
    234                 const auto & typeParams = getGenericParams( paramType );
     236        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
    235237                FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
    236                 cloneAll( typeParams, ftype->forall );
     238                if ( maybePolymorphic ) {
     239                        // only copy in
     240                        const auto & typeParams = getGenericParams( paramType );
     241                        cloneAll( typeParams, ftype->forall );
     242                }
    237243                ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
    238244                ftype->parameters.push_back( dstParam );
     
    241247
    242248        /// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
    243         FunctionType * genCopyType( Type * paramType ) {
    244                 FunctionType *ftype = genDefaultType( paramType );
     249        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
     250                FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
    245251                ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    246252                ftype->parameters.push_back( srcParam );
     
    249255
    250256        /// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
    251         FunctionType * genAssignType( Type * paramType ) {
    252                 FunctionType *ftype = genCopyType( paramType );
     257        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
     258                FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
    253259                ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
    254260                ftype->returnVals.push_back( returnVal );
     
    308314                for ( const FuncData & d : data ) {
    309315                        // generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
    310                         FunctionType * ftype = d.genType( type );
     316                        FunctionType * ftype = d.genType( type, true );
    311317
    312318                        // destructor for concurrent type must be mutex
     
    387393
    388394        void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
    389                 InitTweak::InitExpander srcParam( src );
     395                InitTweak::InitExpander_old srcParam( src );
    390396
    391397                // assign to destination
  • src/SymTab/Autogen.h

    r7951100 rb067d9b  
    1717
    1818#include <cassert>                // for assert
     19#include <iterator>               // for back_inserter
    1920#include <string>                 // for string
    2021
     22#include "AST/Decl.hpp"
     23#include "AST/Expr.hpp"
     24#include "AST/Init.hpp"
     25#include "AST/Node.hpp"
     26#include "AST/Stmt.hpp"
     27#include "AST/Type.hpp"
    2128#include "CodeGen/OperatorTable.h"
    2229#include "Common/UniqueName.h"    // for UniqueName
     30#include "Common/utility.h"       // for splice
    2331#include "InitTweak/InitTweak.h"  // for InitExpander
    2432#include "SynTree/Constant.h"     // for Constant
     
    3644        /// returns true if obj's name is the empty string and it has a bitfield width
    3745        bool isUnnamedBitfield( ObjectDecl * obj );
    38 
    39         /// size_t type - set when size_t typedef is seen. Useful in a few places,
    40         /// such as in determining array dimension type
    41         extern Type * SizeType;
    42 
    43         /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
    44         /// Useful for creating dereference ApplicationExprs without a full resolver pass.
    45         extern FunctionDecl * dereferenceOperator;
    46 
    47         // generate the type of an assignment function for paramType
    48         FunctionType * genAssignType( Type * paramType );
    49 
    50         // generate the type of a default constructor or destructor for paramType
    51         FunctionType * genDefaultType( Type * paramType );
    52 
    53         // generate the type of a copy constructor for paramType
    54         FunctionType * genCopyType( Type * paramType );
     46        bool isUnnamedBitfield( const ast::ObjectDecl * obj );
     47
     48        /// generate the type of an assignment function for paramType.
     49        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     50        FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
     51
     52        /// generate the type of a default constructor or destructor for paramType.
     53        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     54        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
     55
     56        /// generate the type of a copy constructor for paramType.
     57        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     58        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
     59
     60        /// Enum for loop direction
     61        enum LoopDirection { LoopBackward, LoopForward };
    5562
    5663        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5764        template< typename OutputIterator >
    58         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
     65        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
     66
     67        template< typename OutIter >
     68        ast::ptr< ast::Stmt > genCall(
     69                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     70                const CodeLocation & loc, const std::string & fname, OutIter && out,
     71                const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
    5972
    6073        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
    6174        /// optionally returns a statement which must be inserted prior to the containing loop, if there is one
    6275        template< typename OutputIterator >
    63         Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
     76        Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
    6477                bool isReferenceCtorDtor = false;
    6578                if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     
    8497                        //   type->get_qualifiers() = Type::Qualifiers();
    8598                        Type * castType = addCast->clone();
    86                         castType->get_qualifiers() -= Type::Qualifiers( Type::Lvalue | Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     99                        castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    87100                        // castType->set_lvalue( true ); // xxx - might not need this
    88101                        dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
     
    111124        }
    112125
     126        /// inserts into out a generated call expression to function fname with arguments dstParam and
     127        /// srcParam. Should only be called with non-array types.
     128        /// optionally returns a statement which must be inserted prior to the containing loop, if
     129        /// there is one
     130        template< typename OutIter >
     131        ast::ptr< ast::Stmt > genScalarCall(
     132                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     133                const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
     134                const ast::Type * addCast = nullptr
     135        ) {
     136                bool isReferenceCtorDtor = false;
     137                if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     138                        // reference constructors are essentially application of the rebind operator.
     139                        // apply & to both arguments, do not need a cast
     140                        fname = "?=?";
     141                        dstParam = new ast::AddressExpr{ dstParam };
     142                        addCast = nullptr;
     143                        isReferenceCtorDtor = true;
     144                }
     145
     146                // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
     147                // "?=?", "?{}", or "^?{}"
     148                ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
     149
     150                if ( addCast ) {
     151                        // cast to T& with qualifiers removed, so that qualified objects can be constructed and
     152                        // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
     153                        // is considered a qualifier - for AddressExpr to resolve, its argument must have an
     154                        // lvalue-qualified type, so remove all qualifiers except lvalue.
     155                        // xxx -- old code actually removed lvalue too...
     156                        ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
     157                        ast::ptr< ast::Type > castType = addCast;
     158                        ast::remove_qualifiers(
     159                                castType,
     160                                ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
     161                        dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
     162                }
     163                fExpr->args.emplace_back( dstParam );
     164
     165                const ast::Stmt * listInit = srcParam.buildListInit( fExpr );
     166
     167                // fetch next set of arguments
     168                ++srcParam;
     169
     170                // return if adding reference fails -- will happen on default ctor and dtor
     171                if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
     172
     173                std::vector< ast::ptr< ast::Expr > > args = *srcParam;
     174                splice( fExpr->args, args );
     175
     176                *out++ = new ast::ExprStmt{ loc, fExpr };
     177
     178                srcParam.clearArrayIndices();
     179               
     180                return listInit;
     181        }
     182
    113183        /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
    114184        /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
    115185        template< typename OutputIterator >
    116         void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
     186        void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
    117187                static UniqueName indexName( "_index" );
    118188
     
    175245        }
    176246
     247        /// Store in out a loop which calls fname on each element of the array with srcParam and
     248        /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
     249        template< typename OutIter >
     250        void genArrayCall(
     251                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     252                const CodeLocation & loc, const std::string & fname, OutIter && out,
     253                const ast::ArrayType * array, const ast::Type * addCast = nullptr,
     254                LoopDirection forward = LoopForward
     255        ) {
     256                static UniqueName indexName( "_index" );
     257
     258                // for a flexible array member nothing is done -- user must define own assignment
     259                if ( ! array->dimension ) return;
     260
     261                if ( addCast ) {
     262                        // peel off array layer from cast
     263                        addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
     264                }
     265
     266                ast::ptr< ast::Expr > begin, end, cmp, update;
     267
     268                if ( forward ) {
     269                        // generate: for ( int i = 0; i < N; ++i )
     270                        begin = ast::ConstantExpr::from_int( loc, 0 );
     271                        end = array->dimension;
     272                        cmp = new ast::NameExpr{ loc, "?<?" };
     273                        update = new ast::NameExpr{ loc, "++?" };
     274                } else {
     275                        // generate: for ( int i = N-1; i >= 0; --i )
     276                        begin = new ast::UntypedExpr{
     277                                loc, new ast::NameExpr{ loc, "?-?" },
     278                                { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
     279                        end = ast::ConstantExpr::from_int( loc, 0 );
     280                        cmp = new ast::NameExpr{ loc, "?>=?" };
     281                        update = new ast::NameExpr{ loc, "--?" };
     282                }
     283
     284                ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
     285                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
     286                        new ast::SingleInit{ loc, begin } };
     287               
     288                ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
     289                        loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
     290               
     291                ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
     292                        loc, update, { new ast::VariableExpr{ loc, index } } };
     293               
     294                ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
     295                        loc, new ast::NameExpr{ loc, "?[?]" },
     296                        { dstParam, new ast::VariableExpr{ loc, index } } };
     297               
     298                // srcParam must keep track of the array indices to build the source parameter and/or
     299                // array list initializer
     300                srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
     301
     302                // for stmt's body, eventually containing call
     303                ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
     304                ast::ptr< ast::Stmt > listInit = genCall(
     305                        srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
     306                        forward );
     307               
     308                // block containing the stmt and index variable
     309                ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
     310                block->push_back( new ast::DeclStmt{ loc, index } );
     311                if ( listInit ) { block->push_back( listInit ); }
     312                block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
     313
     314                *out++ = block;
     315        }
     316
    177317        template< typename OutputIterator >
    178         Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     318        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
    179319                if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    180320                        genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
     
    185325        }
    186326
     327        template< typename OutIter >
     328        ast::ptr< ast::Stmt > genCall(
     329                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     330                const CodeLocation & loc, const std::string & fname, OutIter && out,
     331                const ast::Type * type, const ast::Type * addCast, LoopDirection forward
     332        ) {
     333                if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     334                        genArrayCall(
     335                                srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
     336                                forward );
     337                        return {};
     338                } else {
     339                        return genScalarCall(
     340                                srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
     341                }
     342        }
     343
    187344        /// inserts into out a generated call expression to function fname with arguments dstParam
    188345        /// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
     
    190347        /// ImplicitCtorDtorStmt node.
    191348        template< typename OutputIterator >
    192         void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
     349        void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
    193350                ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
    194351                assert( obj );
     
    218375                }
    219376        }
     377
     378        static inline ast::ptr< ast::Stmt > genImplicitCall(
     379                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     380                const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
     381                LoopDirection forward = LoopForward
     382        ) {
     383                // unnamed bit fields are not copied as they cannot be accessed
     384                if ( isUnnamedBitfield( obj ) ) return {};
     385
     386                ast::ptr< ast::Type > addCast = nullptr;
     387                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
     388                        assert( dstParam->result );
     389                        addCast = dstParam->result;
     390                }
     391
     392                std::vector< ast::ptr< ast::Stmt > > stmts;
     393                genCall(
     394                        srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
     395
     396                if ( stmts.empty() ) {
     397                        return {};
     398                } else if ( stmts.size() == 1 ) {
     399                        const ast::Stmt * callStmt = stmts.front();
     400                        if ( addCast ) {
     401                                // implicitly generated ctor/dtor calls should be wrapped so that later passes are
     402                                // aware they were generated.
     403                                callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
     404                        }
     405                        return callStmt;
     406                } else {
     407                        assert( false );
     408                        return {};
     409                }
     410        }
    220411} // namespace SymTab
    221412
  • src/SymTab/FixFunction.cc

    r7951100 rb067d9b  
    1818#include <list>                   // for list
    1919
    20 #include "Common/utility.h"       // for maybeClone
     20#include "AST/Decl.hpp"
     21#include "AST/Pass.hpp"
     22#include "AST/Type.hpp"
     23#include "Common/utility.h"       // for maybeClone, copy
    2124#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    2225#include "SynTree/Expression.h"   // for Expression
     
    2427
    2528namespace SymTab {
    26         FixFunction::FixFunction() : isVoid( false ) {}
     29        class FixFunction_old : public WithShortCircuiting {
     30                typedef Mutator Parent;
     31          public:
     32                FixFunction_old() : isVoid( false ) {}
    2733
     34                void premutate(FunctionDecl *functionDecl);
     35                DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    2836
    29         DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
     37                Type * postmutate(ArrayType * arrayType);
     38
     39                void premutate(ArrayType * arrayType);
     40                void premutate(VoidType * voidType);
     41                void premutate(BasicType * basicType);
     42                void premutate(PointerType * pointerType);
     43                void premutate(StructInstType * aggregateUseType);
     44                void premutate(UnionInstType * aggregateUseType);
     45                void premutate(EnumInstType * aggregateUseType);
     46                void premutate(TraitInstType * aggregateUseType);
     47                void premutate(TypeInstType * aggregateUseType);
     48                void premutate(TupleType * tupleType);
     49                void premutate(VarArgsType * varArgsType);
     50                void premutate(ZeroType * zeroType);
     51                void premutate(OneType * oneType);
     52
     53                bool isVoid;
     54        };
     55
     56        DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
    3057                // can't delete function type because it may contain assertions, so transfer ownership to new object
    3158                ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
     59                pointer->location = functionDecl->location;
    3260                functionDecl->attributes.clear();
    3361                functionDecl->type = nullptr;
     
    4068        // does not cause an error
    4169
    42         Type * FixFunction::postmutate(ArrayType *arrayType) {
     70        Type * FixFunction_old::postmutate(ArrayType *arrayType) {
    4371                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    4472                PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
     73                pointerType->location = arrayType->location;
    4574                arrayType->base = nullptr;
    4675                arrayType->dimension = nullptr;
     
    4978        }
    5079
    51         void FixFunction::premutate(VoidType *) {
     80        void FixFunction_old::premutate(VoidType *) {
    5281                isVoid = true;
    5382        }
    5483
    55         void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
    56         void FixFunction::premutate(ArrayType *) { visit_children = false; }
    57         void FixFunction::premutate(BasicType *) { visit_children = false; }
    58         void FixFunction::premutate(PointerType *) { visit_children = false; }
    59         void FixFunction::premutate(StructInstType *) { visit_children = false; }
    60         void FixFunction::premutate(UnionInstType *) { visit_children = false; }
    61         void FixFunction::premutate(EnumInstType *) { visit_children = false; }
    62         void FixFunction::premutate(TraitInstType *) { visit_children = false; }
    63         void FixFunction::premutate(TypeInstType *) { visit_children = false; }
    64         void FixFunction::premutate(TupleType *) { visit_children = false; }
    65         void FixFunction::premutate(VarArgsType *) { visit_children = false; }
    66         void FixFunction::premutate(ZeroType *) { visit_children = false; }
    67         void FixFunction::premutate(OneType *) { visit_children = false; }
     84        void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
     85        void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
     86        void FixFunction_old::premutate(BasicType *) { visit_children = false; }
     87        void FixFunction_old::premutate(PointerType *) { visit_children = false; }
     88        void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
     89        void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
     90        void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
     91        void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
     92        void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
     93        void FixFunction_old::premutate(TupleType *) { visit_children = false; }
     94        void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
     95        void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
     96        void FixFunction_old::premutate(OneType *) { visit_children = false; }
    6897
    6998        bool fixFunction( DeclarationWithType *& dwt ) {
    70                 PassVisitor<FixFunction> fixer;
     99                PassVisitor<FixFunction_old> fixer;
    71100                dwt = dwt->acceptMutator( fixer );
    72101                return fixer.pass.isVoid;
    73102        }
     103
     104namespace {
     105        struct FixFunction_new final : public ast::WithShortCircuiting {
     106                bool isVoid = false;
     107
     108                void premutate( const ast::FunctionDecl * ) { visit_children = false; }
     109
     110                const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
     111                        return new ast::ObjectDecl{
     112                                func->location, func->name, new ast::PointerType{ func->type }, nullptr,
     113                                func->storage, func->linkage, nullptr, copy( func->attributes ) };
     114                }
     115
     116                void premutate( const ast::ArrayType * ) { visit_children = false; }
     117
     118                const ast::Type * postmutate( const ast::ArrayType * array ) {
     119                        return new ast::PointerType{
     120                                array->base, array->dimension, array->isVarLen, array->isStatic,
     121                                array->qualifiers };
     122                }
     123
     124                void premutate( const ast::VoidType * ) { isVoid = true; }
     125
     126                void premutate( const ast::BasicType * ) { visit_children = false; }
     127                void premutate( const ast::PointerType * ) { visit_children = false; }
     128                void premutate( const ast::StructInstType * ) { visit_children = false; }
     129                void premutate( const ast::UnionInstType * ) { visit_children = false; }
     130                void premutate( const ast::EnumInstType * ) { visit_children = false; }
     131                void premutate( const ast::TraitInstType * ) { visit_children = false; }
     132                void premutate( const ast::TypeInstType * ) { visit_children = false; }
     133                void premutate( const ast::TupleType * ) { visit_children = false; }
     134                void premutate( const ast::VarArgsType * ) { visit_children = false; }
     135                void premutate( const ast::ZeroType * ) { visit_children = false; }
     136                void premutate( const ast::OneType * ) { visit_children = false; }
     137        };
     138} // anonymous namespace
     139
     140const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) {
     141        ast::Pass< FixFunction_new > fixer;
     142        dwt = dwt->accept( fixer );
     143        isVoid |= fixer.pass.isVoid;
     144        return dwt;
     145}
     146
    74147} // namespace SymTab
    75148
  • src/SymTab/FixFunction.h

    r7951100 rb067d9b  
    1919#include "SynTree/SynTree.h"    // for Types
    2020
     21namespace ast {
     22        class DeclWithType;
     23}
     24
    2125namespace SymTab {
    22         /// Replaces function and array types by equivalent pointer types.
    23         class FixFunction : public WithShortCircuiting {
    24                 typedef Mutator Parent;
    25           public:
    26                 FixFunction();
     26        /// Replaces function and array types by equivalent pointer types. Returns true if type is
     27        /// void
     28        bool fixFunction( DeclarationWithType *& );
    2729
    28                 void premutate(FunctionDecl *functionDecl);
    29                 DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    30 
    31                 Type * postmutate(ArrayType * arrayType);
    32 
    33                 void premutate(ArrayType * arrayType);
    34                 void premutate(VoidType * voidType);
    35                 void premutate(BasicType * basicType);
    36                 void premutate(PointerType * pointerType);
    37                 void premutate(StructInstType * aggregateUseType);
    38                 void premutate(UnionInstType * aggregateUseType);
    39                 void premutate(EnumInstType * aggregateUseType);
    40                 void premutate(TraitInstType * aggregateUseType);
    41                 void premutate(TypeInstType * aggregateUseType);
    42                 void premutate(TupleType * tupleType);
    43                 void premutate(VarArgsType * varArgsType);
    44                 void premutate(ZeroType * zeroType);
    45                 void premutate(OneType * oneType);
    46 
    47                 bool isVoid;
    48         };
    49 
    50         bool fixFunction( DeclarationWithType *& );
     30        /// Returns declaration with function and array types replaced by equivalent pointer types.
     31        /// Sets isVoid to true if type is void
     32        const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid );
    5133} // namespace SymTab
    5234
  • src/SymTab/Indexer.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:37:33 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 17 16:08:40 2017
    13 // Update Count     : 20
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Mar  8 13:55:00 2019
     13// Update Count     : 21
    1414//
    1515
     
    1717
    1818#include <cassert>                 // for assert, strict_dynamic_cast
    19 #include <iostream>                // for operator<<, basic_ostream, ostream
    2019#include <string>                  // for string, operator<<, operator!=
     20#include <memory>                  // for shared_ptr, make_shared
    2121#include <unordered_map>           // for operator!=, unordered_map<>::const...
    2222#include <unordered_set>           // for unordered_set
    2323#include <utility>                 // for pair, make_pair, move
     24#include <vector>                  // for vector
    2425
    2526#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
    2627#include "Common/SemanticError.h"  // for SemanticError
    2728#include "Common/utility.h"        // for cloneAll
    28 #include "GenPoly/GenPoly.h"
     29#include "Common/Stats/Counter.h"  // for counters
     30#include "GenPoly/GenPoly.h"       // for getFunctionType
    2931#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
    3032#include "Mangler.h"               // for Mangler
     
    3840#include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
    3941
    40 #define debugPrint(x) if ( doDebug ) { std::cerr << x; }
    41 
    4242namespace SymTab {
    43         std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) {
    44                 return out << "(" << data.id << "," << data.baseExpr << ")";
    45         }
    46 
    47         typedef std::unordered_map< std::string, Indexer::IdData > MangleTable;
    48         typedef std::unordered_map< std::string, MangleTable > IdTable;
    49         typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
    50         typedef std::unordered_map< std::string, StructDecl* > StructTable;
    51         typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
    52         typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
    53         typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
    54 
    55         void dump( const IdTable &table, std::ostream &os ) {
    56                 for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) {
    57                         for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) {
    58                                 os << mangle->second << std::endl;
    59                         }
    60                 }
    61         }
    62 
    63         template< typename Decl >
    64         void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
    65                 for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
    66                         os << it->second << std::endl;
    67                 } // for
    68         }
    69 
    70         struct Indexer::Impl {
    71                 Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
    72                                 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
    73                 Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
    74                                 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
    75                 unsigned long refCount;   ///< Number of references to these tables
    76                 unsigned long scope;      ///< Scope these tables are associated with
    77                 unsigned long size;       ///< Number of elements stored in this table
    78                 const Indexer base;       ///< Base indexer this extends
    79 
    80                 IdTable idTable;          ///< Identifier namespace
    81                 TypeTable typeTable;      ///< Type namespace
    82                 StructTable structTable;  ///< Struct namespace
    83                 EnumTable enumTable;      ///< Enum namespace
    84                 UnionTable unionTable;    ///< Union namespace
    85                 TraitTable traitTable;    ///< Trait namespace
    86         };
    87 
    88         Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
    89                 if ( ! toClone ) return 0;
    90 
    91                 // shorten the search chain by skipping empty links
    92                 Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
    93                 if ( ret ) { ++ret->refCount; }
    94 
    95                 return ret;
    96         }
    97 
    98         void Indexer::deleteRef( Indexer::Impl *toFree ) {
    99                 if ( ! toFree ) return;
    100 
    101                 if ( --toFree->refCount == 0 ) delete toFree;
    102         }
    103 
    104         void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const {
    105                 // only need to perform this step for constructors, destructors, and assignment functions
    106                 if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
    107 
    108                 // helpful data structure to organize properties for a type
    109                 struct ValueType {
    110                         struct DeclBall { // properties for this particular decl
    111                                 IdData decl;
    112                                 bool isUserDefinedFunc;
    113                                 bool isCopyFunc;
     43
     44        // Statistics block
     45        namespace {
     46                static inline auto stats() {
     47                        using namespace Stats::Counters;
     48                        static auto group   = build<CounterGroup>("Indexers");
     49                        static struct {
     50                                SimpleCounter * count;
     51                                AverageCounter<double> * size;
     52                                SimpleCounter * new_scopes;
     53                                SimpleCounter * lazy_scopes;
     54                                AverageCounter<double> * avg_scope_depth;
     55                                MaxCounter<size_t> * max_scope_depth;
     56                                SimpleCounter * add_calls;
     57                                SimpleCounter * lookup_calls;
     58                                SimpleCounter * map_lookups;
     59                                SimpleCounter * map_mutations;
     60                        } ret = {
     61                                .count   = build<SimpleCounter>("Count", group),
     62                                .size    = build<AverageCounter<double>>("Average Size", group),
     63                                .new_scopes = build<SimpleCounter>("Scopes", group),
     64                                .lazy_scopes = build<SimpleCounter>("Lazy Scopes", group),
     65                                .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group),
     66                                .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group),
     67                                .add_calls = build<SimpleCounter>("Add Calls", group),
     68                                .lookup_calls = build<SimpleCounter>("Lookup Calls", group),
     69                                .map_lookups = build<SimpleCounter>("Map Lookups", group),
     70                                .map_mutations = build<SimpleCounter>("Map Mutations", group)
    11471                        };
    115                         // properties for this type
    116                         bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
    117                         BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
    118                         std::list< DeclBall > decls;
    119 
    120                         // another FunctionDecl for the current type was found - determine
    121                         // if it has special properties and update data structure accordingly
    122                         ValueType & operator+=( IdData data ) {
    123                                 DeclarationWithType * function = data.id;
    124                                 bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
    125                                 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
    126                                 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
    127                                 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    128                                 if ( isUserDefinedFunc && ! data.deleteStmt ) {
    129                                         // any user-defined function can act as an implicit delete statement for generated constructors.
    130                                         // a delete stmt should not act as an implicit delete statement.
    131                                         deleteStmt = data.id;
    132                                 }
    133                                 return *this;
    134                         }
    135                 }; // ValueType
    136 
    137                 std::list< IdData > copy;
    138                 copy.splice( copy.end(), out );
    139 
    140                 // organize discovered declarations by type
    141                 std::unordered_map< std::string, ValueType > funcMap;
    142                 for ( auto decl : copy ) {
    143                         if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
    144                                 std::list< DeclarationWithType * > & params = function->type->parameters;
    145                                 assert( ! params.empty() );
    146                                 // use base type of pointer, so that qualifiers on the pointer type aren't considered.
    147                                 Type * base = InitTweak::getPointerBase( params.front()->get_type() );
    148                                 assert( base );
    149                                 funcMap[ Mangler::mangle( base ) ] += decl;
    150                         } else {
    151                                 out.push_back( decl );
    152                         }
    153                 }
    154 
    155                 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
    156                 // the set of ctor/dtor/assign that can be used  by the requester. In particular, if the user defines
    157                 // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor
    158                 // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available.
    159                 // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default
    160                 // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor,
    161                 // then the generated copy constructor is unavailable, and likewise for the assignment operator.
    162                 for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    163                         ValueType & val = pair.second;
    164                         for ( ValueType::DeclBall ball : val.decls ) {
    165                                 bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
    166                                 bool isCopyFunc = ball.isCopyFunc;
    167                                 bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
    168                                 // only implicitly delete non-user defined functions that are  not intrinsic, and are
    169                                 // not copy functions (assignment or copy constructor), unless a user-defined copy function exists.
    170                                 // deleteStmt will be non-null only if a user-defined function is found.
    171                                 if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) {
    172                                         ball.decl.deleteStmt = val.deleteStmt;
    173                                 }
    174                                 out.push_back( ball.decl );
    175                         }
    176                 }
    177         }
    178 
    179         void Indexer::makeWritable() {
    180                 if ( ! tables ) {
    181                         // create indexer if not yet set
    182                         tables = new Indexer::Impl( scope );
    183                 } else if ( tables->refCount > 1 || tables->scope != scope ) {
    184                         // make this indexer the base of a fresh indexer at the current scope
    185                         tables = new Indexer::Impl( scope, std::move( *this ) );
    186                 }
    187         }
    188 
    189         Indexer::Indexer() : tables( 0 ), scope( 0 ) {}
    190 
    191         Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {}
    192 
    193         Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) {
    194                 that.tables = 0;
    195         }
     72                        return ret;
     73                }
     74        }
     75
     76        Indexer::Indexer()
     77        : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
     78          prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }
    19679
    19780        Indexer::~Indexer() {
    198                 deleteRef( tables );
    199         }
    200 
    201         Indexer& Indexer::operator= ( const Indexer &that ) {
    202                 deleteRef( tables );
    203 
    204                 tables = newRef( that.tables );
    205                 scope = that.scope;
    206                 doDebug = that.doDebug;
    207 
    208                 return *this;
    209         }
    210 
    211         Indexer& Indexer::operator= ( Indexer &&that ) {
    212                 deleteRef( tables );
    213 
    214                 tables = that.tables;
    215                 scope = that.scope;
    216                 doDebug = that.doDebug;
    217 
    218                 that.tables = 0;
    219 
    220                 return *this;
    221         }
    222 
    223         void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const {
    224                 std::unordered_set< std::string > foundMangleNames;
    225 
    226                 Indexer::Impl *searchTables = tables;
    227                 while ( searchTables ) {
    228 
    229                         IdTable::const_iterator decls = searchTables->idTable.find( id );
    230                         if ( decls != searchTables->idTable.end() ) {
    231                                 const MangleTable &mangleTable = decls->second;
    232                                 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    233                                         // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found
    234                                         if ( foundMangleNames.insert( decl->first ).second == false ) continue;
    235 
    236                                         out.push_back( decl->second );
    237                                 }
    238                         }
    239 
    240                         // get declarations from base indexers
    241                         searchTables = searchTables->base.tables;
    242                 }
    243 
    244                 // some special functions, e.g. constructors and destructors
    245                 // remove autogenerated functions when they are defined so that
    246                 // they can never be matched
    247                 removeSpecialOverrides( id, out );
    248         }
    249 
    250         NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
    251                 if ( ! tables ) return 0;
    252 
    253                 TypeTable::const_iterator ret = tables->typeTable.find( id );
    254                 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
    255         }
    256 
    257         StructDecl *Indexer::lookupStruct( const std::string &id ) const {
    258                 if ( ! tables ) return 0;
    259 
    260                 StructTable::const_iterator ret = tables->structTable.find( id );
    261                 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
    262         }
    263 
    264         EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
    265                 if ( ! tables ) return 0;
    266 
    267                 EnumTable::const_iterator ret = tables->enumTable.find( id );
    268                 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
    269         }
    270 
    271         UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
    272                 if ( ! tables ) return 0;
    273 
    274                 UnionTable::const_iterator ret = tables->unionTable.find( id );
    275                 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
    276         }
    277 
    278         TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
    279                 if ( ! tables ) return 0;
    280 
    281                 TraitTable::const_iterator ret = tables->traitTable.find( id );
    282                 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
    283         }
    284 
    285         const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    286                 if ( ! tables ) return nullptr;
    287                 if ( tables->scope < scope ) return nullptr;
    288 
    289                 IdTable::const_iterator decls = tables->idTable.find( id );
    290                 if ( decls != tables->idTable.end() ) {
    291                         const MangleTable &mangleTable = decls->second;
    292                         MangleTable::const_iterator decl = mangleTable.find( mangleName );
    293                         if ( decl != mangleTable.end() ) return &decl->second;
    294                 }
    295 
    296                 return tables->base.lookupIdAtScope( id, mangleName, scope );
    297         }
    298 
    299         Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) {
    300                 return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope ));
    301         }
    302 
    303         bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    304                 if ( ! tables ) return false;
    305                 if ( tables->scope < scope ) return false;
    306 
    307                 IdTable::const_iterator decls = tables->idTable.find( id );
    308                 if ( decls != tables->idTable.end() ) {
    309                         const MangleTable &mangleTable = decls->second;
    310                         for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    311                                 // check for C decls with the same name, skipping those with a compatible type (by mangleName)
    312                                 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true;
    313                         }
    314                 }
    315 
    316                 return tables->base.hasIncompatibleCDecl( id, mangleName, scope );
    317         }
    318 
    319         bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    320                 if ( ! tables ) return false;
    321                 if ( tables->scope < scope ) return false;
    322 
    323                 IdTable::const_iterator decls = tables->idTable.find( id );
    324                 if ( decls != tables->idTable.end() ) {
    325                         const MangleTable &mangleTable = decls->second;
    326                         for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    327                                 // check for C decls with the same name, skipping
    328                                 // those with an incompatible type (by mangleName)
    329                                 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true;
    330                         }
    331                 }
    332 
    333                 return tables->base.hasCompatibleCDecl( id, mangleName, scope );
    334         }
    335 
    336         NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
    337                 if ( ! tables ) return 0;
    338                 if ( tables->scope < scope ) return 0;
    339 
    340                 TypeTable::const_iterator ret = tables->typeTable.find( id );
    341                 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
    342         }
    343 
    344         StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
    345                 if ( ! tables ) return 0;
    346                 if ( tables->scope < scope ) return 0;
    347 
    348                 StructTable::const_iterator ret = tables->structTable.find( id );
    349                 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
    350         }
    351 
    352         EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
    353                 if ( ! tables ) return 0;
    354                 if ( tables->scope < scope ) return 0;
    355 
    356                 EnumTable::const_iterator ret = tables->enumTable.find( id );
    357                 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
    358         }
    359 
    360         UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
    361                 if ( ! tables ) return 0;
    362                 if ( tables->scope < scope ) return 0;
    363 
    364                 UnionTable::const_iterator ret = tables->unionTable.find( id );
    365                 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
    366         }
    367 
    368         TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
    369                 if ( ! tables ) return 0;
    370                 if ( tables->scope < scope ) return 0;
    371 
    372                 TraitTable::const_iterator ret = tables->traitTable.find( id );
    373                 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
    374         }
    375 
    376         bool isFunction( DeclarationWithType * decl ) {
     81                stats().size->push( idTable ? idTable->size() : 0 );
     82        }
     83
     84        void Indexer::lazyInitScope() {
     85                if ( repScope < scope ) {
     86                        ++* stats().lazy_scopes;
     87                        // create rollback
     88                        prevScope = std::make_shared<Indexer>( * this );
     89                        // update repScope
     90                        repScope = scope;
     91                }
     92        }
     93
     94        void Indexer::enterScope() {
     95                ++scope;
     96
     97                ++* stats().new_scopes;
     98                stats().avg_scope_depth->push( scope );
     99                stats().max_scope_depth->push( scope );
     100        }
     101
     102        void Indexer::leaveScope() {
     103                if ( repScope == scope ) {
     104                        Ptr prev = prevScope;           // make sure prevScope stays live
     105                        * this = std::move(* prevScope);  // replace with previous scope
     106                }
     107
     108                --scope;
     109        }
     110
     111        void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {
     112                ++* stats().lookup_calls;
     113                if ( ! idTable ) return;
     114
     115                ++* stats().map_lookups;
     116                auto decls = idTable->find( id );
     117                if ( decls == idTable->end() ) return;
     118
     119                for ( auto decl : *(decls->second) ) {
     120                        out.push_back( decl.second );
     121                }
     122        }
     123
     124        const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const {
     125                ++* stats().lookup_calls;
     126                if ( ! typeTable ) return nullptr;
     127                ++* stats().map_lookups;
     128                auto it = typeTable->find( id );
     129                return it == typeTable->end() ? nullptr : it->second.decl;
     130        }
     131
     132        const StructDecl * Indexer::lookupStruct( const std::string & id ) const {
     133                ++* stats().lookup_calls;
     134                if ( ! structTable ) return nullptr;
     135                ++* stats().map_lookups;
     136                auto it = structTable->find( id );
     137                return it == structTable->end() ? nullptr : it->second.decl;
     138        }
     139
     140        const EnumDecl * Indexer::lookupEnum( const std::string & id ) const {
     141                ++* stats().lookup_calls;
     142                if ( ! enumTable ) return nullptr;
     143                ++* stats().map_lookups;
     144                auto it = enumTable->find( id );
     145                return it == enumTable->end() ? nullptr : it->second.decl;
     146        }
     147
     148        const UnionDecl * Indexer::lookupUnion( const std::string & id ) const {
     149                ++* stats().lookup_calls;
     150                if ( ! unionTable ) return nullptr;
     151                ++* stats().map_lookups;
     152                auto it = unionTable->find( id );
     153                return it == unionTable->end() ? nullptr : it->second.decl;
     154        }
     155
     156        const TraitDecl * Indexer::lookupTrait( const std::string & id ) const {
     157                ++* stats().lookup_calls;
     158                if ( ! traitTable ) return nullptr;
     159                ++* stats().map_lookups;
     160                auto it = traitTable->find( id );
     161                return it == traitTable->end() ? nullptr : it->second.decl;
     162        }
     163
     164        const Indexer * Indexer::atScope( unsigned long target ) const {
     165                // by lazy construction, final indexer in list has repScope 0, cannot be > target
     166                // otherwise, will find first scope representing the target
     167                const Indexer * indexer = this;
     168                while ( indexer->repScope > target ) {
     169                        indexer = indexer->prevScope.get();
     170                }
     171                return indexer;
     172        }
     173
     174        const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const {
     175                return atScope( 0 )->lookupType( id );
     176        }
     177
     178        const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const {
     179                return atScope( 0 )->lookupStruct( id );
     180        }
     181
     182        const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const {
     183                return atScope( 0 )->lookupUnion( id );
     184        }
     185
     186        const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const {
     187                return atScope( 0 )->lookupEnum( id );
     188        }
     189
     190        bool isFunction( const DeclarationWithType * decl ) {
    377191                return GenPoly::getFunctionType( decl->get_type() );
    378192        }
    379193
    380         bool isObject( DeclarationWithType * decl ) {
     194        bool isObject( const DeclarationWithType * decl ) {
    381195                return ! isFunction( decl );
    382196        }
    383197
    384         bool isDefinition( DeclarationWithType * decl ) {
    385                 if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
     198        bool isDefinition( const DeclarationWithType * decl ) {
     199                if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
    386200                        // a function is a definition if it has a body
    387201                        return func->statements;
     
    393207        }
    394208
    395         bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) {
    396                 // if we're giving the same name mangling to things of different types then there is something wrong
     209
     210        bool Indexer::addedIdConflicts(
     211                        const Indexer::IdData & existing, const DeclarationWithType * added,
     212                        Indexer::OnConflict handleConflicts, const Declaration * deleteStmt ) {
     213                // if we're giving the same name mangling to things of different types then there is
     214                // something wrong
    397215                assert( (isObject( added ) && isObject( existing.id ) )
    398216                        || ( isFunction( added ) && isFunction( existing.id ) ) );
    399217
    400                 if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
     218                if ( LinkageSpec::isOverridable( existing.id->linkage ) ) {
    401219                        // new definition shadows the autogenerated one, even at the same scope
    402220                        return false;
    403                 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) {
     221                } else if ( LinkageSpec::isMangled( added->linkage )
     222                                || ResolvExpr::typesCompatible(
     223                                        added->get_type(), existing.id->get_type(), Indexer() ) ) {
    404224
    405225                        // it is a conflict if one declaration is deleted and the other is not
    406226                        if ( deleteStmt && ! existing.deleteStmt ) {
    407                                 return handleConflicts( existing, "deletion of defined identifier " );
     227                                if ( handleConflicts.mode == OnConflict::Error ) {
     228                                        SemanticError( added, "deletion of defined identifier " );
     229                                }
     230                                return true;
    408231                        } else if ( ! deleteStmt && existing.deleteStmt ) {
    409                                 return handleConflicts( existing, "definition of deleted identifier " );
     232                                if ( handleConflicts.mode == OnConflict::Error ) {
     233                                        SemanticError( added, "definition of deleted identifier " );
     234                                }
     235                                return true;
    410236                        }
    411237
    412238                        if ( isDefinition( added ) && isDefinition( existing.id ) ) {
    413                                 if ( isFunction( added ) ) {
    414                                         return handleConflicts( existing, "duplicate function definition for " );
     239                                if ( handleConflicts.mode == OnConflict::Error ) {
     240                                        SemanticError( added,
     241                                                isFunction( added ) ?
     242                                                        "duplicate function definition for " :
     243                                                        "duplicate object definition for " );
     244                                }
     245                                return true;
     246                        } // if
     247                } else {
     248                        if ( handleConflicts.mode == OnConflict::Error ) {
     249                                SemanticError( added, "duplicate definition for " );
     250                        }
     251                        return true;
     252                } // if
     253
     254                return true;
     255        }
     256
     257        bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const {
     258                if ( ! idTable ) return false;
     259
     260                ++* stats().map_lookups;
     261                auto decls = idTable->find( id );
     262                if ( decls == idTable->end() ) return false;
     263
     264                for ( auto decl : *(decls->second) ) {
     265                        // skip other scopes (hidden by this decl)
     266                        if ( decl.second.scope != scope ) continue;
     267                        // check for C decl with compatible type (by mangleName)
     268                        if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) {
     269                                return true;
     270                        }
     271                }
     272
     273                return false;
     274        }
     275
     276        bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const {
     277                if ( ! idTable ) return false;
     278
     279                ++* stats().map_lookups;
     280                auto decls = idTable->find( id );
     281                if ( decls == idTable->end() ) return false;
     282
     283                for ( auto decl : *(decls->second) ) {
     284                        // skip other scopes (hidden by this decl)
     285                        if ( decl.second.scope != scope ) continue;
     286                        // check for C decl with incompatible type (by manglename)
     287                        if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) {
     288                                return true;
     289                        }
     290                }
     291
     292                return false;
     293        }
     294
     295        /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
     296        std::string getOtypeKey( const FunctionDecl * function ) {
     297                auto& params = function->type->parameters;
     298                assert( ! params.empty() );
     299                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     300                Type * base = InitTweak::getPointerBase( params.front()->get_type() );
     301                assert( base );
     302                return Mangler::mangle( base );
     303        }
     304
     305        /// gets the declaration for the function acting on a type specified by otype key,
     306        /// nullptr if none such
     307        const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) {
     308                const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl );
     309                if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
     310                return func;
     311        }
     312
     313        bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
     314                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which
     315                // determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
     316                // if the user defines a default ctor, then the generated default ctor is unavailable,
     317                // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
     318                // field ctors are available. If the user defines any ctor then the generated default ctor
     319                // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
     320                // anything that looks like a copy constructor, then the generated copy constructor is
     321                // unavailable, and likewise for the assignment operator.
     322
     323                // only relevant on function declarations
     324                const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id );
     325                if ( ! function ) return true;
     326                // only need to perform this check for constructors, destructors, and assignment functions
     327                if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true;
     328
     329                // set up information for this type
     330                bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
     331                bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name );
     332                std::string dataOtypeKey = getOtypeKey( function );
     333
     334                if ( dataIsUserDefinedFunc && dataIsCopyFunc ) {
     335                        // this is a user-defined copy function
     336                        // if this is the first such, delete/remove non-user-defined overloads as needed
     337                        std::vector< std::string > removed;
     338                        std::vector< MangleTable::value_type > deleted;
     339                        bool alreadyUserDefinedFunc = false;
     340
     341                        for ( const auto& entry : * mangleTable ) {
     342                                // skip decls that aren't functions or are for the wrong type
     343                                const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     344                                if ( ! decl ) continue;
     345
     346                                bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name );
     347                                if ( ! LinkageSpec::isOverridable( decl->linkage ) ) {
     348                                        // matching user-defined function
     349                                        if ( isCopyFunc ) {
     350                                                // mutation already performed, return early
     351                                                return true;
     352                                        } else {
     353                                                // note that non-copy deletions already performed
     354                                                alreadyUserDefinedFunc = true;
     355                                        }
    415356                                } else {
    416                                         return handleConflicts( existing, "duplicate object definition for " );
    417                                 } // if
    418                         } // if
    419                 } else {
    420                         return handleConflicts( existing, "duplicate definition for " );
    421                 } // if
    422 
     357                                        // non-user-defined function; mark for deletion/removal as appropriate
     358                                        if ( isCopyFunc ) {
     359                                                removed.push_back( entry.first );
     360                                        } else if ( ! alreadyUserDefinedFunc ) {
     361                                                deleted.push_back( entry );
     362                                        }
     363                                }
     364                        }
     365
     366                        // perform removals from mangle table, and deletions if necessary
     367                        for ( const auto& key : removed ) {
     368                                ++* stats().map_mutations;
     369                                mangleTable = mangleTable->erase( key );
     370                        }
     371                        if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) {
     372                                ++* stats().map_mutations;
     373                                mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
     374                        }
     375                } else if ( dataIsUserDefinedFunc ) {
     376                        // this is a user-defined non-copy function
     377                        // if this is the first user-defined function, delete non-user-defined overloads
     378                        std::vector< MangleTable::value_type > deleted;
     379
     380                        for ( const auto& entry : * mangleTable ) {
     381                                // skip decls that aren't functions or are for the wrong type
     382                                const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     383                                if ( ! decl ) continue;
     384
     385                                // exit early if already a matching user-defined function;
     386                                // earlier function will have mutated table
     387                                if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true;
     388
     389                                // skip mutating intrinsic functions
     390                                if ( decl->linkage == LinkageSpec::Intrinsic ) continue;
     391
     392                                // user-defined non-copy functions do not override copy functions
     393                                if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue;
     394
     395                                // this function to be deleted after mangleTable iteration is complete
     396                                deleted.push_back( entry );
     397                        }
     398
     399                        // mark deletions to update mangle table
     400                        // this needs to be a separate loop because of iterator invalidation
     401                        for ( const auto& entry : deleted ) {
     402                                ++* stats().map_mutations;
     403                                mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
     404                        }
     405                } else if ( function->linkage != LinkageSpec::Intrinsic ) {
     406                        // this is an overridable generated function
     407                        // if there already exists a matching user-defined function, delete this appropriately
     408                        for ( const auto& entry : * mangleTable ) {
     409                                // skip decls that aren't functions or are for the wrong type
     410                                const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     411                                if ( ! decl ) continue;
     412
     413                                // skip non-user-defined functions
     414                                if ( LinkageSpec::isOverridable( decl->linkage ) ) continue;
     415
     416                                if ( dataIsCopyFunc ) {
     417                                        // remove current function if exists a user-defined copy function
     418                                        // since the signatures for copy functions don't need to match exactly, using
     419                                        // a delete statement is the wrong approach
     420                                        if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false;
     421                                } else {
     422                                        // mark current function deleted by first user-defined function found
     423                                        data.deleteStmt = decl;
     424                                        return true;
     425                                }
     426                        }
     427                }
     428
     429                // nothing (more) to fix, return true
    423430                return true;
    424431        }
    425432
    426         void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) {
    427                 if ( decl->name == "" ) return;
    428                 debugPrint( "Adding Id " << decl->name << std::endl );
    429                 makeWritable();
    430 
     433        void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr,
     434                        const Declaration * deleteStmt ) {
     435                ++* stats().add_calls;
    431436                const std::string &name = decl->name;
     437                if ( name == "" ) return;
     438
    432439                std::string mangleName;
    433440                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
    434                         // mangle the name without including the appropriate suffix, so overridable routines are placed into the
    435                         // same "bucket" as their user defined versions.
     441                        // mangle the name without including the appropriate suffix, so overridable routines
     442                        // are placed into the same "bucket" as their user defined versions.
    436443                        mangleName = Mangler::mangle( decl, false );
    437444                } else {
     
    439446                } // if
    440447
    441                 // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage
    442                 if ( ! LinkageSpec::isMangled( decl->linkage ) ) {
    443                         // NOTE this is broken in Richard's original code in such a way that it never triggers (it
    444                         // doesn't check decls that have the same manglename, and all C-linkage decls are defined to
    445                         // have their name as their manglename, hence the error can never trigger).
    446                         // The code here is closer to correct, but name mangling would have to be completely
    447                         // isomorphic to C type-compatibility, which it may not be.
    448                         if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
     448                // this ensures that no two declarations with the same unmangled name at the same scope
     449                // both have C linkage
     450                if ( LinkageSpec::isMangled( decl->linkage ) ) {
     451                        // Check that a Cforall declaration doesn't override any C declaration
     452                        if ( hasCompatibleCDecl( name, mangleName ) ) {
     453                                SemanticError( decl, "Cforall declaration hides C function " );
     454                        }
     455                } else {
     456                        // NOTE: only correct if name mangling is completely isomorphic to C
     457                        // type-compatibility, which it may not be.
     458                        if ( hasIncompatibleCDecl( name, mangleName ) ) {
    449459                                SemanticError( decl, "conflicting overload of C function " );
    450460                        }
    451                 } else {
    452                         // Check that a Cforall declaration doesn't override any C declaration
    453                         if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    454                                 SemanticError( decl, "Cforall declaration hides C function " );
    455                         }
    456                 }
    457 
    458                 // Skip repeat declarations of the same identifier
    459                 IdData * existing = lookupIdAtScope( name, mangleName, scope );
    460                 if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return;
    461 
    462                 // add to indexer
    463                 tables->idTable[ name ][ mangleName ] = IdData{ decl, baseExpr, deleteStmt };
    464                 ++tables->size;
    465         }
    466 
    467         void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
     461                }
     462
     463                // ensure tables exist and add identifier
     464                MangleTable::Ptr mangleTable;
     465                if ( ! idTable ) {
     466                        idTable = IdTable::new_ptr();
     467                        mangleTable = MangleTable::new_ptr();
     468                } else {
     469                        ++* stats().map_lookups;
     470                        auto decls = idTable->find( name );
     471                        if ( decls == idTable->end() ) {
     472                                mangleTable = MangleTable::new_ptr();
     473                        } else {
     474                                mangleTable = decls->second;
     475                                // skip in-scope repeat declarations of same identifier
     476                                ++* stats().map_lookups;
     477                                auto existing = mangleTable->find( mangleName );
     478                                if ( existing != mangleTable->end()
     479                                                && existing->second.scope == scope
     480                                                && existing->second.id ) {
     481                                        if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) {
     482                                                if ( handleConflicts.mode == OnConflict::Delete ) {
     483                                                        // set delete expression for conflicting identifier
     484                                                        lazyInitScope();
     485                                                        * stats().map_mutations += 2;
     486                                                        idTable = idTable->set(
     487                                                                name,
     488                                                                mangleTable->set(
     489                                                                        mangleName,
     490                                                                        IdData{ existing->second, handleConflicts.deleteStmt } ) );
     491                                                }
     492                                                return;
     493                                        }
     494                                }
     495                        }
     496                }
     497
     498                // add/overwrite with new identifier
     499                lazyInitScope();
     500                IdData data{ decl, baseExpr, deleteStmt, scope };
     501                // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary
     502                if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
     503                * stats().map_mutations += 2;
     504                idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );
     505        }
     506
     507        void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) {
    468508                // default handling of conflicts is to raise an error
    469                 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
    470         }
    471 
    472         void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
     509                addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
     510        }
     511
     512        void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) {
    473513                // default handling of conflicts is to raise an error
    474                 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
    475         }
    476 
    477         bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
    478                 if ( existing->get_base() == 0 ) {
     514                addId( decl, OnConflict::error(), nullptr, deleteStmt );
     515        }
     516
     517        bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
     518                if ( existing->base == nullptr ) {
    479519                        return false;
    480                 } else if ( added->get_base() == 0 ) {
     520                } else if ( added->base == nullptr ) {
    481521                        return true;
    482522                } else {
    483                         SemanticError( added, "redeclaration of " );
    484                 }
    485         }
    486 
    487         void Indexer::addType( NamedTypeDecl *decl ) {
    488                 debugPrint( "Adding type " << decl->name << std::endl );
    489                 makeWritable();
    490 
    491                 const std::string &id = decl->get_name();
    492                 TypeTable::iterator existing = tables->typeTable.find( id );
    493                 if ( existing == tables->typeTable.end() ) {
    494                         NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
    495                         if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
    496                                 tables->typeTable.insert( existing, std::make_pair( id, decl ) );
    497                                 ++tables->size;
    498                         }
    499                 } else {
    500                         if ( ! addedTypeConflicts( existing->second, decl ) ) {
    501                                 existing->second = decl;
    502                         }
    503                 }
    504         }
    505 
    506         bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
     523                        assert( existing->base && added->base );
     524                        // typedef redeclarations are errors only if types are different
     525                        if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) {
     526                                SemanticError( added->location, "redeclaration of " + added->name );
     527                        }
     528                }
     529                // does not need to be added to the table if both existing and added have a base that are
     530                // the same
     531                return true;
     532        }
     533
     534        void Indexer::addType( const NamedTypeDecl * decl ) {
     535                ++* stats().add_calls;
     536                const std::string & id = decl->name;
     537
     538                if ( ! typeTable ) {
     539                        typeTable = TypeTable::new_ptr();
     540                } else {
     541                        ++* stats().map_lookups;
     542                        auto existing = typeTable->find( id );
     543                        if ( existing != typeTable->end()
     544                                && existing->second.scope == scope
     545                                && addedTypeConflicts( existing->second.decl, decl ) ) return;
     546                }
     547
     548                lazyInitScope();
     549                ++* stats().map_mutations;
     550                typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } );
     551        }
     552
     553        bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) {
    507554                if ( ! existing->body ) {
    508555                        return false;
     
    513560        }
    514561
    515         void Indexer::addStruct( const std::string &id ) {
    516                 debugPrint( "Adding fwd decl for struct " << id << std::endl );
     562        void Indexer::addStruct( const std::string & id ) {
    517563                addStruct( new StructDecl( id ) );
    518564        }
    519565
    520         void Indexer::addStruct( StructDecl *decl ) {
    521                 debugPrint( "Adding struct " << decl->name << std::endl );
    522                 makeWritable();
    523 
    524                 const std::string &id = decl->get_name();
    525                 StructTable::iterator existing = tables->structTable.find( id );
    526                 if ( existing == tables->structTable.end() ) {
    527                         StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
    528                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    529                                 tables->structTable.insert( existing, std::make_pair( id, decl ) );
    530                                 ++tables->size;
    531                         }
    532                 } else {
    533                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    534                                 existing->second = decl;
    535                         }
    536                 }
    537         }
    538 
    539         void Indexer::addEnum( EnumDecl *decl ) {
    540                 debugPrint( "Adding enum " << decl->name << std::endl );
    541                 makeWritable();
    542 
    543                 const std::string &id = decl->get_name();
    544                 EnumTable::iterator existing = tables->enumTable.find( id );
    545                 if ( existing == tables->enumTable.end() ) {
    546                         EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
    547                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    548                                 tables->enumTable.insert( existing, std::make_pair( id, decl ) );
    549                                 ++tables->size;
    550                         }
    551                 } else {
    552                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    553                                 existing->second = decl;
    554                         }
    555                 }
    556         }
    557 
    558         void Indexer::addUnion( const std::string &id ) {
    559                 debugPrint( "Adding fwd decl for union " << id << std::endl );
     566        void Indexer::addStruct( const StructDecl * decl ) {
     567                ++* stats().add_calls;
     568                const std::string & id = decl->name;
     569
     570                if ( ! structTable ) {
     571                        structTable = StructTable::new_ptr();
     572                } else {
     573                        ++* stats().map_lookups;
     574                        auto existing = structTable->find( id );
     575                        if ( existing != structTable->end()
     576                                && existing->second.scope == scope
     577                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
     578                }
     579
     580                lazyInitScope();
     581                ++* stats().map_mutations;
     582                structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } );
     583        }
     584
     585        void Indexer::addEnum( const EnumDecl * decl ) {
     586                ++* stats().add_calls;
     587                const std::string & id = decl->name;
     588
     589                if ( ! enumTable ) {
     590                        enumTable = EnumTable::new_ptr();
     591                } else {
     592                        ++* stats().map_lookups;
     593                        auto existing = enumTable->find( id );
     594                        if ( existing != enumTable->end()
     595                                && existing->second.scope == scope
     596                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
     597                }
     598
     599                lazyInitScope();
     600                ++* stats().map_mutations;
     601                enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } );
     602        }
     603
     604        void Indexer::addUnion( const std::string & id ) {
    560605                addUnion( new UnionDecl( id ) );
    561606        }
    562607
    563         void Indexer::addUnion( UnionDecl *decl ) {
    564                 debugPrint( "Adding union " << decl->name << std::endl );
    565                 makeWritable();
    566 
    567                 const std::string &id = decl->get_name();
    568                 UnionTable::iterator existing = tables->unionTable.find( id );
    569                 if ( existing == tables->unionTable.end() ) {
    570                         UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
    571                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    572                                 tables->unionTable.insert( existing, std::make_pair( id, decl ) );
    573                                 ++tables->size;
    574                         }
    575                 } else {
    576                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    577                                 existing->second = decl;
    578                         }
    579                 }
    580         }
    581 
    582         void Indexer::addTrait( TraitDecl *decl ) {
    583                 debugPrint( "Adding trait " << decl->name << std::endl );
    584                 makeWritable();
    585 
    586                 const std::string &id = decl->get_name();
    587                 TraitTable::iterator existing = tables->traitTable.find( id );
    588                 if ( existing == tables->traitTable.end() ) {
    589                         TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
    590                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    591                                 tables->traitTable.insert( existing, std::make_pair( id, decl ) );
    592                                 ++tables->size;
    593                         }
    594                 } else {
    595                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    596                                 existing->second = decl;
    597                         }
    598                 }
    599         }
    600 
    601         void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction handleConflicts ) {
     608        void Indexer::addUnion( const UnionDecl * decl ) {
     609                ++* stats().add_calls;
     610                const std::string & id = decl->name;
     611
     612                if ( ! unionTable ) {
     613                        unionTable = UnionTable::new_ptr();
     614                } else {
     615                        ++* stats().map_lookups;
     616                        auto existing = unionTable->find( id );
     617                        if ( existing != unionTable->end()
     618                                && existing->second.scope == scope
     619                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
     620                }
     621
     622                lazyInitScope();
     623                ++* stats().map_mutations;
     624                unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } );
     625        }
     626
     627        void Indexer::addTrait( const TraitDecl * decl ) {
     628                ++* stats().add_calls;
     629                const std::string & id = decl->name;
     630
     631                if ( ! traitTable ) {
     632                        traitTable = TraitTable::new_ptr();
     633                } else {
     634                        ++* stats().map_lookups;
     635                        auto existing = traitTable->find( id );
     636                        if ( existing != traitTable->end()
     637                                && existing->second.scope == scope
     638                                && addedDeclConflicts( existing->second.decl, decl ) ) return;
     639                }
     640
     641                lazyInitScope();
     642                ++* stats().map_mutations;
     643                traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } );
     644        }
     645
     646        void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) {
    602647                for ( Declaration * decl : aggr->members ) {
    603648                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    604649                                addId( dwt, handleConflicts, expr );
    605650                                if ( dwt->name == "" ) {
    606                                         Type * t = dwt->get_type()->stripReferences();
    607                                         if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ) ) {
     651                                        const Type * t = dwt->get_type()->stripReferences();
     652                                        if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) {
    608653                                                Expression * base = expr->clone();
    609654                                                ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
     
    616661        }
    617662
    618         void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
    619                 for ( Expression * expr : withExprs ) {
     663        void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) {
     664                for ( const Expression * expr : withExprs ) {
    620665                        if ( expr->result ) {
    621666                                AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
    622667                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
    623668
    624                                 addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) {
    625                                         // on conflict, delete the identifier
    626                                         existing.deleteStmt = withStmt;
    627                                         return true;
    628                                 });
     669                                addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
    629670                        }
    630671                }
     
    644685        }
    645686
    646         void Indexer::addFunctionType( FunctionType * ftype ) {
     687        void Indexer::addFunctionType( const FunctionType * ftype ) {
    647688                addTypes( ftype->forall );
    648689                addIds( ftype->returnVals );
    649690                addIds( ftype->parameters );
    650         }
    651 
    652         void Indexer::enterScope() {
    653                 ++scope;
    654 
    655                 if ( doDebug ) {
    656                         std::cerr << "--- Entering scope " << scope << std::endl;
    657                 }
    658         }
    659 
    660         void Indexer::leaveScope() {
    661                 using std::cerr;
    662 
    663                 assert( scope > 0 && "cannot leave initial scope" );
    664                 if ( doDebug ) {
    665                         cerr << "--- Leaving scope " << scope << " containing" << std::endl;
    666                 }
    667                 --scope;
    668 
    669                 while ( tables && tables->scope > scope ) {
    670                         if ( doDebug ) {
    671                                 dump( tables->idTable, cerr );
    672                                 dump( tables->typeTable, cerr );
    673                                 dump( tables->structTable, cerr );
    674                                 dump( tables->enumTable, cerr );
    675                                 dump( tables->unionTable, cerr );
    676                                 dump( tables->traitTable, cerr );
    677                         }
    678 
    679                         // swap tables for base table until we find one at an appropriate scope
    680                         Indexer::Impl *base = newRef( tables->base.tables );
    681                         deleteRef( tables );
    682                         tables = base;
    683                 }
    684         }
    685 
    686         void Indexer::print( std::ostream &os, int indent ) const {
    687                 using std::cerr;
    688 
    689                 if ( tables ) {
    690                         os << "--- scope " << tables->scope << " ---" << std::endl;
    691 
    692                         os << "===idTable===" << std::endl;
    693                         dump( tables->idTable, os );
    694                         os << "===typeTable===" << std::endl;
    695                         dump( tables->typeTable, os );
    696                         os << "===structTable===" << std::endl;
    697                         dump( tables->structTable, os );
    698                         os << "===enumTable===" << std::endl;
    699                         dump( tables->enumTable, os );
    700                         os << "===unionTable===" << std::endl;
    701                         dump( tables->unionTable, os );
    702                         os << "===contextTable===" << std::endl;
    703                         dump( tables->traitTable, os );
    704 
    705                         tables->base.print( os, indent );
    706                 } else {
    707                         os << "--- end ---" << std::endl;
    708                 }
    709 
    710691        }
    711692
     
    715696                        Expression * base = baseExpr->clone();
    716697                        ResolvExpr::referenceToRvalueConversion( base, cost );
    717                         ret = new MemberExpr( id, base );
     698                        ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base );
    718699                        // xxx - this introduces hidden environments, for now remove them.
    719700                        // std::swap( base->env, ret->env );
     
    721702                        base->env = nullptr;
    722703                } else {
    723                         ret = new VariableExpr( id );
    724                 }
    725                 if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
     704                        ret = new VariableExpr( const_cast<DeclarationWithType *>(id) );
     705                }
     706                if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) );
    726707                return ret;
    727708        }
  • src/SymTab/Indexer.h

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:38:55 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Aug 17 16:09:12 2017
    13 // Update Count     : 8
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Mar  8 13:55:00 2019
     13// Update Count     : 9
    1414//
    1515
    1616#pragma once
    1717
    18 #include <iosfwd>             // for ostream
    19 #include <list>               // for list
    20 #include <string>             // for string
    21 #include <functional>         // for function
     18#include <functional>              // for function
     19#include <list>                    // for list
     20#include <memory>                  // for shared_ptr, enable_shared_from_this
     21#include <string>                  // for string
    2222
    23 #include "SynTree/Visitor.h"  // for Visitor
    24 #include "SynTree/SynTree.h"  // for AST nodes
     23#include "Common/PersistentMap.h"  // for PersistentMap
     24#include "SynTree/SynTree.h"       // for AST nodes
    2525
    2626namespace ResolvExpr {
    27 class Cost;
     27        class Cost;
    2828}
    2929
    3030namespace SymTab {
    31         class Indexer {
    32           public:
     31        class Indexer : public std::enable_shared_from_this<SymTab::Indexer> {
     32        public:
    3333                explicit Indexer();
     34                virtual ~Indexer();
    3435
    35                 Indexer( const Indexer &that );
    36                 Indexer( Indexer &&that );
    37                 virtual ~Indexer();
    38                 Indexer& operator= ( const Indexer &that );
    39                 Indexer& operator= ( Indexer &&that );
    40 
    41                 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to tell the indexer
    42                 // explicitly when scopes begin and end
     36                // when using an indexer manually (e.g., within a mutator traversal), it is necessary to
     37                // tell the indexer explicitly when scopes begin and end
    4338                void enterScope();
    4439                void leaveScope();
    4540
    4641                struct IdData {
    47                         DeclarationWithType * id = nullptr;
    48                         Expression * baseExpr = nullptr; // WithExpr
     42                        const DeclarationWithType * id = nullptr;
     43                        const Expression * baseExpr = nullptr; // WithExpr
    4944
    5045                        /// non-null if this declaration is deleted
    51                         BaseSyntaxNode * deleteStmt = nullptr;
     46                        const Declaration * deleteStmt = nullptr;
     47                        /// scope of identifier
     48                        unsigned long scope = 0;
    5249
    5350                        // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members.
    5451                        IdData() = default;
    55                         IdData( DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ) {}
     52                        IdData(
     53                                const DeclarationWithType * id, const Expression * baseExpr, const Declaration * deleteStmt,
     54                                unsigned long scope )
     55                                : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {}
     56                        IdData( const IdData& o, const Declaration * deleteStmt )
     57                                : id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {}
    5658
    5759                        Expression * combine( ResolvExpr::Cost & cost ) const;
     
    5961
    6062                /// Gets all declarations with the given ID
    61                 void lookupId( const std::string &id, std::list< IdData > &out ) const;
     63                void lookupId( const std::string & id, std::list< IdData > &out ) const;
    6264                /// Gets the top-most type declaration with the given ID
    63                 NamedTypeDecl *lookupType( const std::string &id ) const;
     65                const NamedTypeDecl * lookupType( const std::string & id ) const;
    6466                /// Gets the top-most struct declaration with the given ID
    65                 StructDecl *lookupStruct( const std::string &id ) const;
     67                const StructDecl * lookupStruct( const std::string & id ) const;
    6668                /// Gets the top-most enum declaration with the given ID
    67                 EnumDecl *lookupEnum( const std::string &id ) const;
     69                const EnumDecl * lookupEnum( const std::string & id ) const;
    6870                /// Gets the top-most union declaration with the given ID
    69                 UnionDecl *lookupUnion( const std::string &id ) const;
     71                const UnionDecl * lookupUnion( const std::string & id ) const;
    7072                /// Gets the top-most trait declaration with the given ID
    71                 TraitDecl *lookupTrait( const std::string &id ) const;
     73                const TraitDecl * lookupTrait( const std::string & id ) const;
    7274
    73                 void print( std::ostream &os, int indent = 0 ) const;
     75                /// Gets the type declaration with the given ID at global scope
     76                const NamedTypeDecl * globalLookupType( const std::string & id ) const;
     77                /// Gets the struct declaration with the given ID at global scope
     78                const StructDecl * globalLookupStruct( const std::string & id ) const;
     79                /// Gets the union declaration with the given ID at global scope
     80                const UnionDecl * globalLookupUnion( const std::string & id ) const;
     81                /// Gets the enum declaration with the given ID at global scope
     82                const EnumDecl * globalLookupEnum( const std::string & id ) const;
    7483
    75                 /// looks up a specific mangled ID at the given scope
    76                 IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope );
    77                 const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
    78                 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
    79                 bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
    80                 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name
    81                 bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
    82                 // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)
    83                 NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;
    84                 StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const;
    85                 EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const;
    86                 UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const;
    87                 TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
     84                void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr );
     85                void addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt );
    8886
    89                 typedef std::function<bool(IdData &, const std::string &)> ConflictFunction;
    90 
    91                 void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr );
    92                 void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt );
    93 
    94                 void addType( NamedTypeDecl *decl );
    95                 void addStruct( const std::string &id );
    96                 void addStruct( StructDecl *decl );
    97                 void addEnum( EnumDecl *decl );
    98                 void addUnion( const std::string &id );
    99                 void addUnion( UnionDecl *decl );
    100                 void addTrait( TraitDecl *decl );
     87                void addType( const NamedTypeDecl * decl );
     88                void addStruct( const std::string & id );
     89                void addStruct( const StructDecl * decl );
     90                void addEnum( const EnumDecl * decl );
     91                void addUnion( const std::string & id );
     92                void addUnion( const UnionDecl * decl );
     93                void addTrait( const TraitDecl * decl );
    10194
    10295                /// adds all of the IDs from WithStmt exprs
    103                 void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt );
    104 
    105                 /// adds all of the members of the Aggregate (addWith helper)
    106                 void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction );
     96                void addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt );
    10797
    10898                /// convenience function for adding a list of Ids to the indexer
     
    113103
    114104                /// convenience function for adding all of the declarations in a function type to the indexer
    115                 void addFunctionType( FunctionType * ftype );
     105                void addFunctionType( const FunctionType * ftype );
    116106
    117                 bool doDebug = false; ///< Display debugging trace?
    118107          private:
    119                 struct Impl;
     108                /// Wraps a Decl * with a scope
     109                template<typename Decl>
     110                struct Scoped {
     111                        const Decl * decl;           ///< declaration
     112                        unsigned long scope;  ///< scope of this declaration
    120113
    121                 Impl *tables;         ///< Copy-on-write instance of table data structure
    122                 unsigned long scope;  ///< Scope index of this pointer
     114                        Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {}
     115                };
    123116
    124                 /// Takes a new ref to a table (returns null if null)
    125                 static Impl *newRef( Impl *toClone );
    126                 /// Clears a ref to a table (does nothing if null)
    127                 static void deleteRef( Impl *toFree );
     117                using Ptr = std::shared_ptr<const Indexer>;
    128118
    129                 // Removes matching autogenerated constructors and destructors
    130                 // so that they will not be selected
    131                 // void removeSpecialOverrides( FunctionDecl *decl );
    132                 void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const;
     119                using MangleTable = PersistentMap< std::string, IdData >;
     120                using IdTable = PersistentMap< std::string, MangleTable::Ptr >;
     121                using TypeTable = PersistentMap< std::string, Scoped<NamedTypeDecl> >;
     122                using StructTable = PersistentMap< std::string, Scoped<StructDecl> >;
     123                using EnumTable = PersistentMap< std::string, Scoped<EnumDecl> >;
     124                using UnionTable = PersistentMap< std::string, Scoped<UnionDecl> >;
     125                using TraitTable = PersistentMap< std::string, Scoped<TraitDecl> >;
    133126
    134                 /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
    135                 void makeWritable();
     127                IdTable::Ptr idTable;          ///< identifier namespace
     128                TypeTable::Ptr typeTable;      ///< type namespace
     129                StructTable::Ptr structTable;  ///< struct namespace
     130                EnumTable::Ptr enumTable;      ///< enum namespace
     131                UnionTable::Ptr unionTable;    ///< union namespace
     132                TraitTable::Ptr traitTable;    ///< trait namespace
     133
     134                Ptr prevScope;                 ///< reference to indexer for parent scope
     135                unsigned long scope;           ///< Scope index of this indexer
     136                unsigned long repScope;        ///< Scope index of currently represented scope
     137
     138                /// Ensures that a proper backtracking scope exists before a mutation
     139                void lazyInitScope();
     140
     141                /// Gets the indexer at the given scope
     142                const Indexer * atScope( unsigned long scope ) const;
     143
     144                /// Removes matching autogenerated constructors and destructors so that they will not be
     145                /// selected. If returns false, passed decl should not be added.
     146                bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
     147
     148                /// Options for handling identifier conflicts
     149                struct OnConflict {
     150                        enum {
     151                                Error,  ///< Throw a semantic error
     152                                Delete  ///< Delete the earlier version with the delete statement
     153                        } mode;
     154                        const Declaration * deleteStmt;  ///< Statement that deletes this expression
     155
     156                private:
     157                        OnConflict() : mode(Error), deleteStmt(nullptr) {}
     158                        OnConflict( const Declaration * d ) : mode(Delete), deleteStmt(d) {}
     159                public:
     160                        OnConflict( const OnConflict& ) = default;
     161
     162                        static OnConflict error() { return {}; }
     163                        static OnConflict deleteWith( const Declaration * d ) { return { d }; }
     164                };
     165
     166                /// true if the existing identifier conflicts with the added identifier
     167                bool addedIdConflicts(
     168                        const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts,
     169                        const Declaration * deleteStmt );
    136170
    137171                /// common code for addId, addDeletedId, etc.
    138                 void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
     172                void addId(const DeclarationWithType * decl, OnConflict handleConflicts,
     173                        const Expression * baseExpr = nullptr, const Declaration * deleteStmt = nullptr );
     174
     175                /// adds all of the members of the Aggregate (addWith helper)
     176                void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts );
     177
     178                /// returns true if there exists a declaration with C linkage and the given name with the same mangled name
     179                bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
     180                /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
     181                bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
    139182        };
    140183} // namespace SymTab
  • src/SymTab/Mangler.cc

    r7951100 rb067d9b  
    1010// Created On       : Sun May 17 21:40:29 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 15:49:26 2017
    13 // Update Count     : 23
     12// Last Modified On : Tue Jul 30 13:46:10 2019
     13// Update Count     : 26
    1414//
    1515#include "Mangler.h"
    1616
    17 #include <algorithm>                // for copy, transform
    18 #include <cassert>                  // for assert, assertf
    19 #include <functional>               // for const_mem_fun_t, mem_fun
    20 #include <iterator>                 // for ostream_iterator, back_insert_ite...
    21 #include <list>                     // for _List_iterator, list, _List_const...
    22 #include <string>                   // for string, char_traits, operator<<
    23 
    24 #include "CodeGen/OperatorTable.h"  // for OperatorInfo, operatorLookup
     17#include <algorithm>                     // for copy, transform
     18#include <cassert>                       // for assert, assertf
     19#include <functional>                    // for const_mem_fun_t, mem_fun
     20#include <iterator>                      // for ostream_iterator, back_insert_ite...
     21#include <list>                          // for _List_iterator, list, _List_const...
     22#include <string>                        // for string, char_traits, operator<<
     23
     24#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
    2525#include "Common/PassVisitor.h"
    26 #include "Common/SemanticError.h"   // for SemanticError
    27 #include "Common/utility.h"         // for toString
    28 #include "Parser/LinkageSpec.h"     // for Spec, isOverridable, AutoGen, Int...
    29 #include "SynTree/Declaration.h"    // for TypeDecl, DeclarationWithType
    30 #include "SynTree/Expression.h"     // for TypeExpr, Expression, operator<<
    31 #include "SynTree/Type.h"           // for Type, ReferenceToType, Type::Fora...
     26#include "Common/SemanticError.h"        // for SemanticError
     27#include "Common/utility.h"              // for toString
     28#include "Parser/LinkageSpec.h"          // for Spec, isOverridable, AutoGen, Int...
     29#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     30#include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
     31#include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
     32#include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
     33
     34#include "AST/Pass.hpp"
    3235
    3336namespace SymTab {
     
    3538                namespace {
    3639                        /// Mangles names to a unique C identifier
    37                         struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
    38                                 Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
    39                                 Mangler( const Mangler & ) = delete;
    40 
    41                                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    42 
    43                                 void postvisit( ObjectDecl * declaration );
    44                                 void postvisit( FunctionDecl * declaration );
    45                                 void postvisit( TypeDecl * declaration );
    46 
    47                                 void postvisit( VoidType * voidType );
    48                                 void postvisit( BasicType * basicType );
    49                                 void postvisit( PointerType * pointerType );
    50                                 void postvisit( ArrayType * arrayType );
    51                                 void postvisit( ReferenceType * refType );
    52                                 void postvisit( FunctionType * functionType );
    53                                 void postvisit( StructInstType * aggregateUseType );
    54                                 void postvisit( UnionInstType * aggregateUseType );
    55                                 void postvisit( EnumInstType * aggregateUseType );
    56                                 void postvisit( TypeInstType * aggregateUseType );
    57                                 void postvisit( TraitInstType * inst );
    58                                 void postvisit( TupleType * tupleType );
    59                                 void postvisit( VarArgsType * varArgsType );
    60                                 void postvisit( ZeroType * zeroType );
    61                                 void postvisit( OneType * oneType );
     40                        struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
     41                                Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
     42                                Mangler_old( const Mangler_old & ) = delete;
     43
     44                                void previsit( const BaseSyntaxNode * ) { visit_children = false; }
     45
     46                                void postvisit( const ObjectDecl * declaration );
     47                                void postvisit( const FunctionDecl * declaration );
     48                                void postvisit( const TypeDecl * declaration );
     49
     50                                void postvisit( const VoidType * voidType );
     51                                void postvisit( const BasicType * basicType );
     52                                void postvisit( const PointerType * pointerType );
     53                                void postvisit( const ArrayType * arrayType );
     54                                void postvisit( const ReferenceType * refType );
     55                                void postvisit( const FunctionType * functionType );
     56                                void postvisit( const StructInstType * aggregateUseType );
     57                                void postvisit( const UnionInstType * aggregateUseType );
     58                                void postvisit( const EnumInstType * aggregateUseType );
     59                                void postvisit( const TypeInstType * aggregateUseType );
     60                                void postvisit( const TraitInstType * inst );
     61                                void postvisit( const TupleType * tupleType );
     62                                void postvisit( const VarArgsType * varArgsType );
     63                                void postvisit( const ZeroType * zeroType );
     64                                void postvisit( const OneType * oneType );
     65                                void postvisit( const QualifiedType * qualType );
    6266
    6367                                std::string get_mangleName() { return mangleName.str(); }
     
    7276                                bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
    7377                                bool inFunctionType = false;    ///< Include type qualifiers if false.
    74 
    75                                 void mangleDecl( DeclarationWithType *declaration );
    76                                 void mangleRef( ReferenceToType *refType, std::string prefix );
    77 
    78                                 void printQualifiers( Type *type );
    79                         }; // Mangler
     78                                bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
     79
     80                          public:
     81                                Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     82                                        int nextVarNum, const VarMapType& varNums );
     83
     84                          private:
     85                                void mangleDecl( const DeclarationWithType * declaration );
     86                                void mangleRef( const ReferenceToType * refType, std::string prefix );
     87
     88                                void printQualifiers( const Type *type );
     89                        }; // Mangler_old
    8090                } // namespace
    8191
    82                 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
    83                         PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
     92                std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
     93                        PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
    8494                        maybeAccept( decl, mangler );
    8595                        return mangler.pass.get_mangleName();
    8696                }
    8797
    88                 std::string mangleType( Type * ty ) {
    89                         PassVisitor<Mangler> mangler( false, true, true );
     98                std::string mangleType( const Type * ty ) {
     99                        PassVisitor<Mangler_old> mangler( false, true, true );
    90100                        maybeAccept( ty, mangler );
    91101                        return mangler.pass.get_mangleName();
    92102                }
    93103
    94                 std::string mangleConcrete( Type * ty ) {
    95                         PassVisitor<Mangler> mangler( false, false, false );
     104                std::string mangleConcrete( const Type * ty ) {
     105                        PassVisitor<Mangler_old> mangler( false, false, false );
    96106                        maybeAccept( ty, mangler );
    97107                        return mangler.pass.get_mangleName();
     
    99109
    100110                namespace {
    101                         Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
    102                                 : nextVarNum( 0 ), isTopLevel( true ), mangleOverridable( mangleOverridable ), typeMode( typeMode ), mangleGenericParams( mangleGenericParams ) {}
    103 
    104                         void Mangler::mangleDecl( DeclarationWithType * declaration ) {
     111                        Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
     112                                : nextVarNum( 0 ), isTopLevel( true ),
     113                                mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     114                                mangleGenericParams( mangleGenericParams ) {}
     115
     116                        Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     117                                int nextVarNum, const VarMapType& varNums )
     118                                : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
     119                                mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     120                                mangleGenericParams( mangleGenericParams ) {}
     121
     122                        void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
    105123                                bool wasTopLevel = isTopLevel;
    106124                                if ( isTopLevel ) {
     
    109127                                        isTopLevel = false;
    110128                                } // if
    111                                 mangleName << "__";
     129                                mangleName << Encoding::manglePrefix;
    112130                                CodeGen::OperatorInfo opInfo;
    113131                                if ( operatorLookup( declaration->get_name(), opInfo ) ) {
    114                                         mangleName << opInfo.outputName;
     132                                        mangleName << opInfo.outputName.size() << opInfo.outputName;
    115133                                } else {
    116                                         mangleName << declaration->get_name();
    117                                 } // if
    118                                 mangleName << "__";
     134                                        mangleName << declaration->name.size() << declaration->name;
     135                                } // if
    119136                                maybeAccept( declaration->get_type(), *visitor );
    120137                                if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
     
    122139                                        // so they need a different name mangling
    123140                                        if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
    124                                                 mangleName << "autogen__";
     141                                                mangleName << Encoding::autogen;
    125142                                        } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
    126                                                 mangleName << "intrinsic__";
     143                                                mangleName << Encoding::intrinsic;
    127144                                        } else {
    128145                                                // if we add another kind of overridable function, this has to change
     
    133150                        }
    134151
    135                         void Mangler::postvisit( ObjectDecl * declaration ) {
     152                        void Mangler_old::postvisit( const ObjectDecl * declaration ) {
    136153                                mangleDecl( declaration );
    137154                        }
    138155
    139                         void Mangler::postvisit( FunctionDecl * declaration ) {
     156                        void Mangler_old::postvisit( const FunctionDecl * declaration ) {
    140157                                mangleDecl( declaration );
    141158                        }
    142159
    143                         void Mangler::postvisit( VoidType * voidType ) {
     160                        void Mangler_old::postvisit( const VoidType * voidType ) {
    144161                                printQualifiers( voidType );
    145                                 mangleName << "v";
    146                         }
    147 
    148                         void Mangler::postvisit( BasicType * basicType ) {
    149                                 static const char *btLetter[] = {
    150                                         "b",    // Bool
    151                                         "c",    // Char
    152                                         "Sc",   // SignedChar
    153                                         "Uc",   // UnsignedChar
    154                                         "s",    // ShortSignedInt
    155                                         "Us",   // ShortUnsignedInt
    156                                         "i",    // SignedInt
    157                                         "Ui",   // UnsignedInt
    158                                         "l",    // LongSignedInt
    159                                         "Ul",   // LongUnsignedInt
    160                                         "q",    // LongLongSignedInt
    161                                         "Uq",   // LongLongUnsignedInt
    162                                         "f",    // Float
    163                                         "d",    // Double
    164                                         "r",    // LongDouble
    165                                         "Xf",   // FloatComplex
    166                                         "Xd",   // DoubleComplex
    167                                         "Xr",   // LongDoubleComplex
    168                                         "If",   // FloatImaginary
    169                                         "Id",   // DoubleImaginary
    170                                         "Ir",   // LongDoubleImaginary
    171                                         "w",    // SignedInt128
    172                                         "Uw",   // UnsignedInt128
    173                                         "x",   // Float80
    174                                         "y",   // Float128
    175                                 };
    176                                 static_assert(
    177                                         sizeof(btLetter)/sizeof(btLetter[0]) == BasicType::NUMBER_OF_BASIC_TYPES,
    178                                         "Each basic type kind should have a corresponding mangler letter"
    179                                 );
    180 
     162                                mangleName << Encoding::void_t;
     163                        }
     164
     165                        void Mangler_old::postvisit( const BasicType * basicType ) {
    181166                                printQualifiers( basicType );
    182                                 assert( basicType->get_kind() < sizeof(btLetter)/sizeof(btLetter[0]) );
    183                                 mangleName << btLetter[ basicType->get_kind() ];
    184                         }
    185 
    186                         void Mangler::postvisit( PointerType * pointerType ) {
     167                                assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
     168                                mangleName << Encoding::basicTypes[ basicType->kind ];
     169                        }
     170
     171                        void Mangler_old::postvisit( const PointerType * pointerType ) {
    187172                                printQualifiers( pointerType );
    188173                                // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
    189                                 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << "P";
     174                                if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << Encoding::pointer;
    190175                                maybeAccept( pointerType->base, *visitor );
    191176                        }
    192177
    193                         void Mangler::postvisit( ArrayType * arrayType ) {
     178                        void Mangler_old::postvisit( const ArrayType * arrayType ) {
    194179                                // TODO: encode dimension
    195180                                printQualifiers( arrayType );
    196                                 mangleName << "A0";
     181                                mangleName << Encoding::array << "0";
    197182                                maybeAccept( arrayType->base, *visitor );
    198183                        }
    199184
    200                         void Mangler::postvisit( ReferenceType * refType ) {
     185                        void Mangler_old::postvisit( const ReferenceType * refType ) {
    201186                                // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    202187                                // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     
    217202                        }
    218203
    219                         void Mangler::postvisit( FunctionType * functionType ) {
     204                        void Mangler_old::postvisit( const FunctionType * functionType ) {
    220205                                printQualifiers( functionType );
    221                                 mangleName << "F";
     206                                mangleName << Encoding::function;
    222207                                // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
    223208                                // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
     
    226211                                inFunctionType = true;
    227212                                std::list< Type* > returnTypes = getTypes( functionType->returnVals );
    228                                 acceptAll( returnTypes, *visitor );
     213                                if (returnTypes.empty()) mangleName << Encoding::void_t;
     214                                else acceptAll( returnTypes, *visitor );
    229215                                mangleName << "_";
    230216                                std::list< Type* > paramTypes = getTypes( functionType->parameters );
     
    233219                        }
    234220
    235                         void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
     221                        void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
    236222                                printQualifiers( refType );
    237223
    238                                 mangleName << ( refType->name.length() + prefix.length() ) << prefix << refType->name;
     224                                mangleName << prefix << refType->name.length() << refType->name;
    239225
    240226                                if ( mangleGenericParams ) {
    241                                         std::list< Expression* >& params = refType->parameters;
     227                                        const std::list< Expression* > & params = refType->parameters;
    242228                                        if ( ! params.empty() ) {
    243229                                                mangleName << "_";
    244                                                 for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
    245                                                         TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    246                                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
     230                                                for ( const Expression * param : params ) {
     231                                                        const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
     232                                                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
    247233                                                        maybeAccept( paramType->type, *visitor );
    248234                                                }
     
    252238                        }
    253239
    254                         void Mangler::postvisit( StructInstType * aggregateUseType ) {
    255                                 mangleRef( aggregateUseType, "s" );
    256                         }
    257 
    258                         void Mangler::postvisit( UnionInstType * aggregateUseType ) {
    259                                 mangleRef( aggregateUseType, "u" );
    260                         }
    261 
    262                         void Mangler::postvisit( EnumInstType * aggregateUseType ) {
    263                                 mangleRef( aggregateUseType, "e" );
    264                         }
    265 
    266                         void Mangler::postvisit( TypeInstType * typeInst ) {
     240                        void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
     241                                mangleRef( aggregateUseType, Encoding::struct_t );
     242                        }
     243
     244                        void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
     245                                mangleRef( aggregateUseType, Encoding::union_t );
     246                        }
     247
     248                        void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
     249                                mangleRef( aggregateUseType, Encoding::enum_t );
     250                        }
     251
     252                        void Mangler_old::postvisit( const TypeInstType * typeInst ) {
    267253                                VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    268254                                if ( varNum == varNums.end() ) {
    269                                         mangleRef( typeInst, "t" );
     255                                        mangleRef( typeInst, Encoding::type );
    270256                                } else {
    271257                                        printQualifiers( typeInst );
    272                                         std::ostringstream numStream;
    273                                         numStream << varNum->second.first;
    274                                         switch ( (TypeDecl::Kind )varNum->second.second ) {
    275                                           case TypeDecl::Dtype:
    276                                                 mangleName << "d";
    277                                                 break;
    278                                           case TypeDecl::Ftype:
    279                                                 mangleName << "f";
    280                                                 break;
    281                                                 case TypeDecl::Ttype:
    282                                                 mangleName << "tVARGS";
    283                                                 break;
    284                                                 default:
    285                                                 assert( false );
    286                                         } // switch
    287                                         mangleName << numStream.str();
    288                                 } // if
    289                         }
    290 
    291                         void Mangler::postvisit( TraitInstType * inst ) {
     258                                        // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
     259                                        //   forall(dtype T) void f(T);
     260                                        //   forall(dtype S) void f(S);
     261                                        // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
     262                                        // are first found and prefixing with the appropriate encoding for the type class.
     263                                        assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
     264                                        mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
     265                                } // if
     266                        }
     267
     268                        void Mangler_old::postvisit( const TraitInstType * inst ) {
    292269                                printQualifiers( inst );
    293                                 mangleName << "_Y" << inst->name << "_";
    294                         }
    295 
    296                         void Mangler::postvisit( TupleType * tupleType ) {
     270                                mangleName << inst->name.size() << inst->name;
     271                        }
     272
     273                        void Mangler_old::postvisit( const TupleType * tupleType ) {
    297274                                printQualifiers( tupleType );
    298                                 mangleName << "T";
     275                                mangleName << Encoding::tuple << tupleType->types.size();
    299276                                acceptAll( tupleType->types, *visitor );
    300                                 mangleName << "_";
    301                         }
    302 
    303                         void Mangler::postvisit( VarArgsType * varArgsType ) {
     277                        }
     278
     279                        void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
    304280                                printQualifiers( varArgsType );
    305                                 mangleName << "VARGS";
    306                         }
    307 
    308                         void Mangler::postvisit( ZeroType * ) {
    309                                 mangleName << "Z";
    310                         }
    311 
    312                         void Mangler::postvisit( OneType * ) {
    313                                 mangleName << "O";
    314                         }
    315 
    316                         void Mangler::postvisit( TypeDecl * decl ) {
    317                                 static const char *typePrefix[] = { "BT", "BD", "BF" };
    318                                 mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name;
     281                                static const std::string vargs = "__builtin_va_list";
     282                                mangleName << Encoding::type << vargs.size() << vargs;
     283                        }
     284
     285                        void Mangler_old::postvisit( const ZeroType * ) {
     286                                mangleName << Encoding::zero;
     287                        }
     288
     289                        void Mangler_old::postvisit( const OneType * ) {
     290                                mangleName << Encoding::one;
     291                        }
     292
     293                        void Mangler_old::postvisit( const QualifiedType * qualType ) {
     294                                bool inqual = inQualifiedType;
     295                                if (! inqual ) {
     296                                        // N marks the start of a qualified type
     297                                        inQualifiedType = true;
     298                                        mangleName << Encoding::qualifiedTypeStart;
     299                                }
     300                                maybeAccept( qualType->parent, *visitor );
     301                                maybeAccept( qualType->child, *visitor );
     302                                if ( ! inqual ) {
     303                                        // E marks the end of a qualified type
     304                                        inQualifiedType = false;
     305                                        mangleName << Encoding::qualifiedTypeEnd;
     306                                }
     307                        }
     308
     309                        void Mangler_old::postvisit( const TypeDecl * decl ) {
     310                                // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
     311                                // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
     312                                // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
     313                                // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
     314                                // aside from the assert false.
     315                                assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl));
     316                                assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
     317                                mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
    319318                        }
    320319
     
    325324                        }
    326325
    327                         void Mangler::printQualifiers( Type * type ) {
     326                        void Mangler_old::printQualifiers( const Type * type ) {
    328327                                // skip if not including qualifiers
    329328                                if ( typeMode ) return;
    330                                 if ( ! type->get_forall().empty() ) {
     329                                if ( ! type->forall.empty() ) {
    331330                                        std::list< std::string > assertionNames;
    332                                         int tcount = 0, dcount = 0, fcount = 0, vcount = 0;
    333                                         mangleName << "A";
    334                                         for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    335                                                 switch ( (*i)->get_kind() ) {
     331                                        int dcount = 0, fcount = 0, vcount = 0, acount = 0;
     332                                        mangleName << Encoding::forall;
     333                                        for ( const TypeDecl * i : type->forall ) {
     334                                                switch ( i->kind ) {
    336335                                                  case TypeDecl::Dtype:
    337336                                                        dcount++;
     
    346345                                                        assert( false );
    347346                                                } // switch
    348                                                 varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
    349                                                 for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
    350                                                         PassVisitor<Mangler> sub_mangler( mangleOverridable, typeMode, mangleGenericParams );
    351                                                         sub_mangler.pass.nextVarNum = nextVarNum;
    352                                                         sub_mangler.pass.isTopLevel = false;
    353                                                         sub_mangler.pass.varNums = varNums;
    354                                                         (*assert)->accept( sub_mangler );
    355                                                         assertionNames.push_back( sub_mangler.pass.mangleName.str() );
     347                                                varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
     348                                                for ( const DeclarationWithType * assert : i->assertions ) {
     349                                                        PassVisitor<Mangler_old> sub_mangler(
     350                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
     351                                                        assert->accept( sub_mangler );
     352                                                        assertionNames.push_back( sub_mangler.pass.get_mangleName() );
     353                                                        acount++;
    356354                                                } // for
    357355                                        } // for
    358                                         mangleName << tcount << "_" << dcount << "_" << fcount << "_" << vcount << "_";
     356                                        mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
    359357                                        std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    360358                                        mangleName << "_";
     
    363361                                        // these qualifiers do not distinguish the outermost type of a function parameter
    364362                                        if ( type->get_const() ) {
    365                                                 mangleName << "C";
     363                                                mangleName << Encoding::qualifiers.at(Type::Const);
    366364                                        } // if
    367365                                        if ( type->get_volatile() ) {
    368                                                 mangleName << "V";
     366                                                mangleName << Encoding::qualifiers.at(Type::Volatile);
    369367                                        } // if
    370368                                        // Removed due to restrict not affecting function compatibility in GCC
     
    373371                                        // } // if
    374372                                        if ( type->get_atomic() ) {
    375                                                 mangleName << "A";
     373                                                mangleName << Encoding::qualifiers.at(Type::Atomic);
    376374                                        } // if
    377375                                }
    378376                                if ( type->get_mutex() ) {
    379                                         mangleName << "M";
    380                                 } // if
    381                                 if ( type->get_lvalue() ) {
    382                                         // mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
    383                                         mangleName << "L";
    384                                 }
    385 
     377                                        mangleName << Encoding::qualifiers.at(Type::Mutex);
     378                                } // if
    386379                                if ( inFunctionType ) {
    387380                                        // turn off inFunctionType so that types can be differentiated for nested qualifiers
     
    394387} // namespace SymTab
    395388
     389namespace Mangle {
     390        namespace {
     391                /// Mangles names to a unique C identifier
     392                struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
     393                        Mangler_new( Mangle::Mode mode );
     394                        Mangler_new( const Mangler_new & ) = delete;
     395
     396                        void previsit( const ast::Node * ) { visit_children = false; }
     397
     398                        void postvisit( const ast::ObjectDecl * declaration );
     399                        void postvisit( const ast::FunctionDecl * declaration );
     400                        void postvisit( const ast::TypeDecl * declaration );
     401
     402                        void postvisit( const ast::VoidType * voidType );
     403                        void postvisit( const ast::BasicType * basicType );
     404                        void postvisit( const ast::PointerType * pointerType );
     405                        void postvisit( const ast::ArrayType * arrayType );
     406                        void postvisit( const ast::ReferenceType * refType );
     407                        void postvisit( const ast::FunctionType * functionType );
     408                        void postvisit( const ast::StructInstType * aggregateUseType );
     409                        void postvisit( const ast::UnionInstType * aggregateUseType );
     410                        void postvisit( const ast::EnumInstType * aggregateUseType );
     411                        void postvisit( const ast::TypeInstType * aggregateUseType );
     412                        void postvisit( const ast::TraitInstType * inst );
     413                        void postvisit( const ast::TupleType * tupleType );
     414                        void postvisit( const ast::VarArgsType * varArgsType );
     415                        void postvisit( const ast::ZeroType * zeroType );
     416                        void postvisit( const ast::OneType * oneType );
     417                        void postvisit( const ast::QualifiedType * qualType );
     418
     419                        std::string get_mangleName() { return mangleName.str(); }
     420                  private:
     421                        std::ostringstream mangleName;  ///< Mangled name being constructed
     422                        typedef std::map< std::string, std::pair< int, int > > VarMapType;
     423                        VarMapType varNums;             ///< Map of type variables to indices
     424                        int nextVarNum;                 ///< Next type variable index
     425                        bool isTopLevel;                ///< Is the Mangler at the top level
     426                        bool mangleOverridable;         ///< Specially mangle overridable built-in methods
     427                        bool typeMode;                  ///< Produce a unique mangled name for a type
     428                        bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
     429                        bool inFunctionType = false;    ///< Include type qualifiers if false.
     430                        bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
     431
     432                  private:
     433                        Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     434                                int nextVarNum, const VarMapType& varNums );
     435                        friend class ast::Pass<Mangler_new>;
     436
     437                  private:
     438                        void mangleDecl( const ast::DeclWithType *declaration );
     439                        void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
     440
     441                        void printQualifiers( const ast::Type *type );
     442                }; // Mangler_new
     443        } // namespace
     444
     445
     446        std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
     447                ast::Pass<Mangler_new> mangler( mode );
     448                maybeAccept( decl, mangler );
     449                return mangler.pass.get_mangleName();
     450        }
     451
     452        namespace {
     453                Mangler_new::Mangler_new( Mangle::Mode mode )
     454                        : nextVarNum( 0 ), isTopLevel( true ),
     455                        mangleOverridable  ( ! mode.no_overrideable   ),
     456                        typeMode           (   mode.type              ),
     457                        mangleGenericParams( ! mode.no_generic_params ) {}
     458
     459                Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
     460                        int nextVarNum, const VarMapType& varNums )
     461                        : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
     462                        mangleOverridable( mangleOverridable ), typeMode( typeMode ),
     463                        mangleGenericParams( mangleGenericParams ) {}
     464
     465                void Mangler_new::mangleDecl( const ast::DeclWithType * decl ) {
     466                        bool wasTopLevel = isTopLevel;
     467                        if ( isTopLevel ) {
     468                                varNums.clear();
     469                                nextVarNum = 0;
     470                                isTopLevel = false;
     471                        } // if
     472                        mangleName << Encoding::manglePrefix;
     473                        CodeGen::OperatorInfo opInfo;
     474                        if ( operatorLookup( decl->name, opInfo ) ) {
     475                                mangleName << opInfo.outputName.size() << opInfo.outputName;
     476                        } else {
     477                                mangleName << decl->name.size() << decl->name;
     478                        } // if
     479                        maybeAccept( decl->get_type(), *visitor );
     480                        if ( mangleOverridable && decl->linkage.is_overrideable ) {
     481                                // want to be able to override autogenerated and intrinsic routines,
     482                                // so they need a different name mangling
     483                                if ( decl->linkage == ast::Linkage::AutoGen ) {
     484                                        mangleName << Encoding::autogen;
     485                                } else if ( decl->linkage == ast::Linkage::Intrinsic ) {
     486                                        mangleName << Encoding::intrinsic;
     487                                } else {
     488                                        // if we add another kind of overridable function, this has to change
     489                                        assert( false && "unknown overrideable linkage" );
     490                                } // if
     491                        }
     492                        isTopLevel = wasTopLevel;
     493                }
     494
     495                void Mangler_new::postvisit( const ast::ObjectDecl * decl ) {
     496                        mangleDecl( decl );
     497                }
     498
     499                void Mangler_new::postvisit( const ast::FunctionDecl * decl ) {
     500                        mangleDecl( decl );
     501                }
     502
     503                void Mangler_new::postvisit( const ast::VoidType * voidType ) {
     504                        printQualifiers( voidType );
     505                        mangleName << Encoding::void_t;
     506                }
     507
     508                void Mangler_new::postvisit( const ast::BasicType * basicType ) {
     509                        printQualifiers( basicType );
     510                        assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
     511                        mangleName << Encoding::basicTypes[ basicType->kind ];
     512                }
     513
     514                void Mangler_new::postvisit( const ast::PointerType * pointerType ) {
     515                        printQualifiers( pointerType );
     516                        // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
     517                        if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer;
     518                        maybe_accept( pointerType->base.get(), *visitor );
     519                }
     520
     521                void Mangler_new::postvisit( const ast::ArrayType * arrayType ) {
     522                        // TODO: encode dimension
     523                        printQualifiers( arrayType );
     524                        mangleName << Encoding::array << "0";
     525                        maybeAccept( arrayType->base.get(), *visitor );
     526                }
     527
     528                void Mangler_new::postvisit( const ast::ReferenceType * refType ) {
     529                        // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
     530                        // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
     531                        // by pretending every reference type is a function parameter.
     532                        GuardValue( inFunctionType );
     533                        inFunctionType = true;
     534                        printQualifiers( refType );
     535                        maybeAccept( refType->base.get(), *visitor );
     536                }
     537
     538                inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {
     539                        std::vector< ast::ptr< ast::Type > > ret;
     540                        std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
     541                                                        std::mem_fun( &ast::DeclWithType::get_type ) );
     542                        return ret;
     543                }
     544
     545                void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
     546                        printQualifiers( functionType );
     547                        mangleName << Encoding::function;
     548                        // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
     549                        // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
     550                        // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
     551                        GuardValue( inFunctionType );
     552                        inFunctionType = true;
     553                        std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
     554                        if (returnTypes.empty()) mangleName << Encoding::void_t;
     555                        else accept_each( returnTypes, *visitor );
     556                        mangleName << "_";
     557                        std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
     558                        accept_each( paramTypes, *visitor );
     559                        mangleName << "_";
     560                }
     561
     562                void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
     563                        printQualifiers( refType );
     564
     565                        mangleName << prefix << refType->name.length() << refType->name;
     566
     567                        if ( mangleGenericParams ) {
     568                                if ( ! refType->params.empty() ) {
     569                                        mangleName << "_";
     570                                        for ( const ast::Expr * param : refType->params ) {
     571                                                auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
     572                                                assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
     573                                                maybeAccept( paramType->type.get(), *visitor );
     574                                        }
     575                                        mangleName << "_";
     576                                }
     577                        }
     578                }
     579
     580                void Mangler_new::postvisit( const ast::StructInstType * aggregateUseType ) {
     581                        mangleRef( aggregateUseType, Encoding::struct_t );
     582                }
     583
     584                void Mangler_new::postvisit( const ast::UnionInstType * aggregateUseType ) {
     585                        mangleRef( aggregateUseType, Encoding::union_t );
     586                }
     587
     588                void Mangler_new::postvisit( const ast::EnumInstType * aggregateUseType ) {
     589                        mangleRef( aggregateUseType, Encoding::enum_t );
     590                }
     591
     592                void Mangler_new::postvisit( const ast::TypeInstType * typeInst ) {
     593                        VarMapType::iterator varNum = varNums.find( typeInst->name );
     594                        if ( varNum == varNums.end() ) {
     595                                mangleRef( typeInst, Encoding::type );
     596                        } else {
     597                                printQualifiers( typeInst );
     598                                // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
     599                                //   forall(dtype T) void f(T);
     600                                //   forall(dtype S) void f(S);
     601                                // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
     602                                // are first found and prefixing with the appropriate encoding for the type class.
     603                                assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
     604                                mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
     605                        } // if
     606                }
     607
     608                void Mangler_new::postvisit( const ast::TraitInstType * inst ) {
     609                        printQualifiers( inst );
     610                        mangleName << inst->name.size() << inst->name;
     611                }
     612
     613                void Mangler_new::postvisit( const ast::TupleType * tupleType ) {
     614                        printQualifiers( tupleType );
     615                        mangleName << Encoding::tuple << tupleType->types.size();
     616                        accept_each( tupleType->types, *visitor );
     617                }
     618
     619                void Mangler_new::postvisit( const ast::VarArgsType * varArgsType ) {
     620                        printQualifiers( varArgsType );
     621                        static const std::string vargs = "__builtin_va_list";
     622                        mangleName << Encoding::type << vargs.size() << vargs;
     623                }
     624
     625                void Mangler_new::postvisit( const ast::ZeroType * ) {
     626                        mangleName << Encoding::zero;
     627                }
     628
     629                void Mangler_new::postvisit( const ast::OneType * ) {
     630                        mangleName << Encoding::one;
     631                }
     632
     633                void Mangler_new::postvisit( const ast::QualifiedType * qualType ) {
     634                        bool inqual = inQualifiedType;
     635                        if (! inqual ) {
     636                                // N marks the start of a qualified type
     637                                inQualifiedType = true;
     638                                mangleName << Encoding::qualifiedTypeStart;
     639                        }
     640                        maybeAccept( qualType->parent.get(), *visitor );
     641                        maybeAccept( qualType->child.get(), *visitor );
     642                        if ( ! inqual ) {
     643                                // E marks the end of a qualified type
     644                                inQualifiedType = false;
     645                                mangleName << Encoding::qualifiedTypeEnd;
     646                        }
     647                }
     648
     649                void Mangler_new::postvisit( const ast::TypeDecl * decl ) {
     650                        // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
     651                        // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
     652                        // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
     653                        // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
     654                        // aside from the assert false.
     655                        assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl));
     656                        assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
     657                        mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
     658                }
     659
     660                __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
     661                        for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
     662                                os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
     663                        } // for
     664                }
     665
     666                void Mangler_new::printQualifiers( const ast::Type * type ) {
     667                        // skip if not including qualifiers
     668                        if ( typeMode ) return;
     669                        if ( auto ptype = dynamic_cast< const ast::ParameterizedType * >(type) ) {
     670                                if ( ! ptype->forall.empty() ) {
     671                                        std::list< std::string > assertionNames;
     672                                        int dcount = 0, fcount = 0, vcount = 0, acount = 0;
     673                                        mangleName << Encoding::forall;
     674                                        for ( const ast::TypeDecl * decl : ptype->forall ) {
     675                                                switch ( decl->kind ) {
     676                                                case ast::TypeVar::Kind::Dtype:
     677                                                        dcount++;
     678                                                        break;
     679                                                case ast::TypeVar::Kind::Ftype:
     680                                                        fcount++;
     681                                                        break;
     682                                                case ast::TypeVar::Kind::Ttype:
     683                                                        vcount++;
     684                                                        break;
     685                                                default:
     686                                                        assert( false );
     687                                                } // switch
     688                                                varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
     689                                                for ( const ast::DeclWithType * assert : decl->assertions ) {
     690                                                        ast::Pass<Mangler_new> sub_mangler(
     691                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
     692                                                        assert->accept( sub_mangler );
     693                                                        assertionNames.push_back( sub_mangler.pass.get_mangleName() );
     694                                                        acount++;
     695                                                } // for
     696                                        } // for
     697                                        mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
     698                                        std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
     699                                        mangleName << "_";
     700                                } // if
     701                        } // if
     702                        if ( ! inFunctionType ) {
     703                                // these qualifiers do not distinguish the outermost type of a function parameter
     704                                if ( type->is_const() ) {
     705                                        mangleName << Encoding::qualifiers.at(Type::Const);
     706                                } // if
     707                                if ( type->is_volatile() ) {
     708                                        mangleName << Encoding::qualifiers.at(Type::Volatile);
     709                                } // if
     710                                // Removed due to restrict not affecting function compatibility in GCC
     711                                // if ( type->get_isRestrict() ) {
     712                                //      mangleName << "E";
     713                                // } // if
     714                                if ( type->is_atomic() ) {
     715                                        mangleName << Encoding::qualifiers.at(Type::Atomic);
     716                                } // if
     717                        }
     718                        if ( type->is_mutex() ) {
     719                                mangleName << Encoding::qualifiers.at(Type::Mutex);
     720                        } // if
     721                        if ( inFunctionType ) {
     722                                // turn off inFunctionType so that types can be differentiated for nested qualifiers
     723                                GuardValue( inFunctionType );
     724                                inFunctionType = false;
     725                        }
     726                }
     727        }       // namespace
     728} // namespace Mangle
     729
    396730// Local Variables: //
    397731// tab-width: 4 //
  • src/SymTab/Mangler.h

    r7951100 rb067d9b  
    2121#include <utility>            // for pair
    2222
     23#include "AST/Bitfield.hpp"
     24#include "AST/Fwd.hpp"
    2325#include "SynTree/SynTree.h"  // for Types
    2426#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
     27
     28// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
     29// The CFA name mangling scheme is based closely on the itanium C++ name mangling scheme, with the following key differences:
     30// * Variable names are also mangled to include type information, not just functions
     31// * CFA does not have template expansion, so the rules for function specialization do not apply.
     32// * CFA instead has to handle type parameters and assertion parameters.
     33// * Currently name compression is not implemented.
     34
     35namespace ResolvExpr {
     36        class TypeEnvironment;
     37}
    2538
    2639namespace SymTab {
    2740        namespace Mangler {
    2841                /// Mangle syntax tree object; primary interface to clients
    29                 std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
     42                std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
    3043
    3144                /// Mangle a type name; secondary interface
    32                 std::string mangleType( Type* ty );
     45                std::string mangleType( const Type * ty );
    3346                /// Mangle ignoring generic type parameters
    34                 std::string mangleConcrete( Type* ty );
     47                std::string mangleConcrete( const Type * ty );
     48
     49                namespace Encoding {
     50                        extern const std::string manglePrefix;
     51                        extern const std::string basicTypes[];
     52                        extern const std::map<int, std::string> qualifiers;
     53
     54                        extern const std::string void_t;
     55                        extern const std::string zero;
     56                        extern const std::string one;
     57
     58                        extern const std::string function;
     59                        extern const std::string tuple;
     60                        extern const std::string pointer;
     61                        extern const std::string array;
     62                        extern const std::string qualifiedTypeStart;
     63                        extern const std::string qualifiedTypeEnd;
     64
     65                        extern const std::string forall;
     66                        extern const std::string typeVariables[];
     67
     68                        extern const std::string struct_t;
     69                        extern const std::string union_t;
     70                        extern const std::string enum_t;
     71                        extern const std::string type;
     72
     73                        extern const std::string autogen;
     74                        extern const std::string intrinsic;
     75                };
    3576        } // Mangler
    3677} // SymTab
     78
     79namespace Mangle {
     80        /// Bitflags for mangle modes
     81        enum {
     82                NoOverrideable  = 1 << 0,
     83                Type            = 1 << 1,
     84                NoGenericParams = 1 << 2
     85        };
     86
     87        /// Bitflag type for mangler modes
     88        struct mangle_flags {
     89                union {
     90                        unsigned int val;
     91                        struct {
     92                                bool no_overrideable   : 1;
     93                                bool type              : 1;
     94                                bool no_generic_params : 1;
     95                        };
     96                };
     97
     98                constexpr mangle_flags( unsigned int val ) : val(val) {}
     99        };
     100
     101        using Mode = bitfield<mangle_flags>;
     102
     103        static inline Mode typeMode() { return NoOverrideable | Type; }
     104
     105        /// Mangle declaration name
     106        std::string mangle( const ast::Node * decl, Mode mode = {} );
     107
     108        namespace Encoding {
     109                using namespace SymTab::Mangler::Encoding;
     110        };
     111}
     112
     113extern "C" {
     114        char * cforall_demangle(const char *, int);
     115}
    37116
    38117// Local Variables: //
  • src/SymTab/Validate.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 28 13:47:23 2017
    13 // Update Count     : 359
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Aug  7 6:42:00 2019
     13// Update Count     : 360
    1414//
    1515
     
    4444#include <list>                        // for list
    4545#include <string>                      // for string
     46#include <unordered_map>               // for unordered_map
    4647#include <utility>                     // for pair
    4748
     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"
    4856#include "CodeGen/CodeGenerator.h"     // for genName
    4957#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5058#include "ControlStruct/Mutate.h"      // for ForExprMutator
     59#include "Common/CodeLocation.h"       // for CodeLocation
     60#include "Common/Stats.h"              // for Stats::Heap
    5161#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
    5262#include "Common/ScopedMap.h"          // for ScopedMap
     
    6171#include "Parser/LinkageSpec.h"        // for C
    6272#include "ResolvExpr/typeops.h"        // for typesCompatible
     73#include "ResolvExpr/Resolver.h"       // for findSingleExpression
     74#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
    6375#include "SymTab/Autogen.h"            // for SizeType
    6476#include "SynTree/Attribute.h"         // for noAttributes, Attribute
     
    7284#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    7385#include "SynTree/Visitor.h"           // for Visitor
     86#include "Validate/HandleAttributes.h" // for handleAttributes
     87#include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
    7488
    7589class CompoundStmt;
     
    7791class SwitchStmt;
    7892
    79 #define debugPrint( x ) if ( doDebug ) { std::cout << x; }
     93#define debugPrint( x ) if ( doDebug ) x
    8094
    8195namespace SymTab {
     96        /// hoists declarations that are difficult to hoist while parsing
     97        struct HoistTypeDecls final : public WithDeclsToAdd {
     98                void previsit( SizeofExpr * );
     99                void previsit( AlignofExpr * );
     100                void previsit( UntypedOffsetofExpr * );
     101                void previsit( CompoundLiteralExpr * );
     102                void handleType( Type * );
     103        };
     104
     105        struct FixQualifiedTypes final : public WithIndexer {
     106                Type * postmutate( QualifiedType * );
     107        };
     108
    82109        struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
    83110                /// Flattens nested struct types
    84111                static void hoistStruct( std::list< Declaration * > &translationUnit );
    85112
    86                 void previsit( EnumInstType * enumInstType );
    87                 void previsit( StructInstType * structInstType );
    88                 void previsit( UnionInstType * unionInstType );
    89113                void previsit( StructDecl * aggregateDecl );
    90114                void previsit( UnionDecl * aggregateDecl );
    91115                void previsit( StaticAssertDecl * assertDecl );
     116                void previsit( StructInstType * type );
     117                void previsit( UnionInstType * type );
     118                void previsit( EnumInstType * type );
    92119
    93120          private:
    94                 template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
     121                template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );
    95122
    96123                AggregateDecl * parentAggr = nullptr;
     
    106133
    107134        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    108         struct EnumAndPointerDecay {
    109                 void previsit( EnumDecl *aggregateDecl );
    110                 void previsit( FunctionType *func );
     135        struct EnumAndPointerDecay_old {
     136                void previsit( EnumDecl * aggregateDecl );
     137                void previsit( FunctionType * func );
    111138        };
    112139
    113140        /// Associates forward declarations of aggregates with their definitions
    114         struct LinkReferenceToTypes final : public WithIndexer, public WithGuards {
    115                 LinkReferenceToTypes( const Indexer *indexer );
    116                 void postvisit( TypeInstType *typeInst );
    117 
    118                 void postvisit( EnumInstType *enumInst );
    119                 void postvisit( StructInstType *structInst );
    120                 void postvisit( UnionInstType *unionInst );
    121                 void postvisit( TraitInstType *traitInst );
    122 
    123                 void postvisit( EnumDecl *enumDecl );
    124                 void postvisit( StructDecl *structDecl );
    125                 void postvisit( UnionDecl *unionDecl );
     141        struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
     142                LinkReferenceToTypes_old( const Indexer * indexer );
     143                void postvisit( TypeInstType * typeInst );
     144
     145                void postvisit( EnumInstType * enumInst );
     146                void postvisit( StructInstType * structInst );
     147                void postvisit( UnionInstType * unionInst );
     148                void postvisit( TraitInstType * traitInst );
     149                void previsit( QualifiedType * qualType );
     150                void postvisit( QualifiedType * qualType );
     151
     152                void postvisit( EnumDecl * enumDecl );
     153                void postvisit( StructDecl * structDecl );
     154                void postvisit( UnionDecl * unionDecl );
    126155                void postvisit( TraitDecl * traitDecl );
    127156
    128                 void previsit( StructDecl *structDecl );
    129                 void previsit( UnionDecl *unionDecl );
     157                void previsit( StructDecl * structDecl );
     158                void previsit( UnionDecl * unionDecl );
    130159
    131160                void renameGenericParams( std::list< TypeDecl * > & params );
    132161
    133162          private:
    134                 const Indexer *local_indexer;
     163                const Indexer * local_indexer;
    135164
    136165                typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
     
    145174
    146175        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
    147         struct ForallPointerDecay final {
     176        struct ForallPointerDecay_old final {
    148177                void previsit( ObjectDecl * object );
    149178                void previsit( FunctionDecl * func );
     
    165194        };
    166195
    167         struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
    168                 EliminateTypedef() : scopeLevel( 0 ) {}
     196        struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
     197                ReplaceTypedef() : scopeLevel( 0 ) {}
    169198                /// Replaces typedefs by forward declarations
    170                 static void eliminateTypedef( std::list< Declaration * > &translationUnit );
    171 
     199                static void replaceTypedef( std::list< Declaration * > &translationUnit );
     200
     201                void premutate( QualifiedType * );
     202                Type * postmutate( QualifiedType * qualType );
    172203                Type * postmutate( TypeInstType * aggregateUseType );
    173204                Declaration * postmutate( TypedefDecl * typeDecl );
     
    180211
    181212                void premutate( CompoundStmt * compoundStmt );
    182                 CompoundStmt * postmutate( CompoundStmt * compoundStmt );
    183213
    184214                void premutate( StructDecl * structDecl );
    185                 Declaration * postmutate( StructDecl * structDecl );
    186215                void premutate( UnionDecl * unionDecl );
    187                 Declaration * postmutate( UnionDecl * unionDecl );
    188216                void premutate( EnumDecl * enumDecl );
    189                 Declaration * postmutate( EnumDecl * enumDecl );
    190                 Declaration * postmutate( TraitDecl * contextDecl );
     217                void premutate( TraitDecl * );
    191218
    192219                void premutate( FunctionType * ftype );
     
    194221          private:
    195222                template<typename AggDecl>
    196                 AggDecl *handleAggregate( AggDecl * aggDecl );
    197 
    198                 template<typename AggDecl>
    199223                void addImplicitTypedef( AggDecl * aggDecl );
     224                template< typename AggDecl >
     225                void handleAggregate( AggDecl * aggr );
    200226
    201227                typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
    202228                typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap;
    203                 typedef std::map< std::string, TypeDecl * > TypeDeclMap;
     229                typedef ScopedMap< std::string, TypeDecl * > TypeDeclMap;
    204230                TypedefMap typedefNames;
    205231                TypeDeclMap typedeclNames;
    206232                int scopeLevel;
    207233                bool inFunctionType = false;
     234        };
     235
     236        struct EliminateTypedef {
     237                /// removes TypedefDecls from the AST
     238                static void eliminateTypedef( std::list< Declaration * > &translationUnit );
     239
     240                template<typename AggDecl>
     241                void handleAggregate( AggDecl * aggregateDecl );
     242
     243                void previsit( StructDecl * aggregateDecl );
     244                void previsit( UnionDecl * aggregateDecl );
     245                void previsit( CompoundStmt * compoundStmt );
    208246        };
    209247
     
    214252                static void verify( std::list< Declaration * > &translationUnit );
    215253
    216                 void previsit( FunctionDecl *funcDecl );
     254                void previsit( FunctionDecl * funcDecl );
    217255        };
    218256
     
    223261        };
    224262
    225         struct ArrayLength {
     263        struct FixObjectType : public WithIndexer {
     264                /// resolves typeof type in object, function, and type declarations
     265                static void fix( std::list< Declaration * > & translationUnit );
     266
     267                void previsit( ObjectDecl * );
     268                void previsit( FunctionDecl * );
     269                void previsit( TypeDecl * );
     270        };
     271
     272        struct ArrayLength : public WithIndexer {
    226273                /// for array types without an explicit length, compute the length and store it so that it
    227274                /// is known to the rest of the phases. For example,
     
    234281
    235282                void previsit( ObjectDecl * objDecl );
     283                void previsit( ArrayType * arrayType );
    236284        };
    237285
     
    239287                Type::StorageClasses storageClasses;
    240288
    241                 void premutate( ObjectDecl *objectDecl );
    242                 Expression * postmutate( CompoundLiteralExpr *compLitExpr );
     289                void premutate( ObjectDecl * objectDecl );
     290                Expression * postmutate( CompoundLiteralExpr * compLitExpr );
    243291        };
    244292
     
    250298        };
    251299
    252         FunctionDecl * dereferenceOperator = nullptr;
    253         struct FindSpecialDeclarations final {
    254                 void previsit( FunctionDecl * funcDecl );
    255         };
    256 
    257300        void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
    258                 PassVisitor<EnumAndPointerDecay> epc;
    259                 PassVisitor<LinkReferenceToTypes> lrt( nullptr );
    260                 PassVisitor<ForallPointerDecay> fpd;
     301                PassVisitor<EnumAndPointerDecay_old> epc;
     302                PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
     303                PassVisitor<ForallPointerDecay_old> fpd;
    261304                PassVisitor<CompoundLiteral> compoundliteral;
    262305                PassVisitor<ValidateGenericParameters> genericParams;
    263                 PassVisitor<FindSpecialDeclarations> finder;
    264306                PassVisitor<LabelAddressFixer> labelAddrFixer;
    265 
    266                 EliminateTypedef::eliminateTypedef( translationUnit );
    267                 HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
    268                 ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    269                 acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling
    270                 acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
    271                 acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes
    272                 VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
    273                 ReturnChecker::checkFunctionReturns( translationUnit );
    274                 InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
    275                 Concurrency::applyKeywords( translationUnit );
    276                 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    277                 ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
    278                 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
    279                 Concurrency::implementMutexFuncs( translationUnit );
    280                 Concurrency::implementThreadStarter( translationUnit );
    281                 mutateAll( translationUnit, compoundliteral );
    282                 ArrayLength::computeLength( translationUnit );
    283                 acceptAll( translationUnit, finder ); // xxx - remove this pass soon
    284                 mutateAll( translationUnit, labelAddrFixer );
    285         }
    286 
    287         void validateType( Type *type, const Indexer *indexer ) {
    288                 PassVisitor<EnumAndPointerDecay> epc;
    289                 PassVisitor<LinkReferenceToTypes> lrt( indexer );
    290                 PassVisitor<ForallPointerDecay> fpd;
     307                PassVisitor<HoistTypeDecls> hoistDecls;
     308                PassVisitor<FixQualifiedTypes> fixQual;
     309
     310                {
     311                        Stats::Heap::newPass("validate-A");
     312                        Stats::Time::BlockGuard guard("validate-A");
     313                        acceptAll( translationUnit, hoistDecls );
     314                        ReplaceTypedef::replaceTypedef( translationUnit );
     315                        ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
     316                        acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
     317                }
     318                {
     319                        Stats::Heap::newPass("validate-B");
     320                        Stats::Time::BlockGuard guard("validate-B");
     321                        Stats::Time::TimeBlock("Link Reference To Types", [&]() {
     322                                acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
     323                        });
     324                        Stats::Time::TimeBlock("Fix Qualified Types", [&]() {
     325                                mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
     326                        });
     327                        Stats::Time::TimeBlock("Hoist Structs", [&]() {
     328                                HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
     329                        });
     330                        Stats::Time::TimeBlock("Eliminate Typedefs", [&]() {
     331                                EliminateTypedef::eliminateTypedef( translationUnit ); //
     332                        });
     333                }
     334                {
     335                        Stats::Heap::newPass("validate-C");
     336                        Stats::Time::BlockGuard guard("validate-C");
     337                        acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes_old
     338                        VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
     339                        ReturnChecker::checkFunctionReturns( translationUnit );
     340                        InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
     341                }
     342                {
     343                        Stats::Heap::newPass("validate-D");
     344                        Stats::Time::BlockGuard guard("validate-D");
     345                        Stats::Time::TimeBlock("Apply Concurrent Keywords", [&]() {
     346                                Concurrency::applyKeywords( translationUnit );
     347                        });
     348                        Stats::Time::TimeBlock("Forall Pointer Decay", [&]() {
     349                                acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
     350                        });
     351                        Stats::Time::TimeBlock("Hoist Control Declarations", [&]() {
     352                                ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
     353                        });
     354                        Stats::Time::TimeBlock("Generate Autogen routines", [&]() {
     355                                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old
     356                        });
     357                }
     358                {
     359                        Stats::Heap::newPass("validate-E");
     360                        Stats::Time::BlockGuard guard("validate-E");
     361                        Stats::Time::TimeBlock("Implement Mutex Func", [&]() {
     362                                Concurrency::implementMutexFuncs( translationUnit );
     363                        });
     364                        Stats::Time::TimeBlock("Implement Thread Start", [&]() {
     365                                Concurrency::implementThreadStarter( translationUnit );
     366                        });
     367                        Stats::Time::TimeBlock("Compound Literal", [&]() {
     368                                mutateAll( translationUnit, compoundliteral );
     369                        });
     370                        Stats::Time::TimeBlock("Resolve With Expressions", [&]() {
     371                                ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
     372                        });
     373                }
     374                {
     375                        Stats::Heap::newPass("validate-F");
     376                        Stats::Time::BlockGuard guard("validate-F");
     377                        Stats::Time::TimeBlock("Fix Object Type", [&]() {
     378                                FixObjectType::fix( translationUnit );
     379                        });
     380                        Stats::Time::TimeBlock("Array Length", [&]() {
     381                                ArrayLength::computeLength( translationUnit );
     382                        });
     383                        Stats::Time::TimeBlock("Find Special Declarations", [&]() {
     384                                Validate::findSpecialDecls( translationUnit );
     385                        });
     386                        Stats::Time::TimeBlock("Fix Label Address", [&]() {
     387                                mutateAll( translationUnit, labelAddrFixer );
     388                        });
     389                        Stats::Time::TimeBlock("Handle Attributes", [&]() {
     390                                Validate::handleAttributes( translationUnit );
     391                        });
     392                }
     393        }
     394
     395        void validateType( Type * type, const Indexer * indexer ) {
     396                PassVisitor<EnumAndPointerDecay_old> epc;
     397                PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
     398                PassVisitor<ForallPointerDecay_old> fpd;
    291399                type->accept( epc );
    292400                type->accept( lrt );
     
    294402        }
    295403
     404
     405        void HoistTypeDecls::handleType( Type * type ) {
     406                // some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here
     407                AggregateDecl * aggr = nullptr;
     408                if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
     409                        aggr = inst->baseStruct;
     410                } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
     411                        aggr = inst->baseUnion;
     412                } else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( type ) ) {
     413                        aggr = inst->baseEnum;
     414                }
     415                if ( aggr && aggr->body ) {
     416                        declsToAddBefore.push_front( aggr );
     417                }
     418        }
     419
     420        void HoistTypeDecls::previsit( SizeofExpr * expr ) {
     421                handleType( expr->type );
     422        }
     423
     424        void HoistTypeDecls::previsit( AlignofExpr * expr ) {
     425                handleType( expr->type );
     426        }
     427
     428        void HoistTypeDecls::previsit( UntypedOffsetofExpr * expr ) {
     429                handleType( expr->type );
     430        }
     431
     432        void HoistTypeDecls::previsit( CompoundLiteralExpr * expr ) {
     433                handleType( expr->result );
     434        }
     435
     436
     437        Type * FixQualifiedTypes::postmutate( QualifiedType * qualType ) {
     438                Type * parent = qualType->parent;
     439                Type * child = qualType->child;
     440                if ( dynamic_cast< GlobalScopeType * >( qualType->parent ) ) {
     441                        // .T => lookup T at global scope
     442                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
     443                                auto td = indexer.globalLookupType( inst->name );
     444                                if ( ! td ) {
     445                                        SemanticError( qualType->location, toString("Use of undefined global type ", inst->name) );
     446                                }
     447                                auto base = td->base;
     448                                assert( base );
     449                                Type * ret = base->clone();
     450                                ret->get_qualifiers() = qualType->get_qualifiers();
     451                                return ret;
     452                        } else {
     453                                // .T => T is not a type name
     454                                assertf( false, "unhandled global qualified child type: %s", toCString(child) );
     455                        }
     456                } else {
     457                        // S.T => S must be an aggregate type, find the declaration for T in S.
     458                        AggregateDecl * aggr = nullptr;
     459                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( parent ) ) {
     460                                aggr = inst->baseStruct;
     461                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * > ( parent ) ) {
     462                                aggr = inst->baseUnion;
     463                        } else {
     464                                SemanticError( qualType->location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
     465                        }
     466                        assert( aggr ); // TODO: need to handle forward declarations
     467                        for ( Declaration * member : aggr->members ) {
     468                                if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
     469                                        // name on the right is a typedef
     470                                        if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
     471                                                if ( aggr->name == inst->name ) {
     472                                                        assert( aggr->base );
     473                                                        Type * ret = aggr->base->clone();
     474                                                        ret->get_qualifiers() = qualType->get_qualifiers();
     475                                                        TypeSubstitution sub = parent->genericSubstitution();
     476                                                        sub.apply(ret);
     477                                                        return ret;
     478                                                }
     479                                        }
     480                                } else {
     481                                        // S.T - S is not an aggregate => error
     482                                        assertf( false, "unhandled qualified child type: %s", toCString(qualType) );
     483                                }
     484                        }
     485                        // failed to find a satisfying definition of type
     486                        SemanticError( qualType->location, toString("Undefined type in qualified type: ", qualType) );
     487                }
     488
     489                // ... may want to link canonical SUE definition to each forward decl so that it becomes easier to lookup?
     490        }
     491
     492
    296493        void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
    297494                PassVisitor<HoistStruct> hoister;
     
    299496        }
    300497
    301         bool shouldHoist( Declaration *decl ) {
     498        bool shouldHoist( Declaration * decl ) {
    302499                return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
    303500        }
    304501
     502        namespace {
     503                void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) {
     504                        if ( aggr->parent ) qualifiedName( aggr->parent, ss );
     505                        ss << "__" << aggr->name;
     506                }
     507
     508                // mangle nested type names using entire parent chain
     509                std::string qualifiedName( AggregateDecl * aggr ) {
     510                        std::ostringstream ss;
     511                        qualifiedName( aggr, ss );
     512                        return ss.str();
     513                }
     514        }
     515
    305516        template< typename AggDecl >
    306         void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
     517        void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {
    307518                if ( parentAggr ) {
     519                        aggregateDecl->parent = parentAggr;
     520                        aggregateDecl->name = qualifiedName( aggregateDecl );
    308521                        // Add elements in stack order corresponding to nesting structure.
    309522                        declsToAddBefore.push_front( aggregateDecl );
     
    316529        }
    317530
    318         void HoistStruct::previsit( EnumInstType * inst ) {
    319                 if ( inst->baseEnum && inst->baseEnum->body ) {
    320                         declsToAddBefore.push_front( inst->baseEnum );
    321                 }
    322         }
    323 
    324         void HoistStruct::previsit( StructInstType * inst ) {
    325                 if ( inst->baseStruct && inst->baseStruct->body ) {
    326                         declsToAddBefore.push_front( inst->baseStruct );
    327                 }
    328         }
    329 
    330         void HoistStruct::previsit( UnionInstType * inst ) {
    331                 if ( inst->baseUnion && inst->baseUnion->body ) {
    332                         declsToAddBefore.push_front( inst->baseUnion );
    333                 }
    334         }
    335 
    336531        void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
    337532                if ( parentAggr ) {
     
    348543        }
    349544
    350         void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
     545        void HoistStruct::previsit( StructInstType * type ) {
     546                // need to reset type name after expanding to qualified name
     547                assert( type->baseStruct );
     548                type->name = type->baseStruct->name;
     549        }
     550
     551        void HoistStruct::previsit( UnionInstType * type ) {
     552                assert( type->baseUnion );
     553                type->name = type->baseUnion->name;
     554        }
     555
     556        void HoistStruct::previsit( EnumInstType * type ) {
     557                assert( type->baseEnum );
     558                type->name = type->baseEnum->name;
     559        }
     560
     561
     562        bool isTypedef( Declaration * decl ) {
     563                return dynamic_cast< TypedefDecl * >( decl );
     564        }
     565
     566        void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
     567                PassVisitor<EliminateTypedef> eliminator;
     568                acceptAll( translationUnit, eliminator );
     569                filter( translationUnit, isTypedef, true );
     570        }
     571
     572        template< typename AggDecl >
     573        void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) {
     574                filter( aggregateDecl->members, isTypedef, true );
     575        }
     576
     577        void EliminateTypedef::previsit( StructDecl * aggregateDecl ) {
     578                handleAggregate( aggregateDecl );
     579        }
     580
     581        void EliminateTypedef::previsit( UnionDecl * aggregateDecl ) {
     582                handleAggregate( aggregateDecl );
     583        }
     584
     585        void EliminateTypedef::previsit( CompoundStmt * compoundStmt ) {
     586                // remove and delete decl stmts
     587                filter( compoundStmt->kids, [](Statement * stmt) {
     588                        if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
     589                                if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) {
     590                                        return true;
     591                                } // if
     592                        } // if
     593                        return false;
     594                }, true);
     595        }
     596
     597        void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) {
    351598                // Set the type of each member of the enumeration to be EnumConstant
    352                 for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
    353                         ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
     599                for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
     600                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );
    354601                        assert( obj );
    355                         obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) );
     602                        obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
    356603                } // for
    357604        }
     
    380627        }
    381628
    382         void EnumAndPointerDecay::previsit( FunctionType *func ) {
     629        void EnumAndPointerDecay_old::previsit( FunctionType * func ) {
    383630                // Fix up parameters and return types
    384631                fixFunctionList( func->parameters, func->isVarArgs, func );
     
    386633        }
    387634
    388         LinkReferenceToTypes::LinkReferenceToTypes( const Indexer *other_indexer ) {
     635        LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {
    389636                if ( other_indexer ) {
    390637                        local_indexer = other_indexer;
     
    394641        }
    395642
    396         void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
    397                 EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name() );
     643        void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {
     644                const EnumDecl * st = local_indexer->lookupEnum( enumInst->name );
    398645                // it's not a semantic error if the enum is not found, just an implicit forward declaration
    399646                if ( st ) {
    400                         //assert( ! enumInst->get_baseEnum() || enumInst->get_baseEnum()->get_members().empty() || ! st->get_members().empty() );
    401                         enumInst->set_baseEnum( st );
    402                 } // if
    403                 if ( ! st || st->get_members().empty() ) {
     647                        enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node
     648                } // if
     649                if ( ! st || ! st->body ) {
    404650                        // use of forward declaration
    405                         forwardEnums[ enumInst->get_name() ].push_back( enumInst );
     651                        forwardEnums[ enumInst->name ].push_back( enumInst );
    406652                } // if
    407653        }
     
    415661        }
    416662
    417         void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
    418                 StructDecl *st = local_indexer->lookupStruct( structInst->get_name() );
     663        void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
     664                const StructDecl * st = local_indexer->lookupStruct( structInst->name );
    419665                // it's not a semantic error if the struct is not found, just an implicit forward declaration
    420666                if ( st ) {
    421                         //assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
    422                         structInst->set_baseStruct( st );
    423                 } // if
    424                 if ( ! st || st->get_members().empty() ) {
     667                        structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node
     668                } // if
     669                if ( ! st || ! st->body ) {
    425670                        // use of forward declaration
    426                         forwardStructs[ structInst->get_name() ].push_back( structInst );
     671                        forwardStructs[ structInst->name ].push_back( structInst );
    427672                } // if
    428673                checkGenericParameters( structInst );
    429674        }
    430675
    431         void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
    432                 UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name() );
     676        void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {
     677                const UnionDecl * un = local_indexer->lookupUnion( unionInst->name );
    433678                // it's not a semantic error if the union is not found, just an implicit forward declaration
    434679                if ( un ) {
    435                         unionInst->set_baseUnion( un );
    436                 } // if
    437                 if ( ! un || un->get_members().empty() ) {
     680                        unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node
     681                } // if
     682                if ( ! un || ! un->body ) {
    438683                        // use of forward declaration
    439                         forwardUnions[ unionInst->get_name() ].push_back( unionInst );
     684                        forwardUnions[ unionInst->name ].push_back( unionInst );
    440685                } // if
    441686                checkGenericParameters( unionInst );
     687        }
     688
     689        void LinkReferenceToTypes_old::previsit( QualifiedType * ) {
     690                visit_children = false;
     691        }
     692
     693        void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) {
     694                // linking only makes sense for the 'oldest ancestor' of the qualified type
     695                qualType->parent->accept( * visitor );
    442696        }
    443697
     
    450704                        DeclarationWithType * dwt2 = dynamic_cast<DeclarationWithType *>( d2 );
    451705                        if ( dwt1 && dwt2 ) {
    452                                 if ( dwt1->get_name() == dwt2->get_name() && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
     706                                if ( dwt1->name == dwt2->name && ResolvExpr::typesCompatible( dwt1->get_type(), dwt2->get_type(), SymTab::Indexer() ) ) {
    453707                                        // std::cerr << "=========== equal:" << std::endl;
    454708                                        // std::cerr << "d1: " << d1 << std::endl;
     
    475729        template< typename Iterator >
    476730        void expandAssertions( TraitInstType * inst, Iterator out ) {
    477                 assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toString( inst ).c_str() );
     731                assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
    478732                std::list< DeclarationWithType * > asserts;
    479733                for ( Declaration * decl : inst->baseTrait->members ) {
     
    484738        }
    485739
    486         void LinkReferenceToTypes::postvisit( TraitDecl * traitDecl ) {
     740        void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
    487741                if ( traitDecl->name == "sized" ) {
    488742                        // "sized" is a special trait - flick the sized status on for the type variable
     
    506760        }
    507761
    508         void LinkReferenceToTypes::postvisit( TraitInstType * traitInst ) {
     762        void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
    509763                // handle other traits
    510                 TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
     764                const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );
    511765                if ( ! traitDecl ) {
    512766                        SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
    513767                } // if
    514                 if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
     768                if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
    515769                        SemanticError( traitInst, "incorrect number of trait parameters: " );
    516770                } // if
    517                 traitInst->baseTrait = traitDecl;
     771                traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node
    518772
    519773                // need to carry over the 'sized' status of each decl in the instance
    520                 for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) {
     774                for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
    521775                        TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
    522776                        if ( ! expr ) {
     
    525779                        if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
    526780                                TypeDecl * formalDecl = std::get<0>(p);
    527                                 TypeDecl * instDecl = inst->get_baseType();
     781                                TypeDecl * instDecl = inst->baseType;
    528782                                if ( formalDecl->get_sized() ) instDecl->set_sized( true );
    529783                        }
     
    532786        }
    533787
    534         void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
     788        void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {
    535789                // visit enum members first so that the types of self-referencing members are updated properly
    536                 if ( ! enumDecl->get_members().empty() ) {
    537                         ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
     790                if ( enumDecl->body ) {
     791                        ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
    538792                        if ( fwds != forwardEnums.end() ) {
    539793                                for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    540                                         (*inst )->set_baseEnum( enumDecl );
     794                                        (* inst)->baseEnum = enumDecl;
    541795                                } // for
    542796                                forwardEnums.erase( fwds );
    543797                        } // if
    544                 } // if
    545         }
    546 
    547         void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
     798
     799                        for ( Declaration * member : enumDecl->members ) {
     800                                ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member );
     801                                if ( field->init ) {
     802                                        // need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information.
     803                                        SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init );
     804                                        ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer );
     805                                }
     806                        }
     807                } // if
     808        }
     809
     810        void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) {
    548811                // rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
    549812                //   forall(otype T)
     
    563826        }
    564827
    565         void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
     828        void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
    566829                renameGenericParams( structDecl->parameters );
    567830        }
    568831
    569         void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
     832        void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
    570833                renameGenericParams( unionDecl->parameters );
    571834        }
    572835
    573         void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
     836        void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {
    574837                // visit struct members first so that the types of self-referencing members are updated properly
    575838                // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
    576                 if ( ! structDecl->get_members().empty() ) {
    577                         ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
     839                if ( structDecl->body ) {
     840                        ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
    578841                        if ( fwds != forwardStructs.end() ) {
    579842                                for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    580                                         (*inst )->set_baseStruct( structDecl );
     843                                        (* inst)->baseStruct = structDecl;
    581844                                } // for
    582845                                forwardStructs.erase( fwds );
     
    585848        }
    586849
    587         void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
    588                 if ( ! unionDecl->get_members().empty() ) {
    589                         ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
     850        void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {
     851                if ( unionDecl->body ) {
     852                        ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
    590853                        if ( fwds != forwardUnions.end() ) {
    591854                                for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
    592                                         (*inst )->set_baseUnion( unionDecl );
     855                                        (* inst)->baseUnion = unionDecl;
    593856                                } // for
    594857                                forwardUnions.erase( fwds );
     
    597860        }
    598861
    599         void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
     862        void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {
    600863                // ensure generic parameter instances are renamed like the base type
    601864                if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
    602                 if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
    603                         if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
    604                                 typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
     865                if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {
     866                        if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) {
     867                                typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
    605868                        } // if
    606869                } // if
     
    614877                        // expand trait instances into their members
    615878                        for ( DeclarationWithType * assertion : asserts ) {
    616                                 if ( TraitInstType *traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     879                                if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
    617880                                        // expand trait instance into all of its members
    618881                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     
    634897        }
    635898
    636         void ForallPointerDecay::previsit( ObjectDecl *object ) {
     899        void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
    637900                // ensure that operator names only apply to functions or function pointers
    638901                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     
    642905        }
    643906
    644         void ForallPointerDecay::previsit( FunctionDecl *func ) {
     907        void ForallPointerDecay_old::previsit( FunctionDecl * func ) {
    645908                func->fixUniqueId();
    646909        }
    647910
    648         void ForallPointerDecay::previsit( FunctionType * ftype ) {
     911        void ForallPointerDecay_old::previsit( FunctionType * ftype ) {
    649912                forallFixer( ftype->forall, ftype );
    650913        }
    651914
    652         void ForallPointerDecay::previsit( StructDecl * aggrDecl ) {
     915        void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) {
    653916                forallFixer( aggrDecl->parameters, aggrDecl );
    654917        }
    655918
    656         void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) {
     919        void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
    657920                forallFixer( aggrDecl->parameters, aggrDecl );
    658921        }
     
    679942
    680943
    681         bool isTypedef( Declaration *decl ) {
    682                 return dynamic_cast< TypedefDecl * >( decl );
    683         }
    684 
    685         void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
    686                 PassVisitor<EliminateTypedef> eliminator;
     944        void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
     945                PassVisitor<ReplaceTypedef> eliminator;
    687946                mutateAll( translationUnit, eliminator );
    688947                if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
    689948                        // grab and remember declaration of size_t
    690                         SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();
     949                        Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
    691950                } else {
    692951                        // xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
    693952                        // eventually should have a warning for this case.
    694                         SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
    695                 }
    696                 filter( translationUnit, isTypedef, true );
    697         }
    698 
    699         Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) {
     953                        Validate::SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     954                }
     955        }
     956
     957        void ReplaceTypedef::premutate( QualifiedType * ) {
     958                visit_children = false;
     959        }
     960
     961        Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) {
     962                // replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type
     963                qualType->parent = qualType->parent->acceptMutator( * visitor );
     964                return qualType;
     965        }
     966
     967        Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
    700968                // instances of typedef types will come here. If it is an instance
    701969                // of a typdef type, link the instance to its actual type.
    702                 TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
     970                TypedefMap::const_iterator def = typedefNames.find( typeInst->name );
    703971                if ( def != typedefNames.end() ) {
    704                         Type *ret = def->second.first->base->clone();
     972                        Type * ret = def->second.first->base->clone();
     973                        ret->location = typeInst->location;
    705974                        ret->get_qualifiers() |= typeInst->get_qualifiers();
    706975                        // attributes are not carried over from typedef to function parameters/return values
     
    713982                        // place instance parameters on the typedef'd type
    714983                        if ( ! typeInst->parameters.empty() ) {
    715                                 ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
     984                                ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret);
    716985                                if ( ! rtt ) {
    717986                                        SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
    718987                                }
    719                                 rtt->get_parameters().clear();
     988                                rtt->parameters.clear();
    720989                                cloneAll( typeInst->parameters, rtt->parameters );
    721                                 mutateAll( rtt->parameters, *visitor );  // recursively fix typedefs on parameters
     990                                mutateAll( rtt->parameters, * visitor );  // recursively fix typedefs on parameters
    722991                        } // if
    723992                        delete typeInst;
    724993                        return ret;
    725994                } else {
    726                         TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->get_name() );
    727                         assertf( base != typedeclNames.end(), "Cannot find typedecl name %s", typeInst->name.c_str() );
     995                        TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name );
     996                        if ( base == typedeclNames.end() ) {
     997                                SemanticError( typeInst->location, toString("Use of undefined type ", typeInst->name) );
     998                        }
    728999                        typeInst->set_baseType( base->second );
    729                 } // if
    730                 return typeInst;
     1000                        return typeInst;
     1001                } // if
     1002                assert( false );
    7311003        }
    7321004
     
    7451017        }
    7461018
    747         Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
    748                 if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
     1019        Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
     1020                if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
    7491021                        // typedef to the same name from the same scope
    7501022                        // must be from the same type
    7511023
    752                         Type * t1 = tyDecl->get_base();
    753                         Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
     1024                        Type * t1 = tyDecl->base;
     1025                        Type * t2 = typedefNames[ tyDecl->name ].first->base;
    7541026                        if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
    7551027                                SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
     
    7631035                        }
    7641036                } else {
    765                         typedefNames[ tyDecl->get_name() ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
     1037                        typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
    7661038                } // if
    7671039
     
    7711043                //    struct screen;
    7721044                // because the expansion of the typedef is:
    773                 //    void rtn( SCREEN *p ) => void rtn( struct screen *p )
     1045                //    void rtn( SCREEN * p ) => void rtn( struct screen * p )
    7741046                // hence the type-name "screen" must be defined.
    7751047                // Note, qualifiers on the typedef are superfluous for the forward declaration.
    7761048
    777                 Type *designatorType = tyDecl->get_base()->stripDeclarator();
    778                 if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
    779                         return new StructDecl( aggDecl->get_name(), DeclarationNode::Struct, noAttributes, tyDecl->get_linkage() );
    780                 } else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
    781                         return new UnionDecl( aggDecl->get_name(), noAttributes, tyDecl->get_linkage() );
    782                 } else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
    783                         return new EnumDecl( enumDecl->get_name(), noAttributes, tyDecl->get_linkage() );
    784                 } else {
    785                         return tyDecl->clone();
    786                 } // if
    787         }
    788 
    789         void EliminateTypedef::premutate( TypeDecl * typeDecl ) {
    790                 TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
     1049                Type * designatorType = tyDecl->base->stripDeclarator();
     1050                if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
     1051                        declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) );
     1052                } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
     1053                        declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
     1054                } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
     1055                        declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) );
     1056                } // if
     1057                return tyDecl->clone();
     1058        }
     1059
     1060        void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
     1061                TypedefMap::iterator i = typedefNames.find( typeDecl->name );
    7911062                if ( i != typedefNames.end() ) {
    7921063                        typedefNames.erase( i ) ;
    7931064                } // if
    7941065
    795                 typedeclNames[ typeDecl->get_name() ] = typeDecl;
    796         }
    797 
    798         void EliminateTypedef::premutate( FunctionDecl * ) {
     1066                typedeclNames.insert( typeDecl->name, typeDecl );
     1067        }
     1068
     1069        void ReplaceTypedef::premutate( FunctionDecl * ) {
    7991070                GuardScope( typedefNames );
    800         }
    801 
    802         void EliminateTypedef::premutate( ObjectDecl * ) {
     1071                GuardScope( typedeclNames );
     1072        }
     1073
     1074        void ReplaceTypedef::premutate( ObjectDecl * ) {
    8031075                GuardScope( typedefNames );
    804         }
    805 
    806         DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
    807                 if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type?
     1076                GuardScope( typedeclNames );
     1077        }
     1078
     1079        DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
     1080                if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
    8081081                        // replace the current object declaration with a function declaration
    809                         FunctionDecl * newDecl = new FunctionDecl( objDecl->get_name(), objDecl->get_storageClasses(), objDecl->get_linkage(), funtype, 0, objDecl->get_attributes(), objDecl->get_funcSpec() );
    810                         objDecl->get_attributes().clear();
     1082                        FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() );
     1083                        objDecl->attributes.clear();
    8111084                        objDecl->set_type( nullptr );
    8121085                        delete objDecl;
     
    8161089        }
    8171090
    818         void EliminateTypedef::premutate( CastExpr * ) {
     1091        void ReplaceTypedef::premutate( CastExpr * ) {
    8191092                GuardScope( typedefNames );
    820         }
    821 
    822         void EliminateTypedef::premutate( CompoundStmt * ) {
     1093                GuardScope( typedeclNames );
     1094        }
     1095
     1096        void ReplaceTypedef::premutate( CompoundStmt * ) {
    8231097                GuardScope( typedefNames );
     1098                GuardScope( typedeclNames );
    8241099                scopeLevel += 1;
    8251100                GuardAction( [this](){ scopeLevel -= 1; } );
    8261101        }
    8271102
    828         CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {
    829                 // remove and delete decl stmts
    830                 filter( compoundStmt->kids, [](Statement * stmt) {
    831                         if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
    832                                 if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
    833                                         return true;
    834                                 } // if
    835                         } // if
    836                         return false;
    837                 }, true);
    838                 return compoundStmt;
    839         }
    840 
    841         // there may be typedefs nested within aggregates. in order for everything to work properly, these should be removed
    842         // as well
    8431103        template<typename AggDecl>
    844         AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
    845                 filter( aggDecl->members, isTypedef, true );
    846                 return aggDecl;
    847         }
    848 
    849         template<typename AggDecl>
    850         void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
     1104        void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
    8511105                if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
    852                         Type *type = nullptr;
     1106                        Type * type = nullptr;
    8531107                        if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) {
    8541108                                type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() );
     
    8601114                        TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
    8611115                        typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
    862                 } // if
    863         }
    864 
    865         void EliminateTypedef::premutate( StructDecl * structDecl ) {
     1116                        // add the implicit typedef to the AST
     1117                        declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) );
     1118                } // if
     1119        }
     1120
     1121        template< typename AggDecl >
     1122        void ReplaceTypedef::handleAggregate( AggDecl * aggr ) {
     1123                SemanticErrorException errors;
     1124
     1125                ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore );
     1126                ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter  );
     1127                declsToAddBefore.clear();
     1128                declsToAddAfter.clear();
     1129
     1130                GuardScope( typedefNames );
     1131                GuardScope( typedeclNames );
     1132                mutateAll( aggr->parameters, * visitor );
     1133
     1134                // unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body.
     1135                for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) {
     1136                        if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); }
     1137
     1138                        try {
     1139                                * i = maybeMutate( * i, * visitor );
     1140                        } catch ( SemanticErrorException &e ) {
     1141                                errors.append( e );
     1142                        }
     1143
     1144                        if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); }
     1145                }
     1146
     1147                if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); }
     1148                if ( !errors.isEmpty() ) { throw errors; }
     1149        }
     1150
     1151        void ReplaceTypedef::premutate( StructDecl * structDecl ) {
     1152                visit_children = false;
    8661153                addImplicitTypedef( structDecl );
    867         }
    868 
    869 
    870         Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
    871                 return handleAggregate( structDecl );
    872         }
    873 
    874         void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
     1154                handleAggregate( structDecl );
     1155        }
     1156
     1157        void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
     1158                visit_children = false;
    8751159                addImplicitTypedef( unionDecl );
    876         }
    877 
    878         Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
    879                 return handleAggregate( unionDecl );
    880         }
    881 
    882         void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
     1160                handleAggregate( unionDecl );
     1161        }
     1162
     1163        void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
    8831164                addImplicitTypedef( enumDecl );
    8841165        }
    8851166
    886         Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) {
    887                 return handleAggregate( enumDecl );
    888         }
    889 
    890         Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
    891                 return handleAggregate( traitDecl );
    892         }
    893 
    894         void EliminateTypedef::premutate( FunctionType * ) {
     1167        void ReplaceTypedef::premutate( FunctionType * ) {
    8951168                GuardValue( inFunctionType );
    8961169                inFunctionType = true;
     1170        }
     1171
     1172        void ReplaceTypedef::premutate( TraitDecl * ) {
     1173                GuardScope( typedefNames );
     1174                GuardScope( typedeclNames);
    8971175        }
    8981176
     
    9391217                        for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) {
    9401218                                if ( i < args.size() ) {
    941                                         TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) );
    942                                         sub.add( (*paramIter)->get_name(), expr->get_type()->clone() );
     1219                                        TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) );
     1220                                        sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );
    9431221                                } else if ( i == args.size() ) {
    944                                         Type * defaultType = (*paramIter)->get_init();
     1222                                        Type * defaultType = (* paramIter)->get_init();
    9451223                                        if ( defaultType ) {
    9461224                                                args.push_back( new TypeExpr( defaultType->clone() ) );
    947                                                 sub.add( (*paramIter)->get_name(), defaultType->clone() );
     1225                                                sub.add( (* paramIter)->get_name(), defaultType->clone() );
    9481226                                        }
    9491227                                }
     
    9641242        }
    9651243
    966         void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
     1244        void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {
    9671245                storageClasses = objectDecl->get_storageClasses();
    9681246        }
    9691247
    970         Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
     1248        Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) {
    9711249                // transform [storage_class] ... (struct S){ 3, ... };
    9721250                // into [storage_class] struct S temp =  { 3, ... };
    9731251                static UniqueName indexName( "_compLit" );
    9741252
    975                 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
     1253                ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
    9761254                compLitExpr->set_result( nullptr );
    9771255                compLitExpr->set_initializer( nullptr );
     
    10111289                        TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    10121290                        // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
    1013                         ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
     1291                        ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );
    10141292                        deleteAll( retVals );
    10151293                        retVals.clear();
     
    10181296        }
    10191297
     1298        void FixObjectType::fix( std::list< Declaration * > & translationUnit ) {
     1299                PassVisitor<FixObjectType> fixer;
     1300                acceptAll( translationUnit, fixer );
     1301        }
     1302
     1303        void FixObjectType::previsit( ObjectDecl * objDecl ) {
     1304                Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer );
     1305                objDecl->set_type( new_type );
     1306        }
     1307
     1308        void FixObjectType::previsit( FunctionDecl * funcDecl ) {
     1309                Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer );
     1310                funcDecl->set_type( new_type );
     1311        }
     1312
     1313        void FixObjectType::previsit( TypeDecl * typeDecl ) {
     1314                if ( typeDecl->get_base() ) {
     1315                        Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer );
     1316                        typeDecl->set_base( new_type );
     1317                } // if
     1318        }
     1319
    10201320        void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
    10211321                PassVisitor<ArrayLength> len;
     
    10241324
    10251325        void ArrayLength::previsit( ObjectDecl * objDecl ) {
    1026                 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
    1027                         if ( at->get_dimension() ) return;
    1028                         if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->get_init() ) ) {
    1029                                 at->set_dimension( new ConstantExpr( Constant::from_ulong( init->get_initializers().size() ) ) );
    1030                         }
     1326                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) {
     1327                        if ( at->dimension ) return;
     1328                        if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->init ) ) {
     1329                                at->dimension = new ConstantExpr( Constant::from_ulong( init->initializers.size() ) );
     1330                        }
     1331                }
     1332        }
     1333
     1334        void ArrayLength::previsit( ArrayType * type ) {
     1335                if ( type->dimension ) {
     1336                        // need to resolve array dimensions early so that constructor code can correctly determine
     1337                        // if a type is a VLA (and hence whether its elements need to be constructed)
     1338                        ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     1339
     1340                        // must re-evaluate whether a type is a VLA, now that more information is available
     1341                        // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
     1342                        type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
    10311343                }
    10321344        }
     
    10621374        }
    10631375
    1064         void FindSpecialDeclarations::previsit( FunctionDecl * funcDecl ) {
    1065                 if ( ! dereferenceOperator ) {
    1066                         if ( funcDecl->get_name() == "*?" && funcDecl->get_linkage() == LinkageSpec::Intrinsic ) {
    1067                                 FunctionType * ftype = funcDecl->get_functionType();
    1068                                 if ( ftype->get_parameters().size() == 1 && ftype->get_parameters().front()->get_type()->get_qualifiers() == Type::Qualifiers() ) {
    1069                                         dereferenceOperator = funcDecl;
     1376namespace {
     1377        /// Replaces enum types by int, and function/array types in function parameter and return
     1378        /// lists by appropriate pointers
     1379        struct EnumAndPointerDecay_new {
     1380                const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
     1381                        // set the type of each member of the enumeration to be EnumConstant
     1382                        for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
     1383                                // build new version of object with EnumConstant
     1384                                ast::ptr< ast::ObjectDecl > obj =
     1385                                        enumDecl->members[i].strict_as< ast::ObjectDecl >();
     1386                                obj.get_and_mutate()->type =
     1387                                        new ast::EnumInstType{ enumDecl->name, ast::CV::Const };
     1388
     1389                                // set into decl
     1390                                ast::EnumDecl * mut = mutate( enumDecl );
     1391                                mut->members[i] = obj.get();
     1392                                enumDecl = mut;
     1393                        }
     1394                        return enumDecl;
     1395                }
     1396
     1397                static const ast::FunctionType * fixFunctionList(
     1398                        const ast::FunctionType * func,
     1399                        std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field,
     1400                        ast::ArgumentFlag isVarArgs = ast::FixedArgs
     1401                ) {
     1402                        const auto & dwts = func->* field;
     1403                        unsigned nvals = dwts.size();
     1404                        bool hasVoid = false;
     1405                        for ( unsigned i = 0; i < nvals; ++i ) {
     1406                                func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) );
     1407                        }
     1408
     1409                        // the only case in which "void" is valid is where it is the only one in the list
     1410                        if ( hasVoid && ( nvals > 1 || isVarArgs ) ) {
     1411                                SemanticError(
     1412                                        dwts.front()->location, func, "invalid type void in function type" );
     1413                        }
     1414
     1415                        // one void is the only thing in the list, remove it
     1416                        if ( hasVoid ) {
     1417                                func = ast::mutate_field(
     1418                                        func, field, std::vector< ast::ptr< ast::DeclWithType > >{} );
     1419                        }
     1420
     1421                        return func;
     1422                }
     1423
     1424                const ast::FunctionType * previsit( const ast::FunctionType * func ) {
     1425                        func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs );
     1426                        return fixFunctionList( func, &ast::FunctionType::returns );
     1427                }
     1428        };
     1429
     1430        /// expand assertions from a trait instance, performing appropriate type variable substitutions
     1431        void expandAssertions(
     1432                const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out
     1433        ) {
     1434                assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) );
     1435
     1436                // build list of trait members, substituting trait decl parameters for instance parameters
     1437                ast::TypeSubstitution sub{
     1438                        inst->base->params.begin(), inst->base->params.end(), inst->params.begin() };
     1439                // deliberately take ast::ptr by-value to ensure this does not mutate inst->base
     1440                for ( ast::ptr< ast::Decl > decl : inst->base->members ) {
     1441                        auto member = decl.strict_as< ast::DeclWithType >();
     1442                        sub.apply( member );
     1443                        out.emplace_back( member );
     1444                }
     1445        }
     1446
     1447        /// Associates forward declarations of aggregates with their definitions
     1448        class LinkReferenceToTypes_new final
     1449        : public ast::WithSymbolTable, public ast::WithGuards, public
     1450          ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
     1451
     1452                // these maps of uses of forward declarations of types need to have the actual type
     1453                // declaration switched in * after * they have been traversed. To enable this in the
     1454                // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
     1455                // before it is placed in the map, properly updating its parents in the usual traversal,
     1456                // then can have the actual mutation applied later
     1457                using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
     1458                using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
     1459                using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
     1460
     1461                const CodeLocation & location;
     1462                const ast::SymbolTable * localSymtab;
     1463
     1464                ForwardEnumsType forwardEnums;
     1465                ForwardStructsType forwardStructs;
     1466                ForwardUnionsType forwardUnions;
     1467
     1468                /// true if currently in a generic type body, so that type parameter instances can be
     1469                /// renamed appropriately
     1470                bool inGeneric = false;
     1471
     1472        public:
     1473                /// contstruct using running symbol table
     1474                LinkReferenceToTypes_new( const CodeLocation & loc )
     1475                : location( loc ), localSymtab( &symtab ) {}
     1476
     1477                /// construct using provided symbol table
     1478                LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
     1479                : location( loc ), localSymtab( &syms ) {}
     1480
     1481                const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     1482                        // ensure generic parameter instances are renamed like the base type
     1483                        if ( inGeneric && typeInst->base ) {
     1484                                typeInst = ast::mutate_field(
     1485                                        typeInst, &ast::TypeInstType::name, typeInst->base->name );
     1486                        }
     1487
     1488                        if (
     1489                                auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
     1490                                        localSymtab->lookupType( typeInst->name ) )
     1491                        ) {
     1492                                typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
     1493                        }
     1494
     1495                        return typeInst;
     1496                }
     1497
     1498                const ast::Type * postvisit( const ast::EnumInstType * inst ) {
     1499                        const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
     1500                        // not a semantic error if the enum is not found, just an implicit forward declaration
     1501                        if ( decl ) {
     1502                                inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
     1503                        }
     1504                        if ( ! decl || ! decl->body ) {
     1505                                // forward declaration
     1506                                auto mut = mutate( inst );
     1507                                forwardEnums.emplace( inst->name, mut );
     1508                                inst = mut;
     1509                        }
     1510                        return inst;
     1511                }
     1512
     1513                void checkGenericParameters( const ast::ReferenceToType * inst ) {
     1514                        for ( const ast::Expr * param : inst->params ) {
     1515                                if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
     1516                                        SemanticError(
     1517                                                location, inst, "Expression parameters for generic types are currently "
     1518                                                "unsupported: " );
    10701519                                }
    10711520                        }
    10721521                }
    1073         }
     1522
     1523                const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
     1524                        const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
     1525                        // not a semantic error if the struct is not found, just an implicit forward declaration
     1526                        if ( decl ) {
     1527                                inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
     1528                        }
     1529                        if ( ! decl || ! decl->body ) {
     1530                                // forward declaration
     1531                                auto mut = mutate( inst );
     1532                                forwardStructs.emplace( inst->name, mut );
     1533                                inst = mut;
     1534                        }
     1535                        checkGenericParameters( inst );
     1536                        return inst;
     1537                }
     1538
     1539                const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
     1540                        const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
     1541                        // not a semantic error if the struct is not found, just an implicit forward declaration
     1542                        if ( decl ) {
     1543                                inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
     1544                        }
     1545                        if ( ! decl || ! decl->body ) {
     1546                                // forward declaration
     1547                                auto mut = mutate( inst );
     1548                                forwardUnions.emplace( inst->name, mut );
     1549                                inst = mut;
     1550                        }
     1551                        checkGenericParameters( inst );
     1552                        return inst;
     1553                }
     1554
     1555                const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
     1556                        // handle other traits
     1557                        const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
     1558                        if ( ! traitDecl )       {
     1559                                SemanticError( location, "use of undeclared trait " + traitInst->name );
     1560                        }
     1561                        if ( traitDecl->params.size() != traitInst->params.size() ) {
     1562                                SemanticError( location, traitInst, "incorrect number of trait parameters: " );
     1563                        }
     1564                        traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
     1565
     1566                        // need to carry over the "sized" status of each decl in the instance
     1567                        for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
     1568                                auto expr = traitInst->params[i].as< ast::TypeExpr >();
     1569                                if ( ! expr ) {
     1570                                        SemanticError(
     1571                                                traitInst->params[i].get(), "Expression parameters for trait instances "
     1572                                                "are currently unsupported: " );
     1573                                }
     1574
     1575                                if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
     1576                                        if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
     1577                                                // traitInst = ast::mutate_field_index(
     1578                                                //      traitInst, &ast::TraitInstType::params, i,
     1579                                                //      ...
     1580                                                // );
     1581                                                ast::TraitInstType * mut = ast::mutate( traitInst );
     1582                                                ast::chain_mutate( mut->params[i] )
     1583                                                        ( &ast::TypeExpr::type )
     1584                                                                ( &ast::TypeInstType::base )->sized = true;
     1585                                                traitInst = mut;
     1586                                        }
     1587                                }
     1588                        }
     1589
     1590                        return traitInst;
     1591                }
     1592
     1593                void previsit( const ast::QualifiedType * ) { visit_children = false; }
     1594
     1595                const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
     1596                        // linking only makes sense for the "oldest ancestor" of the qualified type
     1597                        return ast::mutate_field(
     1598                                qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) );
     1599                }
     1600
     1601                const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
     1602                        // visit enum members first so that the types of self-referencing members are updated
     1603                        // properly
     1604                        if ( ! enumDecl->body ) return enumDecl;
     1605
     1606                        // update forward declarations to point here
     1607                        auto fwds = forwardEnums.equal_range( enumDecl->name );
     1608                        if ( fwds.first != fwds.second ) {
     1609                                auto inst = fwds.first;
     1610                                do {
     1611                                        // forward decl is stored * mutably * in map, can thus be updated
     1612                                        inst->second->base = enumDecl;
     1613                                } while ( ++inst != fwds.second );
     1614                                forwardEnums.erase( fwds.first, fwds.second );
     1615                        }
     1616
     1617                        // ensure that enumerator initializers are properly set
     1618                        for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
     1619                                auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
     1620                                if ( field->init ) {
     1621                                        // need to resolve enumerator initializers early so that other passes that
     1622                                        // determine if an expression is constexpr have appropriate information
     1623                                        auto init = field->init.strict_as< ast::SingleInit >();
     1624
     1625                                        enumDecl = ast::mutate_field_index(
     1626                                                enumDecl, &ast::EnumDecl::members, i,
     1627                                                ast::mutate_field( field, &ast::ObjectDecl::init,
     1628                                                        ast::mutate_field( init, &ast::SingleInit::value,
     1629                                                                ResolvExpr::findSingleExpression(
     1630                                                                        init->value, new ast::BasicType{ ast::BasicType::SignedInt },
     1631                                                                        symtab ) ) ) );
     1632                                }
     1633                        }
     1634
     1635                        return enumDecl;
     1636                }
     1637
     1638                /// rename generic type parameters uniquely so that they do not conflict with user defined
     1639                /// function forall parameters, e.g. the T in Box and the T in f, below
     1640                ///   forall(otype T)
     1641                ///   struct Box {
     1642                ///     T x;
     1643                ///   };
     1644                ///   forall(otype T)
     1645                ///   void f(Box(T) b) {
     1646                ///     ...
     1647                ///   }
     1648                template< typename AggrDecl >
     1649                const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
     1650                        GuardValue( inGeneric );
     1651                        inGeneric = ! aggr->params.empty();
     1652
     1653                        for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
     1654                                const ast::TypeDecl * td = aggr->params[i];
     1655
     1656                                aggr = ast::mutate_field_index(
     1657                                        aggr, &AggrDecl::params, i,
     1658                                        ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
     1659                        }
     1660                        return aggr;
     1661                }
     1662
     1663                const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
     1664                        return renameGenericParams( structDecl );
     1665                }
     1666
     1667                void postvisit( const ast::StructDecl * structDecl ) {
     1668                        // visit struct members first so that the types of self-referencing members are
     1669                        // updated properly
     1670                        if ( ! structDecl->body ) return;
     1671
     1672                        // update forward declarations to point here
     1673                        auto fwds = forwardStructs.equal_range( structDecl->name );
     1674                        if ( fwds.first != fwds.second ) {
     1675                                auto inst = fwds.first;
     1676                                do {
     1677                                        // forward decl is stored * mutably * in map, can thus be updated
     1678                                        inst->second->base = structDecl;
     1679                                } while ( ++inst != fwds.second );
     1680                                forwardStructs.erase( fwds.first, fwds.second );
     1681                        }
     1682                }
     1683
     1684                const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
     1685                        return renameGenericParams( unionDecl );
     1686                }
     1687
     1688                void postvisit( const ast::UnionDecl * unionDecl ) {
     1689                        // visit union members first so that the types of self-referencing members are updated
     1690                        // properly
     1691                        if ( ! unionDecl->body ) return;
     1692
     1693                        // update forward declarations to point here
     1694                        auto fwds = forwardUnions.equal_range( unionDecl->name );
     1695                        if ( fwds.first != fwds.second ) {
     1696                                auto inst = fwds.first;
     1697                                do {
     1698                                        // forward decl is stored * mutably * in map, can thus be updated
     1699                                        inst->second->base = unionDecl;
     1700                                } while ( ++inst != fwds.second );
     1701                                forwardUnions.erase( fwds.first, fwds.second );
     1702                        }
     1703                }
     1704
     1705                const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
     1706                        // set the "sized" status for the special "sized" trait
     1707                        if ( traitDecl->name == "sized" ) {
     1708                                assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect "
     1709                                        "number of parameters: %zd", traitDecl->params.size() );
     1710
     1711                                traitDecl = ast::mutate_field_index(
     1712                                        traitDecl, &ast::TraitDecl::params, 0,
     1713                                        ast::mutate_field(
     1714                                                traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
     1715                        }
     1716
     1717                        // move assertions from type parameters into the body of the trait
     1718                        std::vector< ast::ptr< ast::DeclWithType > > added;
     1719                        for ( const ast::TypeDecl * td : traitDecl->params ) {
     1720                                for ( const ast::DeclWithType * assn : td->assertions ) {
     1721                                        auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
     1722                                        if ( inst ) {
     1723                                                expandAssertions( inst, added );
     1724                                        } else {
     1725                                                added.emplace_back( assn );
     1726                                        }
     1727                                }
     1728                        }
     1729                        if ( ! added.empty() ) {
     1730                                auto mut = mutate( traitDecl );
     1731                                for ( const ast::DeclWithType * decl : added ) {
     1732                                        mut->members.emplace_back( decl );
     1733                                }
     1734                                traitDecl = mut;
     1735                        }
     1736
     1737                        return traitDecl;
     1738                }
     1739        };
     1740
     1741        /// Replaces array and function types in forall lists by appropriate pointer type and assigns
     1742        /// each object and function declaration a unique ID
     1743        class ForallPointerDecay_new {
     1744                const CodeLocation & location;
     1745        public:
     1746                ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {}
     1747
     1748                const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) {
     1749                        // ensure that operator names only apply to functions or function pointers
     1750                        if (
     1751                                CodeGen::isOperator( obj->name )
     1752                                && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() )
     1753                        ) {
     1754                                SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not "
     1755                                        "a function or function pointer." )  );
     1756                        }
     1757
     1758                        // ensure object has unique ID
     1759                        if ( obj->uniqueId ) return obj;
     1760                        auto mut = mutate( obj );
     1761                        mut->fixUniqueId();
     1762                        return mut;
     1763                }
     1764
     1765                const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) {
     1766                        // ensure function has unique ID
     1767                        if ( func->uniqueId ) return func;
     1768                        auto mut = mutate( func );
     1769                        mut->fixUniqueId();
     1770                        return mut;
     1771                }
     1772
     1773                /// Fix up assertions -- flattens assertion lists, removing all trait instances
     1774                template< typename node_t, typename parent_t >
     1775                static const node_t * forallFixer(
     1776                        const CodeLocation & loc, const node_t * node,
     1777                        ast::ParameterizedType::ForallList parent_t::* forallField
     1778                ) {
     1779                        for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {
     1780                                const ast::TypeDecl * type = (node->* forallField)[i];
     1781                                if ( type->assertions.empty() ) continue;
     1782
     1783                                std::vector< ast::ptr< ast::DeclWithType > > asserts;
     1784                                asserts.reserve( type->assertions.size() );
     1785
     1786                                // expand trait instances into their members
     1787                                for ( const ast::DeclWithType * assn : type->assertions ) {
     1788                                        auto traitInst =
     1789                                                dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
     1790                                        if ( traitInst ) {
     1791                                                // expand trait instance to all its members
     1792                                                expandAssertions( traitInst, asserts );
     1793                                        } else {
     1794                                                // pass other assertions through
     1795                                                asserts.emplace_back( assn );
     1796                                        }
     1797                                }
     1798
     1799                                // apply FixFunction to every assertion to check for invalid void type
     1800                                for ( ast::ptr< ast::DeclWithType > & assn : asserts ) {
     1801                                        bool isVoid = false;
     1802                                        assn = fixFunction( assn, isVoid );
     1803                                        if ( isVoid ) {
     1804                                                SemanticError( loc, node, "invalid type void in assertion of function " );
     1805                                        }
     1806                                }
     1807
     1808                                // place mutated assertion list in node
     1809                                auto mut = mutate( type );
     1810                                mut->assertions = move( asserts );
     1811                                node = ast::mutate_field_index( node, forallField, i, mut );
     1812                        }
     1813                        return node;
     1814                }
     1815
     1816                const ast::FunctionType * previsit( const ast::FunctionType * ftype ) {
     1817                        return forallFixer( location, ftype, &ast::FunctionType::forall );
     1818                }
     1819
     1820                const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) {
     1821                        return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params );
     1822                }
     1823
     1824                const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) {
     1825                        return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params );
     1826                }
     1827        };
     1828} // anonymous namespace
     1829
     1830const ast::Type * validateType(
     1831                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
     1832        ast::Pass< EnumAndPointerDecay_new > epc;
     1833        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
     1834        ast::Pass< ForallPointerDecay_new > fpd{ loc };
     1835
     1836        return type->accept( epc )->accept( lrt )->accept( fpd );
     1837}
     1838
    10741839} // namespace SymTab
    10751840
  • src/SymTab/Validate.h

    r7951100 rb067d9b  
    1919#include <list>  // for list
    2020
    21 class Declaration;
    22 class Type;
     21struct CodeLocation;
     22class  Declaration;
     23class  Type;
     24
     25namespace ast {
     26        class Type;
     27        class SymbolTable;
     28}
    2329
    2430namespace SymTab {
     
    2834        void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
    2935        void validateType( Type *type, const Indexer *indexer );
     36
     37        const ast::Type * validateType(
     38                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
    3039} // namespace SymTab
    3140
  • src/SymTab/module.mk

    r7951100 rb067d9b  
    1515###############################################################################
    1616
    17 SRC += SymTab/Indexer.cc \
    18        SymTab/Mangler.cc \
    19        SymTab/Validate.cc \
    20        SymTab/FixFunction.cc \
    21        SymTab/Autogen.cc
     17SRC_SYMTAB = \
     18      SymTab/Autogen.cc \
     19      SymTab/FixFunction.cc \
     20      SymTab/Indexer.cc \
     21      SymTab/Mangler.cc \
     22      SymTab/ManglerCommon.cc \
     23      SymTab/Validate.cc
     24
     25SRC += $(SRC_SYMTAB)
     26SRCDEMANGLE += $(SRC_SYMTAB) SymTab/Demangle.cc
Note: See TracChangeset for help on using the changeset viewer.