From patchwork Tue May 5 15:01:58 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waffl3x X-Patchwork-Id: 134497 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id AA3BA4BA79BA for ; Tue, 5 May 2026 15:15:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AA3BA4BA79BA Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20251104.gappssmtp.com header.i=@baylibre-com.20251104.gappssmtp.com header.a=rsa-sha256 header.s=20251104 header.b=q6XQnOzD X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) by sourceware.org (Postfix) with ESMTPS id 605A94BA900F for ; Tue, 5 May 2026 15:10:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 605A94BA900F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 605A94BA900F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::435 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777993843; cv=none; b=V/ELmwiH7kLQ08may0R+6nNy2+If9YLeJXHJ7EM7G3TtLXJi/qkqYpn94gJcc9SpVVJrImDA1YiZIDoisgyRLH7/fYDHPGdtX1BiNrZryeO+1mmpy3nO7yZfhYyNN8uBITgdz/HSiJVmmIoCmMK4ssV3CJXyzT69zSTtA9F8G0Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777993843; c=relaxed/simple; bh=sF4fV1bDevpXE0R5B1P3u9c74/6q8mKpOtGtykmvCtM=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Arye+rJ74xqqwXl0XTehlBUs1jsyXXKQepuef6btiDWqH/iSLDRqFdnm55oKaojJIiZyE1vmVTTHYic7OLE5CYR5UE9G+KT79d8/EEo9pyM11/UQmljxMF1grfR8vRV4hz526scRC8+YjUF3devtzGHwG14KxcSQw6rKh3ODq60= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 605A94BA900F Received: by mail-pf1-x435.google.com with SMTP id d2e1a72fcca58-835451c5debso112985b3a.2 for ; Tue, 05 May 2026 08:10:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20251104.gappssmtp.com; s=20251104; t=1777993842; x=1778598642; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gqRopMsDKtwE2JgA2ANfgdHhULzFdSfyUcM770uho5I=; b=q6XQnOzDTyACSEKmsS4oG1JUlPDuuAmi+4vP5Jh95OiwNf3tc5JhIkFqZuzR/eHOAi Kqr2CCPgGd5UVFhX4YkJSP46Jlp8hD5cht0atKsxDeMHM/MLZHg24KSlZFtihxRE1VTL O3Jun5fJ1Xz1tDxlOeljx1txXBeSFOKCwQFSGEKS5yFQYCxQCozXo1E4aZmVGO20dWX0 Ms00WfhycXkW+HsUh3zW7jfjuWmeJ7h3Rnn45PcxSO40TB5L0AaoSWnEDKQ82Kbl5p+g At08gFlzJ4MSuYvmsZtrJmckxIHEP61iGq2bn8t3PLNJh9FIAWH0jyei1JoVor1eoGiD EUXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777993842; x=1778598642; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=gqRopMsDKtwE2JgA2ANfgdHhULzFdSfyUcM770uho5I=; b=rMs1W+1ElcxhzSPtMYpPbwqQ+9djj4/lWX2U6Gt4orxzIebYb3SGw0I0PSdqLcJrMB S40APle9Qezb7MYSJHjNAp1+1ZMsgDgsSvu3W5VZBLfzPnybnlGSCBxjgMo+bvYxWMqB YNNhpztPgnGIjEezAcmFIpaX8p5xy3FLzum7YE+6LCI3RCJjMa3W4LaPsUmmr/M5sDz3 9XDgr4PP/xV9GcWweWg71rkMkHLLS2zf/0S3IaPDWid7soLTkyKJvQYC3aa4XRh8WUfY BjS4pTx7osJZk6C3vJ8T8ccRqZ5A1Xi7nY6QUhpfWuaue74/JHWZgwDgFFBhC9jtNPTc DxZw== X-Gm-Message-State: AOJu0YwrNjgUk9NYTrTUvN6fl54s4pUVPQEc1nTePdNyvPY7TegdUw84 XVxxP10VcKUDhF37Z352L1yEvFPsIFbvkz5Jc9Cj+Cokx5wZ449jViYH9EyLo1uf67C+d+AL9J3 KsIG3 X-Gm-Gg: AeBDieuEW60AyFxn56BZY2Ns7VWpCs2v3HUTQpDomQHYcBW0u5SBZC256xc0OOOZDcB Smgc4mBGQ/WuQjxWY+/CJGnHDv9gQ/qO/XQX2VA2SyM8LMJHdfNmLqWvveUdxBJ5tdtTu9HvfDr VeV1dxeDPMmY3koV30G34+oXF8thljqPG+PBZWZL8Bz2wWaRptv/YGZQn2m/Sg9XzTR/ujqH7JD AFuD669ICBH+Jt0uszooDPDxxA4GaOzAia7l3184opuO44iI6xXpTAKbNw5sxnnC1ynwTQ0elCm aP4/Je1RfZS7uiD+gMLB5Nfp3wyFVK4DtwJ6Cb8y0du+fJuau+sA0PDnaocz4A+QdFSSYzAgcjj t8yjgJJmohverpQQw9iS825xN7+Zhewxu9iYe2tm6UqxYy4+PKaTmhn09xqfg8TGJfVoMxxmWTT I72zBRrPl2ahtusg0hEvrV8lJrUhcmx238G81+9ZucH8aM+xSXZQ== X-Received: by 2002:a05:6a00:e18:b0:82f:6a82:4231 with SMTP id d2e1a72fcca58-8352d14842cmr7303425b3a.1.1777993841214; Tue, 05 May 2026 08:10:41 -0700 (PDT) Received: from waffl3x-prestige.lan ([2001:56a:f98a:b800:1f67:ce08:3cbd:86b8]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-83965645140sm2674956b3a.12.2026.05.05.08.10.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 May 2026 08:10:40 -0700 (PDT) From: Waffl3x To: gcc-patches@gcc.gnu.org Cc: Waffl3x Subject: [PATCH 05/12] OpenMP/C++: Enhance diagnostics of 'omp allocate' directive Date: Tue, 5 May 2026 09:01:58 -0600 Message-ID: <20260505151030.1749548-6-waffl3x@baylibre.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260505151030.1749548-1-waffl3x@baylibre.com> References: <20260505151030.1749548-1-waffl3x@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Add diagnostics for multiple uses of a var in a single directive, uses of parameters, vars in a different scope, and vars that are references. Enhances diagnostics, as well as reporting a proper location in most cases. gcc/cp/ChangeLog: * parser.cc (cp_parser_omp_allocate): Add diagnostics, wrap a location into allocator and alignment clause exprs. * semantics.cc: Include gcc-rich-location.h. (finish_omp_allocate): Improve and add diagnostics. gcc/testsuite/ChangeLog: * c-c++-common/gomp/allocate-9.c: Remove xfails. * c-c++-common/gomp/allocate-19.c: Remove xfails. * c-c++-common/gomp/allocate-20.c: New test. * g++.dg/gomp/allocate-14.C: New test. * g++.dg/gomp/allocate-15.C: New test. * g++.dg/gomp/allocate-16.C: New test. * g++.dg/gomp/allocate-17.C: New test. * g++.dg/gomp/allocate-18.C: New test. * g++.dg/gomp/allocate-19.C: New test. * g++.dg/gomp/allocate-handles-1.C: Remove xfails. Signed-off-by: Waffl3x --- gcc/cp/parser.cc | 76 +- gcc/cp/semantics.cc | 76 +- gcc/testsuite/c-c++-common/gomp/allocate-19.c | 10 +- gcc/testsuite/c-c++-common/gomp/allocate-20.c | 343 ++++++ gcc/testsuite/c-c++-common/gomp/allocate-9.c | 30 +- gcc/testsuite/g++.dg/gomp/allocate-14.C | 1042 +++++++++++++++++ gcc/testsuite/g++.dg/gomp/allocate-15.C | 50 + gcc/testsuite/g++.dg/gomp/allocate-16.C | 232 ++++ gcc/testsuite/g++.dg/gomp/allocate-17.C | 560 +++++++++ gcc/testsuite/g++.dg/gomp/allocate-18.C | 274 +++++ gcc/testsuite/g++.dg/gomp/allocate-19.C | 128 ++ .../g++.dg/gomp/allocate-handles-1.C | 34 +- 12 files changed, 2810 insertions(+), 45 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/allocate-20.c create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-14.C create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-15.C create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-16.C create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-17.C create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-18.C create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-19.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 2cec22a9386..924e52da6ea 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -47186,7 +47186,31 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) { tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL_TREE); + /* Make diagnostics emit in forward order. */ + nl = nreverse (nl); + + const tree directive_ctx = current_scope (); { + auto var_is_in_scope = [&] (tree var_decl) + { + /* (OpenMP 6.0 311:11-12) An allocate directive must appear in the same + scope as the declarations of each of its list items and must follow + all such declarations. + + Note that it states declarations, not definitions, thus we can rely + on VAR_DECL's CP_DECL_CONTEXT. This will correctly reject an + allocate directive applied to a definition in a different scope. */ + if (!DECL_DECLARES_FUNCTION_P (directive_ctx)) + return CP_DECL_CONTEXT (var_decl) == directive_ctx; + /* This is O(n^2), caching names during traversal might be better. */ + for (tree block_var = current_binding_level->names; + block_var != NULL_TREE; + block_var = DECL_CHAIN (block_var)) + if (block_var == var_decl) + return true; + return false; + }; + hash_map seen_args; /* The head might have an error and need to be removed. */ tree *chain = &nl; for (tree node = nl; node != NULL_TREE; node = TREE_CHAIN (node)) @@ -47195,6 +47219,52 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) const tree arg_loc_wrapper = TREE_VALUE (node); const location_t arg_loc = EXPR_LOCATION (arg_loc_wrapper); + gcc_assert (var && var != error_mark_node); + /* Diagnose duplicate vars passed to the allocate directive. */ + if (location_t const *const orig_loc = seen_args.get (var)) + { + auto_diagnostic_group d; + /* If we could just get the location of the comma a fixit + hint would be viable here. */ + error_at (arg_loc, + "%qD already appeared as list item in this directive", + var); + inform (*orig_loc, "appeared first here"); + /* Remove the node. */ + *chain = TREE_CHAIN (node); + continue; + } + seen_args.put (var, arg_loc); + + /* Diagnose parameters passed to the allocate directive. */ + if (TREE_CODE (var) == PARM_DECL) + { + auto_diagnostic_group d; + error_at (arg_loc, + "function parameter %qD may not appear as list item in " + "an % directive", var); + inform (DECL_SOURCE_LOCATION (var), + "parameter %qD declared here", var); + /* Remove the node. */ + *chain = TREE_CHAIN (node); + continue; + } + + /* Do this before checking if the var was used in another allocate + directive, as the latter diagnostic implies that removing the var + from the previous directive would fix the problem. */ + if (!var_is_in_scope (var)) + { + auto_diagnostic_group d; + error_at (arg_loc, + "% directive must be in the same scope as " + "%qD", var); + inform (DECL_SOURCE_LOCATION (var), "declared here"); + /* Remove the node. */ + *chain = TREE_CHAIN (node); + continue; + } + tree attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (var)); if (attr) @@ -47284,6 +47354,7 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) if (!parens.require_open (parser)) break; cp_expr expr = cp_parser_assignment_expression (parser); + expr.maybe_add_location_wrapper (); if (p[2] == 'i' && alignment) { error_at (cloc, "too many %qs clauses", "align"); @@ -47302,11 +47373,14 @@ cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) } while (true); cp_parser_require_pragma_eol (parser, pragma_tok); + /* We can still diagnose some things about allocator/alignment even if nl + is NULL_TREE. */ + finish_omp_allocate (pragma_tok->location, nl, allocator, alignment, - current_scope ()); + directive_ctx); } /* OpenMP 2.5: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index ac81bbe9317..00c09e119c8 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "contracts.h" #include "c-family/c-pragma.h" +#include "gcc-rich-location.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -12393,6 +12394,62 @@ finish_omp_allocate (const location_t loc, const tree var_list, } (); /* IILE. */ const bool any_static_vars = any_of_vars (tree_static_p); + /* Create an auto_diagnostic_group before calling this. */ + const auto emit_diag_for_var_group + = [] (const var_predicate pred, + void (*diag_fn)(rich_location *, const char *, ...), + const char *msg, + const const_tree var_list) + { + auto next_match = [&pred] (const_tree first) + { + const_tree vn = first; + for (; vn != NULL_TREE; vn = TREE_CHAIN (vn)) + if (TREE_PURPOSE (vn) != error_mark_node + && pred (TREE_PURPOSE (vn))) + return vn; + return vn; + }; + gcc_assert (var_list != NULL_TREE); + const const_tree first_node = next_match (var_list); + gcc_assert (first_node != NULL_TREE); + + gcc_rich_location rich_loc (EXPR_LOCATION (TREE_VALUE (first_node))); + /* Don't add another range for the first node. */ + for (const_tree vn = next_match (TREE_CHAIN (first_node)); + vn != NULL_TREE; + vn = next_match (TREE_CHAIN (vn))) + rich_loc.add_range (EXPR_LOCATION (TREE_VALUE (vn))); + diag_fn (&rich_loc, msg); + + const_tree vn = first_node; + for (; vn != NULL_TREE; vn = next_match (TREE_CHAIN (vn))) + inform (DECL_SOURCE_LOCATION (TREE_PURPOSE (vn)), + "%qD declared here", TREE_PURPOSE (vn)); + }; + + /* Defer error marking vars until after other diagnostics are done, we might + still need access to them when diagnosing the allocator clause. */ + hash_set deferred_erroneous_var_nodes; + + const auto ref_var_p + = [] (const_tree t) -> bool { return TYPE_REF_P (TREE_TYPE (t)); }; + if (any_of_vars (ref_var_p)) + { + auto_diagnostic_group d; + emit_diag_for_var_group (ref_var_p, + &error_at, + G_("variables with reference type may not " + "appear in an % directive"), + var_list); + for (tree vn = var_list; vn != NULL_TREE; vn = TREE_CHAIN (vn)) + { + if (!ref_var_p (TREE_PURPOSE (vn))) + continue; + deferred_erroneous_var_nodes.add (vn); + } + } + /* (OpenMP 5.2, 174:15) Type: expression of integer type Properties: constant, positive */ const tree align = [&align_in] () @@ -12449,9 +12506,12 @@ finish_omp_allocate (const location_t loc, const tree var_list, allocator values. */ const auto emit_diag_for_static_vars = [&] () { - inform (UNKNOWN_LOCATION, - "because one or more variables with static storage duration " - "appear in the % directive"); + emit_diag_for_var_group (tree_static_p, + &inform, + G_("because one or more variables with " + "static storage duration appear " + "in the % directive"), + var_list); }; if (alloc_in == NULL_TREE) { @@ -12496,10 +12556,12 @@ finish_omp_allocate (const location_t loc, const tree var_list, return cached_alloc_type; } auto_diagnostic_group d; - error_at (EXPR_LOCATION (alloc_in), + gcc_rich_location loc (EXPR_LOCATION (alloc_in)); + maybe_add_include_fixit (&loc, "", false); + error_at (&loc, "% clause requires a valid declaration " "of %"); - inform (EXPR_LOCATION (alloc_in), + inform (&loc, "% is defined in header " "%<%>; this is probably fixable by adding " "%<#include %>"); @@ -12642,6 +12704,10 @@ finish_omp_allocate (const location_t loc, const tree var_list, TREE_PURPOSE (node) = error_mark_node; }; + for (tree vn = var_list; vn != NULL_TREE; vn = TREE_CHAIN (vn)) + if (deferred_erroneous_var_nodes.contains (vn)) + finalize_var_node_with_error (vn); + /* Even if there have been errors, save the current state, there might be more to diagnose on a later instantiation. */ if (processing_template_decl) diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-19.c b/gcc/testsuite/c-c++-common/gomp/allocate-19.c index cabd3875d1e..61d1f7ba4b7 100644 --- a/gcc/testsuite/c-c++-common/gomp/allocate-19.c +++ b/gcc/testsuite/c-c++-common/gomp/allocate-19.c @@ -56,19 +56,17 @@ get () return &A1[q]; } -static int invalid1, okay1, invalid2, invalid3; /* { dg-note "'invalid\[123\]' declared here" "" { target c++ xfail c++ } } */ +static int invalid1, okay1, invalid2, invalid3; /* { dg-note "'invalid\[123\]' declared here" "" { target c++ } } */ #pragma omp allocate(invalid1) align(128) allocator(ompx_gnu_pinned_bogus_1) /* { dg-error "'allocator' clause requires a predefined allocator as 'invalid1' is static" "" { target c } } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-2 } */ /* { dg-note "expression evaluates to '9'" "" { target c++ } .-3 } */ #pragma omp allocate(okay1) align(128) allocator(ompx_gnu_pinned_mem_alloc) /* Okay */ #pragma omp allocate(invalid2) align(128) allocator(ompx_gnu_pinned_bogus_2) /* { dg-error "'allocator' clause requires a predefined allocator as 'invalid2' is static" "" { target c } } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-2 } */ /* { dg-note "expression evaluates to '199'" "" { target c++ } .-3 } */ #pragma omp allocate(invalid3) align(128) allocator(ompx_gnu_pinned_bogus_3) /* { dg-error "'allocator' clause requires a predefined allocator as 'invalid3' is static" "" { target c } } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-2 } */ /* { dg-note "expression evaluates to '2001'" "" { target c++ } .-3 } */ - -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } 0 } */ diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-20.c b/gcc/testsuite/c-c++-common/gomp/allocate-20.c new file mode 100644 index 00000000000..604e4847a92 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/allocate-20.c @@ -0,0 +1,343 @@ +#include "allocate-allocator-handle.h" + +#pragma omp allocate() allocator(omp_default_mem_alloc) +/* { dg-error "expected identifier before '\\\)' token" "" { target c } .-1 } */ +/* { dg-error "expected unqualified-id before '\\\)' token" "" { target c++ } .-2 } */ + +/* The following tests are broken up into multiple lines to verify they refer + to the correct use of the variable, this seems to be the easiest way. + C does not currently refer to the correct line. */ +int g; +/* { dg-error "'g' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ +#pragma omp allocate(\ +g,\ +g,\ +g,\ +g,\ +g) allocator(omp_default_mem_alloc) +/* { dg-note "appeared first here" "" { target c++ } .-5 } */ +/* { dg-error "'g' already appeared as list item in this directive" "" { target c++ } .-5 } */ +/* { dg-error "'g' already appeared as list item in this directive" "" { target c++ } .-5 } */ +/* { dg-error "'g' already appeared as list item in this directive" "" { target c++ } .-5 } */ +/* { dg-error "'g' already appeared as list item in this directive" "" { target c++ } .-5 } */ + +int g0_0; +int g0_1; +/* { dg-error "'g0_0' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ +#pragma omp allocate(\ +g0_0,\ +g0_1,\ +g0_0,\ +g0_0) allocator(omp_default_mem_alloc) +/* { dg-note "appeared first here" "" { target c++ } .-4 } */ +/* { dg-error "'g0_0' already appeared as list item in this directive" "" { target c++ } .-3 } */ +/* { dg-error "'g0_0' already appeared as list item in this directive" "" { target c++ } .-3 } */ + +int g1_0; +int g1_1; +/* { dg-error "'g1_0' already appeared as list item in an 'allocate' directive" "" { target c } .+2 } */ +/* { dg-error "'g1_1' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ +#pragma omp allocate(\ +g1_1,\ +g1_0,\ +g1_1,\ +g1_0,\ +g1_0,\ +g1_1) allocator(omp_default_mem_alloc) +/* { dg-note "appeared first here" "" { target c++ } .-6 } */ +/* { dg-note "appeared first here" "" { target c++ } .-6 } */ +/* { dg-error "'g1_1' already appeared as list item in this directive" "" { target c++ } .-6 } */ +/* { dg-error "'g1_0' already appeared as list item in this directive" "" { target c++ } .-6 } */ +/* { dg-error "'g1_0' already appeared as list item in this directive" "" { target c++ } .-6 } */ +/* { dg-error "'g1_1' already appeared as list item in this directive" "" { target c++ } .-6 } */ + +void f() +{ + int v; + /* { dg-error "'v' already appeared as list item in an 'allocate' directive" "" { target c} .+1 } */ + #pragma omp allocate(\ + v,\ + v,\ + v,\ + v,\ + v) + /* { dg-note "appeared first here" "" { target c++ } .-5 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-5 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-5 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-5 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-5 } */ + + int v0_0; + int v0_1; + /* { dg-error "'v0_0' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v0_0,\ + v0_1,\ + v0_0,\ + v0_0) + /* { dg-note "appeared first here" "" { target c++ } .-4 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-3 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-3 } */ + + int v1_0; + int v1_1; + /* { dg-error "'v1_0' already appeared as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v1_1' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v1_1,\ + v1_0,\ + v1_1,\ + v1_0,\ + v1_0,\ + v1_1) + /* { dg-note "appeared first here" "" { target c++ } .-6 } */ + /* { dg-note "appeared first here" "" { target c++ } .-6 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-6 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-6 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-6 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-6 } */ +} + +void f_with_parm(int p) /* { dg-note "parameter 'p' declared here" "" { target c++ } } */ +{ + #pragma omp allocate(p) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + p,\ + p,\ + p) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-3 } */ + /* { dg-note "appeared first here" "" { target c++ } .-4 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-4 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-4 } */ + + int v; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v,\ + p,\ + v,\ + v,\ + p,\ + v,\ + v) + /* { dg-note "appeared first here" "" { target c++ } .-7 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-7 } */ + /* { dg-note "appeared first here" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + + int v0_0; + int v0_1; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v0_0' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + p,\ + v0_0,\ + v0_1,\ + v0_0,\ + v0_0) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-5 } */ + /* { dg-note "appeared first here" "" { target c++ } .-5 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-4 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-4 } */ + + int v1_0; + int v1_1; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+3 } */ + /* { dg-error "'v1_0' already appeared as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v1_1' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v1_1,\ + p,\ + v1_0,\ + v1_1,\ + v1_0,\ + p,\ + v1_0,\ + v1_1,\ + p) + /* { dg-note "appeared first here" "" { target c++ } .-9 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-9 } */ + /* { dg-note "appeared first here" "" { target c++ } .-10 } */ + /* { dg-note "appeared first here" "" { target c++ } .-10 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-10 } */ +} + +/* Valid var used in allocator clause diagnostics. + (No diagnostic should be emitted related to 'alloc') */ + +void f_with_parm_and_allocator0(int p) /* { dg-note "parameter 'p' declared here" "" { target c++ } } */ +{ + omp_allocator_handle_t alloc = omp_default_mem_alloc; + #pragma omp allocate(p) allocator(alloc) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + p,\ + p,\ + p) allocator(alloc) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-3 } */ + /* { dg-note "appeared first here" "" { target c++ } .-4 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-4 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-4 } */ + + int v; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v,\ + p,\ + v,\ + v,\ + p,\ + v,\ + v) allocator(alloc) + /* { dg-note "appeared first here" "" { target c++ } .-7 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-7 } */ + /* { dg-note "appeared first here" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + /* { dg-error "'v' already appeared as list item in this directive" "" { target c++ } .-8 } */ + + int v0_0; + int v0_1; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v0_0' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + p,\ + v0_0,\ + v0_1,\ + v0_0,\ + v0_0) allocator(alloc) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-5 } */ + /* { dg-note "appeared first here" "" { target c++ } .-5 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-4 } */ + /* { dg-error "'v0_0' already appeared as list item in this directive" "" { target c++ } .-4 } */ + + int v1_0; + int v1_1; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+3 } */ + /* { dg-error "'v1_0' already appeared as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "'v1_1' already appeared as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v1_1,\ + p,\ + v1_0,\ + v1_1,\ + v1_0,\ + p,\ + v1_0,\ + v1_1,\ + p) allocator(alloc) + /* { dg-note "appeared first here" "" { target c++ } .-9 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-9 } */ + /* { dg-note "appeared first here" "" { target c++ } .-10 } */ + /* { dg-note "appeared first here" "" { target c++ } .-10 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_0' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'v1_1' already appeared as list item in this directive" "" { target c++ } .-10 } */ + /* { dg-error "'p' already appeared as list item in this directive" "" { target c++ } .-10 } */ +} + +/* Var used in allocator clause diagnostics. Tests that invalid vars passed + into the allocate directive are not considered and bogus/repeat diagnostics + are not emitted. */ + +void f_with_parm_and_allocator1(int p) /* { dg-note "parameter 'p' declared here" "" { target c++ } } */ +{ + int v0; /* { dg-note "to be allocated variable declared here" "" { xfail c++ } } */ + omp_allocator_handle_t alloc0 = omp_default_mem_alloc; /* { dg-note "declared here" "" { xfail c++ } } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+2 } */ + /* { dg-error "variable 'alloc0' used in the 'allocator' clause must be declared before 'v0'" "" { target c } .+1 } */ + #pragma omp allocate(\ + p,\ + v0)\ + allocator(alloc0) + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-3 } */ + /* { dg-error "variable 'alloc0' used in the 'allocator' clause must be declared before 'v0'" "" { target c++ xfail c++ } .-2 } */ + + int v1; /* { dg-note "declared here" } */ + { + omp_allocator_handle_t alloc1 = omp_default_mem_alloc; + int v2; + /* { dg-error "'allocate' directive must be in the same scope as 'v1'" "" { target c } .+1 } */ + #pragma omp allocate(\ + v1,\ + v2\ + ) allocator(alloc1) + /* { dg-error "'allocate' directive must be in the same scope as 'v1'" "" { target c++ } .-3 } */ + } + { + int v3; /* { dg-note "to be allocated variable declared here" "" { xfail c++ } } */ + omp_allocator_handle_t alloc2 = omp_default_mem_alloc; /* { dg-note "declared here" "" { xfail c++ } } */ + /* { dg-error "variable 'alloc2' used in the 'allocator' clause must be declared before 'v3'" "" { target c } .+2 } */ + /* { dg-error "'allocate' directive must be in the same scope as 'v1'" "" { target c } .+1 } */ + #pragma omp allocate(\ + v1,\ + v3\ + ) allocator(alloc2) + /* { dg-error "'allocate' directive must be in the same scope as 'v1'" "" { target c++ } .-3 } */ + /* { dg-error "variable 'alloc2' used in the 'allocator' clause must be declared before 'v3'" "" { target c++ xfail c++ } .-2 } */ + } +} + +/* First argument valid. + These cases could still be fleshed out a bit more, there was original a typo + that caused diagnostics to always refer to the first argument of the + directive in the C++ front end, these tests are for that case. */ + +void first_valid0() +{ + int a; /* { dg-note "declared here" } */ + { + int v; + /* { dg-error "'allocate' directive must be in the same scope as 'a'" "" { target c } .+1 } */ + #pragma omp allocate(\ + v,\ + a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" "" { target c++ } } */ + } +} + +void first_valid1(int p) /* { dg-note "parameter 'p' declared here" "" { target c++ } } */ +{ + int v; + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v,\ + p) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } } */ +} + +void first_valid2(int p) /* { dg-note "parameter 'p' declared here" "" { target c++ } } */ +{ + int a; /* { dg-note "declared here" } */ + { + int v; + /* { dg-error "'allocate' directive must be in the same scope as 'a'" "" { target c } .+2 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c } .+1 } */ + #pragma omp allocate(\ + v,\ + a,\ + p) + /* { dg-error "'allocate' directive must be in the same scope as 'a'" "" { target c++ } .-2 } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target c++ } .-2 } */ + } +} + +/* Missing cases that contain undeclared variables. */ diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-9.c b/gcc/testsuite/c-c++-common/gomp/allocate-9.c index 52bae8c9a6a..872f7956cdd 100644 --- a/gcc/testsuite/c-c++-common/gomp/allocate-9.c +++ b/gcc/testsuite/c-c++-common/gomp/allocate-9.c @@ -5,7 +5,7 @@ static int A2[5] = {1,2,3,4,5}; static int A3[5] = {1,2,3,4,5}; static int A4[5] = {1,2,3,4,5}; /* { dg-line A4_decl } */ static int A5[5] = {1,2,3,4,5}; /* { dg-line A5_decl } */ -int B, C, C2, D; /* { dg-note "declared here" "" { xfail c++ } } */ +int B, C, C2, D; /* { dg-note "declared here" } */ /* If the following fails because of added predefined allocators, please update - include/gomp-constants.h's GOMP_OMP_PREDEF_ALLOC_MAX or GOMP_OMPX_PREDEF_ALLOC_MAX @@ -18,9 +18,9 @@ int B, C, C2, D; /* { dg-note "declared here" "" { xfail c++ } } */ #pragma omp allocate(A1) align(32) allocator((omp_allocator_handle_t) 9) /* { dg-error "'allocator' clause requires a predefined allocator as 'A1' is static" "" { target c } .-1 } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-2 } */ -/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-3 } */ +/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-3 } */ /* { dg-message "expression evaluates to '9'" "" { target c++ } .-4 } */ -/* { dg-note "'A1' declared here" "" { target c++ xfail c++ } A_decl } */ +/* { dg-note "'A1' declared here" "" { target c++ } A_decl } */ // typo in allocator name: #pragma omp allocate(A2) allocator(omp_low_latency_mem_alloc) /* { dg-error "'omp_low_latency_mem_alloc' undeclared here \\(not in a function\\); did you mean 'omp_low_lat_mem_alloc'\\?" "" { target c } .-1 } */ @@ -35,8 +35,8 @@ int B, C, C2, D; /* { dg-note "declared here" "" { xfail c++ } } */ #pragma omp allocate(A4) align(32) /* { dg-error "'allocator' clause required for static variable 'A4'" "" { target c } .-1 } */ /* { dg-error "'allocator' clause must be specified" "" { target c++ } .-2 } */ -/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-3 } */ -/* { dg-note "'A4' declared here" "" { target c++ xfail c++ } A4_decl } */ +/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-3 } */ +/* { dg-note "'A4' declared here" "" { target c++ } A4_decl } */ /* "expression in the clause must be a constant expression that evaluates to one of the predefined memory allocator values -> omp_low_lat_mem_alloc" */ @@ -49,9 +49,9 @@ int B, C, C2, D; /* { dg-note "declared here" "" { xfail c++ } } */ #pragma omp allocate(A5) align(32) allocator(omp_null_allocator) /* { dg-error "'allocator' clause requires a predefined allocator as 'A5' is static" "" { target c } .-1 } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-2 } */ -/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-3 } */ +/* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-3 } */ /* { dg-message "expression evaluates to '0'" "" { target c++ } .-4 } */ -/* { dg-note "'A5' declared here" "" { target c++ xfail c++ } A5_decl } */ +/* { dg-note "'A5' declared here" "" { target c++ } A5_decl } */ #pragma omp allocate(C2) align(32) allocator(omp_large_cap_mem_alloc) @@ -59,7 +59,7 @@ int B, C, C2, D; /* { dg-note "declared here" "" { xfail c++ } } */ // allocate directive in same TU int f() { - #pragma omp allocate(D) align(32) allocator(omp_large_cap_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'D'" "" { xfail c++ } } */ + #pragma omp allocate(D) align(32) allocator(omp_large_cap_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'D'" } */ return A1[0]; } @@ -71,29 +71,29 @@ int g() /* { dg-note "'a2' previously appeared here" "" { target c++ } .-2 } */ { int c2=3; - #pragma omp allocate(c2, b2) /* { dg-error "'allocate' directive must be in the same scope as 'b2'" "" { xfail c++ } } */ -/* { dg-note "declared here" "" { target *-*-* xfail c++ } g_a2_b2_decl } */ + #pragma omp allocate(c2, b2) /* { dg-error "'allocate' directive must be in the same scope as 'b2'" } */ +/* { dg-note "declared here" "" { target *-*-* } g_a2_b2_decl } */ return c2+a2+b2; } } int h(int q) { - #pragma omp allocate(q) /* { dg-error "function parameter 'q' may not appear as list item in an 'allocate' directive" "" { xfail c++ } } */ -/* { dg-note "parameter 'q' declared here" "" { target c++ xfail c++ } .-3 } */ + #pragma omp allocate(q) /* { dg-error "function parameter 'q' may not appear as list item in an 'allocate' directive" } */ +/* { dg-note "parameter 'q' declared here" "" { target c++ } .-3 } */ return q; } int k () { - static int var3 = 8; /* { dg-note "'var3' declared here" "" { target c++ xfail c++ } } */ + static int var3 = 8; /* { dg-note "'var3' declared here" "" { target c++ } } */ #pragma omp allocate(var3) allocator((omp_allocator_handle_t)-1L) /* { dg-error "'allocator' clause requires a predefined allocator as 'var3' is static" "" { target c } .-1 } */ /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target c++ } .-2 } */ - /* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ xfail c++ } .-3 } */ + /* { dg-message "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target c++ } .-3 } */ /* { dg-message "expression evaluates to '\\d+'" "" { target c++ } .-4 } */ return var3; } -/* { dg-bogus "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail c++ } 0 } */ +/* { dg-bogus "because one or more variables with static storage duration appear in the 'allocate' directive" 0 } */ diff --git a/gcc/testsuite/g++.dg/gomp/allocate-14.C b/gcc/testsuite/g++.dg/gomp/allocate-14.C new file mode 100644 index 00000000000..d40288d957d --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-14.C @@ -0,0 +1,1042 @@ +#include "allocate-allocator-handle.h" + +/* Diagnostics for invalid cases, including a number of negative cases that + should not be diagnosed. */ + +/**************************************************** + * Reference variable used in an allocate directive * + ****************************************************/ + +void ref_var() +{ + int a = 42; + int& ref = a; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void ref_var_templ_not_instantiated() +{ + int a = 42; + int& ref = a; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void dependent_ref_var_templ_not_instantiated() +{ + T a = 42; + T& t = a; /* { dg-note "'t' declared here" } */ + #pragma omp allocate(t) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void dependent_var_templ_not_instantiated() +{ + T t = 42; + #pragma omp allocate(t) +} + +template +void dependent_var_templ_0() +{ + T t = 42; + #pragma omp allocate(t) +} + +template +void dependent_var_templ_1() +{ + T t = 42; /* { dg-note "'t' declared here" } */ + #pragma omp allocate(t) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void dependent_var_templ_2() +{ + int a; + T t = a; /* { dg-note "'t' declared here" } */ + #pragma omp allocate(t) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +void instantiate_var_templ() +{ + dependent_var_templ_0(); /* { dg-bogus "required from here" } */ + dependent_var_templ_1(); /* { dg-bogus "required from here" } */ + dependent_var_templ_1(); /* { dg-message "required from here" } */ + dependent_var_templ_2(); /* { dg-bogus "required from here" } */ + dependent_var_templ_2(); /* { dg-message "required from here" } */ + dependent_var_templ_2(); /* { dg-message "required from here" } */ +} + + +/**************************** + * Invalid allocator clause * + ****************************/ + +template +void nttp_allocator() +{ + int a; + #pragma omp allocate(a) allocator(Alloc) +} + +template +void nttp_allocator_uninstantiated() +{ + int a; + #pragma omp allocate(a) allocator(Alloc) +} + +template +void nttp_wrong_type_allocator_uninstantiated() +{ + int a; + #pragma omp allocate(a) allocator(Alloc) /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { xfail *-*-* } } */ +} + +template +void nttp_dependent_type_allocator() +{ + int a; + #pragma omp allocate(a) allocator(Alloc) /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" } */ +} + +template +void nttp_dependent_type_allocator_uninstantiated() +{ + int a; + #pragma omp allocate(a) allocator(Alloc) +} + +void instantiate_nttp_allocator() +{ + nttp_allocator(); /* { dg-bogus "required from here" } */ + nttp_dependent_type_allocator(); /* { dg-bogus "required from here" } */ + nttp_dependent_type_allocator(); /* { dg-message "required from here" } */ +} + +template +void nttp_allocator_static() +{ + static int a; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-1 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ + /* { dg-note "expression evaluates to '1024'" "" { xfail *-*-* } .-3 }*/ +} + +template +void nttp_allocator_uninstantiated_static() +{ + static int a; + #pragma omp allocate(a) allocator(Alloc) +} + +template +void nttp_wrong_type_allocator_uninstantiated_static() +{ + static int a; + #pragma omp allocate(a) allocator(Alloc) /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { xfail *-*-* } } */ +} + +template +void nttp_dependent_type_allocator_static_0() +{ + static int a; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-1 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ + /* { dg-note "expression evaluates to '1024'" "" { xfail *-*-* } .-3 }*/ +} + +template +void nttp_dependent_type_allocator_static_1() +{ + static int a; + #pragma omp allocate(a) allocator(Alloc) /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" } */ +} + +template +void nttp_dependent_type_allocator_uninstantiated_static() +{ + static int a; + #pragma omp allocate(a) allocator(Alloc) +} + +#define DEFINITELY_NOT_PREDEFINED static_cast(1024) + +void instantiate_nttp_allocator_static() +{ + nttp_allocator_static(); /* { dg-bogus "required from here" } */ + nttp_allocator_static(); /* { dg-message "required from here" } */ + nttp_dependent_type_allocator_static_0(); /* { dg-bogus "required from here" } */ + nttp_dependent_type_allocator_static_0(); /* { dg-message "required from here" } */ + nttp_dependent_type_allocator_static_1(); /* { dg-message "required from here" } */ +} + +#undef DEFINITELY_NOT_PREDEFINED + + +template +void templ_allocator_param_0(AllocT alloc) +{ + int a; + #pragma omp allocate(a) allocator(alloc) +} + +template +void templ_allocator_param_1(AllocT alloc) +{ + int a; + #pragma omp allocate(a) allocator(alloc) /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" } */ +} + +template +void templ_allocator_param_uninstantiated(AllocT alloc) +{ + int a; + #pragma omp allocate(a) allocator(alloc) +} + +void instantiate_templ_allocator_param() +{ + templ_allocator_param_0(omp_default_mem_alloc); /* { dg-bogus "required from here" } */ + templ_allocator_param_1(omp_default_mem_alloc); /* { dg-bogus "required from here" } */ + templ_allocator_param_1(0); /* { dg-message "required from here" } */ +} + + +template +void missing_allocator_clause_uninstantiated() +{ + static int a; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) + /* { dg-error "'allocator' clause must be specified" "" { target *-*-* } .-1 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 }*/ +} + +/* Cases that are never constant omp_allocator_handle_t expressions (and are required to be) */ + +template +void allocator_param_static_uninstantiated(omp_allocator_handle_t alloc) +{ + static int a; /* { dg-note "'a' declared here" "" { xfail *-*-* } } */ + #pragma omp allocate(a) allocator(alloc) + /* { dg-error "'alloc' is not a constant expression" "" { xfail *-*-* } .-1 }*/ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-3 }*/ +} + +template +void allocator_var_static_uninstantiated() +{ + omp_allocator_handle_t alloc = omp_default_mem_alloc; /* { dg-note "'omp_allocator_handle_t alloc' is not const" "" { xfail *-*-* } } */ + static int a; /* { dg-note "'a' declared here" "" { xfail *-*-* } } */ + #pragma omp allocate(a) allocator(alloc) + /* { dg-error "the value of 'alloc' is not usable in a constant expression" "" { xfail *-*-* } .-1 }*/ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-3 }*/ +} + +/* While weird, there are inputs for AllocT that are well-formed here, + therefore these cases can not be diagnosed until instantiation. */ + +template +void templ_allocator_param_static_uninstantiated(AllocT alloc) +{ + static int a; + #pragma omp allocate(a) allocator(alloc) /* { dg-bogus "" } */ +} + +template +void templ_allocator_var_static_uninstantiated() +{ + AllocT alloc = omp_default_mem_alloc; + static int a; + #pragma omp allocate(a) allocator(alloc) /* { dg-bogus "" } */ +} + + +/************************ + * Invalid align clause * + ************************/ + +template +void nttp_align() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ +} + +template +void nttp_align_uninstantiated() +{ + int a; + #pragma omp allocate(a) align(Align) +} + +template +void nttp_wrong_type_align_uninstantiated() +{ + int a; + #pragma omp allocate(a) align(Align) + /* { dg-error "could not convert 'Align' from '\[^\n\r\]+' to '\[^\n\r\]+'" "" { xfail *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ +} + +template +void nttp_dependent_type_align_0() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ +} + +template +void nttp_dependent_type_align_1() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ +} + +template +void nttp_dependent_type_align_uninstantiated() +{ + int a; + #pragma omp allocate(a) align(Align) +} + +void instantiate_nttp_align() +{ + nttp_align<32>(); + nttp_align<42>(); /* { dg-message "required from here" } */ + nttp_dependent_type_align_0(); /* { dg-bogus "required from here" } */ + nttp_dependent_type_align_0(); /* { dg-message "required from here" } */ + nttp_dependent_type_align_1(); /* { dg-bogus "required from here" } */ + /* We just need any non integer NTTP that is valid in c++98, a fptr fits the bill. */ + nttp_dependent_type_align_1(); /* { dg-message "required from here" } */ + /* { dg-error "could not convert 'instantiate_nttp_align' from 'void \\(\\*\\)\\(\\)' to '\[^\n\r\]+'" "Bugged location, see comment" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "Bugged location, see comment" { target *-*-* } .-2 } */ + /* { dg-error "conversion from 'void \\(\\*\\)\\(\\)' to '\[^\n\r\]+' in a converted constant expression" "Bugged location, see comment" { target *-*-* } .-3 } */ + /* I believe this diagnostic is bugged, it should refer to where the + expression is used, not where it originated from. This isn't a bug for + this feature though so I'm making the test case work around it, + when this bug is fixed this test case, and the xfail in the test case in + nttp_dependent_type_align_1 can be remove. */ +} + +/* Cases that are never constant integer expressions (always required for the align clause.) */ + +template +void align_param_uninstantiated(int align) +{ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "'align' is not a constant expression" "" { xfail *-*-* } .-1 }*/ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ +} + +template +void align_var_uninstantiated() +{ + int align = 32; /* { dg-note "'int align' is not const" "" { xfail *-*-* } } */ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "the value of 'align' is not usable in a constant expression" "" { xfail *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ +} + +/* While weird, there are inputs for AlignT that are well-formed here, + therefore these cases can not be diagnosed until instantiation. */ + +template +void templ_align_param_uninstantiated(AlignT align) +{ + int a; + #pragma omp allocate(a) align(align) /* { dg-bogus "" } */ +} + +template +void templ_align_var_uninstantiated() +{ + AlignT align = 32; + int a; + #pragma omp allocate(a) align(align) /* { dg-bogus "" } */ +} + + + +/*************** + * Mixed cases * + ***************/ + +template +void all_dependent_uninstantiated() +{ + int b = 42; + Var a = b; + #pragma omp allocate(a) allocator(Alloc) align(Align) +} + +template +void all_dependent_valid() +{ + int b = 42; + Var a = b; + #pragma omp allocate(a) allocator(Alloc) align(Align) +} + +template +void all_dependent_0() +{ + int b = 42; + Var a = b; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ +} + +template +void all_dependent_1() +{ + int b = 42; + Var a = b; + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */ +} + +template +void all_dependent_2() +{ + int b = 42; + Var a = b; + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} + +template +void all_dependent_3() +{ + int b = 42; + Var a = b; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-2 } */ +} + +template +void all_dependent_4() +{ + int b = 42; + Var a = b; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ +} + +template +void all_dependent_5() +{ + int b = 42; + Var a = b; + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ +} + +template +void all_dependent_6() +{ + int b = 42; + Var a = b; /* { dg-note "'a' declared here" } */ + #pragma omp allocate(a) allocator(Alloc) align(Align) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-2 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-3 } */ +} + +void instantiate_all_dependent() +{ + all_dependent_valid(); + /* Don't test the type mismatch for the align clause here, it's diagnostic + location is buggy, and the error message is the same. We just really want + to test that we aren't emitting bogus errors when multiple things are + dependent, so it's unnecessary to test that case again. */ + all_dependent_0(); /* { dg-bogus "required from here" } */ + all_dependent_0(); /* { dg-message "required from here" } */ + + all_dependent_1(); /* { dg-bogus "required from here" } */ + all_dependent_1(); /* { dg-message "required from here" } */ + + all_dependent_2(); /* { dg-bogus "required from here" } */ + all_dependent_2(); /* { dg-message "required from here" } */ + + all_dependent_3(); /* { dg-bogus "required from here" } */ + all_dependent_3(); /* { dg-message "required from here" } */ + + all_dependent_4(); /* { dg-bogus "required from here" } */ + all_dependent_4(); /* { dg-message "required from here" } */ + + all_dependent_5(); /* { dg-bogus "required from here" } */ + all_dependent_5(); /* { dg-message "required from here" } */ + + all_dependent_6(); /* { dg-bogus "required from here" } */ + all_dependent_6(); /* { dg-message "required from here" } */ +} + +/* We are missing combined cases for static var used in the allocate directive, + but it should be fine, the combined cases immediately above are probably + overkill as it is. */ + + +/****************************** + * Invalid allocate directive * + ******************************/ + +/* We are only testing that we gracefully handle an empty list of vars. */ + +void no_parens() +{ + #pragma omp allocate /* { dg-error "expected '\\\(' before end of line" } */ +} + +template +void templ_no_parens() +{ + #pragma omp allocate /* { dg-error "expected '\\\(' before end of line" } */ +} +template void templ_no_parens(); + +template +void templ_no_parens_uninstantiated() +{ + #pragma omp allocate /* { dg-error "expected '\\\(' before end of line" } */ +} + +void no_vars() +{ + #pragma omp allocate() /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} + +template +void templ_no_vars() +{ + #pragma omp allocate() /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} +template void templ_no_vars(); + +template +void templ_no_vars_uninstantiated() +{ + #pragma omp allocate() /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} + +/* We can't diagnose anything about the allocator clause if we have no + variables, but we do need to make sure we don't crash. */ + +void no_vars_allocator() +{ + #pragma omp allocate() allocator(omp_default_mem_alloc) /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} + +template +void templ_no_vars_allocator() +{ + #pragma omp allocate() allocator(omp_default_mem_alloc) /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} +template void templ_no_vars_allocator(); + +template +void templ_no_vars_allocator_uninstantiated() +{ + #pragma omp allocate() allocator(omp_default_mem_alloc) /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} + +/* We can still diagnose errors about the align clause without any vars. */ + +void no_vars_invalid_align() +{ + #pragma omp allocate() align(42) /* { dg-error "expected unqualified-id before '\\\)' token" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ +} + +template +void templ_no_vars_invalid_align() +{ + #pragma omp allocate() align(42) /* { dg-error "expected unqualified-id before '\\\)' token" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ +} +template void templ_no_vars_invalid_align(); + +template +void templ_no_vars_invalid_align_uninstantiated() +{ + #pragma omp allocate() align(42) /* { dg-error "expected unqualified-id before '\\\)' token" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} + +template +void templ_no_vars_dep_align() +{ + #pragma omp allocate() align(Align) /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} +template void templ_no_vars_dep_align<32>(); + +template +void templ_no_vars_dep_align_invalid() +{ + #pragma omp allocate() align(Align) /* { dg-error "expected unqualified-id before '\\\)' token" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} +template void templ_no_vars_dep_align_invalid<42>(); + +template +void templ_no_vars_dep_align_uninstantiated() +{ + #pragma omp allocate() align(Align) /* { dg-error "expected unqualified-id before '\\\)' token" } */ +} + +/********************************* + * All vars in directive invalid * + *********************************/ + +void invalid_vars_param(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} + +template +void templ_invalid_vars_param(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} +template void templ_invalid_vars_param(int); + +template +void templ_invalid_vars_param_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} + +void invalid_vars_out_of_scope() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} + +template +void templ_invalid_vars_out_of_scope() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} +template void templ_invalid_vars_out_of_scope(); + +template +void templ_invalid_vars_out_of_scope_uninstantiated() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} + +void invalid_vars_out_of_scope_and_param(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} + +template +void templ_invalid_vars_out_of_scope_and_param(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} +template void templ_invalid_vars_out_of_scope_and_param(int); + +template +void templ_invalid_vars_out_of_scope_and_param_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} + +/* Same as above, we can't diagnose anything about the allocator clause if we + have no variables, but we do need to make sure we don't crash. */ + +void invalid_vars_param_allocator(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) allocator(omp_default_mem_alloc) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} + +template +void templ_invalid_vars_param_allocator(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) allocator(omp_default_mem_alloc) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} +template void templ_invalid_vars_param_allocator(int); + +template +void templ_invalid_vars_param_allocator_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) allocator(omp_default_mem_alloc) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} + +void invalid_vars_out_of_scope_allocator() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} + +template +void templ_invalid_vars_out_of_scope_allocator() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} +template void templ_invalid_vars_out_of_scope_allocator(); + +template +void templ_invalid_vars_out_of_scope_allocator_uninstantiated() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} + +void invalid_vars_out_of_scope_and_param_allocator(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} + +template +void templ_invalid_vars_out_of_scope_and_param_allocator(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} +template void templ_invalid_vars_out_of_scope_and_param_allocator(int); + +template +void templ_invalid_vars_out_of_scope_and_param_allocator_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) allocator(omp_default_mem_alloc) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} + +/* Invalid vars with non-dependent invalid align */ + +void invalid_vars_param_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(42) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ +} + +template +void templ_invalid_vars_param_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(42) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ +} +template void templ_invalid_vars_param_align_invalid(int); + +template +void templ_invalid_vars_param_align_invalid_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(42) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} + +void invalid_vars_out_of_scope_align_invalid() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ + } +} + +template +void templ_invalid_vars_out_of_scope_align_invalid() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */ + } +} +template void templ_invalid_vars_out_of_scope_align_invalid(); + +template +void templ_invalid_vars_out_of_scope_align_invalid_uninstantiated() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + } +} + +void invalid_vars_out_of_scope_and_param_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */ + } +} + +template +void templ_invalid_vars_out_of_scope_and_param_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */ + } +} +template void templ_invalid_vars_out_of_scope_and_param_align_invalid(int); + +template +void templ_invalid_vars_out_of_scope_and_param_align_invalid_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(42) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ + } +} + + +/* Param (dependent align) */ + +template +void templ_invalid_vars_param_dependent_align_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(Align) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} + +template +void templ_invalid_vars_param_dependent_align(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(Align) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ +} +template void templ_invalid_vars_param_dependent_align<32>(int); + +template +void templ_invalid_vars_param_dependent_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + #pragma omp allocate(p) align(Align) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} +template void templ_invalid_vars_param_dependent_align_invalid<42>(int); + + +/* Out of scope (dependent align) */ + +template +void templ_invalid_vars_out_of_scope_dependent_align_uninstantiated() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} + +template +void templ_invalid_vars_out_of_scope_dependent_align() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + } +} +template void templ_invalid_vars_out_of_scope_dependent_align<32>(); + +template +void templ_invalid_vars_out_of_scope_dependent_align_invalid() +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + } +} +template void templ_invalid_vars_out_of_scope_dependent_align_invalid<42>(); + + +/* Param and out of scope (dependent align) */ + +template +void templ_invalid_vars_out_of_scope_and_param_dependent_align_uninstantiated(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} + +template +void templ_invalid_vars_out_of_scope_and_param_dependent_align(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + } +} +template void templ_invalid_vars_out_of_scope_and_param_dependent_align<32>(int); + +template +void templ_invalid_vars_out_of_scope_and_param_dependent_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */ +{ + int a; /* { dg-note "declared here" } */ + { + #pragma omp allocate(a, p) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ + } +} +template void templ_invalid_vars_out_of_scope_and_param_dependent_align_invalid<42>(int); + + + +/**************************************************** + * uses of var in multiple directives in a template * + ****************************************************/ + +/* We are missing a lot of cases here but testing all of them shouldn't be + necessary. Uses of variables in multiple directives are diagnosed during + parsing so templates shouldn't change anything. This is of course as long + as we don't change that, and these cases should be enough to deter anyone + from doing so. */ + +template +void multiple_uses_non_dependent_directive_uninstantiated() +{ + int a; + #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} + +template +void multiple_uses_non_dependent_directive() +{ + int a; + #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} +template void multiple_uses_non_dependent_directive(); + + +template +void multiple_uses_dep_directive_before_align_uninstantiated() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} + +template +void multiple_uses_dep_directive_before_valid_align() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} +template void multiple_uses_dep_directive_before_valid_align<32>(); + +template +void multiple_uses_dep_directive_before_invalid_align() +{ + int a; + #pragma omp allocate(a) align(Align) /* { dg-note "'a' previously appeared here" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} +template void multiple_uses_dep_directive_before_invalid_align<42>(); + + +/* Dependent directive after the independent one. */ + +template +void multiple_uses_dep_directive_after_align_uninstantiated() +{ + int a; + #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) align(Align) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} + +template +void multiple_uses_dep_directive_after_valid_align() +{ + int a; + #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) align(Align) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ +} +template void multiple_uses_dep_directive_after_valid_align<32>(); + +template +void multiple_uses_dep_directive_after_invalid_align() +{ + int a; + #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */ + #pragma omp allocate(a) align(Align) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ +} +template void multiple_uses_dep_directive_after_invalid_align<42>(); + +/* These are fixed by the later location wrapping patch. */ +/* { dg-bogus "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } 0 } */ +/* { dg-bogus "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } 0 } */ +/* { dg-bogus "expression evaluates to '1024'" "" { xfail *-*-* } 0 } */ diff --git a/gcc/testsuite/g++.dg/gomp/allocate-15.C b/gcc/testsuite/g++.dg/gomp/allocate-15.C new file mode 100644 index 00000000000..605e10e477f --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-15.C @@ -0,0 +1,50 @@ +/* { dg-do compile { target c++11 } } */ + +/* Diagnostics for rvalue reference vars used in an allocate directive. */ + +void rref_var() +{ + int&& ref = 42; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +void const_rref_var() +{ + int const&& ref = 42; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void rref_var_templ_not_instantiated() +{ + int&& ref = 42; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void const_rref_var_templ_not_instantiated() +{ + int const&& ref = 42; /* { dg-note "'ref' declared here" } */ + #pragma omp allocate(ref) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void dependent_rref_var_templ_not_instantiated() +{ + T&& t = 42; /* { dg-note "'t' declared here" } */ + #pragma omp allocate(t) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} + +template +void dependent_var_templ() +{ + T t = 42; /* { dg-note "'t' declared here" } */ + #pragma omp allocate(t) /* { dg-error "variables with reference type may not appear in an 'allocate' directive" } */ +} +void instantiate_var_templ() +{ + dependent_var_templ(); /* { dg-bogus "required from here" } */ + dependent_var_templ(); /* { dg-message "required from here" } */ + dependent_var_templ(); /* { dg-message "required from here" } */ +} + diff --git a/gcc/testsuite/g++.dg/gomp/allocate-16.C b/gcc/testsuite/g++.dg/gomp/allocate-16.C new file mode 100644 index 00000000000..7258d8c1c3c --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-16.C @@ -0,0 +1,232 @@ +/* { dg-do compile { target c++11 } } */ +/* { dg-ice "" { c++17 } } */ +#include "allocate-allocator-handle.h" + +/* Incorrect use of lambda captures in a directive or clause. + There are a few cases in here that are impacted by the bug with implicit + constexpr functions. */ + +/* These errors (specifically in capture_used_in_directive) really could be better. */ + +void capture_used_in_directive() +{ + int a = 42; + auto cl = [a](){ /* { dg-note "declared here" } */ + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + }; +} + +template +void capture_used_in_directive_templ_uninstantiated() +{ + int a = 42; + auto cl = [a](){ /* { dg-note "declared here" } */ + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + }; +} + +template +void capture_used_in_directive_templ() +{ + int a = 42; + auto cl = [a](){ /* { dg-note "declared here" } */ + #pragma omp allocate(a) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */ + }; +} + +void instantiate_capture_used_in_directive() +{ + capture_used_in_directive_templ(); +} + + + +void capture_used_in_allocator_clause_static_var() +{ + omp_allocator_handle_t alloc = omp_default_mem_alloc; /* { dg-note "'omp_allocator_handle_t alloc' is not const" } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-note "'a' declared here" } */ + int b = 42; /* { dg-bogus "'b' declared here" } */ + static int c = 42; /* { dg-note "'c' declared here" } */ + int d = 42; /* { dg-bogus "'d' declared here" } */ + #pragma omp allocate(a, b, c, d) allocator(alloc) + /* { dg-error "the value of 'alloc' is not usable in a constant expression" "" { target *-*-* } .-1 } */ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-3 } */ + }; +} + +template +void capture_used_in_allocator_clause_static_var_templ_uninstantiated() +{ + omp_allocator_handle_t alloc = omp_default_mem_alloc; /* { dg-note "'omp_allocator_handle_t alloc' is not const" "" { xfail *-*-* } } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-note "'a' declared here" "" { xfail *-*-* } } */ + int b = 42; /* { dg-bogus "'b' declared here" } */ + static int c = 42; /* { dg-note "'c' declared here" "" { xfail *-*-* } } */ + int d = 42; /* { dg-bogus "'d' declared here" } */ + #pragma omp allocate(a, b, c, d) allocator(alloc) + /* { dg-error "the value of 'alloc' is not usable in a constant expression" "" { xfail *-*-* } .-1 } */ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-3 } */ + }; +} +/* This case can't be diagnosed, there exists a T where alloc is a converted + constant expression of type omp_allocator_handle_t. This is demonstrated + below in dependent_capture_used_in_allocator_clause_static_var_templ_valid. */ +template +void dependent_capture_used_in_allocator_clause_static_var_templ_uninstantiated() +{ + T alloc = omp_default_mem_alloc; /* { dg-bogus "" } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-bogus "'a' declared here" } */ + static int c = 42; /* { dg-bogus "'c' declared here" } */ + #pragma omp allocate(a, c) allocator(alloc) + /* { dg-bogus "the value of 'alloc' is not usable in a constant expression" "" { target *-*-* } .-1 } */ + /* { dg-bogus "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ + }; +} + +template +void capture_used_in_allocator_clause_static_var_templ() +{ + omp_allocator_handle_t alloc = omp_default_mem_alloc; /* { dg-note "'omp_allocator_handle_t alloc' is not const" "" { xfail c++17 } } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-note "'a' declared here" "" { xfail c++17 } } */ + int b = 42; /* { dg-bogus "'b' declared here" } */ + static int c = 42; /* { dg-note "'c' declared here" "" { xfail c++17 } } */ + int d = 42; /* { dg-bogus "'d' declared here" } */ + #pragma omp allocate(a, b, c, d) allocator(alloc) + /* { dg-error "the value of 'alloc' is not usable in a constant expression" "" { xfail c++17 } .-1 }*/ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail c++17 } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail c++17 } .-3 } */ + }; +} + +template +void dependent_capture_used_in_allocator_clause_static_var_templ() +{ + T alloc = omp_default_mem_alloc; /* { dg-note "'omp_allocator_handle_t alloc' is not const" "" { xfail c++17 } } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-note "'a' declared here" "" { xfail c++17 } } */ + int b = 42; /* { dg-bogus "'b' declared here" } */ + static int c = 42; /* { dg-note "'c' declared here" "" { xfail c++17 } } */ + int d = 42; /* { dg-bogus "'d' declared here" } */ + #pragma omp allocate(a, b, c, d) allocator(alloc) + /* { dg-error "the value of 'alloc' is not usable in a constant expression" "" { xfail c++17 } .-1 } */ + /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail c++17 } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail c++17 } .-3 } */ + }; +} + +template +void dependent_capture_used_in_allocator_clause_static_var_templ_valid() +{ + T alloc = omp_default_mem_alloc; /* { dg-bogus "" } */ + auto cl = [alloc](){ + static int a = 42; /* { dg-bogus "" } */ + static int c = 42; /* { dg-bogus "" } */ + #pragma omp allocate(a, c) allocator(alloc) + /* { dg-bogus "the value of 'alloc' is not usable in a constant expression" "" { target *-*-* } .-1 } */ + /* { dg-bogus "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-2 } */ + }; +} + +void instantiate_capture_used_in_allocator_clause_static_var() +{ + capture_used_in_allocator_clause_static_var_templ(); + dependent_capture_used_in_allocator_clause_static_var_templ(); + + struct S { + constexpr S (omp_allocator_handle_t) {} + constexpr operator omp_allocator_handle_t () const { return omp_default_mem_alloc; } + }; + dependent_capture_used_in_allocator_clause_static_var_templ_valid (); + dependent_capture_used_in_allocator_clause_static_var_templ_valid (); +} + + + +void capture_used_in_align_clause() +{ + int align = 32; /* { dg-note "'int align' is not const" } */ + auto cl = [align](){ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "the value of 'align' is not usable in a constant expression" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */ + }; +} + +template +void capture_used_in_align_clause_templ_uninstantiated() +{ + int align = 32; /* { dg-note "'int align' is not const" "" { xfail *-*-* } } */ + auto cl = [align](){ + /* { dg-bogus "the value of 'align' is not usable in a constant expression" "" { target *-*-* } .-1 } */ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "the value of 'align' is not usable in a constant expression" "" { xfail *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ + }; +} + +/* This case can't be diagnosed, there exists a T where align is a converted + constant expression of long unsigned int. This is demonstrated + below in dependent_capture_used_in_align_clause_templ_valid. */ +template +void dependent_capture_used_in_align_clause_templ_uninstantiated() +{ + T align = 32; /* { dg-bogus "" } */ + auto cl = [align](){ + int a; + #pragma omp allocate(a) align(align) /* { dg-bogus "" } */ + }; +} + +template +void capture_used_in_align_clause_templ() +{ + int align = 32; /* { dg-note "'int align' is not const" "" { xfail c++17 } } */ + auto cl = [align](){ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "the value of 'align' is not usable in a constant expression" "" { target *-*-* xfail c++17 } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* xfail c++17 } .-2 } */ + }; +} + +template +void dependent_capture_used_in_align_clause_templ() +{ + T align = 32; /* { dg-note "'int align' is not const" "" { xfail c++17 } } */ + auto cl = [align](){ + int a; + #pragma omp allocate(a) align(align) + /* { dg-error "the value of 'align' is not usable in a constant expression" "" { target *-*-* xfail c++17 } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* xfail c++17 } .-2 } */ + }; +} + +template +void dependent_capture_used_in_align_clause_templ_valid() +{ + T align = 32; /* { dg-bogus "" } */ + auto cl = [align](){ + int a; + #pragma omp allocate(a) align(align) /* { dg-bogus "" } */ + }; +} + +void instantiate_capture_used_in_align() +{ + capture_used_in_align_clause_templ(); + dependent_capture_used_in_align_clause_templ(); + + struct S { + constexpr S (int) {} + constexpr operator unsigned int () const { return 32; } + }; + dependent_capture_used_in_align_clause_templ_valid (); + dependent_capture_used_in_align_clause_templ_valid (); +} diff --git a/gcc/testsuite/g++.dg/gomp/allocate-17.C b/gcc/testsuite/g++.dg/gomp/allocate-17.C new file mode 100644 index 00000000000..e265ecdd1e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-17.C @@ -0,0 +1,560 @@ +/* { dg-do compile { target c++17 } } */ + +/* Nested lambdas. */ + +#include "allocate-allocator-handle.h" + +template +auto lambda_0_valid() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + return a; + }; + }; + }; + }; +} + +template +auto lambda_0_bad_align() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_0_ref_in_directive() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + + +template +auto lambda_0_invalid_allocator() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_0_all() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-3 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_0_wrong_align_partially_instantiated() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_0_invalid_allocator_partially_instantiated() +{ + return [](auto p0){ + return [](auto p1){ + return [](auto p2){ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { xfail *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +void instantiate_lambdas_0() +{ + { + auto c0 = lambda_0_valid<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(omp_default_mem_alloc); + c3(0); + } + { + auto c0 = lambda_0_bad_align<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + auto c1 = c0(0); /* { dg-bogus "required from here" } */ + auto c2 = c1(0); /* { dg-bogus "required from here" } */ + auto c3 = c2(omp_default_mem_alloc); /* { dg-bogus "required from here" } */ + c3(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_0_ref_in_directive<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(omp_default_mem_alloc); + int a = 0; + c3.operator()(a); /* { dg-message "required from here" } */ + } + { + auto c0 = lambda_0_invalid_allocator<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); /* { dg-message "required from here" "" { xfail *-*-* } } */ + c3(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_0_all<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + auto c1 = c0(0); /* { dg-bogus "required from here" } */ + auto c2 = c1(0); /* { dg-bogus "required from here" } */ + auto c3 = c2(0); /* { dg-message "required from here" "" { xfail *-*-* } } */ + int a = 0; + c3.operator()(a); /* { dg-message "required from here" } */ + } + { + auto c = lambda_0_wrong_align_partially_instantiated<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_0_invalid_allocator_partially_instantiated<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); /* { dg-message "required from here" "" { xfail *-*-* } } */ + } +} + + + +template +auto lambda_1_valid() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_bad_align() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_ref_in_directive() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_invalid_allocator() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_all() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */ + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-3 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_wrong_align_partially_instantiated() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_1_invalid_allocator_partially_instantiated() +{ + return [](auto p0){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p1){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [](auto p2){ + int a = 42; + #pragma omp allocate(a) align(Align) + return [p2](auto p3){ + int b = 42; + decltype(p3) a = b; + #pragma omp allocate(a) align(Align) allocator(p2) + /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { xfail *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +void instantiate_lambdas_1() +{ + { + auto c0 = lambda_1_valid<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(omp_default_mem_alloc); + c3(0); + } + { + auto c0 = lambda_1_bad_align<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + auto c1 = c0(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + auto c2 = c1(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + auto c3 = c2(omp_default_mem_alloc); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + c3(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_1_ref_in_directive<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(omp_default_mem_alloc); + int a = 0; + c3.operator()(a); /* { dg-message "required from here" } */ + } + { + auto c0 = lambda_1_invalid_allocator<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); /* { dg-message "required from here" "" { xfail *-*-* } } */ + c3(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_1_all<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + auto c1 = c0(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + auto c2 = c1(0); /* { dg-bogus "required from here" "" { xfail *-*-* } } */ + auto c3 = c2(0); /* { dg-message "required from here" } */ + int a = 0; + c3.operator()(a); /* { dg-message "required from here" } */ + } + { + auto c = lambda_1_wrong_align_partially_instantiated<30>(); /* { dg-message "required from here" "" { xfail *-*-* } } */ + } + { + auto c0 = lambda_1_invalid_allocator_partially_instantiated<32>(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); /* { dg-message "required from here" "" { xfail *-*-* } } */ + } +} + + + +template +auto lambda_2_0_valid() +{ + return [](auto){ + return [](auto){ + return [](auto){ + return [](auto){ + int b = 42; + T a = b; + #pragma omp allocate(a) + return a; + }; + }; + }; + }; +} + +template +auto lambda_2_0_invalid() +{ + return [](auto){ + return [](auto){ + return [](auto){ + return [](auto){ + int b = 42; + T a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_2_0_invalid_partially_instantiated() +{ + return [](auto){ + return [](auto){ + return [](auto){ + return [](auto){ + int b = 42; + T a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_2_1_valid() +{ + return [](auto){ + return [](auto){ + return [](auto p2){ + using type = decltype(p2); + return [](auto){ + int b = 42; + type a = b; + #pragma omp allocate(a) + return a; + }; + }; + }; + }; +} + +template +auto lambda_2_1_invalid() +{ + return [](auto){ + return [](auto){ + return [](auto p2){ + using type = decltype(p2); + return [](auto){ + int b = 42; + type a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +template +auto lambda_2_1_invalid_partially_instantiated() +{ + return [](auto){ + return [](auto){ + return [](auto p2){ + using type = decltype(p2); + return [](auto){ + int b = 42; + type a = b; /* { dg-message "'a' declared here" } */ + #pragma omp allocate(a) + /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */ + return a; + }; + }; + }; + }; +} + +void instantiate_lambdas_2() +{ + { + auto c0 = lambda_2_0_valid(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); + c3(0); + } + { + auto c0 = lambda_2_0_invalid(); /* { dg-message "required from here" } */ + auto c1 = c0(0); /* { dg-bogus "required from here" } */ + auto c2 = c1(0); /* { dg-bogus "required from here" } */ + auto c3 = c2(0); /* { dg-bogus "required from here" } */ + c3(0); /* { dg-bogus "required from here" } */ + } + { + auto c0 = lambda_2_0_invalid_partially_instantiated(); /* { dg-message "required from here" } */ + } + { + auto c0 = lambda_2_1_valid(); + auto c1 = c0(0); + auto c2 = c1(0); + auto c3 = c2(0); + c3(0); + } + { + auto c0 = lambda_2_1_invalid(); + auto c1 = c0(0); + auto c2 = c1(0); + int a = 0; + auto c3 = c2.operator()(a); /* { dg-message "required from here" } */ + c3(0); /* { dg-bogus "required from here" } */ + } + { + auto c0 = lambda_2_1_invalid_partially_instantiated(); + auto c1 = c0(0); + auto c2 = c1(0); + int a = 0; + auto c3 = c2.operator()(a); /* { dg-message "required from here" } */ + } +} + +/* This is fixed by the later location wrapping patch. */ +/* { dg-bogus "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } 0 } */ diff --git a/gcc/testsuite/g++.dg/gomp/allocate-18.C b/gcc/testsuite/g++.dg/gomp/allocate-18.C new file mode 100644 index 00000000000..3a04bbe8bcd --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-18.C @@ -0,0 +1,274 @@ +/* { dg-do compile { target c++17 } } */ + +/* OpenMP allocate directive in constant expressions where execution does not + pass through the allocation of the variable in the directive. + Lambdas, both implicit and explicit constexpr, + in a function and in a function template. + + These cases will be valid if/when OpenMP relaxes restrictions on directives + in constexpr functions. It might make sense to only allow this behavior in + c++23 though. + + Constexpr lambdas are only permitted in c++17, it doesn't make sense to test + anything prior than that. + + NOTE: The error messages for the cases that are not explicitly declared + constexpr are probably not what we want, we likely want something stating + that the calls are not usable in a constant expression because of the use of + an OpenMP directive. */ + +void do_constexpr_lambda() +{ + auto cl = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_constexpr_lambda\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} + +void do_constexpr_generic_lambda() +{ + auto cl = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_constexpr_generic_lambda\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} + +void do_lambda() +{ + auto cl = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_lambda\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} + +void do_generic_lambda() +{ + auto cl = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_generic_lambda\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} + +template +void do_constexpr_lambda_templ_uninstantiated() +{ + auto cl = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} + +template +void do_constexpr_generic_lambda_templ_uninstantiated() +{ + auto cl = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} + +template +void do_lambda_templ_uninstantiated() +{ + auto cl = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} + +template +void do_generic_lambda_templ_uninstantiated() +{ + auto cl = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} + + +template +void do_constexpr_lambda_templ() +{ + auto cl = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_constexpr_lambda_templ\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} +template void do_constexpr_lambda_templ(); + +template +void do_constexpr_generic_lambda_templ() +{ + auto cl = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_constexpr_lambda_templ\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b) constexpr { + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; + }(true); +} +template void do_constexpr_generic_lambda_templ(); + +template +void do_lambda_templ() +{ + auto cl = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_lambda_templ\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](bool b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} +template void do_lambda_templ(); + +template +void do_generic_lambda_templ() +{ + auto cl = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }; + constexpr int v0 = cl(true); /* { dg-error "'do_generic_lambda_templ\\\(\\\)::' called in a constant expression" "" { xfail *-*-* } } */ + + constexpr int v1 = [](auto b){ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; + }(true); +} +template void do_generic_lambda_templ(); + +/* Missing cases where the lambda/lambda body is dependent on the outer + template params. */ diff --git a/gcc/testsuite/g++.dg/gomp/allocate-19.C b/gcc/testsuite/g++.dg/gomp/allocate-19.C new file mode 100644 index 00000000000..e99106893da --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/allocate-19.C @@ -0,0 +1,128 @@ +/* { dg-do compile { target c++14 } } */ +/* { dg-additional-options "-fimplicit-constexpr" } */ + +/* OpenMP allocate directive in constant expressions where execution does not + pass through the allocation of the variable in the directive. + Regular functions and function templates, + constexpr and inline with -fimplicit-constexpr. + + These cases will be valid if/when OpenMP relaxes restrictions on directives + in constexpr functions. It might make sense to only allow this behavior in + c++23 though. + + It doesn't make sense to test these cases in c++11 as constexpr functions + are far more limited, and are diagnosed completely differently. + + Even though -fimplicit-constexpr is an extension, its behavior is similar to + lambdas in c++17, so I am including tests for it. + See allocate-18.C for test cases involving lambdas. + + NOTE: The error messages for the inline cases are are probably not what we + want, we likely want something stating that the calls are not usable in a + constant expression because of the use of an OpenMP directive. */ + +constexpr int f_constexpr(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; +} +constexpr int g_cx_0 = f_constexpr(true); /* { dg-error "'constexpr int f_constexpr\\\(bool\\\)' called in a constant expression" "" { xfail *-*-* } } */ + +template +constexpr int f_constexpr_templ_uninstantiated(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; +} + +template +constexpr int f_constexpr_templ(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; +} +constexpr int g_cx_1 = f_constexpr_templ(true); /* { dg-error "'constexpr int f_constexpr_templ\\\(bool\\\) \\\[with = void\\\]' called in a constant expression" "" { xfail *-*-* } } */ + +template +constexpr int f_constexpr_dep_parm_templ_uninstantiated(B b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; +} + +template +constexpr int f_constexpr_dep_parm_templ(B b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" } */ + return a; +} +constexpr int g_cx_2 = f_constexpr_dep_parm_templ(true); /* { dg-error "'constexpr int f_constexpr_dep_parm_templ\\\(bool\\\) \\\[with = bool\\\]' called in a constant expression" "" { xfail *-*-* } } */ + + + +inline int f_inline(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; +} +constexpr int g_inline_0 = f_inline(true); /* { dg-error "'int f_inline\\\(bool\\\)' called in a constant expression" "" { xfail *-*-* } } */ + +template +inline int f_inline_templ_uninstantiated(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; +} + +template +inline int f_inline_templ(bool b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; +} +constexpr int g_inline_1 = f_inline_templ(true); /* { dg-error "'int f_inline_templ\\\(bool\\\) \\\[with = void\\\]' called in a constant expression" "" { xfail *-*-* } } */ + +template +inline int f_inline_dep_parm_templ_uninstantiated(B b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; +} + +template +inline int f_inline_dep_parm_templ(B b) +{ + if (b) + return 42; + int a = 42; + #pragma omp allocate(a) /* { dg-error "OpenMP directives may not appear in 'constexpr' functions" "" { xfail *-*-* } } */ + return a; +} +constexpr int g_inline_2 = f_inline_dep_parm_templ(true); /* { dg-error "'int f_inline_deb_parm_templ\\\(bool\\\) \\\[with = bool\\\]' called in a constant expression" "" { xfail *-*-* } } */ diff --git a/gcc/testsuite/g++.dg/gomp/allocate-handles-1.C b/gcc/testsuite/g++.dg/gomp/allocate-handles-1.C index c0c59a30a3c..786c2f5550e 100644 --- a/gcc/testsuite/g++.dg/gomp/allocate-handles-1.C +++ b/gcc/testsuite/g++.dg/gomp/allocate-handles-1.C @@ -15,49 +15,47 @@ #define GOMP_OMPX_PREDEF_ALLOC_MIN 200 #define GOMP_OMPX_PREDEF_ALLOC_MAX 201 -int g0 = 42; /* { dg-note "'g0' declared here" "" { xfail *-*-* } } */ +int g0 = 42; /* { dg-note "'g0' declared here" } */ #pragma omp allocate(g0) allocator(omp_null_allocator) /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '0'" "" { target *-*-* } .-3 } */ -int g1 = 42; /* { dg-note "'g1' declared here" "" { xfail *-*-* } }*/ +int g1 = 42; /* { dg-note "'g1' declared here" } */ #pragma omp allocate(g1) allocator(static_cast(GOMP_OMP_PREDEF_ALLOC_MAX + 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "If this test fails because of added predefined allocators please ensure everything is updated accordingly, see this test case for more information" { target *-*-* } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '9'" "" { target *-*-* } .-3 } */ -int g2 = 42; /* { dg-note "'g2' declared here" "" { xfail *-*-* } }*/ +int g2 = 42; /* { dg-note "'g2' declared here" } */ #pragma omp allocate(g2) allocator(static_cast(GOMP_OMPX_PREDEF_ALLOC_MIN - 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '199'" "" { target *-*-* } .-3 } */ -int g3 = 42; /* { dg-note "'g3' declared here" "" { xfail *-*-* } }*/ +int g3 = 42; /* { dg-note "'g3' declared here" } */ #pragma omp allocate(g3) allocator(static_cast(GOMP_OMPX_PREDEF_ALLOC_MAX + 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "If this test fails because of added predefined allocators please ensure everything is updated accordingly, see this test case for more information" { target *-*-* } .-1 } */ -/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ +/* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '202'" "" { target *-*-* } .-3 } */ void test_predefined_allocs() { - static int a0 = 42; /* { dg-note "'a0' declared here" "" { xfail *-*-* } }*/ + static int a0 = 42; /* { dg-note "'a0' declared here" }*/ #pragma omp allocate(a0) allocator(omp_null_allocator) /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */ - /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '0'" "" { target *-*-* } .-3 } */ - static int a1 = 42; /* { dg-note "'a1' declared here" "" { xfail *-*-* } }*/ + static int a1 = 42; /* { dg-note "'a1' declared here" }*/ #pragma omp allocate(a1) allocator(static_cast(GOMP_OMP_PREDEF_ALLOC_MAX + 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "If this test fails because of added predefined allocators please ensure everything is updated accordingly, see this test case for more information" { target *-*-* } .-1 } */ - /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '9'" "" { target *-*-* } .-3 } */ - static int a2 = 42; /* { dg-note "'a2' declared here" "" { xfail *-*-* } }*/ + static int a2 = 42; /* { dg-note "'a2' declared here" }*/ #pragma omp allocate(a2) allocator(static_cast(GOMP_OMPX_PREDEF_ALLOC_MIN - 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */ - /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '199'" "" { target *-*-* } .-3 } */ - static int a3 = 42; /* { dg-note "'a3' declared here" "" { xfail *-*-* } }*/ + static int a3 = 42; /* { dg-note "'a3' declared here" }*/ #pragma omp allocate(a3) allocator(static_cast(GOMP_OMPX_PREDEF_ALLOC_MAX + 1)) /* { dg-error "'allocator' clause requires a constant predefined allocator" "If this test fails because of added predefined allocators please ensure everything is updated accordingly, see this test case for more information" { target *-*-* } .-1 } */ - /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail *-*-* } .-2 } */ + /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */ /* { dg-note "expression evaluates to '202'" "" { target *-*-* } .-3 } */ } - -/* { dg-bogus "because one or more variables with static storage duration appear in the 'allocate' directive" "" { xfail c++ } 0 }*/