// File: /workspace/github_c_makefile_star2_O0/michaelforney[P]cproc/decl.c
// Function: declspecs
static struct qualtype
declspecs(struct scope *s, enum storageclass *sc, enum funcspec *fs, int *align)
{
	struct type *t, *other;
	struct decl *d;
	struct expr *e;
	enum typespec ts = SPECNONE;
	enum typequal tq = QUALNONE;
	enum tokenkind op;
	int ntypes = 0;
	unsigned long long i;
	struct expr *typeofexpr = NULL;

	t = NULL;
	if (sc)
		*sc = SCNONE;
	if (fs)
		*fs = FUNCNONE;
	if (align)
		*align = 0;
	for (;;) {
		if (typequal(&tq) || storageclass(sc) || funcspec(fs))
			continue;
		op = tok.kind;
		switch (op) {
		/* 6.7.2 Type specifiers */
		case TVOID:
			t = &typevoid;
			++ntypes;
			next();
			break;
		case TCHAR:
			ts |= SPECCHAR;
			++ntypes;
			next();
			break;
		case TSHORT:
			if (ts & SPECSHORT)
				error(&tok.loc, "duplicate 'short'");
			ts |= SPECSHORT;
			next();
			break;
		case TINT:
			ts |= SPECINT;
			++ntypes;
			next();
			break;
		case TLONG:
			if (ts & SPECLONG2)
				error(&tok.loc, "too many 'long'");
			if (ts & SPECLONG)
				ts |= SPECLONG2;
			ts |= SPECLONG;
			next();
			break;
		case TFLOAT:
			ts |= SPECFLOAT;
			++ntypes;
			next();
			break;
		case TDOUBLE:
			ts |= SPECDOUBLE;
			++ntypes;
			next();
			break;
		case TSIGNED:
			if (ts & SPECSIGNED)
				error(&tok.loc, "duplicate 'signed'");
			ts |= SPECSIGNED;
			next();
			break;
		case TUNSIGNED:
			if (ts & SPECUNSIGNED)
				error(&tok.loc, "duplicate 'unsigned'");
			ts |= SPECUNSIGNED;
			next();
			break;
		case TBOOL:
			t = &typebool;
			++ntypes;
			next();
			break;
		case T_COMPLEX:
			error(&tok.loc, "_Complex is not yet supported");
			break;
		case T_ATOMIC:
			error(&tok.loc, "_Atomic is not yet supported");
			break;
		case TSTRUCT:
		case TUNION:
		case TENUM:
			t = tagspec(s);
			++ntypes;
			break;
		case TIDENT:
			if (t || ts)
				goto done;
			d = scopegetdecl(s, tok.lit, 1);
			if (!d || d->kind != DECLTYPE)
				goto done;
			t = d->type;
			tq |= d->qual;
			++ntypes;
			next();
			break;
		case TTYPEOF:
		case TTYPEOF_UNQUAL:
			next();
			expect(TLPAREN, "after 'typeof'");
			t = typename(s, &tq, &typeofexpr);
			if (!t) {
				e = expr(s);
				if (e->decayed)
					e = e->base;
				t = e->type;
				if (op == TTYPEOF)
					tq |= e->qual;
				if (t->prop & PROPVM)
					typeofexpr = e;
			}
			++ntypes;
			expect(TRPAREN, "to close 'typeof'");
			break;

		/* 6.7.5 Alignment specifier */
		case TALIGNAS:
			if (!align)
				error(&tok.loc, "alignment specifier not allowed in this declaration");
			next();
			expect(TLPAREN, "after 'alignas'");
			other = typename(s, NULL, NULL);
			i = other ? other->align : intconstexpr(s, false);
			if (i & i - 1 || i > INT_MAX)
				error(&tok.loc, "invalid alignment: %llu", i);
			if (i > *align)
				*align = i;
			expect(TRPAREN, "to close 'alignas' specifier");
			break;

		case T__ATTRIBUTE__:
			gnuattr(NULL, 0);
			break;

		default:
			goto done;
		}
		if (ntypes > 1 || (t && ts))
			error(&tok.loc, "multiple types in declaration specifiers");
	}
done:
	switch ((int)ts) {
	case SPECNONE:                                            break;
	case SPECCHAR:                          t = &typechar;    break;
	case SPECSIGNED|SPECCHAR:               t = &typeschar;   break;
	case SPECUNSIGNED|SPECCHAR:             t = &typeuchar;   break;
	case SPECSHORT:
	case SPECSHORT|SPECINT:
	case SPECSIGNED|SPECSHORT:
	case SPECSIGNED|SPECSHORT|SPECINT:      t = &typeshort;   break;
	case SPECUNSIGNED|SPECSHORT:
	case SPECUNSIGNED|SPECSHORT|SPECINT:    t = &typeushort;  break;
	case SPECINT:
	case SPECSIGNED:
	case SPECSIGNED|SPECINT:                t = &typeint;     break;
	case SPECUNSIGNED:
	case SPECUNSIGNED|SPECINT:              t = &typeuint;    break;
	case SPECLONG:
	case SPECLONG|SPECINT:
	case SPECSIGNED|SPECLONG:
	case SPECSIGNED|SPECLONG|SPECINT:       t = &typelong;    break;
	case SPECUNSIGNED|SPECLONG:
	case SPECUNSIGNED|SPECLONG|SPECINT:     t = &typeulong;   break;
	case SPECLONGLONG:
	case SPECLONGLONG|SPECINT:
	case SPECSIGNED|SPECLONGLONG:
	case SPECSIGNED|SPECLONGLONG|SPECINT:   t = &typellong;   break;
	case SPECUNSIGNED|SPECLONGLONG:
	case SPECUNSIGNED|SPECLONGLONG|SPECINT: t = &typeullong;  break;
	case SPECFLOAT:                         t = &typefloat;   break;
	case SPECDOUBLE:                        t = &typedouble;  break;
	case SPECLONG|SPECDOUBLE:               t = &typeldouble; break;
	default:
		error(&tok.loc, "invalid combination of type specifiers");
	}
	if (!t && (tq || sc && *sc || fs && *fs))
		error(&tok.loc, "declaration has no type specifier");
	/*
	TODO: consider delaying attribute parsing to declarator(),
	so we can tell the difference between the start of an
	attribute and an array declarator.
	*/
	attr(NULL, 0);

	return (struct qualtype){t, tq, typeofexpr};
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x70(%rbp)
movq %rdi, -0x68(%rbp)
movq %rsi, -0x8(%rbp)
movq %rdx, -0x10(%rbp)
movq %rcx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movl $0x0, -0x44(%rbp)
movl $0x0, -0x48(%rbp)
movl $0x0, -0x50(%rbp)
movq $0x0, -0x60(%rbp)
movq $0x0, -0x28(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x3a89
movq -0x10(%rbp), %rax
movl $0x0, (%rax)
cmpq $0x0, -0x18(%rbp)
je 0x3a9a
movq -0x18(%rbp), %rax
movl $0x0, (%rax)
cmpq $0x0, -0x20(%rbp)
je 0x3aab
movq -0x20(%rbp), %rax
movl $0x0, (%rax)
jmp 0x3aad
leaq -0x48(%rbp), %rdi
callq 0x55b0
cmpl $0x0, %eax
jne 0x3ad7
movq -0x10(%rbp), %rdi
callq 0x5650
cmpl $0x0, %eax
jne 0x3ad7
movq -0x18(%rbp), %rdi
callq 0x5790
cmpl $0x0, %eax
je 0x3ad9
jmp 0x3aad
leaq 0x1e6c8(%rip), %rax     # 0x221a8
movl (%rax), %eax
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
addl $-0x4, %eax
movl %eax, %ecx
movq %rcx, -0x78(%rbp)
subl $0x3b, %eax
ja 0x3f20
movq -0x78(%rbp), %rax
leaq 0x145e3(%rip), %rcx     # 0x180e8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq 0x1df23(%rip), %rax     # 0x21a38
movq %rax, -0x28(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
orl $0x4, %eax
movl %eax, -0x44(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x3b6e
leaq 0x1e64c(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14b67(%rip), %rsi     # 0x186ce
movb $0x0, %al
callq 0x11190
movl -0x44(%rbp), %eax
orl $0x80, %eax
movl %eax, -0x44(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
orl $0x10, %eax
movl %eax, -0x44(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
andl $0x200, %eax            # imm = 0x200
cmpl $0x0, %eax
je 0x3bc5
leaq 0x1e5f5(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14b22(%rip), %rsi     # 0x186e0
movb $0x0, %al
callq 0x11190
movl -0x44(%rbp), %eax
andl $0x100, %eax            # imm = 0x100
cmpl $0x0, %eax
je 0x3bdd
movl -0x44(%rbp), %eax
orl $0x200, %eax            # imm = 0x200
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
orl $0x100, %eax            # imm = 0x100
movl %eax, -0x44(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
orl $0x20, %eax
movl %eax, -0x44(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
orl $0x40, %eax
movl %eax, -0x44(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
andl $0x400, %eax            # imm = 0x400
cmpl $0x0, %eax
je 0x3c50
leaq 0x1e56a(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14aa7(%rip), %rsi     # 0x186f0
movb $0x0, %al
callq 0x11190
movl -0x44(%rbp), %eax
orl $0x400, %eax            # imm = 0x400
movl %eax, -0x44(%rbp)
callq 0xd540
jmp 0x3f22
movl -0x44(%rbp), %eax
andl $0x800, %eax            # imm = 0x800
cmpl $0x0, %eax
je 0x3c8b
leaq 0x1e52f(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14a7f(%rip), %rsi     # 0x18703
movb $0x0, %al
callq 0x11190
movl -0x44(%rbp), %eax
orl $0x800, %eax            # imm = 0x800
movl %eax, -0x44(%rbp)
callq 0xd540
jmp 0x3f22
leaq 0x1dde9(%rip), %rax     # 0x21a90
movq %rax, -0x28(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
leaq 0x1e4e3(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14a48(%rip), %rsi     # 0x18718
movb $0x0, %al
callq 0x11190
jmp 0x3f22
leaq 0x1e4c5(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14a48(%rip), %rsi     # 0x18736
movb $0x0, %al
callq 0x11190
jmp 0x3f22
movq -0x8(%rbp), %rdi
callq 0x5820
movq %rax, -0x28(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x3f22
cmpq $0x0, -0x28(%rbp)
jne 0x3d22
cmpl $0x0, -0x44(%rbp)
je 0x3d27
jmp 0x3f53
movq -0x8(%rbp), %rdi
leaq 0x1e476(%rip), %rax     # 0x221a8
movq 0x20(%rax), %rsi
movl $0x1, %edx
callq 0xfef0
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x3d55
movq -0x38(%rbp), %rax
cmpl $0x0, 0x8(%rax)
je 0x3d5a
jmp 0x3f53
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x38(%rbp), %rax
movl 0x18(%rax), %eax
orl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
callq 0xd540
jmp 0x3f22
callq 0xd540
movl $0x42, %edi
leaq 0x149bc(%rip), %rsi     # 0x18753
callq 0xd8d0
movq -0x8(%rbp), %rdi
leaq -0x48(%rbp), %rsi
leaq -0x60(%rbp), %rdx
callq 0x3960
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x3e13
movq -0x8(%rbp), %rdi
callq 0x8f10
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
testb $0x1, 0x5(%rax)
je 0x3ddb
movq -0x40(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x28(%rbp)
cmpl $0x2e, -0x4c(%rbp)
jne 0x3dfa
movq -0x40(%rbp), %rax
movl 0x10(%rax), %eax
orl -0x48(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movl 0x4(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x3e11
movq -0x40(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x3e13
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
movl $0x43, %edi
leaq 0x1493a(%rip), %rsi     # 0x18762
callq 0xd8d0
jmp 0x3f22
cmpq $0x0, -0x20(%rbp)
jne 0x3e52
leaq 0x1e368(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14929(%rip), %rsi     # 0x18774
movb $0x0, %al
callq 0x11190
callq 0xd540
movl $0x42, %edi
leaq 0x14945(%rip), %rsi     # 0x187a8
callq 0xd8d0
movq -0x8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %edx
movq %rdx, %rsi
callq 0x3960
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x3e91
movq -0x30(%rbp), %rax
movslq 0x8(%rax), %rax
movq %rax, -0x80(%rbp)
jmp 0x3ea0
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x90c0
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
jne 0x3ec7
cmpq $0x7fffffff, -0x58(%rbp) # imm = 0x7FFFFFFF
jbe 0x3ee4
movq -0x58(%rbp), %rdx
leaq 0x1e2d6(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x148db(%rip), %rsi     # 0x187b8
movb $0x0, %al
callq 0x11190
movq -0x58(%rbp), %rax
movq -0x20(%rbp), %rcx
movslq (%rcx), %rcx
cmpq %rcx, %rax
jbe 0x3f00
movq -0x58(%rbp), %rax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movl %ecx, (%rax)
movl $0x43, %edi
leaq 0x148c4(%rip), %rsi     # 0x187d0
callq 0xd8d0
jmp 0x3f22
xorl %eax, %eax
movl %eax, %edi
xorl %esi, %esi
callq 0x3450
jmp 0x3f22
jmp 0x3f53
cmpl $0x1, -0x50(%rbp)
jg 0x3f35
cmpq $0x0, -0x28(%rbp)
je 0x3f4e
cmpl $0x0, -0x44(%rbp)
je 0x3f4e
leaq 0x1e26c(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x148a6(%rip), %rsi     # 0x187ed
movb $0x0, %al
callq 0x11190
jmp 0x3aad
movl -0x44(%rbp), %eax
movl %eax, -0x84(%rbp)
testl %eax, %eax
je 0x4188
jmp 0x3f66
movl -0x84(%rbp), %eax
subl $0x4, %eax
je 0x418d
jmp 0x3f77
movl -0x84(%rbp), %eax
subl $0x10, %eax
je 0x41dd
jmp 0x3f88
movl -0x84(%rbp), %eax
subl $0x20, %eax
je 0x422e
jmp 0x3f99
movl -0x84(%rbp), %eax
subl $0x40, %eax
je 0x423b
jmp 0x3faa
movl -0x84(%rbp), %eax
subl $0x80, %eax
je 0x41bd
jmp 0x3fbd
movl -0x84(%rbp), %eax
subl $0x90, %eax
je 0x41bd
jmp 0x3fd0
movl -0x84(%rbp), %eax
subl $0x100, %eax            # imm = 0x100
je 0x41fa
jmp 0x3fe3
movl -0x84(%rbp), %eax
subl $0x110, %eax            # imm = 0x110
je 0x41fa
jmp 0x3ff6
movl -0x84(%rbp), %eax
subl $0x140, %eax            # imm = 0x140
je 0x4248
jmp 0x4009
movl -0x84(%rbp), %eax
subl $0x300, %eax            # imm = 0x300
je 0x4214
jmp 0x401c
movl -0x84(%rbp), %eax
subl $0x310, %eax            # imm = 0x310
je 0x4214
jmp 0x402f
movl -0x84(%rbp), %eax
subl $0x400, %eax            # imm = 0x400
je 0x41dd
jmp 0x4042
movl -0x84(%rbp), %eax
subl $0x404, %eax            # imm = 0x404
je 0x419d
jmp 0x4055
movl -0x84(%rbp), %eax
subl $0x410, %eax            # imm = 0x410
je 0x41dd
jmp 0x4068
movl -0x84(%rbp), %eax
subl $0x480, %eax            # imm = 0x480
je 0x41bd
jmp 0x407b
movl -0x84(%rbp), %eax
subl $0x490, %eax            # imm = 0x490
je 0x41bd
jmp 0x408e
movl -0x84(%rbp), %eax
subl $0x500, %eax            # imm = 0x500
je 0x41fa
jmp 0x40a1
movl -0x84(%rbp), %eax
subl $0x510, %eax            # imm = 0x510
je 0x41fa
jmp 0x40b4
movl -0x84(%rbp), %eax
subl $0x700, %eax            # imm = 0x700
je 0x4214
jmp 0x40c7
movl -0x84(%rbp), %eax
subl $0x710, %eax            # imm = 0x710
je 0x4214
jmp 0x40da
movl -0x84(%rbp), %eax
subl $0x800, %eax            # imm = 0x800
je 0x41ed
jmp 0x40ed
movl -0x84(%rbp), %eax
subl $0x804, %eax            # imm = 0x804
je 0x41ad
jmp 0x4100
movl -0x84(%rbp), %eax
subl $0x810, %eax            # imm = 0x810
je 0x41ed
jmp 0x4113
movl -0x84(%rbp), %eax
subl $0x880, %eax            # imm = 0x880
je 0x41cd
jmp 0x4126
movl -0x84(%rbp), %eax
subl $0x890, %eax            # imm = 0x890
je 0x41cd
jmp 0x4139
movl -0x84(%rbp), %eax
subl $0x900, %eax            # imm = 0x900
je 0x4207
jmp 0x414c
movl -0x84(%rbp), %eax
subl $0x910, %eax            # imm = 0x910
je 0x4207
jmp 0x415f
movl -0x84(%rbp), %eax
subl $0xb00, %eax            # imm = 0xB00
je 0x4221
jmp 0x4172
movl -0x84(%rbp), %eax
subl $0xb10, %eax            # imm = 0xB10
je 0x4221
jmp 0x4255
jmp 0x426e
leaq 0x1d954(%rip), %rax     # 0x21ae8
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1d99c(%rip), %rax     # 0x21b40
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1d9e4(%rip), %rax     # 0x21b98
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1da2c(%rip), %rax     # 0x21bf0
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1da74(%rip), %rax     # 0x21c48
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dabc(%rip), %rax     # 0x21ca0
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1db04(%rip), %rax     # 0x21cf8
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1db4f(%rip), %rax     # 0x21d50
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1db9a(%rip), %rax     # 0x21da8
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dbe5(%rip), %rax     # 0x21e00
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dc30(%rip), %rax     # 0x21e58
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dc7b(%rip), %rax     # 0x21eb0
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dcc6(%rip), %rax     # 0x21f08
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1dd11(%rip), %rax     # 0x21f60
movq %rax, -0x28(%rbp)
jmp 0x426e
leaq 0x1df4c(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x145af(%rip), %rsi     # 0x18816
movb $0x0, %al
callq 0x11190
cmpq $0x0, -0x28(%rbp)
jne 0x42b4
cmpl $0x0, -0x48(%rbp)
jne 0x429b
cmpq $0x0, -0x10(%rbp)
je 0x428b
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0x429b
cmpq $0x0, -0x18(%rbp)
je 0x42b4
movq -0x18(%rbp), %rax
cmpl $0x0, (%rax)
je 0x42b4
leaq 0x1df06(%rip), %rdi     # 0x221a8
addq $0x8, %rdi
leaq 0x14590(%rip), %rsi     # 0x1883d
movb $0x0, %al
callq 0x11190
xorl %eax, %eax
movl %eax, %edi
xorl %esi, %esi
callq 0x3360
movq -0x70(%rbp), %rcx
movq -0x68(%rbp), %rax
movq -0x28(%rbp), %rdx
movq %rdx, (%rcx)
movl -0x48(%rbp), %edx
movl %edx, 0x8(%rcx)
movq -0x60(%rbp), %rdx
movq %rdx, 0x10(%rcx)
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)