From patchwork Wed Nov 12 13:43:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 409978 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 82E2C14009B for ; Thu, 13 Nov 2014 00:49:49 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=DS6X0VVy1XqljmixqSZfQAzFQvoHaw7CzcZNVVfDLQkKLtM224EZg +R6brFasnf4zJ3Dzgzhde3xxfEx6pLX7y0WfkntDHy6+ODhUS8g5oLOvEdqLTZ1O 9U7u5OzNHOmmvaXC6Lbzb9FnSxjLfJMYkeT1JXcNdIJNttwLNLMOLc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=rz9E25mPaLiggFyBn0XHWCTMPT8=; b=m+V7MCH4El6hnjF3fYZX NenciZUwYxG5UVdzNDkL20+iAoZJDZCrQSg5oNcusF0uiaHfc9f1QBLlGq5ncsqo Cs/o/K8eaSX67OWbJjO7m7iT6DMgzfvFqwh6T3xSSIPQY5DETNyfoqvt3cnPDQpT 4mLIg/sxl6UjRHpdx1TkPlw= Received: (qmail 11682 invoked by alias); 12 Nov 2014 13:49:05 -0000 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 Received: (qmail 11632 invoked by uid 89); 12 Nov 2014 13:49:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.5 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx2.suse.de Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Wed, 12 Nov 2014 13:49:02 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EB804AAC3 for ; Wed, 12 Nov 2014 13:48:58 +0000 (UTC) Date: Wed, 12 Nov 2014 14:43:00 +0100 (CET) From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH] Merge genmatch improvements from branch Message-ID: User-Agent: Alpine 2.11 (LSU 23 2013-08-11) MIME-Version: 1.0 The following patch merges diagnostic enhancements from the branch (diagnosing stuff in match.pd) and the define_operator_list support. There are no changes in the generated files thus I am only bootstrapping this right now (for -Werror). Thanks, Richard. 2014-11-12 Richard Biener Merge from match-and-simplify branch 2014-11-04 Prathamesh Kulkarni * genmatch.c (user_id): Add new member is_oper_list. (user_id::user_id): Add new default argument. (parser::parse_operator_list): New function. (parser::parse_for): Allow operator-list. (parser::parse_pattern): Call parser::parse_operator_list. (parser::parse_operation): Reject operator-list. * match-builtin.pd: Define operator lists POWs, CBRTs and SQRTs. 2014-10-31 Prathamesh Kulkarni * genmatch.c (parser::parse_c_expr): Mark user-defined ops as used. 2014-10-30 Prathamesh Kulkarni * genmatch.c (parser::parse_op): Check if predicate is used in result operand. 2014-10-29 Prathamesh Kulkarni * genmatch.c (parser::parse_for): Make sure to have a valid token to report errors at. 2014-10-28 Prathamesh Kulkarni * genmatch.c (parser): Add new member parsing_match_operand. (parser::parse_operation): Check for conditional convert in result operand. (parser::parse_expr): Check for commutative operator in result operand. Check for :type in match operand. (parser::parse_simplify): Set/unset parsing_match_operand. (parser::parser): Initialize parsing_match_operand. 2014-10-28 Richard Biener * genmatch.c (parser::parse_for): Properly check for already defined operators. 2014-10-28 Prathamesh Kulkarni * genmatch.c (error_cb): Adjust for printing warnings. (warning_at): New function. (user_id): Add new member used. (get_operator): Mark user_id as used. (parse_for): Warn for unused operators. Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (svn+ssh://rguenth@gcc.gnu.org/svn/gcc/trunk/gcc/genmatch.c) (revision 217416) +++ gcc/genmatch.c (.../gcc/genmatch.c) (working copy) @@ -54,13 +54,14 @@ static bool #if GCC_VERSION >= 4001 __attribute__((format (printf, 6, 0))) #endif -error_cb (cpp_reader *, int, int, source_location location, +error_cb (cpp_reader *, int errtype, int, source_location location, unsigned int, const char *msg, va_list *ap) { const line_map *map; linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map); expanded_location loc = linemap_expand_location (line_table, map, location); - fprintf (stderr, "%s:%d:%d error: ", loc.file, loc.line, loc.column); + fprintf (stderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column, + (errtype == CPP_DL_WARNING) ? "warning" : "error"); vfprintf (stderr, msg, *ap); fprintf (stderr, "\n"); FILE *f = fopen (loc.file, "r"); @@ -86,7 +87,10 @@ error_cb (cpp_reader *, int, int, source notfound: fclose (f); } - exit (1); + + if (errtype == CPP_DL_FATAL) + exit (1); + return false; } static void @@ -102,6 +106,18 @@ fatal_at (const cpp_token *tk, const cha } static void +#if GCC_VERSION >= 4001 +__attribute__((format (printf, 2, 3))) +#endif +warning_at (const cpp_token *tk, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + error_cb (NULL, CPP_DL_WARNING, 0, tk->src_loc, 0, msg, &ap); + va_end (ap); +} + +static void output_line_directive (FILE *f, source_location location, bool dumpfile = false) { @@ -228,9 +244,12 @@ struct predicate_id : public id_base struct user_id : public id_base { - user_id (const char *id_) - : id_base (id_base::USER, id_), substitutes (vNULL) {} + user_id (const char *id_, bool is_oper_list_ = false) + : id_base (id_base::USER, id_), substitutes (vNULL), + used (false), is_oper_list (is_oper_list_) {} vec substitutes; + bool used; + bool is_oper_list; }; template<> @@ -331,7 +350,12 @@ get_operator (const char *id) id_base *op = operators->find_with_hash (&tem, tem.hashval); if (op) - return op; + { + /* If this is a user-defined identifier track whether it was used. */ + if (user_id *uid = dyn_cast (op)) + uid->used = true; + return op; + } /* Try all-uppercase. */ char *id2 = xstrdup (id); @@ -2650,6 +2674,7 @@ private: void parse_for (source_location); void parse_if (source_location); void parse_predicates (source_location); + void parse_operator_list (source_location); cpp_reader *r; vec active_ifs; @@ -2660,6 +2685,7 @@ private: public: vec simplifiers; vec user_predicates; + bool parsing_match_operand; }; /* Lexing helpers. */ @@ -2805,6 +2831,10 @@ parser::parse_operation () ; else fatal_at (id_tok, "non-convert operator conditionalized"); + + if (!parsing_match_operand) + fatal_at (id_tok, "conditional convert can only be used in " + "match expression"); eat_token (CPP_QUERY); } else if (strcmp (id, "convert1") == 0 @@ -2813,6 +2843,11 @@ parser::parse_operation () id_base *op = get_operator (id); if (!op) fatal_at (id_tok, "unknown operator %s", id); + + user_id *p = dyn_cast (op); + if (p && p->is_oper_list) + fatal_at (id_tok, "operator-list not allowed in expression"); + return op; } @@ -2824,7 +2859,7 @@ parser::parse_capture (operand *op) { eat_token (CPP_ATSIGN); const cpp_token *token = peek (); - const char *id; + const char *id = NULL; if (token->type == CPP_NUMBER) id = get_number (); else if (token->type == CPP_NAME) @@ -2861,11 +2896,21 @@ parser::parse_expr () { const char *s = get_ident (); if (s[0] == 'c' && !s[1]) - is_commutative = true; + { + if (!parsing_match_operand) + fatal_at (token, + "flag 'c' can only be used in match expression"); + is_commutative = true; + } else if (s[1] != '\0') - expr_type = s; + { + if (parsing_match_operand) + fatal_at (token, "type can only be used in result expression"); + expr_type = s; + } else fatal_at (token, "flag %s not recognized", s); + token = peek (); } else @@ -2937,6 +2982,11 @@ parser::parse_c_expr (cpp_ttype start) if (token->type == CPP_SEMICOLON) nr_stmts++; + /* If this is possibly a user-defined identifier mark it used. */ + if (token->type == CPP_NAME) + get_operator ((const char *)CPP_HASHNODE + (token->val.node.node)->ident.str); + /* Record the token. */ code.safe_push (*token); } @@ -2984,6 +3034,8 @@ parser::parse_op () op = new predicate (p); else fatal_at (token, "using an unsupported operator as predicate"); + if (!parsing_match_operand) + fatal_at (token, "predicates are only allowed in match expression"); token = peek (); if (token->flags & PREV_WHITE) return op; @@ -3020,7 +3072,9 @@ parser::parse_simplify (source_location capture_ids = new cid_map_t; const cpp_token *loc = peek (); + parsing_match_operand = true; struct operand *match = parse_op (); + parsing_match_operand = false; if (match->type == operand::OP_CAPTURE && !matcher) fatal_at (loc, "outermost expression cannot be captured"); if (match->type == operand::OP_EXPR @@ -3138,24 +3192,26 @@ parser::parse_simplify (source_location void parser::parse_for (source_location) { + auto_vec user_id_tokens; vec user_ids = vNULL; const cpp_token *token; unsigned min_n_opers = 0, max_n_opers = 0; while (1) { - token = peek_ident (); - if (token == 0) + token = peek (); + if (token->type != CPP_NAME) break; /* Insert the user defined operators into the operator hash. */ const char *id = get_ident (); + if (get_operator (id) != NULL) + fatal_at (token, "operator already defined"); user_id *op = new user_id (id); id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); - if (*slot) - fatal_at (token, "operator already defined"); *slot = op; user_ids.safe_push (op); + user_id_tokens.safe_push (token); eat_token (CPP_OPEN_PAREN); @@ -3177,7 +3233,11 @@ parser::parse_for (source_location) fatal_at (token, "operator '%s' with arity %d does not match " "others with arity %d", oper, idb->nargs, arity); - op->substitutes.safe_push (idb); + user_id *p = dyn_cast (idb); + if (p && p->is_oper_list) + op->substitutes.safe_splice (p->substitutes); + else + op->substitutes.safe_push (idb); } op->nargs = arity; token = expect (CPP_CLOSE_PAREN); @@ -3225,7 +3285,59 @@ parser::parse_for (source_location) /* Remove user-defined operators from the hash again. */ for (unsigned i = 0; i < user_ids.length (); ++i) - operators->remove_elt (user_ids[i]); + { + if (!user_ids[i]->used) + warning_at (user_id_tokens[i], + "operator %s defined but not used", user_ids[i]->id); + operators->remove_elt (user_ids[i]); + } +} + +/* Parse an identifier associated with a list of operators. + oprs = '(' 'define_operator_list' ... ')' */ + +void +parser::parse_operator_list (source_location) +{ + const cpp_token *token = peek (); + const char *id = get_ident (); + + if (get_operator (id) != 0) + fatal_at (token, "operator %s already defined", id); + + user_id *op = new user_id (id, true); + int arity = -1; + + while ((token = peek_ident ()) != 0) + { + token = peek (); + const char *oper = get_ident (); + id_base *idb = get_operator (oper); + + if (idb == 0) + fatal_at (token, "no such operator '%s'", oper); + + if (arity == -1) + arity = idb->nargs; + else if (idb->nargs == -1) + ; + else if (arity != idb->nargs) + fatal_at (token, "operator '%s' with arity %d does not match " + "others with arity %d", oper, idb->nargs, arity); + + /* We allow composition of multiple operator lists. */ + if (user_id *p = dyn_cast (idb)) + op->substitutes.safe_splice (p->substitutes); + else + op->substitutes.safe_push (idb); + } + + if (op->substitutes.length () == 0) + fatal_at (token, "operator-list cannot be empty"); + + op->nargs = arity; + id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); + *slot = op; } /* Parse an outer if expression. @@ -3328,6 +3440,13 @@ parser::parse_pattern () fatal_at (token, "define_predicates inside if or for is not supported"); parse_predicates (token->src_loc); } + else if (strcmp (id, "define_operator_list") == 0) + { + if (active_ifs.length () > 0 + || active_fors.length () > 0) + fatal_at (token, "operator-list inside if or for is not supported"); + parse_operator_list (token->src_loc); + } else fatal_at (token, "expected %s'simplify', 'match', 'for' or 'if'", active_ifs.length () == 0 && active_fors.length () == 0 @@ -3345,6 +3464,7 @@ parser::parser (cpp_reader *r_) active_fors = vNULL; simplifiers = vNULL; user_predicates = vNULL; + parsing_match_operand = false; const cpp_token *token = next (); while (token->type != CPP_EOF)