gcov: dump in a static dtor instead of in an atexit handler
authorMartin Liska <mliska@suse.cz>
Tue, 27 Sep 2016 11:07:11 +0000 (13:07 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 27 Sep 2016 11:07:11 +0000 (11:07 +0000)
PR gcov-profile/7970
PR gcov-profile/16855
PR gcov-profile/44779
* g++.dg/gcov/pr16855.C: New test.
* coverage.c (build_gcov_exit_decl): New function.
(coverage_obj_init): Call the function and generate __gcov_exit
destructor.
* doc/gcov.texi: Document when __gcov_exit function is called.
* libgcov-driver.c (__gcov_init): Do not register a atexit
handler.
(__gcov_exit): Rename from gcov_exit.
* libgcov.h (__gcov_exit): Declare.

From-SVN: r240529

gcc/ChangeLog
gcc/coverage.c
gcc/doc/gcov.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/gcov/pr16855.C [new file with mode: 0644]
libgcc/ChangeLog
libgcc/libgcov-driver.c
libgcc/libgcov.h

index d0691b2e06ff9f8a547aea51b232ce9d7c3b5e5c..d0ebc8e53edd616fd6108a1ad2eff1ec111bf190 100644 (file)
@@ -1,3 +1,13 @@
+2016-09-27  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/7970
+       PR gcov-profile/16855
+       PR gcov-profile/44779
+       * coverage.c (build_gcov_exit_decl): New function.
+       (coverage_obj_init): Call the function and generate __gcov_exit
+       destructor.
+       * doc/gcov.texi: Document when __gcov_exit function is called.
+
 2016-09-27  Marek Polacek  <polacek@redhat.com>
 
        PR bootstrap/77751
index 30cdc69e1873afcaba0d28da6ccf7d553a048c42..0b8c0b378435708c4fadb505811aec61b0d52070 100644 (file)
@@ -1055,8 +1055,30 @@ build_init_ctor (tree gcov_info_type)
   stmt = build_call_expr (init_fn, 1, stmt);
   append_to_statement_list (stmt, &ctor);
 
-  /* Generate a constructor to run it.  */
-  cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY);
+  /* Generate a constructor to run it (with priority 99).  */
+  cgraph_build_static_cdtor ('I', ctor, DEFAULT_INIT_PRIORITY - 1);
+}
+
+/* Generate the destructor function to call __gcov_exit.  */
+
+static void
+build_gcov_exit_decl (void)
+{
+  tree init_fn = build_function_type_list (void_type_node, void_type_node,
+                                          NULL);
+  init_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+                       get_identifier ("__gcov_exit"), init_fn);
+  TREE_PUBLIC (init_fn) = 1;
+  DECL_EXTERNAL (init_fn) = 1;
+  DECL_ASSEMBLER_NAME (init_fn);
+
+  /* Generate a call to __gcov_exit ().  */
+  tree dtor = NULL;
+  tree stmt = build_call_expr (init_fn, 0);
+  append_to_statement_list (stmt, &dtor);
+
+  /* Generate a destructor to run it (with priority 99).  */
+  cgraph_build_static_cdtor ('D', dtor, DEFAULT_INIT_PRIORITY - 1);
 }
 
 /* Create the gcov_info types and object.  Generate the constructor
@@ -1114,6 +1136,7 @@ coverage_obj_init (void)
   DECL_NAME (gcov_info_var) = get_identifier (name_buf);
 
   build_init_ctor (gcov_info_type);
+  build_gcov_exit_decl ();
 
   return true;
 }
index 1523cb14f0162f9b298ca2d1ea6e07736a2b2b68..1912f85422e1e15dab0da09f928db63998a9e91e 100644 (file)
@@ -600,6 +600,10 @@ facilities to restrict profile collection to the program region of
 interest. Calling @code{__gcov_reset(void)} will clear all profile counters
 to zero, and calling @code{__gcov_dump(void)} will cause the profile information
 collected at that point to be dumped to @file{.gcda} output files.
+Instrumented applications use a static destructor with priority 99
+to invoke the @code{__gcov_dump} function. Thus @code{__gcov_dump}
+is executed after all user defined static destructors,
+as well as handlers registered with @code{atexit}.
 
 @c man end
 
index d5240e6888b2b29382fd1480264c9bad4389f360..cefbca950f92b63700956ba8c9f0447b90e94a47 100644 (file)
@@ -1,3 +1,10 @@
+2016-09-27  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/7970
+       PR gcov-profile/16855
+       PR gcov-profile/44779
+       * g++.dg/gcov/pr16855.C: New test.
+
 2016-09-27  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
        * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Require int32plus.
diff --git a/gcc/testsuite/g++.dg/gcov/pr16855.C b/gcc/testsuite/g++.dg/gcov/pr16855.C
new file mode 100644 (file)
index 0000000..91801d4
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+#include <stdlib.h>
+
+int a;
+
+void foo()
+{
+  a = 123;                                               /* count(1) */
+}
+
+#include <iostream>
+using namespace std;
+class Test {
+public:
+       Test(void){
+       cout<< "In Test ctor" << endl;                    /* count(1) */
+       }
+       ~Test(void){
+       cout<< "In Test dtor" << endl;                    /* count(1) */
+       }
+}T1;
+
+void uncalled(void){
+       cout<< "In uncalled" << endl;                     /* count(#####) */
+}
+int main(void){
+atexit (&foo);
+// Test T2;
+cout<< "In main" << endl;                                /* count(1) */
+return 0;
+}
+
+#include <stdio.h>
+
+__attribute__((constructor))
+static void construct_navigationBarImages() {
+  fprintf (stderr,  "((construct_navigationBarImages))"); /* count(1) */
+}
+
+__attribute__((destructor))
+static void destroy_navigationBarImages() {
+  fprintf (stderr,  "((destroy_navigationBarImages))");          /* count(1) */
+}
+
+/* { dg-final { run-gcov branches { -b pr16855.C } } } */
index 1b4fd93f4ce2f96bf4a299e45a0eb3f33c194622..d1b2d21e2e910b98893cbfe44c4140f9b3f8b069 100644 (file)
@@ -1,3 +1,13 @@
+2016-09-27  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/7970
+       PR gcov-profile/16855
+       PR gcov-profile/44779
+       * libgcov-driver.c (__gcov_init): Do not register a atexit
+       handler.
+       (__gcov_exit): Rename from gcov_exit.
+       * libgcov.h (__gcov_exit): Declare.
+
 2016-09-27  Martin Liska  <mliska@suse.cz>
 
        PR bootstrap/77749
index d51397e0f8a0d8d48063fbe4f4b14e0a252a6f7c..84471bd8162345f2afb0cfb0cd4981cf93b211df 100644 (file)
@@ -872,8 +872,8 @@ struct gcov_root __gcov_root;
 struct gcov_master __gcov_master = 
   {GCOV_VERSION, 0};
 
-static void
-gcov_exit (void)
+void
+__gcov_exit (void)
 {
   __gcov_dump_one (&__gcov_root);
   if (__gcov_root.next)
@@ -906,7 +906,6 @@ __gcov_init (struct gcov_info *info)
                __gcov_master.root->prev = &__gcov_root;
              __gcov_master.root = &__gcov_root;
            }
-         atexit (gcov_exit);
        }
 
       info->next = __gcov_root.list;
index 725ef0a6283fdfaa19798fdc8b5cc7694b0cf73b..dc74134b8cadd0cdf88b42e2fc9b1d9fa18aabd4 100644 (file)
@@ -234,6 +234,9 @@ extern void __gcov_dump_one (struct gcov_root *) ATTRIBUTE_HIDDEN;
 /* Register a new object file module.  */
 extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN;
 
+/* GCOV exit function registered via a static destructor.  */
+extern void __gcov_exit (void) ATTRIBUTE_HIDDEN;
+
 /* Called before fork, to avoid double counting.  */
 extern void __gcov_flush (void) ATTRIBUTE_HIDDEN;