Changeset 62423350
- Timestamp:
- Jun 29, 2017, 5:06:24 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- a12d5aa
- Parents:
- bb1cd95
- Location:
- src
- Files:
-
- 25 edited
-
CodeGen/CodeGenerator.cc (modified) (1 diff)
-
Common/PassVisitor.h (modified) (1 diff)
-
Common/PassVisitor.impl.h (modified) (2 diffs)
-
Common/PassVisitor.proto.h (modified) (2 diffs)
-
InitTweak/FixInit.cc (modified) (7 diffs)
-
Parser/TypeData.cc (modified) (1 diff)
-
ResolvExpr/AlternativeFinder.cc (modified) (3 diffs)
-
ResolvExpr/CurrentObject.cc (modified) (17 diffs)
-
ResolvExpr/CurrentObject.h (modified) (1 diff)
-
ResolvExpr/Resolver.cc (modified) (2 diffs)
-
ResolvExpr/Unify.cc (modified) (4 diffs)
-
SymTab/ImplementationType.cc (modified) (2 diffs)
-
SynTree/Constant.cc (modified) (2 diffs)
-
SynTree/Constant.h (modified) (2 diffs)
-
SynTree/Expression.cc (modified) (2 diffs)
-
SynTree/Expression.h (modified) (1 diff)
-
SynTree/Initializer.cc (modified) (1 diff)
-
SynTree/Mutator.cc (modified) (1 diff)
-
SynTree/TupleType.cc (modified) (1 diff)
-
SynTree/Type.h (modified) (3 diffs)
-
SynTree/VarExprReplacer.cc (modified) (1 diff)
-
SynTree/VarExprReplacer.h (modified) (1 diff)
-
SynTree/Visitor.cc (modified) (1 diff)
-
Tuples/TupleExpansion.cc (modified) (1 diff)
-
tests/designations.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
rbb1cd95 r62423350 292 292 if ( designators.size() == 0 ) return; 293 293 for ( Expression * des : designators ) { 294 if ( dynamic_cast< ConstantExpr * >( des ) ) { 295 // if expression is a ConstantExpr, then initializing array element 294 if ( dynamic_cast< NameExpr * >( des ) || dynamic_cast< VariableExpr * >( des ) ) { 295 // if expression is a NameExpr or VariableExpr, then initializing aggregate member 296 output << "."; 297 des->accept( *this ); 298 } else { 299 // otherwise, it has to be a ConstantExpr or CastExpr, initializing array eleemnt 296 300 output << "["; 297 301 des->accept( *this ); 298 302 output << "]"; 299 } else {300 // if not a ConstantExpr, it has to be a NameExpr or VariableExpr, initializing aggregate member301 output << ".";302 des->accept( *this );303 303 } // if 304 304 } // for -
src/Common/PassVisitor.h
rbb1cd95 r62423350 257 257 258 258 void set_visit_children( bool& ref ) { bool_ref * ptr = visit_children_impl(pass, 0); if(ptr) ptr->set( ref ); } 259 260 guard_value_impl init_guard() {261 guard_value_impl guard;262 auto at_cleanup = at_cleanup_impl(pass, 0);263 if( at_cleanup ) {264 *at_cleanup = [&guard]( cleanup_func_t && func, void* val ) {265 guard.push( std::move( func ), val );266 };267 }268 return guard;269 }270 259 }; 271 260 -
src/Common/PassVisitor.impl.h
rbb1cd95 r62423350 3 3 #define VISIT_START( node ) \ 4 4 __attribute__((unused)) \ 5 const auto & guard = init_guard();\5 guard_value_impl guard( at_cleanup_impl(pass, 0) ); \ 6 6 bool visit_children = true; \ 7 7 set_visit_children( visit_children ); \ … … 15 15 #define MUTATE_START( node ) \ 16 16 __attribute__((unused)) \ 17 const auto & guard = init_guard();\17 guard_value_impl guard( at_cleanup_impl(pass, 0) ); \ 18 18 bool visit_children = true; \ 19 19 set_visit_children( visit_children ); \ -
src/Common/PassVisitor.proto.h
rbb1cd95 r62423350 5 5 6 6 typedef std::function<void( void * )> cleanup_func_t; 7 typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t; 7 8 8 9 class guard_value_impl { 9 10 public: 10 guard_value_impl() = default; 11 guard_value_impl( at_cleanup_t * at_cleanup ) { 12 if( at_cleanup ) { 13 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 14 push( std::move( func ), val ); 15 }; 16 } 17 } 11 18 12 19 ~guard_value_impl() { … … 33 40 }; 34 41 35 typedef std::function< void( cleanup_func_t, void * ) > at_cleanup_t;36 42 37 43 class bool_ref { -
src/InitTweak/FixInit.cc
rbb1cd95 r62423350 104 104 typedef AddStmtVisitor Parent; 105 105 using Parent::visit; 106 typedef std::set< ObjectDecl * > ObjectSet; 106 // use ordered data structure to maintain ordering for set_difference and for consistent error messages 107 typedef std::list< ObjectDecl * > ObjectSet; 107 108 virtual void visit( CompoundStmt *compoundStmt ) override; 108 109 virtual void visit( DeclStmt *stmt ) override; … … 116 117 117 118 // debug 118 struct printSet {119 typedef ObjDeclCollector::ObjectSet ObjectSet;120 printSet( const ObjectSet & objs ) : objs( objs ) {}119 template<typename ObjectSet> 120 struct PrintSet { 121 PrintSet( const ObjectSet & objs ) : objs( objs ) {} 121 122 const ObjectSet & objs; 122 123 }; 123 std::ostream & operator<<( std::ostream & out, const printSet & set) { 124 template<typename ObjectSet> 125 PrintSet<ObjectSet> printSet( const ObjectSet & objs ) { return PrintSet<ObjectSet>( objs ); } 126 template<typename ObjectSet> 127 std::ostream & operator<<( std::ostream & out, const PrintSet<ObjectSet> & set) { 124 128 out << "{ "; 125 129 for ( ObjectDecl * obj : set.objs ) { … … 745 749 746 750 Statement * dtor = ctorInit->get_dtor(); 747 objDecl->set_init( NULL);748 ctorInit->set_ctor( NULL);751 objDecl->set_init( nullptr ); 752 ctorInit->set_ctor( nullptr ); 749 753 ctorInit->set_dtor( nullptr ); 750 754 if ( dtor ) { … … 799 803 } else { 800 804 stmtsToAddAfter.push_back( ctor ); 801 objDecl->set_init( NULL);802 ctorInit->set_ctor( NULL);805 objDecl->set_init( nullptr ); 806 ctorInit->set_ctor( nullptr ); 803 807 } 804 808 } // if 805 809 } else if ( Initializer * init = ctorInit->get_init() ) { 806 810 objDecl->set_init( init ); 807 ctorInit->set_init( NULL);811 ctorInit->set_init( nullptr ); 808 812 } else { 809 813 // no constructor and no initializer, which is okay 810 objDecl->set_init( NULL);814 objDecl->set_init( nullptr ); 811 815 } // if 812 816 delete ctorInit; … … 816 820 817 821 void ObjDeclCollector::visit( CompoundStmt * compoundStmt ) { 818 std::set< ObjectDecl * >prevVars = curVars;822 ObjectSet prevVars = curVars; 819 823 Parent::visit( compoundStmt ); 820 824 curVars = prevVars; … … 824 828 // keep track of all variables currently in scope 825 829 if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) { 826 curVars. insert( objDecl );830 curVars.push_back( objDecl ); 827 831 } // if 828 832 Parent::visit( stmt ); … … 939 943 ) 940 944 if ( ! diff.empty() ) { 945 // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages. 946 std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() ); 947 941 948 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor 942 949 OrderedDecls ordered; 943 950 for ( OrderedDecls & rdo : reverseDeclOrder ) { 944 951 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order. 945 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } );952 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } ); 946 953 } // for 947 954 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) ); -
src/Parser/TypeData.cc
rbb1cd95 r62423350 777 777 TupleType * buildTuple( const TypeData * td ) { 778 778 assert( td->kind == TypeData::Tuple ); 779 TupleType * ret = new TupleType( buildQualifiers( td ) ); 780 buildTypeList( td->tuple, ret->get_types() ); 779 std::list< Type * > types; 780 buildTypeList( td->tuple, types ); 781 TupleType * ret = new TupleType( buildQualifiers( td ), types ); 781 782 buildForall( td->forall, ret->get_forall() ); 782 783 return ret; -
src/ResolvExpr/AlternativeFinder.cc
rbb1cd95 r62423350 809 809 } 810 810 811 Expression * restructureCast( Expression * argExpr, Type * toType ) { 812 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() ) { 813 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 814 // to its corresponding target type, producing the tuple of those cast expressions. If there are 815 // more components of the tuple than components in the target type, then excess components do not 816 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 817 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 818 // expressions which may contain side effects require a single unique instance of the expression. 819 argExpr = new UniqueExpr( argExpr ); 820 } 821 std::list< Expression * > componentExprs; 822 for ( unsigned int i = 0; i < toType->size(); i++ ) { 823 // cast each component 824 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i ); 825 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) ); 826 } 827 delete argExpr; 828 assert( componentExprs.size() > 0 ); 829 // produce the tuple of casts 830 return new TupleExpr( componentExprs ); 831 } else { 832 // handle normally 833 return new CastExpr( argExpr, toType->clone() ); 834 } 835 } 836 811 837 void AlternativeFinder::visit( CastExpr *castExpr ) { 812 838 Type *& toType = castExpr->get_result(); … … 840 866 thisCost += Cost( 0, 0, discardedValues ); 841 867 842 Expression * argExpr = i->expr->clone(); 843 if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) { 844 // Argument expression is a tuple and the target type is not void. Cast each member of the tuple 845 // to its corresponding target type, producing the tuple of those cast expressions. If there are 846 // more components of the tuple than components in the target type, then excess components do not 847 // come out in the result expression (but UniqueExprs ensure that side effects will still be done). 848 if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) { 849 // expressions which may contain side effects require a single unique instance of the expression. 850 argExpr = new UniqueExpr( argExpr ); 851 } 852 std::list< Expression * > componentExprs; 853 for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) { 854 // cast each component 855 TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i ); 856 componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) ); 857 } 858 delete argExpr; 859 assert( componentExprs.size() > 0 ); 860 // produce the tuple of casts 861 candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) ); 862 } else { 863 // handle normally 864 candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) ); 865 } 868 candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) ); 866 869 } // if 867 870 } // for … … 1183 1186 1184 1187 void AlternativeFinder::visit( UntypedInitExpr *initExpr ) { 1185 AlternativeFinder finder( indexer, env ); 1186 finder.findWithAdjustment( initExpr->get_expr() ); 1187 // handle each option like a cast -- should probably push this info into AltFinder as a kind of expression, both to keep common code close and to have less 'reach-in', but more 'push-in' 1188 // handle each option like a cast 1188 1189 AltList candidates; 1189 std::cerr << "untyped init expr: " << initExpr << std::endl;1190 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1190 1191 // O(N^2) checks of d-types with e-types 1191 for ( Alternative & alt : finder.get_alternatives() ) { 1192 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { 1192 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { 1193 Type * toType = resolveTypeof( initAlt.type, indexer ); 1194 SymTab::validateType( toType, &indexer ); 1195 adjustExprType( toType, env, indexer ); 1196 // Ideally the call to findWithAdjustment could be moved out of the loop, but unfortunately it currently has to occur inside or else 1197 // polymorphic return types are not properly bound to the initialization type, since return type variables are only open for the duration of resolving 1198 // the UntypedExpr. This is only actually an issue in initialization contexts that allow more than one possible initialization type, but it is still suboptimal. 1199 AlternativeFinder finder( indexer, env ); 1200 finder.targetType = toType; 1201 finder.findWithAdjustment( initExpr->get_expr() ); 1202 for ( Alternative & alt : finder.get_alternatives() ) { 1203 TypeEnvironment newEnv( alt.env ); 1193 1204 AssertionSet needAssertions, haveAssertions; 1194 OpenVarSet openVars; 1195 std::cerr << " " << initAlt.type << " " << initAlt.designation << std::endl;1205 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1206 PRINT( std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; ) 1196 1207 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1197 1208 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1198 1209 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1199 1210 // to. 1200 int discardedValues = alt.expr->get_result()->size() - initAlt.type->size();1211 int discardedValues = alt.expr->get_result()->size() - toType->size(); 1201 1212 if ( discardedValues < 0 ) continue; 1202 1213 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1203 1214 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1204 1215 // unification run for side-effects 1205 unify( initAlt.type, alt.expr->get_result(), alt.env, needAssertions, haveAssertions, openVars, indexer );1206 1207 Cost thisCost = castCost( alt.expr->get_result(), initAlt.type, indexer, alt.env );1216 unify( toType, alt.expr->get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1217 1218 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv ); 1208 1219 if ( thisCost != Cost::infinity ) { 1209 1220 // count one safe conversion for each value that is thrown away 1210 1221 thisCost += Cost( 0, 0, discardedValues ); 1211 candidates.push_back( Alternative( new InitExpr( alt.expr->clone(), initAlt.type->clone(), initAlt.designation->clone() ), alt.env, alt.cost, thisCost ) );1222 candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) ); 1212 1223 } 1213 1224 } -
src/ResolvExpr/CurrentObject.cc
rbb1cd95 r62423350 22 22 #include "SynTree/Initializer.h" 23 23 #include "SynTree/Type.h" 24 #include "SynTree/TypeSubstitution.h" 24 25 25 26 #if 0 … … 32 33 long long int getConstValue( ConstantExpr * constExpr ) { 33 34 if ( BasicType * basicType = dynamic_cast< BasicType * >( constExpr->get_result() ) ) { 34 if ( basicType->get_kind() == BasicType::Char || basicType->get_kind() == BasicType::SignedChar || basicType->get_kind() == BasicType::UnsignedChar ) { 35 assertf( constExpr->get_constant()->get_value().size() == 3, "constant value with unusual length: %s", constExpr->get_constant()->get_value().c_str() ); 36 return constExpr->get_constant()->get_value()[1]; 35 if ( basicType->isInteger() ) { 36 return constExpr->get_constant()->get_ival(); 37 37 } else { 38 return stoll( constExpr->get_constant()->get_value() ); 39 } 38 assertf( false, "Non-integer constant expression in getConstValue", toString( constExpr ).c_str() ); // xxx - might be semantic error 39 } 40 } else if ( dynamic_cast< OneType * >( constExpr->get_result() ) ) { 41 return 1; 42 } else if ( dynamic_cast< ZeroType * >( constExpr->get_result() ) ) { 43 return 0; 40 44 } else { 41 assertf( false, "unhandled type on getConstValue %s", constExpr->get_result() );45 assertf( false, "unhandled type on getConstValue %s", toString( constExpr->get_result() ).c_str() ); // xxx - might be semantic error 42 46 } 43 47 } … … 56 60 std::ostream & operator<<( std::ostream & out, Indenter & indent ) { 57 61 return out << std::string(indent.indent, ' '); 62 } 63 64 template< typename AggrInst > 65 TypeSubstitution makeGenericSubstitution( AggrInst * inst ) { 66 assert( inst ); 67 assert( inst->get_baseParameters() ); 68 std::list< TypeDecl * > baseParams = *inst->get_baseParameters(); 69 std::list< Expression * > typeSubs = inst->get_parameters(); 70 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); 71 return subs; 72 } 73 74 TypeSubstitution makeGenericSubstitution( Type * type ) { 75 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) { 76 return makeGenericSubstitution( inst ); 77 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) { 78 return makeGenericSubstitution( inst ); 79 } else { 80 return TypeSubstitution(); 81 } 58 82 } 59 83 … … 135 159 void setSize( Expression * expr ) { 136 160 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 137 size = getConstValue( constExpr ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this161 size = getConstValue( constExpr ); 138 162 PRINT( std::cerr << "array type with size: " << size << std::endl; ) 139 163 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 140 setSize( castExpr->get_arg() ); 164 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast 141 165 } else { 142 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); 166 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this 143 167 } 144 168 } … … 231 255 class AggregateIterator : public MemberIterator { 232 256 public: 233 typedef std::list<Declaration *>::iterator iterator; 234 const char * kind = ""; // for debug 235 ReferenceToType * inst = nullptr; 236 AggregateDecl * decl = nullptr; 257 typedef std::list<Declaration *> MemberList; 258 typedef MemberList::const_iterator iterator; 259 std::string kind = ""; // for debug 260 std::string name; 261 Type * inst = nullptr; 262 const MemberList & members; 237 263 iterator curMember; 238 bool atbegin = true; // false at first {small,big}Step -- this structtype is only added to the possibilities at the beginning264 bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning 239 265 Type * curType = nullptr; 240 266 MemberIterator * memberIter = nullptr; 241 242 AggregateIterator( const char * kind, ReferenceToType * inst, AggregateDecl * decl ) : kind( kind ), inst( inst ), decl( decl ), curMember( decl->get_members().begin() ) { 267 mutable TypeSubstitution sub; 268 269 AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) { 243 270 init(); 244 271 } … … 249 276 250 277 bool init() { 251 PRINT( std::cerr << "--init()--" << std::endl; )252 if ( curMember != decl->get_members().end() ) {278 PRINT( std::cerr << "--init()--" << members.size() << std::endl; ) 279 if ( curMember != members.end() ) { 253 280 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) { 254 281 PRINT( std::cerr << "incremented to field: " << field << std::endl; ) … … 264 291 if (memberIter && *memberIter) { 265 292 std::list<InitAlternative> ret = memberIter->first(); 293 PRINT( std::cerr << "sub: " << sub << std::endl; ) 266 294 for ( InitAlternative & alt : ret ) { 267 295 PRINT( std::cerr << "iterating and adding designators" << std::endl; ) 268 296 alt.designation->get_designators().push_front( new VariableExpr( safe_dynamic_cast< ObjectDecl * >( *curMember ) ) ); 297 // need to substitute for generic types, so that casts are to concrete types 298 PRINT( std::cerr << " type is: " << alt.type; ) 299 sub.apply( alt.type ); // also apply to designation?? 300 PRINT( std::cerr << " ==> " << alt.type << std::endl; ) 269 301 } 270 302 return ret; … … 276 308 if ( ! designators.empty() ) { 277 309 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) { 278 for ( curMember = decl->get_members().begin(); curMember != decl->get_members().end(); ++curMember ) {310 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) { 279 311 if ( *curMember == varExpr->get_var() ) { 280 312 designators.pop_front(); … … 282 314 memberIter = createMemberIterator( varExpr->get_result() ); 283 315 curType = varExpr->get_result(); 284 atbegin = curMember == decl->get_members().begin() && designators.empty(); // xxx - is this right??316 atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin?? 285 317 memberIter->setPosition( designators ); 286 318 return; 287 319 } // if 288 320 } // for 289 assertf( false, "could not find member in %s: %s", kind , toString( varExpr ).c_str() );321 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() ); 290 322 } else { 291 assertf( false, "bad designator given to %s: %s", kind , toString( designators.front() ).c_str() );323 assertf( false, "bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() ); 292 324 } // if 293 325 } // if … … 336 368 337 369 virtual void print( std::ostream & out, Indenter indent ) const { 338 out << kind << "(" << decl->get_name()<< ")";370 out << kind << "(" << name << ")"; 339 371 if ( memberIter ) { 340 372 Indenter childIndent = indent+1; … … 347 379 class UnionIterator : public AggregateIterator { 348 380 public: 349 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst , inst->get_baseUnion() ) {}381 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {} 350 382 351 383 virtual operator bool() const { return (memberIter && *memberIter); } … … 357 389 memberIter = nullptr; 358 390 curType = nullptr; 359 curMember = decl->get_members().end();391 curMember = members.end(); 360 392 return *this; 361 393 } … … 365 397 class StructIterator : public AggregateIterator { 366 398 public: 367 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst , inst->get_baseStruct() ) {}368 369 virtual operator bool() const { return curMember != decl->get_members().end() || (memberIter && *memberIter); }399 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {} 400 401 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); } 370 402 371 403 virtual MemberIterator & bigStep() { … … 375 407 memberIter = nullptr; 376 408 curType = nullptr; 377 for ( ; curMember != decl->get_members().end(); ) { 409 for ( ; curMember != members.end(); ) { 410 ++curMember; 411 if ( init() ) { 412 return *this; 413 } 414 } 415 return *this; 416 } 417 }; 418 419 class TupleIterator : public AggregateIterator { 420 public: 421 TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {} 422 423 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); } 424 425 virtual MemberIterator & bigStep() { 426 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 427 atbegin = false; 428 delete memberIter; 429 memberIter = nullptr; 430 curType = nullptr; 431 for ( ; curMember != members.end(); ) { 378 432 ++curMember; 379 433 if ( init() ) { … … 392 446 return new UnionIterator( uit ); 393 447 } else { 394 assertf( false, "some other reftotype" ); 448 assertf( dynamic_cast< TypeInstType * >( type ), "some other reftotype" ); 449 return new SimpleIterator( type ); 395 450 } 396 451 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) { 397 452 return new ArrayIterator( at ); 453 } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) { 454 return new TupleIterator( tt ); 398 455 } else { 399 456 return new SimpleIterator( type ); … … 494 551 Type * type = objStack.top()->getNext(); 495 552 if ( type ) { 496 // xxx - record types.front()?497 553 objStack.push( createMemberIterator( type ) ); 498 554 } else { … … 517 573 return **objStack.top(); 518 574 } 575 576 Type * CurrentObject::getCurrentType() { 577 PRINT( std::cerr << "____getting current type" << std::endl; ) 578 assertf( ! objStack.empty(), "objstack empty in getCurrentType" ); 579 return objStack.top()->getNext(); 580 } 519 581 } // namespace ResolvExpr 520 582 -
src/ResolvExpr/CurrentObject.h
rbb1cd95 r62423350 42 42 /// produces a list of alternatives (Type *, Designation *) for the current sub-object's initializer 43 43 std::list< InitAlternative > getOptions(); 44 /// produces the type of the current object but no subobjects 45 Type * getCurrentType(); 44 46 45 47 private: -
src/ResolvExpr/Resolver.cc
rbb1cd95 r62423350 375 375 } 376 376 377 template< typename Aggr >378 void lookupDesignation( Aggr * aggr, const std::list< Expression > & designators ) {379 380 }381 382 377 void Resolver::visit( SingleInit *singleInit ) { 378 // resolve initialization using the possibilities as determined by the currentObject cursor 383 379 UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() ); 384 380 Expression * newExpr = findSingleExpression( untyped, *this ); 385 381 InitExpr * initExpr = safe_dynamic_cast< InitExpr * >( newExpr ); 386 singleInit->set_value( new CastExpr( initExpr->get_expr()->clone(), initExpr->get_result()->clone() ) ); 382 383 // move cursor to the object that is actually initialized 387 384 currentObject.setNext( initExpr->get_designation() ); 385 386 // discard InitExpr wrapper and retain relevant pieces 387 newExpr = initExpr->get_expr(); 388 singleInit->get_value()->set_env( initExpr->get_env() ); 389 initExpr->set_expr( nullptr ); 390 initExpr->set_env( nullptr ); 391 delete initExpr; 392 393 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 394 Type * initContext = currentObject.getCurrentType(); 395 396 // check if actual object's type is char[] 397 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 398 if ( isCharType( at->get_base() ) ) { 399 // check if the resolved type is char * 400 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 401 if ( isCharType( pt->get_base() ) ) { 402 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 403 CastExpr *ce = safe_dynamic_cast< CastExpr * >( newExpr ); 404 newExpr = ce->get_arg(); 405 ce->set_arg( nullptr ); 406 delete ce; 407 } 408 } 409 } 410 } 411 412 // set initializer expr to resolved express 413 singleInit->set_value( newExpr ); 414 415 // move cursor to next object in preparation for next initializer 388 416 currentObject.increment(); 389 delete initExpr; 390 391 // // check if initializing type is char[] 392 // if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 393 // if ( isCharType( at->get_base() ) ) { 394 // // check if the resolved type is char * 395 // if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 396 // if ( isCharType( pt->get_base() ) ) { 397 // // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 398 // CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ); 399 // singleInit->set_value( ce->get_arg() ); 400 // ce->set_arg( NULL ); 401 // delete ce; 402 // } 403 // } 404 // } 405 // } 406 } 407 408 // template< typename AggrInst > 409 // TypeSubstitution makeGenericSubstitution( AggrInst * inst ) { 410 // assert( inst ); 411 // assert( inst->get_baseParameters() ); 412 // std::list< TypeDecl * > baseParams = *inst->get_baseParameters(); 413 // std::list< Expression * > typeSubs = inst->get_parameters(); 414 // TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() ); 415 // return subs; 416 // } 417 418 // ReferenceToType * isStructOrUnion( Type * type ) { 419 // if ( StructInstType * sit = dynamic_cast< StructInstType * >( type ) ) { 420 // return sit; 421 // } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( type ) ) { 422 // return uit; 423 // } 424 // return nullptr; 425 // } 426 427 // void Resolver::resolveSingleAggrInit( Declaration * dcl, InitIterator & init, InitIterator & initEnd, TypeSubstitution sub ) { 428 // ObjectDecl * obj = dynamic_cast< ObjectDecl * >( dcl ); 429 // assert( obj ); 430 // // need to substitute for generic types, so that casts are to concrete types 431 // currentObject = obj->clone(); // xxx - delete this 432 // sub.apply( currentObject ); 433 434 // try { 435 // if ( init == initEnd ) return; // stop when there are no more initializers 436 // (*init)->accept( *this ); 437 // ++init; // made it past an initializer 438 // } catch( SemanticError & ) { 439 // // need to delve deeper, if you can 440 // if ( ReferenceToType * type = isStructOrUnion( currentObject->get_type() ) ) { 441 // resolveAggrInit( type, init, initEnd ); 442 // } else { 443 // // member is not an aggregate type, so can't go any deeper 444 445 // // might need to rethink what is being thrown 446 // throw; 447 // } // if 448 // } 449 // } 450 451 // void Resolver::resolveAggrInit( ReferenceToType * inst, InitIterator & init, InitIterator & initEnd ) { 452 // if ( StructInstType * sit = dynamic_cast< StructInstType * >( inst ) ) { 453 // TypeSubstitution sub = makeGenericSubstitution( sit ); 454 // StructDecl * st = sit->get_baseStruct(); 455 // if(st->get_members().empty()) return; 456 // // want to resolve each initializer to the members of the struct, 457 // // but if there are more initializers than members we should stop 458 // list< Declaration * >::iterator it = st->get_members().begin(); 459 // for ( ; it != st->get_members().end(); ++it) { 460 // resolveSingleAggrInit( *it, init, initEnd, sub ); 461 // } 462 // } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( inst ) ) { 463 // TypeSubstitution sub = makeGenericSubstitution( uit ); 464 // UnionDecl * un = uit->get_baseUnion(); 465 // if(un->get_members().empty()) return; 466 // // only resolve to the first member of a union 467 // resolveSingleAggrInit( *un->get_members().begin(), init, initEnd, sub ); 468 // } // if 469 // } 417 } 470 418 471 419 void Resolver::visit( ListInit * listInit ) { 420 // move cursor into brace-enclosed initializer-list 472 421 currentObject.enterListInit(); 473 422 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 474 423 std::list<Designation *> newDesignations; 475 424 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 425 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving 426 // the initializer against that object. 476 427 Designation * des = std::get<0>(p); 477 428 Initializer * init = std::get<1>(p); … … 479 430 init->accept( *this ); 480 431 } 432 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list 481 433 listInit->get_designations() = newDesignations; // xxx - memory management 482 434 currentObject.exitListInit(); 483 435 436 // xxx - this part has not be folded into CurrentObject yet 484 437 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) { 485 438 // Type * base = tt->get_baseType()->get_base(); -
src/ResolvExpr/Unify.cc
rbb1cd95 r62423350 606 606 } else if ( tupleParam ) { 607 607 // bundle other parameters into tuple to match 608 TupleType* binder = new TupleType{ paramTy->get_qualifiers() };608 std::list< Type * > binderTypes; 609 609 610 610 do { 611 binder ->get_types().push_back( otherParam->get_type()->clone() );611 binderTypes.push_back( otherParam->get_type()->clone() ); 612 612 ++jt; 613 613 … … 618 618 } while (true); 619 619 620 otherParamTy = binder;620 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes }; 621 621 ++it; // skip ttype parameter for break 622 622 } else if ( otherTupleParam ) { 623 623 // bundle parameters into tuple to match other 624 TupleType* binder = new TupleType{ otherParamTy->get_qualifiers() };624 std::list< Type * > binderTypes; 625 625 626 626 do { 627 binder ->get_types().push_back( param->get_type()->clone() );627 binderTypes.push_back( param->get_type()->clone() ); 628 628 ++it; 629 629 … … 634 634 } while (true); 635 635 636 paramTy = binder;636 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes }; 637 637 ++jt; // skip ttype parameter for break 638 638 } … … 756 756 return function->get_returnVals().front()->get_type()->clone(); 757 757 } else { 758 TupleType * tupleType = new TupleType( Type::Qualifiers() );758 std::list< Type * > types; 759 759 for ( DeclarationWithType * decl : function->get_returnVals() ) { 760 t upleType->get_types().push_back( decl->get_type()->clone() );760 types.push_back( decl->get_type()->clone() ); 761 761 } // for 762 return tupleType;762 return new TupleType( Type::Qualifiers(), types ); 763 763 } 764 764 } -
src/SymTab/ImplementationType.cc
rbb1cd95 r62423350 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ImplementationType.cc -- 7 // ImplementationType.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 92 92 93 93 void ImplementationType::visit(TupleType *tupleType) { 94 TupleType *newType = new TupleType( Type::Qualifiers() );94 std::list< Type * > types; 95 95 for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) { 96 96 Type *implType = implementationType( *i, indexer ); 97 97 implType->get_qualifiers() |= tupleType->get_qualifiers(); 98 newType->get_types().push_back( implType );98 types.push_back( implType ); 99 99 } // for 100 result = new Type;100 result = new TupleType( Type::Qualifiers(), types ); 101 101 } 102 102 -
src/SynTree/Constant.cc
rbb1cd95 r62423350 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Constant.cc -- 7 // Constant.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 46 46 } 47 47 48 unsigned long long Constant::get_ival() const { 49 assertf( safe_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." ); 50 return val.ival; 51 } 52 53 double Constant::get_dval() const { 54 assertf( ! safe_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." ); 55 return val.dval; 56 } 57 48 58 void Constant::print( std::ostream &os ) const { 49 59 os << "(" << rep << " " << val.ival; -
src/SynTree/Constant.h
rbb1cd95 r62423350 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Constant.h -- 7 // Constant.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 32 32 std::string & get_value() { return rep; } 33 33 void set_value( std::string newValue ) { rep = newValue; } 34 unsigned long long get_ival() const; 35 double get_dval() const; 34 36 35 37 /// generates a boolean constant of the given bool -
src/SynTree/Expression.cc
rbb1cd95 r62423350 21 21 #include <iterator> 22 22 23 #include "Declaration.h" 24 #include "Expression.h" 25 #include "Initializer.h" 26 #include "Statement.h" 23 27 #include "Type.h" 24 #include "Initializer.h"25 #include "Expression.h"26 #include "Declaration.h"27 #include "Statement.h"28 28 #include "TypeSubstitution.h" 29 #include "VarExprReplacer.h" 30 29 31 #include "Common/utility.h" 32 #include "Common/PassVisitor.h" 33 30 34 #include "InitTweak/InitTweak.h" 31 35 … … 681 685 } 682 686 683 InitExpr::InitExpr( Expression * expr, Type * type,Designation * designation ) : expr( expr ), designation( designation ) {684 set_result( type);687 InitExpr::InitExpr( Expression * expr, Designation * designation ) : expr( expr ), designation( designation ) { 688 set_result( expr->get_result()->clone() ); 685 689 } 686 690 InitExpr::InitExpr( const InitExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ), designation( maybeClone( other.designation) ) {} -
src/SynTree/Expression.h
rbb1cd95 r62423350 776 776 class InitExpr : public Expression { 777 777 public: 778 InitExpr( Expression * expr, Type * type,Designation * designation );778 InitExpr( Expression * expr, Designation * designation ); 779 779 InitExpr( const InitExpr & other ); 780 780 ~InitExpr(); -
src/SynTree/Initializer.cc
rbb1cd95 r62423350 65 65 66 66 67 ListInit::ListInit( const std::list<Initializer*> &initializers, const std::list<Designation *> &designations, bool maybeConstructed ) 68 : Initializer( maybeConstructed ), initializers( initializers ), designations( designations ) { 67 ListInit::ListInit( const std::list<Initializer*> &inits, const std::list<Designation *> &des, bool maybeConstructed ) 68 : Initializer( maybeConstructed ), initializers( inits ), designations( des ) { 69 // handle the common case where a ListInit is created without designations by making a list of empty designations with the same length as the initializer 70 if ( designations.empty() ) { 71 for ( auto & i : initializers ) { 72 (void)i; 73 designations.push_back( new Designation( {} ) ); 74 } 75 } 76 assertf( initializers.size() == designations.size(), "Created ListInit with mismatching initializers (%d) and designations (%d)", initializers.size(), designations.size() ); 69 77 } 70 78 -
src/SynTree/Mutator.cc
rbb1cd95 r62423350 515 515 mutateAll( tupleType->get_forall(), *this ); 516 516 mutateAll( tupleType->get_types(), *this ); 517 mutateAll( tupleType->get_members(), *this ); 517 518 return tupleType; 518 519 } -
src/SynTree/TupleType.cc
rbb1cd95 r62423350 14 14 // 15 15 16 #include "Declaration.h" 17 #include "Initializer.h" 16 18 #include "Type.h" 17 19 #include "Common/utility.h" 20 #include "Parser/LinkageSpec.h" 18 21 19 22 TupleType::TupleType( const Type::Qualifiers &tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes ) : Type( tq, attributes ), types( types ) { 23 for ( Type * t : *this ) { 24 // xxx - this is very awkward. TupleTypes should contain objects so that members can be named, but if they don't have an initializer node then 25 // they end up getting constructors, which end up being inserted causing problems. This happens because the object decls have to be visited so that 26 // their types are kept in sync with the types list here. Ultimately, the types list here should be eliminated and perhaps replaced with a list-view 27 // of the object types list, but I digress. The temporary solution here is to make a ListInit with maybeConstructed = false, that way even when the 28 // object is visited, it is never constructed. Ultimately, a better solution might be either: 29 // a) to separate TupleType from its declarations, into TupleDecl and Tuple{Inst?}Type, ala StructDecl and StructInstType 30 // b) separate initializer nodes better, e.g. add a MaybeConstructed node that is replaced by genInit, rather than what currently exists in a bool 31 members.push_back( new ObjectDecl( "" , Type::StorageClasses(), LinkageSpec::Cforall, nullptr, t->clone(), new ListInit( {}, {}, false ) ) ); 32 } 20 33 } 21 34 22 35 TupleType::TupleType( const TupleType& other ) : Type( other ) { 23 36 cloneAll( other.types, types ); 37 cloneAll( other.members, members ); 24 38 } 25 39 26 40 TupleType::~TupleType() { 27 41 deleteAll( types ); 42 deleteAll( members ); 28 43 } 29 44 -
src/SynTree/Type.h
rbb1cd95 r62423350 481 481 class TupleType : public Type { 482 482 public: 483 TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types = std::list< Type * >(), const std::list< Attribute * > & attributes = std::list< Attribute * >() );483 TupleType( const Type::Qualifiers & tq, const std::list< Type * > & types, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 484 484 TupleType( const TupleType& ); 485 485 virtual ~TupleType(); … … 488 488 typedef value_type::iterator iterator; 489 489 490 std::list<Type *>& get_types() { return types; }490 std::list<Type *> & get_types() { return types; } 491 491 virtual unsigned size() const { return types.size(); }; 492 493 // For now, this is entirely synthetic -- tuple types always have unnamed members. 494 // Eventually, we may allow named tuples, in which case members should subsume types 495 std::list<Declaration *> & get_members() { return members; } 492 496 493 497 iterator begin() { return types.begin(); } … … 506 510 virtual void print( std::ostream & os, int indent = 0 ) const; 507 511 private: 508 std::list<Type*> types; 512 std::list<Type *> types; 513 std::list<Declaration *> members; 509 514 }; 510 515 -
src/SynTree/VarExprReplacer.cc
rbb1cd95 r62423350 14 14 // 15 15 16 #include "Declaration.h" 16 17 #include "Expression.h" 17 18 #include "VarExprReplacer.h" 18 19 19 VarExprReplacer::VarExprReplacer( const DeclMap & declMap ) : declMap( declMap) {}20 VarExprReplacer::VarExprReplacer( const DeclMap & declMap, bool debug ) : declMap( declMap ), debug( debug ) {} 20 21 21 22 // replace variable with new node from decl map 22 23 void VarExprReplacer::visit( VariableExpr * varExpr ) { 23 // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are) 24 if ( declMap.count( varExpr->get_var() ) ) { 25 varExpr->set_var( declMap.at( varExpr->get_var() ) ); 26 } 24 // xxx - assertions and parameters aren't accounted for in this... (i.e. they aren't inserted into the map when it's made, only DeclStmts are) 25 if ( declMap.count( varExpr->get_var() ) ) { 26 if ( debug ) { 27 std::cerr << "replacing variable reference: " << (void*)varExpr->get_var() << " " << varExpr->get_var() << " with " << (void*)declMap.at( varExpr->get_var() ) << " " << declMap.at( varExpr->get_var() ) << std::endl; 28 } 29 varExpr->set_var( declMap.at( varExpr->get_var() ) ); 30 } 27 31 } -
src/SynTree/VarExprReplacer.h
rbb1cd95 r62423350 27 27 private: 28 28 const DeclMap & declMap; 29 bool debug; 29 30 public: 30 VarExprReplacer( const DeclMap & declMap );31 VarExprReplacer( const DeclMap & declMap, bool debug = false ); 31 32 32 33 // replace variable with new node from decl map -
src/SynTree/Visitor.cc
rbb1cd95 r62423350 407 407 acceptAll( tupleType->get_forall(), *this ); 408 408 acceptAll( tupleType->get_types(), *this ); 409 acceptAll( tupleType->get_members(), *this ); 409 410 } 410 411 -
src/Tuples/TupleExpansion.cc
rbb1cd95 r62423350 310 310 Type * makeTupleType( const std::list< Expression * > & exprs ) { 311 311 // produce the TupleType which aggregates the types of the exprs 312 TupleType *tupleType = new TupleType( Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex ) );313 Type::Qualifiers &qualifiers = tupleType->get_qualifiers();312 std::list< Type * > types; 313 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Lvalue | Type::Atomic | Type::Mutex ); 314 314 for ( Expression * expr : exprs ) { 315 315 assert( expr->get_result() ); 316 316 if ( expr->get_result()->isVoid() ) { 317 317 // if the type of any expr is void, the type of the entire tuple is void 318 delete tupleType;319 318 return new VoidType( Type::Qualifiers() ); 320 319 } 321 320 Type * type = expr->get_result()->clone(); 322 t upleType->get_types().push_back( type );321 types.push_back( type ); 323 322 // the qualifiers on the tuple type are the qualifiers that exist on all component types 324 323 qualifiers &= type->get_qualifiers(); 325 324 } // for 326 325 if ( exprs.empty() ) qualifiers = Type::Qualifiers(); 327 return tupleType;326 return new TupleType( qualifiers, types ); 328 327 } 329 328 -
src/tests/designations.c
rbb1cd95 r62423350 26 26 const int indentAmt = 2; 27 27 void indent(int level) { 28 for (int i = 0; i < level; ++i) {29 printf(" ");30 }28 for (int i = 0; i < level; ++i) { 29 printf(" "); 30 } 31 31 } 32 32 33 33 // A contains fields with different types (int vs. int *) 34 34 struct A { 35 int x, y;36 int * ptr;35 int x, y; 36 int * ptr; 37 37 }; 38 38 void printA(struct A a, int level) { 39 indent(level);40 printf("(A){ %d %d %p }\n", a.x, a.y, a.ptr);39 indent(level); 40 printf("(A){ %d %d %p }\n", a.x, a.y, a.ptr); 41 41 } 42 42 43 43 // B contains struct members 44 44 struct B { 45 struct A a0, a1;45 struct A a0, a1; 46 46 }; 47 47 void printB(struct B b, int level) { 48 indent(level);49 printf("(B){\n");50 printA(b.a0, level+indentAmt);51 printA(b.a1, level+indentAmt);52 indent(level);53 printf("}\n");48 indent(level); 49 printf("(B){\n"); 50 printA(b.a0, level+indentAmt); 51 printA(b.a1, level+indentAmt); 52 indent(level); 53 printf("}\n"); 54 54 } 55 55 56 56 // C contains an array - tests that after 3 ints, the members of B are initialized. 57 57 struct C { 58 int arr[3];59 struct B b;58 int arr[3]; 59 struct B b; 60 60 }; 61 61 void printC(struct C c, int level) { 62 indent(level);63 printf("(C){\n");64 indent(level+indentAmt);65 printf("(int[]{ %d %d %d }\n", c.arr[0], c.arr[1], c.arr[2]);66 printB(c.b, level+indentAmt);67 indent(level);68 printf("}\n");62 indent(level); 63 printf("(C){\n"); 64 indent(level+indentAmt); 65 printf("(int[]{ %d %d %d }\n", c.arr[0], c.arr[1], c.arr[2]); 66 printB(c.b, level+indentAmt); 67 indent(level); 68 printf("}\n"); 69 69 } 70 70 71 71 // D contains an unnamed aggregate - tests that this doesn't interfere with initialization. 72 72 struct D { 73 struct {74 int x;75 };73 struct { 74 int x; 75 }; 76 76 }; 77 77 void printD(struct D d, int level) { 78 indent(level);79 printf("(D){ %d }\n", d.x);78 indent(level); 79 printf("(D){ %d }\n", d.x); 80 80 } 81 81 82 82 // E tests unions 83 83 union E { 84 struct A a;85 struct B b;86 struct C c;87 struct D d;88 int i;84 struct A a; 85 struct B b; 86 struct C c; 87 struct D d; 88 int i; 89 89 }; 90 90 91 91 int main() { 92 // simple designation case - starting from beginning of structure, leaves ptr default-initialized (zero)93 struct A y0 = {94 .x DES 2,95 .y DES 396 };97 98 // simple initializaiton case - initialize all elements explicitly with no designations99 struct A y1 = {100 2, 3, 0101 };102 103 104 // use designation to move to member y, leaving x default-initialized (zero)105 struct A y2 = {106 .y DES 3,107 0108 };92 // simple designation case - starting from beginning of structure, leaves ptr default-initialized (zero) 93 struct A y0 = { 94 .x DES 2, 95 .y DES 3 96 }; 97 98 // simple initializaiton case - initialize all elements explicitly with no designations 99 struct A y1 = { 100 2, 3, 0 101 }; 102 103 104 // use designation to move to member y, leaving x default-initialized (zero) 105 struct A y2 = { 106 .y DES 3, 107 0 108 }; 109 109 110 110 #if ERROR 111 struct A yErr0 = {112 {} // error - empty scalar initializer is illegal113 };114 #endif 115 116 printf("=====A=====\n");117 printA(y0, 0);118 printA(y1, 0);119 printA(y2, 0);120 printf("=====A=====\n\n");121 122 // initialize only first element (z0.a.x), leaving everything else default-initialized (zero), no nested curly-braces123 struct B z0 = { 5 };124 125 // some nested curly braces, use designation to 'jump around' within structure, leaving some members default-initialized126 struct B z1 = {127 { 3 }, // z1.a0128 { 4 }, // z1.a1129 .a0 DES { 5 }, // z1.a0130 { 6 }, // z1.a1131 .a0.y DES 2, // z1.a0.y132 0, // z1.a0.ptr133 };134 135 // z2.a0.y and z2.a0.ptr default-initialized, everything else explicit136 struct B z2 = {137 { 1 },138 { 2, 3, 0 }139 };140 141 // initialize every member, omitting nested curly braces142 struct B z3 = {143 1, 2, 0, 4, 5, 0144 };145 146 // no initializer - legal C, but garbage values - don't print this one147 struct B z4;148 149 // no curly braces - initialize with object of same type150 struct B z5 = z2;151 152 // z6.a0.y and z6.a0.ptr default-initialized, everything else explicit.153 // no curly braces on z6.a1 initializers154 struct B z6 = {155 { 1 },156 2, 3, 0157 };158 159 printf("=====B=====\n");160 printB(z0, 0);161 printB(z1, 0);162 printB(z2, 0);163 printB(z3, 0);164 printB(z5, 0);165 printB(z6, 0);166 printf("=====B=====\n\n");167 168 // TODO: what about extra things in a nested init? are empty structs skipped??169 170 // test that initializing 'past array bound' correctly moves to next member.171 struct C c1 = {172 2, 3, 4, // arr173 5, 6, 0, // b.a0174 7, 8, 0, // b.a1175 };176 177 printf("=====C=====\n");178 printC(c1, 0);179 printf("=====C=====\n\n");111 struct A yErr0 = { 112 {} // error - empty scalar initializer is illegal 113 }; 114 #endif 115 116 printf("=====A=====\n"); 117 printA(y0, 0); 118 printA(y1, 0); 119 printA(y2, 0); 120 printf("=====A=====\n\n"); 121 122 // initialize only first element (z0.a.x), leaving everything else default-initialized (zero), no nested curly-braces 123 struct B z0 = { 5 }; 124 125 // some nested curly braces, use designation to 'jump around' within structure, leaving some members default-initialized 126 struct B z1 = { 127 { 3 }, // z1.a0 128 { 4 }, // z1.a1 129 .a0 DES { 5 }, // z1.a0 130 { 6 }, // z1.a1 131 .a0.y DES 2, // z1.a0.y 132 0, // z1.a0.ptr 133 }; 134 135 // z2.a0.y and z2.a0.ptr default-initialized, everything else explicit 136 struct B z2 = { 137 { 1 }, 138 { 2, 3, 0 } 139 }; 140 141 // initialize every member, omitting nested curly braces 142 struct B z3 = { 143 1, 2, 0, 4, 5, 0 144 }; 145 146 // no initializer - legal C, but garbage values - don't print this one 147 struct B z4; 148 149 // no curly braces - initialize with object of same type 150 struct B z5 = z2; 151 152 // z6.a0.y and z6.a0.ptr default-initialized, everything else explicit. 153 // no curly braces on z6.a1 initializers 154 struct B z6 = { 155 { 1 }, 156 2, 3, 0 157 }; 158 159 printf("=====B=====\n"); 160 printB(z0, 0); 161 printB(z1, 0); 162 printB(z2, 0); 163 printB(z3, 0); 164 printB(z5, 0); 165 printB(z6, 0); 166 printf("=====B=====\n\n"); 167 168 // TODO: what about extra things in a nested init? are empty structs skipped?? 169 170 // test that initializing 'past array bound' correctly moves to next member. 171 struct C c1 = { 172 2, 3, 4, // arr 173 5, 6, 0, // b.a0 174 7, 8, 0, // b.a1 175 }; 176 177 printf("=====C=====\n"); 178 printC(c1, 0); 179 printf("=====C=====\n\n"); 180 180 181 181 #if ERROR 182 // nested initializer can't refer to same type in C183 struct C cErr0 = { c1 };184 185 // must use curly braces to initialize members186 struct C cErr1 = 2;187 188 // can't initialize with array compound literal189 struct C cErr2 = {190 (int[3]) { 1, 2, 3 } // error: array initialized from non-constant array expression191 };182 // nested initializer can't refer to same type in C 183 struct C cErr0 = { c1 }; 184 185 // must use curly braces to initialize members 186 struct C cErr1 = 2; 187 188 // can't initialize with array compound literal 189 struct C cErr2 = { 190 (int[3]) { 1, 2, 3 } // error: array initialized from non-constant array expression 191 }; 192 192 #endif 193 193 194 194 #if WARNING 195 // can't initialize array with array - converts to int*196 int cWarn0_arr[3] = { 1, 2, 3 };197 struct C cWarn0 = {198 cWarn0_arr // warning: initialization makes integer from ptr without cast199 };200 #endif 201 202 // allowed to have 'too many' initialized lists - essentially they are ignored.203 int i1 = { 3 };204 205 // doesn't work yet.206 // designate unnamed object's members207 // struct D d = { .x DES 3 };195 // can't initialize array with array - converts to int* 196 int cWarn0_arr[3] = { 1, 2, 3 }; 197 struct C cWarn0 = { 198 cWarn0_arr // warning: initialization makes integer from ptr without cast 199 }; 200 #endif 201 202 // allowed to have 'too many' initialized lists - essentially they are ignored. 203 int i1 = { 3 }; 204 205 // doesn't work yet. 206 // designate unnamed object's members 207 // struct D d = { .x DES 3 }; 208 208 #if ERROR 209 struct D d1 = { .y DES 3 }; 210 #endif 211 212 // simple union initialization - initialized first member (e0.a) 213 union E e0 = { 214 y0 215 }; 216 217 // simple union initialization - initializes first member (e1.a) - with nested initializer list 218 union E e1 = { 219 { 2, 3, 0 } 220 }; 221 222 // simple union initialization - initializes first member (e2.a) - without nested initializer list 223 union E e2 = { 224 2, 3, 0 225 }; 226 227 // move cursor to e4.b.a0.x and initialize until e3.b.a1.ptr inclusive 228 union E e3 = { 229 .b.a0.x DES 2, 3, 0, 5, 6, 0 230 }; 231 232 printf("=====E=====\n"); 233 printA(e0.a, 0); 234 printA(e1.a, 0); 235 printA(e2.a, 0); 236 printB(e3.b, 0); 237 printf("=====E=====\n\n"); 209 struct D d1 = { .y DES 3 }; 210 #endif 211 212 // simple union initialization - initialized first member (e0.a) 213 union E e0 = { 214 y0 215 }; 216 217 // simple union initialization - initializes first member (e1.a) - with nested initializer list 218 union E e1 = { 219 { 2, 3, 0 } 220 }; 221 222 // simple union initialization - initializes first member (e2.a) - without nested initializer list 223 union E e2 = { 224 2, 3, 0 225 }; 226 227 // move cursor to e4.b.a0.x and initialize until e3.b.a1.ptr inclusive 228 union E e3 = { 229 .b.a0.x DES 2, 3, 0, 5, 6, 0 230 }; 231 232 printf("=====E=====\n"); 233 printA(e0.a, 0); 234 printA(e1.a, 0); 235 printA(e2.a, 0); 236 printB(e3.b, 0); 237 printf("=====E=====\n\n"); 238 239 // special case of initialization: char[] can be initialized with a string literal 240 const char * str0 = "hello"; 241 char str1[] = "hello"; 238 242 } 239 243
Note:
See TracChangeset
for help on using the changeset viewer.