* In eval(), don't use the target value `v' as a temporary.
Overwriting `v' breaks when the expression evaluation to an assertion failure or throw.
This commit is contained in:
		
							parent
							
								
									a5ece7d016
								
							
						
					
					
						commit
						a353aef0b1
					
				
					 1 changed files with 17 additions and 13 deletions
				
			
		|  | @ -369,10 +369,11 @@ void EvalState::eval(Env & env, Expr e, Value & v) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (matchSelect(e, e2, name)) { |     else if (matchSelect(e, e2, name)) { | ||||||
|         eval(env, e2, v); |         Value v2; | ||||||
|         forceAttrs(v); // !!! eval followed by force is slightly inefficient
 |         eval(env, e2, v2); | ||||||
|         Bindings::iterator i = v.attrs->find(name); |         forceAttrs(v2); // !!! eval followed by force is slightly inefficient
 | ||||||
|         if (i == v.attrs->end()) |         Bindings::iterator i = v2.attrs->find(name); | ||||||
|  |         if (i == v2.attrs->end()) | ||||||
|             throwEvalError("attribute `%1%' missing", aterm2String(name)); |             throwEvalError("attribute `%1%' missing", aterm2String(name)); | ||||||
|         try {             |         try {             | ||||||
|             forceValue(i->second); |             forceValue(i->second); | ||||||
|  | @ -391,10 +392,11 @@ void EvalState::eval(Env & env, Expr e, Value & v) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (matchCall(e, fun, arg)) { |     else if (matchCall(e, fun, arg)) { | ||||||
|         eval(env, fun, v); |         Value vFun; | ||||||
|  |         eval(env, fun, vFun); | ||||||
|         Value vArg; |         Value vArg; | ||||||
|         mkThunk(vArg, env, arg); // !!! should this be on the heap?
 |         mkThunk(vArg, env, arg); // !!! should this be on the heap?
 | ||||||
|         callFunction(v, vArg, v); |         callFunction(vFun, vArg, v); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else if (matchWith(e, attrs, body, pos)) { |     else if (matchWith(e, attrs, body, pos)) { | ||||||
|  | @ -446,9 +448,10 @@ void EvalState::eval(Env & env, Expr e, Value & v) | ||||||
|         std::ostringstream s; |         std::ostringstream s; | ||||||
|          |          | ||||||
|         bool first = true, isPath = false; |         bool first = true, isPath = false; | ||||||
|  |         Value vStr; | ||||||
|          |          | ||||||
|         for (ATermIterator i(es); i; ++i) { |         for (ATermIterator i(es); i; ++i) { | ||||||
|             eval(env, *i, v); |             eval(env, *i, vStr); | ||||||
| 
 | 
 | ||||||
|             /* If the first element is a path, then the result will
 |             /* If the first element is a path, then the result will
 | ||||||
|                also be a path, we don't copy anything (yet - that's |                also be a path, we don't copy anything (yet - that's | ||||||
|  | @ -456,11 +459,11 @@ void EvalState::eval(Env & env, Expr e, Value & v) | ||||||
|                in a derivation), and none of the strings are allowed |                in a derivation), and none of the strings are allowed | ||||||
|                to have contexts. */ |                to have contexts. */ | ||||||
|             if (first) { |             if (first) { | ||||||
|                 isPath = v.type == tPath; |                 isPath = vStr.type == tPath; | ||||||
|                 first = false; |                 first = false; | ||||||
|             } |             } | ||||||
|              |              | ||||||
|             s << coerceToString(v, context, false, !isPath); |             s << coerceToString(vStr, context, false, !isPath); | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if (isPath && !context.empty()) |         if (isPath && !context.empty()) | ||||||
|  | @ -514,9 +517,10 @@ void EvalState::eval(Env & env, Expr e, Value & v) | ||||||
| 
 | 
 | ||||||
|     /* Attribute existence test (?). */ |     /* Attribute existence test (?). */ | ||||||
|     else if (matchOpHasAttr(e, e1, name)) { |     else if (matchOpHasAttr(e, e1, name)) { | ||||||
|         eval(env, e1, v); |         Value vAttrs; | ||||||
|         forceAttrs(v); |         eval(env, e1, vAttrs); | ||||||
|         mkBool(v, v.attrs->find(name) != v.attrs->end()); |         forceAttrs(vAttrs); | ||||||
|  |         mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     else throw Error("unsupported term"); |     else throw Error("unsupported term"); | ||||||
|  | @ -660,7 +664,7 @@ void EvalState::strictEval(Expr e, Value & v) | ||||||
| void EvalState::forceValue(Value & v) | void EvalState::forceValue(Value & v) | ||||||
| { | { | ||||||
|     if (v.type == tThunk) { |     if (v.type == tThunk) { | ||||||
|         v.type = tBlackhole; |         //v.type = tBlackhole;
 | ||||||
|         eval(*v.thunk.env, v.thunk.expr, v); |         eval(*v.thunk.env, v.thunk.expr, v); | ||||||
|     } |     } | ||||||
|     else if (v.type == tCopy) { |     else if (v.type == tCopy) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue