// File: /workspace/github_c_makefile_star2_O1/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 0x38093
testq %rax, %rax
je 0x35c4c
movq 0x30(%rbx), %rdi
callq 0x32c63
testq %rax, %rax
je 0x35a9d
movq 0x20(%rbx), %rdi
callq 0x33628
movq %rax, %r12
movq 0x30(%rbx), %rdi
callq 0x33628
movq %rax, %r14
movq 0x28(%rbx), %rdi
testq %rdi, %rdi
je 0x35aa5
callq 0x32c63
testq %rax, %rax
je 0x35a9d
leaq 0x28(%rbx), %r13
movq (%r13), %rdi
callq 0x33628
movq %rax, %r15
jmp 0x35aac
xorl %r12d, %r12d
jmp 0x35c4c
leaq 0x20(%rbx), %r13
movq %r12, %r15
leaq 0x30(%rbx), %rbp
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 0x35aeb
callq 0xf305
testl %eax, %eax
movq %r13, %rax
cmoveq %rbp, %rax
movq (%rax), %rax
movl $0xf400, %ecx           # imm = 0xF400
andl (%rax), %ecx
movb %ch, 0x1(%rbx)
cmpb $0x3, (%r15)
jne 0x35af5
movq 0x60(%r15), %r15
cmpb $0xa, (%r15)
jne 0x35b0f
movq %r15, %rdi
callq 0x2b5f4
movq %rax, %r15
cmpb $0x3, (%rax)
jne 0x35b0f
movq 0x60(%r15), %r15
cmpb $0x9, (%r15)
jne 0x35b19
movq 0x60(%r15), %r15
movzbl (%r15), %eax
cmpq $0x2, %rax
jne 0x35b39
movq 0x60(%r15), %rcx
cmpq 0x2b452(%rip), %rcx     # 0x60f80
je 0x35b45
cmpq 0x2b409(%rip), %rcx     # 0x60f40
je 0x35b4c
leaq 0x15100(%rip), %rcx     # 0x4ac40
movl (%rcx,%rax,4), %ecx
jmp 0x35b51
movl $0x1, %ecx
jmp 0x35b51
movl $0x9, %ecx
cmpb $0x3, (%r14)
jne 0x35b5b
movq 0x60(%r14), %r14
cmpb $0xa, (%r14)
jne 0x35b85
movq %r14, %rdi
movq %r15, %r14
movq %rbp, %r15
movl %ecx, %ebp
callq 0x2b5f4
cmpb $0x3, (%rax)
jne 0x35b7a
movq 0x60(%rax), %rax
movl %ebp, %ecx
movq %r15, %rbp
movq %r14, %r15
movq %rax, %r14
cmpb $0x9, (%r14)
jne 0x35b8f
movq 0x60(%r14), %r14
movzbl (%r14), %eax
cmpq $0x2, %rax
movq %r13, 0x18(%rsp)
movq %rbp, 0x10(%rsp)
jne 0x35bb9
movq 0x60(%r14), %rdx
cmpq 0x2b3d2(%rip), %rdx     # 0x60f80
je 0x35bc5
cmpq 0x2b389(%rip), %rdx     # 0x60f40
je 0x35bcc
leaq 0x15080(%rip), %rdx     # 0x4ac40
movl (%rdx,%rax,4), %ebp
jmp 0x35bd1
movl $0x1, %ebp
jmp 0x35bd1
movl $0x9, %ebp
movl %ebp, %r13d
andl %ecx, %r13d
testb $0x1, %r13b
jne 0x35bfa
movl %ebp, %eax
orl %ecx, %eax
testb $0x10, %al
jne 0x35c5e
cmpq %r14, %r15
je 0x35d7d
leaq 0x150a9(%rip), %rdx     # 0x4ac9e
jmp 0x35e1f
movq 0x18(%rsp), %r13
movq (%r13), %rsi
movq 0x10(%rsp), %rax
movq (%rax), %rdx
movq %r14, (%rsp)
movl $0x3f, %edi
movl %ebp, %r8d
movq %rax, %rbp
movq %r15, %r9
callq 0x37305
movq %rax, %r12
movq (%r13), %rdi
movq %r12, %rsi
callq 0x334cd
movq %rax, (%r13)
movq (%rbp), %rdi
movq %r12, %rsi
callq 0x334cd
movq %rax, (%rbp)
movq %r12, %r14
movq %r14, 0x10(%rbx)
movq %r12, %rax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x18(%rsp), %rax
movq (%rax), %rdi
movq 0x10(%rdi), %rax
movl $0x1, %edx
movl $0x1, %esi
cmpq 0x2b335(%rip), %rax     # 0x60fb0
je 0x35ca1
xorl %esi, %esi
testb $0x10, 0x1(%rdi)
je 0x35ca1
movl %ecx, 0xc(%rsp)
callq 0xf386
movl $0x1, %edx
movl 0xc(%rsp), %ecx
xorl %esi, %esi
testl %eax, %eax
setne %sil
addl %esi, %esi
movq 0x10(%rsp), %rax
movq (%rax), %rdi
movq 0x10(%rdi), %rax
cmpq 0x2b2fc(%rip), %rax     # 0x60fb0
je 0x35cdc
xorl %edx, %edx
testb $0x10, 0x1(%rdi)
je 0x35cdc
movl %ecx, 0xc(%rsp)
movl %esi, 0x24(%rsp)
callq 0xf386
movl 0x24(%rsp), %esi
movl 0xc(%rsp), %ecx
xorl %edx, %edx
testl %eax, %eax
setne %dl
addl %edx, %edx
testl %esi, %esi
je 0x35d22
testl %edx, %edx
je 0x35d22
movq 0x18(%rsp), %r13
movq (%r13), %rdi
leaq 0x37844(%rip), %r12     # 0x6d538
movq %r12, %rsi
callq 0x334cd
movq %rax, (%r13)
movq 0x10(%rsp), %rbp
movq (%rbp), %rdi
movq %r12, %rsi
callq 0x334cd
movq %rax, (%rbp)
movl $0x2, %ecx
xorl %r13d, %r13d
jmp 0x35e11
testb $0x10, %bpl
je 0x35d88
testl %esi, %esi
je 0x35d88
cmpl $0x2, %esi
movq 0x18(%rsp), %r12
jne 0x35d58
leaq 0x2b883(%rip), %rax     # 0x615c0
cmpl $0x0, (%rax)
je 0x35d58
movq (%r12), %rax
movq 0x8(%rax), %rdi
leaq 0x15273(%rip), %rsi     # 0x4afc4
xorl %eax, %eax
callq 0x118b4
movq (%r12), %rdi
movq %r14, %rsi
callq 0x334cd
movq %rax, (%r12)
movl $0x2, %ecx
xorl %r13d, %r13d
movq %r14, %r12
movq 0x10(%rsp), %rbp
jmp 0x35e11
movq %r15, %r14
movq %r15, %r12
jmp 0x35c48
testl %edx, %edx
je 0x35dda
andl $0x10, %ecx
je 0x35dda
cmpl $0x2, %edx
movq 0x10(%rsp), %rbp
jne 0x35dbd
leaq 0x2b81e(%rip), %rax     # 0x615c0
cmpl $0x0, (%rax)
je 0x35dbd
movq (%rbp), %rax
movq 0x8(%rax), %rdi
leaq 0x1520e(%rip), %rsi     # 0x4afc4
xorl %eax, %eax
callq 0x118b4
movq (%rbp), %rdi
movq %r15, %rsi
callq 0x334cd
movq %rax, (%rbp)
movl $0x2, %ecx
xorl %r13d, %r13d
movq %r15, %r12
jmp 0x35e11
movl $0x3, %ecx
testb $0x10, %r13b
movq 0x10(%rsp), %rbp
jne 0x35df3
leaq 0x14e93(%rip), %rdx     # 0x4ac84
jmp 0x35e0e
movq 0x80(%r15), %rax
cmpq 0x80(%r14), %rax
je 0x35ed1
leaq 0x14ecd(%rip), %rdx     # 0x4acdb
xorl %r13d, %r13d
cmpl $0x2, %ecx
je 0x35c45
cmpl $0x3, %ecx
jne 0x35e8a
leaq 0x1581b(%rip), %rsi     # 0x4b641
xorl %r12d, %r12d
movq %rbx, %rdi
xorl %eax, %eax
callq 0x11abc
movq %r15, %rdi
callq 0x2386c
movq 0x8(%rbx), %rdi
leaq 0x13ad1(%rip), %r13     # 0x49917
movq %r13, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x11744
movq %r14, %rdi
callq 0x2386c
movq 0x8(%rbx), %rdi
movq %r13, %rsi
movq %rax, %rdx
xorl %eax, %eax
callq 0x11744
movq 0x20(%rbx), %rdi
callq 0xf305
cmpl $0x1, %eax
je 0x35ec9
testl %eax, %eax
jne 0x35c4c
xorl %r12d, %r12d
jmp 0x35c48
movl 0x68(%r12), %eax
notl %eax
testl %eax, %r13d
je 0x35ebf
movq 0x4(%r12), %rdi
movl $0x4, %esi
callq 0x2b547
movq %rax, %r14
movl $0xe0, %edx
movq %rax, %rdi
movq %r12, %rsi
callq 0xe1e0
orq %r13, 0x68(%r14)
movq %r14, %r12
movq 0x18(%rsp), %r13
jmp 0x35c25
movq %r15, %r14
jmp 0x35c48
movq %r15, %rdi
callq 0x2bfd0
movq %rax, %r12
movq %r14, %rdi
callq 0x2bfd0
movq 0x60(%r15), %rdx
movq 0x68(%r15), %rcx
andl $0x11000e00, %ecx       # imm = 0x11000E00
testq %rdx, %rdx
je 0x35f00
xorl %esi, %esi
cmpb $0x6, (%rdx)
cmoveq %rsi, %rcx
movq 0x60(%r14), %rdx
movq 0x68(%r14), %r13
andl $0x11000e00, %r13d      # imm = 0x11000E00
testq %rdx, %rdx
je 0x35f1d
xorl %esi, %esi
cmpb $0x6, (%rdx)
cmoveq %rsi, %r13
orq %rcx, %r13
movl $0x4, %ecx
cmpq 0x2b00c(%rip), %r12     # 0x60f38
je 0x35dd5
cmpq 0x2afff(%rip), %rax     # 0x60f38
je 0x35f5f
leaq 0x60(%r15), %rdi
leaq 0x60(%r14), %rsi
movq %r13, %rdx
movq %r13, %rcx
callq 0x32020
movq %rax, %rdx
xorl %ecx, %ecx
cmpq $0x1, %rax
adcl $0x3, %ecx
jmp 0x35dd5
movq %r14, %r12
jmp 0x35e11