// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/evaluate.c
// Function: evaluate_conditional_expression
static struct symbol *evaluate_conditional_expression(struct expression *expr)
{
	struct expression **cond;
	struct symbol *ctype, *ltype, *rtype, *lbase, *rbase;
	int lclass, rclass;
	const char * typediff;
	int qual;

	if (!evaluate_conditional(expr->conditional, 0))
		return NULL;
	if (!evaluate_expression(expr->cond_false))
		return NULL;

	ctype = degenerate(expr->conditional);
	rtype = degenerate(expr->cond_false);

	cond = &expr->conditional;
	ltype = ctype;
	if (expr->cond_true) {
		if (!evaluate_expression(expr->cond_true))
			return NULL;
		ltype = degenerate(expr->cond_true);
		cond = &expr->cond_true;
	}

	expr->flags = (expr->conditional->flags & (*cond)->flags &
			expr->cond_false->flags & ~CEF_CONST_MASK);
	/*
	 * In the standard, it is defined that an integer constant expression
	 * shall only have operands that are themselves constant [6.6(6)].
	 * While this definition is very clear for expressions that need all
	 * their operands to be evaluated, for conditional expressions with a
	 * constant condition things are much less obvious.
	 * So, as an extension, do the same as GCC seems to do:
	 *	Consider a conditional expression with a constant condition
	 *	as having the same constantness as the argument corresponding
	 *	to the truth value (including in the case of address constants
	 *	which are defined more stricly [6.6(9)]).
	 */
	if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) {
		int is_true = expr_truth_value(expr->conditional);
		struct expression *arg = is_true ? *cond : expr->cond_false;
		expr->flags = arg->flags & ~CEF_CONST_MASK;
	}

	lclass = classify_type(ltype, &ltype);
	rclass = classify_type(rtype, &rtype);
	if (lclass & rclass & TYPE_NUM) {
		ctype = usual_conversions('?', *cond, expr->cond_false,
					  lclass, rclass, ltype, rtype);
		*cond = cast_to(*cond, ctype);
		expr->cond_false = cast_to(expr->cond_false, ctype);
		goto out;
	}

	if ((lclass | rclass) & TYPE_PTR) {
		int is_null1 = is_null_pointer_constant(*cond);
		int is_null2 = is_null_pointer_constant(expr->cond_false);

		if (is_null1 && is_null2) {
			*cond = cast_to(*cond, &ptr_ctype);
			expr->cond_false = cast_to(expr->cond_false, &ptr_ctype);
			ctype = &ptr_ctype;
			goto out;
		}
		if (is_null1 && (rclass & TYPE_PTR)) {
			if (is_null1 == NULL_ZERO)
				bad_null(*cond);
			*cond = cast_to(*cond, rtype);
			ctype = rtype;
			goto out;
		}
		if (is_null2 && (lclass & TYPE_PTR)) {
			if (is_null2 == NULL_ZERO)
				bad_null(expr->cond_false);
			expr->cond_false = cast_to(expr->cond_false, ltype);
			ctype = ltype;
			goto out;
		}
		if (!(lclass & rclass & TYPE_PTR)) {
			typediff = "different types";
			goto Err;
		}
		/* OK, it's pointer on pointer */
		if (ltype->ctype.as != rtype->ctype.as) {
			typediff = "different address spaces";
			goto Err;
		}

		/* need to be lazier here */
		lbase = examine_pointer_target(ltype);
		rbase = examine_pointer_target(rtype);
		qual = target_qualifiers(ltype) | target_qualifiers(rtype);

		if (lbase == &void_ctype) {
			/* XXX: pointers to function should warn here */
			ctype = ltype;
			goto Qual;

		}
		if (rbase == &void_ctype) {
			/* XXX: pointers to function should warn here */
			ctype = rtype;
			goto Qual;
		}
		/* XXX: that should be pointer to composite */
		ctype = ltype;
		typediff = type_difference(&ltype->ctype, &rtype->ctype,
					   qual, qual);
		if (!typediff)
			goto Qual;
		goto Err;
	}

	/* void on void, struct on same struct, union on same union */
	if (ltype == rtype) {
		ctype = ltype;
		goto out;
	}
	typediff = "different base types";

Err:
	expression_error(expr, "incompatible types in conditional expression (%s):", typediff);
	info(expr->pos, "   %s", show_typename(ltype));
	info(expr->pos, "   %s", show_typename(rtype));
	/*
	 * if the condition is constant, the type is in fact known
	 * so use it, as gcc & clang do.
	 */
	switch (expr_truth_value(expr->conditional)) {
	case 1:	expr->ctype = ltype;
		break;
	case 0: expr->ctype = rtype;
		break;
	default:
		break;
	}
	return NULL;

out:
	expr->ctype = ctype;
	return ctype;

Qual:
	if (qual & ~ctype->ctype.modifiers) {
		struct symbol *sym = alloc_symbol(ctype->pos, SYM_PTR);
		*sym = *ctype;
		sym->ctype.modifiers |= qual;
		ctype = sym;
	}
	*cond = cast_to(*cond, ctype);
	expr->cond_false = cast_to(expr->cond_false, ctype);
	goto out;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
xorl %esi, %esi
callq 0x526c0
cmpq $0x0, %rax
jne 0x4ead1
movq $0x0, -0x8(%rbp)
jmp 0x4f0a1
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x4bb70
cmpq $0x0, %rax
jne 0x4eaf1
movq $0x0, -0x8(%rbp)
jmp 0x4f0a1
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x4c1c0
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x4c1c0
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
cmpq $0x0, 0x28(%rax)
je 0x4eb73
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x4bb70
cmpq $0x0, %rax
jne 0x4eb52
movq $0x0, -0x8(%rbp)
jmp 0x4f0a1
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x4c1c0
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
addq $0x20, %rax
addq $0x8, %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movl (%rax), %edx
shrl $0x8, %edx
andl $0xff, %edx
movq -0x18(%rbp), %rax
movq (%rax), %rax
movl (%rax), %eax
shrl $0x8, %eax
andl $0xff, %eax
andl %eax, %edx
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movl (%rax), %eax
shrl $0x8, %eax
andl $0xff, %eax
andl %eax, %edx
andl $-0xc, %edx
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $0xff, %edx
shll $0x8, %edx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movl (%rax), %eax
shrl $0x8, %eax
andl $0xff, %eax
andl $0x60, %eax
cmpl $0x0, %eax
je 0x4ec45
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x121b0
movl %eax, -0x58(%rbp)
cmpl $0x0, -0x58(%rbp)
je 0x4ec06
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x78(%rbp)
jmp 0x4ec12
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movl (%rax), %edx
shrl $0x8, %edx
andl $0xff, %edx
andl $-0xc, %edx
movq -0x10(%rbp), %rax
movl (%rax), %ecx
andl $0xff, %edx
shll $0x8, %edx
andl $0xffff00ff, %ecx       # imm = 0xFFFF00FF
orl %edx, %ecx
movl %ecx, (%rax)
movq -0x28(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x4bf20
movl %eax, -0x44(%rbp)
movq -0x30(%rbp), %rdi
leaq -0x30(%rbp), %rsi
callq 0x4bf20
movl %eax, -0x48(%rbp)
movl -0x44(%rbp), %eax
andl -0x48(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x4ecde
movq -0x18(%rbp), %rax
movq (%rax), %rsi
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdx
movl -0x44(%rbp), %ecx
movl -0x48(%rbp), %r8d
movq -0x28(%rbp), %r9
movq -0x30(%rbp), %rax
movl $0x3f, %edi
movq %rax, (%rsp)
callq 0x50e50
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x20(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
jmp 0x4eff4
movl -0x44(%rbp), %eax
orl -0x48(%rbp), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x4eef4
movq -0x18(%rbp), %rax
movq (%rax), %rdi
callq 0x51c70
movl %eax, -0x64(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x51c70
movl %eax, -0x68(%rbp)
cmpl $0x0, -0x64(%rbp)
je 0x4ed67
cmpl $0x0, -0x68(%rbp)
je 0x4ed67
movq -0x18(%rbp), %rax
movq (%rax), %rdi
leaq 0x43bef(%rip), %rsi     # 0x92918
callq 0x4c020
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
leaq 0x43bd1(%rip), %rsi     # 0x92918
callq 0x4c020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
leaq 0x43bba(%rip), %rax     # 0x92918
movq %rax, -0x20(%rbp)
jmp 0x4eff4
cmpl $0x0, -0x64(%rbp)
je 0x4edb1
movl -0x48(%rbp), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x4edb1
cmpl $0x2, -0x64(%rbp)
jne 0x4ed8a
movq -0x18(%rbp), %rax
movq (%rax), %rdi
callq 0x51ce0
movq -0x18(%rbp), %rax
movq (%rax), %rdi
movq -0x30(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x4eff4
cmpl $0x0, -0x68(%rbp)
je 0x4edfe
movl -0x44(%rbp), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x4edfe
cmpl $0x2, -0x68(%rbp)
jne 0x4edd5
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x51ce0
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x28(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x4eff4
movl -0x44(%rbp), %eax
andl -0x48(%rbp), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x4ee1c
leaq 0x1cb01(%rip), %rax     # 0x6b914
movq %rax, -0x50(%rbp)
jmp 0x4ef16
movq -0x28(%rbp), %rax
movq 0x80(%rax), %rax
movq -0x30(%rbp), %rcx
cmpq 0x80(%rcx), %rax
je 0x4ee44
leaq 0x1cb30(%rip), %rax     # 0x6b96b
movq %rax, -0x50(%rbp)
jmp 0x4ef16
movq -0x28(%rbp), %rdi
callq 0x40260
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rdi
callq 0x40260
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rdi
callq 0x52670
movq %rax, -0x80(%rbp)
movq -0x30(%rbp), %rdi
callq 0x52670
movq %rax, %rcx
movq -0x80(%rbp), %rax
orq %rcx, %rax
movl %eax, -0x54(%rbp)
leaq 0x42670(%rip), %rax     # 0x914f8
cmpq %rax, -0x38(%rbp)
jne 0x4ee9b
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x4f00d
leaq 0x42656(%rip), %rax     # 0x914f8
cmpq %rax, -0x40(%rbp)
jne 0x4eeb5
movq -0x30(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x4f00d
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rdi
addq $0x48, %rdi
addq $0x18, %rdi
movq -0x30(%rbp), %rsi
addq $0x48, %rsi
addq $0x18, %rsi
movslq -0x54(%rbp), %rdx
movslq -0x54(%rbp), %rcx
callq 0x4ad70
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x4eef2
jmp 0x4f00d
jmp 0x4ef16
movq -0x28(%rbp), %rax
cmpq -0x30(%rbp), %rax
jne 0x4ef0b
movq -0x28(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x4eff4
leaq 0x1ca1c(%rip), %rax     # 0x6b92e
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rdi
movq -0x50(%rbp), %rdx
leaq 0x1d3ac(%rip), %rsi     # 0x6c2d1
xorl %eax, %eax
movb %al, -0x85(%rbp)
callq 0x17030
movq -0x10(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x28(%rbp), %rdi
callq 0x33340
movq -0xa0(%rbp), %rcx
movq %rax, %rdx
movb -0x85(%rbp), %al
movq 0x8(%rcx), %rdi
leaq 0x1b502(%rip), %rsi     # 0x6a463
movq %rsi, -0x90(%rbp)
callq 0x16c10
movq -0x10(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x30(%rbp), %rdi
callq 0x33340
movq -0x98(%rbp), %rcx
movq -0x90(%rbp), %rsi
movq %rax, %rdx
movb -0x85(%rbp), %al
movq 0x8(%rcx), %rdi
callq 0x16c10
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x121b0
movl %eax, %ecx
movl %ecx, -0x84(%rbp)
testl %eax, %eax
je 0x4efd7
jmp 0x4efbc
movl -0x84(%rbp), %eax
subl $0x1, %eax
jne 0x4efe5
jmp 0x4efc9
movq -0x28(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
jmp 0x4efe7
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
jmp 0x4efe7
jmp 0x4efe7
movq $0x0, -0x8(%rbp)
jmp 0x4f0a1
movq -0x20(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x4f0a1
movslq -0x54(%rbp), %rax
movq -0x20(%rbp), %rcx
movq 0x68(%rcx), %rcx
xorq $-0x1, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x4f066
movq -0x20(%rbp), %rax
movq 0x4(%rax), %rdi
movl $0x4, %esi
callq 0x3f4d0
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0xe0, %edx
callq 0x111d0
movslq -0x54(%rbp), %rcx
movq -0x70(%rbp), %rax
orq 0x68(%rax), %rcx
movq %rcx, 0x68(%rax)
movq -0x70(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rdi
movq -0x20(%rbp), %rsi
callq 0x4c020
movq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
jmp 0x4eff4
movq -0x8(%rbp), %rax
addq $0xb0, %rsp
popq %rbp
retq
nop