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
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 29 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 36 35 int x, y; 36 int * ptr; 37 37 }; 38 38 void printA(struct A a, int level) { 39 40 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 45 struct A a0, a1; 46 46 }; 47 47 void printB(struct B b, int level) { 48 49 50 51 52 53 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 59 58 int arr[3]; 59 struct B b; 60 60 }; 61 61 void printC(struct C c, int level) { 62 63 64 65 66 67 68 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 74 75 73 struct { 74 int x; 75 }; 76 76 }; 77 77 void printD(struct D d, int level) { 78 79 78 indent(level); 79 printf("(D){ %d }\n", d.x); 80 80 } 81 81 82 82 // E tests unions 83 83 union E { 84 85 86 87 88 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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 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 112 113 114 #endif 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 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 183 184 185 186 187 188 189 190 191 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 196 197 198 199 200 #endif 201 202 203 204 205 206 207 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.