-*- text -*-
+* Add .errif and .warnif directives, permitting user-controlled diagnostics
+ with conditionals that are evaluated only at the end of assembly.
+
* Predefined symbols "GAS(version)" and, on non-release builds, "GAS(date)" are
now being made available.
* Equiv:: @code{.equiv @var{symbol}, @var{expression}}
* Eqv:: @code{.eqv @var{symbol}, @var{expression}}
* Err:: @code{.err}
+* Errif:: @code{.errif @var{expression}}
* Error:: @code{.error @var{string}}
* Exitm:: @code{.exitm}
* Extern:: @code{.extern}
* VTableInherit:: @code{.vtable_inherit @var{child}, @var{parent}}
@end ifset
+* Warnif:: @code{.warnif @var{expression}}
* Warning:: @code{.warning @var{string}}
* Weak:: @code{.weak @var{names}}
* Weakref:: @code{.weakref @var{alias}, @var{symbol}}
message and, unless the @option{-Z} option was used, it will not generate an
object file. This can be used to signal an error in conditionally compiled code.
+@node Errif
+@section @code{.errif "@var{expression}"}
+@cindex errif directive
+
+Record @var{expression} for evaluation at the end of assembly. Raise an error
+if the expression evaluates to non-zero.
+
@node Error
@section @code{.error "@var{string}"}
@cindex error directive
parent name of @code{0} is treated as referring to the @code{*ABS*} section.
@end ifset
+@node Warnif
+@section @code{.warnif "@var{expression}"}
+@cindex errif directive
+
+Record @var{expression} for evaluation at the end of assembly. Raise a
+warning if the expression evaluates to non-zero.
+
@node Warning
@section @code{.warning "@var{string}"}
@cindex warning directive
static void do_s_func (int end_p, const char *default_prefix);
static void s_altmacro (int);
static void s_bad_end (int);
+static void s_errwarn_if (int);
static void s_reloc (int);
static int hex_float (int, char *);
static segT get_known_segmented_expression (expressionS * expP);
{"equiv", s_set, 1},
{"eqv", s_set, -1},
{"err", s_err, 0},
+ {"errif", s_errwarn_if, 1},
{"error", s_errwarn, 1},
{"exitm", s_mexit, 0},
/* extend */
{"xdef", s_globl, 0},
{"xref", s_ignore, 0},
{"xstabs", s_xstab, 's'},
+ {"warnif", s_errwarn_if, 0},
{"warning", s_errwarn, 0},
{"weakref", s_weakref, 0},
{"word", cons, 2},
demand_empty_rest_of_line ();
}
+/* Handle the .errif and .warnif pseudo-ops. */
+
+static struct deferred_diag {
+ struct deferred_diag *next;
+ const char *file;
+ unsigned int lineno;
+ bool err;
+ expressionS exp;
+} *deferred_diags, *last_deferred_diag;
+
+static void
+s_errwarn_if (int err)
+{
+ struct deferred_diag *diag = XNEW (struct deferred_diag);
+ int errcnt = had_errors ();
+
+ deferred_expression (&diag->exp);
+ if (errcnt != had_errors ())
+ {
+ ignore_rest_of_line ();
+ return;
+ }
+
+ diag->err = err;
+ diag->file = as_where (&diag->lineno);
+ diag->next = NULL;
+ if ( deferred_diags == NULL )
+ deferred_diags = diag;
+ else
+ last_deferred_diag->next = diag;
+ last_deferred_diag = diag;
+
+ demand_empty_rest_of_line ();
+}
+
+void
+evaluate_deferred_diags (void)
+{
+ struct deferred_diag *diag;
+
+ for (diag = deferred_diags; diag != NULL; diag = diag->next)
+ {
+ if (!resolve_expression (&diag->exp) || diag->exp.X_op != O_constant)
+ as_warn_where (diag->file, diag->lineno,
+ _("expression does not evaluate to a constant"));
+ else if (diag->exp.X_add_number == 0)
+ continue;
+ else if (diag->err)
+ as_bad_where (diag->file, diag->lineno,
+ _(".errif expression evaluates to true"));
+ else
+ as_warn_where (diag->file, diag->lineno,
+ _(".warnif expression evaluates to true"));
+ }
+}
+
/* Handle the MRI fail pseudo-op. */
void
extern symbolS *s_lcomm_internal (int, symbolS *, addressT);
extern void temp_ilp (char *);
extern void restore_ilp (void);
+extern void evaluate_deferred_diags (void);
extern void s_file_string (char *);
extern void s_abort (int) ATTRIBUTE_NORETURN;
--- /dev/null
+# This should match the output of gas cond-diag.s.
+.*: Assembler messages:
+.*:1: Error: non-constant .*
+.*:6: Error: backward ref .*
+.*:7: Warning: \.warning .*
+.*:4: Warning: \.warnif .*
--- /dev/null
+ .if end - start > 16
+ .warning
+ .endif
+ .warnif end - start < 16
+ .errif end - start >= 16
+ .warnif 1b
+ .warning
+
+ .data
+start:
+ .uleb128 end - start
+end:
}
}
+# This test uses a local label, which some targets don't support.
+# MeP can't deal with forward ref labels in .uleb128.
+switch -glob $target_triplet {
+ *c54x*-*-* { }
+ hppa*-*-* { }
+ ia64-*-*vms* { }
+ mep-*-* { }
+ sh-*-pe* { }
+ default {
+ run_list_test "cond-diag"
+ }
+}
+
gas_test_error "weakref2.s" "" "e: would close weakref loop: e => a => b => c => d => e"
gas_test_error "weakref3.s" "" "a: would close weakref loop: a => b => c => d => e => a"
gas_test_error "weakref4.s" "" "is already defined"
resolve_local_symbol_values ();
resolve_reloc_expr_symbols ();
+ evaluate_deferred_diags ();
+
#ifdef OBJ_ELF
if (IS_ELF)
maybe_generate_build_notes ();