Changes in / [62cd621:7c782af]


Ignore:
Location:
src
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r62cd621 r7c782af  
    764764
    765765        void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
    766                 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
     766                std::list< Statement * > & stmts = stmtExpr->statements->kids;
    767767                output << "({" << endl;
    768768                ++indent;
     
    775775                                // cannot cast to void, otherwise the expression statement has no value
    776776                                if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
    777                                         exprStmt->get_expr()->accept( *visitor );
     777                                        exprStmt->expr->accept( *visitor );
    778778                                        output << ";" << endl;
    779779                                        ++i;
     
    795795                assertf( ! genC, "Unique expressions should not reach code generation." );
    796796                expr->callExpr->accept( *visitor );
     797        }
     798
     799        void CodeGenerator::postvisit( DeletedExpr * expr ) {
     800                assertf( ! genC, "Deleted expressions should not reach code generation." );
     801                expr->expr->accept( *visitor );
    797802        }
    798803
  • src/CodeGen/CodeGenerator.h

    r62cd621 r7c782af  
    8888                void postvisit( StmtExpr * );
    8989                void postvisit( ConstructorExpr * );
     90                void postvisit( DeletedExpr * );
    9091
    9192                //*** Statements
  • src/Common/PassVisitor.h

    r62cd621 r7c782af  
    121121        virtual void visit( UntypedInitExpr *  initExpr ) override final;
    122122        virtual void visit( InitExpr *  initExpr ) override final;
     123        virtual void visit( DeletedExpr *  delExpr ) override final;
    123124
    124125        virtual void visit( VoidType * basicType ) override final;
     
    215216        virtual Expression * mutate( UntypedInitExpr *  initExpr ) override final;
    216217        virtual Expression * mutate( InitExpr *  initExpr ) override final;
     218        virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
    217219
    218220        virtual Type * mutate( VoidType * basicType ) override final;
     
    303305        void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    304306        void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
    305         void indexerAddWith     ( std::list< Expression * > & exprs ) { indexer_impl_addWith     ( pass, 0, exprs ); }
     307        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith     ( pass, 0, exprs, withStmt ); }
    306308
    307309
  • src/Common/PassVisitor.impl.h

    r62cd621 r7c782af  
    393393                // shadow with exprs and not the other way around.
    394394                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    395                 indexerAddWith( node->withExprs );
     395                indexerAddWith( node->withExprs, node );
    396396                {
    397397                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     
    423423                // shadow with exprs and not the other way around.
    424424                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    425                 indexerAddWith( node->withExprs );
     425                indexerAddWith( node->withExprs, node );
    426426                {
    427427                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     
    10641064                // catch statements introduce a level of scope (for the caught exception)
    10651065                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1066                 indexerAddWith( node->exprs );
     1066                indexerAddWith( node->exprs, node );
    10671067                maybeAccept_impl( node->stmt, *this );
    10681068        }
     
    10771077                // catch statements introduce a level of scope (for the caught exception)
    10781078                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1079                 indexerAddWith( node->exprs );
     1079                indexerAddWith( node->exprs, node );
    10801080                maybeMutate_impl( node->stmt, *this );
    10811081        }
     
    19711971}
    19721972
     1973//--------------------------------------------------------------------------
     1974// DeletedExpr
     1975template< typename pass_type >
     1976void PassVisitor< pass_type >::visit( DeletedExpr * node ) {
     1977        VISIT_START( node );
     1978
     1979        indexerScopedAccept( node->result, *this );
     1980        maybeAccept_impl( node->expr, *this );
     1981        // don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
     1982
     1983        VISIT_END( node );
     1984}
     1985
     1986template< typename pass_type >
     1987Expression * PassVisitor< pass_type >::mutate( DeletedExpr * node ) {
     1988        MUTATE_START( node );
     1989
     1990        indexerScopedMutate( node->env, *this );
     1991        indexerScopedMutate( node->result, *this );
     1992        maybeMutate_impl( node->expr, *this );
     1993
     1994        MUTATE_END( Expression, node );
     1995}
     1996
     1997
    19731998template< typename pass_type >
    19741999void PassVisitor< pass_type >::visit( VoidType * node ) {
  • src/Common/PassVisitor.proto.h

    r62cd621 r7c782af  
    193193
    194194
    195 #define INDEXER_FUNC( func, type )                                                                                             \
     195#define INDEXER_FUNC1( func, type )                                                                                             \
    196196template<typename pass_type>                                                                                                   \
    197197static inline auto indexer_impl_##func ( pass_type & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {   \
     
    202202static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
    203203
    204 INDEXER_FUNC( addId     , DeclarationWithType *       );
    205 INDEXER_FUNC( addType   , NamedTypeDecl *             );
    206 INDEXER_FUNC( addStruct , StructDecl *                );
    207 INDEXER_FUNC( addEnum   , EnumDecl *                  );
    208 INDEXER_FUNC( addUnion  , UnionDecl *                 );
    209 INDEXER_FUNC( addTrait  , TraitDecl *                 );
    210 INDEXER_FUNC( addWith   , std::list< Expression * > & );
     204#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
     205template<typename pass_type>                                                                                                   \
     206static inline auto indexer_impl_##func ( pass_type & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void() ) {   \
     207        pass.indexer.func( arg1, arg2 );                                                                                                \
     208}                                                                                                                              \
     209                                                                                                                               \
     210template<typename pass_type>                                                                                                   \
     211static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
     212
     213
     214INDEXER_FUNC1( addId     , DeclarationWithType *       );
     215INDEXER_FUNC1( addType   , NamedTypeDecl *             );
     216INDEXER_FUNC1( addStruct , StructDecl *                );
     217INDEXER_FUNC1( addEnum   , EnumDecl *                  );
     218INDEXER_FUNC1( addUnion  , UnionDecl *                 );
     219INDEXER_FUNC1( addTrait  , TraitDecl *                 );
     220INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    211221
    212222
  • src/Common/utility.h

    r62cd621 r7c782af  
    9898}
    9999
     100template< typename SrcContainer, typename DestContainer, typename Predicate >
     101void cloneAll_if( const SrcContainer &src, DestContainer &dest, Predicate pred ) {
     102        std::back_insert_iterator< DestContainer > out( dest );
     103        for ( auto x : src ) {
     104                if ( pred(x) ) {
     105                        *out++ = x->clone();
     106                }
     107        } // while
     108}
     109
    100110template< typename Container >
    101111void assertAll( const Container &container ) {
  • src/ResolvExpr/Alternative.h

    r62cd621 r7c782af  
    5757        /// Moves all elements from src to the beginning of dst
    5858        void spliceBegin( AltList& dst, AltList& src );
     59
     60        static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) {
     61                alt.print( os );
     62                return os;
     63        }
    5964} // namespace ResolvExpr
    6065
  • src/ResolvExpr/AlternativeFinder.cc

    r62cd621 r7c782af  
    9595                void postvisit( StmtExpr * stmtExpr );
    9696                void postvisit( UntypedInitExpr * initExpr );
     97                void postvisit( InitExpr * initExpr );
     98                void postvisit( DeletedExpr * delExpr );
    9799
    98100                /// Adds alternatives for anonymous members
     
    120122                Type *& targetType;
    121123        };
    122 
    123         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    124                 CastExpr *castToVoid = new CastExpr( expr );
    125 
    126                 AlternativeFinder finder( indexer, env );
    127                 finder.findWithAdjustment( castToVoid );
    128 
    129                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    130                 // interpretations, an exception has already been thrown.
    131                 assert( finder.get_alternatives().size() == 1 );
    132                 CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );
    133                 assert( newExpr );
    134                 env = finder.get_alternatives().front().env;
    135                 return newExpr->get_arg()->clone();
    136         }
    137124
    138125        Cost sumCost( const AltList &in ) {
     
    13801367        void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) {
    13811368                std::list< SymTab::Indexer::IdData > declList;
    1382                 indexer.lookupId( nameExpr->get_name(), declList );
    1383                 PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
     1369                indexer.lookupId( nameExpr->name, declList );
     1370                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    13841371                for ( auto & data : declList ) {
    13851372                        Expression * newExpr = data.combine();
     
    14021389                // not sufficient to clone here, because variable's type may have changed
    14031390                // since the VariableExpr was originally created.
    1404                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->get_var() ), env, Cost::zero ) );
     1391                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
    14051392        }
    14061393
     
    14691456                // xxx - resolveTypeof?
    14701457                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) {
    1471                         addOffsetof( structInst, offsetofExpr->get_member() );
     1458                        addOffsetof( structInst, offsetofExpr->member );
    14721459                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( offsetofExpr->get_type() ) ) {
    1473                         addOffsetof( unionInst, offsetofExpr->get_member() );
     1460                        addOffsetof( unionInst, offsetofExpr->member );
    14741461                }
    14751462        }
     
    15481535                secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
    15491536                if ( secondFinder.alternatives.empty() ) return;
    1550                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1551                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     1537                for ( const Alternative & first : firstFinder.alternatives ) {
     1538                        for ( const Alternative & second : secondFinder.alternatives ) {
    15521539                                TypeEnvironment compositeEnv;
    1553                                 compositeEnv.simpleCombine( first->env );
    1554                                 compositeEnv.simpleCombine( second->env );
    1555 
    1556                                 LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() );
    1557                                 alternatives.push_back( Alternative( newExpr, compositeEnv, first->cost + second->cost ) );
     1540                                compositeEnv.simpleCombine( first.env );
     1541                                compositeEnv.simpleCombine( second.env );
     1542
     1543                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1544                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
    15581545                        }
    15591546                }
     
    16051592                AlternativeFinder secondFinder( indexer, newEnv );
    16061593                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    1607                 for ( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt ) {
    1608                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt->expr->clone() ), alt->env, alt->cost ) );
     1594                for ( const Alternative & alt : secondFinder.alternatives ) {
     1595                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    16091596                } // for
    16101597                delete newFirstArg;
     
    16141601                // resolve low and high, accept alternatives whose low and high types unify
    16151602                AlternativeFinder firstFinder( indexer, env );
    1616                 firstFinder.findWithAdjustment( rangeExpr->get_low() );
     1603                firstFinder.findWithAdjustment( rangeExpr->low );
    16171604                if ( firstFinder.alternatives.empty() ) return;
    16181605                AlternativeFinder secondFinder( indexer, env );
    1619                 secondFinder.findWithAdjustment( rangeExpr->get_high() );
     1606                secondFinder.findWithAdjustment( rangeExpr->high );
    16201607                if ( secondFinder.alternatives.empty() ) return;
    1621                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1622                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     1608                for ( const Alternative & first : firstFinder.alternatives ) {
     1609                        for ( const Alternative & second : secondFinder.alternatives ) {
    16231610                                TypeEnvironment compositeEnv;
    1624                                 compositeEnv.simpleCombine( first->env );
    1625                                 compositeEnv.simpleCombine( second->env );
     1611                                compositeEnv.simpleCombine( first.env );
     1612                                compositeEnv.simpleCombine( second.env );
    16261613                                OpenVarSet openVars;
    16271614                                AssertionSet needAssertions, haveAssertions;
    1628                                 Alternative newAlt( 0, compositeEnv, first->cost + second->cost );
     1615                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    16291616                                Type* commonType = nullptr;
    1630                                 if ( unify( first->expr->get_result(), second->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1631                                         RangeExpr *newExpr = new RangeExpr( first->expr->clone(), second->expr->clone() );
    1632                                         newExpr->set_result( commonType ? commonType : first->expr->get_result()->clone() );
     1617                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1618                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1619                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    16331620                                        newAlt.expr = newExpr;
    16341621                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     
    17511738                findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    17521739        }
     1740
     1741        void AlternativeFinder::Finder::postvisit( InitExpr * ) {
     1742                assertf( false, "AlternativeFinder should never see a resolved InitExpr." );
     1743        }
     1744
     1745        void AlternativeFinder::Finder::postvisit( DeletedExpr * ) {
     1746                assertf( false, "AlternativeFinder should never see a DeletedExpr." );
     1747        }
    17531748} // namespace ResolvExpr
    17541749
  • src/ResolvExpr/Resolver.cc

    r62cd621 r7c782af  
    105105        }
    106106
    107         // used in resolveTypeof
    108         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    109                 TypeEnvironment env;
    110                 return resolveInVoidContext( expr, indexer, env );
     107        namespace {
     108                struct DeleteFinder : public WithShortCircuiting        {
     109                        DeletedExpr * delExpr = nullptr;
     110                        void previsit( DeletedExpr * expr ) {
     111                                if ( delExpr ) visit_children = false;
     112                                else delExpr = expr;
     113                        }
     114
     115                        void previsit( Expression * ) {
     116                                if ( delExpr ) visit_children = false;
     117                        }
     118                };
     119        }
     120
     121        DeletedExpr * findDeletedExpr( Expression * expr ) {
     122                PassVisitor<DeleteFinder> finder;
     123                expr->accept( finder );
     124                return finder.pass.delExpr;
    111125        }
    112126
     
    130144        } // namespace
    131145
     146        namespace {
     147                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     148                        assertf( untyped, "expected a non-null expression." );
     149                        TypeEnvironment env;
     150                        AlternativeFinder finder( indexer, env );
     151                        finder.find( untyped, adjust, prune, failFast );
     152
     153                        #if 0
     154                        if ( finder.get_alternatives().size() != 1 ) {
     155                                std::cerr << "untyped expr is ";
     156                                untyped->print( std::cerr );
     157                                std::cerr << std::endl << "alternatives are:";
     158                                for ( const Alternative & alt : finder.get_alternatives() ) {
     159                                        alt.print( std::cerr );
     160                                } // for
     161                        } // if
     162                        #endif
     163
     164                        AltList candidates;
     165                        for ( Alternative & alt : finder.get_alternatives() ) {
     166                                if ( pred( alt ) ) {
     167                                        candidates.push_back( std::move( alt ) );
     168                                }
     169                        }
     170
     171                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     172                        // choose the lowest cost expression among the candidates
     173                        AltList winners;
     174                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     175                        if ( winners.size() == 0 ) {
     176                                throw SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     177                        } else if ( winners.size() != 1 ) {
     178                                std::ostringstream stream;
     179                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     180                                untyped->print( stream );
     181                                stream << "Alternatives are:\n";
     182                                printAlts( winners, stream, 1 );
     183                                throw SemanticError( untyped->location, stream.str() );
     184                        }
     185
     186                        // there is one unambiguous interpretation - move the expression into the with statement
     187                        Alternative & choice = winners.front();
     188                        if ( findDeletedExpr( choice.expr ) ) {
     189                                throw SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
     190                        }
     191                        alt = std::move( choice );
     192                }
     193
     194                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
     195                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     196                        if ( ! untyped ) return;
     197                        Alternative choice;
     198                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     199                        finishExpr( choice.expr, choice.env, untyped->env );
     200                        delete untyped;
     201                        untyped = choice.expr;
     202                        choice.expr = nullptr;
     203                }
     204
     205                bool standardAlternativeFilter( const Alternative & ) {
     206                        // currently don't need to filter, under normal circumstances.
     207                        // in the future, this may be useful for removing deleted expressions
     208                        return true;
     209                }
     210        } // namespace
     211
     212        // used in resolveTypeof
     213        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     214                TypeEnvironment env;
     215                return resolveInVoidContext( expr, indexer, env );
     216        }
     217
     218        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
     219                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
     220                // interpretations, an exception has already been thrown.
     221                assertf( expr, "expected a non-null expression." );
     222
     223                static CastExpr untyped( nullptr ); // cast to void
     224
     225                // set up and resolve expression cast to void
     226                untyped.arg = expr;
     227                Alternative choice;
     228                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     229                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
     230                env = std::move( choice.env );
     231
     232                // clean up resolved expression
     233                Expression * ret = castExpr->arg;
     234                castExpr->arg = nullptr;
     235
     236                // unlink the arg so that it isn't deleted twice at the end of the program
     237                untyped.arg = nullptr;
     238                return ret;
     239        }
     240
    132241        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    133242                resetTyVarRenaming();
    134243                TypeEnvironment env;
    135                 Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
     244                Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
    136245                finishExpr( newExpr, env, untyped->env );
    137246                delete untyped;
     
    140249
    141250        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    142                 if ( ! untyped ) return;
    143                 TypeEnvironment env;
    144                 AlternativeFinder finder( indexer, env );
    145                 finder.find( untyped );
    146                 #if 0
    147                 if ( finder.get_alternatives().size() != 1 ) {
    148                         std::cerr << "untyped expr is ";
    149                         untyped->print( std::cerr );
    150                         std::cerr << std::endl << "alternatives are:";
    151                         for ( const Alternative & alt : finder.get_alternatives() ) {
    152                                 alt.print( std::cerr );
    153                         } // for
    154                 } // if
    155                 #endif
    156                 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() );
    157                 Alternative &choice = finder.get_alternatives().front();
    158                 Expression *newExpr = choice.expr->clone();
    159                 finishExpr( newExpr, choice.env, untyped->env );
    160                 delete untyped;
    161                 untyped = newExpr;
     251                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    162252        }
    163253
     
    170260
    171261        namespace {
    172                 /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    173                 template<typename Pred>
    174                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) {
    175                         TypeEnvironment env;
    176                         AlternativeFinder finder( indexer, env );
    177                         finder.findWithAdjustment( untyped );
    178 
    179                         AltList candidates;
    180                         for ( Alternative & alt : finder.get_alternatives() ) {
    181                                 if ( pred( alt.expr->result ) ) {
    182                                         candidates.push_back( std::move( alt ) );
    183                                 }
    184                         }
    185 
    186                         // choose the lowest cost expression among the candidates
    187                         AltList winners;
    188                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    189                         if ( winners.size() == 0 ) {
    190                                 throw SemanticError( untyped, "No reasonable alternatives for " + kindStr + " expression: " );
    191                         } else if ( winners.size() != 1 ) {
    192                                 std::ostringstream stream;
    193                                 stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr +  " expression\n";
    194                                 untyped->print( stream );
    195                                 stream << "Alternatives are:\n";
    196                                 printAlts( winners, stream, 1 );
    197                                 throw SemanticError( untyped->location, stream.str() );
    198                         }
    199 
    200                         // there is one unambiguous interpretation - move the expression into the with statement
    201                         Alternative & alt = winners.front();
    202                         finishExpr( alt.expr, alt.env, untyped->env );
    203                         delete untyped;
    204                         untyped = alt.expr;
    205                         alt.expr = nullptr;
    206                 }
    207 
    208                 bool isIntegralType( Type *type ) {
     262                bool isIntegralType( const Alternative & alt ) {
     263                        Type * type = alt.expr->result;
    209264                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    210265                                return true;
     
    559614                        if( func_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    560615                        if( args_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    561 
     616                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    562617
    563618                        // Swap the results from the alternative with the unresolved values.
     
    592647        }
    593648
    594         bool isStructOrUnion( Type * t ) {
    595                 t = t->stripReferences();
     649        bool isStructOrUnion( const Alternative & alt ) {
     650                Type * t = alt.expr->result->stripReferences();
    596651                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    597652        }
  • src/ResolvExpr/Unify.cc

    r62cd621 r7c782af  
    563563                        flatten( dcl->get_type(), back_inserter( types ) );
    564564                        for ( Type * t : types ) {
     565                                // outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable.
     566                                // Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function.
     567                                t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic);
     568
    565569                                dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    566570                        }
     
    580584
    581585                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    582                         if ( (flatFunc->get_parameters().size() == flatOther->get_parameters().size() && flatFunc->get_returnVals().size() == flatOther->get_returnVals().size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
    583                                 if ( unifyDeclList( flatFunc->get_parameters().begin(), flatFunc->get_parameters().end(), flatOther->get_parameters().begin(), flatOther->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    584                                         if ( unifyDeclList( flatFunc->get_returnVals().begin(), flatFunc->get_returnVals().end(), flatOther->get_returnVals().begin(), flatOther->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     586                        if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
     587                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     588                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    585589
    586590                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    599603                // check that other type is compatible and named the same
    600604                RefType *otherStruct = dynamic_cast< RefType* >( other );
    601                 result = otherStruct && inst->get_name() == otherStruct->get_name();
     605                result = otherStruct && inst->name == otherStruct->name;
    602606        }
    603607
     
    608612                if ( ! result ) return;
    609613                // Check that parameters of types unify, if any
    610                 std::list< Expression* > params = inst->get_parameters();
    611                 std::list< Expression* > otherParams = ((RefType*)other)->get_parameters();
     614                std::list< Expression* > params = inst->parameters;
     615                std::list< Expression* > otherParams = ((RefType*)other)->parameters;
    612616
    613617                std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
  • src/SymTab/Autogen.cc

    r62cd621 r7c782af  
    377377                        paramType->attributes.clear();
    378378                        // add a parameter corresponding to this field
    379                         memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr ) );
     379                        ObjectDecl * param = new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr );
     380                        cloneAll_if( field->attributes, param->attributes, [](Attribute * attr) { return attr->isValidOnFuncParam(); } );
     381                        memCtorType->parameters.push_back( param );
    380382                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    381383                        makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor );
  • src/SymTab/FixFunction.cc

    r62cd621 r7c782af  
    3636        }
    3737
     38        // xxx - this passes on void[], e.g.
     39        //   void foo(void [10]);
     40        // does not cause an error
     41
    3842        Type * FixFunction::postmutate(ArrayType *arrayType) {
    3943                // need to recursively mutate the base type in order for multi-dimensional arrays to work.
     
    6266        void FixFunction::premutate(ZeroType *) { visit_children = false; }
    6367        void FixFunction::premutate(OneType *) { visit_children = false; }
     68
     69        bool fixFunction( DeclarationWithType *& dwt ) {
     70                PassVisitor<FixFunction> fixer;
     71                dwt = dwt->acceptMutator( fixer );
     72                return fixer.pass.isVoid;
     73        }
    6474} // namespace SymTab
    6575
  • src/SymTab/FixFunction.h

    r62cd621 r7c782af  
    4747                bool isVoid;
    4848        };
     49
     50        bool fixFunction( DeclarationWithType *& );
    4951} // namespace SymTab
    5052
  • src/SymTab/Indexer.cc

    r62cd621 r7c782af  
    286286        }
    287287
    288         DeclarationWithType *Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    289                 if ( ! tables ) return 0;
    290                 if ( tables->scope < scope ) return 0;
     288        const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     289                if ( ! tables ) return nullptr;
     290                if ( tables->scope < scope ) return nullptr;
    291291
    292292                IdTable::const_iterator decls = tables->idTable.find( id );
     
    294294                        const MangleTable &mangleTable = decls->second;
    295295                        MangleTable::const_iterator decl = mangleTable.find( mangleName );
    296                         if ( decl != mangleTable.end() ) return decl->second.id;
     296                        if ( decl != mangleTable.end() ) return &decl->second;
    297297                }
    298298
    299299                return tables->base.lookupIdAtScope( id, mangleName, scope );
     300        }
     301
     302        Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) {
     303                return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope ));
    300304        }
    301305
     
    373377        }
    374378
    375         bool addedIdConflicts( DeclarationWithType *existing, DeclarationWithType *added ) {
     379        bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) {
    376380                // if we're giving the same name mangling to things of different types then there is something wrong
    377                 assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing ) )
    378                         || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing ) ) );
    379 
    380                 if ( LinkageSpec::isOverridable( existing->get_linkage() ) ) {
     381                assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing.id ) )
     382                        || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing.id ) ) );
     383
     384                if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
    381385                        // new definition shadows the autogenerated one, even at the same scope
    382386                        return false;
    383                 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
     387                } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) {
     388
     389                        // it is a conflict if one declaration is deleted and the other is not
     390                        if ( deleteStmt && ! existing.deleteStmt ) {
     391                                return handleConflicts( existing, "deletion of defined identifier " );
     392                        } else if ( ! deleteStmt && existing.deleteStmt ) {
     393                                return handleConflicts( existing, "definition of deleted identifier " );
     394                        }
     395
    384396                        // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
    385397                        // we should ignore outermost pointer qualifiers, except _Atomic?
    386                         FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( added );
    387                         FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( existing );
     398                        FunctionDecl * newentry = dynamic_cast< FunctionDecl * >( added );
     399                        FunctionDecl * oldentry = dynamic_cast< FunctionDecl * >( existing.id );
    388400                        if ( newentry && oldentry ) {
    389401                                if ( newentry->get_statements() && oldentry->get_statements() ) {
    390                                         throw SemanticError( added, "duplicate function definition for " );
     402                                        return handleConflicts( existing, "duplicate function definition for " );
    391403                                } // if
    392404                        } else {
     
    395407                                // xxx - perhaps it's actually if either is intrinsic then this is okay?
    396408                                //       might also need to be same storage class?
    397                                 ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( added );
    398                                 ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
     409                                ObjectDecl * newobj = dynamic_cast< ObjectDecl * >( added );
     410                                ObjectDecl * oldobj = dynamic_cast< ObjectDecl * >( existing.id );
    399411                                if ( ! newobj->get_storageClasses().is_extern && ! oldobj->get_storageClasses().is_extern ) {
    400                                         throw SemanticError( added, "duplicate object definition for " );
     412                                        return handleConflicts( existing, "duplicate object definition for " );
    401413                                } // if
    402414                        } // if
    403415                } else {
    404                         throw SemanticError( added, "duplicate definition for " );
     416                        return handleConflicts( existing, "duplicate definition for " );
    405417                } // if
    406418
     
    408420        }
    409421
    410         void Indexer::addId( DeclarationWithType *decl, Expression * baseExpr ) {
     422        void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) {
    411423                if ( decl->name == "" ) return;
    412424                debugPrint( "Adding Id " << decl->name << std::endl );
     
    434446                        }
    435447                } else {
    436                         // Check that a Cforall declaration doesn't overload any C declaration
     448                        // Check that a Cforall declaration doesn't override any C declaration
    437449                        if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
    438450                                throw SemanticError( decl, "Cforall declaration hides C function " );
     
    441453
    442454                // Skip repeat declarations of the same identifier
    443                 DeclarationWithType *existing = lookupIdAtScope( name, mangleName, scope );
    444                 if ( existing && addedIdConflicts( existing, decl ) ) return;
     455                IdData * existing = lookupIdAtScope( name, mangleName, scope );
     456                if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return;
    445457
    446458                // add to indexer
    447                 tables->idTable[ name ][ mangleName ] = { decl, baseExpr };
     459                tables->idTable[ name ][ mangleName ] = { decl, baseExpr, deleteStmt };
    448460                ++tables->size;
     461        }
     462
     463        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
     464                // default handling of conflicts is to raise an error
     465                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, baseExpr );
     466        }
     467
     468        void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
     469                // default handling of conflicts is to raise an error
     470                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
    449471        }
    450472
     
    573595        }
    574596
    575         void Indexer::addMembers( AggregateDecl * aggr, Expression * expr ) {
     597        void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction handleConflicts ) {
    576598                for ( Declaration * decl : aggr->members ) {
    577599                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    578                                 addId( dwt, expr );
     600                                addId( dwt, handleConflicts, expr );
    579601                                if ( dwt->name == "" ) {
    580602                                        Type * t = dwt->get_type()->stripReferences();
     
    582604                                                Expression * base = expr->clone();
    583605                                                ResolvExpr::referenceToRvalueConversion( base );
    584                                                 addMembers( t->getAggr(), new MemberExpr( dwt, base ) );
     606                                                addMembers( t->getAggr(), new MemberExpr( dwt, base ), handleConflicts );
    585607                                        }
    586608                                }
     
    589611        }
    590612
    591         void Indexer::addWith( std::list< Expression * > & withExprs ) {
     613        void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
    592614                for ( Expression * expr : withExprs ) {
    593615                        if ( expr->result ) {
     
    595617                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
    596618
    597                                 addMembers( aggr, expr );
     619                                addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) {
     620                                        // on conflict, delete the identifier
     621                                        existing.deleteStmt = withStmt;
     622                                        return true;
     623                                });
    598624                        }
    599625                }
     
    654680
    655681        void Indexer::print( std::ostream &os, int indent ) const {
    656             using std::cerr;
     682                using std::cerr;
    657683
    658684                if ( tables ) {
     
    680706
    681707        Expression * Indexer::IdData::combine() const {
     708                Expression * ret = nullptr;
    682709                if ( baseExpr ) {
    683710                        Expression * base = baseExpr->clone();
    684711                        ResolvExpr::referenceToRvalueConversion( base );
    685                         Expression * ret = new MemberExpr( id, base );
     712                        ret = new MemberExpr( id, base );
    686713                        // xxx - this introduces hidden environments, for now remove them.
    687714                        // std::swap( base->env, ret->env );
    688715                        delete base->env;
    689716                        base->env = nullptr;
    690                         return ret;
    691                 } else {
    692                         return new VariableExpr( id );
    693                 }
     717                } else {
     718                        ret = new VariableExpr( id );
     719                }
     720                if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
     721                return ret;
    694722        }
    695723} // namespace SymTab
  • src/SymTab/Indexer.h

    r62cd621 r7c782af  
    1919#include <list>               // for list
    2020#include <string>             // for string
     21#include <functional>         // for function
    2122
    2223#include "SynTree/Visitor.h"  // for Visitor
     
    4041
    4142                struct IdData {
    42                         DeclarationWithType * id;
    43                         Expression * baseExpr; // WithExpr
     43                        DeclarationWithType * id = nullptr;
     44                        Expression * baseExpr = nullptr; // WithExpr
     45
     46                        /// non-null if this declaration is deleted
     47                        BaseSyntaxNode * deleteStmt = nullptr;
    4448
    4549                        Expression * combine() const;
     
    6266
    6367                /// looks up a specific mangled ID at the given scope
    64                 DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     68                IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope );
     69                const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
    6570                /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
    6671                bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     
    7479                TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
    7580
    76                 void addId( DeclarationWithType *decl, Expression * baseExpr = nullptr );
     81                typedef std::function<bool(IdData &, const std::string &)> ConflictFunction;
     82
     83                void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr );
     84                void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt );
     85
    7786                void addType( NamedTypeDecl *decl );
    7887                void addStruct( const std::string &id );
     
    8493
    8594                /// adds all of the IDs from WithStmt exprs
    86                 void addWith( std::list< Expression * > & withExprs );
     95                void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt );
    8796
    8897                /// adds all of the members of the Aggregate (addWith helper)
    89                 void addMembers( AggregateDecl * aggr, Expression * expr );
     98                void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction );
    9099
    91100                /// convenience function for adding a list of Ids to the indexer
     
    117126                /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
    118127                void makeWritable();
     128
     129                /// common code for addId, addDeletedId, etc.
     130                void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
    119131        };
    120132} // namespace SymTab
  • src/SymTab/Mangler.cc

    r62cd621 r7c782af  
    3737                        struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler> {
    3838                                Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
    39                                 Mangler( const Mangler & );
     39                                Mangler( const Mangler & ) = delete;
    4040
    4141                                void previsit( BaseSyntaxNode * ) { visit_children = false; }
  • src/SymTab/Validate.cc

    r62cd621 r7c782af  
    351351        namespace {
    352352                template< typename DWTList >
    353                 void fixFunctionList( DWTList & dwts, FunctionType * func ) {
    354                         // the only case in which "void" is valid is where it is the only one in the list; then it should be removed
    355                         // entirely. other fix ups are handled by the FixFunction class
    356                         typedef typename DWTList::iterator DWTIterator;
    357                         DWTIterator begin( dwts.begin() ), end( dwts.end() );
    358                         if ( begin == end ) return;
    359                         PassVisitor<FixFunction> fixer;
    360                         DWTIterator i = begin;
    361                         *i = (*i)->acceptMutator( fixer );
    362                         if ( fixer.pass.isVoid ) {
    363                                 DWTIterator j = i;
    364                                 ++i;
    365                                 delete *j;
    366                                 dwts.erase( j );
    367                                 if ( i != end ) {
    368                                         throw SemanticError( func, "invalid type void in function type " );
    369                                 } // if
    370                         } else {
    371                                 ++i;
    372                                 for ( ; i != end; ++i ) {
    373                                         PassVisitor<FixFunction> fixer;
    374                                         *i = (*i)->acceptMutator( fixer );
    375                                         if ( fixer.pass.isVoid ) {
    376                                                 throw SemanticError( func, "invalid type void in function type " );
    377                                         } // if
    378                                 } // for
    379                         } // if
     353                void fixFunctionList( DWTList & dwts, bool isVarArgs, FunctionType * func ) {
     354                        auto nvals = dwts.size();
     355                        bool containsVoid = false;
     356                        for ( auto & dwt : dwts ) {
     357                                // fix each DWT and record whether a void was found
     358                                containsVoid |= fixFunction( dwt );
     359                        }
     360
     361                        // the only case in which "void" is valid is where it is the only one in the list
     362                        if ( containsVoid && ( nvals > 1 || isVarArgs ) ) {
     363                                throw SemanticError( func, "invalid type void in function type " );
     364                        }
     365
     366                        // one void is the only thing in the list; remove it.
     367                        if ( containsVoid ) {
     368                                delete dwts.front();
     369                                dwts.clear();
     370                        }
    380371                }
    381372        }
     
    383374        void EnumAndPointerDecay::previsit( FunctionType *func ) {
    384375                // Fix up parameters and return types
    385                 fixFunctionList( func->get_parameters(), func );
    386                 fixFunctionList( func->get_returnVals(), func );
     376                fixFunctionList( func->parameters, func->isVarArgs, func );
     377                fixFunctionList( func->returnVals, false, func );
    387378        }
    388379
     
    626617                        // apply FixFunction to every assertion to check for invalid void type
    627618                        for ( DeclarationWithType *& assertion : type->assertions ) {
    628                                 PassVisitor<FixFunction> fixer;
    629                                 assertion = assertion->acceptMutator( fixer );
    630                                 if ( fixer.pass.isVoid ) {
     619                                bool isVoid = fixFunction( assertion );
     620                                if ( isVoid ) {
    631621                                        throw SemanticError( node, "invalid type void in assertion of function " );
    632622                                } // if
  • src/SynTree/Attribute.cc

    r62cd621 r7c782af  
    1515
    1616#include <ostream>           // for operator<<, ostream, basic_ostream, endl
     17#include <set>
    1718
    1819#include "Attribute.h"
     
    2122
    2223Attribute::Attribute( const Attribute &other ) : name( other.name ) {
    23   cloneAll( other.parameters, parameters );
     24        cloneAll( other.parameters, parameters );
    2425}
    2526
    2627Attribute::~Attribute() {
    27   deleteAll( parameters );
     28        deleteAll( parameters );
     29}
     30
     31bool Attribute::isValidOnFuncParam() const {
     32        // attributes such as aligned, cleanup, etc. produce GCC errors when they appear
     33        // on function parameters. Maintain here a whitelist of attribute names that are
     34        // allowed to appear on parameters.
     35        static std::set< std::string > valid = {
     36                "noreturn", "unused"
     37        };
     38        return valid.count( normalizedName() );
     39}
     40
     41std::string Attribute::normalizedName() const {
     42        // trim beginning/ending _, convert to lowercase
     43        auto begin = name.find_first_not_of('_');
     44        auto end = name.find_last_not_of('_');
     45        if (begin == std::string::npos || end == std::string::npos) return "";
     46        std::string ret;
     47        ret.reserve( end-begin+1 );
     48        std::transform( &name[begin], &name[end+1], back_inserter( ret ), tolower );
     49        return ret;
    2850}
    2951
    3052void Attribute::print( std::ostream &os, Indenter indent ) const {
    31   using std::endl;
    32   using std::string;
     53        using std::endl;
     54        using std::string;
    3355
    34   if ( ! empty() ) {
    35     os << "Attribute with name: " << name;
    36     if ( ! parameters.empty() ) {
    37       os << " with parameters: " << endl;
    38       printAll( parameters, os, indent+1 );
    39     }
    40   }
     56        if ( ! empty() ) {
     57                os << "Attribute with name: " << name;
     58                if ( ! parameters.empty() ) {
     59                        os << " with parameters: " << endl;
     60                        printAll( parameters, os, indent+1 );
     61                }
     62        }
    4163}
    4264
  • src/SynTree/Attribute.h

    r62cd621 r7c782af  
    4343        bool empty() const { return name == ""; }
    4444
     45        std::string normalizedName() const;
     46
     47        /// true if this attribute is allowed to appear attached to a function parameter
     48        bool isValidOnFuncParam() const;
     49
    4550        Attribute * clone() const override { return new Attribute( *this ); }
    4651        virtual void accept( Visitor & v ) override { v.visit( this ); }
  • src/SynTree/Expression.cc

    r62cd621 r7c782af  
    710710}
    711711
     712DeletedExpr::DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt ) : expr( expr ), deleteStmt( deleteStmt ) {
     713        assert( expr->result );
     714        result = expr->result->clone();
     715}
     716DeletedExpr::DeletedExpr( const DeletedExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), deleteStmt( other.deleteStmt ) {}
     717DeletedExpr::~DeletedExpr() {
     718        delete expr;
     719}
     720
     721void DeletedExpr::print( std::ostream & os, Indenter indent ) const {
     722        os << "Deleted Expression" << std::endl << indent+1;
     723        expr->print( os, indent+1 );
     724        os << std::endl << indent+1 << "... deleted by: ";
     725        deleteStmt->print( os, indent+1 );
     726}
     727
     728
    712729// Local Variables: //
    713730// tab-width: 4 //
  • src/SynTree/Expression.h

    r62cd621 r7c782af  
    822822};
    823823
     824/// expression that contains a deleted identifier - should never make it past the resolver.
     825class DeletedExpr : public Expression {
     826public:
     827        Expression * expr;
     828        BaseSyntaxNode * deleteStmt;
     829
     830        DeletedExpr( Expression * expr, BaseSyntaxNode * deleteStmt );
     831        DeletedExpr( const DeletedExpr & other );
     832        ~DeletedExpr();
     833
     834        virtual DeletedExpr * clone() const { return new DeletedExpr( * this ); }
     835        virtual void accept( Visitor & v ) { v.visit( this ); }
     836        virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
     837        virtual void print( std::ostream & os, Indenter indent = {} ) const;
     838};
     839
    824840// Local Variables: //
    825841// tab-width: 4 //
  • src/SynTree/Mutator.h

    r62cd621 r7c782af  
    5555        virtual Statement * mutate( ImplicitCtorDtorStmt * impCtorDtorStmt );
    5656
    57         virtual Expression* mutate( ApplicationExpr * applicationExpr );
    58         virtual Expression* mutate( UntypedExpr * untypedExpr );
    59         virtual Expression* mutate( NameExpr * nameExpr );
    60         virtual Expression* mutate( AddressExpr * castExpr );
    61         virtual Expression* mutate( LabelAddressExpr * labAddressExpr );
    62         virtual Expression* mutate( CastExpr * castExpr );
    63         virtual Expression* mutate( VirtualCastExpr * castExpr );
    64         virtual Expression* mutate( UntypedMemberExpr * memberExpr );
    65         virtual Expression* mutate( MemberExpr * memberExpr );
    66         virtual Expression* mutate( VariableExpr * variableExpr );
    67         virtual Expression* mutate( ConstantExpr * constantExpr );
    68         virtual Expression* mutate( SizeofExpr * sizeofExpr );
    69         virtual Expression* mutate( AlignofExpr * alignofExpr );
    70         virtual Expression* mutate( UntypedOffsetofExpr * offsetofExpr );
    71         virtual Expression* mutate( OffsetofExpr * offsetofExpr );
    72         virtual Expression* mutate( OffsetPackExpr * offsetPackExpr );
    73         virtual Expression* mutate( AttrExpr * attrExpr );
    74         virtual Expression* mutate( LogicalExpr * logicalExpr );
    75         virtual Expression* mutate( ConditionalExpr * conditionalExpr );
    76         virtual Expression* mutate( CommaExpr * commaExpr );
    77         virtual Expression* mutate( TypeExpr * typeExpr );
    78         virtual Expression* mutate( AsmExpr * asmExpr );
    79         virtual Expression* mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    80         virtual Expression* mutate( ConstructorExpr * ctorExpr );
    81         virtual Expression* mutate( CompoundLiteralExpr * compLitExpr );
    82         virtual Expression* mutate( RangeExpr * rangeExpr );
    83         virtual Expression* mutate( UntypedTupleExpr * tupleExpr );
    84         virtual Expression* mutate( TupleExpr * tupleExpr );
    85         virtual Expression* mutate( TupleIndexExpr * tupleExpr );
    86         virtual Expression* mutate( TupleAssignExpr * assignExpr );
    87         virtual Expression* mutate( StmtExpr  * stmtExpr );
    88         virtual Expression* mutate( UniqueExpr  * uniqueExpr );
    89         virtual Expression* mutate( UntypedInitExpr  * initExpr );
    90         virtual Expression* mutate( InitExpr  * initExpr );
     57        virtual Expression * mutate( ApplicationExpr * applicationExpr );
     58        virtual Expression * mutate( UntypedExpr * untypedExpr );
     59        virtual Expression * mutate( NameExpr * nameExpr );
     60        virtual Expression * mutate( AddressExpr * castExpr );
     61        virtual Expression * mutate( LabelAddressExpr * labAddressExpr );
     62        virtual Expression * mutate( CastExpr * castExpr );
     63        virtual Expression * mutate( VirtualCastExpr * castExpr );
     64        virtual Expression * mutate( UntypedMemberExpr * memberExpr );
     65        virtual Expression * mutate( MemberExpr * memberExpr );
     66        virtual Expression * mutate( VariableExpr * variableExpr );
     67        virtual Expression * mutate( ConstantExpr * constantExpr );
     68        virtual Expression * mutate( SizeofExpr * sizeofExpr );
     69        virtual Expression * mutate( AlignofExpr * alignofExpr );
     70        virtual Expression * mutate( UntypedOffsetofExpr * offsetofExpr );
     71        virtual Expression * mutate( OffsetofExpr * offsetofExpr );
     72        virtual Expression * mutate( OffsetPackExpr * offsetPackExpr );
     73        virtual Expression * mutate( AttrExpr * attrExpr );
     74        virtual Expression * mutate( LogicalExpr * logicalExpr );
     75        virtual Expression * mutate( ConditionalExpr * conditionalExpr );
     76        virtual Expression * mutate( CommaExpr * commaExpr );
     77        virtual Expression * mutate( TypeExpr * typeExpr );
     78        virtual Expression * mutate( AsmExpr * asmExpr );
     79        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     80        virtual Expression * mutate( ConstructorExpr * ctorExpr );
     81        virtual Expression * mutate( CompoundLiteralExpr * compLitExpr );
     82        virtual Expression * mutate( RangeExpr * rangeExpr );
     83        virtual Expression * mutate( UntypedTupleExpr * tupleExpr );
     84        virtual Expression * mutate( TupleExpr * tupleExpr );
     85        virtual Expression * mutate( TupleIndexExpr * tupleExpr );
     86        virtual Expression * mutate( TupleAssignExpr * assignExpr );
     87        virtual Expression * mutate( StmtExpr  * stmtExpr );
     88        virtual Expression * mutate( UniqueExpr  * uniqueExpr );
     89        virtual Expression * mutate( UntypedInitExpr  * initExpr );
     90        virtual Expression * mutate( InitExpr  * initExpr );
     91        virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
    9192
    9293        virtual Type * mutate( VoidType * basicType );
  • src/SynTree/Statement.cc

    r62cd621 r7c782af  
    468468void WithStmt::print( std::ostream & os, Indenter indent ) const {
    469469        os << "With statement" << endl;
     470        os << indent << "... with expressions: " << endl;
     471        printAll( exprs, os, indent+1 );
    470472        os << indent << "... with statement:" << endl << indent+1;
    471473        stmt->print( os, indent+1 );
  • src/SynTree/SynTree.h

    r62cd621 r7c782af  
    9797class UntypedInitExpr;
    9898class InitExpr;
     99class DeletedExpr;
    99100
    100101class Type;
  • src/SynTree/Visitor.h

    r62cd621 r7c782af  
    9191        virtual void visit( UntypedInitExpr *  initExpr );
    9292        virtual void visit( InitExpr *  initExpr );
     93        virtual void visit( DeletedExpr * delExpr ) = 0;
    9394
    9495        virtual void visit( VoidType * basicType );
  • src/Tuples/Explode.h

    r62cd621 r7c782af  
    4343        /// Append alternative to an OutputIterator of Alternatives
    4444        template<typename OutputIterator>
    45         void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env, 
     45        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
    4646                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    4747                *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
     
    4949
    5050        /// Append alternative to an ExplodedActual
    51         static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 
     51        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    5252                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    5353                ea.exprs.emplace_back( expr );
     
    5757        /// helper function used by explode
    5858        template< typename Output >
    59         void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, 
     59        void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt,
    6060                        const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) {
    6161                if ( isTupleAssign ) {
     
    6363                        if ( CastExpr * castExpr = isReferenceCast( expr ) ) {
    6464                                ResolvExpr::AltList alts;
    65                                 explodeUnique( 
     65                                explodeUnique(
    6666                                        castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
    6767                                for ( ResolvExpr::Alternative & alt : alts ) {
    6868                                        // distribute reference cast over all components
    69                                         append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 
     69                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    7070                                                alt.env, alt.cost, alt.cvtCost );
    7171                                }
     
    108108        /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
    109109        template< typename Output >
    110         void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, 
     110        void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer,
    111111                        Output&& out, bool isTupleAssign = false ) {
    112112                explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
     
    115115        // explode list of alternatives
    116116        template< typename AltIterator, typename Output >
    117         void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, 
     117        void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer,
    118118                        Output&& out, bool isTupleAssign = false ) {
    119119                for ( ; altBegin != altEnd; ++altBegin ) {
     
    123123
    124124        template< typename Output >
    125         void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out, 
     125        void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out,
    126126                        bool isTupleAssign = false ) {
    127127                explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
  • src/libcfa/assert.c

    r62cd621 r7c782af  
    2222        extern const char * __progname;                                         // global name of running executable (argv[0])
    2323
    24         #define CFA_ASSERT_FMT "Cforall Assertion error from program \"%s\" in \"%s\" at line %d in file \"%s\""
     24        #define CFA_ASSERT_FMT "Cforall Assertion error \"%s\" from program \"%s\" in \"%s\" at line %d in file \"%s\""
    2525
    2626        // called by macro assert in assert.h
    2727        void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function ) {
    28                 __cfaabi_dbg_bits_print_safe( CFA_ASSERT_FMT ".\n", __progname, function, line, file );
     28                __cfaabi_dbg_bits_print_safe( CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
    2929                abort();
    3030        }
     
    3333        void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {
    3434                __cfaabi_dbg_bits_acquire();
    35                 __cfaabi_dbg_bits_print_nolock( CFA_ASSERT_FMT ": ", __progname, function, line, file );
     35                __cfaabi_dbg_bits_print_nolock( CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
    3636
    3737                va_list args;
  • src/tests/.expect/attributes.x64.txt

    r62cd621 r7c782af  
    6363static inline void ___destructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1);
    6464static inline struct Fdl ___operator_assign__F4sFdl_R4sFdl4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1, struct Fdl ___src__4sFdl_1);
    65 static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1);
    66 static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1);
    67 static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1);
    68 static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1);
    69 static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1);
    70 static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1);
    71 static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1);
    72 static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1);
    73 static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object1);
    74 static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object2, signed int *__f9__Pi_1);
     65static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1);
     66static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1);
     67static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1);
     68static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1);
     69static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1);
     70static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1);
     71static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1);
     72static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1);
     73static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1, __attribute__ ((unused)) signed int __anonymous_object1);
     74static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1, __attribute__ ((unused)) signed int __anonymous_object2, __attribute__ ((unused,unused)) signed int *__f9__Pi_1);
    7575static inline void ___constructor__F_R4sFdl_autogen___1(struct Fdl *___dst__R4sFdl_1){
    7676    ((void)((*___dst__R4sFdl_1).__f1__i_1) /* ?{} */);
     
    124124    return ___ret__4sFdl_1;
    125125}
    126 static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1){
     126static inline void ___constructor__F_R4sFdli_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1){
    127127    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    128128    ((void)((*___dst__R4sFdl_1).__f2__i_1) /* ?{} */);
     
    136136    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    137137}
    138 static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1){
     138static inline void ___constructor__F_R4sFdlii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1){
    139139    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    140140    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    148148    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    149149}
    150 static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1){
     150static inline void ___constructor__F_R4sFdliii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1){
    151151    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    152152    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    160160    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    161161}
    162 static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1){
     162static inline void ___constructor__F_R4sFdliiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1){
    163163    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    164164    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    172172    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    173173}
    174 static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1){
    175     ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    176     ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
    177     ((void)((*___dst__R4sFdl_1).__f3__i_1=__f3__i_1) /* ?{} */);
    178     ((void)((*___dst__R4sFdl_1).__f4__i_1=__f4__i_1) /* ?{} */);
    179     ((void)((*___dst__R4sFdl_1).__f5__i_1=__f5__i_1) /* ?{} */);
    180     ((void)((*___dst__R4sFdl_1).__f6__i_1) /* ?{} */);
    181     ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
    182     ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
    183     ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
    184     ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    185 }
    186 static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1){
     174static inline void ___constructor__F_R4sFdliiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1){
     175    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
     176    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     177    ((void)((*___dst__R4sFdl_1).__f3__i_1=__f3__i_1) /* ?{} */);
     178    ((void)((*___dst__R4sFdl_1).__f4__i_1=__f4__i_1) /* ?{} */);
     179    ((void)((*___dst__R4sFdl_1).__f5__i_1=__f5__i_1) /* ?{} */);
     180    ((void)((*___dst__R4sFdl_1).__f6__i_1) /* ?{} */);
     181    ((void)((*___dst__R4sFdl_1).__f7__i_1) /* ?{} */);
     182    ((void)((*___dst__R4sFdl_1).__f8__i_1) /* ?{} */);
     183    ((void)((*___dst__R4sFdl_1).__anonymous_object0) /* ?{} */);
     184    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
     185}
     186static inline void ___constructor__F_R4sFdliiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1){
    187187    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    188188    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    196196    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    197197}
    198 static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1){
     198static inline void ___constructor__F_R4sFdliiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1){
    199199    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    200200    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    208208    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    209209}
    210 static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1){
     210static inline void ___constructor__F_R4sFdliiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1){
    211211    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    212212    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    220220    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    221221}
    222 static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object3){
     222static inline void ___constructor__F_R4sFdliiiiiiiii_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1, __attribute__ ((unused)) signed int __anonymous_object3){
    223223    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    224224    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    232232    ((void)((*___dst__R4sFdl_1).__f9__Pi_1) /* ?{} */);
    233233}
    234 static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, signed int __f1__i_1, signed int __f2__i_1, signed int __f3__i_1, signed int __f4__i_1, signed int __f5__i_1, signed int __f6__i_1, signed int __f7__i_1, signed int __f8__i_1, signed int __anonymous_object4, signed int *__f9__Pi_1){
     234static inline void ___constructor__F_R4sFdliiiiiiiiiPi_autogen___1(struct Fdl *___dst__R4sFdl_1, __attribute__ ((unused)) signed int __f1__i_1, __attribute__ ((unused)) signed int __f2__i_1, __attribute__ ((unused,unused)) signed int __f3__i_1, __attribute__ ((unused)) signed int __f4__i_1, __attribute__ ((unused,unused)) signed int __f5__i_1, signed int __f6__i_1, __attribute__ ((unused,unused)) signed int __f7__i_1, __attribute__ ((unused)) signed int __f8__i_1, __attribute__ ((unused)) signed int __anonymous_object4, __attribute__ ((unused,unused)) signed int *__f9__Pi_1){
    235235    ((void)((*___dst__R4sFdl_1).__f1__i_1=__f1__i_1) /* ?{} */);
    236236    ((void)((*___dst__R4sFdl_1).__f2__i_1=__f2__i_1) /* ?{} */);
     
    371371static inline void ___destructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1);
    372372static inline struct Vad ___operator_assign__F4sVad_R4sVad4sVad_autogen___1(struct Vad *___dst__R4sVad_1, struct Vad ___src__4sVad_1);
    373 static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object36);
    374 static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object37, signed int *__anonymous_object38);
    375 static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object39, signed int *__anonymous_object40, signed int __anonymous_object41[((unsigned long int )10)]);
    376 static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object42, signed int *__anonymous_object43, signed int __anonymous_object44[((unsigned long int )10)], signed int (*__anonymous_object45)());
     373static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object36);
     374static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object37, __attribute__ ((unused,unused)) signed int *__anonymous_object38);
     375static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object39, __attribute__ ((unused,unused)) signed int *__anonymous_object40, __attribute__ ((unused,unused)) signed int __anonymous_object41[((unsigned long int )10)]);
     376static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object42, __attribute__ ((unused,unused)) signed int *__anonymous_object43, __attribute__ ((unused,unused)) signed int __anonymous_object44[((unsigned long int )10)], __attribute__ ((unused,unused)) signed int (*__anonymous_object45)());
    377377static inline void ___constructor__F_R4sVad_autogen___1(struct Vad *___dst__R4sVad_1){
    378378    ((void)((*___dst__R4sVad_1).__anonymous_object32) /* ?{} */);
     
    430430    return ___ret__4sVad_1;
    431431}
    432 static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object46){
     432static inline void ___constructor__F_R4sVadi_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object46){
    433433    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object46) /* ?{} */);
    434434    ((void)((*___dst__R4sVad_1).__anonymous_object33) /* ?{} */);
     
    443443    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
    444444}
    445 static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object47, signed int *__anonymous_object48){
     445static inline void ___constructor__F_R4sVadiPi_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object47, __attribute__ ((unused,unused)) signed int *__anonymous_object48){
    446446    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object47) /* ?{} */);
    447447    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object48) /* ?{} */);
     
    456456    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
    457457}
    458 static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object49, signed int *__anonymous_object50, signed int __anonymous_object51[((unsigned long int )10)]){
     458static inline void ___constructor__F_R4sVadiPiA0i_autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object49, __attribute__ ((unused,unused)) signed int *__anonymous_object50, __attribute__ ((unused,unused)) signed int __anonymous_object51[((unsigned long int )10)]){
    459459    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object49) /* ?{} */);
    460460    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object50) /* ?{} */);
     
    469469    ((void)((*___dst__R4sVad_1).__anonymous_object35) /* ?{} */);
    470470}
    471 static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, signed int __anonymous_object52, signed int *__anonymous_object53, signed int __anonymous_object54[((unsigned long int )10)], signed int (*__anonymous_object55)()){
     471static inline void ___constructor__F_R4sVadiPiA0iPFi___autogen___1(struct Vad *___dst__R4sVad_1, __attribute__ ((unused)) signed int __anonymous_object52, __attribute__ ((unused,unused)) signed int *__anonymous_object53, __attribute__ ((unused,unused)) signed int __anonymous_object54[((unsigned long int )10)], __attribute__ ((unused,unused)) signed int (*__anonymous_object55)()){
    472472    ((void)((*___dst__R4sVad_1).__anonymous_object32=__anonymous_object52) /* ?{} */);
    473473    ((void)((*___dst__R4sVad_1).__anonymous_object33=__anonymous_object53) /* ?{} */);
  • src/tests/tuple/tupleVariadic.c

    r62cd621 r7c782af  
    9595}
    9696
     97forall(ttype T | { void foo(T); }) void bar(T x) {}
     98void foo(int) {}
     99
    97100int main() {
    98101        array * x0 = new();
     
    117120        func(3, 2.0, 111, 4.145);
    118121        printf("finished func\n");
     122
     123        {
     124                // T = [const int] -- this ensures that void(*)(int) satisfies void(*)(const int)
     125                const int x;
     126                bar(x);
     127        }
    119128}
    120129
Note: See TracChangeset for help on using the changeset viewer.