diff --git a/gas/ChangeLog b/gas/ChangeLog index 9bf6931b48..19bdb16433 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2015-05-08 Nick Clifton + + PR gas/18347 + * config/tc-arm.h (TC_EQUAL_IN_INSN): Define. + * config/tc-arm.c (arm_tc_equal_in_insn): New function. Move + the symbol name checking code to here from... + (md_undefined_symbo): ... here. + 2015-05-08 H.J. Lu * config/tc-i386.c (no_shared): New. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 2f6fea6d00..683774f6ac 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -21625,6 +21625,49 @@ md_pcrel_from_section (fixS * fixP, segT seg) static bfd_boolean flag_warn_syms = TRUE; +bfd_boolean +arm_tc_equal_in_insn (int c ATTRIBUTE_UNUSED, char * name) +{ + /* PR 18347 - Warn if the user attempts to create a symbol with the same + name as an ARM instruction. Whilst strictly speaking it is allowed, it + does mean that the resulting code might be very confusing to the reader. + Also this warning can be triggered if the user omits an operand before + an immediate address, eg: + + LDR =foo + + GAS treats this as an assignment of the value of the symbol foo to a + symbol LDR, and so (without this code) it will not issue any kind of + warning or error message. + + Note - ARM instructions are case-insensitive but the strings in the hash + table are all stored in lower case, so we must first ensure that name is + lower case too. */ + if (flag_warn_syms && arm_ops_hsh) + { + char * nbuf = strdup (name); + char * p; + + for (p = nbuf; *p; p++) + *p = TOLOWER (*p); + if (hash_find (arm_ops_hsh, nbuf) != NULL) + { + static struct hash_control * already_warned = NULL; + + if (already_warned == NULL) + already_warned = hash_new (); + /* Only warn about the symbol once. To keep the code + simple we let hash_insert do the lookup for us. */ + if (hash_insert (already_warned, name, NULL) == NULL) + as_warn (_("[-mwarn-syms]: Assignment makes a symbol match an ARM instruction: %s"), name); + } + else + free (nbuf); + } + + return FALSE; +} + /* Under ELF we need to default _GLOBAL_OFFSET_TABLE. Otherwise we have no need to default values of symbols. */ @@ -21648,52 +21691,6 @@ md_undefined_symbol (char * name ATTRIBUTE_UNUSED) } #endif - /* PR 18347 - Warn if the user attempts to create a symbol with the same - name as an ARM instruction. Whilst strictly speaking it is allowed, it - does mean that the resulting code might be very confusing to the reader. - Also this warning can be triggered if the user omits an operand before - an immediate address, eg: - - LDR =foo - - GAS treats this as an assignment of the value of the symbol foo to a - symbol LDR, and so (without this code) it will not issue any kind of - warning or error message. - - Note - ARM instructions are case-insensitive but the strings in the hash - table are all stored in lower case, so we must first ensure that name is - lower case too. - - Some names are problematical. Several gas tests for example use: - - b: - - as a label, but of course this matches the branch instruction. For now - we punt and only check names longer than 1. - - FIXME: Should this be made into generic code for all targets ? */ - if (flag_warn_syms && arm_ops_hsh && strlen (name) > 1) - { - char * nbuf = strdup (name); - char * p; - - for (p = nbuf; *p; p++) - *p = TOLOWER (*p); - if (hash_find (arm_ops_hsh, nbuf) != NULL) - { - static struct hash_control * already_warned = NULL; - - if (already_warned == NULL) - already_warned = hash_new (); - /* Only warn about the symbol once. To keep the code - simple we let hash_insert do the lookup for us. */ - if (hash_insert (already_warned, name, NULL) == NULL) - as_warn (_("[-mwarn-syms]: Symbol '%s' matches an ARM instruction - is this intentional ?"), name); - } - else - free (nbuf); - } - return NULL; } diff --git a/gas/config/tc-arm.h b/gas/config/tc-arm.h index 22162672c1..22e9027a89 100644 --- a/gas/config/tc-arm.h +++ b/gas/config/tc-arm.h @@ -389,3 +389,6 @@ extern char arm_comment_chars[]; #define tc_line_separator_chars arm_line_separator_chars extern char arm_line_separator_chars[]; + +#define TC_EQUAL_IN_INSN(c, s) arm_tc_equal_in_insn ((c), (s)) +extern bfd_boolean arm_tc_equal_in_insn (int, char *); diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index d63f48a43d..b3efb8fd3c 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-05-08 Nick Clifton + + PR gas/18347 + * gas/arm/pr18347.s: Add tests of other symbol assignments which + should not generate the warning. + * gas/arm/pr18347.l: Update expected output. + 2015-05-08 H.J. Lu * gas/i386/i386.exp: Run relax-4 and x86-64-relax-3. diff --git a/gas/testsuite/gas/arm/pr18347.l b/gas/testsuite/gas/arm/pr18347.l index 12e223d06d..9ef0da83bf 100644 --- a/gas/testsuite/gas/arm/pr18347.l +++ b/gas/testsuite/gas/arm/pr18347.l @@ -1,2 +1,2 @@ [^:]*: Assembler messages: -[^:]*:2: Warning: \[-mwarn-syms\]: Symbol 'LDR' matches an ARM instruction - is this intentional \? +[^:]*:2: Warning: \[-mwarn-syms\]: Assignment makes a symbol match an ARM instruction: LDR diff --git a/gas/testsuite/gas/arm/pr18347.s b/gas/testsuite/gas/arm/pr18347.s index ac22b45d99..591d69baa8 100644 --- a/gas/testsuite/gas/arm/pr18347.s +++ b/gas/testsuite/gas/arm/pr18347.s @@ -1,3 +1,14 @@ MOV r1, r0 LDR =garbage // no destination register MOV r2, r3 + + // The warning should only be triggered by a "foo = bar" + // type of expression. Other ways of creating symbols + // should allow ARM instruction names. +b: + nop + +.set bx, fred +.equiv ldr, bar +.eqv nop, fred +.equ mov, foo