$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r53373 - in sandbox/tools/profile_templates: . src test
From: steven_at_[hidden]
Date: 2009-05-28 19:26:32
Author: steven_watanabe
Date: 2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
New Revision: 53373
URL: http://svn.boost.org/trac/boost/changeset/53373
Log:
Intermediate commit -- this is broken
Text files modified: 
   sandbox/tools/profile_templates/preprocess.pl         |    30 ++++++-                                 
   sandbox/tools/profile_templates/src/filter.cpp        |    21 ++--                                    
   sandbox/tools/profile_templates/src/postprocess.cpp   |   157 ++++++++++++++++++++++++++------------- 
   sandbox/tools/profile_templates/template_profiler.hpp |    49 +++++++----                             
   sandbox/tools/profile_templates/test/test.cpp         |    28 ++++++                                  
   5 files changed, 196 insertions(+), 89 deletions(-)
Modified: sandbox/tools/profile_templates/preprocess.pl
==============================================================================
--- sandbox/tools/profile_templates/preprocess.pl	(original)
+++ sandbox/tools/profile_templates/preprocess.pl	2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
@@ -1,6 +1,6 @@
 # preprocess.pl
 #
-# Copyright (c) 2008
+# Copyright (c) 2008-2009
 # Steven Watanabe
 #
 # Distributed under the Boost Software License, Version 1.0. (See
@@ -16,7 +16,7 @@
 
 $backslashed_lines = qr/(?>(?>\\(?>\n|\r\n)|.)*)/;
 $string = qr/(?>\"(?>\\\\|\\\"|[^\"])*\"|'(?>\\\\|\\'|[^'])*')/;
-$comment = qr{(?>//$backslashed_lines|/\*(?>[^*]|\*(?!/))*\*/)};  #as far as we are concerned any text between off and on is a comment
+$comment = qr{(?>//$backslashed_lines|/\*(?>[^*]|\*(?!/))*\*/)};
 $pp = qr/(?>#$backslashed_lines)/;
 $ignored = qr/(?>$string|$comment|$pp)/;
 $parens = qr/(?>\((?>(?>(?>$ignored|[^()])+)|(??{$parens}))*\))/;
@@ -26,15 +26,35 @@
 
 $control = qr/(?:\b(?:__attribute__|__if_exists|__if_not_exists|for|while|if|catch|switch)\b)/;
 $modifiers = qr/(?:\b(?:try|const|volatile)\b)/;
-$start = qr/(?:^|\G|[{};])(?>$ws*)/;
+$start = qr/(?:^|\G|(?<=[{};]))(?>$ws*)/;
 $body = qr/(?:(?!$control)(?>$ignored|[^{};]))/;
 $end = qr/(?:$parens|\])/;
 $body_start = qr/(?>$ws*(?:$modifiers$ws*)*\{)/;
 
-$function_header = qr/(?>($start)($body*?$end)($body_start))/;
+$function_header = qr/(?>(?:$start)(?:$body*?$end)(?:$body_start))/;
+
+@braces = ();
+
+sub process {
+    my $header = $_[0];
+    my $open_brace = $_[1];
+    my $close_brace = $_[2];
+
+    if($header) {
+        push(@braces, " TEMPLATE_PROFILE_EXIT() }");
+        return("$header TEMPLATE_PROFILE_ENTER()");
+    } elsif($open_brace) {
+        push(@braces, "}");
+        return($open_brace);
+    } elsif($close_brace) {
+        return(pop(@braces));
+    } else {
+        die("This should only be called if the pattern matched: \$$_[0],$_[1],$_[2],$_[3],\$");
+    }
+}
 
 while(<>) {
-    s/($ignored)|((?>$class_header|$function_header))/$1?$1:"$2 PROFILE_TRACER\(\); "/ge;
+    s/(($ignored)|((?>$class_header|$function_header))|([{])|([}]))/$2?$2:process($3,$4,$5)/ge;
     print "#include <template_profiler.hpp>\n";
     print;
 }
Modified: sandbox/tools/profile_templates/src/filter.cpp
==============================================================================
--- sandbox/tools/profile_templates/src/filter.cpp	(original)
+++ sandbox/tools/profile_templates/src/filter.cpp	2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
@@ -1,6 +1,6 @@
 // filter.cpp
 //
-// Copyright (c) 2008
+// Copyright (c) 2008-2009
 // Steven Watanabe
 // 
 // Distributed under the Boost Software License, Version 1.0. (See
@@ -36,13 +36,14 @@
                 }
                 ++counter;
 #ifdef _MSC_VER
-                int instantiations = counter / 2;
+                if(counter % 400 == 0) {
+                    std::fprintf(stderr, "On Instantiation %d\n", counter/4);
+                }
 #else
-                int instantiations = counter;
-#endif
-                if(instantiations % 100 == 0) {
-                    std::fprintf(stderr, "On Instantiation %d\n", instantiations);
+                if(counter % 200 == 0) {
+                    std::fprintf(stderr, "On Instantiation %d\n", counter/2);
                 }
+#endif
             }
             buffer.clear();
             matched = false;
@@ -59,7 +60,7 @@
 }
 
 void copy_call_graph() {
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && 0
     std::string buffer;
     int ch;
     int pos = 0;
@@ -72,8 +73,8 @@
                 for(std::size_t i = 0; i < buffer.size(); ++i) {
                     std::putchar(buffer[i]);
                 }
-                if(++counter % 100 == 0) {
-                    std::fprintf(stderr, "On Instantiation %d\n", counter);
+                if(++counter % 200 == 0) {
+                    std::fprintf(stderr, "On Instantiation %d\n", counter/2);
                 }
                 buffer.clear();
                 matched = false;
@@ -123,7 +124,7 @@
             pos = 0;
         }
     }
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) || 1
     // trying to figure out what we should copy is too hard.
     int ch;
     while((ch = std::getchar()) != EOF) {
Modified: sandbox/tools/profile_templates/src/postprocess.cpp
==============================================================================
--- sandbox/tools/profile_templates/src/postprocess.cpp	(original)
+++ sandbox/tools/profile_templates/src/postprocess.cpp	2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
@@ -1,6 +1,6 @@
 // postprocess.cpp
 //
-// Copyright (c) 2008
+// Copyright (c) 2008-2009
 // Steven Watanabe
 // 
 // Distributed under the Boost Software License, Version 1.0. (See
@@ -10,6 +10,7 @@
 #include <boost/regex.hpp>
 #include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/numeric/conversion/cast.hpp>
 #include <string>
 #include <iostream>
 #include <fstream>
@@ -23,7 +24,10 @@
 
 #ifdef _MSC_VER
 
-boost::regex warning_message("(.*) : warning C4150: deletion of pointer to incomplete type 'template_profiler::incomplete'; no destructor called");
+#pragma warning(disable:4512)
+
+boost::regex enter_message("(.*) : warning C4150: deletion of pointer to incomplete type 'template_profiler::incomplete_enter'; no destructor called");
+boost::regex exit_message("(.*) : warning C4150: deletion of pointer to incomplete type 'template_profiler::incomplete_exit'; no destructor called");
 boost::regex call_graph_line("        (.*)\\((\\d+)\\) : see reference to .*");
 boost::regex split_file_and_line("(.*)\\((\\d+)\\)");
 
@@ -31,13 +35,15 @@
 
 #if (__GNUC__ < 4) || (__GNUC_MINOR__ < 3)
 
-boost::regex warning_message("(.*): warning: division by zero in .template_profiler::value / 0.");
+boost::regex enter_message("(.*): warning: division by zero in .template_profiler::enter_value / 0.");
+boost::regex exit_message("(.*): warning: division by zero in .template_profiler::exit_value / 0.");
 boost::regex call_graph_line("(.*):(\\d+):   instantiated from .*");
 boost::regex split_file_and_line("(.*):(\\d+)");
 
 #else
 
-boost::regex warning_message("(.*): warning: .int template_profiler::f\\(int\\).*");
+boost::regex enter_message("(.*): warning: .int template_profiler::enter\\(int\\).*");
+boost::regex exit_message("(.*): warning: .int template_profiler::exit\\(int\\).*");
 boost::regex call_graph_line("(.*):(\\d+):   instantiated from .*");
 boost::regex split_file_and_line("(.*):(\\d+)");
 
@@ -94,6 +100,62 @@
     return(os);
 }
 
+class instantiation_state {
+public:
+    instantiation_state(std::map<const line_id*, node_info>& g) : graph(g) {}
+    void finish_instantiation() {
+        std::cerr << "finish_instantiation, state.size(): " << state.size() << std::endl;
+        if(state.empty() || !state.back()) {
+            std::cerr << "attempt to finish unstarted instantiation: " << state.size() << std::endl;
+            std::exit(1);
+        }
+        state.pop_back();
+        pending_children.pop_back();
+    }
+    void add_instantiation(const line_id* new_line, std::size_t backtrace_size) {
+        if(backtrace_size == 0) {
+            std::cerr << "non-template" << std::endl;
+            // top level non-template
+            backtrace_size = state.size() + 1;
+        } else {
+            ++backtrace_size;
+        }
+        std::cerr << "backtrace size: " << backtrace_size << ", state.size(): " << state.size() << std::endl;
+        if(backtrace_size < state.size()) {
+            std::cerr << "Instantiation not exited." << std::endl;
+            std::exit(1);
+        }
+        ++graph[new_line].count;
+        std::cerr << "Adding lines" << std::endl;
+        BOOST_FOREACH(const line_id* line, state) {
+            if(line) {
+                add_child(line, new_line);
+            }
+        }
+        state.resize(backtrace_size);
+        pending_children.resize(backtrace_size);
+        state.back() = new_line;
+        BOOST_FOREACH(const line_id* child, pending_children.back()) {
+            add_child(new_line, child);
+        }
+        BOOST_FOREACH(std::vector<const line_id*>& v, pending_children) {
+            v.push_back(new_line);
+        }
+    }
+private:
+    void add_child(const line_id* parent, const line_id* child) {
+        std::cerr << "parent: " << parent << ", child: " << child << std::endl;
+        if(parent != child) {
+            ++graph[parent].children[child];
+            ++graph[child].parents[child];
+            ++graph[parent].total_with_children;
+        }
+    }
+    std::vector<const line_id*> state;
+    std::vector<std::vector<const line_id*> > pending_children;
+    std::map<const line_id*, node_info>& graph;
+};
+
 int main(int argc, char** argv) {
     const char* input_file_name = 0;
     bool use_call_graph = false;
@@ -113,13 +175,13 @@
     std::map<std::string, int> messages;
     std::string line;
     int total_matches = 0;
-    std::ptrdiff_t max_match_length = 0;
+    int max_match_length = 0;
     {
         std::ifstream input(input_file_name);
         while(std::getline(input, line)) {
             boost::smatch match;
-            if(boost::regex_match(line, match, warning_message)) {
-                max_match_length = (std::max)(max_match_length, match[1].length());
+            if(boost::regex_match(line, match, enter_message)) {
+                max_match_length = boost::numeric_cast<int>((std::max)(max_match_length, match[1].length()));
                 ++messages[match[1]];
                 ++total_matches;
             }
@@ -135,7 +197,9 @@
     std::for_each(copy.begin(), copy.end(), p);
 
     if(use_call_graph) {
+        std::size_t backtrace_depth = 0;
         std::map<const line_id*, node_info> graph;
+        instantiation_state state(graph);
         std::set<line_id> lines;
         typedef std::pair<std::string, int> raw_line;
         BOOST_FOREACH(const raw_line& l, messages) {
@@ -145,76 +209,61 @@
         }
         const line_id* current_instantiation = 0;
         std::ifstream input(input_file_name);
+        int line_number = 0;
 #if defined(_MSC_VER)
         // msvc puts the warning first and follows it with the backtrace.
         while(std::getline(input, line)) {
+            std::cerr << line_number++ << std::endl;
             boost::smatch match;
-            if(boost::regex_match(line, match, warning_message)) {
+            if(boost::regex_match(line, match, enter_message)) {
+                // commit the current instantiation
+                if(current_instantiation) {
+                    state.add_instantiation(current_instantiation, backtrace_depth);
+                }
+                // start a new instantiation
                 std::string file_and_line(match[1].str());
                 boost::regex_match(file_and_line, match, split_file_and_line);
                 std::string file = match[1];
                 int line = boost::lexical_cast<int>(match[2].str());
                 current_instantiation = &*lines.find(line_id(file, line));
-                ++graph[current_instantiation].total_with_children;
-                ++graph[current_instantiation].count;
             } else if(boost::regex_match(line, match, call_graph_line)) {
-                std::string file = match[1];
-                int line = boost::lexical_cast<int>(match[2].str());
-                std::set<line_id>::const_iterator pos = lines.lower_bound(line_id(file, line));
-                if(pos != lines.end()) {
-                    if(*pos != line_id(file, line) && pos != lines.begin() && boost::prior(pos)->first == file) {
-                        --pos;
-                    }
-                } else if(pos != lines.begin()) {
-                    --pos;
-                } else {
-                    break;
+                ++backtrace_depth;
+            } else if(boost::regex_match(line, match, exit_message)) {
+                // commit the current instantiation
+                if(current_instantiation) {
+                    state.add_instantiation(current_instantiation, backtrace_depth);
+                }
+
+                state.finish_instantiation();
+                if(backtrace_depth) {
+                    --backtrace_depth;
                 }
-                const line_id* parent = &*pos;
-                ++graph[current_instantiation].parents[parent];
-                ++graph[parent].children[current_instantiation];
-                ++graph[parent].total_with_children;
+                current_instantiation = 0;
             }
         }
+        // commit the current instantiation
+        if(current_instantiation) {
+            state.add_instantiation(current_instantiation, backtrace_depth);
+        }
 #elif defined(__GNUC__)
         // gcc puts the backtrace first, and then the warning.
-        // so we have to buffer the backtrace until we reach the
-        // warning.
-        std::vector<std::string> pending_lines;
         while(std::getline(input, line)) {
             boost::smatch match;
-            if(boost::regex_match(line, match, warning_message)) {
+            if(boost::regex_match(line, match, enter_message)) {
                 std::string file_and_line(match[1].str());
                 boost::regex_match(file_and_line, match, split_file_and_line);
                 std::string file = match[1];
                 int line = boost::lexical_cast<int>(match[2].str());
                 current_instantiation = &*lines.find(line_id(file, line));
-                ++graph[current_instantiation].total_with_children;
-                ++graph[current_instantiation].count;
-                BOOST_FOREACH(const std::string& line, pending_lines) {
-                    boost::regex_match(line, match, call_graph_line);
-                    std::string file = match[1];
-                    int line = boost::lexical_cast<int>(match[2].str());
-                    std::set<line_id>::const_iterator pos = lines.lower_bound(line_id(file, line));
-                    if(pos != lines.end()) {
-                        if(*pos != line_id(file, line) && pos != lines.begin() && boost::prior(pos)->first == file) {
-                            --pos;
-                        }
-                    } else if(pos != lines.begin()) {
-                        --pos;
-                    } else {
-                        break;
-                    }
-                    const line_id* parent = &*pos;
-                    ++graph[current_instantiation].parents[parent];
-                    ++graph[parent].children[current_instantiation];
-                    ++graph[parent].total_with_children;
-                }
-                pending_lines.clear();
+                ++backtrace_depth;
+                std::cerr << backtrace_depth << std::endl;
+                state.add_instantiation(current_instantiation, backtrace_depth);
+                backtrace_depth = 0;
             } else if(boost::regex_match(line, match, call_graph_line)) {
-                pending_lines.push_back(line);
-            } else {
-                pending_lines.clear();
+                ++backtrace_depth;
+            } else if(boost::regex_match(line, match, exit_message)) {
+                state.finish_instantiation();
+                backtrace_depth = 0;
             }
         }
 #else
Modified: sandbox/tools/profile_templates/template_profiler.hpp
==============================================================================
--- sandbox/tools/profile_templates/template_profiler.hpp	(original)
+++ sandbox/tools/profile_templates/template_profiler.hpp	2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
@@ -11,7 +11,8 @@
 #define TEMPLATE_PROFILER_HPP_INLUCDED
 
 namespace template_profiler {
-    struct incomplete;
+    struct incomplete_enter;
+    struct incomplete_exit;
     template<int N>
     struct int_ {
         enum { value = N };
@@ -21,45 +22,55 @@
     struct make_zero {
         enum { value = 0 };
     };
-    extern int value;
+    extern int enter_value;
+    extern int exit_value;
 }
 
 char template_profiler_size_one(...);
 
-#ifdef PROFILE_TEMPLATES
-
 #if defined(_MSC_VER)
-    #define PROFILE_TRACER() enum template_profiler_test { template_profiler_value = sizeof(delete ((::template_profiler::incomplete*)0),0) };
+    #define TEMPLATE_PROFILE_ENTER() enum template_profiler_test_enter { template_profiler_value_enter = sizeof(delete ((::template_profiler::incomplete_enter*)0),0) };
+    #define TEMPLATE_PROFILE_EXIT() enum template_profiler_test_exit { template_profiler_value_exit = sizeof(delete ((::template_profiler::incomplete_exit*)0),0) };
 #elif defined(__GNUC__)
     #if (__GNUC__ < 4) || (__GNUC_MINOR__ < 3)
-        #define PROFILE_TRACER()\
-        struct template_profiler_test {};\
-        enum {template_profiler_size = sizeof(template_profiler_size_one(static_cast<template_profiler_test*>(0))) };\
+        #define TEMPLATE_PROFILE_ENTER()\
+        struct template_profiler_test_enter {};\
+        enum {template_profiler_size_enter = sizeof(template_profiler_size_one(static_cast<template_profiler_test*>(0))) };\
+        typedef ::template_profiler::int_<\
+            sizeof(\
+                ::template_profiler::enter_value /\
+                ::template_profiler::make_zero<\
+                    ::template_profiler::int_<\
+                        template_profiler_size\
+                    >\
+                >::value\
+            )\
+        > template_profiler_test_result_enter;
+        #define TEMPLATE_PROFILE_EXIT()\
+        struct template_profiler_test_exit {};\
+        enum {template_profiler_size_exit = sizeof(template_profiler_size_one(static_cast<template_profiler_test*>(0))) };\
         typedef ::template_profiler::int_<\
             sizeof(\
-                ::template_profiler::value /\
+                ::template_profiler::exit_value /\
                 ::template_profiler::make_zero<\
                     ::template_profiler::int_<\
                         template_profiler_size\
                     >\
                 >::value\
             )\
-        > template_profiler_test_result;
+        > template_profiler_test_result_exit;
     #else
         namespace template_profiler {
-            __attribute__((deprecated)) int f(int);
-            int f(double);
+            __attribute__((deprecated)) int enter(int);
+            int begin(double);
+            __attribute__((deprecated)) int exit(int);
+            int end(double);
         }
-        #define PROFILE_TRACER() enum { template_profiler_size = sizeof(::template_profiler::f(1)) };
+        #define TEMPLATE_PROFILE_ENTER() enum { template_profiler_size_enter = sizeof(::template_profiler::enter(1)) };
+        #define TEMPLATE_PROFILE_EXIT() enum { template_profiler_size_exit = sizeof(::template_profiler::exit(1)) };
     #endif
 #else
     #error Unknown compiler
 #endif
 
-#else
-
-    #define PROFILE_TRACER()
-
-#endif
-
 #endif
Modified: sandbox/tools/profile_templates/test/test.cpp
==============================================================================
--- sandbox/tools/profile_templates/test/test.cpp	(original)
+++ sandbox/tools/profile_templates/test/test.cpp	2009-05-28 19:26:32 EDT (Thu, 28 May 2009)
@@ -1,6 +1,6 @@
 // test.cpp
 //
-// Copyright (c) 2008
+// Copyright (c) 2008-2009
 // Steven Watanabe
 //
 // Distributed under the Boost Software License, Version 1.0. (See
@@ -9,9 +9,35 @@
 
 #include <test.hpp>
 
+struct outer {
+    struct inner {
+    };
+};
+
+template<int N>
+struct inheritence_test
+    :
+    inheritence_test<N - 1>
+    {};
+
+template<>
+struct inheritence_test<0> {};
+
+template<int N>
+struct member_test {
+    typedef typename member_test<N - 1>::type type;
+};
+
+template<>
+struct member_test<0> {
+    typedef void type;
+};
+
 int main() {
     X<int> x1;
     X<char> x2;
     f(1);
     f('a');
+    inheritence_test<5> i_test;
+    member_test<5> m_test;
 }