Changeset 2724b4e


Ignore:
Timestamp:
Sep 16, 2020, 1:48:17 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
673eb7a
Parents:
c402739 (diff), da9a27c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
9 added
24 edited
1 moved

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    rc402739 r2724b4e  
    6262        iterator.hfa \
    6363        limits.hfa \
     64        memory.hfa \
    6465        parseargs.hfa \
    6566        rational.hfa \
  • libcfa/src/concurrency/monitor.cfa

    rc402739 r2724b4e  
    8989        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    9090
    91         if( !this->owner ) {
     91        if( unlikely(0 != (0x1 & (uintptr_t)this->owner)) ) {
     92                abort( "Attempt by thread \"%.256s\" (%p) to access joined monitor %p.", thrd->self_cor.name, thrd, this );
     93        }
     94        else if( !this->owner ) {
    9295                // No one has the monitor, just take it
    9396                __set_owner( this, thrd );
     
    137140}
    138141
    139 static void __dtor_enter( $monitor * this, fptr_t func ) {
     142static void __dtor_enter( $monitor * this, fptr_t func, bool join ) {
    140143        // Lock the monitor spinlock
    141144        lock( this->lock __cfaabi_dbg_ctx2 );
     
    157160                return;
    158161        }
    159         else if( this->owner == thrd) {
     162        else if( this->owner == thrd && !join) {
    160163                // We already have the monitor... but where about to destroy it so the nesting will fail
    161164                // Abort!
    162165                abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
     166        }
     167        // SKULLDUGGERY: join will act as a dtor so it would normally trigger to above check
     168        // to avoid that it sets the owner to the special value thrd | 1p before exiting
     169        else if( this->owner == ($thread*)(1 | (uintptr_t)thrd) ) {
     170                // restore the owner and just return
     171                __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     172
     173                // No one has the monitor, just take it
     174                this->owner = thrd;
     175
     176                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     177
     178                unlock( this->lock );
     179                return;
    163180        }
    164181
     
    251268
    252269// Leave single monitor for the last time
    253 void __dtor_leave( $monitor * this ) {
     270void __dtor_leave( $monitor * this, bool join ) {
    254271        __cfaabi_dbg_debug_do(
    255272                if( TL_GET( this_thread ) != this->owner ) {
    256273                        abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
    257274                }
    258                 if( this->recursion != 1 ) {
     275                if( this->recursion != 1  && !join ) {
    259276                        abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    260277                }
    261278        )
     279
     280        this->owner = ($thread*)(1 | (uintptr_t)this->owner);
    262281}
    263282
     
    307326}
    308327
     328// Join a thread
     329forall( dtype T | is_thread(T) )
     330T & join( T & this ) {
     331        $monitor *    m = get_monitor(this);
     332        void (*dtor)(T& mutex this) = ^?{};
     333        monitor_dtor_guard_t __guard = { &m, (fptr_t)dtor, true };
     334        {
     335                return this;
     336        }
     337}
     338
    309339// Enter multiple monitor
    310340// relies on the monitor array being sorted
     
    366396// Ctor for monitor guard
    367397// Sorts monitors before entering
    368 void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
     398void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func, bool join ) {
    369399        // optimization
    370400        $thread * thrd = TL_GET( this_thread );
     
    376406        this.prev = thrd->monitors;
    377407
     408        // Save whether we are in a join or not
     409        this.join = join;
     410
    378411        // Update thread context (needed for conditions)
    379412        (thrd->monitors){m, 1, func};
    380413
    381         __dtor_enter( this.m, func );
     414        __dtor_enter( this.m, func, join );
    382415}
    383416
     
    385418void ^?{}( monitor_dtor_guard_t & this ) {
    386419        // Leave the monitors in order
    387         __dtor_leave( this.m );
     420        __dtor_leave( this.m, this.join );
    388421
    389422        // Restore thread context
  • libcfa/src/concurrency/monitor.hfa

    rc402739 r2724b4e  
    5353        $monitor *    m;
    5454        __monitor_group_t prev;
     55        bool join;
    5556};
    5657
    57 void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );
     58void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)(), bool join );
    5859void ^?{}( monitor_dtor_guard_t & this );
    5960
  • libcfa/src/concurrency/thread.hfa

    rc402739 r2724b4e  
    106106void sleep( Duration duration );
    107107
     108//----------
     109// join
     110forall( dtype T | is_thread(T) )
     111T & join( T & this );
     112
    108113// Local Variables: //
    109114// mode: c //
  • src/AST/Convert.cpp

    rc402739 r2724b4e  
    11621162        }
    11631163
    1164         const ast::Type * postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
     1164        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
    11651165                ty->forall = get<TypeDecl>().acceptL( old->forall );
    11661166                ty->parameters = get<Expression>().acceptL( old->params );
     
    25212521        }
    25222522
    2523         void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
     2523        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
    25242524                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
    25252525                ty->params = GET_ACCEPT_V( parameters, Expr );
  • src/AST/Fwd.hpp

    rc402739 r2724b4e  
    107107class QualifiedType;
    108108class FunctionType;
    109 class ReferenceToType;
     109class BaseInstType;
    110110template<typename decl_t> class SueInstType;
    111111using StructInstType = SueInstType<StructDecl>;
  • src/AST/GenericSubstitution.cpp

    rc402739 r2724b4e  
    4242        private:
    4343                // make substitution for generic type
    44                 void makeSub( const ReferenceToType * ty ) {
     44                void makeSub( const BaseInstType * ty ) {
    4545                        visit_children = false;
    4646                        const AggregateDecl * aggr = ty->aggr();
  • src/AST/Node.cpp

    rc402739 r2724b4e  
    266266template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::weak >;
    267267template class ast::ptr_base< ast::FunctionType, ast::Node::ref_type::strong >;
    268 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::weak >;
    269 template class ast::ptr_base< ast::ReferenceToType, ast::Node::ref_type::strong >;
     268template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::weak >;
     269template class ast::ptr_base< ast::BaseInstType, ast::Node::ref_type::strong >;
    270270template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::weak >;
    271271template class ast::ptr_base< ast::StructInstType, ast::Node::ref_type::strong >;
  • src/AST/Pass.hpp

    rc402739 r2724b4e  
    118118
    119119        // Versions of the above for older compilers.
     120        template< typename... Args >
    120121        static void run( std::list< ptr<Decl> > & decls ) {
    121122                Pass<core_t> visitor;
     
    123124        }
    124125
    125         static auto read( Node const * node ) {
     126        template< typename node_type, typename... Args >
     127        static auto read( node_type const * node ) {
    126128                Pass<core_t> visitor;
    127                 Node const * temp = node->accept( visitor );
     129                node_type const * temp = node->accept( visitor );
    128130                assert( temp == node );
    129131                return visitor.get_result();
  • src/AST/Print.cpp

    rc402739 r2724b4e  
    270270        }
    271271
    272         void preprint( const ast::ReferenceToType * node ) {
     272        void preprint( const ast::BaseInstType * node ) {
    273273                print( node->forall );
    274274                print( node->attributes );
  • src/AST/SymbolTable.cpp

    rc402739 r2724b4e  
    313313                if ( ! expr->result ) continue;
    314314                const Type * resTy = expr->result->stripReferences();
    315                 auto aggrType = dynamic_cast< const ReferenceToType * >( resTy );
     315                auto aggrType = dynamic_cast< const BaseInstType * >( resTy );
    316316                assertf( aggrType, "WithStmt expr has non-aggregate type: %s",
    317317                        toString( expr->result ).c_str() );
     
    654654                        if ( dwt->name == "" ) {
    655655                                const Type * t = dwt->get_type()->stripReferences();
    656                                 if ( auto rty = dynamic_cast<const ReferenceToType *>( t ) ) {
     656                                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    657657                                        if ( ! dynamic_cast<const StructInstType *>(rty)
    658658                                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
  • src/AST/Type.cpp

    rc402739 r2724b4e  
    124124}
    125125
    126 // --- ReferenceToType
    127 
    128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     126// --- BaseInstType
     127
     128void BaseInstType::initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub ) {
    129129        ParameterizedType::initWithSub( o, sub ); // initialize substitution
    130130        params = sub.core( o.params );            // apply to parameters
    131131}
    132132
    133 ReferenceToType::ReferenceToType( const ReferenceToType & o )
     133BaseInstType::BaseInstType( const BaseInstType & o )
    134134: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
    135135  hoistType( o.hoistType ) {
     
    138138}
    139139
    140 std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
     140std::vector<readonly<Decl>> BaseInstType::lookup( const std::string& name ) const {
    141141        assertf( aggr(), "Must have aggregate to perform lookup" );
    142142
     
    153153SueInstType<decl_t>::SueInstType(
    154154        const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    155 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     155: BaseInstType( b->name, q, move(as) ), base( b ) {}
    156156
    157157template<typename decl_t>
     
    168168TraitInstType::TraitInstType(
    169169        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     170: BaseInstType( b->name, q, move(as) ), base( b ) {}
    171171
    172172// --- TypeInstType
    173173
    174174TypeInstType::TypeInstType( const TypeInstType & o )
    175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
     175: BaseInstType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
    176176        Pass< ForallSubstitutor > sub;
    177177        initWithSub( o, sub );      // initialize substitution
  • src/AST/Type.hpp

    rc402739 r2724b4e  
    329329
    330330/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    331 class ReferenceToType : public ParameterizedType {
     331class BaseInstType : public ParameterizedType {
    332332protected:
    333333        /// Initializes forall and parameters based on substitutor
    334         void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
     334        void initWithSub( const BaseInstType & o, Pass< ForallSubstitutor > & sub );
    335335public:
    336336        std::vector<ptr<Expr>> params;
     
    338338        bool hoistType = false;
    339339
    340         ReferenceToType(
     340        BaseInstType(
    341341                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    342342        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    343343
    344         ReferenceToType( const ReferenceToType & o );
     344        BaseInstType( const BaseInstType & o );
    345345
    346346        /// Gets aggregate declaration this type refers to
     
    350350
    351351private:
    352         virtual ReferenceToType * clone() const override = 0;
     352        virtual BaseInstType * clone() const override = 0;
    353353        MUTATE_FRIEND
    354354};
     
    356356// Common implementation for the SUE instance types. Not to be used directly.
    357357template<typename decl_t>
    358 class SueInstType final : public ReferenceToType {
     358class SueInstType final : public BaseInstType {
    359359public:
    360360        using base_type = decl_t;
     
    363363        SueInstType(
    364364                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    365         : ReferenceToType( n, q, std::move(as) ), base() {}
     365        : BaseInstType( n, q, std::move(as) ), base() {}
    366366
    367367        SueInstType(
     
    388388
    389389/// An instance of a trait type.
    390 class TraitInstType final : public ReferenceToType {
     390class TraitInstType final : public BaseInstType {
    391391public:
    392392        readonly<TraitDecl> base;
     
    394394        TraitInstType(
    395395                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    396         : ReferenceToType( n, q, std::move(as) ), base() {}
     396        : BaseInstType( n, q, std::move(as) ), base() {}
    397397
    398398        TraitInstType(
     
    411411
    412412/// instance of named type alias (typedef or variable)
    413 class TypeInstType final : public ReferenceToType {
     413class TypeInstType final : public BaseInstType {
    414414public:
    415415        readonly<TypeDecl> base;
     
    419419                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    420420                std::vector<ptr<Attribute>> && as = {} )
    421         : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     421        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    422422        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
    423423                std::vector<ptr<Attribute>> && as = {} )
    424         : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     424        : BaseInstType( n, q, std::move(as) ), base(), kind( k ) {}
    425425
    426426        TypeInstType( const TypeInstType & o );
  • src/AST/TypeSubstitution.cpp

    rc402739 r2724b4e  
    176176}
    177177
    178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
     178void TypeSubstitution::Substituter::handleAggregateType( const BaseInstType * type ) {
    179179        GuardValue( boundVars );
    180180        // bind type variables from forall-qualifiers
  • src/AST/TypeSubstitution.hpp

    rc402739 r2724b4e  
    169169                void previsit( const ParameterizedType * type );
    170170                /// Records type variable bindings from forall-statements and instantiations of generic types
    171                 void handleAggregateType( const ReferenceToType * type );
     171                void handleAggregateType( const BaseInstType * type );
    172172
    173173                void previsit( const StructInstType * aggregateUseType );
  • src/Concurrency/Keywords.cc

    rc402739 r2724b4e  
    931931                                        {
    932932                                                new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ),
    933                                                 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) )
     933                                                new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ),
     934                                                new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) )
    934935                                        },
    935936                                        noDesignators,
  • src/ResolvExpr/CandidateFinder.cpp

    rc402739 r2724b4e  
    816816                /// Adds aggregate member interpretations
    817817                void addAggMembers(
    818                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     818                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    819819                        const Candidate & cand, const Cost & addedCost, const std::string & name
    820820                ) {
     
    12631263
    12641264                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    1265                         const ast::ReferenceToType * aggInst;
     1265                        const ast::BaseInstType * aggInst;
    12661266                        if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
    12671267                        else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
  • src/ResolvExpr/CurrentObject.cc

    rc402739 r2724b4e  
    923923
    924924        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    925                 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
     925                if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
    926926                        if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    927927                                return new StructIterator{ loc, sit };
     
    932932                                        dynamic_cast< const EnumInstType * >( type )
    933933                                                || dynamic_cast< const TypeInstType * >( type ),
    934                                         "Encountered unhandled ReferenceToType in createMemberIterator: %s",
     934                                        "Encountered unhandled BaseInstType in createMemberIterator: %s",
    935935                                                toString( type ).c_str() );
    936936                                return new SimpleIterator{ loc, type };
     
    965965                                        DesignatorChain & d = *dit;
    966966                                        PRINT( std::cerr << "____actual: " << t << std::endl; )
    967                                         if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
     967                                        if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
    968968                                                // concatenate identical field names
    969969                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
  • src/ResolvExpr/Resolver.cc

    rc402739 r2724b4e  
    12591259                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    12601260                const ast::CatchStmt *       previsit( const ast::CatchStmt * );
     1261                const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
    12611262                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    12621263
     
    14911492
    14921493        const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
    1493                 // TODO: This will need a fix for the decl/cond scoping problem.
     1494                // Until we are very sure this invarent (ifs that move between passes have thenPart)
     1495                // holds, check it. This allows a check for when to decode the mangling.
     1496                if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
     1497                        assert( ifStmt->thenPart );
     1498                }
     1499                // Encode the catchStmt so the condition can see the declaration.
    14941500                if ( catchStmt->cond ) {
    1495                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1496                         catchStmt = ast::mutate_field(
    1497                                 catchStmt, &ast::CatchStmt::cond,
    1498                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
     1501                        ast::CatchStmt * stmt = mutate( catchStmt );
     1502                        stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );
     1503                        stmt->cond = nullptr;
     1504                        return stmt;
     1505                }
     1506                return catchStmt;
     1507        }
     1508
     1509        const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) {
     1510                // Decode the catchStmt so everything is stored properly.
     1511                const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
     1512                if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
     1513                        assert( ifStmt->cond );
     1514                        assert( ifStmt->elsePart );
     1515                        ast::CatchStmt * stmt = ast::mutate( catchStmt );
     1516                        stmt->cond = ifStmt->cond;
     1517                        stmt->body = ifStmt->elsePart;
     1518                        // ifStmt should be implicately deleted here.
     1519                        return stmt;
    14991520                }
    15001521                return catchStmt;
  • src/SymTab/Mangler.cc

    rc402739 r2724b4e  
    437437                  private:
    438438                        void mangleDecl( const ast::DeclWithType *declaration );
    439                         void mangleRef( const ast::ReferenceToType *refType, std::string prefix );
     439                        void mangleRef( const ast::BaseInstType *refType, std::string prefix );
    440440
    441441                        void printQualifiers( const ast::Type *type );
     
    560560                }
    561561
    562                 void Mangler_new::mangleRef( const ast::ReferenceToType * refType, std::string prefix ) {
     562                void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) {
    563563                        printQualifiers( refType );
    564564
  • src/SymTab/Validate.cc

    rc402739 r2724b4e  
    960960        }
    961961
     962        static bool isNonParameterAttribute( Attribute * attr ) {
     963                static const std::vector<std::string> bad_names = {
     964                        "aligned", "__aligned__",
     965                };
     966                for ( auto name : bad_names ) {
     967                        if ( name == attr->name ) {
     968                                return true;
     969                        }
     970                }
     971                return false;
     972        }
     973
    962974        Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
    963975                // instances of typedef types will come here. If it is an instance
     
    968980                        ret->location = typeInst->location;
    969981                        ret->get_qualifiers() |= typeInst->get_qualifiers();
    970                         // attributes are not carried over from typedef to function parameters/return values
    971                         if ( ! inFunctionType ) {
    972                                 ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
    973                         } else {
    974                                 deleteAll( ret->attributes );
    975                                 ret->attributes.clear();
    976                         }
     982                        // GCC ignores certain attributes if they arrive by typedef, this mimics that.
     983                        if ( inFunctionType ) {
     984                                ret->attributes.remove_if( isNonParameterAttribute );
     985                        }
     986                        ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
    977987                        // place instance parameters on the typedef'd type
    978988                        if ( ! typeInst->parameters.empty() ) {
     
    15081518                }
    15091519
    1510                 void checkGenericParameters( const ast::ReferenceToType * inst ) {
     1520                void checkGenericParameters( const ast::BaseInstType * inst ) {
    15111521                        for ( const ast::Expr * param : inst->params ) {
    15121522                                if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
  • tests/Makefile.am

    rc402739 r2724b4e  
    3838# since automake doesn't have support for CFA we have to
    3939AM_CFLAGS = $(if $(test), 2> $(test), ) \
     40        -fdebug-prefix-map=$(abspath ${abs_srcdir})= \
     41        -fdebug-prefix-map=/tmp= \
    4042        -g \
    4143        -Wall \
     
    110112% : %.cfa $(CFACCBIN)
    111113        $(CFACOMPILETEST) -c -o $(abspath ${@}).o
    112         $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})
     114        $(CFACCLOCAL) $(if $(test), 2> $(test), ) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) ${@}.o -o $(abspath ${@})
    113115
    114116# implicit rule for c++ test
     
    137139# CUSTOM TARGET
    138140#------------------------------------------------------------------------------
     141# tests that just validate syntax
     142expression : expression.cfa $(CFACCBIN)
     143        $(CFACOMPILETEST) -c -fsyntax-only 2> $(abspath ${@})
     144
    139145# expected failures
    140146# use custom target since they require a custom define and custom dependencies
  • tests/pybin/tools.py

    rc402739 r2724b4e  
    120120                return None
    121121
    122         file = open(file, mode)
     122        file = open(file, mode, encoding="latin-1") # use latin-1 so all chars mean something.
    123123        exitstack.push(file)
    124124        return file
  • tests/test.py

    rc402739 r2724b4e  
    207207                else:
    208208                        if os.stat(out_file).st_size < 1048576:
    209                                 with open (out_file, "r") as myfile:
     209                                with open (out_file, "r", encoding='latin-1') as myfile:  # use latin-1 so all chars mean something.
    210210                                        error = myfile.read()
    211211                        else:
Note: See TracChangeset for help on using the changeset viewer.