From patchwork Fri Aug 20 09:45:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1518964 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=dx2IQKL/; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GrcHY2SJqz9sWw for ; Fri, 20 Aug 2021 19:47:21 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2E079381DC69 for ; Fri, 20 Aug 2021 09:47:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2E079381DC69 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1629452839; bh=/4HKFIt9x1Yx0lxIU0J+yCQK1d2wXELefZHw9AGqS50=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=dx2IQKL/DYqVn7y/y8ubd7wK/tAQ9fJ/HdX6YDh8wm9Cuuf6uYQJrB0tP6eHOcZRL pyl8Ge2Ta9cGTfNE5ZmQ8gGkZ2Fui4FYNvadaN/jic6AasTK8UN+TDdVtNeE+xvxvH f4zUoz9LNtgQ3c46WgA9sEjii7Ab9sjl5E68GtOU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 3DC03381DCF5 for ; Fri, 20 Aug 2021 09:45:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3DC03381DCF5 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-95-9SRQuAUSOxCQI9pc8JEkHg-1; Fri, 20 Aug 2021 05:45:33 -0400 X-MC-Unique: 9SRQuAUSOxCQI9pc8JEkHg-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 643EB1008060; Fri, 20 Aug 2021 09:45:32 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.120]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BB6D86A8FA; Fri, 20 Aug 2021 09:45:31 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 17K9jT6n2768771 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 20 Aug 2021 11:45:29 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 17K9jTFb2768770; Fri, 20 Aug 2021 11:45:29 +0200 Date: Fri, 20 Aug 2021 11:45:29 +0200 To: gcc-patches@gcc.gnu.org Subject: [committed] openmp: Implement the error directive Message-ID: <20210820094529.GD2380545@tucnak> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SCC_5_SHORT_WORD_LINES, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: Tobias Burnus Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Hi! This patch implements the error directive. Depending on clauses it is either a compile time diagnostics (in that case diagnosed right away) or runtime diagnostics (libgomp API call that diagnoses at runtime), and either fatal or warning (error or warning at compile time or fatal error vs. error at runtime) and either has no message or user supplied message (this kind of e.g. deprecated attribute). The directive is also stand-alone directive when at runtime while utility (thus disappears from the IL as if it wasn't there for parsing like nothing directive) at compile time. There are some clarifications in the works ATM, so this patch doesn't yet require that for compile time diagnostics the user message must be a constant string literal, there are uncertainities on what exactly is valid argument of message clause (whether just const char * type, convertible to const char *, qualified/unqualified const char * or char * or what else) and what to do in templates. Currently even in templates it is diagnosed right away for compile time diagnostics, if we'll need to substitute it, we'd need to queue something into the IL, have pt.c handle it and diagnose only later. Bootstrapped/regtested on x86_64-linux, committed to trunk. 2021-08-20 Jakub Jelinek gcc/ * omp-builtins.def (BUILT_IN_GOMP_WARNING, BUILT_IN_GOMP_ERROR): New builtins. gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ERROR. * c-pragma.c (omp_pragmas): Add error directive. * c-omp.c (omp_directives): Uncomment error directive entry. gcc/c/ * c-parser.c (c_parser_omp_error): New function. (c_parser_pragma): Handle PRAGMA_OMP_ERROR. gcc/cp/ * parser.c (cp_parser_handle_statement_omp_attributes): Determine if PRAGMA_OMP_ERROR directive is C_OMP_DIR_STANDALONE. (cp_parser_omp_error): New function. (cp_parser_pragma): Handle PRAGMA_OMP_ERROR. gcc/fortran/ * types.def (BT_FN_VOID_CONST_PTR_SIZE): New DEF_FUNCTION_TYPE_2. * f95-lang.c (ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST): Define. gcc/testsuite/ * c-c++-common/gomp/error-1.c: New test. * c-c++-common/gomp/error-2.c: New test. * c-c++-common/gomp/error-3.c: New test. * g++.dg/gomp/attrs-1.C (bar): Add error directive test. * g++.dg/gomp/attrs-2.C (bar): Add error directive test. * g++.dg/gomp/attrs-13.C: New test. * g++.dg/gomp/error-1.C: New test. libgomp/ * libgomp.map (GOMP_5.1): Add GOMP_error and GOMP_warning. * libgomp_g.h (GOMP_warning, GOMP_error): Declare. * error.c (GOMP_warning, GOMP_error): New functions. * testsuite/libgomp.c-c++-common/error-1.c: New test. Jakub --- gcc/omp-builtins.def.jj 2021-08-19 12:53:44.693106618 +0200 +++ gcc/omp-builtins.def 2021-08-19 17:46:45.960368837 +0200 @@ -463,3 +463,7 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE, "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning", + BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST) +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ERROR, "GOMP_error", + BT_FN_VOID_CONST_PTR_SIZE, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) --- gcc/c-family/c-pragma.h.jj 2021-08-19 12:53:44.690106660 +0200 +++ gcc/c-family/c-pragma.h 2021-08-19 14:37:58.004167196 +0200 @@ -53,6 +53,7 @@ enum pragma_kind { PRAGMA_OMP_DECLARE, PRAGMA_OMP_DEPOBJ, PRAGMA_OMP_DISTRIBUTE, + PRAGMA_OMP_ERROR, PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, --- gcc/c-family/c-pragma.c.jj 2021-08-19 12:53:44.690106660 +0200 +++ gcc/c-family/c-pragma.c 2021-08-19 14:37:58.004167196 +0200 @@ -1326,6 +1326,7 @@ static const struct omp_pragma_def omp_p { "cancellation", PRAGMA_OMP_CANCELLATION_POINT }, { "critical", PRAGMA_OMP_CRITICAL }, { "depobj", PRAGMA_OMP_DEPOBJ }, + { "error", PRAGMA_OMP_ERROR }, { "end", PRAGMA_OMP_END_DECLARE_TARGET }, { "flush", PRAGMA_OMP_FLUSH }, { "nothing", PRAGMA_OMP_NOTHING }, --- gcc/c-family/c-omp.c.jj 2021-08-19 12:53:44.690106660 +0200 +++ gcc/c-family/c-omp.c 2021-08-19 14:37:58.004167196 +0200 @@ -2991,8 +2991,8 @@ static const struct c_omp_directive omp_ /* { "end", "metadirective", nullptr, PRAGMA_OMP_END, C_OMP_DIR_???, ??? }, */ /* error with at(execution) is C_OMP_DIR_STANDALONE. */ - /* { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, - C_OMP_DIR_UTILITY, false }, */ + { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, + C_OMP_DIR_UTILITY, false }, { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH, C_OMP_DIR_STANDALONE, false }, { "for", nullptr, nullptr, PRAGMA_OMP_FOR, --- gcc/c/c-parser.c.jj 2021-08-19 13:19:56.217288105 +0200 +++ gcc/c/c-parser.c 2021-08-19 15:22:10.146195464 +0200 @@ -1588,6 +1588,7 @@ static bool c_parser_omp_target (c_parse static void c_parser_omp_end_declare_target (c_parser *); static bool c_parser_omp_declare (c_parser *, enum pragma_context); static void c_parser_omp_requires (c_parser *); +static bool c_parser_omp_error (c_parser *, enum pragma_context); static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *); static void c_parser_oacc_routine (c_parser *, enum pragma_context); @@ -12485,6 +12486,9 @@ c_parser_pragma (c_parser *parser, enum c_parser_omp_nothing (parser); return false; + case PRAGMA_OMP_ERROR: + return c_parser_omp_error (parser, context); + case PRAGMA_OMP_ORDERED: return c_parser_omp_ordered (parser, context, if_p); @@ -21936,6 +21940,173 @@ c_parser_omp_nothing (c_parser *parser) c_parser_skip_to_pragma_eol (parser); } +/* OpenMP 5.1 + #pragma omp error clauses[optseq] new-line */ + +static bool +c_parser_omp_error (c_parser *parser, enum pragma_context context) +{ + int at_compilation = -1; + int severity_fatal = -1; + tree message = NULL_TREE; + bool first = true; + bool bad = false; + location_t loc = c_parser_peek_token (parser)->location; + + c_parser_consume_pragma (parser); + + while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) + { + if (!first + && c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + + first = false; + + if (!c_parser_next_token_is (parser, CPP_NAME)) + break; + + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + location_t cloc = c_parser_peek_token (parser)->location; + static const char *args[] = { + "execution", "compilation", "warning", "fatal" + }; + int *v = NULL; + int idx = 0, n = -1; + tree m = NULL_TREE; + + if (!strcmp (p, "at")) + v = &at_compilation; + else if (!strcmp (p, "severity")) + { + v = &severity_fatal; + idx += 2; + } + else if (strcmp (p, "message")) + { + error_at (cloc, + "expected %, % or % clause"); + c_parser_skip_to_pragma_eol (parser, false); + return false; + } + + c_parser_consume_token (parser); + + matching_parens parens; + if (parens.require_open (parser)) + { + if (v == NULL) + { + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true); + m = convert (const_string_type_node, expr.value); + m = c_fully_fold (m, false, NULL); + } + else + { + if (c_parser_next_token_is (parser, CPP_NAME)) + { + tree val = c_parser_peek_token (parser)->value; + const char *q = IDENTIFIER_POINTER (val); + + if (!strcmp (q, args[idx])) + n = 0; + else if (!strcmp (q, args[idx + 1])) + n = 1; + } + if (n == -1) + { + error_at (c_parser_peek_token (parser)->location, + "expected %qs or %qs", args[idx], args[idx + 1]); + bad = true; + switch (c_parser_peek_token (parser)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (c_parser_peek_2nd_token (parser)->type + == CPP_CLOSE_PAREN) + c_parser_consume_token (parser); + break; + } + } + else + c_parser_consume_token (parser); + } + + parens.skip_until_found_close (parser); + + if (v == NULL) + { + if (message) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + message = m; + } + else if (n != -1) + { + if (*v != -1) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + *v = n; + } + } + else + bad = true; + } + c_parser_skip_to_pragma_eol (parser); + if (bad) + return true; + + if (at_compilation == -1) + at_compilation = 1; + if (severity_fatal == -1) + severity_fatal = 1; + if (!at_compilation) + { + if (context != pragma_compound) + { + error_at (loc, "%<#pragma omp error%> with % clause " + "may only be used in compound statements"); + return true; + } + tree fndecl + = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR + : BUILT_IN_GOMP_WARNING); + if (!message) + message = build_zero_cst (const_string_type_node); + tree stmt = build_call_expr_loc (loc, fndecl, 2, message, + build_all_ones_cst (size_type_node)); + add_stmt (stmt); + return true; + } + const char *msg = NULL; + if (message) + { + msg = c_getstr (message); + if (msg == NULL) + msg = _(""); + } + if (msg) + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "% encountered: %s", msg); + else + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "% encountered"); + return false; +} + /* Main entry point to parsing most OpenMP pragmas. */ static void --- gcc/cp/parser.c.jj 2021-08-19 13:40:26.387178416 +0200 +++ gcc/cp/parser.c 2021-08-19 17:47:20.769883975 +0200 @@ -11760,10 +11760,30 @@ cp_parser_handle_statement_omp_attribute "depend") == 0) kind = C_OMP_DIR_STANDALONE; } - /* else if (dir->id == PRAGMA_OMP_ERROR) + else if (dir->id == PRAGMA_OMP_ERROR) { - error with at(execution) clause is C_OMP_DIR_STANDALONE. - } */ + /* error with at(execution) clause is C_OMP_DIR_STANDALONE. */ + int paren_depth = 0; + for (int i = 1; first + i < last; i++) + if (first[i].type == CPP_OPEN_PAREN) + paren_depth++; + else if (first[i].type == CPP_CLOSE_PAREN) + paren_depth--; + else if (paren_depth == 0 + && first + i + 2 < last + && first[i].type == CPP_NAME + && first[i + 1].type == CPP_OPEN_PAREN + && first[i + 2].type == CPP_NAME + && !strcmp (IDENTIFIER_POINTER (first[i].u.value), + "at") + && !strcmp (IDENTIFIER_POINTER (first[i + + 2].u.value), + "execution")) + { + kind = C_OMP_DIR_STANDALONE; + break; + } + } cp_omp_attribute_data v = { DEFPARSE_TOKENS (d), dir, kind }; vec.safe_push (v); if (flag_openmp || dir->simd) @@ -45590,6 +45610,184 @@ cp_parser_omp_nothing (cp_parser *parser } +/* OpenMP 5.1 + #pragma omp error clauses[optseq] new-line */ + +static bool +cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok, + enum pragma_context context) +{ + int at_compilation = -1; + int severity_fatal = -1; + tree message = NULL_TREE; + bool first = true; + bool bad = false; + location_t loc = pragma_tok->location; + + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) + { + /* For now only in C++ attributes, do it always for OpenMP 5.1. */ + if ((!first || parser->lexer->in_omp_attribute_pragma) + && cp_lexer_next_token_is (parser->lexer, CPP_COMMA) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)) + cp_lexer_consume_token (parser->lexer); + + first = false; + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + break; + + const char *p + = IDENTIFIER_POINTER (cp_lexer_peek_token (parser->lexer)->u.value); + location_t cloc = cp_lexer_peek_token (parser->lexer)->location; + static const char *args[] = { + "execution", "compilation", "warning", "fatal" + }; + int *v = NULL; + int idx = 0, n = -1; + tree m = NULL_TREE; + + if (!strcmp (p, "at")) + v = &at_compilation; + else if (!strcmp (p, "severity")) + { + v = &severity_fatal; + idx += 2; + } + else if (strcmp (p, "message")) + { + error_at (cloc, + "expected %, % or % clause"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return false; + } + + cp_lexer_consume_token (parser->lexer); + + matching_parens parens; + if (parens.require_open (parser)) + { + if (v == NULL) + { + m = cp_parser_assignment_expression (parser); + if (type_dependent_expression_p (m)) + m = build1 (IMPLICIT_CONV_EXPR, const_string_type_node, m); + else + m = perform_implicit_conversion_flags (const_string_type_node, m, + tf_warning_or_error, + LOOKUP_NORMAL); + } + else + { + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree val = cp_lexer_peek_token (parser->lexer)->u.value; + const char *q = IDENTIFIER_POINTER (val); + + if (!strcmp (q, args[idx])) + n = 0; + else if (!strcmp (q, args[idx + 1])) + n = 1; + } + if (n == -1) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "expected %qs or %qs", args[idx], args[idx + 1]); + bad = true; + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + case CPP_CLOSE_PAREN: + break; + default: + if (cp_lexer_nth_token_is (parser->lexer, 2, + CPP_CLOSE_PAREN)) + cp_lexer_consume_token (parser->lexer); + break; + } + } + else + cp_lexer_consume_token (parser->lexer); + } + + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/ + true); + + if (v == NULL) + { + if (message) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + message = m; + } + else if (n != -1) + { + if (*v != -1) + { + error_at (cloc, "too many %qs clauses", p); + bad = true; + } + else + *v = n; + } + } + else + bad = true; + } + cp_parser_require_pragma_eol (parser, pragma_tok); + if (bad) + return true; + + if (at_compilation == -1) + at_compilation = 1; + if (severity_fatal == -1) + severity_fatal = 1; + if (!at_compilation) + { + if (context != pragma_compound) + { + error_at (loc, "%<#pragma omp error%> with % clause " + "may only be used in compound statements"); + return true; + } + tree fndecl + = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR + : BUILT_IN_GOMP_WARNING); + if (!message) + message = build_zero_cst (const_string_type_node); + tree stmt = build_call_expr_loc (loc, fndecl, 2, message, + build_all_ones_cst (size_type_node)); + add_stmt (stmt); + return true; + } + + if (in_discarded_stmt) + return false; + + const char *msg = NULL; + if (message) + { + msg = c_getstr (fold_for_warn (message)); + if (msg == NULL) + msg = _(""); + } + if (msg) + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "% encountered: %s", msg); + else + emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + "% encountered"); + return false; +} + /* OpenMP 4.5: #pragma omp taskloop taskloop-clause[optseq] new-line for-loop @@ -46703,6 +46901,9 @@ cp_parser_pragma (cp_parser *parser, enu cp_parser_omp_nothing (parser, pragma_tok); return false; + case PRAGMA_OMP_ERROR: + return cp_parser_omp_error (parser, pragma_tok, context); + case PRAGMA_OMP_ORDERED: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; --- gcc/fortran/types.def.jj 2021-08-17 09:24:58.778051205 +0200 +++ gcc/fortran/types.def 2021-08-19 17:47:10.548026356 +0200 @@ -120,6 +120,7 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE, BT_VOID, BT_PTR, BT_PTRMODE) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR) --- gcc/fortran/f95-lang.c.jj 2021-08-19 12:53:44.693106618 +0200 +++ gcc/fortran/f95-lang.c 2021-08-19 14:37:58.004167196 +0200 @@ -535,7 +535,7 @@ gfc_builtin_function (tree decl) return decl; } -/* So far we need just these 8 attribute types. */ +/* So far we need just these 10 attribute types. */ #define ATTR_NULL 0 #define ATTR_LEAF_LIST (ECF_LEAF) #define ATTR_NOTHROW_LEAF_LIST (ECF_NOTHROW | ECF_LEAF) @@ -546,6 +546,9 @@ gfc_builtin_function (tree decl) #define ATTR_CONST_NOTHROW_LIST (ECF_NOTHROW | ECF_CONST) #define ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST \ (ECF_NOTHROW) +#define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \ + (ECF_COLD | ECF_NORETURN | \ + ECF_NOTHROW | ECF_LEAF) static void gfc_define_builtin (const char *name, tree type, enum built_in_function code, --- gcc/testsuite/c-c++-common/gomp/error-1.c.jj 2021-08-19 14:37:58.000167251 +0200 +++ gcc/testsuite/c-c++-common/gomp/error-1.c 2021-08-19 14:37:57.999167265 +0200 @@ -0,0 +1,45 @@ +#pragma omp error /* { dg-error "'pragma omp error' encountered" } */ +#pragma omp error at(compilation) /* { dg-error "'pragma omp error' encountered" } */ +#pragma omp error severity(fatal) /* { dg-error "'pragma omp error' encountered" } */ +#pragma omp error message("my msg") /* { dg-error "'pragma omp error' encountered: my msg" } */ +#pragma omp error severity(warning)message("another message")at(compilation) /* { dg-warning "'pragma omp error' encountered: another message" } */ + +struct S { + #pragma omp error /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error at(compilation) /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error severity(fatal) /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error message("42") /* { dg-error "'pragma omp error' encountered: 42" } */ + #pragma omp error severity(warning), message("foo"), at(compilation) /* { dg-warning "'pragma omp error' encountered: foo" } */ + int s; +}; + +int +foo (int i, int x) +{ + #pragma omp error /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error at(compilation) /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error severity(fatal) /* { dg-error "'pragma omp error' encountered" } */ + #pragma omp error message("42 / 1") /* { dg-error "'pragma omp error' encountered: 42 / 1" } */ + #pragma omp error severity(warning) message("bar") at(compilation) /* { dg-warning "'pragma omp error' encountered: bar" } */ + if (x) + #pragma omp error /* { dg-error "'pragma omp error' encountered" } */ + i++; + if (x) + ; + else + #pragma omp error at(compilation) /* { dg-error "'pragma omp error' encountered" } */ + i++; + switch (0) + #pragma omp error severity(fatal) /* { dg-error "'pragma omp error' encountered" } */ + { + default: + break; + } + while (0) + #pragma omp error message("42 - 1") /* { dg-error "'pragma omp error' encountered: 42 - 1" } */ + i++; + lab: + #pragma omp error severity(warning) message("bar") at(compilation) /* { dg-warning "'pragma omp error' encountered: bar" } */ + i++; + return i; +} --- gcc/testsuite/c-c++-common/gomp/error-2.c.jj 2021-08-19 14:37:58.000167251 +0200 +++ gcc/testsuite/c-c++-common/gomp/error-2.c 2021-08-19 14:37:58.000167251 +0200 @@ -0,0 +1,24 @@ +void +foo (int x, const char *msg1, const char *msg2) +{ + if (x == 0) + { + #pragma omp error at(execution) + } + else if (x == 1) + { + #pragma omp error severity (warning), at (execution) + } + else if (x == 2) + { + #pragma omp error at ( execution ) severity (fatal) message ("baz") + } + else if (x == 3) + { + #pragma omp error severity(warning) message (msg1) at(execution) + } + else + { + #pragma omp error message (msg2), at(execution), severity(fatal) + } +} --- gcc/testsuite/c-c++-common/gomp/error-3.c.jj 2021-08-19 14:37:58.000167251 +0200 +++ gcc/testsuite/c-c++-common/gomp/error-3.c 2021-08-19 17:41:51.712467429 +0200 @@ -0,0 +1,70 @@ +#pragma omp error asdf /* { dg-error "expected 'at', 'severity' or 'message' clause" } */ +#pragma omp error at /* { dg-error "expected '\\\(' before end of line" } */ +#pragma omp error at( /* { dg-error "expected 'execution' or 'compilation'" } */ + /* { dg-error "expected '\\\)' before end of line" "" { target *-*-* } .-1 } */ +#pragma omp error at(runtime) /* { dg-error "expected 'execution' or 'compilation'" } */ +#pragma omp error at(+ /* { dg-error "expected 'execution' or 'compilation'" } */ + /* { dg-error "expected '\\\)' before '\\\+' token" "" { target *-*-* } .-1 } */ +#pragma omp error at(compilation /* { dg-error "expected '\\\)' before end of line" } */ + /* { dg-error "'pragma omp error' encountered" "" { target *-*-* } .-1 } */ +#pragma omp error severity /* { dg-error "expected '\\\(' before end of line" } */ +#pragma omp error severity( /* { dg-error "expected 'warning' or 'fatal'" } */ + /* { dg-error "expected '\\\)' before end of line" "" { target *-*-* } .-1 } */ +#pragma omp error severity(error) /* { dg-error "expected 'warning' or 'fatal'" } */ +#pragma omp error severity(- /* { dg-error "expected 'warning' or 'fatal'" } */ + /* { dg-error "expected '\\\)' before '-' token" "" { target *-*-* } .-1 } */ +#pragma omp error severity(fatal /* { dg-error "expected '\\\)' before end of line" } */ + /* { dg-error "'pragma omp error' encountered" "" { target *-*-* } .-1 } */ +#pragma omp error message /* { dg-error "expected '\\\(' before end of line" } */ +#pragma omp error message( /* { dg-error "expected expression before end of line" "" { target c } } */ + /* { dg-error "expected primary-expression before end of line" "" { target c++ } .-1 } */ + /* { dg-error "expected '\\\)' before end of line" "" { target c++ } .-2 } */ + /* { dg-error "'pragma omp error' encountered: " "" { target *-*-* } .-3 } */ +#pragma omp error message(0 /* { dg-error "expected '\\\)' before end of line" } */ + /* { dg-error "'pragma omp error' encountered: " "" { target *-*-* } .-1 } */ +#pragma omp error message("foo" /* { dg-error "expected '\\\)' before end of line" } */ + /* { dg-error "'pragma omp error' encountered: foo" "" { target *-*-* } .-1 } */ +#pragma omp error message(1) /* { dg-error "'pragma omp error' encountered: " } */ + /* { dg-error "invalid conversion from 'int' to 'const char\\*'" "" { target c++ } .-1 } */ +#pragma omp error message(1.2) /* { dg-error "cannot convert to a pointer type" "" { target c } } */ + /* { dg-error "could not convert" "" { target c++ } .-1 } */ + /* { dg-error "'pragma omp error' encountered: " "" { target *-*-* } .-2 } */ +#pragma omp error message(L"bar") /* { dg-error "'pragma omp error' encountered: " } */ + /* { dg-error "could not convert" "" { target c++ } .-1 } */ +#pragma omp error message("foo"),at(compilation),severity(fatal), /* { dg-error "expected end of line before ',' token" } */ + /* { dg-error "'pragma omp error' encountered: foo" "" { target *-*-* } .-1 } */ +#pragma omp error message("foo"),at(compilation),severity(fatal),asdf /* { dg-error "expected 'at', 'severity' or 'message' clause" } */ +#pragma omp error at(compilation) at(compilation) /* { dg-error "too many 'at' clauses" } */ +#pragma omp error severity(fatal) severity(warning) /* { dg-error "too many 'severity' clauses" } */ +#pragma omp error message("foo") message("foo") /* { dg-error "too many 'message' clauses" } */ +#pragma omp error at(execution) /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + +struct S +{ + #pragma omp error at(execution) message("foo")/* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + int s; +}; + +int +foo (int i, int x, const char *msg) +{ + #pragma omp error message(msg) /* { dg-error "'pragma omp error' encountered: " } */ + if (x) + #pragma omp error at(execution) /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + i++; + if (x) + ; + else + #pragma omp error at(execution) severity(warning) /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + i++; + switch (0) + #pragma omp error severity(fatal) at(execution) /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + ; + while (0) + #pragma omp error at(execution)message("42 - 1") /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + i++; + lab: + #pragma omp error severity(warning) message("bar") at(execution) /* { dg-error "'#pragma omp error' with 'at\\\(execution\\\)' clause may only be used in compound statements" } */ + i++; + return i; +} --- gcc/testsuite/g++.dg/gomp/attrs-1.C.jj 2021-08-19 11:42:27.417421677 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-1.C 2021-08-19 17:05:23.953934117 +0200 @@ -109,9 +109,11 @@ baz (int d, int m, int i1, int i2, int p void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, - int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm, + const char *msg) { [[omp::directive (nothing)]]; + [[omp::directive (error at (execution) severity (warning) message (msg))]]; [[omp::directive (for simd private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) allocate (f))]] --- gcc/testsuite/g++.dg/gomp/attrs-2.C.jj 2021-08-19 11:42:27.421421621 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-2.C 2021-08-19 17:05:06.757173496 +0200 @@ -109,9 +109,11 @@ baz (int d, int m, int i1, int i2, int p void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, - int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm, + const char *msg) { [[omp::directive (nothing)]]; + [[omp::directive (error, at (execution), severity (warning), message (msg))]]; [[omp::directive (for simd, private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, safelen(8),simdlen(4),aligned(q: 32),nontemporal(ntm),if(i1),order(concurrent),allocate (f))]] --- gcc/testsuite/g++.dg/gomp/attrs-13.C.jj 2021-08-19 17:09:01.228909636 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-13.C 2021-08-19 17:57:29.933397757 +0200 @@ -0,0 +1,34 @@ +// { dg-do compile { target c++11 } } + +[[omp::directive(error)]]; // { dg-error "'pragma omp error' encountered" } +[[omp::directive(error, at(compilation))]]; // { dg-error "'pragma omp error' encountered" } +[[omp::directive(error severity(fatal))]]; // { dg-error "'pragma omp error' encountered" } +[[omp::directive(error, message("my msg"))]]; // { dg-error "'pragma omp error' encountered: my msg" } +[[omp::directive(error severity(warning)message("another message")at(compilation))]]; // { dg-warning "'pragma omp error' encountered: another message" } + +int +foo (int i, int x) +{ + [[omp::directive(error)]]; // { dg-error "'pragma omp error' encountered" } + [[omp::directive(error, at(compilation))]]; // { dg-error "'pragma omp error' encountered" } + [[omp::directive(error severity(fatal))]]; // { dg-error "'pragma omp error' encountered" } + [[omp::directive(error, message("42 / 1"))]]; // { dg-error "'pragma omp error' encountered: 42 / 1" } + [[omp::directive(error severity(warning) message("bar") at(compilation))]]; // { dg-warning "'pragma omp error' encountered: bar" } + if (x) + [[omp::directive(error)]]; // { dg-error "'pragma omp error' encountered" } + i++; + if (x) + ; + else + [[omp::directive(error at(compilation))]]; // { dg-error "'pragma omp error' encountered" } + i++; + switch (0) + [[omp::directive(error, severity(fatal))]]; // { dg-error "'pragma omp error' encountered" } + while (0) + [[omp::directive(error, message("42 - 1"))]]; // { dg-error "'pragma omp error' encountered: 42 - 1" } + i++; + lab: + [[omp::directive(error, severity(warning) message("bar"), at(compilation))]]; // { dg-warning "'pragma omp error' encountered: bar" } + i++; + return i; +} --- gcc/testsuite/g++.dg/gomp/error-1.C.jj 2021-08-19 17:18:58.231599327 +0200 +++ gcc/testsuite/g++.dg/gomp/error-1.C 2021-08-19 17:56:41.478073032 +0200 @@ -0,0 +1,42 @@ +// { dg-do compile { target c++17 } } + +void +foo () +{ + if constexpr (false) + { + #pragma omp error // { dg-bogus "'pragma omp error' encountered" } + } + else + { + #pragma omp error at(compilation) severity(warning) message("foo") // { dg-warning "'pragma omp error' encountered: foo" } + } + if constexpr (true) + { + #pragma omp error message("bar") // { dg-error "'pragma omp error' encountered: bar" } + } + else + { + #pragma omp error message("baz") // { dg-bogus "'pragma omp error' encountered" } + } +} + +template +bool +bar (T x) +{ + #pragma omp error at(execution) message (x) + return false; +} + +bool a = bar ("foo"); + +template +bool +baz (T x) +{ + #pragma omp error at(execution) message (x) // { dg-error "could not convert" } + return false; +} + +bool b = baz (L"foo"); --- libgomp/libgomp.map.jj 2021-08-19 12:53:44.693106618 +0200 +++ libgomp/libgomp.map 2021-08-19 14:37:58.004167196 +0200 @@ -382,7 +382,9 @@ GOMP_5.0.1 { GOMP_5.1 { global: + GOMP_error; GOMP_scope_start; + GOMP_warning; } GOMP_5.0.1; OACC_2.0 { --- libgomp/libgomp_g.h.jj 2021-08-19 12:53:44.693106618 +0200 +++ libgomp/libgomp_g.h 2021-08-19 14:58:44.728786591 +0200 @@ -366,6 +366,11 @@ extern void GOMP_teams_reg (void (*) (vo extern void *GOMP_alloc (size_t, size_t, uintptr_t); extern void GOMP_free (void *, uintptr_t); +/* error.c */ + +extern void GOMP_warning (const char *, size_t); +extern void GOMP_error (const char *, size_t); + /* oacc-async.c */ extern void GOACC_wait (int, int, ...); --- libgomp/error.c.jj 2021-08-19 12:53:44.693106618 +0200 +++ libgomp/error.c 2021-08-19 17:58:55.633203432 +0200 @@ -89,3 +89,34 @@ gomp_fatal (const char *fmt, ...) gomp_vfatal (fmt, list); va_end (list); } + +void +GOMP_warning (const char *msg, size_t msglen) +{ + if (msg && msglen == (size_t) -1) + gomp_error ("error directive encountered: %s", msg); + else if (msg) + { + fputs ("\nlibgomp: error directive encountered: ", stderr); + fwrite (msg, 1, msglen, stderr); + fputc ('\n', stderr); + } + else + gomp_error ("error directive encountered"); +} + +void +GOMP_error (const char *msg, size_t msglen) +{ + if (msg && msglen == (size_t) -1) + gomp_fatal ("fatal error: error directive encountered: %s", msg); + else if (msg) + { + fputs ("\nlibgomp: fatal error: error directive encountered: ", stderr); + fwrite (msg, 1, msglen, stderr); + fputc ('\n', stderr); + exit (EXIT_FAILURE); + } + else + gomp_fatal ("fatal error: error directive encountered"); +} --- libgomp/testsuite/libgomp.c-c++-common/error-1.c.jj 2021-08-19 15:26:12.576816311 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/error-1.c 2021-08-19 17:59:10.389997780 +0200 @@ -0,0 +1,49 @@ +/* { dg-shouldfail "error directive" } */ + +#ifdef __cplusplus +extern "C" +#endif +void abort (); + +int +foo (int i, int x) +{ + if (x) + #pragma omp error severity(warning) /* { dg-warning "'pragma omp error' encountered" } */ + i++; + if (!x) + ; + else + #pragma omp error severity(warning) /* { dg-warning "'pragma omp error' encountered" } */ + i += 2; + switch (0) + #pragma omp error severity(warning) /* { dg-warning "'pragma omp error' encountered" } */ + { + default: + break; + } + while (0) + #pragma omp error message("42 - 1") severity (warning) /* { dg-warning "'pragma omp error' encountered: 42 - 1" } */ + i += 4; + lab: + #pragma omp error severity(warning) message("bar") at(compilation) /* { dg-warning "'pragma omp error' encountered: bar" } */ + i += 8; + return i; +} + +int +main () +{ + if (foo (5, 0) != 13 || foo (6, 1) != 17) + abort (); + #pragma omp error at (execution) severity (warning) + const char *msg = "my message" + 2; + #pragma omp error at (execution) severity (warning) message (msg + 1) + #pragma omp error at (execution) severity (fatal) message (msg - 2) + #pragma omp error at (execution) severity (warning) message ("foobar") + return 0; +} + +/* { dg-output "libgomp: error directive encountered(\n|\r|\n\r)(\n|\r|\n\r)" } */ +/* { dg-output "libgomp: error directive encountered: message(\n|\r|\n\r)(\n|\r|\n\r)" } */ +/* { dg-output "libgomp: fatal error: error directive encountered: my message" } */