From patchwork Mon Apr 11 16:24:28 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Diego Novillo X-Patchwork-Id: 90626 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id BB152B6F0C for ; Tue, 12 Apr 2011 02:24:46 +1000 (EST) Received: (qmail 30194 invoked by alias); 11 Apr 2011 16:24:41 -0000 Received: (qmail 30181 invoked by uid 22791); 11 Apr 2011 16:24:39 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.67) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 11 Apr 2011 16:24:33 +0000 Received: from wpaz5.hot.corp.google.com (wpaz5.hot.corp.google.com [172.24.198.69]) by smtp-out.google.com with ESMTP id p3BGOUEp002086; Mon, 11 Apr 2011 09:24:31 -0700 Received: from topo.tor.corp.google.com (topo.tor.corp.google.com [172.29.41.2]) by wpaz5.hot.corp.google.com with ESMTP id p3BGOSkk020327; Mon, 11 Apr 2011 09:24:28 -0700 Received: by topo.tor.corp.google.com (Postfix, from userid 54752) id 59E401DA1BE; Mon, 11 Apr 2011 12:24:28 -0400 (EDT) To: reply@codereview.appspotmail.com, jason@redhat.com, crowl@google.com, gcc-patches@gcc.gnu.org Subject: Add debugging functions for cp_parser (issue4389045) Message-Id: <20110411162428.59E401DA1BE@topo.tor.corp.google.com> Date: Mon, 11 Apr 2011 12:24:28 -0400 (EDT) From: dnovillo@google.com (Diego Novillo) X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds a debugging function to print the state of a cp_parser instance. It prints all the status fields in the structure and a window of 20 tokens around the current token. This patch is against the pph branch, but it should apply almost cleanly to trunk. OK for mainline? Diego. cp/ChangeLog.pph * parser.c (cp_lexer_dump_tokens): Add arguments START_TOKEN and CURR_TOKEN. Update all callers. Print tokens starting with START_TOKEN. Highlight CURR_TOKEN by enclosing it in [[ ]]. (cp_debug_print_tree_if_set): New. (cp_debug_print_context): New. (cp_debug_print_context_stack): New. (cp_debug_print_flag): New. (cp_debug_print_unparsed_function): New. (cp_debug_print_unparsed_queues): New. (cp_debug_parser): New. * cp/parser.h (cp_debug_parser): Declare. --- This patch is available for review at http://codereview.appspot.com/4389045 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 042a838..0f13a44 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -248,24 +248,49 @@ static FILE *cp_lexer_debug_stream; sizeof, typeof, or alignof. */ int cp_unevaluated_operand; -/* FIX pph: #ifdef ENABLE_CHECKING */ -/* Dump up to NUM tokens in BUFFER to FILE. If NUM is 0, dump all the - tokens. */ +/* Dump up to NUM tokens in BUFFER to FILE starting with token + START_TOKEN. If START_TOKEN is NULL, the dump starts with the + first token in BUFFER. If NUM is 0, dump all the tokens. If + CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be + highlighted by surrounding it in [[ ]]. */ void -cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num) +cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, + cp_token *start_token, unsigned num, + cp_token *curr_token) { unsigned i; cp_token *token; + bool do_print; fprintf (file, "%u tokens\n", VEC_length (cp_token, buffer)); if (num == 0) num = VEC_length (cp_token, buffer); + if (start_token && start_token > VEC_address (cp_token, buffer)) + { + cp_lexer_print_token (file, VEC_index (cp_token, buffer, 0)); + fprintf (file, " ... "); + } + + do_print = false; for (i = 0; VEC_iterate (cp_token, buffer, i, token) && i < num; i++) { + if (token == start_token) + do_print = true; + + if (!do_print) + continue; + + if (token == curr_token) + fprintf (file, "[["); + cp_lexer_print_token (file, token); + + if (token == curr_token) + fprintf (file, "]]"); + switch (token->type) { case CPP_SEMICOLON: @@ -296,9 +321,195 @@ cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num) void cp_lexer_debug_tokens (VEC(cp_token,gc) *buffer) { - cp_lexer_dump_tokens (stderr, buffer, 0); + cp_lexer_dump_tokens (stderr, buffer, NULL, 0, NULL); +} + + +/* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the + description for T. */ + +static void +cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t) +{ + if (t) + { + fprintf (file, "%s: ", desc); + debug_generic_expr (t); + } +} + + +/* Dump parser context C to FILE. */ + +static void +cp_debug_print_context (FILE *file, cp_parser_context *c) +{ + const char *status_s[] = { "OK", "ERROR", "COMMITTED" }; + fprintf (file, "{ status = %s, scope = ", status_s[c->status]); + print_generic_expr (file, c->object_type, 0); + fprintf (file, "}\n"); +} + + +/* Print the stack of parsing contexts to FILE starting with FIRST. */ +static void +cp_debug_print_context_stack (FILE *file, cp_parser_context *first) +{ + unsigned i; + cp_parser_context *c; + + fprintf (file, "Parsing context stack:\n"); + for (i = 0, c = first; c; c = c->next) + { + fprintf (file, "\t#%u: ", i); + cp_debug_print_context (file, c); + } +} + + +/* Print the value of FLAG to FILE. DESC is a string describing the flag. */ + +static void +cp_debug_print_flag (FILE *file, const char *desc, bool flag) +{ + if (flag) + fprintf (file, "%s: %s\n", desc, flag ? "true" : "false"); +} + + +/* Print an unparsed function entry UF to FILE. */ + +static void +cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf) +{ + unsigned i; + cp_default_arg_entry *default_arg_fn; + tree fn; + + fprintf (file, "\tFunctions with default args:\n"); + for (i = 0; + VEC_iterate (cp_default_arg_entry, uf->funs_with_default_args, i, + default_arg_fn); + i++) + { + fprintf (file, "\t\tClass type: "); + print_generic_expr (file, default_arg_fn->class_type, 0); + fprintf (file, "\t\tDeclaration: "); + print_generic_expr (file, default_arg_fn->decl, 0); + fprintf (file, "\n"); + } + + fprintf (file, "\n\tFunctions with definitions that require " + "post-processing\n\t\t"); + for (i = 0; VEC_iterate (tree, uf->funs_with_definitions, i, fn); i++) + { + print_generic_expr (file, fn, 0); + fprintf (file, " "); + } + fprintf (file, "\n"); +} + + +/* Print the stack of unparsed member functions S to FILE. */ + +static void +cp_debug_print_unparsed_queues (FILE *file, + VEC(cp_unparsed_functions_entry, gc) *s) +{ + unsigned i; + cp_unparsed_functions_entry *uf; + + fprintf (file, "Unparsed functions\n"); + for (i = 0; VEC_iterate (cp_unparsed_functions_entry, s, i, uf); i++) + { + fprintf (file, "#%u:\n", i); + cp_debug_print_unparsed_function (file, uf); + } } -/* FIX pph: #endif */ + + +/* Dump debugging information for the given PARSER. If FILE is NULL, + the output is printed on stderr. */ + +void +cp_debug_parser (FILE *file, cp_parser *parser) +{ + cp_token *start_token, *first_token, *next_token; + const size_t window_size = 20; + + if (file == NULL) + file = stderr; + + fprintf (file, "Parser state\n\n"); + fprintf (file, "Number of tokens: %u\n", + VEC_length (cp_token, parser->lexer->buffer)); + cp_debug_print_tree_if_set (file, "Lookup scope", parser->scope); + cp_debug_print_tree_if_set (file, "Object scope", + parser->object_scope); + cp_debug_print_tree_if_set (file, "Qualifying scope", + parser->qualifying_scope); + cp_debug_print_context_stack (file, parser->context); + cp_debug_print_flag (file, "Allow GNU extensions", + parser->allow_gnu_extensions_p); + cp_debug_print_flag (file, "'>' token is greater-than", + parser->greater_than_is_operator_p); + cp_debug_print_flag (file, "Default args allowed in current " + "parameter list", parser->default_arg_ok_p); + cp_debug_print_flag (file, "Parsing integral constant-expression", + parser->integral_constant_expression_p); + cp_debug_print_flag (file, "Allow non-constant expression in current " + "constant-expression", + parser->allow_non_integral_constant_expression_p); + cp_debug_print_flag (file, "Seen non-constant expression", + parser->non_integral_constant_expression_p); + cp_debug_print_flag (file, "Local names and 'this' forbidden in " + "current context", + parser->local_variables_forbidden_p); + cp_debug_print_flag (file, "In unbraced linkage specification", + parser->in_unbraced_linkage_specification_p); + cp_debug_print_flag (file, "Parsing a declarator", + parser->in_declarator_p); + cp_debug_print_flag (file, "In template argument list", + parser->in_template_argument_list_p); + cp_debug_print_flag (file, "Parsing an iteration statement", + parser->in_statement & IN_ITERATION_STMT); + cp_debug_print_flag (file, "Parsing a switch statement", + parser->in_statement & IN_SWITCH_STMT); + cp_debug_print_flag (file, "Parsing a structured OpenMP block", + parser->in_statement & IN_OMP_BLOCK); + cp_debug_print_flag (file, "Parsing a an OpenMP loop", + parser->in_statement & IN_OMP_FOR); + cp_debug_print_flag (file, "Parsing an if statement", + parser->in_statement & IN_IF_STMT); + cp_debug_print_flag (file, "Parsing a type-id in an expression " + "context", parser->in_type_id_in_expr_p); + cp_debug_print_flag (file, "Declarations are implicitly extern \"C\"", + parser->implicit_extern_c); + cp_debug_print_flag (file, "String expressions should be translated " + "to execution character set", + parser->translate_strings_p); + cp_debug_print_flag (file, "Parsing function body outside of a " + "local class", parser->in_function_body); + cp_debug_print_flag (file, "Auto correct a colon to a scope operator", + parser->colon_corrects_to_scope_p); + if (parser->type_definition_forbidden_message) + fprintf (file, "Error message for forbidden type definitions: %s\n", + parser->type_definition_forbidden_message); + cp_debug_print_unparsed_queues (file, parser->unparsed_queues); + fprintf (file, "Number of class definitions in progress: %u\n", + parser->num_classes_being_defined); + fprintf (file, "Number of template parameter lists for the current " + "declaration: %u\n", parser->num_template_parameter_lists); + + next_token = parser->lexer->next_token; + first_token = VEC_address (cp_token, parser->lexer->buffer); + start_token = (next_token > first_token + window_size / 2) + ? next_token - window_size / 2 + : first_token; + cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size, + next_token); +} + /* Return true if LEXER has a CPP_EOF at the end of the buffer. */ diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index ac08918..32a22e2 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -370,10 +370,12 @@ typedef struct GTY(()) cp_parser { extern cp_token eof_token; extern GTY(()) cp_parser *the_parser; -extern void cp_lexer_dump_tokens (FILE *, VEC(cp_token,gc) *, unsigned); +extern void cp_lexer_dump_tokens (FILE *, VEC(cp_token,gc) *, cp_token *, + unsigned, cp_token *); extern void cp_lexer_get_tokens (cp_lexer *); extern cp_token_position cp_lexer_token_position (cp_lexer *, bool); extern void cp_lexer_debug_tokens (VEC(cp_token,gc) *); extern cp_token_cache *cp_token_cache_new (cp_token *, cp_token *); +extern void cp_debug_parser (FILE *, cp_parser *); #endif /* GCC_CP_PARSER_H */ diff --git a/gcc/cp/pph.c b/gcc/cp/pph.c index 14a62c8..add6dfc 100644 --- a/gcc/cp/pph.c +++ b/gcc/cp/pph.c @@ -525,7 +525,7 @@ static void pth_dump_hunk (FILE *stream, cp_token_hunk *hunk) { pth_dump_identifiers (stream, &hunk->identifiers); - cp_lexer_dump_tokens (stream, hunk->buffer, 0); + cp_lexer_dump_tokens (stream, hunk->buffer, NULL, 0, NULL); } /* Dump a debug log of the HUNK. */ @@ -749,7 +749,7 @@ pth_dump_state (FILE *f) if (state->lexer) { fprintf (f, "Tokens in main lexer:\n"); - cp_lexer_dump_tokens (f, state->lexer->buffer, 0); + cp_lexer_dump_tokens (f, state->lexer->buffer, NULL, 0, NULL); } } @@ -3133,7 +3133,7 @@ pph_print_token_range (VEC(tree,heap) *v, VEC(cp_token, heap) *vtok) pph_debug_location (pph_logfile, VEC_last (cp_token, vtok)->location); fprintf (pph_logfile, "\n"); fprintf (pph_logfile, "PPH: hunk tokens "); - cp_lexer_dump_tokens (stderr, (VEC(cp_token, gc) *)vtok, 0); + cp_lexer_dump_tokens (stderr, (VEC(cp_token, gc) *)vtok, NULL, 0, NULL); fprintf (pph_logfile, "PPH: hunk ASTs:\n"); for (i = 0; VEC_iterate (tree, v, i, t); i++) {