// File: /workspace/github_c_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rdi, %rbx
movq 0x20(%rdi), %rdi
xorl %r12d, %r12d
xorl %esi, %esi
callq 0x37599
testq %rax, %rax
je 0x3538c
movq 0x30(%rbx), %rdi
callq 0x32223
testq %rax, %rax
je 0x35070
movq 0x20(%rbx), %rdi
callq 0x32bf6
movq %rax, %r14
movq 0x30(%rbx), %rdi
callq 0x32bf6
movq %rax, %r15
movq 0x28(%rbx), %rdi
testq %rdi, %rdi
je 0x35078
callq 0x32223
testq %rax, %rax
je 0x35070
leaq 0x28(%rbx), %r13
movq (%r13), %rdi
callq 0x32bf6
movq %rax, %r14
jmp 0x3507c
xorl %r12d, %r12d
jmp 0x3538c
leaq 0x20(%rbx), %r13
leaq 0x30(%rbx), %r12
movq 0x20(%rbx), %rdi
movq 0x30(%rbx), %rcx
movl (%rdi), %eax
movq (%r13), %rdx
andl (%rdx), %eax
andl (%rcx), %eax
andl $0xf400, %eax           # imm = 0xF400
movb %ah, 0x1(%rbx)
testb $0x60, 0x1(%rdi)
je 0x350bb
callq 0xf4c9
testl %eax, %eax
movq %r13, %rax
cmoveq %r12, %rax
movq (%rax), %rax
movl $0xf400, %ecx           # imm = 0xF400
andl (%rax), %ecx
movb %ch, 0x1(%rbx)
movzbl (%r14), %eax
cmpl $0x3, %eax
jne 0x350cc
movq 0x60(%r14), %r14
movzbl (%r14), %eax
cmpl $0xa, %eax
jne 0x350ec
movq %r14, %rdi
callq 0x2b0b8
movq %rax, %r14
movzbl (%rax), %eax
cmpl $0x3, %eax
jne 0x350ec
movq 0x60(%r14), %r14
movzbl (%r14), %eax
cmpl $0x9, %eax
jne 0x350f9
movq 0x60(%r14), %r14
movzbl (%r14), %eax
cmpl $0x2, %eax
movq %r13, 0x10(%rsp)
jne 0x35119
movq 0x60(%r14), %rcx
cmpq 0x2ae7a(%rip), %rcx     # 0x5ff88
je 0x35127
cmpq 0x2ae39(%rip), %rcx     # 0x5ff50
je 0x3512e
movl %eax, %eax
leaq 0x14a8e(%rip), %rcx     # 0x49bb0
movl (%rcx,%rax,4), %ebp
jmp 0x35133
movl $0x1, %ebp
jmp 0x35133
movl $0x9, %ebp
movzbl (%r15), %eax
cmpl $0x3, %eax
jne 0x35144
movq 0x60(%r15), %r15
movzbl (%r15), %eax
cmpl $0xa, %eax
jne 0x35164
movq %r15, %rdi
callq 0x2b0b8
movq %rax, %r15
movzbl (%rax), %eax
cmpl $0x3, %eax
jne 0x35164
movq 0x60(%r15), %r15
movzbl (%r15), %eax
cmpl $0x9, %eax
jne 0x35171
movq 0x60(%r15), %r15
movzbl (%r15), %eax
cmpl $0x2, %eax
movq %r12, 0x18(%rsp)
jne 0x35191
movq 0x60(%r15), %rcx
cmpq 0x2ae02(%rip), %rcx     # 0x5ff88
je 0x351a0
cmpq 0x2adc1(%rip), %rcx     # 0x5ff50
je 0x351a8
movl %eax, %eax
leaq 0x14a16(%rip), %rcx     # 0x49bb0
movl (%rcx,%rax,4), %r13d
jmp 0x351ae
movl $0x1, %r13d
jmp 0x351ae
movl $0x9, %r13d
movl %r13d, %r12d
andl %ebp, %r12d
testb $0x1, %r12b
jne 0x35247
movl %r13d, %eax
orl %ebp, %eax
testb $0x10, %al
jne 0x35297
cmpq %r15, %r14
je 0x35500
leaq 0x14a33(%rip), %rdx     # 0x49c0e
leaq 0x153cf(%rip), %rsi     # 0x4a5b1
xorl %r12d, %r12d
movq %rbx, %rdi
xorl %eax, %eax
callq 0x11b04
movq %r14, %rdi
callq 0x237c5
movq 0x8(%rbx), %rdi
leaq 0x13685(%rip), %r13     # 0x48887
movq %r13, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x1178c
movq %r15, %rdi
callq 0x237c5
movq 0x8(%rbx), %rdi
movq %r13, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x1178c
movq 0x20(%rbx), %rdi
callq 0xf4c9
cmpl $0x1, %eax
je 0x353e3
testl %eax, %eax
je 0x353e6
jmp 0x3538c
movl %ebp, %ecx
movq 0x10(%rsp), %rbp
movq (%rbp), %rsi
movq 0x18(%rsp), %r12
movq (%r12), %rdx
movq %r15, (%rsp)
movl $0x3f, %edi
movl %r13d, %r8d
movq %r14, %r9
callq 0x36814
movq %rax, %r15
movq (%rbp), %rdi
movq %rax, %rsi
callq 0x32aa9
movq %rax, (%rbp)
movq (%r12), %rdi
movq %r15, %rsi
callq 0x32aa9
movq %rax, (%r12)
jmp 0x35382
movq 0x10(%rsp), %rax
movq (%rax), %rdi
movq 0x10(%rdi), %rax
movl $0x1, %edx
movl $0x1, %esi
cmpq 0x2ad04(%rip), %rax     # 0x5ffb8
je 0x352d2
xorl %esi, %esi
testb $0x10, 0x1(%rdi)
je 0x352d2
callq 0xf54a
movl $0x1, %edx
xorl %esi, %esi
testl %eax, %eax
setne %sil
addl %esi, %esi
movq 0x18(%rsp), %rax
movq (%rax), %rdi
movq 0x10(%rdi), %rax
cmpq 0x2acd3(%rip), %rax     # 0x5ffb8
je 0x3530e
testb $0x10, 0x1(%rdi)
jne 0x352f8
testl %esi, %esi
setne %cl
xorl %eax, %eax
xorl %edx, %edx
jmp 0x3533f
movl %esi, 0x24(%rsp)
callq 0xf54a
movl 0x24(%rsp), %esi
xorl %edx, %edx
testl %eax, %eax
setne %dl
addl %edx, %edx
testl %edx, %edx
setne %al
testl %esi, %esi
setne %cl
je 0x3533f
testl %edx, %edx
je 0x3533f
movq 0x10(%rsp), %r14
movq (%r14), %rdi
leaq 0x3720b(%rip), %r15     # 0x6c538
movq %r15, %rsi
callq 0x32aa9
movq %rax, (%r14)
movq 0x18(%rsp), %r14
jmp 0x35374
testb $0x10, %r13b
je 0x3539e
testb %cl, %cl
je 0x3539e
movq 0x10(%rsp), %r14
movq (%r14), %rdi
cmpl $0x2, %esi
jne 0x35377
leaq 0x2b263(%rip), %rax     # 0x605c0
cmpl $0x0, (%rax)
je 0x35377
movq 0x8(%rdi), %rdi
leaq 0x14bc7(%rip), %rsi     # 0x49f34
xorl %eax, %eax
callq 0x118fc
movq (%r14), %rdi
movq %r15, %rsi
callq 0x32aa9
movq %rax, (%r14)
movq %r15, %r14
movq %r15, 0x10(%rbx)
movq %r14, %r12
movq %r12, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
andl $0x10, %ebp
shrl $0x4, %ebp
andb %bpl, %al
cmpb $0x1, %al
jne 0x353eb
movq 0x18(%rsp), %r15
movq (%r15), %rdi
cmpl $0x2, %edx
jne 0x354f5
leaq 0x2b1fd(%rip), %rax     # 0x605c0
cmpl $0x0, (%rax)
je 0x354f5
movq 0x8(%rdi), %rdi
leaq 0x14b5d(%rip), %rsi     # 0x49f34
xorl %eax, %eax
callq 0x118fc
jmp 0x354f2
movq %r14, %r15
xorl %r14d, %r14d
jmp 0x35385
testb $0x10, %r12b
jne 0x353fd
leaq 0x147fc(%rip), %rdx     # 0x49bf4
jmp 0x351db
movq 0x80(%r14), %rax
cmpq 0x80(%r15), %rax
je 0x35419
leaq 0x14837(%rip), %rdx     # 0x49c4b
jmp 0x351db
movq %r14, %rdi
callq 0x2baa4
movq %rax, %rbp
movq %r15, %rdi
callq 0x2baa4
movq 0x60(%r14), %rdx
movq 0x68(%r14), %rcx
andl $0x11000e00, %ecx       # imm = 0x11000E00
testq %rdx, %rdx
je 0x35448
xorl %esi, %esi
cmpb $0x6, (%rdx)
cmoveq %rsi, %rcx
movq 0x60(%r15), %rdx
movq 0x68(%r15), %r12
andl $0x11000e00, %r12d      # imm = 0x11000E00
testq %rdx, %rdx
je 0x35465
xorl %esi, %esi
cmpb $0x6, (%rdx)
cmoveq %rsi, %r12
orq %rcx, %r12
cmpq 0x2aad9(%rip), %rbp     # 0x5ff48
je 0x354a0
cmpq 0x2aad0(%rip), %rax     # 0x5ff48
movq 0x10(%rsp), %r13
je 0x354a7
leaq 0x60(%r14), %rdi
leaq 0x60(%r15), %rsi
movq %r12, %rdx
movq %r12, %rcx
callq 0x31898
movq %rax, %rdx
testq %rax, %rax
jne 0x351db
jmp 0x354aa
movq 0x10(%rsp), %r13
jmp 0x354aa
movq %r15, %r14
movl 0x68(%r14), %eax
notl %eax
testl %eax, %r12d
je 0x354dd
movq 0x4(%r14), %rdi
movl $0x4, %esi
callq 0x2b00b
movq %rax, %r15
movl $0xe0, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0xe1e0
orq %r12, 0x68(%r15)
movq %r15, %r14
movq (%r13), %rdi
movq %r14, %rsi
callq 0x32aa9
movq %rax, (%r13)
movq 0x18(%rsp), %r15
movq (%r15), %rdi
movq %r14, %rsi
callq 0x32aa9
movq %rax, (%r15)
movq %r14, %r15
jmp 0x35385