+/**
+ * Return the declaration for a given label symbol or create a new one.
+ *
+ * @param symbol the symbol of the label
+ */
+static declaration_t *get_label(symbol_t *symbol)
+{
+ declaration_t *candidate;
+ assert(current_function != NULL);
+
+ candidate = get_declaration(symbol, NAMESPACE_LOCAL_LABEL);
+ /* if we found a local label, we already created the declaration */
+ if (candidate != NULL) {
+ assert(candidate->parent_scope == scope);
+ return candidate;
+ }
+
+ candidate = get_declaration(symbol, NAMESPACE_LABEL);
+ /* if we found a label in the same function, then we already created the
+ * declaration */
+ if (candidate != NULL
+ && candidate->parent_scope == ¤t_function->scope) {
+ return candidate;
+ }
+
+ /* otherwise we need to create a new one */
+ declaration_t *const declaration = allocate_declaration_zero();
+ declaration->namespc = NAMESPACE_LABEL;
+ declaration->symbol = symbol;
+
+ label_push(declaration);
+
+ return declaration;
+}
+
+/**
+ * Parses a GNU && label address expression.
+ */
+static expression_t *parse_label_address(void)
+{
+ source_position_t source_position = token.source_position;
+ eat(T_ANDAND);
+ if (token.type != T_IDENTIFIER) {
+ parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
+ goto end_error;
+ }
+ symbol_t *symbol = token.v.symbol;
+ next_token();
+
+ declaration_t *label = get_label(symbol);
+
+ label->used = true;
+ label->address_taken = true;
+
+ expression_t *expression = allocate_expression_zero(EXPR_LABEL_ADDRESS);
+ expression->base.source_position = source_position;
+
+ /* label address is threaten as a void pointer */
+ expression->base.type = type_void_ptr;
+ expression->label_address.declaration = label;
+ return expression;
+end_error:
+ return create_invalid_expression();
+}
+