if (attributes != NULL) {
handle_entity_attributes(attributes, entity);
+ // TODO: maybe drop alias symbol here if not file_scope
}
if (entity->kind == ENTITY_FUNCTION && !freestanding) {
static bool is_main(entity_t*);
+/*
+__attribute__(alias("sym")) provides a definition
+in function scope function and variable declarations
+
+the sym must be declared in the same translation unit
+but the sym declaration can come later than the alias one
+(weakref is not supported)
+
+sym must be marked used
+*/
+static struct alias {
+ struct alias *next;
+ entity_t *entity;
+ symbol_t *symbol;
+} *aliases;
+static void add_alias(entity_t *entity, symbol_t *symbol)
+{
+ struct alias *a;
+
+ assert(entity->kind == ENTITY_FUNCTION || entity->kind == ENTITY_VARIABLE);
+ a = malloc(sizeof *a);
+ a->entity = entity;
+ a->symbol = symbol;
+ a->next = aliases;
+ aliases = a;
+}
+static void mark_aliases_used(void)
+{
+ struct alias *alias;
+ for (alias = aliases; alias; alias = alias->next) {
+ const namespace_tag_t namespc = (namespace_tag_t)alias->entity->base.namespc;
+ entity_t *entity = get_entity(alias->symbol, namespc);
+ if (entity == NULL) {
+ errorf(&alias->entity->base.pos, "'%N' is aliased to undefined symbol \"%s\"", alias->entity, alias->symbol->string);
+ } else if (entity->base.parent_scope != file_scope) {
+ errorf(&alias->entity->base.pos, "'%N' is aliased to undefined symbol \"%s\" (TODO: scope)", alias->entity, alias->symbol->string);
+ } else {
+ // printf("handle alias %s -> %s\n", alias->entity->base.symbol->string, alias->symbol->string);
+ assert(entity->kind == ENTITY_FUNCTION || entity->kind == ENTITY_VARIABLE);
+ entity->declaration.used = true;
+ }
+ }
+}
+
/**
* record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
* for various problems that occur for multiple definitions
warningf(WARN_NESTED_EXTERNS, pos, "nested extern declaration of '%#N'", entity);
}
+ if (current_scope == file_scope) {
+ if (entity->kind == ENTITY_FUNCTION) {
+ if (entity->function.alias) {
+ if (is_definition)
+ errorf(pos, "definition of '%N' with alias attribute", entity);
+ /* TODO alias provides a definition */
+ *(bool*)&is_definition = true;
+ add_alias(entity, entity->function.alias);
+ }
+ }
+ if (entity->kind == ENTITY_VARIABLE) {
+ if (entity->variable.alias) {
+ if (is_definition)
+ errorf(pos, "definition of '%N' with alias attribute", entity);
+ /* TODO alias provides a definition */
+ *(bool*)&is_definition = true;
+ add_alias(entity, entity->variable.alias);
+ }
+ }
+ }
+
if (previous_entity != NULL) {
position_t const *const ppos = &previous_entity->base.pos;
}
}
+ /* merge alias attribute into earlier declaration */
+ if (entity->kind == ENTITY_FUNCTION) {
+ if (entity->function.alias)
+ previous_entity->function.alias = entity->function.alias;
+ }
+ if (entity->kind == ENTITY_VARIABLE) {
+ if (entity->variable.alias)
+ previous_entity->variable.alias = entity->variable.alias;
+ }
+
prev_decl->modifiers |= decl->modifiers;
if (entity->kind == ENTITY_FUNCTION) {
previous_entity->function.is_inline |= entity->function.is_inline;
*/
static void check_unused_globals(void)
{
+ mark_aliases_used();
+
if (!is_warn_on(WARN_UNUSED_FUNCTION) && !is_warn_on(WARN_UNUSED_VARIABLE))
return;