Changeset b067d9b for src/GenPoly/Lvalue.cc
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
r7951100 rb067d9b 21 21 #include "Lvalue.h" 22 22 23 #include "InitTweak/InitTweak.h" 23 24 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 24 25 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 25 26 #include "ResolvExpr/Unify.h" // for unify 26 27 #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 dereferenceOperator 35 36 36 37 #if 0 … … 44 45 // TODO: fold this into the general createDeref function?? 45 46 Expression * mkDeref( Expression * arg ) { 46 if ( SymTab::dereferenceOperator ) {47 if ( Validate::dereferenceOperator ) { 47 48 // 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 48 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );49 VariableExpr * deref = new VariableExpr( Validate::dereferenceOperator ); 49 50 deref->result = new PointerType( Type::Qualifiers(), deref->result ); 50 51 Type * base = InitTweak::getPointerBase( arg->result ); … … 53 54 delete ret->result; 54 55 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 reference148 // true for intrinsic function calls that return an lvalue in C 149 149 bool isIntrinsicReference( Expression * expr ) { 150 // known intrinsic-reference prelude functions 151 static std::set<std::string> lvalueFunctions = { "*?", "?[?]" }; 150 152 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 151 153 std::string fname = InitTweak::getFunctionName( untyped ); 152 // known intrinsic-reference prelude functions 153 return fname == "*?" || fname == "?[?]"; 154 return lvalueFunctions.count(fname); 154 155 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 155 156 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 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 ); 157 return func->linkage == LinkageSpec::Intrinsic && lvalueFunctions.count(func->name); 160 158 } 161 159 } … … 168 166 ReferenceType * result = strict_dynamic_cast< ReferenceType * >( appExpr->result ); 169 167 appExpr->result = result->base->clone(); 170 appExpr->result->set_lvalue( true );171 168 if ( ! inIntrinsic ) { 172 169 // when not in an intrinsic function, add a cast to … … 197 194 unsigned int i = 0; 198 195 const unsigned int end = ftype->parameters.size(); 196 197 /// The for loop may eagerly dereference the iterators and fail on empty lists 198 if(i == end) { return appExpr; } 199 199 for ( auto p : unsafe_group_iterate( appExpr->args, ftype->parameters ) ) { 200 if (i == end) break;201 200 Expression *& arg = std::get<0>( p ); 202 201 Type * formal = std::get<1>( p )->get_type(); … … 212 211 // TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation. 213 212 214 if ( function-> get_linkage()!= LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {213 if ( function->linkage != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) { 215 214 // needed for definition of prelude functions, etc. 216 215 // if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address … … 228 227 arg = new AddressExpr( arg ); 229 228 // } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) { 230 } else if ( function-> get_linkage()== LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {229 } else if ( function->linkage == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) { 231 230 // argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument 232 231 PRINT( … … 243 242 } 244 243 ++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 ) ); 357 359 int depth1 = destType->referenceDepth(); 358 360 int depth2 = srcType->referenceDepth(); 359 361 int diff = depth1 - depth2; 360 362 361 if ( diff > 0 && ! srcType->get_lvalue() ) {363 if ( diff > 0 && ! castExpr->arg->get_lvalue() ) { 362 364 // rvalue to reference conversion -- introduce temporary 363 365 // know that reference depth of cast argument is 0, need to introduce n temporaries for reference depth of n, e.g. … … 403 405 ret = new AddressExpr( ret ); 404 406 } 405 if ( srcType->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) {407 if ( castExpr->arg->get_lvalue() && ! ResolvExpr::typesCompatible( srcType, strict_dynamic_cast<ReferenceType *>( destType )->base, SymTab::Indexer() ) ) { 406 408 // must keep cast if cast-to type is different from the actual type 407 409 castExpr->arg = ret; … … 432 434 delete ret->result; 433 435 ret->result = castExpr->result; 434 ret->result->set_lvalue( true); // ensure result is lvalue436 assert( ret->get_lvalue() ); // ensure result is lvalue 435 437 castExpr->env = nullptr; 436 438 castExpr->arg = nullptr;
Note:
See TracChangeset
for help on using the changeset viewer.