// File: /workspace/github_c_makefile_star2_O3/michaelforney[P]cproc/decl.c
// Function: decl
bool
decl(struct scope *s, struct func *f)
{
	struct qualtype base, qt;
	struct type *t;
	enum typequal tq;
	enum storageclass sc;
	enum funcspec fs;
	struct init *init;
	bool hasinit;
	char *name, *asmname;
	int allowfunc = !f;
	struct decl *d, *prior;
	enum declkind kind;
	struct scope *funcscope;
	int align;

	if (staticassert(s))
		return true;
	if (attr(NULL, 0) && consume(TSEMICOLON))
		return true;
	base = declspecs(s, &sc, &fs, &align);
	if (!base.type)
		return false;
	if (f) {
		if (sc == SCTHREADLOCAL)
			error(&tok.loc, "block scope declaration containing 'thread_local' must contain 'static' or 'extern'");
	} else {
		/* 6.9p2 */
		if (sc & SCAUTO)
			error(&tok.loc, "external declaration must not contain 'auto'");
		if (sc & SCREGISTER)
			error(&tok.loc, "external declaration must not contain 'register'");
	}
	if (consume(TSEMICOLON)) {
		/* XXX 6.7p2 error unless in function parameter/struct/union, or tag/enum members are declared */
		return true;
	}
	for (;;) {
		qt = declarator(s, base, &name, &funcscope, false);
		t = qt.type;
		tq = qt.qual;
		if (consume(T__ASM__)) {
			expect(TLPAREN, "after __asm__");
			asmname = expect(TSTRINGLIT, "for assembler name");
			expect(TRPAREN, "after assembler name");
			allowfunc = 0;
		} else {
			asmname = NULL;
		}
		kind = sc & SCTYPEDEF ? DECLTYPE : t->kind == TYPEFUNC ? DECLFUNC : DECLOBJECT;
		prior = scopegetdecl(s, name, false);
		if (prior && prior->kind != kind)
			error(&tok.loc, "'%s' redeclared with different kind", name);
		switch (kind) {
		case DECLTYPE:
			if (align)
				error(&tok.loc, "typedef '%s' declared with alignment specifier", name);
			if (asmname)
				error(&tok.loc, "typedef '%s' declared with assembler label", name);
			if (!prior)
				scopeputdecl(s, mkdecl(name, DECLTYPE, t, tq, LINKNONE));
			else if (!typesame(prior->type, t) || prior->qual != tq)
				error(&tok.loc, "typedef '%s' redefined with different type", name);
			break;
		case DECLOBJECT:
			if (align && align < t->align)
				error(&tok.loc, "object '%s' requires alignment %d, which is stricter than specified alignment %d", name, t->align, align);
			d = declcommon(s, kind, name, asmname, t, tq, sc, prior);
			if (d->u.obj.align < align)
				d->u.obj.align = align;
			if (d->linkage == LINKNONE && !(sc & SCSTATIC)) {
				d->u.obj.storage = SDAUTO;
			} else {
				d->u.obj.storage = sc & SCTHREADLOCAL ? SDTHREAD : SDSTATIC;
				if (t->prop & PROPVM)
					error(&tok.loc, "object '%s' with %s storage duration cannot have variably modified type", name, d->u.obj.storage == SDSTATIC ? "static" : "thread");
				d->value = mkglobal(d);
			}

			if (base.expr)
				funcexpr(f, base.expr);
			init = NULL;
			hasinit = false;
			if (consume(TASSIGN)) {
				if (f && d->linkage != LINKNONE)
					error(&tok.loc, "object '%s' with block scope and %s linkage cannot have initializer", name, d->linkage == LINKEXTERN ? "external" : "internal");
				if (d->defined)
					error(&tok.loc, "object '%s' redefined", name);
				init = parseinit(s, d->type);
				hasinit = true;
			} else if (sc & SCEXTERN) {
				break;
			} else if (d->linkage != LINKNONE && d->u.obj.storage == SDSTATIC) {
				if (!d->defined && !d->tentative) {
					d->tentative = true;
					*tentativedefnsend = d;
					tentativedefnsend = &d->next;
				}
				break;
			}
			defineobj(d, init, hasinit, f);
			break;
		case DECLFUNC:
			if (align)
				error(&tok.loc, "function '%s' declared with alignment specifier", name);
			if (f && sc && sc != SCEXTERN)  /* 6.7.1p7 */
				error(&tok.loc, "function '%s' with block scope may only have storage class 'extern'", name);
			d = declcommon(s, kind, name, asmname, t, tq, sc, prior);
			d->value = mkglobal(d);
			d->u.func.inlinedefn = d->linkage == LINKEXTERN && fs & FUNCINLINE && !(sc & SCEXTERN) && (!prior || prior->u.func.inlinedefn);
			d->u.func.isnoreturn = fs & FUNCNORETURN;
			if (tok.kind == TLBRACE) {
				if (!allowfunc)
					error(&tok.loc, "function definition not allowed");
				if (d->defined)
					error(&tok.loc, "function '%s' redefined", name);
				/* re-open scope from function declarator */
				assert(funcscope);
				s = funcscope;
				f = mkfunc(d, name, t, s);
				stmt(f, s);
				if (d->u.func.isnoreturn)
					funchlt(f);
				/* XXX: need to keep track of function in case a later declaration specifies extern */
				if (!d->u.func.inlinedefn)
					emitfunc(f, d->linkage == LINKEXTERN);
				s = delscope(s);
				delfunc(f);
				d->defined = true;
				return true;
			} else if (funcscope) {
				delscope(funcscope);
			}
			break;
		}
		if (consume(TSEMICOLON))
			return true;
		expect(TCOMMA, "or ';' after declarator");
		allowfunc = 0;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %r15
movq %rsi, 0x20(%rsp)
testq %rsi, %rsi
setne %r14b
callq 0x5124
movb $0x1, %bpl
testb %al, %al
jne 0x50f4
xorl %edi, %edi
xorl %esi, %esi
callq 0x33ec
testb %al, %al
je 0x4b37
movl $0x61, %edi
callq 0xb00a
testb %al, %al
jne 0x50f4
leaq 0x38(%rsp), %rbx
leaq 0xc(%rsp), %rdx
leaq 0x2c(%rsp), %rcx
leaq 0x28(%rsp), %r8
movq %rbx, %rdi
movq %r15, %rsi
callq 0x38e3
cmpq $0x0, (%rbx)
je 0x4b76
movl 0xc(%rsp), %eax
cmpq $0x0, 0x20(%rsp)
je 0x4b7d
cmpl $0x40, %eax
jne 0x4bbb
leaq 0xd664(%rip), %rsi      # 0x121d8
jmp 0x4ba9
xorl %ebp, %ebp
jmp 0x50f4
testb $0x10, %al
je 0x4b9e
leaq 0x17580(%rip), %rdi     # 0x1c108
addq $0x8, %rdi
leaq 0xd699(%rip), %rsi      # 0x1222c
xorl %eax, %eax
callq 0xd55c
movl 0xc(%rsp), %eax
testb $0x20, %al
je 0x4bbb
leaq 0xd6b0(%rip), %rsi      # 0x12259
leaq 0x17558(%rip), %rdi     # 0x1c108
addq $0x8, %rdi
xorl %eax, %eax
callq 0xd55c
movl $0x61, %edi
callq 0xb00a
testb %al, %al
jne 0x50f4
leaq 0x17534(%rip), %rax     # 0x1c108
addq $0x8, %rax
movq %rax, 0x18(%rsp)
subq $0x20, %rsp
movq 0x68(%rsp), %rax
movq %rax, 0x10(%rsp)
movups 0x58(%rsp), %xmm0
movups %xmm0, (%rsp)
leaq 0x70(%rsp), %rdi
movq %r15, %rsi
leaq 0x30(%rsp), %rdx
leaq 0x50(%rsp), %rcx
xorl %r8d, %r8d
callq 0x48fe
addq $0x20, %rsp
movq 0x50(%rsp), %rbp
movl 0x58(%rsp), %r13d
movl $0x3e, %edi
callq 0xb00a
testb %al, %al
je 0x4c67
movl $0x42, %edi
leaq 0xd654(%rip), %rsi      # 0x1228a
callq 0xafeb
movl $0x7, %edi
leaq 0xd651(%rip), %rsi      # 0x12298
callq 0xafeb
movq %rax, %r14
movl $0x43, %edi
leaq 0xd650(%rip), %rsi      # 0x122ab
callq 0xafeb
movb $0x1, 0xb(%rsp)
jmp 0x4c6f
movb %r14b, 0xb(%rsp)
xorl %r14d, %r14d
xorl %r12d, %r12d
testb $0x2, 0xc(%rsp)
jne 0x4c87
xorl %r12d, %r12d
cmpl $0xe, (%rbp)
sete %r12b
incl %r12d
movq 0x10(%rsp), %rsi
movq %r15, %rdi
xorl %edx, %edx
callq 0xc70d
movq %rax, %rbx
testq %rax, %rax
je 0x4cbc
cmpl %r12d, 0x8(%rbx)
je 0x4cbc
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd60b(%rip), %rsi      # 0x122c0
xorl %eax, %eax
callq 0xd55c
movl 0x28(%rsp), %r8d
cmpl $0x2, %r12d
je 0x4d4c
cmpl $0x1, %r12d
jne 0x4df1
testl %r8d, %r8d
je 0x4cfa
movl 0x8(%rbp), %ecx
cmpl %ecx, %r8d
jge 0x4cfa
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd676(%rip), %rsi      # 0x12369
xorl %eax, %eax
callq 0xd55c
movq 0x10(%rsp), %rdx
movl 0xc(%rsp), %eax
movq %r15, %rdi
movl $0x1, %esi
movq %r14, %rcx
movq %rbp, %r8
movl %r13d, %r9d
pushq %rbx
pushq %rax
callq 0x520c
addq $0x10, %rsp
movq %rax, %rbx
movl 0x28(%rsp), %eax
cmpl %eax, 0x40(%rbx)
jge 0x4d2e
movl %eax, 0x40(%rbx)
movl 0xc(%rsp), %eax
movl %eax, %ecx
andl $0x8, %ecx
orl 0xc(%rbx), %ecx
jne 0x4e6b
movl $0x2, 0x44(%rbx)
jmp 0x4eb2
testl %r8d, %r8d
je 0x4d69
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd713(%rip), %rsi      # 0x12475
xorl %eax, %eax
callq 0xd55c
cmpq $0x0, 0x20(%rsp)
setne %cl
movl 0xc(%rsp), %eax
testl $0xfffffffb, %eax       # imm = 0xFFFFFFFB
setne %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0x4da1
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd70f(%rip), %rsi      # 0x124a5
xorl %eax, %eax
callq 0xd55c
movl 0xc(%rsp), %eax
movq 0x10(%rsp), %rdx
movq %r15, %rdi
movl $0x2, %esi
movq %r14, %rcx
movq %rbp, %r8
movl %r13d, %r9d
pushq %rbx
pushq %rax
callq 0x520c
addq $0x10, %rsp
movq %rax, %r14
movq %rax, %rdi
callq 0xe324
movq %rax, 0x20(%r14)
cmpl $0x2, 0xc(%r14)
setne %cl
movl 0x2c(%rsp), %eax
testb $0x2, %al
sete %dl
orb %cl, %dl
je 0x4f74
xorl %ecx, %ecx
jmp 0x4f8f
testl %r8d, %r8d
je 0x4e0e
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd4dd(%rip), %rsi      # 0x122e4
xorl %eax, %eax
callq 0xd55c
testq %r14, %r14
je 0x4e2b
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd4ef(%rip), %rsi      # 0x12313
xorl %eax, %eax
callq 0xd55c
testq %rbx, %rbx
je 0x4fbd
movq 0x10(%rbx), %rdi
movq %rbp, %rsi
callq 0xd9c0
testb %al, %al
je 0x4e4e
cmpl %r13d, 0x18(%rbx)
je 0x4ff9
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd4df(%rip), %rsi      # 0x1233e
xorl %eax, %eax
callq 0xd55c
jmp 0x4ff9
shrl $0x6, %eax
andl $0x1, %eax
movl %eax, 0x44(%rbx)
testb $0x40, 0x4(%rbp)
je 0x4ea6
movq 0x10(%rsp), %rdx
testl %eax, %eax
leaq 0xfd1e(%rip), %rcx      # 0x14ba6
leaq 0xd573(%rip), %rax      # 0x12402
cmoveq %rax, %rcx
movq 0x18(%rsp), %rdi
leaq 0xd51b(%rip), %rsi      # 0x123ba
xorl %eax, %eax
callq 0xd55c
movq %rbx, %rdi
callq 0xe324
movq %rax, 0x20(%rbx)
movq 0x48(%rsp), %rsi
testq %rsi, %rsi
je 0x4ec6
movq 0x20(%rsp), %rdi
callq 0xf251
movl $0x63, %edi
callq 0xb00a
movl %eax, %ebp
testb %al, %al
je 0x4f41
cmpq $0x0, 0x20(%rsp)
je 0x4f12
movl 0xc(%rbx), %eax
testl %eax, %eax
je 0x4f12
movq 0x10(%rsp), %rdx
cmpl $0x2, %eax
leaq 0xd562(%rip), %rcx      # 0x12456
leaq 0xd552(%rip), %rax      # 0x1244d
cmoveq %rax, %rcx
movq 0x18(%rsp), %rdi
leaq 0xd4fe(%rip), %rsi      # 0x12409
xorl %eax, %eax
callq 0xd55c
cmpb $0x1, 0x30(%rbx)
jne 0x4f30
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rdi
leaq 0xd536(%rip), %rsi      # 0x1245f
xorl %eax, %eax
callq 0xd55c
movq 0x10(%rbx), %rsi
movq %r15, %rdi
callq 0x997d
movq %rax, %rsi
jmp 0x4f5e
testb $0x4, 0xc(%rsp)
jne 0x4ff9
cmpl $0x0, 0xc(%rbx)
je 0x4f5c
cmpl $0x0, 0x44(%rbx)
je 0x5020
xorl %esi, %esi
movzbl %bpl, %edx
movq %rbx, %rdi
movq 0x20(%rsp), %rcx
callq 0x5583
jmp 0x4ff9
testq %rbx, %rbx
sete %dl
movl 0xc(%rsp), %esi
andl $0x4, %esi
sete %cl
shrl $0x2, %esi
orb %dl, %sil
jne 0x4f8f
movb 0x40(%rbx), %cl
movb %cl, 0x40(%r14)
shrb $0x2, %al
andb $0x1, %al
movb %al, 0x41(%r14)
leaq 0x17165(%rip), %rax     # 0x1c108
cmpl $0x44, (%rax)
je 0x504f
movq 0x30(%rsp), %rdi
testq %rdi, %rdi
je 0x4ff9
callq 0xc6cd
jmp 0x4ff9
movq 0x10(%rsp), %rbx
movl $0x48, %edi
callq 0xe142
xorps %xmm0, %xmm0
movups %xmm0, 0x18(%rax)
movups %xmm0, 0x28(%rax)
movups %xmm0, 0x38(%rax)
movq %rbx, (%rax)
movq $0x0, 0x8(%rax)
movq %rbp, 0x10(%rax)
movl %r13d, 0x18(%rax)
movq %r15, %rdi
movq %rax, %rsi
callq 0xc644
movl $0x61, %edi
callq 0xb00a
testb %al, %al
jne 0x5047
movl $0x6e, %edi
leaq 0xd549(%rip), %rsi      # 0x1255c
callq 0xafeb
movb $0x1, %r14b
jmp 0x4bdd
cmpb $0x0, 0x30(%rbx)
jne 0x4ff9
cmpb $0x0, 0x31(%rbx)
jne 0x4ff9
movb $0x1, 0x31(%rbx)
movq 0x16109(%rip), %rax     # 0x1b140
movq %rbx, (%rax)
addq $0x38, %rbx
movq %rbx, 0x160fb(%rip)     # 0x1b140
jmp 0x4ff9
movb $0x1, %bpl
jmp 0x50f4
testb $0x1, 0xb(%rsp)
je 0x5069
leaq 0xd48c(%rip), %rsi      # 0x124e9
movq 0x18(%rsp), %rdi
xorl %eax, %eax
callq 0xd55c
cmpb $0x1, 0x30(%r14)
jne 0x5088
movq 0x10(%rsp), %rdx
leaq 0xd48d(%rip), %rsi      # 0x12509
movq 0x18(%rsp), %rdi
xorl %eax, %eax
callq 0xd55c
movq 0x30(%rsp), %rbx
testq %rbx, %rbx
je 0x5105
movq 0x10(%rsp), %rsi
movq %r14, %rdi
movq %rbp, %rdx
movq %rbx, %rcx
callq 0xe397
movq %rax, %r15
movq %rax, %rdi
movq %rbx, %rsi
callq 0xc828
cmpb $0x1, 0x41(%r14)
jne 0x50c2
movq %r15, %rdi
callq 0xf19b
cmpb $0x0, 0x40(%r14)
movb $0x1, %bpl
jne 0x50df
xorl %esi, %esi
cmpl $0x2, 0xc(%r14)
sete %sil
movq %r15, %rdi
callq 0x109de
movq %rbx, %rdi
callq 0xc6cd
movq %r15, %rdi
callq 0xed64
movb $0x1, 0x30(%r14)
movl %ebp, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd415(%rip), %rdi      # 0x12521
leaq 0xd418(%rip), %rsi      # 0x1252b
leaq 0xd418(%rip), %rcx      # 0x12532
movl $0x449, %edx            # imm = 0x449
callq 0x30e0