+ if (spec & add)
+ goto error;
+ spec |= add;
+ }
+
+ if (*c == '\0') {
+ type_t *type;
+ switch (spec & ~SPECIFIER_COMPLEX) {
+ case SPECIFIER_NONE: type = type_int; break;
+ case SPECIFIER_LONG: type = type_long; break;
+ case SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_long_long; break;
+ case SPECIFIER_UNSIGNED: type = type_unsigned_int; break;
+ case SPECIFIER_UNSIGNED | SPECIFIER_LONG: type = type_unsigned_long; break;
+ case SPECIFIER_UNSIGNED | SPECIFIER_LONG | SPECIFIER_LONG_LONG: type = type_unsigned_long_long; break;
+ default: panic("inconsistent suffix");
+ }
+ if (spec != SPECIFIER_NONE && spec != SPECIFIER_LONG) {
+ warn_traditional_suffix(suffix);
+ }
+ if (spec & SPECIFIER_COMPLEX) {
+ assert(type->kind == TYPE_ATOMIC);
+ type = make_complex_type(type->atomic.akind, TYPE_QUALIFIER_NONE);
+ }
+ expr->base.type = type;
+ /* Integer type depends on the size of the number and the size
+ * representable by the types. The backend/codegeneration has to
+ * determine that. */
+ determine_literal_type(&expr->literal);
+ } else {
+error:
+ errorf(HERE, "invalid suffix '%s' on integer constant", suffix);
+ }
+}
+
+static void check_floatingpoint_suffix(expression_t *const expr, char const *const suffix)
+{
+ type_t *type;
+ char const *c = suffix;
+ bool is_complex = false;
+next:
+ switch (*c) {
+ case 'F':
+ case 'f': type = type_float; ++c; break;
+ case 'L':
+ case 'l': type = type_long_double; ++c; break;
+ case 'i':
+ case 'I':
+ case 'j':
+ case 'J':
+ if (!GNU_MODE)
+ break;
+ is_complex = true;
+ ++c;
+ goto next;
+ default: type = type_double; break;