Changes in / [bd5cf7c:e93f1d2]


Ignore:
Location:
src
Files:
2 added
2 deleted
35 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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/ControlStruct/ExceptTranslate.cc

    rbd5cf7c re93f1d2  
    3434#include "SynTree/Statement.h"        // for CompoundStmt, CatchStmt, ThrowStmt
    3535#include "SynTree/Type.h"             // for FunctionType, Type, noQualifiers
    36 #include "SynTree/VarExprReplacer.h"  // for VarExprReplacer, VarExprReplace...
     36#include "SynTree/DeclReplacer.h"     // for DeclReplacer
    3737#include "SynTree/Visitor.h"          // for acceptAll
    3838
     
    314314                        // Update variables in the body to point to this local copy.
    315315                        {
    316                                 VarExprReplacer::DeclMap mapping;
     316                                DeclReplacer::DeclMap mapping;
    317317                                mapping[ handler_decl ] = local_except;
    318                                 VarExprReplacer::replace( handler->body, mapping );
     318                                DeclReplacer::replace( handler->body, mapping );
    319319                        }
    320320
  • src/GenPoly/Lvalue.cc

    rbd5cf7c re93f1d2  
    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/Makefile.in

    rbd5cf7c re93f1d2  
    249249        SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
    250250        SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
    251         SynTree/driver_cfa_cpp-VarExprReplacer.$(OBJEXT) \
     251        SynTree/driver_cfa_cpp-DeclReplacer.$(OBJEXT) \
    252252        Tuples/driver_cfa_cpp-TupleAssignment.$(OBJEXT) \
    253253        Tuples/driver_cfa_cpp-TupleExpansion.$(OBJEXT) \
     
    526526        SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
    527527        SynTree/Initializer.cc SynTree/TypeSubstitution.cc \
    528         SynTree/Attribute.cc SynTree/VarExprReplacer.cc \
     528        SynTree/Attribute.cc SynTree/DeclReplacer.cc \
    529529        Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
    530530        Tuples/Explode.cc Virtual/ExpandCasts.cc
     
    912912SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
    913913        SynTree/$(DEPDIR)/$(am__dirstamp)
    914 SynTree/driver_cfa_cpp-VarExprReplacer.$(OBJEXT):  \
     914SynTree/driver_cfa_cpp-DeclReplacer.$(OBJEXT):  \
    915915        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
    916916Tuples/$(am__dirstamp):
     
    10391039@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CompoundStmt.Po@am__quote@
    10401040@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Constant.Po@am__quote@
     1041@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po@am__quote@
    10411042@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-DeclStmt.Po@am__quote@
    10421043@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Declaration.Po@am__quote@
     
    10601061@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-TypeofType.Po@am__quote@
    10611062@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po@am__quote@
    1062 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po@am__quote@
    10631063@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@
    10641064@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po@am__quote@
     
    24982498@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
    24992499
    2500 SynTree/driver_cfa_cpp-VarExprReplacer.o: SynTree/VarExprReplacer.cc
    2501 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarExprReplacer.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo -c -o SynTree/driver_cfa_cpp-VarExprReplacer.o `test -f 'SynTree/VarExprReplacer.cc' || echo '$(srcdir)/'`SynTree/VarExprReplacer.cc
    2502 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po
    2503 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VarExprReplacer.cc' object='SynTree/driver_cfa_cpp-VarExprReplacer.o' libtool=no @AMDEPBACKSLASH@
    2504 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2505 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VarExprReplacer.o `test -f 'SynTree/VarExprReplacer.cc' || echo '$(srcdir)/'`SynTree/VarExprReplacer.cc
    2506 
    2507 SynTree/driver_cfa_cpp-VarExprReplacer.obj: SynTree/VarExprReplacer.cc
    2508 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-VarExprReplacer.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo -c -o SynTree/driver_cfa_cpp-VarExprReplacer.obj `if test -f 'SynTree/VarExprReplacer.cc'; then $(CYGPATH_W) 'SynTree/VarExprReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarExprReplacer.cc'; fi`
    2509 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po
    2510 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/VarExprReplacer.cc' object='SynTree/driver_cfa_cpp-VarExprReplacer.obj' libtool=no @AMDEPBACKSLASH@
    2511 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2512 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-VarExprReplacer.obj `if test -f 'SynTree/VarExprReplacer.cc'; then $(CYGPATH_W) 'SynTree/VarExprReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/VarExprReplacer.cc'; fi`
     2500SynTree/driver_cfa_cpp-DeclReplacer.o: SynTree/DeclReplacer.cc
     2501@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclReplacer.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo -c -o SynTree/driver_cfa_cpp-DeclReplacer.o `test -f 'SynTree/DeclReplacer.cc' || echo '$(srcdir)/'`SynTree/DeclReplacer.cc
     2502@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po
     2503@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclReplacer.cc' object='SynTree/driver_cfa_cpp-DeclReplacer.o' libtool=no @AMDEPBACKSLASH@
     2504@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2505@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclReplacer.o `test -f 'SynTree/DeclReplacer.cc' || echo '$(srcdir)/'`SynTree/DeclReplacer.cc
     2506
     2507SynTree/driver_cfa_cpp-DeclReplacer.obj: SynTree/DeclReplacer.cc
     2508@am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-DeclReplacer.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo -c -o SynTree/driver_cfa_cpp-DeclReplacer.obj `if test -f 'SynTree/DeclReplacer.cc'; then $(CYGPATH_W) 'SynTree/DeclReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclReplacer.cc'; fi`
     2509@am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-DeclReplacer.Po
     2510@AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/DeclReplacer.cc' object='SynTree/driver_cfa_cpp-DeclReplacer.obj' libtool=no @AMDEPBACKSLASH@
     2511@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
     2512@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-DeclReplacer.obj `if test -f 'SynTree/DeclReplacer.cc'; then $(CYGPATH_W) 'SynTree/DeclReplacer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/DeclReplacer.cc'; fi`
    25132513
    25142514Tuples/driver_cfa_cpp-TupleAssignment.o: Tuples/TupleAssignment.cc
  • src/Parser/DeclarationNode.cc

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    2828
    2929// #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/ConversionCost.cc

    rbd5cf7c re93f1d2  
    275275                        // xxx - not positive this is correct, but appears to allow casting int => enum
    276276                        cost = Cost::unsafe;
    277                 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    278                         cost = Cost::unsafe;
    279                 } // if
     277                } // if
     278                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
    280279        }
    281280
     
    309308                                // assignResult == 0 means Cost::Infinity
    310309                        } // if
    311                 } else if ( dynamic_cast< ZeroType * >( dest ) ) {
    312                         cost = Cost::unsafe;
     310                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
    313311                } // if
    314312        }
  • src/ResolvExpr/Resolver.cc

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    8989                void previsit( StructDecl * aggregateDecl );
    9090                void previsit( UnionDecl * aggregateDecl );
     91                void previsit( StaticAssertDecl * assertDecl );
    9192
    9293          private:
     
    147148                void previsit( ObjectDecl * object );
    148149                void previsit( FunctionDecl * func );
     150                void previsit( FunctionType * ftype );
    149151                void previsit( StructDecl * aggrDecl );
    150152                void previsit( UnionDecl * aggrDecl );
     
    296298        }
    297299
    298         bool isStructOrUnion( Declaration *decl ) {
    299                 return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
     300        bool shouldHoist( Declaration *decl ) {
     301                return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
    300302        }
    301303
     
    310312                } // if
    311313                // Always remove the hoisted aggregate from the inner structure.
    312                 GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } );
     314                GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, shouldHoist, false ); } );
    313315        }
    314316
     
    328330                if ( inst->baseUnion ) {
    329331                        declsToAddBefore.push_front( inst->baseUnion );
     332                }
     333        }
     334
     335        void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
     336                if ( parentAggr ) {
     337                        declsToAddBefore.push_back( assertDecl );
    330338                }
    331339        }
     
    626634
    627635        void ForallPointerDecay::previsit( ObjectDecl *object ) {
    628                 forallFixer( object->type->forall, object );
    629                 if ( PointerType *pointer = dynamic_cast< PointerType * >( object->type ) ) {
    630                         forallFixer( pointer->base->forall, object );
    631                 } // if
     636                // ensure that operator names only apply to functions or function pointers
     637                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     638                        SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." ) );
     639                }
    632640                object->fixUniqueId();
    633641        }
    634642
    635643        void ForallPointerDecay::previsit( FunctionDecl *func ) {
    636                 forallFixer( func->type->forall, func );
    637644                func->fixUniqueId();
     645        }
     646
     647        void ForallPointerDecay::previsit( FunctionType * ftype ) {
     648                forallFixer( ftype->forall, ftype );
    638649        }
    639650
  • src/SynTree/CompoundStmt.cc

    rbd5cf7c re93f1d2  
    2323#include "Statement.h"                // for CompoundStmt, Statement, DeclStmt
    2424#include "SynTree/Label.h"            // for Label
    25 #include "SynTree/VarExprReplacer.h"  // for VarExprReplacer, VarExprReplace...
     25#include "SynTree/DeclReplacer.h"     // for DeclReplacer
    2626
    2727using std::string;
     
    4949        // recursively execute this routine. There may be more efficient ways of doing
    5050        // this.
    51         VarExprReplacer::DeclMap declMap;
     51        DeclReplacer::DeclMap declMap;
    5252        std::list< Statement * >::const_iterator origit = other.kids.begin();
    5353        for ( Statement * s : kids ) {
     
    6464        }
    6565        if ( ! declMap.empty() ) {
    66                 VarExprReplacer::replace( this, declMap );
     66                DeclReplacer::replace( this, declMap );
    6767        }
    6868}
  • src/SynTree/Declaration.cc

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    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/FunctionDecl.cc

    rbd5cf7c re93f1d2  
    2626#include "Statement.h"           // for CompoundStmt
    2727#include "Type.h"                // for Type, FunctionType, Type::FuncSpecif...
    28 #include "VarExprReplacer.h"
     28#include "DeclReplacer.h"
    2929
    3030extern bool translation_unit_nomain;
     
    4141                : Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
    4242
    43         VarExprReplacer::DeclMap declMap;
     43        DeclReplacer::DeclMap declMap;
    4444        for ( auto p : group_iterate( other.type->parameters, type->parameters ) ) {
    4545                declMap[ std::get<0>(p) ] = std::get<1>(p);
     
    4949        }
    5050        if ( ! declMap.empty() ) {
    51                 VarExprReplacer::replace( this, declMap );
     51                DeclReplacer::replace( this, declMap );
    5252        }
    5353        cloneAll( other.withExprs, withExprs );
  • src/SynTree/Mutator.h

    rbd5cf7c re93f1d2  
    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

    rbd5cf7c re93f1d2  
    3838class TypedefDecl;
    3939class AsmDecl;
     40class StaticAssertDecl;
    4041
    4142class Statement;
  • src/SynTree/TypeSubstitution.cc

    rbd5cf7c re93f1d2  
    149149                return inst;
    150150        } else {
    151 ///         std::cerr << "found " << inst->get_name() << ", replacing with ";
    152 ///         i->second->print( std::cerr );
    153 ///         std::cerr << std::endl;
     151                // cut off infinite loop for the case where a type is bound to itself.
     152                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
     153                // TODO: investigate preventing type variables from being bound to themselves in the first place.
     154                if ( TypeInstType * replacement = dynamic_cast< TypeInstType * >( i->second ) ) {
     155                        if ( inst->name == replacement->name ) {
     156                                return inst;
     157                        }
     158                }
     159                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    154160                subCount++;
    155161                Type * newtype = i->second->clone();
    156162                newtype->get_qualifiers() |= inst->get_qualifiers();
    157163                delete inst;
    158                 return newtype;
     164                // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
     165                return newtype->acceptMutator( *visitor );
    159166        } // if
    160167}
  • src/SynTree/TypeSubstitution.h

    rbd5cf7c re93f1d2  
    129129
    130130// definitition must happen after PassVisitor is included so that WithGuards can be used
    131 struct TypeSubstitution::Substituter : public WithGuards {
     131struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
    132132                Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    133133
  • src/SynTree/Visitor.h

    rbd5cf7c re93f1d2  
    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/SynTree/module.mk

    rbd5cf7c re93f1d2  
    4848       SynTree/TypeSubstitution.cc \
    4949       SynTree/Attribute.cc \
    50        SynTree/VarExprReplacer.cc
     50       SynTree/DeclReplacer.cc
    5151
  • src/libcfa/concurrency/kernel.c

    rbd5cf7c re93f1d2  
    628628        __cfaabi_dbg_bits_write( abort_text, len );
    629629
    630         if ( thrd != TL_GET( this_coroutine ) ) {
     630        if ( get_coroutine(thrd) != TL_GET( this_coroutine ) ) {
    631631                len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", TL_GET( this_coroutine )->name, TL_GET( this_coroutine ) );
    632632                __cfaabi_dbg_bits_write( abort_text, len );
  • src/libcfa/stdlib.c

    rbd5cf7c re93f1d2  
    9999        char * eeptr;
    100100        re = strtof( sptr, &eeptr );
    101         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
     101        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
    102102        im = strtof( eeptr, &eeptr );
    103         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
     103        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
    104104        if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0f + 0.0f * _Complex_I; }
    105105        return re + im * _Complex_I;
     
    110110        char * eeptr;
    111111        re = strtod( sptr, &eeptr );
    112         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
     112        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
    113113        im = strtod( eeptr, &eeptr );
    114         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
     114        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
    115115        if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0 + 0.0 * _Complex_I; }
    116116        return re + im * _Complex_I;
     
    121121        char * eeptr;
    122122        re = strtold( sptr, &eeptr );
    123         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
     123        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
    124124        im = strtold( eeptr, &eeptr );
    125         if ( sptr == *eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
     125        if ( sptr == eeptr ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
    126126        if ( *eeptr != 'i' ) { if ( eptr != 0 ) *eptr = eeptr; return 0.0L + 0.0L * _Complex_I; }
    127127        return re + im * _Complex_I;
  • src/tests/.expect/attributes.x64.txt

    rbd5cf7c re93f1d2  
    33    L: __attribute__ ((unused)) ((void)1);
    44}
    5 __attribute__ ((unused)) struct __anonymous0 {
     5struct __attribute__ ((unused)) __anonymous0 {
    66};
    77static inline void ___constructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1);
     
    2020    return ___ret__13s__anonymous0_1;
    2121}
    22 __attribute__ ((unused)) struct Agn1;
    23 __attribute__ ((unused)) struct Agn2 {
     22struct __attribute__ ((unused)) Agn1;
     23struct __attribute__ ((unused)) Agn2 {
    2424};
    2525static inline void ___constructor__F_R5sAgn2_autogen___1(struct Agn2 *___dst__R5sAgn2_1);
     
    4545    __E2__C5eAgn3_1,
    4646};
    47 __attribute__ ((unused)) struct __anonymous2;
    48 __attribute__ ((unused)) struct __anonymous3;
     47struct __attribute__ ((unused)) __anonymous2;
     48struct __attribute__ ((unused)) __anonymous3;
    4949struct Fdl {
    5050    __attribute__ ((unused)) signed int __f1__i_1;
     
    314314    ((void)sizeof(__attribute__ ((unused,unused,unused)) signed int (*)[10]));
    315315    ((void)sizeof(__attribute__ ((unused,unused,unused)) signed int ()));
    316     __attribute__ ((unused)) struct __anonymous4 {
     316    struct __attribute__ ((unused)) __anonymous4 {
    317317        signed int __i__i_2;
    318318    };
  • src/tests/.expect/attributes.x86.txt

    rbd5cf7c re93f1d2  
    33    L: __attribute__ ((unused)) ((void)1);
    44}
    5 __attribute__ ((unused)) struct __anonymous0 {
     5struct __attribute__ ((unused)) __anonymous0 {
    66};
    77static inline void ___constructor__F_R13s__anonymous0_autogen___1(struct __anonymous0 *___dst__R13s__anonymous0_1);
     
    2020    return ___ret__13s__anonymous0_1;
    2121}
    22 __attribute__ ((unused)) struct Agn1;
    23 __attribute__ ((unused)) struct Agn2 {
     22struct __attribute__ ((unused)) Agn1;
     23struct __attribute__ ((unused)) Agn2 {
    2424};
    2525static inline void ___constructor__F_R5sAgn2_autogen___1(struct Agn2 *___dst__R5sAgn2_1);
     
    4545    __E2__C5eAgn3_1,
    4646};
    47 __attribute__ ((unused)) struct __anonymous2;
    48 __attribute__ ((unused)) struct __anonymous3;
     47struct __attribute__ ((unused)) __anonymous2;
     48struct __attribute__ ((unused)) __anonymous3;
    4949struct Fdl {
    5050    __attribute__ ((unused)) signed int __f1__i_1;
     
    314314    ((void)sizeof(__attribute__ ((unused,unused,unused)) signed int (*)[10]));
    315315    ((void)sizeof(__attribute__ ((unused,unused,unused)) signed int ()));
    316     __attribute__ ((unused)) struct __anonymous4 {
     316    struct __attribute__ ((unused)) __anonymous4 {
    317317        signed int __i__i_2;
    318318    };
  • src/tests/.expect/references.txt

    rbd5cf7c re93f1d2  
    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

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

    rbd5cf7c re93f1d2  
    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.