#include <config.h>
#include <assert.h>
+#include "adt/strutil.h"
#include "diagnostic.h"
#include "warning.h"
#include "attribute_t.h"
return attribute_names[kind];
}
-/**
- * compare two string, ignoring double underscores on the second.
- */
-static int strcmp_underscore(const char *s1, const char *s2)
-{
- if (s2[0] == '_' && s2[1] == '_') {
- size_t len2 = strlen(s2);
- size_t len1 = strlen(s1);
- if (len1 == len2-4 && s2[len2-2] == '_' && s2[len2-1] == '_') {
- return strncmp(s1, s2+2, len2-4);
- }
- }
-
- return strcmp(s1, s2);
-}
-
type_t *handle_attribute_mode(const attribute_t *attribute, type_t *orig_type)
{
type_t *type = skip_typeref(orig_type);
const char *symbol_str = arg->v.symbol->string;
bool sign = is_type_signed(type);
atomic_type_kind_t akind;
- if (strcmp_underscore("QI", symbol_str) == 0 ||
- strcmp_underscore("byte", symbol_str) == 0) {
+ if (streq_underscore("QI", symbol_str) ||
+ streq_underscore("byte", symbol_str)) {
akind = sign ? ATOMIC_TYPE_CHAR : ATOMIC_TYPE_UCHAR;
- } else if (strcmp_underscore("HI", symbol_str) == 0) {
+ } else if (streq_underscore("HI", symbol_str)) {
akind = sign ? ATOMIC_TYPE_SHORT : ATOMIC_TYPE_USHORT;
- } else if (strcmp_underscore("SI", symbol_str) == 0
- || strcmp_underscore("word", symbol_str) == 0
- || strcmp_underscore("pointer", symbol_str) == 0) {
+ } else if (streq_underscore("SI", symbol_str)
+ || streq_underscore("word", symbol_str)
+ || streq_underscore("pointer", symbol_str)) {
akind = sign ? ATOMIC_TYPE_INT : ATOMIC_TYPE_UINT;
- } else if (strcmp_underscore("DI", symbol_str) == 0) {
+ } else if (streq_underscore("DI", symbol_str)) {
akind = sign ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG;
} else {
- if (warning.other)
- warningf(&attribute->source_position, "ignoring unknown mode '%s'",
- symbol_str);
+ source_position_t const *const pos = &attribute->source_position;
+ warningf(WARN_OTHER, pos, "ignoring unknown mode '%s'", symbol_str);
return orig_type;
}
- if (type->kind == TYPE_ATOMIC) {
+ if (type->kind == TYPE_ATOMIC || type->kind == TYPE_ENUM) {
type_t *copy = duplicate_type(type);
copy->atomic.akind = akind;
return identify_new_type(copy);
- } else if (type->kind == TYPE_ENUM) {
- type_t *copy = duplicate_type(type);
- copy->enumt.akind = akind;
- return identify_new_type(copy);
} else if (is_type_pointer(type)) {
- warningf(&attribute->source_position,
- "__attribute__((mode)) on pointers not implemented yet (ignored)");
+ source_position_t const *const pos = &attribute->source_position;
+ warningf(WARN_OTHER, pos, "__attribute__((mode)) on pointers not implemented yet (ignored)");
return type;
}
entity->compound.alignment = alignment;
}
break;
- default:
- if (warning.other) {
- const char *what = get_entity_kind_name(entity->kind);
- warningf(&attribute->source_position,
- "alignment attribute specification on %s '%S' ignored",
- what, entity->base.symbol);
- }
+ default: {
+ source_position_t const *const pos = &attribute->source_position;
+ char const *const what = get_entity_kind_name(entity->kind);
+ symbol_t const *const sym = entity->base.symbol;
+ warningf(WARN_OTHER, pos, "alignment attribute specification on %s '%S' ignored", what, sym);
break;
}
+ }
}
static const char *get_argument_string(const attribute_argument_t *argument)
case ENTITY_FUNCTION:
entity->function.elf_visibility = visibility;
break;
- default:
- if (warning.other) {
- const char *what = get_entity_kind_name(entity->kind);
- warningf(&attribute->source_position,
- "visibility attribute specification on %s '%S' ignored",
- what, entity->base.symbol);
- }
+ default: {
+ source_position_t const *const pos = &attribute->source_position;
+ char const *const what = get_entity_kind_name(entity->kind);
+ symbol_t const *const sym = entity->base.symbol;
+ warningf(WARN_OTHER, pos, "visibility attribute specification on %s '%S' ignored", what, sym);
break;
}
+ }
}
static void warn_arguments(const attribute_t *attribute)
if (attribute->a.arguments == NULL)
return;
- if (warning.other) {
- warningf(&attribute->source_position,
- "attribute '%s' needs no arguments",
- get_attribute_name(attribute->kind));
- }
+ source_position_t const *const pos = &attribute->source_position;
+ char const *const what = get_attribute_name(attribute->kind);
+ warningf(WARN_OTHER, pos, "attribute '%s' needs no arguments", what);
}
static void handle_attribute_packed_e(const attribute_t *attribute,
{
#if 0
if (entity->kind != ENTITY_STRUCT) {
- warningf(&attribute->source_position,
- "packed attribute on %s '%s' ignored",
- get_entity_kind_name(entity->kind),
- entity->base.symbol->string);
+ source_position_t const *const pos = &attribute->source_position;
+ char const *const what = get_entity_kind_name(entity->kind);
+ symbol_t const *const sym = entity->base.symbol;
+ warningf(WARN_OTHER, pos, "packed attribute on %s '%S' ignored", what, sym);
return;
}
#endif
static void handle_attribute_packed(const attribute_t *attribute, type_t *type)
{
if (type->kind != TYPE_COMPOUND_STRUCT) {
- warningf(&attribute->source_position,
- "packed attribute on type '%T' ignored", type);
+ source_position_t const *const pos = &attribute->source_position;
+ warningf(WARN_OTHER, pos, "packed attribute on type '%T' ignored", type);
return;
}
case ATTRIBUTE_GNU_CONST: modifiers |= DM_CONST; break;
case ATTRIBUTE_GNU_DEPRECATED: modifiers |= DM_DEPRECATED; break;
case ATTRIBUTE_GNU_NOINLINE: modifiers |= DM_NOINLINE; break;
- case ATTRIBUTE_GNU_RETURNS_TWICE: modifiers |= DM_RETURNS_TWICE; break;
- case ATTRIBUTE_GNU_NORETURN: modifiers |= DM_NORETURN; break;
case ATTRIBUTE_GNU_NAKED: modifiers |= DM_NAKED; break;
case ATTRIBUTE_GNU_PURE: modifiers |= DM_PURE; break;
case ATTRIBUTE_GNU_ALWAYS_INLINE: modifiers |= DM_FORCEINLINE; break;
- case ATTRIBUTE_GNU_MALLOC: modifiers |= DM_MALLOC; break;
case ATTRIBUTE_GNU_CONSTRUCTOR: modifiers |= DM_CONSTRUCTOR; break;
case ATTRIBUTE_GNU_DESTRUCTOR: modifiers |= DM_DESTRUCTOR; break;
- case ATTRIBUTE_GNU_NOTHROW: modifiers |= DM_NOTHROW; break;
case ATTRIBUTE_GNU_TRANSPARENT_UNION:
modifiers |= DM_TRANSPARENT_UNION;
break;
case ATTRIBUTE_GNU_DLLEXPORT: modifiers |= DM_DLLEXPORT; break;
case ATTRIBUTE_GNU_WEAK: modifiers |= DM_WEAK; break;
- case ATTRIBUTE_MS_ALLOCATE: modifiers |= DM_MALLOC; break;
case ATTRIBUTE_MS_DLLIMPORT: modifiers |= DM_DLLIMPORT; break;
case ATTRIBUTE_MS_DLLEXPORT: modifiers |= DM_DLLEXPORT; break;
case ATTRIBUTE_MS_NAKED: modifiers |= DM_NAKED; break;
case ATTRIBUTE_MS_NOINLINE: modifiers |= DM_NOINLINE; break;
- case ATTRIBUTE_MS_RETURNS_TWICE: modifiers |= DM_RETURNS_TWICE; break;
- case ATTRIBUTE_MS_NORETURN: modifiers |= DM_NORETURN; break;
- case ATTRIBUTE_MS_NOTHROW: modifiers |= DM_NOTHROW; break;
case ATTRIBUTE_MS_THREAD: modifiers |= DM_THREAD; break;
case ATTRIBUTE_MS_DEPRECATED: modifiers |= DM_DEPRECATED; break;
case ATTRIBUTE_MS_RESTRICT: modifiers |= DM_RESTRICT; break;
return identify_new_type(new_type);
}
+static type_t *add_modifiers(type_t *type, decl_modifiers_t modifiers)
+{
+ if (is_typeref(type) || !is_type_function(type)) {
+ return type;
+ }
+
+ if ((type->function.modifiers & modifiers) == modifiers)
+ return type;
+
+ type_t* new_type = duplicate_type(type);
+ new_type->function.modifiers |= modifiers;
+ return identify_new_type(new_type);
+}
+
type_t *handle_type_attributes(const attribute_t *attributes, type_t *type)
{
const attribute_t *attribute = attributes;
case ATTRIBUTE_MS_THISCALL:
type = change_calling_convention(type, CC_THISCALL);
break;
+ case ATTRIBUTE_GNU_RETURNS_TWICE:
+ case ATTRIBUTE_MS_RETURNS_TWICE:
+ type = add_modifiers(type, DM_RETURNS_TWICE);
+ break;
+ case ATTRIBUTE_GNU_NORETURN:
+ case ATTRIBUTE_MS_NORETURN:
+ type = add_modifiers(type, DM_NORETURN);
+ break;
+ case ATTRIBUTE_GNU_MALLOC:
+ case ATTRIBUTE_MS_ALLOCATE:
+ type = add_modifiers(type, DM_MALLOC);
+ break;
+ case ATTRIBUTE_GNU_NOTHROW:
+ case ATTRIBUTE_MS_NOTHROW:
+ type = add_modifiers(type, DM_NOTHROW);
+ break;
case ATTRIBUTE_GNU_MODE:
type = handle_attribute_mode(attribute, type);
break;