Changeset 9cb8e88d


Ignore:
Timestamp:
Dec 18, 2015, 2:36:53 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
267cb3d
Parents:
0ddb713
Message:

validate constructors and destructors - ensure they return nothing, have at least one parameter, and take a pointer as the first parameter

Location:
src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    r0ddb713 r9cb8e88d  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Validate.cc -- 
     7// Validate.cc --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:50:04 2015
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri Nov 20 16:33:52 2015
    13 // Update Count     : 201
     12// Last Modified On : Fri Dec 18 14:32:59 2015
     13// Update Count     : 268
    1414//
    1515
     
    6363                /// Flattens nested struct types
    6464                static void hoistStruct( std::list< Declaration * > &translationUnit );
    65  
     65
    6666                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    67  
     67
    6868                virtual void visit( StructDecl *aggregateDecl );
    6969                virtual void visit( UnionDecl *aggregateDecl );
     
    107107
    108108                const Indexer *indexer;
    109  
     109
    110110                typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
    111111                typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
     
    132132
    133133                std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
    134  
     134
    135135                virtual void visit( EnumDecl *enumDecl );
    136136                virtual void visit( StructDecl *structDecl );
     
    142142                virtual void visit( FunctionType *ftype );
    143143                virtual void visit( PointerType *ftype );
    144  
     144
    145145                virtual void visit( CompoundStmt *compoundStmt );
    146146                virtual void visit( IfStmt *ifStmt );
     
    155155          private:
    156156                template< typename StmtClass > void visitStatement( StmtClass *stmt );
    157  
     157
    158158                std::list< Declaration * > declsToAdd;
    159159                std::set< std::string > structsDone;
     
    188188        };
    189189
     190        class VerifyCtorDtor : public Visitor {
     191        public:
     192                /// ensure that constructors and destructors have at least one
     193                /// parameter, the first of which must be a pointer, and no
     194                /// return values.
     195                static void verify( std::list< Declaration * > &translationUnit );
     196
     197                // VerifyCtorDtor() {}
     198
     199                virtual void visit( FunctionDecl *funcDecl );
     200        private:
     201        };
     202
    190203        void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
    191204                Pass1 pass1;
     
    198211                AutogenerateRoutines::autogenerateRoutines( translationUnit );
    199212                acceptAll( translationUnit, pass3 );
    200         }
    201        
     213                VerifyCtorDtor::verify( translationUnit );
     214        }
     215
    202216        void validateType( Type *type, const Indexer *indexer ) {
    203217                Pass1 pass1;
     
    307321        void Pass1::visit( EnumDecl *enumDecl ) {
    308322                // Set the type of each member of the enumeration to be EnumConstant
    309  
     323
    310324                for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
    311325                        ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
     
    331345                                ++i;
    332346                                func->get_parameters().erase( j );
    333                                 if ( i != end ) { 
     347                                if ( i != end ) {
    334348                                        throw SemanticError( "invalid type void in function type ", func );
    335349                                } // if
     
    512526
    513527                UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    514  
     528
    515529                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    516530                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    517  
     531
    518532                // do something special for unnamed members
    519533                Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
    520534                assignExpr->get_args().push_back( dstselect );
    521  
     535
    522536                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    523537                assignExpr->get_args().push_back( srcselect );
    524  
     538
    525539                *out++ = new ExprStmt( noLabels, assignExpr );
    526540        }
     
    529543        void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
    530544                static UniqueName indexName( "_index" );
    531  
     545
    532546                // for a flexible array member nothing is done -- user must define own assignment
    533547                if ( ! array->get_dimension() ) return;
    534  
     548
    535549                ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
    536550                *out++ = new DeclStmt( noLabels, index );
    537  
     551
    538552                UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
    539553                init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
     
    542556                std::list<Statement *> initList;
    543557                initList.push_back( initStmt );
    544  
     558
    545559                UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
    546560                cond->get_args().push_back( new VariableExpr( index ) );
    547561                cond->get_args().push_back( array->get_dimension()->clone() );
    548  
     562
    549563                UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
    550564                inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
    551  
     565
    552566                UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
    553  
     567
    554568                UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
    555569                derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
    556  
     570
    557571                Expression *dstselect = new MemberExpr( member, derefExpr );
    558572                UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
     
    560574                dstIndex->get_args().push_back( new VariableExpr( index ) );
    561575                assignExpr->get_args().push_back( dstIndex );
    562  
     576
    563577                Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
    564578                UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
     
    566580                srcIndex->get_args().push_back( new VariableExpr( index ) );
    567581                assignExpr->get_args().push_back( srcIndex );
    568  
     582
    569583                *out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
    570584        }
    571585
    572         //E ?=?(E volatile*, int), 
     586        //E ?=?(E volatile*, int),
    573587        //  ?=?(E _Atomic volatile*, int);
    574588        void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
    575589                FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
    576  
     590
    577591                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
    578592                assignType->get_returnVals().push_back( returnVal );
     
    593607                // E ?=?(E volatile *, int)
    594608                assignType2->get_parameters().push_back( dstParam->clone() );
    595                 BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt); 
     609                BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
    596610                ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
    597611                assignType2->get_parameters().push_back( srcParam2 );
     
    645659                        structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    646660                }
    647  
     661
    648662                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    649663                assignType->get_returnVals().push_back( returnVal );
    650  
     664
    651665                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
    652666                assignType->get_parameters().push_back( dstParam );
    653  
     667
    654668                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
    655669                assignType->get_parameters().push_back( srcParam );
     
    659673                FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    660674                assignDecl->fixUniqueId();
    661  
     675
    662676                for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
    663677                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
    664                                 // query the type qualifiers of this field and skip assigning it if it is marked const. 
     678                                // query the type qualifiers of this field and skip assigning it if it is marked const.
    665679                                // If it is an array type, we need to strip off the array layers to find its qualifiers.
    666680                                Type * type = dwt->get_type();
     
    682696                } // for
    683697                assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    684  
     698
    685699                return assignDecl;
    686700        }
     
    697711                        unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
    698712                }
    699  
     713
    700714                ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    701715                assignType->get_returnVals().push_back( returnVal );
    702  
     716
    703717                ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
    704718                assignType->get_parameters().push_back( dstParam );
    705  
     719
    706720                ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
    707721                assignType->get_parameters().push_back( srcParam );
    708  
     722
    709723                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
    710724                // because each unit generates copies of the default routines for each aggregate.
    711725                FunctionDecl *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
    712726                assignDecl->fixUniqueId();
    713  
     727
    714728                UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
    715729                copy->get_args().push_back( new VariableExpr( dstParam ) );
     
    719733                assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
    720734                assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
    721  
     735
    722736                return assignDecl;
    723737        }
     
    727741                        EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
    728742                        // enumInst->set_baseEnum( enumDecl );
    729                         // declsToAdd.push_back( 
     743                        // declsToAdd.push_back(
    730744                        makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
    731745                }
     
    847861
    848862        Type *EliminateTypedef::mutate( TypeInstType * typeInst ) {
    849                 // instances of typedef types will come here. If it is an instance 
     863                // instances of typedef types will come here. If it is an instance
    850864                // of a typdef type, link the instance to its actual type.
    851865                TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
     
    871885                Declaration *ret = Mutator::mutate( tyDecl );
    872886                if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
    873                         // typedef to the same name from the same scope 
     887                        // typedef to the same name from the same scope
    874888                        // must be from the same type
    875889
     
    9931007        }
    9941008
     1009        void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
     1010                VerifyCtorDtor verifier;
     1011                acceptAll( translationUnit, verifier );
     1012        }
     1013
     1014        void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
     1015                FunctionType * funcType = funcDecl->get_functionType();
     1016                std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
     1017                std::list< DeclarationWithType * > &params = funcType->get_parameters();
     1018
     1019                if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
     1020                        if ( params.size() == 0 ) {
     1021                                throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
     1022                        }
     1023                        if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
     1024                                throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
     1025                        }
     1026                        if ( returnVals.size() != 0 ) {
     1027                                throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
     1028                        }
     1029                }
     1030
     1031                Visitor::visit( funcDecl );
     1032                // original idea: modify signature of ctor/dtors and insert appropriate return statements
     1033                // to cause desired behaviour
     1034                // new idea: add comma exprs to every ctor call to produce first parameter.
     1035                // this requires some memoization of the first parameter, because it can be a
     1036                // complicated expression with side effects (see: malloc). idea: add temporary variable
     1037                // that is assigned address of constructed object in ctor argument position and
     1038                // return the temporary. It should also be done after all implicit ctors are
     1039                // added, so not in this pass!
     1040        }
    9951041} // namespace SymTab
    9961042
  • src/initialization.txt

    r0ddb713 r9cb8e88d  
    3434sure that resolved initializers for all declarations are being
    3535generated.
     36
     37
     38------
     39
     40More recent email: (I am quoted; Richard is the responder)
     41> As far as I'm aware, the only way that I could currently get the correct
     42> results from the unification engine is by feeding it an expression that
     43> looks like "?=?( ((struct Y)x.y).a, 10 )", then picking out the pieces that
     44> I need (namely the correct choice for a). Does this seem like a reasonable
     45> approach to solve this problem?
     46
     47No, unfortunately. Initialization isn't being rewritten as assignment,
     48so you shouldn't allow the particular selection of assignment
     49operators that happen to be in scope (and which may include
     50user-defined operators) to guide the type resolution.
     51
     52I don't think there is any way to rewrite an initializer as a single
     53expression and have the resolver just do the right thing. I see the
     54algorithm as:
     55
     56For each alternative interpretation of the designator:
     57  Construct an expression that casts the initializer to the type of
     58    the designator
     59  Construct an AlternativeFinder and use it to find the lowest cost
     60    interpretation of the expression
     61  Add this interpretation to a list of possibilities
     62Go through the list of possibilities and pick the lowest cost
     63
     64As with many things in the resolver, it's conceptually simple but the
     65implementation may be a bit of a pain. It fits in with functions like
     66findSingleExpression, findIntegralExpression in Resolver.cc, although
     67it will be significantly more complicated than any of the existing
     68ones.
     69
     70
     71
Note: See TracChangeset for help on using the changeset viewer.