Changes in / [d2034b4:c5ce0ec]
- Location:
- src
- Files:
-
- 5 edited
-
Common/Debug.h (modified) (1 diff)
-
Common/SemanticError.h (modified) (2 diffs)
-
GenPoly/Lvalue.cc (modified) (13 diffs)
-
tests/.expect/references.txt (modified) (1 diff)
-
tests/references.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Debug.h
rd2034b4 rc5ce0ec 28 28 namespace Debug { 29 29 /// debug codegen a translation unit 30 static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label , LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler) {30 static inline void codeGen( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label ) { 31 31 #ifdef DEBUG 32 32 std::list< Declaration * > decls; 33 33 34 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), [ linkageFilter]( Declaration * decl ) {35 return ! (decl->linkage & linkageFilter);34 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), []( Declaration * decl ) { 35 return ! LinkageSpec::isBuiltin( decl->get_linkage() ); 36 36 }); 37 37 38 38 std::cerr << "======" << label << "======" << std::endl; 39 CodeGen::generate( decls, std::cerr, true, true );39 CodeGen::generate( decls, std::cerr, false, true ); 40 40 #endif 41 41 } // dump 42 42 43 static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label , LinkageSpec::Spec linkageFilter = LinkageSpec::Compiler) {43 static inline void treeDump( __attribute__((unused)) const std::list< Declaration * > & translationUnit, __attribute__((unused)) const std::string & label ) { 44 44 #ifdef DEBUG 45 45 std::list< Declaration * > decls; 46 46 47 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), [ linkageFilter]( Declaration * decl ) {48 return ! (decl->linkage & linkageFilter);47 filter( translationUnit.begin(), translationUnit.end(), back_inserter( decls ), []( Declaration * decl ) { 48 return ! LinkageSpec::isBuiltin( decl->get_linkage() ); 49 49 }); 50 50 -
src/Common/SemanticError.h
rd2034b4 rc5ce0ec 38 38 constexpr const char * const WarningFormats[] = { 39 39 "self assignment of expression: %s", 40 "rvalue to reference conversion of rvalue: %s",41 40 }; 42 41 43 42 enum class Warning { 44 43 SelfAssignment, 45 RvalueToReferenceConversion,46 44 NUMBER_OF_WARNINGS, //This MUST be the last warning 47 45 }; … … 52 50 ); 53 51 54 // ## used here to allow empty __VA_ARGS__ 55 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id], ## __VA_ARGS__) 52 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id], __VA_ARGS__) 56 53 57 54 void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4))); -
src/GenPoly/Lvalue.cc
rd2034b4 rc5ce0ec 59 59 } 60 60 61 struct ReferenceConversions final : public WithStmtsToAdd{61 struct ReferenceConversions final { 62 62 Expression * postmutate( CastExpr * castExpr ); 63 63 Expression * postmutate( AddressExpr * addrExpr ); … … 114 114 } 115 115 116 void convertLvalue( std::list< Declaration* > & translationUnit ) {116 void convertLvalue( std::list< Declaration* >& translationUnit ) { 117 117 PassVisitor<ReferenceConversions> refCvt; 118 118 PassVisitor<ReferenceTypeElimination> elim; … … 150 150 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 151 151 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 152 Type * ret = ftype-> returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type();153 return func-> linkage== LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );152 Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type(); 153 return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 154 154 } 155 155 } … … 160 160 if ( isIntrinsicReference( appExpr ) ) { 161 161 // eliminate reference types from intrinsic applications - now they return lvalues 162 Type * result = appExpr-> result;163 appExpr-> result = result->stripReferences()->clone();164 appExpr-> result->set_lvalue( true );162 Type * result = appExpr->get_result(); 163 appExpr->set_result( result->stripReferences()->clone() ); 164 appExpr->get_result()->set_lvalue( true ); 165 165 if ( ! inIntrinsic ) { 166 166 // when not in an intrinsic function, add a cast to 167 167 // don't add cast when in an intrinsic function, since they already have the cast 168 168 Expression * ret = new CastExpr( appExpr, result ); 169 std::swap( ret->env, appExpr->env ); 169 ret->set_env( appExpr->get_env() ); 170 appExpr->set_env( nullptr ); 170 171 return ret; 171 172 } … … 186 187 assertf( ftype, "Function declaration does not have function type." ); 187 188 // can be of differing lengths only when function is variadic 188 assertf( ftype-> parameters.size() == appExpr->args.size() || ftype->isVarArgs, "ApplicationExpr args do not match formal parameter type." );189 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." ); 189 190 190 191 191 192 unsigned int i = 0; 192 const unsigned int end = ftype-> parameters.size();193 for ( auto p : unsafe_group_iterate( appExpr-> args, ftype->parameters) ) {193 const unsigned int end = ftype->get_parameters().size(); 194 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) { 194 195 if (i == end) break; 195 196 Expression *& arg = std::get<0>( p ); … … 211 212 // std::cerr << "===adding deref to arg" << std::endl; 212 213 // if the parameter is a reference, add a dereference to the reference-typed argument. 213 Type * baseType = InitTweak::getPointerBase( arg-> result);214 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg-> result).c_str() );214 Type * baseType = InitTweak::getPointerBase( arg->get_result() ); 215 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() ); 215 216 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 216 delete arg-> result;217 delete arg->get_result(); 217 218 arg->set_result( ptrType ); 218 219 arg = mkDeref( arg ); … … 248 249 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 249 250 if ( refDepth == 0 ) { 250 if ( ! isIntrinsicReference( addrExpr-> arg) ) {251 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 251 252 // try to avoid ?[?] 252 refDepth = addrExpr-> arg->result->referenceDepth();253 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 253 254 } 254 255 } … … 279 280 // pointer casts in the right places. 280 281 281 // Note: reference depth difference is the determining factor in what code is run, rather than whether something is 282 // reference type or not, since conversion still needs to occur when both types are references that differ in depth. 283 284 Type * destType = castExpr->result; 285 Type * srcType = castExpr->arg->result; 286 int depth1 = destType->referenceDepth(); 287 int depth2 = srcType->referenceDepth(); 288 int diff = depth1 - depth2; 289 290 if ( diff > 0 && ! srcType->get_lvalue() ) { 291 // rvalue to reference conversion -- introduce temporary 292 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. 293 // (int &&&)3; 294 // becomes 295 // int __ref_tmp_0 = 3; 296 // int & __ref_tmp_1 = _&_ref_tmp_0; 297 // int && __ref_tmp_2 = &__ref_tmp_1; 298 // &__ref_tmp_2; 299 // the last & comes from the remaining reference conversion code 300 SemanticWarning( castExpr->arg->location, Warning::RvalueToReferenceConversion, toCString( castExpr->arg ) ); 301 302 static UniqueName tempNamer( "__ref_tmp_" ); 303 ObjectDecl * temp = ObjectDecl::newObject( tempNamer.newName(), castExpr->arg->result->clone(), new SingleInit( castExpr->arg ) ); 304 PRINT( std::cerr << "made temp: " << temp << std::endl; ) 305 stmtsToAddBefore.push_back( new DeclStmt( temp ) ); 306 for ( int i = 0; i < depth1-1; i++ ) { // xxx - maybe this should be diff-1? check how this works with reference type for srcType 307 ObjectDecl * newTemp = ObjectDecl::newObject( tempNamer.newName(), new ReferenceType( Type::Qualifiers(), temp->type->clone() ), new SingleInit( new AddressExpr( new VariableExpr( temp ) ) ) ); 308 PRINT( std::cerr << "made temp" << i << ": " << newTemp << std::endl; ) 309 stmtsToAddBefore.push_back( new DeclStmt( newTemp ) ); 310 temp = newTemp; 311 } 312 // update diff so that remaining code works out correctly 313 castExpr->arg = new VariableExpr( temp ); 314 PRINT( std::cerr << "update cast to: " << castExpr << std::endl; ) 315 srcType = castExpr->arg->result; 316 depth2 = srcType->referenceDepth(); 317 diff = depth1 - depth2; 318 assert( diff == 1 ); 319 } 320 321 // handle conversion between different depths 322 PRINT ( 323 if ( depth1 || depth2 ) { 324 std::cerr << "destType: " << destType << " / srcType: " << srcType << std::endl; 325 std::cerr << "depth: " << depth1 << " / " << depth2 << std::endl; 326 } 327 ) 328 if ( diff > 0 ) { 329 // conversion to type with more depth (e.g. int & -> int &&): add address-of for each level of difference 282 // conversion to reference type 283 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) { 284 (void)refType; 285 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 286 // nothing to do if casting from reference to reference. 287 (void)otherRef; 288 PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; ) 289 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 290 Expression * callExpr = castExpr->get_arg(); 291 PRINT( 292 std::cerr << "but arg is deref -- &" << std::endl; 293 std::cerr << callExpr << std::endl; 294 ) 295 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 296 delete callExpr->get_result(); 297 callExpr->set_result( refType->clone() ); 298 // move environment out to new top-level 299 callExpr->set_env( castExpr->get_env() ); 300 castExpr->set_arg( nullptr ); 301 castExpr->set_env( nullptr ); 302 delete castExpr; 303 return callExpr; 304 } 305 int depth1 = refType->referenceDepth(); 306 int depth2 = otherRef->referenceDepth(); 307 int diff = depth1-depth2; 308 if ( diff == 0 ) { 309 // conversion between references of the same depth 310 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 311 PRINT( std::cerr << castExpr << std::endl; ) 312 return castExpr; 313 } else if ( diff < 0 ) { 314 // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences 315 Expression * ret = castExpr->arg; 316 for ( int i = 0; i < diff; ++i ) { 317 ret = mkDeref( ret ); 318 } 319 ret->env = castExpr->env; 320 delete ret->result; 321 ret->result = castExpr->result; 322 ret->result->set_lvalue( true ); // ensure result is lvalue 323 castExpr->env = nullptr; 324 castExpr->arg = nullptr; 325 castExpr->result = nullptr; 326 delete castExpr; 327 return ret; 328 } else if ( diff > 0 ) { 329 // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of 330 Expression * ret = castExpr->arg; 331 for ( int i = 0; i < diff; ++i ) { 332 ret = new AddressExpr( ret ); 333 } 334 ret->env = castExpr->env; 335 delete ret->result; 336 ret->result = castExpr->result; 337 castExpr->env = nullptr; 338 castExpr->arg = nullptr; 339 castExpr->result = nullptr; 340 delete castExpr; 341 return ret; 342 } 343 344 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 345 PRINT( std::cerr << castExpr << std::endl; ) 346 return castExpr; 347 } else if ( castExpr->arg->result->get_lvalue() ) { 348 // conversion from lvalue to reference 349 // xxx - keep cast, but turn into pointer cast?? 350 // xxx - memory 351 PRINT( 352 std::cerr << "convert lvalue to reference -- &" << std::endl; 353 std::cerr << castExpr->arg << std::endl; 354 ) 355 AddressExpr * ret = new AddressExpr( castExpr->arg ); 356 if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) { 357 // must keep cast if cast-to type is different from the actual type 358 castExpr->arg = ret; 359 return castExpr; 360 } 361 ret->env = castExpr->env; 362 delete ret->result; 363 ret->result = castExpr->result; 364 castExpr->env = nullptr; 365 castExpr->arg = nullptr; 366 castExpr->result = nullptr; 367 delete castExpr; 368 return ret; 369 } else { 370 // rvalue to reference conversion -- introduce temporary 371 } 372 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 373 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 374 (void)refType; 375 // conversion from reference to rvalue 376 PRINT( 377 std::cerr << "convert reference to rvalue -- *" << std::endl; 378 std::cerr << "was = " << castExpr << std::endl; 379 ) 330 380 Expression * ret = castExpr->arg; 331 for ( int i = 0; i < diff; ++i ) { 332 ret = new AddressExpr( ret ); 333 } 334 if ( srcType->get_lvalue() && srcType->get_qualifiers() != strict_dynamic_cast<ReferenceType *>( destType )->base->get_qualifiers() ) { 335 // must keep cast if cast-to type is different from the actual type 336 castExpr->arg = ret; 337 return castExpr; 338 } 339 ret->env = castExpr->env; 340 delete ret->result; 341 ret->result = castExpr->result; 342 castExpr->env = nullptr; 343 castExpr->arg = nullptr; 344 castExpr->result = nullptr; 345 delete castExpr; 346 return ret; 347 } else if ( diff < 0 ) { 348 // conversion to type with less depth (e.g. int && -> int &): add dereferences for each level of difference 349 diff = -diff; // care only about magnitude now 350 Expression * ret = castExpr->arg; 351 for ( int i = 0; i < diff; ++i ) { 381 TypeSubstitution * env = castExpr->env; 382 castExpr->set_env( nullptr ); 383 if ( ! isIntrinsicReference( ret ) ) { 384 // dereference if not already dereferenced 352 385 ret = mkDeref( ret ); 353 386 } 354 if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) { 387 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) { 388 // can remove cast if types are compatible, changing expression type to value type 389 ret->result = castExpr->result->clone(); 390 ret->result->set_lvalue( true ); // ensure result is lvalue 391 castExpr->arg = nullptr; 392 delete castExpr; 393 } else { 355 394 // must keep cast if types are different 356 395 castExpr->arg = ret; 357 return castExpr; 358 } 359 ret->env = castExpr->env; 360 delete ret->result; 361 ret->result = castExpr->result; 362 ret->result->set_lvalue( true ); // ensure result is lvalue 363 castExpr->env = nullptr; 364 castExpr->arg = nullptr; 365 castExpr->result = nullptr; 366 delete castExpr; 396 ret = castExpr; 397 } 398 ret->set_env( env ); 399 PRINT( std::cerr << "now: " << ret << std::endl; ) 367 400 return ret; 368 } else { 369 assert( diff == 0 ); 370 // conversion between references of the same depth 371 return castExpr; 372 } 401 } 402 return castExpr; 373 403 } 374 404 375 405 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 376 Type * base = refType-> base;406 Type * base = refType->get_base(); 377 407 Type::Qualifiers qualifiers = refType->get_qualifiers(); 378 refType-> base = nullptr;408 refType->set_base( nullptr ); 379 409 delete refType; 380 410 return new PointerType( qualifiers, base ); … … 384 414 Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) { 385 415 if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) { 386 Expression * arg1 = commaExpr-> arg1->clone();387 Expression * arg2 = commaExpr-> arg2->clone();416 Expression * arg1 = commaExpr->get_arg1()->clone(); 417 Expression * arg2 = commaExpr->get_arg2()->clone(); 388 418 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) ); 389 ret-> env = expr->env;390 expr-> env = nullptr;419 ret->set_env( expr->get_env() ); 420 expr->set_env( nullptr ); 391 421 delete expr; 392 422 return ret; 393 423 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) { 394 Expression * arg1 = condExpr-> arg1->clone();395 Expression * arg2 = condExpr-> arg2->clone();396 Expression * arg3 = condExpr-> arg3->clone();424 Expression * arg1 = condExpr->get_arg1()->clone(); 425 Expression * arg2 = condExpr->get_arg2()->clone(); 426 Expression * arg3 = condExpr->get_arg3()->clone(); 397 427 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) ); 398 ret-> env = expr->env;399 expr-> env = nullptr;428 ret->set_env( expr->get_env() ); 429 expr->set_env( nullptr ); 400 430 delete expr; 401 431 … … 406 436 AssertionSet needAssertions, haveAssertions; 407 437 OpenVarSet openVars; 408 unify( ret-> arg2->result, ret->arg3->result, newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );409 ret-> result = commonType ? commonType : ret->arg2->result->clone();438 unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType ); 439 ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() ); 410 440 return ret; 411 441 } … … 414 444 415 445 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) { 416 return applyTransformation( memExpr, memExpr-> aggregate, [=]( Expression * aggr ) { return new MemberExpr( memExpr->member, aggr ); } );446 return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } ); 417 447 } 418 448 419 449 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 420 return applyTransformation( addrExpr, addrExpr-> arg, []( Expression * arg ) { return new AddressExpr( arg ); } );450 return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } ); 421 451 } 422 452 423 453 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 424 Expression * arg = addrExpr-> arg;454 Expression * arg = addrExpr->get_arg(); 425 455 if ( isIntrinsicReference( arg ) ) { 426 456 std::string fname = InitTweak::getFunctionName( arg ); … … 428 458 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 429 459 Expression * ret = arg0; 430 ret->set_env( addrExpr-> env);460 ret->set_env( addrExpr->get_env() ); 431 461 arg0 = nullptr; 432 addrExpr-> env = nullptr;462 addrExpr->set_env( nullptr ); 433 463 delete addrExpr; 434 464 return ret; … … 457 487 // } 458 488 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) { 459 Expression * ret = addrExpr-> arg;460 ret-> env = appExpr->env;461 addrExpr-> arg = nullptr;462 appExpr-> env = nullptr;489 Expression * ret = addrExpr->get_arg(); 490 ret->set_env( appExpr->get_env() ); 491 addrExpr->set_arg( nullptr ); 492 appExpr->set_env( nullptr ); 463 493 delete appExpr; 464 494 return ret; -
src/tests/.expect/references.txt
rd2034b4 rc5ce0ec 28 28 Destructing a Y 29 29 Destructing a Y 30 3 331 332 333 3 9 { 1, 7 }, [1, 2, 3]34 30 Destructing a Y 35 31 Destructing a Y -
src/tests/references.c
rd2034b4 rc5ce0ec 49 49 &r1 = x, &&r2 = r1, &&&r3 = r2; 50 50 ***p3 = 3; // change x 51 // ((int&)r3 = 3; // change x, ***r352 51 **p3 = &x; // change p1 53 // ((int*&)&r3) = &x; // change r1, (&*)**r354 52 *p3 = &p1; // change p2 55 // ((int**&)&&r3) = &p2; // change r2, (&(&*)*)*r356 // ((int***&)&&&r3) = p3; // change r3 to p3, (&(&(&*)*)*)r357 53 int y = 0, z = 11, & ar[3] = { x, y, z }; // initialize array of references 58 // &ar[1] = &z; // change reference array element59 // typeof( ar[1] ) p; // is int, i.e., the type of referenced object60 // typeof( &ar[1] ) q; // is int &, i.e., the type of reference61 // sizeof( ar[1] ) == sizeof( int ); // is true, i.e., the size of referenced object62 // sizeof( &ar[1] ) == sizeof( int *); // is true, i.e., the size of a reference63 54 64 55 // test that basic reference properties are true - r1 should be an alias for x … … 85 76 &z1.r = &z1r; 86 77 &z2.r = &z2r; 87 88 78 z1 = z2; 89 90 // test rvalue-to-reference conversion91 {92 struct S { double x, y; };93 void f( int & i, int & j, S & s, int v[] ) {94 printf("%d %d { %g, %g }, [%d, %d, %d]\n", i, j, s.[x, y], v[0], v[1], v[2]);95 }96 void g(int & i) { printf("%d\n", i); }97 void h(int &&& i) { printf("%d\n", i); }98 99 int &&& r = 3; // rvalue to reference100 int i = r;101 printf("%d %d\n", i, r); // both 3102 103 g( 3 ); // rvalue to reference104 h( (int &&&)3 ); // rvalue to reference105 106 int a = 5, b = 4;107 f( 3, a + b, (S){ 1.0, 7.0 }, (int [3]){ 1, 2, 3 } ); // two rvalue to reference108 }109 79 } 110 80
Note:
See TracChangeset
for help on using the changeset viewer.