summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarxin <marxin@138bc75d-0d04-0410-961f-82ee72b054a4>2016-09-27 11:07:11 +0000
committermarxin <marxin@138bc75d-0d04-0410-961f-82ee72b054a4>2016-09-27 11:07:11 +0000
commitdb46bcd377f4b4a26b9807a7cb3565a161178660 (patch)
tree0dfe81cd421cbccec0f0b4ed0c7bdb2943ad2f00
parent2e0bcd964c73da2188d7ac68f563035fd78dad05 (diff)
downloadgcc-db46bcd377f4b4a26b9807a7cb3565a161178660.tar.gz
gcov: dump in a static dtor instead of in an atexit handler
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240529 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/coverage.c27
-rw-r--r--gcc/doc/gcov.texi4
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/gcov/pr16855.C47
-rw-r--r--libgcc/ChangeLog10
-rw-r--r--libgcc/libgcov-driver.c5
-rw-r--r--libgcc/libgcov.h3
8 files changed, 108 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d0691b2e06f..d0ebc8e53ed 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 30cdc69e187..0b8c0b37843 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -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;
}
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index 1523cb14f01..1912f85422e 100644
--- a/gcc/doc/gcov.texi
+++ b/gcc/doc/gcov.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d5240e6888b..cefbca950f9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..91801d4d1e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gcov/pr16855.C
@@ -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 } } } */
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 1b4fd93f4ce..d1b2d21e2e9 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,5 +1,15 @@
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
* Makefile.in: Remove _gcov_merge_delta.
* libgcov-merge.c (void __gcov_merge_delta): Remove.
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index d51397e0f8a..84471bd8162 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -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;
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 725ef0a6283..dc74134b8ca 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -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;