Changes in / [8ad6533:ca37445]


Ignore:
Location:
src
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    r8ad6533 rca37445  
    203203
    204204        void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
    205                 genAttributes( aggDecl->get_attributes() );
    206 
    207205                if( ! aggDecl->get_parameters().empty() && ! genC ) {
    208206                        // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
     
    213211                }
    214212
    215                 output << kind << aggDecl->get_name();
     213                output << kind;
     214                genAttributes( aggDecl->get_attributes() );
     215                output << aggDecl->get_name();
    216216
    217217                if ( aggDecl->has_body() ) {
     
    298298                        output << " }";
    299299                }
     300        }
     301
     302        void CodeGenerator::postvisit( StaticAssertDecl * assertDecl ) {
     303                output << "_Static_assert(";
     304                assertDecl->condition->accept( *visitor );
     305                output << ", ";
     306                assertDecl->message->accept( *visitor );
     307                output << ")";
    300308        }
    301309
  • src/CodeGen/CodeGenerator.h

    r8ad6533 rca37445  
    4242                void postvisit( FunctionDecl * );
    4343                void postvisit( ObjectDecl * );
    44                 void postvisit( UnionDecl *aggregateDecl );
    45                 void postvisit( EnumDecl *aggregateDecl );
    46                 void postvisit( TraitDecl *aggregateDecl );
    47                 void postvisit( TypedefDecl *typeDecl );
    48                 void postvisit( TypeDecl *typeDecl );
     44                void postvisit( UnionDecl * aggregateDecl );
     45                void postvisit( EnumDecl * aggregateDecl );
     46                void postvisit( TraitDecl * aggregateDecl );
     47                void postvisit( TypedefDecl * typeDecl );
     48                void postvisit( TypeDecl * typeDecl );
     49                void postvisit( StaticAssertDecl * assertDecl );
    4950
    5051                //*** Initializer
  • src/CodeGen/OperatorTable.cc

    r8ad6533 rca37445  
    7979        } // namespace
    8080
    81         bool operatorLookup( std::string funcName, OperatorInfo &info ) {
     81        bool operatorLookup( const std::string & funcName, OperatorInfo & info ) {
    8282                static bool init = false;
    8383                if ( ! init ) {
     
    100100                        return true;
    101101                } // if
     102        }
     103
     104        bool isOperator( const std::string & funcName ) {
     105                OperatorInfo info;
     106                return operatorLookup( funcName, info );
    102107        }
    103108
  • src/CodeGen/OperatorTable.h

    r8ad6533 rca37445  
    4141        };
    4242
    43         bool operatorLookup( std::string funcName, OperatorInfo &info );
     43        bool isOperator( const std::string & funcName );
     44        bool operatorLookup( const std::string & funcName, OperatorInfo & info );
    4445
    4546        bool isConstructor( const std::string & );
  • src/Common/Debug.h

    r8ad6533 rca37445  
    2828namespace Debug {
    2929        /// debug codegen a translation unit
    30         static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
     30        static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
    3131        #ifdef DEBUG
    3232                std::list< Declaration * > decls;
     
    4141        } // dump
    4242
    43         static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
     43        static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label, __attribute__((unused)) LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler ) {
    4444        #ifdef DEBUG
    4545                std::list< Declaration * > decls;
  • src/Common/ErrorObjects.h

    r8ad6533 rca37445  
    3535class SemanticErrorException : public std::exception {
    3636  public:
    37         SemanticErrorException() = default;
     37        SemanticErrorException() = default;
    3838        SemanticErrorException( CodeLocation location, std::string error );
    3939        ~SemanticErrorException() throw() {}
  • src/Common/PassVisitor.h

    r8ad6533 rca37445  
    6666        virtual void visit( TypedefDecl * typeDecl ) override final;
    6767        virtual void visit( AsmDecl * asmDecl ) override final;
     68        virtual void visit( StaticAssertDecl * assertDecl ) override final;
    6869
    6970        virtual void visit( CompoundStmt * compoundStmt ) override final;
     
    161162        virtual Declaration * mutate( TypedefDecl * typeDecl ) override final;
    162163        virtual AsmDecl * mutate( AsmDecl * asmDecl ) override final;
     164        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) override final;
    163165
    164166        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override final;
  • src/Common/PassVisitor.impl.h

    r8ad6533 rca37445  
    685685
    686686//--------------------------------------------------------------------------
     687// StaticAssertDecl
     688template< typename pass_type >
     689void PassVisitor< pass_type >::visit( StaticAssertDecl * node ) {
     690        VISIT_START( node );
     691
     692        maybeAccept_impl( node->condition, *this );
     693        maybeAccept_impl( node->message  , *this );
     694
     695        VISIT_END( node );
     696}
     697
     698template< typename pass_type >
     699StaticAssertDecl * PassVisitor< pass_type >::mutate( StaticAssertDecl * node ) {
     700        MUTATE_START( node );
     701
     702        maybeMutate_impl( node->condition, *this );
     703        maybeMutate_impl( node->message  , *this );
     704
     705        MUTATE_END( StaticAssertDecl, node );
     706}
     707
     708//--------------------------------------------------------------------------
    687709// CompoundStmt
    688710template< typename pass_type >
     
    14901512        indexerScopedAccept( node->result, *this );
    14911513        maybeAccept_impl   ( node->type  , *this );
    1492         maybeAccept_impl   ( node->member, *this );
    14931514
    14941515        VISIT_END( node );
     
    15021523        indexerScopedMutate( node->result, *this );
    15031524        maybeMutate_impl   ( node->type  , *this );
    1504         maybeMutate_impl   ( node->member, *this );
    15051525
    15061526        MUTATE_END( Expression, node );
  • src/GenPoly/Lvalue.cc

    r8ad6533 rca37445  
    4545                Expression * mkDeref( Expression * arg ) {
    4646                        if ( SymTab::dereferenceOperator ) {
     47                                // note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass
    4748                                VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
    4849                                deref->result = new PointerType( Type::Qualifiers(), deref->result );
     
    197198                                        PRINT(
    198199                                                std::cerr << "pair<0>: " << arg << std::endl;
     200                                                std::cerr << " -- " << arg->result << std::endl;
    199201                                                std::cerr << "pair<1>: " << formal << std::endl;
    200202                                        )
    201203                                        if ( dynamic_cast<ReferenceType*>( formal ) ) {
    202                                                 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
    203                                                         if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
    204                                                                 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
    205                                                                 PRINT(
    206                                                                         std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
    207                                                                 )
    208                                                                 arg = new AddressExpr( arg );
    209                                                         }
    210                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
    211                                                         // std::cerr << "===adding deref to arg" << std::endl;
    212                                                         // if the parameter is a reference, add a dereference to the reference-typed argument.
     204                                                PRINT(
     205                                                        std::cerr << "===formal is reference" << std::endl;
     206                                                )
     207                                                // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
     208                                                if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
     209                                                        // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
     210                                                        PRINT(
     211                                                                std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
     212                                                        )
     213                                                        arg = new AddressExpr( arg );
     214                                                } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
     215                                                        // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
     216                                                        PRINT(
     217                                                                std::cerr << "===is non-intrinsic arg in intrinsic call - adding deref to arg" << std::endl;
     218                                                        )
    213219                                                        Type * baseType = InitTweak::getPointerBase( arg->result );
    214220                                                        assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->result ).c_str() );
     
    217223                                                        arg->set_result( ptrType );
    218224                                                        arg = mkDeref( arg );
     225                                                        assertf( arg->result->referenceDepth() == 0, "Reference types should have been eliminated from intrinsic function calls, but weren't: %s", toCString( arg->result ) );
    219226                                                }
    220227                                        }
  • src/Parser/DeclarationNode.cc

    r8ad6533 rca37445  
    7171        attr.expr = nullptr;
    7272        attr.type = nullptr;
     73
     74        assert.condition = nullptr;
     75        assert.message = nullptr;
    7376}
    7477
     
    8891        // asmName, no delete, passed to next stage
    8992        delete initializer;
     93
     94        delete assert.condition;
     95        delete assert.message;
    9096}
    9197
     
    117123        newnode->attr.expr = maybeClone( attr.expr );
    118124        newnode->attr.type = maybeClone( attr.type );
     125
     126        newnode->assert.condition = maybeClone( assert.condition );
     127        newnode->assert.message = maybeClone( assert.message );
    119128        return newnode;
    120129} // DeclarationNode::clone
     
    434443        return newnode;
    435444}
     445
     446DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression * message ) {
     447        DeclarationNode * newnode = new DeclarationNode;
     448        newnode->assert.condition = condition;
     449        newnode->assert.message = message;
     450        return newnode;
     451}
     452
    436453
    437454void appendError( string & dst, const string & src ) {
     
    10521069        } // if
    10531070
     1071        if ( assert.condition ) {
     1072                return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) );
     1073        }
     1074
    10541075        // SUE's cannot have function specifiers, either
    10551076        //
  • src/Parser/ParseNode.h

    r8ad6533 rca37445  
    246246        static DeclarationNode * newAttribute( std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    247247        static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
     248        static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
    248249
    249250        DeclarationNode();
     
    313314        Attr_t attr;
    314315
     316        struct StaticAssert_t {
     317                ExpressionNode * condition;
     318                Expression * message;
     319        };
     320        StaticAssert_t assert;
     321
    315322        BuiltinType builtin;
    316323
  • src/Parser/parser.yy

    r8ad6533 rca37445  
    13141314static_assert:
    13151315        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1316                 { SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; }
     1316                { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
    13171317
    13181318// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
  • src/ResolvExpr/CommonType.cc

    r8ad6533 rca37445  
    2727#include "typeops.h"                     // for isFtype
    2828
    29 // #define DEBUG
     29#define DEBUG
     30#ifdef DEBUG
     31#define PRINT(x) x
     32#else
     33#define PRINT(x)
     34#endif
    3035
    3136namespace ResolvExpr {
     
    7075                // need unify to bind type variables
    7176                if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
    72                         // std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
     77                        PRINT(
     78                                std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
     79                        )
    7380                        if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {
    74                                 // std::cerr << "widen okay" << std::endl;
     81                                PRINT(
     82                                        std::cerr << "widen okay" << std::endl;
     83                                )
    7584                                common->get_qualifiers() |= t1->get_qualifiers();
    7685                                common->get_qualifiers() |= t2->get_qualifiers();
     
    7887                        }
    7988                }
    80                 // std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
     89                PRINT(
     90                        std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
     91                )
    8192                return nullptr;
    8293        }
     
    94105                        // special case where one type has a reference depth of 1 larger than the other
    95106                        if ( diff > 0 || diff < 0 ) {
    96                                 // std::cerr << "reference depth diff: " << diff << std::endl;
     107                                PRINT(
     108                                        std::cerr << "reference depth diff: " << diff << std::endl;
     109                                )
    97110                                Type * result = nullptr;
    98111                                ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
     
    109122                                if ( result && ref1 ) {
    110123                                        // formal is reference, so result should be reference
    111                                         // std::cerr << "formal is reference; result should be reference" << std::endl;
     124                                        PRINT(
     125                                                std::cerr << "formal is reference; result should be reference" << std::endl;
     126                                        )
    112127                                        result = new ReferenceType( ref1->get_qualifiers(), result );
    113128                                }
    114                                 // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
     129                                PRINT(
     130                                        std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
     131                                )
    115132                                return result;
    116133                        }
  • src/ResolvExpr/Resolver.cc

    r8ad6533 rca37445  
    5959                void previsit( TypeDecl *typeDecl );
    6060                void previsit( EnumDecl * enumDecl );
     61                void previsit( StaticAssertDecl * assertDecl );
    6162
    6263                void previsit( ArrayType * at );
     
    361362                GuardValue( inEnumDecl );
    362363                inEnumDecl = true;
     364        }
     365
     366        void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     367                findIntegralExpression( assertDecl->condition, indexer );
    363368        }
    364369
  • src/SymTab/Validate.cc

    r8ad6533 rca37445  
    8989                void previsit( StructDecl * aggregateDecl );
    9090                void previsit( UnionDecl * aggregateDecl );
     91                void previsit( StaticAssertDecl * assertDecl );
    9192
    9293          private:
     
    296297        }
    297298
    298         bool isStructOrUnion( Declaration *decl ) {
    299                 return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
     299        bool shouldHoist( Declaration *decl ) {
     300                return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
    300301        }
    301302
     
    310311                } // if
    311312                // Always remove the hoisted aggregate from the inner structure.
    312                 GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } );
     313                GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, shouldHoist, false ); } );
    313314        }
    314315
     
    328329                if ( inst->baseUnion ) {
    329330                        declsToAddBefore.push_front( inst->baseUnion );
     331                }
     332        }
     333
     334        void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
     335                if ( parentAggr ) {
     336                        declsToAddBefore.push_back( assertDecl );
    330337                }
    331338        }
     
    630637                        forallFixer( pointer->base->forall, object );
    631638                } // if
     639                // ensure that operator names only apply to functions or function pointers
     640                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     641                        SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
     642                }
    632643                object->fixUniqueId();
    633644        }
  • src/SynTree/Declaration.cc

    r8ad6533 rca37445  
    8181
    8282
     83StaticAssertDecl::StaticAssertDecl( Expression * condition, ConstantExpr * message ) : Declaration( "", Type::StorageClasses(), LinkageSpec::C ), condition( condition ), message( message )  {
     84}
     85
     86StaticAssertDecl::StaticAssertDecl( const StaticAssertDecl & other ) : Declaration( other ), condition( maybeClone( other.condition ) ), message( maybeClone( other.message ) )  {
     87}
     88
     89StaticAssertDecl::~StaticAssertDecl() {
     90        delete condition;
     91        delete message;
     92}
     93
     94void StaticAssertDecl::print( std::ostream &os, Indenter indent ) const {
     95        os << "Static Assert with condition: ";
     96        condition->print( os, indent+1 );
     97        os << std::endl << indent << "and message: ";
     98        message->print( os, indent+1 );
     99os << std::endl;
     100}
     101
     102void StaticAssertDecl::printShort( std::ostream &os, Indenter indent ) const {
     103        print( os, indent );
     104}
     105
    83106// Local Variables: //
    84107// tab-width: 4 //
  • src/SynTree/Declaration.h

    r8ad6533 rca37445  
    365365};
    366366
     367class StaticAssertDecl : public Declaration {
     368public:
     369        Expression * condition;
     370        ConstantExpr * message;   // string literal
     371
     372        StaticAssertDecl( Expression * condition, ConstantExpr * message );
     373        StaticAssertDecl( const StaticAssertDecl & other );
     374        virtual ~StaticAssertDecl();
     375
     376        virtual StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
     377        virtual void accept( Visitor &v ) override { v.visit( this ); }
     378        virtual StaticAssertDecl * acceptMutator( Mutator &m )  override { return m.mutate( this ); }
     379        virtual void print( std::ostream &os, Indenter indent = {} ) const override;
     380        virtual void printShort( std::ostream &os, Indenter indent = {} ) const override;
     381};
     382
    367383std::ostream & operator<<( std::ostream & os, const TypeDecl::Data & data );
    368384
  • src/SynTree/Mutator.h

    r8ad6533 rca37445  
    3434        virtual Declaration * mutate( TypedefDecl * typeDecl ) = 0;
    3535        virtual AsmDecl * mutate( AsmDecl * asmDecl ) = 0;
     36        virtual StaticAssertDecl * mutate( StaticAssertDecl * assertDecl ) = 0;
    3637
    3738        virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) = 0;
  • src/SynTree/SynTree.h

    r8ad6533 rca37445  
    3838class TypedefDecl;
    3939class AsmDecl;
     40class StaticAssertDecl;
    4041
    4142class Statement;
  • src/SynTree/Visitor.h

    r8ad6533 rca37445  
    3636        virtual void visit( TypedefDecl * typeDecl ) = 0;
    3737        virtual void visit( AsmDecl * asmDecl ) = 0;
     38        virtual void visit( StaticAssertDecl * assertDecl ) = 0;
    3839
    3940        virtual void visit( CompoundStmt * compoundStmt ) = 0;
  • src/tests/.expect/references.txt

    r8ad6533 rca37445  
    4413 1 12
    5514 14
     6x = 6 ; x2 = 789
     7x = 6 ; x2 = 999
     8x = 12345 ; x2 = 999
     9x = 22222 ; x2 = 999
    610Default constructing a Y
    711Copy constructing a Y
  • src/tests/operators.c

    r8ad6533 rca37445  
    2727        a(b);
    2828        a + b;
    29         struct accumulator ?+?; // why not, eh?
    30         a + b;
    3129}
    3230
  • src/tests/references.c

    r8ad6533 rca37445  
    4646
    4747int main() {
    48         int x = 123456, *p1 = &x, **p2 = &p1, ***p3 = &p2,
     48        int x = 123456, x2 = 789, *p1 = &x, **p2 = &p1, ***p3 = &p2,
    4949                &r1 = x,    &&r2 = r1,   &&&r3 = r2;
    5050        ***p3 = 3;                          // change x
    51         // ((int&)r3 = 3;                      // change x, ***r3
    5251        **p3 = &x;                          // change p1
    53         // ((int*&)&r3) = &x;                  // change r1, (&*)**r3
    5452        *p3 = &p1;                          // change p2
    55         // ((int**&)&&r3) = &p2;               // change r2, (&(&*)*)*r3
    56         // ((int***&)&&&r3) = p3;              // change r3 to p3, (&(&(&*)*)*)r3
    5753        int y = 0, z = 11, & ar[3] = { x, y, z };    // initialize array of references
    5854        // &ar[1] = &z;                        // change reference array element
     
    6258        // sizeof( &ar[1] ) == sizeof( int *); // is true, i.e., the size of a reference
    6359
     60        ((int*&)&r3) = &x;                  // change r1, (&*)**r3
     61        x = 3;
    6462        // test that basic reference properties are true - r1 should be an alias for x
    6563        printf("%d %d %d\n", x, r1, &x == &r1);
     
    7674        changeRef( r1 );
    7775        printf("%d %d\n", r1, x);
     76
     77        ((int&)r3) = 6;                       // change x, ***r3
     78        printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
     79        ((int*&)&r3) = &x2;                   // change r1 to refer to x2, (&*)**r3
     80        ((int&)r3) = 999;                     // modify x2
     81        printf("x = %d ; x2 = %d\n", x, x2);  // check that x2 was changed
     82        ((int**&)&&r3) = p2;                  // change r2, (&(&*)*)*r3
     83        ((int&)r3) = 12345;                   // modify x
     84        printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
     85        ((int***&)&&&r3) = p3;                // change r3 to p3, (&(&(&*)*)*)r3
     86        ((int&)r3) = 22222;                   // modify x
     87        printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
    7888
    7989        // test that reference members are not implicitly constructed/destructed/assigned
Note: See TracChangeset for help on using the changeset viewer.