]> gcc.gnu.org Git - gcc.git/commitdiff
expr.c (expand_expr_real_1): Use get_callee_fndecl instead of checking CALL_EXPR_FN...
authorJakub Jelinek <jakub@redhat.com>
Sun, 23 Sep 2007 09:39:39 +0000 (11:39 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sun, 23 Sep 2007 09:39:39 +0000 (11:39 +0200)
* expr.c (expand_expr_real_1) <case CALL_EXPR>: Use get_callee_fndecl
instead of checking CALL_EXPR_FN directly to test for builtins.
If error or warning attributes are present, print
error resp. warning.
* c-common.c (handle_error_attribute): New function.
(c_common_attribute_table): Add error and warning
attributes.
* doc/extend.texi: Document error and warning attributes.

* gcc.dg/va-arg-pack-len-1.c: Use error and warning
attributes.
* gcc.dg/va-arg-pack-len-2.c: New test.
* g++.dg/ext/va-arg-pack-len-1.C: Use error and warning
attributes.
* g++.dg/ext/va-arg-pack-len-2.C: New test.

From-SVN: r128687

gcc/ChangeLog
gcc/c-common.c
gcc/doc/extend.texi
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/va-arg-pack-len-1.C
gcc/testsuite/g++.dg/ext/va-arg-pack-len-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/va-arg-pack-len-1.c
gcc/testsuite/gcc.dg/va-arg-pack-len-2.c [new file with mode: 0644]

index f8ea8a1fd0a31b9d0df9b4b57623133c50d21961..cfad806a99b9a1969285e76dde0120b9dd9c8e80 100644 (file)
@@ -1,5 +1,14 @@
 2007-09-23  Jakub Jelinek  <jakub@redhat.com>
 
+       * expr.c (expand_expr_real_1) <case CALL_EXPR>: Use get_callee_fndecl
+       instead of checking CALL_EXPR_FN directly to test for builtins.
+       If error or warning attributes are present, print
+       error resp. warning.
+       * c-common.c (handle_error_attribute): New function.
+       (c_common_attribute_table): Add error and warning
+       attributes.
+       * doc/extend.texi: Document error and warning attributes.
+
        * tree.h (block_nonartificial_location): New prototype.
        * tree.c (block_nonartificial_location): New function.
        * dwarf2out.c (gen_subprogram_die): Add DW_AT_artificial
index 3b5f477f5f938cdf4a62ee1c9fec541de088a05c..8ebc92007cacdc84ec41cfffdf43fc637831c23e 100644 (file)
@@ -518,6 +518,7 @@ static tree handle_always_inline_attribute (tree *, tree, tree, int,
 static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
 static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
 static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
+static tree handle_error_attribute (tree *, tree, tree, int, bool *);
 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
 static tree handle_externally_visible_attribute (tree *, tree, tree, int,
@@ -663,6 +664,10 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_cold_attribute },
   { "hot",                    0, 0, true,  false, false,
                              handle_hot_attribute },
+  { "warning",               1, 1, true,  false, false,
+                             handle_error_attribute },
+  { "error",                 1, 1, true,  false, false,
+                             handle_error_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -4923,6 +4928,26 @@ handle_flatten_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+/* Handle a "warning" or "error" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_error_attribute (tree *node, tree name, tree args,
+                       int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL
+      || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+    /* Do nothing else, just set the attribute.  We'll get at
+       it later with lookup_attribute.  */
+    ;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
 
 /* Handle a "used" attribute; arguments as in
    struct attribute_spec.handler.  */
index de3a1211c738d160697cbc159acff14c47dc37c0..a4f7a3a68cef295747d7a8cd795cfcf379415033 100644 (file)
@@ -1803,7 +1803,8 @@ attributes are currently defined for functions on all targets:
 @code{destructor}, @code{used}, @code{unused}, @code{deprecated},
 @code{weak}, @code{malloc}, @code{alias}, @code{warn_unused_result},
 @code{nonnull}, @code{gnu_inline}, @code{externally_visible},
-@code{hot}, @code{cold} and @code{artificial}.
+@code{hot}, @code{cold}, @code{artificial}, @code{error}
+and @code{warning}.
 Several other attributes are defined for functions on particular
 target systems.  Other attributes, including @code{section} are
 supported for variables declarations (@pxref{Variable Attributes}) and
@@ -1941,6 +1942,30 @@ Whether the function itself is considered for inlining depends on its size and
 the current inlining parameters.  The @code{flatten} attribute only works
 reliably in unit-at-a-time mode.
 
+@item error ("@var{message}")
+@cindex @code{error} function attribute
+If this attribute is used on a function declaration and a call to such a function
+is not eliminated through dead code elimination or other optimizations, an error
+which will include @var{message} will be diagnosed.  This is useful
+for compile time checking, especially together with @code{__builtin_constant_p}
+and inline functions where checking the inline function arguments is not
+possible through @code{extern char [(condition) ? 1 : -1];} tricks.
+While it is possible to leave the function undefined and thus invoke
+a link failure, when using this attribute the problem will be diagnosed
+earlier and with exact location of the call even in presence of inline
+functions or when not emitting debugging information.
+
+@item warning ("@var{message}")
+@cindex @code{warning} function attribute
+If this attribute is used on a function declaration and a call to such a function
+is not eliminated through dead code elimination or other optimizations, a warning
+which will include @var{message} will be diagnosed.  This is useful
+for compile time checking, especially together with @code{__builtin_constant_p}
+and inline functions.  While it is possible to define the function with
+a message in @code{.gnu.warning*} section, when using this attribute the problem
+will be diagnosed earlier and with exact location of the call even in presence
+of inline functions or when not emitting debugging information.
+
 @item cdecl
 @cindex functions that do pop the argument stack on the 386
 @opindex mrtd
index c7b29b53c942319a0093d438b64bb6a7f46a9841..afd01acb4aa569f5140cd3fa5d8b75bc15d4f632 100644 (file)
@@ -8002,21 +8002,32 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         inlining.  */
       if (CALL_EXPR_VA_ARG_PACK (exp))
        error ("invalid use of %<__builtin_va_arg_pack ()%>");
-      /* Check for a built-in function.  */
-      if (TREE_CODE (CALL_EXPR_FN (exp)) == ADDR_EXPR
-         && (TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (exp), 0))
-             == FUNCTION_DECL)
-         && DECL_BUILT_IN (TREE_OPERAND (CALL_EXPR_FN (exp), 0)))
-       {
-         if (DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (exp), 0))
-             == BUILT_IN_FRONTEND)
-           return lang_hooks.expand_expr (exp, original_target,
-                                          tmode, modifier,
-                                          alt_rtl);
-         else
-           return expand_builtin (exp, target, subtarget, tmode, ignore);
-       }
-
+      {
+       tree fndecl = get_callee_fndecl (exp), attr;
+
+       if (fndecl
+           && (attr = lookup_attribute ("error",
+                                        DECL_ATTRIBUTES (fndecl))) != NULL)
+         error ("call to %qs declared with attribute error: %s",
+                lang_hooks.decl_printable_name (fndecl, 1),
+                TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+       if (fndecl
+           && (attr = lookup_attribute ("warning",
+                                        DECL_ATTRIBUTES (fndecl))) != NULL)
+         warning (0, "call to %qs declared with attribute warning: %s",
+                  lang_hooks.decl_printable_name (fndecl, 1),
+                  TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+
+       /* Check for a built-in function.  */
+       if (fndecl && DECL_BUILT_IN (fndecl))
+         {
+           if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND)
+             return lang_hooks.expand_expr (exp, original_target,
+                                            tmode, modifier, alt_rtl);
+           else
+             return expand_builtin (exp, target, subtarget, tmode, ignore);
+         }
+      }
       return expand_call (exp, target, ignore);
 
     case NON_LVALUE_EXPR:
index a6d166095a3af948917b1195295e9b64ef6f3b1a..294cf33e11defd20c93aa34af76fee4c7959dd6e 100644 (file)
@@ -1,5 +1,12 @@
 2007-09-23  Jakub Jelinek  <jakub@redhat.com>
 
+       * gcc.dg/va-arg-pack-len-1.c: Use error and warning
+       attributes.
+       * gcc.dg/va-arg-pack-len-2.c: New test.
+       * g++.dg/ext/va-arg-pack-len-1.C: Use error and warning
+       attributes.
+       * g++.dg/ext/va-arg-pack-len-2.C: New test.
+
        PR middle-end/28755
        * gcc.dg/pr28755.c: New test.
 
index 36104cf840b36460cc48232ef88c40578afb8ad3..d3c84091b8f03f1c99ec10aa2198e80af69cc363 100644 (file)
@@ -3,8 +3,10 @@
 
 #include <stdarg.h>
 
-extern "C" int warn_open_missing_mode (void);
-extern "C" int warn_open_too_many_arguments (void);
+extern "C" int error_open_missing_mode (void)
+  __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
+extern "C" int warn_open_too_many_arguments (void)
+  __attribute__((__warning__ ("open called with more than 3 arguments")));
 extern "C" void abort (void);
 
 char expected_char;
@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...)
     {
       if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
        {
-         warn_open_missing_mode ();
+         error_open_missing_mode ();
          return myopen2 (path, oflag);
        }
       return myopenva (path, oflag, __builtin_va_arg_pack ());
diff --git a/gcc/testsuite/g++.dg/ext/va-arg-pack-len-2.C b/gcc/testsuite/g++.dg/ext/va-arg-pack-len-2.C
new file mode 100644 (file)
index 0000000..0d369bd
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-do compile }
+// { dg-options "-O2" }
+
+#include <stdarg.h>
+
+extern int error_open_missing_mode (void)
+  __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
+extern int warn_open_too_many_arguments (void)
+  __attribute__((__warning__ ("open called with more than 3 arguments")));
+
+extern int myopen2 (const char *path, int oflag);
+extern int myopenva (const char *path, int oflag, ...);
+
+extern inline __attribute__((always_inline, gnu_inline)) int
+myopen (const char *path, int oflag, ...)
+{
+  if (__builtin_va_arg_pack_len () > 1)
+    warn_open_too_many_arguments ();   // { dg-warning "called with more than 3" }
+
+  if (__builtin_constant_p (oflag))
+    {
+      if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
+       {
+         error_open_missing_mode ();   // { dg-error "needs 3 arguments, only 2 were given" }
+         return myopen2 (path, oflag);
+       }
+      return myopenva (path, oflag, __builtin_va_arg_pack ());
+    }
+
+  if (__builtin_va_arg_pack_len () < 1)
+    return myopen2 (path, oflag);
+
+  return myopenva (path, oflag, __builtin_va_arg_pack ());
+}
+
+int
+main (void)
+{
+  myopen ("h", 0x43);
+  myopen ("i", 0x43, 0644, 0655);
+  return 0;
+}
index 7df638006882741fb04413b3fbe599a12e9a1e39..409c345850849aea2bc6c07bbb7797e3d60915b6 100644 (file)
@@ -3,8 +3,10 @@
 
 #include <stdarg.h>
 
-extern int warn_open_missing_mode (void);
-extern int warn_open_too_many_arguments (void);
+extern int error_open_missing_mode (void)
+  __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
+extern int warn_open_too_many_arguments (void)
+  __attribute__((__warning__ ("open called with more than 3 arguments")));
 extern void abort (void);
 
 char expected_char;
@@ -83,7 +85,7 @@ myopen (const char *path, int oflag, ...)
     {
       if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
        {
-         warn_open_missing_mode ();
+         error_open_missing_mode ();
          return myopen2 (path, oflag);
        }
       return myopenva (path, oflag, __builtin_va_arg_pack ());
diff --git a/gcc/testsuite/gcc.dg/va-arg-pack-len-2.c b/gcc/testsuite/gcc.dg/va-arg-pack-len-2.c
new file mode 100644 (file)
index 0000000..c3fa856
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <stdarg.h>
+
+extern int error_open_missing_mode (void)
+  __attribute__((__error__ ("open with O_CREAT needs 3 arguments, only 2 were given")));
+extern int warn_open_too_many_arguments (void)
+  __attribute__((__warning__ ("open called with more than 3 arguments")));
+
+extern int myopen2 (const char *path, int oflag);
+extern int myopenva (const char *path, int oflag, ...);
+
+extern inline __attribute__((always_inline, gnu_inline)) int
+myopen (const char *path, int oflag, ...)
+{
+  if (__builtin_va_arg_pack_len () > 1)
+    warn_open_too_many_arguments ();   /* { dg-warning "called with more than 3" } */
+
+  if (__builtin_constant_p (oflag))
+    {
+      if ((oflag & 0x40) != 0 && __builtin_va_arg_pack_len () < 1)
+       {
+         error_open_missing_mode ();   /* { dg-error "needs 3 arguments, only 2 were given" } */
+         return myopen2 (path, oflag);
+       }
+      return myopenva (path, oflag, __builtin_va_arg_pack ());
+    }
+
+  if (__builtin_va_arg_pack_len () < 1)
+    return myopen2 (path, oflag);
+
+  return myopenva (path, oflag, __builtin_va_arg_pack ());
+}
+
+int
+main (void)
+{
+  myopen ("h", 0x43);
+  myopen ("i", 0x43, 0644, 0655);
+  return 0;
+}
This page took 0.145649 seconds and 5 git commands to generate.