@@ -320,36 +320,80 @@ void c_typecheck_baset::typecheck_expr_main(exprt &expr)
320320 // these should only exist as constants,
321321 // and should already be typed
322322 }
323- else if (expr.id ()==ID_complex_real ||
324- expr.id ()==ID_complex_imag)
323+ else if (expr.id () == ID_complex_real)
325324 {
326- // get the subtype
327- assert (expr.operands ().size ()==1 );
328- const typet &op_type=follow (expr.op0 ().type ());
329- if (op_type.id ()!=ID_complex)
325+ INVARIANT (
326+ expr.operands ().size () == 1 ,
327+ " real part retrieval operation should have one operand" );
328+
329+ exprt op = expr.op0 ();
330+ op.type () = follow (op.type ());
331+
332+ if (op.type ().id () != ID_complex)
330333 {
331- if (!is_number (op_type ))
334+ if (!is_number (op. type () ))
332335 {
333- err_location (expr. op0 () );
334- error () << " real/imag expect numerical operand, "
335- << " but got `" << to_string (op_type ) << " '" << eom;
336+ err_location (op );
337+ error () << " real part retrieval expects numerical operand, "
338+ << " but got `" << to_string (op. type () ) << " '" << eom;
336339 throw 0 ;
337340 }
338341
339- // we could compile away, I suppose
340- expr.type ()=op_type;
341- expr.op0 ().make_typecast (complex_typet (op_type));
342+ typecast_exprt typecast_expr (op, complex_typet (op.type ()));
343+ complex_real_exprt complex_real_expr (typecast_expr);
344+
345+ expr.swap (complex_real_expr);
342346 }
343347 else
344348 {
345- expr. type ()=op_type. subtype ( );
349+ complex_real_exprt complex_real_expr (op );
346350
347351 // these are lvalues if the operand is one
348- if (expr.op0 ().get_bool (ID_C_lvalue))
349- expr.set (ID_C_lvalue, true );
352+ if (op.get_bool (ID_C_lvalue))
353+ complex_real_expr.set (ID_C_lvalue, true );
354+
355+ if (op.get_bool (ID_C_constant))
356+ complex_real_expr.set (ID_C_constant, true );
357+
358+ expr.swap (complex_real_expr);
359+ }
360+ }
361+ else if (expr.id () == ID_complex_imag)
362+ {
363+ INVARIANT (
364+ expr.operands ().size () == 1 ,
365+ " imaginary part retrieval operation should have one operand" );
366+
367+ exprt op = expr.op0 ();
368+ op.type () = follow (op.type ());
369+
370+ if (op.type ().id () != ID_complex)
371+ {
372+ if (!is_number (op.type ()))
373+ {
374+ err_location (op);
375+ error () << " real part retrieval expects numerical operand, "
376+ << " but got `" << to_string (op.type ()) << " '" << eom;
377+ throw 0 ;
378+ }
379+
380+ typecast_exprt typecast_expr (op, complex_typet (op.type ()));
381+ complex_imag_exprt complex_imag_expr (typecast_expr);
382+
383+ expr.swap (complex_imag_expr);
384+ }
385+ else
386+ {
387+ complex_imag_exprt complex_imag_expr (op);
388+
389+ // these are lvalues if the operand is one
390+ if (op.get_bool (ID_C_lvalue))
391+ complex_imag_expr.set (ID_C_lvalue, true );
392+
393+ if (op.get_bool (ID_C_constant))
394+ complex_imag_expr.set (ID_C_constant, true );
350395
351- if (expr.op0 ().get_bool (ID_C_constant))
352- expr.set (ID_C_constant, true );
396+ expr.swap (complex_imag_expr);
353397 }
354398 }
355399 else if (expr.id ()==ID_generic_selection)
0 commit comments