===================================================================
@@ -585,6 +585,10 @@
C++ ObjC++ Var(warn_namespaces) Warning
Warn on namespace definition.
+Wonly-top-basic-asm
+C ObjC ObjC++ C++ Var(warn_only_top_basic_asm) Warning
+Warn on unsafe uses of basic asm.
+
Wsized-deallocation
C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra)
Warn about missing sized deallocation functions.
===================================================================
@@ -5973,7 +5973,18 @@
labels = NULL_TREE;
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
+ {
+ /* Warn on basic asm used inside of functions,
+ EXCEPT when in naked functions. Also allow asm(""). */
+ if (warn_only_top_basic_asm && TREE_STRING_LENGTH (str) != 1)
+ if (lookup_attribute ("naked",
+ DECL_ATTRIBUTES (current_function_decl))
+ == NULL_TREE)
+ warning_at (asm_loc, OPT_Wonly_top_basic_asm,
+ "asm statement in function does not use extended syntax");
+
goto done_asm;
+ }
/* Parse each colon-delimited section of operands. */
nsections = 3 + is_goto;
===================================================================
@@ -18003,6 +18003,8 @@
bool goto_p = false;
required_token missing = RT_NONE;
+ location_t asm_loc = cp_lexer_peek_token (parser->lexer)->location;
+
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, RT_ASM);
@@ -18161,6 +18163,17 @@
/* If the extended syntax was not used, mark the ASM_EXPR. */
if (!extended_p)
{
+ /* Warn on basic asm used inside of functions,
+ EXCEPT when in naked functions. Also allow asm(""). */
+ if (warn_only_top_basic_asm
+ && TREE_STRING_LENGTH (string) != 1)
+ if (lookup_attribute("naked",
+ DECL_ATTRIBUTES (current_function_decl))
+ == NULL_TREE)
+ warning_at (asm_loc, OPT_Wonly_top_basic_asm,
+ "asm statement in function does not use extended"
+ " syntax");
+
tree temp = asm_stmt;
if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
temp = TREE_OPERAND (temp, 0);
===================================================================
@@ -7458,7 +7458,8 @@
@end table
@subsubheading Remarks
-Using extended @code{asm} typically produces smaller, safer, and more
+Using extended @code{asm} (@pxref{Extended Asm}) typically produces smaller,
+safer, and more
efficient code, and in most cases it is a better solution than basic
@code{asm}. However, there are two situations where only basic @code{asm}
can be used:
@@ -7516,11 +7517,51 @@
Basic @code{asm} provides no
mechanism to provide different assembler strings for different dialects.
-Here is an example of basic @code{asm} for i386:
+Basic @code{asm} statements do not perform an implicit "memory" clobber
+(@pxref{Clobbers}). Also, there is no implicit clobbering of @emph{any}
+registers, so (other than in @code{naked} functions which follow the ABI
+rules) changed registers must be restored to their original value before
+exiting the @code{asm}. While this behavior has not always been
+documented, GCC has worked this way since at least v2.95.3.
+@strong{Warning:} This "clobber nothing" behavior may be different than how
+other compilers treat basic @code{asm}, since the C standards for the
+@code{asm} statement provide no guidance regarding these semantics. As a
+result, @code{asm} statements that work correctly on other compilers may not
+work correctly with GCC (and vice versa), even though they both compile
+without error.
+
+Future versions of GCC may change basic @code{asm} to clobber memory and
+perhaps some (or all) registers. This change may fix subtle problems with
+existing @code{asm} statements. However it may break or slow down ones
+that were working correctly. To ``future-proof'' your asm against possible
+changes to basic @code{asm}'s semantics, use extended @code{asm}.
+
+You can use @option{-Wonly-top-basic-asm} to locate basic @code{asm}
+statements that may need changes, and refer to
+@uref{https://gcc.gnu.org/wiki/ConvertBasicAsmToExtended, How to convert
+from basic asm to extended asm} for information about how to perform the
+conversion.
+
+Here is an example of top-level basic @code{asm} for i386 that defines an
+asm macro. That macro is then invoked from within a function using
+extended @code{asm}:
+
@example
-/* Note that this code will not compile with -masm=intel */
-#define DebugBreak() asm("int $3")
+/* Define macro at file scope with basic asm. */
+/* Add macro parameter p to eax. */
+asm(".macro test p\n\t"
+ "addl $\\p, %eax\n\t"
+ ".endm");
+
+/* Use macro in function using extended asm. It needs */
+/* the "cc" clobber since the flags are changed and uses */
+/* the "a" constraint since it modifies eax. */
+int DoAdd(int value)
+@{
+ asm("test 5" : "+a" (value) : : "cc");
+ return value;
+@}
@end example
@node Extended Asm
@@ -8047,7 +8088,7 @@
for @code{d} by specifying both constraints.
@anchor{FlagOutputOperands}
-@subsection Flag Output Operands
+@subsubsection Flag Output Operands
@cindex @code{asm} flag output operands
Some targets have a special register that holds the ``flags'' for the
===================================================================
@@ -5693,6 +5693,21 @@
a structure that has been marked with the @code{designated_init}
attribute.
+@item -Wonly-top-basic-asm @r{(C and C++ only)}
+Warn if basic @code{asm} statements are used inside a function (i.e. not at
+top-level/file scope).
+
+When used inside of functions, basic @code{asm} can result in unexpected and
+unwanted variations in behavior between compilers due to how registers are
+handled when calling the asm (@pxref{Basic Asm}). The lack of input and
+output constraints (@pxref{Extended Asm}) can also make it difficult for
+optimizers to correctly and consistently position the output relative to
+other code.
+
+Functions that are marked with the @option{naked} attribute (@pxref{Function
+Attributes}) and @code{asm} statements with an empty instruction string are
+excluded from this check.
+
@item -Whsa
Issue a warning when HSAIL cannot be emitted for the compiled function or
OpenMP construct.
===================================================================
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target naked_functions } */
+/* { dg-options "-Wonly-top-basic-asm" } */
+
+int __attribute__((naked))
+func (int x, int y)
+{
+ /* basic asm should not warn in naked functions. */
+ asm(" "); /* no warning */
+}
+
+int main(int argc, char *argv[])
+{
+ return func(argc, argc);
+}
===================================================================
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-Wonly-top-basic-asm" } */
+
+/* acceptable */
+register int b asm("esi");
+
+/* acceptable */
+int foo asm ("myfoo") = 2;
+
+/* acceptable */
+asm ("# top level");
+
+/* acceptable */
+int func (int x, int y) asm ("MYFUNC");
+
+int main(int argc, char *argv[])
+{
+ /* acceptable */
+ register int a asm("edi");
+
+ /* acceptable */
+ asm("#"::"r"(a), "r" (b));
+
+ /* acceptable */
+ asm goto (""::::done);
+
+ /* acceptable */
+ asm("");
+
+ /* warning */
+ asm(" "); /* { dg-warning "does not use extended syntax" } */
+
+ done:
+ return 0;
+}