Changes in src/GenPoly/Lvalue.cc [b4f8808:6b8c4a8]
- File:
-
- 1 edited
-
src/GenPoly/Lvalue.cc (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
rb4f8808 r6b8c4a8 21 21 #include "Lvalue.h" 22 22 23 #include "InitTweak/InitTweak.h"24 23 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 25 24 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 26 25 #include "ResolvExpr/Unify.h" // for unify 27 26 #include "ResolvExpr/typeops.h" 27 #include "SymTab/Autogen.h" 28 28 #include "SymTab/Indexer.h" // for Indexer 29 29 #include "SynTree/Declaration.h" // for Declaration, FunctionDecl … … 33 33 #include "SynTree/Type.h" // for PointerType, Type, FunctionType 34 34 #include "SynTree/Visitor.h" // for Visitor, acceptAll 35 #include "Validate/FindSpecialDecls.h" // for dereferenceOperator36 35 37 36 #if 0 … … 45 44 // TODO: fold this into the general createDeref function?? 46 45 Expression * mkDeref( Expression * arg ) { 47 if ( Validate::dereferenceOperator ) {46 if ( SymTab::dereferenceOperator ) { 48 47 // note: reference depth can be arbitrarily deep here, so peel off the outermost pointer/reference, not just pointer because they are effecitvely equivalent in this pass 49 VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator );48 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 50 49 deref->result = new PointerType( Type::Qualifiers(), deref->result ); 51 50 Type * base = InitTweak::getPointerBase( arg->result ); … … 54 53 delete ret->result; 55 54 ret->result = base->clone(); 55 ret->result->set_lvalue( true ); 56 56 return ret; 57 57 } else { … … 146 146 147 147 namespace { 148 // true for intrinsic function calls that return a n lvalue in C148 // true for intrinsic function calls that return a reference 149 149 bool isIntrinsicReference( Expression * expr ) { 150 // known intrinsic-reference prelude functions151 static std::set<std::string> lvalueFunctions = { "*?", "?[?]" };152 150 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 153 151 std::string fname = InitTweak::getFunctionName( untyped ); 154 return lvalueFunctions.count(fname); 152 // known intrinsic-reference prelude functions 153 return fname == "*?" || fname == "?[?]"; 155 154 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 156 155 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 157 return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name); 156 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 157 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 158 Type * ret = ftype->returnVals.empty() ? nullptr : ftype->returnVals.front()->get_type(); 159 return func->linkage == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 158 160 } 159 161 } … … 166 168 ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result ); 167 169 appExpr->result = result->base->clone(); 170 appExpr->result->set_lvalue( true ); 168 171 if ( ! inIntrinsic ) { 169 172 // when not in an intrinsic function, add a cast to … … 194 197 unsigned int i = 0; 195 198 const unsigned int end = ftype->parameters.size(); 196 197 /// The for loop may eagerly dereference the iterators and fail on empty lists198 if(i == end) { return appExpr; }199 199 for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) { 200 if (i == end) break; 200 201 Expression *& arg = std::get<0>( p ); 201 202 Type * formal = std::get<1>( p )->get_type(); … … 211 212 // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation. 212 213 213 if ( function-> linkage!= LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {214 if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) { 214 215 // needed for definition of prelude functions, etc. 215 216 // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address … … 227 228 arg = new AddressExpr( arg ); 228 229 // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) { 229 } else if ( function-> linkage== LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {230 } else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) { 230 231 // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument 231 232 PRINT( … … 242 243 } 243 244 ++i; 244 if (i == end) break;245 245 } 246 246 } … … 355 355 Type * destType = castExpr->result; 356 356 Type * srcType = castExpr->arg->result; 357 assertf( destType, "Cast to no type in: %s", toCString( castExpr ) );358 assertf( srcType, "Cast from no type in: %s", toCString( castExpr ) );359 357 int depth1 = destType->referenceDepth(); 360 358 int depth2 = srcType->referenceDepth(); 361 359 int diff = depth1 - depth2; 362 360 363 if ( diff > 0 && ! castExpr->arg->get_lvalue() ) {361 if ( diff > 0 && ! srcType->get_lvalue() ) { 364 362 // rvalue to reference conversion -- introduce temporary 365 363 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. … … 405 403 ret = new AddressExpr( ret ); 406 404 } 407 if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {405 if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) { 408 406 // must keep cast if cast-to type is different from the actual type 409 407 castExpr->arg = ret; … … 434 432 delete ret->result; 435 433 ret->result = castExpr->result; 436 assert( ret->get_lvalue()); // ensure result is lvalue434 ret->result->set_lvalue( true ); // ensure result is lvalue 437 435 castExpr->env = nullptr; 438 436 castExpr->arg = nullptr;
Note:
See TracChangeset
for help on using the changeset viewer.