Changeset b1e63ac5 for src/SymTab


Ignore:
Timestamp:
Jul 4, 2017, 9:40:16 AM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
208e5be
Parents:
9c951e3 (diff), f7cb0bc (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into references

Location:
src/SymTab
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.cc

    r9c951e3 rb1e63ac5  
    99// Author           : Rob Schluntz
    1010// Created On       : Thu Mar 03 15:45:56 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 17 09:41:08 2017
    13 // Update Count     : 60
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 28 15:30:00 2017
     13// Update Count     : 61
    1414//
    1515
     
    263263        // E ?=?(E volatile*, int),
    264264        //   ?=?(E _Atomic volatile*, int);
    265         void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
     265        void makeEnumFunctions( EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    266266
    267267                // T ?=?(E *, E);
     
    401401        /// generates struct constructors, destructor, and assignment functions
    402402        void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
     403                // Builtins do not use autogeneration.
     404                if ( aggregateDecl->get_linkage() == LinkageSpec::Builtin ||
     405                         aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) {
     406                        return;
     407                }
     408
    403409                // Make function polymorphic in same parameters as generic struct, if applicable
    404410                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
     
    487493
    488494        /// generates the body of a union assignment/copy constructor/field constructor
    489         void makeUnionAssignBody( FunctionDecl * funcDecl, bool isDynamicLayout ) {
     495        void makeUnionAssignBody( FunctionDecl * funcDecl ) {
    490496                FunctionType * ftype = funcDecl->get_functionType();
    491497                assert( ftype->get_parameters().size() == 2 );
     
    507513                // Make function polymorphic in same parameters as generic union, if applicable
    508514                const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
    509                 bool isDynamicLayout = hasDynamicLayout( aggregateDecl );  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
    510 
     515               
    511516                // default ctor/dtor need only first parameter
    512517                // void ?{}(T *); void ^?{}(T *);
     
    534539                FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
    535540
    536                 makeUnionAssignBody( assignDecl, isDynamicLayout );
     541                makeUnionAssignBody( assignDecl );
    537542
    538543                // body of assignment and copy ctor is the same
    539                 makeUnionAssignBody( copyCtorDecl, isDynamicLayout );
     544                makeUnionAssignBody( copyCtorDecl );
    540545
    541546                // create a constructor which takes the first member type as a parameter.
     
    552557                                FunctionDecl * ctor = genFunc( "?{}", memCtorType, functionNesting );
    553558
    554                                 makeUnionAssignBody( ctor, isDynamicLayout );
     559                                makeUnionAssignBody( ctor );
    555560                                memCtors.push_back( ctor );
    556561                                // only generate a ctor for the first field
     
    579584                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    580585                        // enumInst->set_baseEnum( enumDecl );
    581                         makeEnumFunctions( enumDecl, enumInst, functionNesting, declsToAddAfter );
     586                        makeEnumFunctions( enumInst, functionNesting, declsToAddAfter );
    582587                }
    583588        }
  • src/SymTab/Autogen.h

    r9c951e3 rb1e63ac5  
    1010// Created On       : Sun May 17 21:53:34 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 17 09:10:41 2017
    13 // Update Count     : 9
     12// Last Modified On : Wed Jun 21 17:25:26 2017
     13// Update Count     : 14
    1414//
    1515
     
    4343        template< typename OutputIterator >
    4444        Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
    45                 // want to be able to generate assignment, ctor, and dtor generically,
    46                 // so fname is either ?=?, ?{}, or ^?{}
    47                 UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
     45        // want to be able to generate assignment, ctor, and dtor generically,
     46        // so fname is either ?=?, ?{}, or ^?{}
     47        UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
    4848
    49                 // do something special for unnamed members
    50                 dstParam = new AddressExpr( dstParam );
    51                 if ( addCast ) {
    52                         // cast to T* with qualifiers removed, so that qualified objects can be constructed
    53                         // and destructed with the same functions as non-qualified objects.
    54                         // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
    55                         // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
    56                         // remove lvalue as a qualifier, this can change to
    57                         //   type->get_qualifiers() = Type::Qualifiers();
    58                         assert( type );
    59                         Type * castType = type->clone();
    60 //                      castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, false);
    61                         castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    62                         castType->set_lvalue( true ); // xxx - might not need this
    63                         dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
    64                 }
    65                 fExpr->get_args().push_back( dstParam );
     49        // do something special for unnamed members
     50        dstParam = new AddressExpr( dstParam );
     51        if ( addCast ) {
     52                // cast to T* with qualifiers removed, so that qualified objects can be constructed
     53                // and destructed with the same functions as non-qualified objects.
     54                // unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
     55                // must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
     56                // remove lvalue as a qualifier, this can change to
     57                //   type->get_qualifiers() = Type::Qualifiers();
     58                assert( type );
     59                Type * castType = type->clone();
     60                castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     61                castType->set_lvalue( true ); // xxx - might not need this
     62                dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
     63        }
     64        fExpr->get_args().push_back( dstParam );
    6665
    67                 Statement * listInit = srcParam.buildListInit( fExpr );
     66        Statement * listInit = srcParam.buildListInit( fExpr );
    6867
    69                 std::list< Expression * > args = *++srcParam;
    70                 fExpr->get_args().splice( fExpr->get_args().end(), args );
     68        std::list< Expression * > args = *++srcParam;
     69        fExpr->get_args().splice( fExpr->get_args().end(), args );
    7170
    72                 *out++ = new ExprStmt( noLabels, fExpr );
     71        *out++ = new ExprStmt( noLabels, fExpr );
    7372
    74                 srcParam.clearArrayIndices();
     73        srcParam.clearArrayIndices();
    7574
    76                 return listInit;
     75        return listInit;
    7776        }
    7877
     
    8887                Expression * begin, * end, * update, * cmp;
    8988                if ( forward ) {
    90                         // generate: for ( int i = 0; i < 0; ++i )
    91                         begin = new ConstantExpr( Constant( new ZeroType( emptyQualifiers ), "0" ) );
     89                        // generate: for ( int i = 0; i < N; ++i )
     90                        begin = new ConstantExpr( Constant::from_int( 0 ) );
    9291                        end = array->get_dimension()->clone();
    9392                        cmp = new NameExpr( "?<?" );
     
    9796                        begin = new UntypedExpr( new NameExpr( "?-?" ) );
    9897                        ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
    99                         ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant( new OneType( emptyQualifiers ), "1" ) ) );
    100                         end = new ConstantExpr( Constant( new ZeroType( emptyQualifiers ), "0" ) );
     98                        ((UntypedExpr*)begin)->get_args().push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
     99                        end = new ConstantExpr( Constant::from_int( 0 ) );
    101100                        cmp = new NameExpr( "?>=?" );
    102101                        update = new NameExpr( "--?" );
    103102                }
    104103
    105                 ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
     104                ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
    106105
    107106                UntypedExpr *cond = new UntypedExpr( cmp );
  • src/SymTab/FixFunction.cc

    r9c951e3 rb1e63ac5  
    2424
    2525        DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
    26                 ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0, functionDecl->get_attributes() );
     26                ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
    2727                functionDecl->get_attributes().clear();
     28                // can't delete function type because it may contain assertions, but can't transfer ownership without a clone since set_type checks for nullptr
     29                functionDecl->set_type( functionDecl->get_type()->clone() );
    2830                delete functionDecl;
    2931                return pointer;
  • src/SymTab/ImplementationType.cc

    r9c951e3 rb1e63ac5  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ImplementationType.cc -- 
     7// ImplementationType.cc --
    88//
    99// Author           : Richard C. Bilson
     
    6161        }
    6262
    63         void ImplementationType::visit(VoidType *voidType) {
    64         }
    65 
    66         void ImplementationType::visit(BasicType *basicType) {
    67         }
     63        void ImplementationType::visit( __attribute__((unused)) VoidType *voidType ) {}
     64        void ImplementationType::visit( __attribute__((unused)) BasicType *basicType ) {}
    6865
    6966        void ImplementationType::visit(PointerType *pointerType) {
     
    7976        }
    8077
    81         void ImplementationType::visit(FunctionType *functionType) {
    82 ///   FunctionType *newType = functionType->clone();
    83 ///   for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
    84 ///     i->set_type( implementationType( i->get_type(), indexer ) );
    85 ///   }
    86 ///   for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
    87 ///     i->set_type( implementationType( i->get_type(), indexer ) );
    88 ///   }
    89         }
    90 
    91         void ImplementationType::visit(StructInstType *aggregateUseType) {
    92         }
    93 
    94         void ImplementationType::visit(UnionInstType *aggregateUseType) {
    95         }
    96 
    97         void ImplementationType::visit(EnumInstType *aggregateUseType) {
    98         }
    99 
    100         void ImplementationType::visit(TraitInstType *aggregateUseType) {
    101         }
     78        void ImplementationType::visit( __attribute__((unused)) FunctionType *functionType ) {}
     79        void ImplementationType::visit( __attribute__((unused)) StructInstType * aggregateUseType ) {}
     80        void ImplementationType::visit( __attribute__((unused)) UnionInstType * aggregateUseType ) {}
     81        void ImplementationType::visit( __attribute__((unused)) EnumInstType * aggregateUseType ) {}
     82        void ImplementationType::visit( __attribute__((unused)) TraitInstType * aggregateUseType ) {}
    10283
    10384        void ImplementationType::visit(TypeInstType *inst) {
     
    11192
    11293        void ImplementationType::visit(TupleType *tupleType) {
    113                 TupleType *newType = new TupleType( Type::Qualifiers() );
     94                std::list< Type * > types;
    11495                for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
    11596                        Type *implType = implementationType( *i, indexer );
    11697                        implType->get_qualifiers() |= tupleType->get_qualifiers();
    117                         newType->get_types().push_back( implType );
     98                        types.push_back( implType );
    11899                } // for
    119                 result = newType;
     100                result = new TupleType( Type::Qualifiers(), types );
    120101        }
    121102
    122         void ImplementationType::visit(VarArgsType *varArgsType) {
    123         }
    124 
    125         void ImplementationType::visit(ZeroType *zeroType) {
    126         }
    127 
    128         void ImplementationType::visit(OneType *oneType) {
    129         }
     103        void ImplementationType::visit( __attribute__((unused)) VarArgsType *varArgsType ) {}
     104        void ImplementationType::visit( __attribute__((unused)) ZeroType *zeroType ) {}
     105        void ImplementationType::visit( __attribute__((unused)) OneType *oneType ) {}
    130106} // namespace SymTab
    131107
  • src/SymTab/Indexer.cc

    r9c951e3 rb1e63ac5  
    124124                        };
    125125                        // properties for this type
    126                         bool userDefinedFunc = false; // any user-defined function found
    127                         bool userDefinedCtor = false; // any user-defined constructor found
    128                         bool userDefinedDtor = false; // any user-defined destructor found
    129                         bool userDefinedCopyFunc = false; // user-defined copy ctor found
     126                        bool existsUserDefinedFunc = false;    // any user-defined function found
     127                        bool existsUserDefinedCtor = false;    // any user-defined constructor found
     128                        bool existsUserDefinedDtor = false;    // any user-defined destructor found
     129                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
     130                        bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found
    130131                        std::list< DeclBall > decls;
    131132
     
    138139                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
    139140                                decls.push_back( DeclBall{ function, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
    140                                 userDefinedFunc = userDefinedFunc || isUserDefinedFunc;
    141                                 userDefinedCtor = userDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
    142                                 userDefinedDtor = userDefinedDtor || (isUserDefinedFunc && isDtor);
    143                                 userDefinedCopyFunc = userDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
     141                                existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
     142                                existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && InitTweak::isConstructor( function->get_name() ) );
     143                                existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
     144                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
     145                                existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor);
    144146                                return *this;
    145147                        }
     
    164166                }
    165167
    166                 // if a type contains user defined ctor/dtors, then special rules trigger, which determine
    167                 // the set of ctor/dtors that are seen by the requester. In particular, if the user defines
     168                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
     169                // the set of ctor/dtor/assign that are seen by the requester. In particular, if the user defines
    168170                // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
    169171                // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
    170                 // If the user defines any ctor then the generated default ctor should not be seen.
     172                // If the user defines any ctor then the generated default ctor should not be seen (intrinsic default
     173                // ctor must be overridden exactly).
    171174                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    172175                        ValueType & val = pair.second;
    173176                        for ( ValueType::DeclBall ball : val.decls ) {
    174                                 if ( ! val.userDefinedFunc || ball.isUserDefinedFunc || (! val.userDefinedCtor && ball.isDefaultCtor) || (! val.userDefinedCopyFunc && ball.isCopyFunc) || (! val.userDefinedDtor && ball.isDtor) ) {
     177                                bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
     178                                bool isUserDefinedFunc = ball.isUserDefinedFunc;
     179                                bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
     180                                bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
     181                                bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
     182                                if ( noUserDefinedFunc || isUserDefinedFunc || isAcceptableDefaultCtor || isAcceptableCopyFunc || isAcceptableDtor ) {
    175183                                        // decl conforms to the rules described above, so it should be seen by the requester
    176184                                        out.push_back( ball.decl );
     
    278286                addType( typeDecl );
    279287                acceptAll( typeDecl->get_assertions(), *this );
     288                acceptNewScope( typeDecl->get_init(), *this );
    280289        }
    281290
     
    487496        }
    488497
    489         void Indexer::visit( UntypedValofExpr *valofExpr ) {
    490                 acceptNewScope( valofExpr->get_result(), *this );
    491                 maybeAccept( valofExpr->get_body(), *this );
    492         }
    493 
    494498        void Indexer::visit( RangeExpr *rangeExpr ) {
    495499                maybeAccept( rangeExpr->get_low(), *this );
     
    510514                acceptNewScope( tupleExpr->get_result(), *this );
    511515                maybeAccept( tupleExpr->get_tuple(), *this );
    512         }
    513 
    514         void Indexer::visit( MemberTupleExpr *tupleExpr ) {
    515                 acceptNewScope( tupleExpr->get_result(), *this );
    516                 maybeAccept( tupleExpr->get_member(), *this );
    517                 maybeAccept( tupleExpr->get_aggregate(), *this );
    518516        }
    519517
  • src/SymTab/Indexer.h

    r9c951e3 rb1e63ac5  
    6969                virtual void visit( ConstructorExpr * ctorExpr );
    7070                virtual void visit( CompoundLiteralExpr *compLitExpr );
    71                 virtual void visit( UntypedValofExpr *valofExpr );
    7271                virtual void visit( RangeExpr *rangeExpr );
    7372                virtual void visit( UntypedTupleExpr *tupleExpr );
    7473                virtual void visit( TupleExpr *tupleExpr );
    7574                virtual void visit( TupleIndexExpr *tupleExpr );
    76                 virtual void visit( MemberTupleExpr *tupleExpr );
    7775                virtual void visit( TupleAssignExpr *tupleExpr );
    7876                virtual void visit( StmtExpr * stmtExpr );
  • src/SymTab/Mangler.cc

    r9c951e3 rb1e63ac5  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:40:29 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 17 09:40:01 2017
    13 // Update Count     : 20
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jun 28 15:31:00 2017
     13// Update Count     : 21
    1414//
    1515
     
    7272                        } else {
    7373                                // if we add another kind of overridable function, this has to change
    74                                 assert( false );
     74                                assert( false && "unknown overrideable linkage" );
    7575                        } // if
    7676                }
     
    236236        }
    237237
    238         void Mangler::visit( ZeroType *zeroType ) {
     238        void Mangler::visit( __attribute__((unused)) ZeroType *zeroType ) {
    239239                mangleName << "Z";
    240240        }
    241241
    242         void Mangler::visit( OneType *oneType ) {
     242        void Mangler::visit( __attribute__((unused)) OneType *oneType ) {
    243243                mangleName << "O";
    244244        }
  • src/SymTab/Validate.cc

    r9c951e3 rb1e63ac5  
    3838//   definition occurs later in the input.
    3939
     40#include <algorithm>
     41#include <iterator>
    4042#include <list>
    41 #include <iterator>
     43
     44#include "CodeGen/CodeGenerator.h"
     45
     46#include "Common/PassVisitor.h"
    4247#include "Common/ScopedMap.h"
     48#include "Common/UniqueName.h"
    4349#include "Common/utility.h"
    44 #include "Common/UniqueName.h"
     50
    4551#include "Concurrency/Keywords.h"
    46 #include "Validate.h"
    47 #include "SynTree/Visitor.h"
    48 #include "SynTree/Mutator.h"
    49 #include "SynTree/Type.h"
    50 #include "SynTree/Expression.h"
    51 #include "SynTree/Statement.h"
    52 #include "SynTree/TypeSubstitution.h"
    53 #include "Indexer.h"
     52
     53#include "GenPoly/DeclMutator.h"
     54
     55#include "InitTweak/InitTweak.h"
     56
     57#include "AddVisit.h"
     58#include "Autogen.h"
    5459#include "FixFunction.h"
    5560// #include "ImplementationType.h"
    56 #include "GenPoly/DeclMutator.h"
    57 #include "AddVisit.h"
     61#include "Indexer.h"
    5862#include "MakeLibCfa.h"
    5963#include "TypeEquality.h"
    60 #include "Autogen.h"
     64#include "Validate.h"
     65
    6166#include "ResolvExpr/typeops.h"
    62 #include <algorithm>
    63 #include "InitTweak/InitTweak.h"
    64 #include "CodeGen/CodeGenerator.h"
     67
     68#include "SynTree/Attribute.h"
     69#include "SynTree/Expression.h"
     70#include "SynTree/Mutator.h"
     71#include "SynTree/Statement.h"
     72#include "SynTree/Type.h"
     73#include "SynTree/TypeSubstitution.h"
     74#include "SynTree/Visitor.h"
    6575
    6676#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
     
    96106
    97107        /// Fix return types so that every function returns exactly one value
    98         class ReturnTypeFixer final : public Visitor {
    99           public:
    100                 typedef Visitor Parent;
    101                 using Parent::visit;
    102 
     108        struct ReturnTypeFixer {
    103109                static void fix( std::list< Declaration * > &translationUnit );
    104110
    105                 virtual void visit( FunctionDecl * functionDecl );
    106                 virtual void visit( FunctionType * ftype );
     111                void postvisit( FunctionDecl * functionDecl );
     112                void postvisit( FunctionType * ftype );
    107113        };
    108114
    109115        /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
    110         class EnumAndPointerDecayPass final : public Visitor {
    111                 typedef Visitor Parent;
    112                 virtual void visit( EnumDecl *aggregateDecl );
    113                 virtual void visit( FunctionType *func );
     116        struct EnumAndPointerDecay {
     117                void previsit( EnumDecl *aggregateDecl );
     118                void previsit( FunctionType *func );
    114119        };
    115120
     
    119124          public:
    120125                LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
    121           private:
    122126                using Parent::visit;
    123127                void visit( EnumInstType *enumInst ) final;
     
    129133                void visit( UnionDecl *unionDecl ) final;
    130134                void visit( TypeInstType *typeInst ) final;
    131 
     135          private:
    132136                const Indexer *indexer;
    133137
     
    140144        };
    141145
    142         /// Replaces array and function types in forall lists by appropriate pointer type
    143         class Pass3 final : public Indexer {
     146        /// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
     147        class ForallPointerDecay final : public Indexer {
    144148                typedef Indexer Parent;
    145149          public:
    146150                using Parent::visit;
    147                 Pass3( const Indexer *indexer );
    148           private:
     151                ForallPointerDecay( const Indexer *indexer );
     152
    149153                virtual void visit( ObjectDecl *object ) override;
    150154                virtual void visit( FunctionDecl *func ) override;
     
    153157        };
    154158
    155         class ReturnChecker : public Visitor {
    156           public:
     159        struct ReturnChecker : public WithGuards {
    157160                /// Checks that return statements return nothing if their return type is void
    158161                /// and return something if the return type is non-void.
    159162                static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
    160           private:
    161                 virtual void visit( FunctionDecl * functionDecl );
    162                 virtual void visit( ReturnStmt * returnStmt );
    163 
    164                 std::list< DeclarationWithType * > returnVals;
     163
     164                void previsit( FunctionDecl * functionDecl );
     165                void previsit( ReturnStmt * returnStmt );
     166
     167                typedef std::list< DeclarationWithType * > ReturnVals;
     168                ReturnVals returnVals;
    165169        };
    166170
     
    198202        };
    199203
    200         class VerifyCtorDtorAssign : public Visitor {
    201         public:
     204        struct VerifyCtorDtorAssign {
    202205                /// ensure that constructors, destructors, and assignment have at least one
    203206                /// parameter, the first of which must be a pointer, and that ctor/dtors have no
     
    205208                static void verify( std::list< Declaration * > &translationUnit );
    206209
    207                 virtual void visit( FunctionDecl *funcDecl );
    208         };
    209 
    210         class ArrayLength : public Visitor {
    211         public:
     210                void previsit( FunctionDecl *funcDecl );
     211        };
     212
     213        /// ensure that generic types have the correct number of type arguments
     214        struct ValidateGenericParameters {
     215                void previsit( StructInstType * inst );
     216                void previsit( UnionInstType * inst );
     217        };
     218
     219        struct ArrayLength {
    212220                /// for array types without an explicit length, compute the length and store it so that it
    213221                /// is known to the rest of the phases. For example,
     
    219227                static void computeLength( std::list< Declaration * > & translationUnit );
    220228
    221                 virtual void visit( ObjectDecl * objDecl );
    222         };
    223 
    224         class CompoundLiteral final : public GenPoly::DeclMutator {
     229                void previsit( ObjectDecl * objDecl );
     230        };
     231
     232        struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral> {
    225233                Type::StorageClasses storageClasses;
    226234
    227                 using GenPoly::DeclMutator::mutate;
    228                 DeclarationWithType * mutate( ObjectDecl *objectDecl ) final;
    229                 Expression *mutate( CompoundLiteralExpr *compLitExpr ) final;
     235                void premutate( ObjectDecl *objectDecl );
     236                Expression * postmutate( CompoundLiteralExpr *compLitExpr );
    230237        };
    231238
    232239        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    233                 EnumAndPointerDecayPass epc;
     240                PassVisitor<EnumAndPointerDecay> epc;
    234241                LinkReferenceToTypes lrt( doDebug, 0 );
    235                 Pass3 pass3( 0 );
    236                 CompoundLiteral compoundliteral;
    237 
    238                 HoistStruct::hoistStruct( translationUnit );
     242                ForallPointerDecay fpd( 0 );
     243                PassVisitor<CompoundLiteral> compoundliteral;
     244                PassVisitor<ValidateGenericParameters> genericParams;
     245
    239246                EliminateTypedef::eliminateTypedef( translationUnit );
     247                HoistStruct::hoistStruct( translationUnit ); // must happen after EliminateTypedef, so that aggregate typedefs occur in the correct order
    240248                ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
    241249                acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
     250                acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes
    242251                acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist
    243252                VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
    244253                Concurrency::applyKeywords( translationUnit );
    245                 autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
     254                autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
    246255                Concurrency::implementMutexFuncs( translationUnit );
    247256                Concurrency::implementThreadStarter( translationUnit );
    248257                ReturnChecker::checkFunctionReturns( translationUnit );
    249                 compoundliteral.mutateDeclarationList( translationUnit );
    250                 acceptAll( translationUnit, pass3 );
     258                mutateAll( translationUnit, compoundliteral );
     259                acceptAll( translationUnit, fpd );
    251260                ArrayLength::computeLength( translationUnit );
    252261        }
    253262
    254263        void validateType( Type *type, const Indexer *indexer ) {
    255                 EnumAndPointerDecayPass epc;
     264                PassVisitor<EnumAndPointerDecay> epc;
    256265                LinkReferenceToTypes lrt( false, indexer );
    257                 Pass3 pass3( indexer );
     266                ForallPointerDecay fpd( indexer );
    258267                type->accept( epc );
    259268                type->accept( lrt );
    260                 type->accept( pass3 );
     269                type->accept( fpd );
    261270        }
    262271
     
    337346        }
    338347
    339         void EnumAndPointerDecayPass::visit( EnumDecl *enumDecl ) {
     348        void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
    340349                // Set the type of each member of the enumeration to be EnumConstant
    341350                for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
     
    344353                        obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->get_name() ) );
    345354                } // for
    346                 Parent::visit( enumDecl );
    347355        }
    348356
     
    351359                void fixFunctionList( DWTList & dwts, FunctionType * func ) {
    352360                        // the only case in which "void" is valid is where it is the only one in the list; then it should be removed
    353                         // entirely other fix ups are handled by the FixFunction class
     361                        // entirely. other fix ups are handled by the FixFunction class
    354362                        typedef typename DWTList::iterator DWTIterator;
    355363                        DWTIterator begin( dwts.begin() ), end( dwts.end() );
     
    370378                                for ( ; i != end; ++i ) {
    371379                                        FixFunction fixer;
    372                                         *i = (*i )->acceptMutator( fixer );
     380                                        *i = (*i)->acceptMutator( fixer );
    373381                                        if ( fixer.get_isVoid() ) {
    374382                                                throw SemanticError( "invalid type void in function type ", func );
     
    379387        }
    380388
    381         void EnumAndPointerDecayPass::visit( FunctionType *func ) {
     389        void EnumAndPointerDecay::previsit( FunctionType *func ) {
    382390                // Fix up parameters and return types
    383391                fixFunctionList( func->get_parameters(), func );
    384392                fixFunctionList( func->get_returnVals(), func );
    385                 Visitor::visit( func );
    386393        }
    387394
     
    496503        void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
    497504                // visit struct members first so that the types of self-referencing members are updated properly
     505                // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and and their defaults)
    498506                Parent::visit( structDecl );
    499507                if ( ! structDecl->get_members().empty() ) {
     
    529537        }
    530538
    531         Pass3::Pass3( const Indexer *other_indexer ) :  Indexer( false ) {
     539        ForallPointerDecay::ForallPointerDecay( const Indexer *other_indexer ) :  Indexer( false ) {
    532540                if ( other_indexer ) {
    533541                        indexer = other_indexer;
     
    567575        }
    568576
    569         void Pass3::visit( ObjectDecl *object ) {
     577        void ForallPointerDecay::visit( ObjectDecl *object ) {
    570578                forallFixer( object->get_type() );
    571579                if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
     
    576584        }
    577585
    578         void Pass3::visit( FunctionDecl *func ) {
     586        void ForallPointerDecay::visit( FunctionDecl *func ) {
    579587                forallFixer( func->get_type() );
    580588                Parent::visit( func );
     
    583591
    584592        void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
    585                 ReturnChecker checker;
     593                PassVisitor<ReturnChecker> checker;
    586594                acceptAll( translationUnit, checker );
    587595        }
    588596
    589         void ReturnChecker::visit( FunctionDecl * functionDecl ) {
    590                 std::list< DeclarationWithType * > oldReturnVals = returnVals;
     597        void ReturnChecker::previsit( FunctionDecl * functionDecl ) {
     598                GuardValue( returnVals );
    591599                returnVals = functionDecl->get_functionType()->get_returnVals();
    592                 Visitor::visit( functionDecl );
    593                 returnVals = oldReturnVals;
    594         }
    595 
    596         void ReturnChecker::visit( ReturnStmt * returnStmt ) {
     600        }
     601
     602        void ReturnChecker::previsit( ReturnStmt * returnStmt ) {
    597603                // Previously this also checked for the existence of an expr paired with no return values on
    598604                // the  function return type. This is incorrect, since you can have an expression attached to
     
    804810
    805811        void VerifyCtorDtorAssign::verify( std::list< Declaration * > & translationUnit ) {
    806                 VerifyCtorDtorAssign verifier;
     812                PassVisitor<VerifyCtorDtorAssign> verifier;
    807813                acceptAll( translationUnit, verifier );
    808814        }
    809815
    810         void VerifyCtorDtorAssign::visit( FunctionDecl * funcDecl ) {
     816        void VerifyCtorDtorAssign::previsit( FunctionDecl * funcDecl ) {
    811817                FunctionType * funcType = funcDecl->get_functionType();
    812818                std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
     
    826832                        }
    827833                }
    828 
    829                 Visitor::visit( funcDecl );
    830         }
    831 
    832         DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) {
     834        }
     835
     836        template< typename Aggr >
     837        void validateGeneric( Aggr * inst ) {
     838                std::list< TypeDecl * > * params = inst->get_baseParameters();
     839                if ( params != NULL ) {
     840                        std::list< Expression * > & args = inst->get_parameters();
     841
     842                        // insert defaults arguments when a type argument is missing (currently only supports missing arguments at the end of the list).
     843                        // A substitution is used to ensure that defaults are replaced correctly, e.g.,
     844                        //   forall(otype T, otype alloc = heap_allocator(T)) struct vector;
     845                        //   vector(int) v;
     846                        // after insertion of default values becomes
     847                        //   vector(int, heap_allocator(T))
     848                        // and the substitution is built with T=int so that after substitution, the result is
     849                        //   vector(int, heap_allocator(int))
     850                        TypeSubstitution sub;
     851                        auto paramIter = params->begin();
     852                        for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) {
     853                                if ( i < args.size() ) {
     854                                        TypeExpr * expr = safe_dynamic_cast< TypeExpr * >( *std::next( args.begin(), i ) );
     855                                        sub.add( (*paramIter)->get_name(), expr->get_type()->clone() );
     856                                } else if ( i == args.size() ) {
     857                                        Type * defaultType = (*paramIter)->get_init();
     858                                        if ( defaultType ) {
     859                                                args.push_back( new TypeExpr( defaultType->clone() ) );
     860                                                sub.add( (*paramIter)->get_name(), defaultType->clone() );
     861                                        }
     862                                }
     863                        }
     864
     865                        sub.apply( inst );
     866                        if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst );
     867                        if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", inst );
     868                }
     869        }
     870
     871        void ValidateGenericParameters::previsit( StructInstType * inst ) {
     872                validateGeneric( inst );
     873        }
     874
     875        void ValidateGenericParameters::previsit( UnionInstType * inst ) {
     876                validateGeneric( inst );
     877        }
     878
     879        void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
    833880                storageClasses = objectDecl->get_storageClasses();
    834                 DeclarationWithType * temp = Mutator::mutate( objectDecl );
    835                 return temp;
    836         }
    837 
    838         Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) {
     881        }
     882
     883        Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
    839884                // transform [storage_class] ... (struct S){ 3, ... };
    840885                // into [storage_class] struct S temp =  { 3, ... };
    841886                static UniqueName indexName( "_compLit" );
    842887
    843                 ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_result(), compLitExpr->get_initializer() );
    844                 compLitExpr->set_result( 0 );
    845                 compLitExpr->set_initializer( 0 );
     888                ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
     889                compLitExpr->set_result( nullptr );
     890                compLitExpr->set_initializer( nullptr );
    846891                delete compLitExpr;
    847                 DeclarationWithType * newtempvar = mutate( tempvar );
    848                 addDeclaration( newtempvar );                                   // add modified temporary to current block
    849                 return new VariableExpr( newtempvar );
     892                declsToAddBefore.push_back( tempvar );                                  // add modified temporary to current block
     893                return new VariableExpr( tempvar );
    850894        }
    851895
    852896        void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
    853                 ReturnTypeFixer fixer;
     897                PassVisitor<ReturnTypeFixer> fixer;
    854898                acceptAll( translationUnit, fixer );
    855899        }
    856900
    857         void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) {
    858                 Parent::visit( functionDecl );
     901        void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) {
    859902                FunctionType * ftype = functionDecl->get_functionType();
    860903                std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
     
    867910                                ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) );
    868911                        }
    869                 }
    870         }
    871 
    872         void ReturnTypeFixer::visit( FunctionType * ftype ) {
     912                        ret->get_attributes().push_back( new Attribute( "unused" ) );
     913                }
     914        }
     915
     916        void ReturnTypeFixer::postvisit( FunctionType * ftype ) {
    873917                // xxx - need to handle named return values - this information needs to be saved somehow
    874918                // so that resolution has access to the names.
     
    888932
    889933        void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
    890                 ArrayLength len;
     934                PassVisitor<ArrayLength> len;
    891935                acceptAll( translationUnit, len );
    892936        }
    893937
    894         void ArrayLength::visit( ObjectDecl * objDecl ) {
     938        void ArrayLength::previsit( ObjectDecl * objDecl ) {
    895939                if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
    896940                        if ( at->get_dimension() != nullptr ) return;
Note: See TracChangeset for help on using the changeset viewer.