138fd1498Szrj /* Perform the semantic phase of parsing, i.e., the process of
238fd1498Szrj building tree structure, checking semantic consistency, and
338fd1498Szrj building RTL. These routines are used both during actual parsing
438fd1498Szrj and during the instantiation of template functions.
538fd1498Szrj
638fd1498Szrj Copyright (C) 1998-2018 Free Software Foundation, Inc.
738fd1498Szrj Written by Mark Mitchell (mmitchell@usa.net) based on code found
838fd1498Szrj formerly in parse.y and pt.c.
938fd1498Szrj
1038fd1498Szrj This file is part of GCC.
1138fd1498Szrj
1238fd1498Szrj GCC is free software; you can redistribute it and/or modify it
1338fd1498Szrj under the terms of the GNU General Public License as published by
1438fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1538fd1498Szrj any later version.
1638fd1498Szrj
1738fd1498Szrj GCC is distributed in the hope that it will be useful, but
1838fd1498Szrj WITHOUT ANY WARRANTY; without even the implied warranty of
1938fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2038fd1498Szrj General Public License for more details.
2138fd1498Szrj
2238fd1498Szrj You should have received a copy of the GNU General Public License
2338fd1498Szrj along with GCC; see the file COPYING3. If not see
2438fd1498Szrj <http://www.gnu.org/licenses/>. */
2538fd1498Szrj
2638fd1498Szrj #include "config.h"
2738fd1498Szrj #include "system.h"
2838fd1498Szrj #include "coretypes.h"
2938fd1498Szrj #include "target.h"
3038fd1498Szrj #include "bitmap.h"
3138fd1498Szrj #include "cp-tree.h"
3238fd1498Szrj #include "stringpool.h"
3338fd1498Szrj #include "cgraph.h"
3438fd1498Szrj #include "stmt.h"
3538fd1498Szrj #include "varasm.h"
3638fd1498Szrj #include "stor-layout.h"
3738fd1498Szrj #include "c-family/c-objc.h"
3838fd1498Szrj #include "tree-inline.h"
3938fd1498Szrj #include "intl.h"
4038fd1498Szrj #include "tree-iterator.h"
4138fd1498Szrj #include "omp-general.h"
4238fd1498Szrj #include "convert.h"
4338fd1498Szrj #include "stringpool.h"
4438fd1498Szrj #include "attribs.h"
4538fd1498Szrj #include "gomp-constants.h"
4638fd1498Szrj #include "predict.h"
4738fd1498Szrj
4838fd1498Szrj /* There routines provide a modular interface to perform many parsing
4938fd1498Szrj operations. They may therefore be used during actual parsing, or
5038fd1498Szrj during template instantiation, which may be regarded as a
5138fd1498Szrj degenerate form of parsing. */
5238fd1498Szrj
5338fd1498Szrj static tree maybe_convert_cond (tree);
5438fd1498Szrj static tree finalize_nrv_r (tree *, int *, void *);
5538fd1498Szrj static tree capture_decltype (tree);
5638fd1498Szrj
5738fd1498Szrj /* Used for OpenMP non-static data member privatization. */
5838fd1498Szrj
5938fd1498Szrj static hash_map<tree, tree> *omp_private_member_map;
6038fd1498Szrj static vec<tree> omp_private_member_vec;
6138fd1498Szrj static bool omp_private_member_ignore_next;
6238fd1498Szrj
6338fd1498Szrj
6438fd1498Szrj /* Deferred Access Checking Overview
6538fd1498Szrj ---------------------------------
6638fd1498Szrj
6738fd1498Szrj Most C++ expressions and declarations require access checking
6838fd1498Szrj to be performed during parsing. However, in several cases,
6938fd1498Szrj this has to be treated differently.
7038fd1498Szrj
7138fd1498Szrj For member declarations, access checking has to be deferred
7238fd1498Szrj until more information about the declaration is known. For
7338fd1498Szrj example:
7438fd1498Szrj
7538fd1498Szrj class A {
7638fd1498Szrj typedef int X;
7738fd1498Szrj public:
7838fd1498Szrj X f();
7938fd1498Szrj };
8038fd1498Szrj
8138fd1498Szrj A::X A::f();
8238fd1498Szrj A::X g();
8338fd1498Szrj
8438fd1498Szrj When we are parsing the function return type `A::X', we don't
8538fd1498Szrj really know if this is allowed until we parse the function name.
8638fd1498Szrj
8738fd1498Szrj Furthermore, some contexts require that access checking is
8838fd1498Szrj never performed at all. These include class heads, and template
8938fd1498Szrj instantiations.
9038fd1498Szrj
9138fd1498Szrj Typical use of access checking functions is described here:
9238fd1498Szrj
9338fd1498Szrj 1. When we enter a context that requires certain access checking
9438fd1498Szrj mode, the function `push_deferring_access_checks' is called with
9538fd1498Szrj DEFERRING argument specifying the desired mode. Access checking
9638fd1498Szrj may be performed immediately (dk_no_deferred), deferred
9738fd1498Szrj (dk_deferred), or not performed (dk_no_check).
9838fd1498Szrj
9938fd1498Szrj 2. When a declaration such as a type, or a variable, is encountered,
10038fd1498Szrj the function `perform_or_defer_access_check' is called. It
10138fd1498Szrj maintains a vector of all deferred checks.
10238fd1498Szrj
10338fd1498Szrj 3. The global `current_class_type' or `current_function_decl' is then
10438fd1498Szrj setup by the parser. `enforce_access' relies on these information
10538fd1498Szrj to check access.
10638fd1498Szrj
10738fd1498Szrj 4. Upon exiting the context mentioned in step 1,
10838fd1498Szrj `perform_deferred_access_checks' is called to check all declaration
10938fd1498Szrj stored in the vector. `pop_deferring_access_checks' is then
11038fd1498Szrj called to restore the previous access checking mode.
11138fd1498Szrj
11238fd1498Szrj In case of parsing error, we simply call `pop_deferring_access_checks'
11338fd1498Szrj without `perform_deferred_access_checks'. */
11438fd1498Szrj
11538fd1498Szrj struct GTY(()) deferred_access {
11638fd1498Szrj /* A vector representing name-lookups for which we have deferred
11738fd1498Szrj checking access controls. We cannot check the accessibility of
11838fd1498Szrj names used in a decl-specifier-seq until we know what is being
11938fd1498Szrj declared because code like:
12038fd1498Szrj
12138fd1498Szrj class A {
12238fd1498Szrj class B {};
12338fd1498Szrj B* f();
12438fd1498Szrj }
12538fd1498Szrj
12638fd1498Szrj A::B* A::f() { return 0; }
12738fd1498Szrj
12838fd1498Szrj is valid, even though `A::B' is not generally accessible. */
12938fd1498Szrj vec<deferred_access_check, va_gc> * GTY(()) deferred_access_checks;
13038fd1498Szrj
13138fd1498Szrj /* The current mode of access checks. */
13238fd1498Szrj enum deferring_kind deferring_access_checks_kind;
13338fd1498Szrj
13438fd1498Szrj };
13538fd1498Szrj
13638fd1498Szrj /* Data for deferred access checking. */
13738fd1498Szrj static GTY(()) vec<deferred_access, va_gc> *deferred_access_stack;
13838fd1498Szrj static GTY(()) unsigned deferred_access_no_check;
13938fd1498Szrj
14038fd1498Szrj /* Save the current deferred access states and start deferred
14138fd1498Szrj access checking iff DEFER_P is true. */
14238fd1498Szrj
14338fd1498Szrj void
push_deferring_access_checks(deferring_kind deferring)14438fd1498Szrj push_deferring_access_checks (deferring_kind deferring)
14538fd1498Szrj {
14638fd1498Szrj /* For context like template instantiation, access checking
14738fd1498Szrj disabling applies to all nested context. */
14838fd1498Szrj if (deferred_access_no_check || deferring == dk_no_check)
14938fd1498Szrj deferred_access_no_check++;
15038fd1498Szrj else
15138fd1498Szrj {
15238fd1498Szrj deferred_access e = {NULL, deferring};
15338fd1498Szrj vec_safe_push (deferred_access_stack, e);
15438fd1498Szrj }
15538fd1498Szrj }
15638fd1498Szrj
15738fd1498Szrj /* Save the current deferred access states and start deferred access
15838fd1498Szrj checking, continuing the set of deferred checks in CHECKS. */
15938fd1498Szrj
16038fd1498Szrj void
reopen_deferring_access_checks(vec<deferred_access_check,va_gc> * checks)16138fd1498Szrj reopen_deferring_access_checks (vec<deferred_access_check, va_gc> * checks)
16238fd1498Szrj {
16338fd1498Szrj push_deferring_access_checks (dk_deferred);
16438fd1498Szrj if (!deferred_access_no_check)
16538fd1498Szrj deferred_access_stack->last().deferred_access_checks = checks;
16638fd1498Szrj }
16738fd1498Szrj
16838fd1498Szrj /* Resume deferring access checks again after we stopped doing
16938fd1498Szrj this previously. */
17038fd1498Szrj
17138fd1498Szrj void
resume_deferring_access_checks(void)17238fd1498Szrj resume_deferring_access_checks (void)
17338fd1498Szrj {
17438fd1498Szrj if (!deferred_access_no_check)
17538fd1498Szrj deferred_access_stack->last().deferring_access_checks_kind = dk_deferred;
17638fd1498Szrj }
17738fd1498Szrj
17838fd1498Szrj /* Stop deferring access checks. */
17938fd1498Szrj
18038fd1498Szrj void
stop_deferring_access_checks(void)18138fd1498Szrj stop_deferring_access_checks (void)
18238fd1498Szrj {
18338fd1498Szrj if (!deferred_access_no_check)
18438fd1498Szrj deferred_access_stack->last().deferring_access_checks_kind = dk_no_deferred;
18538fd1498Szrj }
18638fd1498Szrj
18738fd1498Szrj /* Discard the current deferred access checks and restore the
18838fd1498Szrj previous states. */
18938fd1498Szrj
19038fd1498Szrj void
pop_deferring_access_checks(void)19138fd1498Szrj pop_deferring_access_checks (void)
19238fd1498Szrj {
19338fd1498Szrj if (deferred_access_no_check)
19438fd1498Szrj deferred_access_no_check--;
19538fd1498Szrj else
19638fd1498Szrj deferred_access_stack->pop ();
19738fd1498Szrj }
19838fd1498Szrj
19938fd1498Szrj /* Returns a TREE_LIST representing the deferred checks.
20038fd1498Szrj The TREE_PURPOSE of each node is the type through which the
20138fd1498Szrj access occurred; the TREE_VALUE is the declaration named.
20238fd1498Szrj */
20338fd1498Szrj
20438fd1498Szrj vec<deferred_access_check, va_gc> *
get_deferred_access_checks(void)20538fd1498Szrj get_deferred_access_checks (void)
20638fd1498Szrj {
20738fd1498Szrj if (deferred_access_no_check)
20838fd1498Szrj return NULL;
20938fd1498Szrj else
21038fd1498Szrj return (deferred_access_stack->last().deferred_access_checks);
21138fd1498Szrj }
21238fd1498Szrj
21338fd1498Szrj /* Take current deferred checks and combine with the
21438fd1498Szrj previous states if we also defer checks previously.
21538fd1498Szrj Otherwise perform checks now. */
21638fd1498Szrj
21738fd1498Szrj void
pop_to_parent_deferring_access_checks(void)21838fd1498Szrj pop_to_parent_deferring_access_checks (void)
21938fd1498Szrj {
22038fd1498Szrj if (deferred_access_no_check)
22138fd1498Szrj deferred_access_no_check--;
22238fd1498Szrj else
22338fd1498Szrj {
22438fd1498Szrj vec<deferred_access_check, va_gc> *checks;
22538fd1498Szrj deferred_access *ptr;
22638fd1498Szrj
22738fd1498Szrj checks = (deferred_access_stack->last ().deferred_access_checks);
22838fd1498Szrj
22938fd1498Szrj deferred_access_stack->pop ();
23038fd1498Szrj ptr = &deferred_access_stack->last ();
23138fd1498Szrj if (ptr->deferring_access_checks_kind == dk_no_deferred)
23238fd1498Szrj {
23338fd1498Szrj /* Check access. */
23438fd1498Szrj perform_access_checks (checks, tf_warning_or_error);
23538fd1498Szrj }
23638fd1498Szrj else
23738fd1498Szrj {
23838fd1498Szrj /* Merge with parent. */
23938fd1498Szrj int i, j;
24038fd1498Szrj deferred_access_check *chk, *probe;
24138fd1498Szrj
24238fd1498Szrj FOR_EACH_VEC_SAFE_ELT (checks, i, chk)
24338fd1498Szrj {
24438fd1498Szrj FOR_EACH_VEC_SAFE_ELT (ptr->deferred_access_checks, j, probe)
24538fd1498Szrj {
24638fd1498Szrj if (probe->binfo == chk->binfo &&
24738fd1498Szrj probe->decl == chk->decl &&
24838fd1498Szrj probe->diag_decl == chk->diag_decl)
24938fd1498Szrj goto found;
25038fd1498Szrj }
25138fd1498Szrj /* Insert into parent's checks. */
25238fd1498Szrj vec_safe_push (ptr->deferred_access_checks, *chk);
25338fd1498Szrj found:;
25438fd1498Szrj }
25538fd1498Szrj }
25638fd1498Szrj }
25738fd1498Szrj }
25838fd1498Szrj
25938fd1498Szrj /* Perform the access checks in CHECKS. The TREE_PURPOSE of each node
26038fd1498Szrj is the BINFO indicating the qualifying scope used to access the
26138fd1498Szrj DECL node stored in the TREE_VALUE of the node. If CHECKS is empty
26238fd1498Szrj or we aren't in SFINAE context or all the checks succeed return TRUE,
26338fd1498Szrj otherwise FALSE. */
26438fd1498Szrj
26538fd1498Szrj bool
perform_access_checks(vec<deferred_access_check,va_gc> * checks,tsubst_flags_t complain)26638fd1498Szrj perform_access_checks (vec<deferred_access_check, va_gc> *checks,
26738fd1498Szrj tsubst_flags_t complain)
26838fd1498Szrj {
26938fd1498Szrj int i;
27038fd1498Szrj deferred_access_check *chk;
27138fd1498Szrj location_t loc = input_location;
27238fd1498Szrj bool ok = true;
27338fd1498Szrj
27438fd1498Szrj if (!checks)
27538fd1498Szrj return true;
27638fd1498Szrj
27738fd1498Szrj FOR_EACH_VEC_SAFE_ELT (checks, i, chk)
27838fd1498Szrj {
27938fd1498Szrj input_location = chk->loc;
28038fd1498Szrj ok &= enforce_access (chk->binfo, chk->decl, chk->diag_decl, complain);
28138fd1498Szrj }
28238fd1498Szrj
28338fd1498Szrj input_location = loc;
28438fd1498Szrj return (complain & tf_error) ? true : ok;
28538fd1498Szrj }
28638fd1498Szrj
28738fd1498Szrj /* Perform the deferred access checks.
28838fd1498Szrj
28938fd1498Szrj After performing the checks, we still have to keep the list
29038fd1498Szrj `deferred_access_stack->deferred_access_checks' since we may want
29138fd1498Szrj to check access for them again later in a different context.
29238fd1498Szrj For example:
29338fd1498Szrj
29438fd1498Szrj class A {
29538fd1498Szrj typedef int X;
29638fd1498Szrj static X a;
29738fd1498Szrj };
29838fd1498Szrj A::X A::a, x; // No error for `A::a', error for `x'
29938fd1498Szrj
30038fd1498Szrj We have to perform deferred access of `A::X', first with `A::a',
30138fd1498Szrj next with `x'. Return value like perform_access_checks above. */
30238fd1498Szrj
30338fd1498Szrj bool
perform_deferred_access_checks(tsubst_flags_t complain)30438fd1498Szrj perform_deferred_access_checks (tsubst_flags_t complain)
30538fd1498Szrj {
30638fd1498Szrj return perform_access_checks (get_deferred_access_checks (), complain);
30738fd1498Szrj }
30838fd1498Szrj
30938fd1498Szrj /* Defer checking the accessibility of DECL, when looked up in
31038fd1498Szrj BINFO. DIAG_DECL is the declaration to use to print diagnostics.
31138fd1498Szrj Return value like perform_access_checks above.
31238fd1498Szrj If non-NULL, report failures to AFI. */
31338fd1498Szrj
31438fd1498Szrj bool
perform_or_defer_access_check(tree binfo,tree decl,tree diag_decl,tsubst_flags_t complain,access_failure_info * afi)31538fd1498Szrj perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl,
31638fd1498Szrj tsubst_flags_t complain,
31738fd1498Szrj access_failure_info *afi)
31838fd1498Szrj {
31938fd1498Szrj int i;
32038fd1498Szrj deferred_access *ptr;
32138fd1498Szrj deferred_access_check *chk;
32238fd1498Szrj
32338fd1498Szrj
32438fd1498Szrj /* Exit if we are in a context that no access checking is performed.
32538fd1498Szrj */
32638fd1498Szrj if (deferred_access_no_check)
32738fd1498Szrj return true;
32838fd1498Szrj
32938fd1498Szrj gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
33038fd1498Szrj
33138fd1498Szrj ptr = &deferred_access_stack->last ();
33238fd1498Szrj
33338fd1498Szrj /* If we are not supposed to defer access checks, just check now. */
33438fd1498Szrj if (ptr->deferring_access_checks_kind == dk_no_deferred)
33538fd1498Szrj {
33638fd1498Szrj bool ok = enforce_access (binfo, decl, diag_decl, complain, afi);
33738fd1498Szrj return (complain & tf_error) ? true : ok;
33838fd1498Szrj }
33938fd1498Szrj
34038fd1498Szrj /* See if we are already going to perform this check. */
34138fd1498Szrj FOR_EACH_VEC_SAFE_ELT (ptr->deferred_access_checks, i, chk)
34238fd1498Szrj {
34338fd1498Szrj if (chk->decl == decl && chk->binfo == binfo &&
34438fd1498Szrj chk->diag_decl == diag_decl)
34538fd1498Szrj {
34638fd1498Szrj return true;
34738fd1498Szrj }
34838fd1498Szrj }
34938fd1498Szrj /* If not, record the check. */
35038fd1498Szrj deferred_access_check new_access = {binfo, decl, diag_decl, input_location};
35138fd1498Szrj vec_safe_push (ptr->deferred_access_checks, new_access);
35238fd1498Szrj
35338fd1498Szrj return true;
35438fd1498Szrj }
35538fd1498Szrj
35638fd1498Szrj /* Returns nonzero if the current statement is a full expression,
35738fd1498Szrj i.e. temporaries created during that statement should be destroyed
35838fd1498Szrj at the end of the statement. */
35938fd1498Szrj
36038fd1498Szrj int
stmts_are_full_exprs_p(void)36138fd1498Szrj stmts_are_full_exprs_p (void)
36238fd1498Szrj {
36338fd1498Szrj return current_stmt_tree ()->stmts_are_full_exprs_p;
36438fd1498Szrj }
36538fd1498Szrj
36638fd1498Szrj /* T is a statement. Add it to the statement-tree. This is the C++
36738fd1498Szrj version. The C/ObjC frontends have a slightly different version of
36838fd1498Szrj this function. */
36938fd1498Szrj
37038fd1498Szrj tree
add_stmt(tree t)37138fd1498Szrj add_stmt (tree t)
37238fd1498Szrj {
37338fd1498Szrj enum tree_code code = TREE_CODE (t);
37438fd1498Szrj
37538fd1498Szrj if (EXPR_P (t) && code != LABEL_EXPR)
37638fd1498Szrj {
37738fd1498Szrj if (!EXPR_HAS_LOCATION (t))
37838fd1498Szrj SET_EXPR_LOCATION (t, input_location);
37938fd1498Szrj
38038fd1498Szrj /* When we expand a statement-tree, we must know whether or not the
38138fd1498Szrj statements are full-expressions. We record that fact here. */
38238fd1498Szrj STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
38338fd1498Szrj }
38438fd1498Szrj
38538fd1498Szrj if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
38638fd1498Szrj STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
38738fd1498Szrj
38838fd1498Szrj /* Add T to the statement-tree. Non-side-effect statements need to be
38938fd1498Szrj recorded during statement expressions. */
39038fd1498Szrj gcc_checking_assert (!stmt_list_stack->is_empty ());
39138fd1498Szrj append_to_statement_list_force (t, &cur_stmt_list);
39238fd1498Szrj
39338fd1498Szrj return t;
39438fd1498Szrj }
39538fd1498Szrj
39638fd1498Szrj /* Returns the stmt_tree to which statements are currently being added. */
39738fd1498Szrj
39838fd1498Szrj stmt_tree
current_stmt_tree(void)39938fd1498Szrj current_stmt_tree (void)
40038fd1498Szrj {
40138fd1498Szrj return (cfun
40238fd1498Szrj ? &cfun->language->base.x_stmt_tree
40338fd1498Szrj : &scope_chain->x_stmt_tree);
40438fd1498Szrj }
40538fd1498Szrj
40638fd1498Szrj /* If statements are full expressions, wrap STMT in a CLEANUP_POINT_EXPR. */
40738fd1498Szrj
40838fd1498Szrj static tree
maybe_cleanup_point_expr(tree expr)40938fd1498Szrj maybe_cleanup_point_expr (tree expr)
41038fd1498Szrj {
41138fd1498Szrj if (!processing_template_decl && stmts_are_full_exprs_p ())
41238fd1498Szrj expr = fold_build_cleanup_point_expr (TREE_TYPE (expr), expr);
41338fd1498Szrj return expr;
41438fd1498Szrj }
41538fd1498Szrj
41638fd1498Szrj /* Like maybe_cleanup_point_expr except have the type of the new expression be
41738fd1498Szrj void so we don't need to create a temporary variable to hold the inner
41838fd1498Szrj expression. The reason why we do this is because the original type might be
41938fd1498Szrj an aggregate and we cannot create a temporary variable for that type. */
42038fd1498Szrj
42138fd1498Szrj tree
maybe_cleanup_point_expr_void(tree expr)42238fd1498Szrj maybe_cleanup_point_expr_void (tree expr)
42338fd1498Szrj {
42438fd1498Szrj if (!processing_template_decl && stmts_are_full_exprs_p ())
42538fd1498Szrj expr = fold_build_cleanup_point_expr (void_type_node, expr);
42638fd1498Szrj return expr;
42738fd1498Szrj }
42838fd1498Szrj
42938fd1498Szrj
43038fd1498Szrj
43138fd1498Szrj /* Create a declaration statement for the declaration given by the DECL. */
43238fd1498Szrj
43338fd1498Szrj void
add_decl_expr(tree decl)43438fd1498Szrj add_decl_expr (tree decl)
43538fd1498Szrj {
43638fd1498Szrj tree r = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl);
43738fd1498Szrj if (DECL_INITIAL (decl)
43838fd1498Szrj || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl))))
43938fd1498Szrj r = maybe_cleanup_point_expr_void (r);
44038fd1498Szrj add_stmt (r);
44138fd1498Szrj }
44238fd1498Szrj
44338fd1498Szrj /* Finish a scope. */
44438fd1498Szrj
44538fd1498Szrj tree
do_poplevel(tree stmt_list)44638fd1498Szrj do_poplevel (tree stmt_list)
44738fd1498Szrj {
44838fd1498Szrj tree block = NULL;
44938fd1498Szrj
45038fd1498Szrj if (stmts_are_full_exprs_p ())
45138fd1498Szrj block = poplevel (kept_level_p (), 1, 0);
45238fd1498Szrj
45338fd1498Szrj stmt_list = pop_stmt_list (stmt_list);
45438fd1498Szrj
45538fd1498Szrj if (!processing_template_decl)
45638fd1498Szrj {
45738fd1498Szrj stmt_list = c_build_bind_expr (input_location, block, stmt_list);
45838fd1498Szrj /* ??? See c_end_compound_stmt re statement expressions. */
45938fd1498Szrj }
46038fd1498Szrj
46138fd1498Szrj return stmt_list;
46238fd1498Szrj }
46338fd1498Szrj
46438fd1498Szrj /* Begin a new scope. */
46538fd1498Szrj
46638fd1498Szrj static tree
do_pushlevel(scope_kind sk)46738fd1498Szrj do_pushlevel (scope_kind sk)
46838fd1498Szrj {
46938fd1498Szrj tree ret = push_stmt_list ();
47038fd1498Szrj if (stmts_are_full_exprs_p ())
47138fd1498Szrj begin_scope (sk, NULL);
47238fd1498Szrj return ret;
47338fd1498Szrj }
47438fd1498Szrj
47538fd1498Szrj /* Queue a cleanup. CLEANUP is an expression/statement to be executed
47638fd1498Szrj when the current scope is exited. EH_ONLY is true when this is not
47738fd1498Szrj meant to apply to normal control flow transfer. */
47838fd1498Szrj
47938fd1498Szrj void
push_cleanup(tree decl,tree cleanup,bool eh_only)48038fd1498Szrj push_cleanup (tree decl, tree cleanup, bool eh_only)
48138fd1498Szrj {
48238fd1498Szrj tree stmt = build_stmt (input_location, CLEANUP_STMT, NULL, cleanup, decl);
48338fd1498Szrj CLEANUP_EH_ONLY (stmt) = eh_only;
48438fd1498Szrj add_stmt (stmt);
48538fd1498Szrj CLEANUP_BODY (stmt) = push_stmt_list ();
48638fd1498Szrj }
48738fd1498Szrj
48838fd1498Szrj /* Simple infinite loop tracking for -Wreturn-type. We keep a stack of all
48938fd1498Szrj the current loops, represented by 'NULL_TREE' if we've seen a possible
49038fd1498Szrj exit, and 'error_mark_node' if not. This is currently used only to
49138fd1498Szrj suppress the warning about a function with no return statements, and
49238fd1498Szrj therefore we don't bother noting returns as possible exits. We also
49338fd1498Szrj don't bother with gotos. */
49438fd1498Szrj
49538fd1498Szrj static void
begin_maybe_infinite_loop(tree cond)49638fd1498Szrj begin_maybe_infinite_loop (tree cond)
49738fd1498Szrj {
49838fd1498Szrj /* Only track this while parsing a function, not during instantiation. */
49938fd1498Szrj if (!cfun || (DECL_TEMPLATE_INSTANTIATION (current_function_decl)
50038fd1498Szrj && !processing_template_decl))
50138fd1498Szrj return;
50238fd1498Szrj bool maybe_infinite = true;
50338fd1498Szrj if (cond)
50438fd1498Szrj {
50538fd1498Szrj cond = fold_non_dependent_expr (cond);
50638fd1498Szrj maybe_infinite = integer_nonzerop (cond);
50738fd1498Szrj }
50838fd1498Szrj vec_safe_push (cp_function_chain->infinite_loops,
50938fd1498Szrj maybe_infinite ? error_mark_node : NULL_TREE);
51038fd1498Szrj
51138fd1498Szrj }
51238fd1498Szrj
51338fd1498Szrj /* A break is a possible exit for the current loop. */
51438fd1498Szrj
51538fd1498Szrj void
break_maybe_infinite_loop(void)51638fd1498Szrj break_maybe_infinite_loop (void)
51738fd1498Szrj {
51838fd1498Szrj if (!cfun)
51938fd1498Szrj return;
52038fd1498Szrj cp_function_chain->infinite_loops->last() = NULL_TREE;
52138fd1498Szrj }
52238fd1498Szrj
52338fd1498Szrj /* If we reach the end of the loop without seeing a possible exit, we have
52438fd1498Szrj an infinite loop. */
52538fd1498Szrj
52638fd1498Szrj static void
end_maybe_infinite_loop(tree cond)52738fd1498Szrj end_maybe_infinite_loop (tree cond)
52838fd1498Szrj {
52938fd1498Szrj if (!cfun || (DECL_TEMPLATE_INSTANTIATION (current_function_decl)
53038fd1498Szrj && !processing_template_decl))
53138fd1498Szrj return;
53238fd1498Szrj tree current = cp_function_chain->infinite_loops->pop();
53338fd1498Szrj if (current != NULL_TREE)
53438fd1498Szrj {
53538fd1498Szrj cond = fold_non_dependent_expr (cond);
53638fd1498Szrj if (integer_nonzerop (cond))
53738fd1498Szrj current_function_infinite_loop = 1;
53838fd1498Szrj }
53938fd1498Szrj }
54038fd1498Szrj
54138fd1498Szrj
54238fd1498Szrj /* Begin a conditional that might contain a declaration. When generating
54338fd1498Szrj normal code, we want the declaration to appear before the statement
54438fd1498Szrj containing the conditional. When generating template code, we want the
54538fd1498Szrj conditional to be rendered as the raw DECL_EXPR. */
54638fd1498Szrj
54738fd1498Szrj static void
begin_cond(tree * cond_p)54838fd1498Szrj begin_cond (tree *cond_p)
54938fd1498Szrj {
55038fd1498Szrj if (processing_template_decl)
55138fd1498Szrj *cond_p = push_stmt_list ();
55238fd1498Szrj }
55338fd1498Szrj
55438fd1498Szrj /* Finish such a conditional. */
55538fd1498Szrj
55638fd1498Szrj static void
finish_cond(tree * cond_p,tree expr)55738fd1498Szrj finish_cond (tree *cond_p, tree expr)
55838fd1498Szrj {
55938fd1498Szrj if (processing_template_decl)
56038fd1498Szrj {
56138fd1498Szrj tree cond = pop_stmt_list (*cond_p);
56238fd1498Szrj
56338fd1498Szrj if (expr == NULL_TREE)
56438fd1498Szrj /* Empty condition in 'for'. */
56538fd1498Szrj gcc_assert (empty_expr_stmt_p (cond));
56638fd1498Szrj else if (check_for_bare_parameter_packs (expr))
56738fd1498Szrj expr = error_mark_node;
56838fd1498Szrj else if (!empty_expr_stmt_p (cond))
56938fd1498Szrj expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), cond, expr);
57038fd1498Szrj }
57138fd1498Szrj *cond_p = expr;
57238fd1498Szrj }
57338fd1498Szrj
57438fd1498Szrj /* If *COND_P specifies a conditional with a declaration, transform the
57538fd1498Szrj loop such that
57638fd1498Szrj while (A x = 42) { }
57738fd1498Szrj for (; A x = 42;) { }
57838fd1498Szrj becomes
57938fd1498Szrj while (true) { A x = 42; if (!x) break; }
58038fd1498Szrj for (;;) { A x = 42; if (!x) break; }
58138fd1498Szrj The statement list for BODY will be empty if the conditional did
58238fd1498Szrj not declare anything. */
58338fd1498Szrj
58438fd1498Szrj static void
simplify_loop_decl_cond(tree * cond_p,tree body)58538fd1498Szrj simplify_loop_decl_cond (tree *cond_p, tree body)
58638fd1498Szrj {
58738fd1498Szrj tree cond, if_stmt;
58838fd1498Szrj
58938fd1498Szrj if (!TREE_SIDE_EFFECTS (body))
59038fd1498Szrj return;
59138fd1498Szrj
59238fd1498Szrj cond = *cond_p;
59338fd1498Szrj *cond_p = boolean_true_node;
59438fd1498Szrj
59538fd1498Szrj if_stmt = begin_if_stmt ();
59638fd1498Szrj cond = cp_build_unary_op (TRUTH_NOT_EXPR, cond, false, tf_warning_or_error);
59738fd1498Szrj finish_if_stmt_cond (cond, if_stmt);
59838fd1498Szrj finish_break_stmt ();
59938fd1498Szrj finish_then_clause (if_stmt);
60038fd1498Szrj finish_if_stmt (if_stmt);
60138fd1498Szrj }
60238fd1498Szrj
60338fd1498Szrj /* Finish a goto-statement. */
60438fd1498Szrj
60538fd1498Szrj tree
finish_goto_stmt(tree destination)60638fd1498Szrj finish_goto_stmt (tree destination)
60738fd1498Szrj {
60838fd1498Szrj if (identifier_p (destination))
60938fd1498Szrj destination = lookup_label (destination);
61038fd1498Szrj
61138fd1498Szrj /* We warn about unused labels with -Wunused. That means we have to
61238fd1498Szrj mark the used labels as used. */
61338fd1498Szrj if (TREE_CODE (destination) == LABEL_DECL)
61438fd1498Szrj TREE_USED (destination) = 1;
61538fd1498Szrj else
61638fd1498Szrj {
61738fd1498Szrj destination = mark_rvalue_use (destination);
61838fd1498Szrj if (!processing_template_decl)
61938fd1498Szrj {
62038fd1498Szrj destination = cp_convert (ptr_type_node, destination,
62138fd1498Szrj tf_warning_or_error);
62238fd1498Szrj if (error_operand_p (destination))
62338fd1498Szrj return NULL_TREE;
62438fd1498Szrj destination
62538fd1498Szrj = fold_build_cleanup_point_expr (TREE_TYPE (destination),
62638fd1498Szrj destination);
62738fd1498Szrj }
62838fd1498Szrj }
62938fd1498Szrj
63038fd1498Szrj check_goto (destination);
63138fd1498Szrj
63238fd1498Szrj add_stmt (build_predict_expr (PRED_GOTO, NOT_TAKEN));
63338fd1498Szrj return add_stmt (build_stmt (input_location, GOTO_EXPR, destination));
63438fd1498Szrj }
63538fd1498Szrj
63638fd1498Szrj /* COND is the condition-expression for an if, while, etc.,
63738fd1498Szrj statement. Convert it to a boolean value, if appropriate.
63838fd1498Szrj In addition, verify sequence points if -Wsequence-point is enabled. */
63938fd1498Szrj
64038fd1498Szrj static tree
maybe_convert_cond(tree cond)64138fd1498Szrj maybe_convert_cond (tree cond)
64238fd1498Szrj {
64338fd1498Szrj /* Empty conditions remain empty. */
64438fd1498Szrj if (!cond)
64538fd1498Szrj return NULL_TREE;
64638fd1498Szrj
64738fd1498Szrj /* Wait until we instantiate templates before doing conversion. */
648*e215fc28Szrj if (processing_template_decl
649*e215fc28Szrj && (type_dependent_expression_p (cond)
650*e215fc28Szrj /* For GCC 8 only convert non-dependent condition in a lambda. */
651*e215fc28Szrj || !current_lambda_expr ()))
65238fd1498Szrj return cond;
65338fd1498Szrj
654*e215fc28Szrj if (warn_sequence_point && !processing_template_decl)
65538fd1498Szrj verify_sequence_points (cond);
65638fd1498Szrj
65738fd1498Szrj /* Do the conversion. */
65838fd1498Szrj cond = convert_from_reference (cond);
65938fd1498Szrj
66038fd1498Szrj if (TREE_CODE (cond) == MODIFY_EXPR
66138fd1498Szrj && !TREE_NO_WARNING (cond)
66238fd1498Szrj && warn_parentheses)
66338fd1498Szrj {
66438fd1498Szrj warning_at (EXPR_LOC_OR_LOC (cond, input_location), OPT_Wparentheses,
66538fd1498Szrj "suggest parentheses around assignment used as truth value");
66638fd1498Szrj TREE_NO_WARNING (cond) = 1;
66738fd1498Szrj }
66838fd1498Szrj
66938fd1498Szrj return condition_conversion (cond);
67038fd1498Szrj }
67138fd1498Szrj
67238fd1498Szrj /* Finish an expression-statement, whose EXPRESSION is as indicated. */
67338fd1498Szrj
67438fd1498Szrj tree
finish_expr_stmt(tree expr)67538fd1498Szrj finish_expr_stmt (tree expr)
67638fd1498Szrj {
67738fd1498Szrj tree r = NULL_TREE;
67838fd1498Szrj location_t loc = EXPR_LOCATION (expr);
67938fd1498Szrj
68038fd1498Szrj if (expr != NULL_TREE)
68138fd1498Szrj {
68238fd1498Szrj /* If we ran into a problem, make sure we complained. */
68338fd1498Szrj gcc_assert (expr != error_mark_node || seen_error ());
68438fd1498Szrj
68538fd1498Szrj if (!processing_template_decl)
68638fd1498Szrj {
68738fd1498Szrj if (warn_sequence_point)
68838fd1498Szrj verify_sequence_points (expr);
68938fd1498Szrj expr = convert_to_void (expr, ICV_STATEMENT, tf_warning_or_error);
69038fd1498Szrj }
69138fd1498Szrj else if (!type_dependent_expression_p (expr))
69238fd1498Szrj convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT,
69338fd1498Szrj tf_warning_or_error);
69438fd1498Szrj
69538fd1498Szrj if (check_for_bare_parameter_packs (expr))
69638fd1498Szrj expr = error_mark_node;
69738fd1498Szrj
69838fd1498Szrj /* Simplification of inner statement expressions, compound exprs,
69938fd1498Szrj etc can result in us already having an EXPR_STMT. */
70038fd1498Szrj if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
70138fd1498Szrj {
70238fd1498Szrj if (TREE_CODE (expr) != EXPR_STMT)
70338fd1498Szrj expr = build_stmt (loc, EXPR_STMT, expr);
70438fd1498Szrj expr = maybe_cleanup_point_expr_void (expr);
70538fd1498Szrj }
70638fd1498Szrj
70738fd1498Szrj r = add_stmt (expr);
70838fd1498Szrj }
70938fd1498Szrj
71038fd1498Szrj return r;
71138fd1498Szrj }
71238fd1498Szrj
71338fd1498Szrj
71438fd1498Szrj /* Begin an if-statement. Returns a newly created IF_STMT if
71538fd1498Szrj appropriate. */
71638fd1498Szrj
71738fd1498Szrj tree
begin_if_stmt(void)71838fd1498Szrj begin_if_stmt (void)
71938fd1498Szrj {
72038fd1498Szrj tree r, scope;
72138fd1498Szrj scope = do_pushlevel (sk_cond);
72238fd1498Szrj r = build_stmt (input_location, IF_STMT, NULL_TREE,
72338fd1498Szrj NULL_TREE, NULL_TREE, scope);
72438fd1498Szrj current_binding_level->this_entity = r;
72538fd1498Szrj begin_cond (&IF_COND (r));
72638fd1498Szrj return r;
72738fd1498Szrj }
72838fd1498Szrj
72938fd1498Szrj /* Process the COND of an if-statement, which may be given by
73038fd1498Szrj IF_STMT. */
73138fd1498Szrj
73238fd1498Szrj tree
finish_if_stmt_cond(tree cond,tree if_stmt)73338fd1498Szrj finish_if_stmt_cond (tree cond, tree if_stmt)
73438fd1498Szrj {
73538fd1498Szrj cond = maybe_convert_cond (cond);
73638fd1498Szrj if (IF_STMT_CONSTEXPR_P (if_stmt)
73738fd1498Szrj && !type_dependent_expression_p (cond)
73838fd1498Szrj && require_constant_expression (cond)
73938fd1498Szrj && !instantiation_dependent_expression_p (cond)
74038fd1498Szrj /* Wait until instantiation time, since only then COND has been
74138fd1498Szrj converted to bool. */
74258e805e6Szrj && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node)
74338fd1498Szrj {
74438fd1498Szrj cond = instantiate_non_dependent_expr (cond);
74538fd1498Szrj cond = cxx_constant_value (cond, NULL_TREE);
74638fd1498Szrj }
74738fd1498Szrj finish_cond (&IF_COND (if_stmt), cond);
74838fd1498Szrj add_stmt (if_stmt);
74938fd1498Szrj THEN_CLAUSE (if_stmt) = push_stmt_list ();
75038fd1498Szrj return cond;
75138fd1498Szrj }
75238fd1498Szrj
75338fd1498Szrj /* Finish the then-clause of an if-statement, which may be given by
75438fd1498Szrj IF_STMT. */
75538fd1498Szrj
75638fd1498Szrj tree
finish_then_clause(tree if_stmt)75738fd1498Szrj finish_then_clause (tree if_stmt)
75838fd1498Szrj {
75938fd1498Szrj THEN_CLAUSE (if_stmt) = pop_stmt_list (THEN_CLAUSE (if_stmt));
76038fd1498Szrj return if_stmt;
76138fd1498Szrj }
76238fd1498Szrj
76338fd1498Szrj /* Begin the else-clause of an if-statement. */
76438fd1498Szrj
76538fd1498Szrj void
begin_else_clause(tree if_stmt)76638fd1498Szrj begin_else_clause (tree if_stmt)
76738fd1498Szrj {
76838fd1498Szrj ELSE_CLAUSE (if_stmt) = push_stmt_list ();
76938fd1498Szrj }
77038fd1498Szrj
77138fd1498Szrj /* Finish the else-clause of an if-statement, which may be given by
77238fd1498Szrj IF_STMT. */
77338fd1498Szrj
77438fd1498Szrj void
finish_else_clause(tree if_stmt)77538fd1498Szrj finish_else_clause (tree if_stmt)
77638fd1498Szrj {
77738fd1498Szrj ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt));
77838fd1498Szrj }
77938fd1498Szrj
78038fd1498Szrj /* Finish an if-statement. */
78138fd1498Szrj
78238fd1498Szrj void
finish_if_stmt(tree if_stmt)78338fd1498Szrj finish_if_stmt (tree if_stmt)
78438fd1498Szrj {
78538fd1498Szrj tree scope = IF_SCOPE (if_stmt);
78638fd1498Szrj IF_SCOPE (if_stmt) = NULL;
78738fd1498Szrj add_stmt (do_poplevel (scope));
78838fd1498Szrj }
78938fd1498Szrj
79038fd1498Szrj /* Begin a while-statement. Returns a newly created WHILE_STMT if
79138fd1498Szrj appropriate. */
79238fd1498Szrj
79338fd1498Szrj tree
begin_while_stmt(void)79438fd1498Szrj begin_while_stmt (void)
79538fd1498Szrj {
79638fd1498Szrj tree r;
79738fd1498Szrj r = build_stmt (input_location, WHILE_STMT, NULL_TREE, NULL_TREE);
79838fd1498Szrj add_stmt (r);
79938fd1498Szrj WHILE_BODY (r) = do_pushlevel (sk_block);
80038fd1498Szrj begin_cond (&WHILE_COND (r));
80138fd1498Szrj return r;
80238fd1498Szrj }
80338fd1498Szrj
80438fd1498Szrj /* Process the COND of a while-statement, which may be given by
80538fd1498Szrj WHILE_STMT. */
80638fd1498Szrj
80738fd1498Szrj void
finish_while_stmt_cond(tree cond,tree while_stmt,bool ivdep,unsigned short unroll)80838fd1498Szrj finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep,
80938fd1498Szrj unsigned short unroll)
81038fd1498Szrj {
81138fd1498Szrj cond = maybe_convert_cond (cond);
81238fd1498Szrj finish_cond (&WHILE_COND (while_stmt), cond);
81338fd1498Szrj begin_maybe_infinite_loop (cond);
81438fd1498Szrj if (ivdep && cond != error_mark_node)
81538fd1498Szrj WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR,
81638fd1498Szrj TREE_TYPE (WHILE_COND (while_stmt)),
81738fd1498Szrj WHILE_COND (while_stmt),
81838fd1498Szrj build_int_cst (integer_type_node,
81938fd1498Szrj annot_expr_ivdep_kind),
82038fd1498Szrj integer_zero_node);
82138fd1498Szrj if (unroll && cond != error_mark_node)
82238fd1498Szrj WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR,
82338fd1498Szrj TREE_TYPE (WHILE_COND (while_stmt)),
82438fd1498Szrj WHILE_COND (while_stmt),
82538fd1498Szrj build_int_cst (integer_type_node,
82638fd1498Szrj annot_expr_unroll_kind),
82738fd1498Szrj build_int_cst (integer_type_node,
82838fd1498Szrj unroll));
82938fd1498Szrj simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
83038fd1498Szrj }
83138fd1498Szrj
83238fd1498Szrj /* Finish a while-statement, which may be given by WHILE_STMT. */
83338fd1498Szrj
83438fd1498Szrj void
finish_while_stmt(tree while_stmt)83538fd1498Szrj finish_while_stmt (tree while_stmt)
83638fd1498Szrj {
83738fd1498Szrj end_maybe_infinite_loop (boolean_true_node);
83838fd1498Szrj WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt));
83938fd1498Szrj }
84038fd1498Szrj
84138fd1498Szrj /* Begin a do-statement. Returns a newly created DO_STMT if
84238fd1498Szrj appropriate. */
84338fd1498Szrj
84438fd1498Szrj tree
begin_do_stmt(void)84538fd1498Szrj begin_do_stmt (void)
84638fd1498Szrj {
84738fd1498Szrj tree r = build_stmt (input_location, DO_STMT, NULL_TREE, NULL_TREE);
84838fd1498Szrj begin_maybe_infinite_loop (boolean_true_node);
84938fd1498Szrj add_stmt (r);
85038fd1498Szrj DO_BODY (r) = push_stmt_list ();
85138fd1498Szrj return r;
85238fd1498Szrj }
85338fd1498Szrj
85438fd1498Szrj /* Finish the body of a do-statement, which may be given by DO_STMT. */
85538fd1498Szrj
85638fd1498Szrj void
finish_do_body(tree do_stmt)85738fd1498Szrj finish_do_body (tree do_stmt)
85838fd1498Szrj {
85938fd1498Szrj tree body = DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt));
86038fd1498Szrj
86138fd1498Szrj if (TREE_CODE (body) == STATEMENT_LIST && STATEMENT_LIST_TAIL (body))
86238fd1498Szrj body = STATEMENT_LIST_TAIL (body)->stmt;
86338fd1498Szrj
86438fd1498Szrj if (IS_EMPTY_STMT (body))
86538fd1498Szrj warning (OPT_Wempty_body,
86638fd1498Szrj "suggest explicit braces around empty body in %<do%> statement");
86738fd1498Szrj }
86838fd1498Szrj
86938fd1498Szrj /* Finish a do-statement, which may be given by DO_STMT, and whose
87038fd1498Szrj COND is as indicated. */
87138fd1498Szrj
87238fd1498Szrj void
finish_do_stmt(tree cond,tree do_stmt,bool ivdep,unsigned short unroll)87338fd1498Szrj finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll)
87438fd1498Szrj {
87538fd1498Szrj cond = maybe_convert_cond (cond);
87638fd1498Szrj end_maybe_infinite_loop (cond);
87738fd1498Szrj if (ivdep && cond != error_mark_node)
87838fd1498Szrj cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
87938fd1498Szrj build_int_cst (integer_type_node, annot_expr_ivdep_kind),
88038fd1498Szrj integer_zero_node);
88138fd1498Szrj if (unroll && cond != error_mark_node)
88238fd1498Szrj cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
88338fd1498Szrj build_int_cst (integer_type_node, annot_expr_unroll_kind),
88438fd1498Szrj build_int_cst (integer_type_node, unroll));
88538fd1498Szrj DO_COND (do_stmt) = cond;
88638fd1498Szrj }
88738fd1498Szrj
88838fd1498Szrj /* Finish a return-statement. The EXPRESSION returned, if any, is as
88938fd1498Szrj indicated. */
89038fd1498Szrj
89138fd1498Szrj tree
finish_return_stmt(tree expr)89238fd1498Szrj finish_return_stmt (tree expr)
89338fd1498Szrj {
89438fd1498Szrj tree r;
89538fd1498Szrj bool no_warning;
89638fd1498Szrj
89738fd1498Szrj expr = check_return_expr (expr, &no_warning);
89838fd1498Szrj
89938fd1498Szrj if (error_operand_p (expr)
90038fd1498Szrj || (flag_openmp && !check_omp_return ()))
90138fd1498Szrj {
90238fd1498Szrj /* Suppress -Wreturn-type for this function. */
90338fd1498Szrj if (warn_return_type)
90438fd1498Szrj TREE_NO_WARNING (current_function_decl) = true;
90538fd1498Szrj return error_mark_node;
90638fd1498Szrj }
90738fd1498Szrj
90838fd1498Szrj if (!processing_template_decl)
90938fd1498Szrj {
91038fd1498Szrj if (warn_sequence_point)
91138fd1498Szrj verify_sequence_points (expr);
91238fd1498Szrj
91338fd1498Szrj if (DECL_DESTRUCTOR_P (current_function_decl)
91438fd1498Szrj || (DECL_CONSTRUCTOR_P (current_function_decl)
91538fd1498Szrj && targetm.cxx.cdtor_returns_this ()))
91638fd1498Szrj {
91738fd1498Szrj /* Similarly, all destructors must run destructors for
91838fd1498Szrj base-classes before returning. So, all returns in a
91938fd1498Szrj destructor get sent to the DTOR_LABEL; finish_function emits
92038fd1498Szrj code to return a value there. */
92138fd1498Szrj return finish_goto_stmt (cdtor_label);
92238fd1498Szrj }
92338fd1498Szrj }
92438fd1498Szrj
92538fd1498Szrj r = build_stmt (input_location, RETURN_EXPR, expr);
92638fd1498Szrj TREE_NO_WARNING (r) |= no_warning;
92738fd1498Szrj r = maybe_cleanup_point_expr_void (r);
92838fd1498Szrj r = add_stmt (r);
92938fd1498Szrj
93038fd1498Szrj return r;
93138fd1498Szrj }
93238fd1498Szrj
93338fd1498Szrj /* Begin the scope of a for-statement or a range-for-statement.
93438fd1498Szrj Both the returned trees are to be used in a call to
93538fd1498Szrj begin_for_stmt or begin_range_for_stmt. */
93638fd1498Szrj
93738fd1498Szrj tree
begin_for_scope(tree * init)93838fd1498Szrj begin_for_scope (tree *init)
93938fd1498Szrj {
94038fd1498Szrj tree scope = NULL_TREE;
94138fd1498Szrj if (flag_new_for_scope)
94238fd1498Szrj scope = do_pushlevel (sk_for);
94338fd1498Szrj
94438fd1498Szrj if (processing_template_decl)
94538fd1498Szrj *init = push_stmt_list ();
94638fd1498Szrj else
94738fd1498Szrj *init = NULL_TREE;
94838fd1498Szrj
94938fd1498Szrj return scope;
95038fd1498Szrj }
95138fd1498Szrj
95238fd1498Szrj /* Begin a for-statement. Returns a new FOR_STMT.
95338fd1498Szrj SCOPE and INIT should be the return of begin_for_scope,
95438fd1498Szrj or both NULL_TREE */
95538fd1498Szrj
95638fd1498Szrj tree
begin_for_stmt(tree scope,tree init)95738fd1498Szrj begin_for_stmt (tree scope, tree init)
95838fd1498Szrj {
95938fd1498Szrj tree r;
96038fd1498Szrj
96138fd1498Szrj r = build_stmt (input_location, FOR_STMT, NULL_TREE, NULL_TREE,
96238fd1498Szrj NULL_TREE, NULL_TREE, NULL_TREE);
96338fd1498Szrj
96438fd1498Szrj if (scope == NULL_TREE)
96538fd1498Szrj {
96638fd1498Szrj gcc_assert (!init || !flag_new_for_scope);
96738fd1498Szrj if (!init)
96838fd1498Szrj scope = begin_for_scope (&init);
96938fd1498Szrj }
97038fd1498Szrj FOR_INIT_STMT (r) = init;
97138fd1498Szrj FOR_SCOPE (r) = scope;
97238fd1498Szrj
97338fd1498Szrj return r;
97438fd1498Szrj }
97538fd1498Szrj
97638fd1498Szrj /* Finish the init-statement of a for-statement, which may be
97738fd1498Szrj given by FOR_STMT. */
97838fd1498Szrj
97938fd1498Szrj void
finish_init_stmt(tree for_stmt)98038fd1498Szrj finish_init_stmt (tree for_stmt)
98138fd1498Szrj {
98238fd1498Szrj if (processing_template_decl)
98338fd1498Szrj FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt));
98438fd1498Szrj add_stmt (for_stmt);
98538fd1498Szrj FOR_BODY (for_stmt) = do_pushlevel (sk_block);
98638fd1498Szrj begin_cond (&FOR_COND (for_stmt));
98738fd1498Szrj }
98838fd1498Szrj
98938fd1498Szrj /* Finish the COND of a for-statement, which may be given by
99038fd1498Szrj FOR_STMT. */
99138fd1498Szrj
99238fd1498Szrj void
finish_for_cond(tree cond,tree for_stmt,bool ivdep,unsigned short unroll)99338fd1498Szrj finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll)
99438fd1498Szrj {
99538fd1498Szrj cond = maybe_convert_cond (cond);
99638fd1498Szrj finish_cond (&FOR_COND (for_stmt), cond);
99738fd1498Szrj begin_maybe_infinite_loop (cond);
99838fd1498Szrj if (ivdep && cond != error_mark_node)
99938fd1498Szrj FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR,
100038fd1498Szrj TREE_TYPE (FOR_COND (for_stmt)),
100138fd1498Szrj FOR_COND (for_stmt),
100238fd1498Szrj build_int_cst (integer_type_node,
100338fd1498Szrj annot_expr_ivdep_kind),
100438fd1498Szrj integer_zero_node);
100538fd1498Szrj if (unroll && cond != error_mark_node)
100638fd1498Szrj FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR,
100738fd1498Szrj TREE_TYPE (FOR_COND (for_stmt)),
100838fd1498Szrj FOR_COND (for_stmt),
100938fd1498Szrj build_int_cst (integer_type_node,
101038fd1498Szrj annot_expr_unroll_kind),
101138fd1498Szrj build_int_cst (integer_type_node,
101238fd1498Szrj unroll));
101338fd1498Szrj simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
101438fd1498Szrj }
101538fd1498Szrj
101638fd1498Szrj /* Finish the increment-EXPRESSION in a for-statement, which may be
101738fd1498Szrj given by FOR_STMT. */
101838fd1498Szrj
101938fd1498Szrj void
finish_for_expr(tree expr,tree for_stmt)102038fd1498Szrj finish_for_expr (tree expr, tree for_stmt)
102138fd1498Szrj {
102238fd1498Szrj if (!expr)
102338fd1498Szrj return;
102438fd1498Szrj /* If EXPR is an overloaded function, issue an error; there is no
102538fd1498Szrj context available to use to perform overload resolution. */
102638fd1498Szrj if (type_unknown_p (expr))
102738fd1498Szrj {
102838fd1498Szrj cxx_incomplete_type_error (expr, TREE_TYPE (expr));
102938fd1498Szrj expr = error_mark_node;
103038fd1498Szrj }
103138fd1498Szrj if (!processing_template_decl)
103238fd1498Szrj {
103338fd1498Szrj if (warn_sequence_point)
103438fd1498Szrj verify_sequence_points (expr);
103538fd1498Szrj expr = convert_to_void (expr, ICV_THIRD_IN_FOR,
103638fd1498Szrj tf_warning_or_error);
103738fd1498Szrj }
103838fd1498Szrj else if (!type_dependent_expression_p (expr))
103938fd1498Szrj convert_to_void (build_non_dependent_expr (expr), ICV_THIRD_IN_FOR,
104038fd1498Szrj tf_warning_or_error);
104138fd1498Szrj expr = maybe_cleanup_point_expr_void (expr);
104238fd1498Szrj if (check_for_bare_parameter_packs (expr))
104338fd1498Szrj expr = error_mark_node;
104438fd1498Szrj FOR_EXPR (for_stmt) = expr;
104538fd1498Szrj }
104638fd1498Szrj
104738fd1498Szrj /* Finish the body of a for-statement, which may be given by
104838fd1498Szrj FOR_STMT. The increment-EXPR for the loop must be
104938fd1498Szrj provided.
105038fd1498Szrj It can also finish RANGE_FOR_STMT. */
105138fd1498Szrj
105238fd1498Szrj void
finish_for_stmt(tree for_stmt)105338fd1498Szrj finish_for_stmt (tree for_stmt)
105438fd1498Szrj {
105538fd1498Szrj end_maybe_infinite_loop (boolean_true_node);
105638fd1498Szrj
105738fd1498Szrj if (TREE_CODE (for_stmt) == RANGE_FOR_STMT)
105838fd1498Szrj RANGE_FOR_BODY (for_stmt) = do_poplevel (RANGE_FOR_BODY (for_stmt));
105938fd1498Szrj else
106038fd1498Szrj FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt));
106138fd1498Szrj
106238fd1498Szrj /* Pop the scope for the body of the loop. */
106338fd1498Szrj if (flag_new_for_scope)
106438fd1498Szrj {
106538fd1498Szrj tree scope;
106638fd1498Szrj tree *scope_ptr = (TREE_CODE (for_stmt) == RANGE_FOR_STMT
106738fd1498Szrj ? &RANGE_FOR_SCOPE (for_stmt)
106838fd1498Szrj : &FOR_SCOPE (for_stmt));
106938fd1498Szrj scope = *scope_ptr;
107038fd1498Szrj *scope_ptr = NULL;
107138fd1498Szrj add_stmt (do_poplevel (scope));
107238fd1498Szrj }
107338fd1498Szrj }
107438fd1498Szrj
107538fd1498Szrj /* Begin a range-for-statement. Returns a new RANGE_FOR_STMT.
107638fd1498Szrj SCOPE and INIT should be the return of begin_for_scope,
107738fd1498Szrj or both NULL_TREE .
107838fd1498Szrj To finish it call finish_for_stmt(). */
107938fd1498Szrj
108038fd1498Szrj tree
begin_range_for_stmt(tree scope,tree init)108138fd1498Szrj begin_range_for_stmt (tree scope, tree init)
108238fd1498Szrj {
108338fd1498Szrj tree r;
108438fd1498Szrj
108538fd1498Szrj begin_maybe_infinite_loop (boolean_false_node);
108638fd1498Szrj
108738fd1498Szrj r = build_stmt (input_location, RANGE_FOR_STMT,
108838fd1498Szrj NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
108938fd1498Szrj
109038fd1498Szrj if (scope == NULL_TREE)
109138fd1498Szrj {
109238fd1498Szrj gcc_assert (!init || !flag_new_for_scope);
109338fd1498Szrj if (!init)
109438fd1498Szrj scope = begin_for_scope (&init);
109538fd1498Szrj }
109638fd1498Szrj
109738fd1498Szrj /* RANGE_FOR_STMTs do not use nor save the init tree, so we
109838fd1498Szrj pop it now. */
109938fd1498Szrj if (init)
110038fd1498Szrj pop_stmt_list (init);
110138fd1498Szrj RANGE_FOR_SCOPE (r) = scope;
110238fd1498Szrj
110338fd1498Szrj return r;
110438fd1498Szrj }
110538fd1498Szrj
110638fd1498Szrj /* Finish the head of a range-based for statement, which may
110738fd1498Szrj be given by RANGE_FOR_STMT. DECL must be the declaration
110838fd1498Szrj and EXPR must be the loop expression. */
110938fd1498Szrj
111038fd1498Szrj void
finish_range_for_decl(tree range_for_stmt,tree decl,tree expr)111138fd1498Szrj finish_range_for_decl (tree range_for_stmt, tree decl, tree expr)
111238fd1498Szrj {
111338fd1498Szrj RANGE_FOR_DECL (range_for_stmt) = decl;
111438fd1498Szrj RANGE_FOR_EXPR (range_for_stmt) = expr;
111538fd1498Szrj add_stmt (range_for_stmt);
111638fd1498Szrj RANGE_FOR_BODY (range_for_stmt) = do_pushlevel (sk_block);
111738fd1498Szrj }
111838fd1498Szrj
111938fd1498Szrj /* Finish a break-statement. */
112038fd1498Szrj
112138fd1498Szrj tree
finish_break_stmt(void)112238fd1498Szrj finish_break_stmt (void)
112338fd1498Szrj {
112438fd1498Szrj /* In switch statements break is sometimes stylistically used after
112538fd1498Szrj a return statement. This can lead to spurious warnings about
112638fd1498Szrj control reaching the end of a non-void function when it is
112738fd1498Szrj inlined. Note that we are calling block_may_fallthru with
112838fd1498Szrj language specific tree nodes; this works because
112938fd1498Szrj block_may_fallthru returns true when given something it does not
113038fd1498Szrj understand. */
113138fd1498Szrj if (!block_may_fallthru (cur_stmt_list))
113238fd1498Szrj return void_node;
113338fd1498Szrj note_break_stmt ();
113438fd1498Szrj return add_stmt (build_stmt (input_location, BREAK_STMT));
113538fd1498Szrj }
113638fd1498Szrj
113738fd1498Szrj /* Finish a continue-statement. */
113838fd1498Szrj
113938fd1498Szrj tree
finish_continue_stmt(void)114038fd1498Szrj finish_continue_stmt (void)
114138fd1498Szrj {
114238fd1498Szrj return add_stmt (build_stmt (input_location, CONTINUE_STMT));
114338fd1498Szrj }
114438fd1498Szrj
114538fd1498Szrj /* Begin a switch-statement. Returns a new SWITCH_STMT if
114638fd1498Szrj appropriate. */
114738fd1498Szrj
114838fd1498Szrj tree
begin_switch_stmt(void)114938fd1498Szrj begin_switch_stmt (void)
115038fd1498Szrj {
115138fd1498Szrj tree r, scope;
115238fd1498Szrj
115338fd1498Szrj scope = do_pushlevel (sk_cond);
115438fd1498Szrj r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE, scope);
115538fd1498Szrj
115638fd1498Szrj begin_cond (&SWITCH_STMT_COND (r));
115738fd1498Szrj
115838fd1498Szrj return r;
115938fd1498Szrj }
116038fd1498Szrj
116138fd1498Szrj /* Finish the cond of a switch-statement. */
116238fd1498Szrj
116338fd1498Szrj void
finish_switch_cond(tree cond,tree switch_stmt)116438fd1498Szrj finish_switch_cond (tree cond, tree switch_stmt)
116538fd1498Szrj {
116638fd1498Szrj tree orig_type = NULL;
116738fd1498Szrj
116838fd1498Szrj if (!processing_template_decl)
116938fd1498Szrj {
117038fd1498Szrj /* Convert the condition to an integer or enumeration type. */
117138fd1498Szrj cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true);
117238fd1498Szrj if (cond == NULL_TREE)
117338fd1498Szrj {
117438fd1498Szrj error ("switch quantity not an integer");
117538fd1498Szrj cond = error_mark_node;
117638fd1498Szrj }
117738fd1498Szrj /* We want unlowered type here to handle enum bit-fields. */
117838fd1498Szrj orig_type = unlowered_expr_type (cond);
117938fd1498Szrj if (TREE_CODE (orig_type) != ENUMERAL_TYPE)
118038fd1498Szrj orig_type = TREE_TYPE (cond);
118138fd1498Szrj if (cond != error_mark_node)
118238fd1498Szrj {
118338fd1498Szrj /* [stmt.switch]
118438fd1498Szrj
118538fd1498Szrj Integral promotions are performed. */
118638fd1498Szrj cond = perform_integral_promotions (cond);
118738fd1498Szrj cond = maybe_cleanup_point_expr (cond);
118838fd1498Szrj }
118938fd1498Szrj }
119038fd1498Szrj if (check_for_bare_parameter_packs (cond))
119138fd1498Szrj cond = error_mark_node;
119238fd1498Szrj else if (!processing_template_decl && warn_sequence_point)
119338fd1498Szrj verify_sequence_points (cond);
119438fd1498Szrj
119538fd1498Szrj finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
119638fd1498Szrj SWITCH_STMT_TYPE (switch_stmt) = orig_type;
119738fd1498Szrj add_stmt (switch_stmt);
119838fd1498Szrj push_switch (switch_stmt);
119938fd1498Szrj SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
120038fd1498Szrj }
120138fd1498Szrj
120238fd1498Szrj /* Finish the body of a switch-statement, which may be given by
120338fd1498Szrj SWITCH_STMT. The COND to switch on is indicated. */
120438fd1498Szrj
120538fd1498Szrj void
finish_switch_stmt(tree switch_stmt)120638fd1498Szrj finish_switch_stmt (tree switch_stmt)
120738fd1498Szrj {
120838fd1498Szrj tree scope;
120938fd1498Szrj
121038fd1498Szrj SWITCH_STMT_BODY (switch_stmt) =
121138fd1498Szrj pop_stmt_list (SWITCH_STMT_BODY (switch_stmt));
121238fd1498Szrj pop_switch ();
121338fd1498Szrj
121438fd1498Szrj scope = SWITCH_STMT_SCOPE (switch_stmt);
121538fd1498Szrj SWITCH_STMT_SCOPE (switch_stmt) = NULL;
121638fd1498Szrj add_stmt (do_poplevel (scope));
121738fd1498Szrj }
121838fd1498Szrj
121938fd1498Szrj /* Begin a try-block. Returns a newly-created TRY_BLOCK if
122038fd1498Szrj appropriate. */
122138fd1498Szrj
122238fd1498Szrj tree
begin_try_block(void)122338fd1498Szrj begin_try_block (void)
122438fd1498Szrj {
122538fd1498Szrj tree r = build_stmt (input_location, TRY_BLOCK, NULL_TREE, NULL_TREE);
122638fd1498Szrj add_stmt (r);
122738fd1498Szrj TRY_STMTS (r) = push_stmt_list ();
122838fd1498Szrj return r;
122938fd1498Szrj }
123038fd1498Szrj
123138fd1498Szrj /* Likewise, for a function-try-block. The block returned in
123238fd1498Szrj *COMPOUND_STMT is an artificial outer scope, containing the
123338fd1498Szrj function-try-block. */
123438fd1498Szrj
123538fd1498Szrj tree
begin_function_try_block(tree * compound_stmt)123638fd1498Szrj begin_function_try_block (tree *compound_stmt)
123738fd1498Szrj {
123838fd1498Szrj tree r;
123938fd1498Szrj /* This outer scope does not exist in the C++ standard, but we need
124038fd1498Szrj a place to put __FUNCTION__ and similar variables. */
124138fd1498Szrj *compound_stmt = begin_compound_stmt (0);
124238fd1498Szrj r = begin_try_block ();
124338fd1498Szrj FN_TRY_BLOCK_P (r) = 1;
124438fd1498Szrj return r;
124538fd1498Szrj }
124638fd1498Szrj
124738fd1498Szrj /* Finish a try-block, which may be given by TRY_BLOCK. */
124838fd1498Szrj
124938fd1498Szrj void
finish_try_block(tree try_block)125038fd1498Szrj finish_try_block (tree try_block)
125138fd1498Szrj {
125238fd1498Szrj TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block));
125338fd1498Szrj TRY_HANDLERS (try_block) = push_stmt_list ();
125438fd1498Szrj }
125538fd1498Szrj
125638fd1498Szrj /* Finish the body of a cleanup try-block, which may be given by
125738fd1498Szrj TRY_BLOCK. */
125838fd1498Szrj
125938fd1498Szrj void
finish_cleanup_try_block(tree try_block)126038fd1498Szrj finish_cleanup_try_block (tree try_block)
126138fd1498Szrj {
126238fd1498Szrj TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block));
126338fd1498Szrj }
126438fd1498Szrj
126538fd1498Szrj /* Finish an implicitly generated try-block, with a cleanup is given
126638fd1498Szrj by CLEANUP. */
126738fd1498Szrj
126838fd1498Szrj void
finish_cleanup(tree cleanup,tree try_block)126938fd1498Szrj finish_cleanup (tree cleanup, tree try_block)
127038fd1498Szrj {
127138fd1498Szrj TRY_HANDLERS (try_block) = cleanup;
127238fd1498Szrj CLEANUP_P (try_block) = 1;
127338fd1498Szrj }
127438fd1498Szrj
127538fd1498Szrj /* Likewise, for a function-try-block. */
127638fd1498Szrj
127738fd1498Szrj void
finish_function_try_block(tree try_block)127838fd1498Szrj finish_function_try_block (tree try_block)
127938fd1498Szrj {
128038fd1498Szrj finish_try_block (try_block);
128138fd1498Szrj /* FIXME : something queer about CTOR_INITIALIZER somehow following
128238fd1498Szrj the try block, but moving it inside. */
128338fd1498Szrj in_function_try_handler = 1;
128438fd1498Szrj }
128538fd1498Szrj
128638fd1498Szrj /* Finish a handler-sequence for a try-block, which may be given by
128738fd1498Szrj TRY_BLOCK. */
128838fd1498Szrj
128938fd1498Szrj void
finish_handler_sequence(tree try_block)129038fd1498Szrj finish_handler_sequence (tree try_block)
129138fd1498Szrj {
129238fd1498Szrj TRY_HANDLERS (try_block) = pop_stmt_list (TRY_HANDLERS (try_block));
129338fd1498Szrj check_handlers (TRY_HANDLERS (try_block));
129438fd1498Szrj }
129538fd1498Szrj
129638fd1498Szrj /* Finish the handler-seq for a function-try-block, given by
129738fd1498Szrj TRY_BLOCK. COMPOUND_STMT is the outer block created by
129838fd1498Szrj begin_function_try_block. */
129938fd1498Szrj
130038fd1498Szrj void
finish_function_handler_sequence(tree try_block,tree compound_stmt)130138fd1498Szrj finish_function_handler_sequence (tree try_block, tree compound_stmt)
130238fd1498Szrj {
130338fd1498Szrj in_function_try_handler = 0;
130438fd1498Szrj finish_handler_sequence (try_block);
130538fd1498Szrj finish_compound_stmt (compound_stmt);
130638fd1498Szrj }
130738fd1498Szrj
130838fd1498Szrj /* Begin a handler. Returns a HANDLER if appropriate. */
130938fd1498Szrj
131038fd1498Szrj tree
begin_handler(void)131138fd1498Szrj begin_handler (void)
131238fd1498Szrj {
131338fd1498Szrj tree r;
131438fd1498Szrj
131538fd1498Szrj r = build_stmt (input_location, HANDLER, NULL_TREE, NULL_TREE);
131638fd1498Szrj add_stmt (r);
131738fd1498Szrj
131838fd1498Szrj /* Create a binding level for the eh_info and the exception object
131938fd1498Szrj cleanup. */
132038fd1498Szrj HANDLER_BODY (r) = do_pushlevel (sk_catch);
132138fd1498Szrj
132238fd1498Szrj return r;
132338fd1498Szrj }
132438fd1498Szrj
132538fd1498Szrj /* Finish the handler-parameters for a handler, which may be given by
132638fd1498Szrj HANDLER. DECL is the declaration for the catch parameter, or NULL
132738fd1498Szrj if this is a `catch (...)' clause. */
132838fd1498Szrj
132938fd1498Szrj void
finish_handler_parms(tree decl,tree handler)133038fd1498Szrj finish_handler_parms (tree decl, tree handler)
133138fd1498Szrj {
133238fd1498Szrj tree type = NULL_TREE;
133338fd1498Szrj if (processing_template_decl)
133438fd1498Szrj {
133538fd1498Szrj if (decl)
133638fd1498Szrj {
133738fd1498Szrj decl = pushdecl (decl);
133838fd1498Szrj decl = push_template_decl (decl);
133938fd1498Szrj HANDLER_PARMS (handler) = decl;
134038fd1498Szrj type = TREE_TYPE (decl);
134138fd1498Szrj }
134238fd1498Szrj }
134338fd1498Szrj else
134438fd1498Szrj {
134538fd1498Szrj type = expand_start_catch_block (decl);
134638fd1498Szrj if (warn_catch_value
134738fd1498Szrj && type != NULL_TREE
134838fd1498Szrj && type != error_mark_node
134938fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE)
135038fd1498Szrj {
135138fd1498Szrj tree orig_type = TREE_TYPE (decl);
135238fd1498Szrj if (CLASS_TYPE_P (orig_type))
135338fd1498Szrj {
135438fd1498Szrj if (TYPE_POLYMORPHIC_P (orig_type))
135538fd1498Szrj warning (OPT_Wcatch_value_,
135638fd1498Szrj "catching polymorphic type %q#T by value", orig_type);
135738fd1498Szrj else if (warn_catch_value > 1)
135838fd1498Szrj warning (OPT_Wcatch_value_,
135938fd1498Szrj "catching type %q#T by value", orig_type);
136038fd1498Szrj }
136138fd1498Szrj else if (warn_catch_value > 2)
136238fd1498Szrj warning (OPT_Wcatch_value_,
136338fd1498Szrj "catching non-reference type %q#T", orig_type);
136438fd1498Szrj }
136538fd1498Szrj }
136638fd1498Szrj HANDLER_TYPE (handler) = type;
136738fd1498Szrj }
136838fd1498Szrj
136938fd1498Szrj /* Finish a handler, which may be given by HANDLER. The BLOCKs are
137038fd1498Szrj the return value from the matching call to finish_handler_parms. */
137138fd1498Szrj
137238fd1498Szrj void
finish_handler(tree handler)137338fd1498Szrj finish_handler (tree handler)
137438fd1498Szrj {
137538fd1498Szrj if (!processing_template_decl)
137638fd1498Szrj expand_end_catch_block ();
137738fd1498Szrj HANDLER_BODY (handler) = do_poplevel (HANDLER_BODY (handler));
137838fd1498Szrj }
137938fd1498Szrj
138038fd1498Szrj /* Begin a compound statement. FLAGS contains some bits that control the
138138fd1498Szrj behavior and context. If BCS_NO_SCOPE is set, the compound statement
138238fd1498Szrj does not define a scope. If BCS_FN_BODY is set, this is the outermost
138338fd1498Szrj block of a function. If BCS_TRY_BLOCK is set, this is the block
138438fd1498Szrj created on behalf of a TRY statement. Returns a token to be passed to
138538fd1498Szrj finish_compound_stmt. */
138638fd1498Szrj
138738fd1498Szrj tree
begin_compound_stmt(unsigned int flags)138838fd1498Szrj begin_compound_stmt (unsigned int flags)
138938fd1498Szrj {
139038fd1498Szrj tree r;
139138fd1498Szrj
139238fd1498Szrj if (flags & BCS_NO_SCOPE)
139338fd1498Szrj {
139438fd1498Szrj r = push_stmt_list ();
139538fd1498Szrj STATEMENT_LIST_NO_SCOPE (r) = 1;
139638fd1498Szrj
139738fd1498Szrj /* Normally, we try hard to keep the BLOCK for a statement-expression.
139838fd1498Szrj But, if it's a statement-expression with a scopeless block, there's
139938fd1498Szrj nothing to keep, and we don't want to accidentally keep a block
140038fd1498Szrj *inside* the scopeless block. */
140138fd1498Szrj keep_next_level (false);
140238fd1498Szrj }
140338fd1498Szrj else
140438fd1498Szrj {
140538fd1498Szrj scope_kind sk = sk_block;
140638fd1498Szrj if (flags & BCS_TRY_BLOCK)
140738fd1498Szrj sk = sk_try;
140838fd1498Szrj else if (flags & BCS_TRANSACTION)
140938fd1498Szrj sk = sk_transaction;
141038fd1498Szrj r = do_pushlevel (sk);
141138fd1498Szrj }
141238fd1498Szrj
141338fd1498Szrj /* When processing a template, we need to remember where the braces were,
141438fd1498Szrj so that we can set up identical scopes when instantiating the template
141538fd1498Szrj later. BIND_EXPR is a handy candidate for this.
141638fd1498Szrj Note that do_poplevel won't create a BIND_EXPR itself here (and thus
141738fd1498Szrj result in nested BIND_EXPRs), since we don't build BLOCK nodes when
141838fd1498Szrj processing templates. */
141938fd1498Szrj if (processing_template_decl)
142038fd1498Szrj {
142138fd1498Szrj r = build3 (BIND_EXPR, NULL, NULL, r, NULL);
142238fd1498Szrj BIND_EXPR_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0;
142338fd1498Szrj BIND_EXPR_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0;
142438fd1498Szrj TREE_SIDE_EFFECTS (r) = 1;
142538fd1498Szrj }
142638fd1498Szrj
142738fd1498Szrj return r;
142838fd1498Szrj }
142938fd1498Szrj
143038fd1498Szrj /* Finish a compound-statement, which is given by STMT. */
143138fd1498Szrj
143238fd1498Szrj void
finish_compound_stmt(tree stmt)143338fd1498Szrj finish_compound_stmt (tree stmt)
143438fd1498Szrj {
143538fd1498Szrj if (TREE_CODE (stmt) == BIND_EXPR)
143638fd1498Szrj {
143738fd1498Szrj tree body = do_poplevel (BIND_EXPR_BODY (stmt));
143838fd1498Szrj /* If the STATEMENT_LIST is empty and this BIND_EXPR isn't special,
143938fd1498Szrj discard the BIND_EXPR so it can be merged with the containing
144038fd1498Szrj STATEMENT_LIST. */
144138fd1498Szrj if (TREE_CODE (body) == STATEMENT_LIST
144238fd1498Szrj && STATEMENT_LIST_HEAD (body) == NULL
144338fd1498Szrj && !BIND_EXPR_BODY_BLOCK (stmt)
144438fd1498Szrj && !BIND_EXPR_TRY_BLOCK (stmt))
144538fd1498Szrj stmt = body;
144638fd1498Szrj else
144738fd1498Szrj BIND_EXPR_BODY (stmt) = body;
144838fd1498Szrj }
144938fd1498Szrj else if (STATEMENT_LIST_NO_SCOPE (stmt))
145038fd1498Szrj stmt = pop_stmt_list (stmt);
145138fd1498Szrj else
145238fd1498Szrj {
145338fd1498Szrj /* Destroy any ObjC "super" receivers that may have been
145438fd1498Szrj created. */
145538fd1498Szrj objc_clear_super_receiver ();
145638fd1498Szrj
145738fd1498Szrj stmt = do_poplevel (stmt);
145838fd1498Szrj }
145938fd1498Szrj
146038fd1498Szrj /* ??? See c_end_compound_stmt wrt statement expressions. */
146138fd1498Szrj add_stmt (stmt);
146238fd1498Szrj }
146338fd1498Szrj
146438fd1498Szrj /* Finish an asm-statement, whose components are a STRING, some
146538fd1498Szrj OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some
146638fd1498Szrj LABELS. Also note whether the asm-statement should be
146758e805e6Szrj considered volatile, and whether it is asm inline. */
146838fd1498Szrj
146938fd1498Szrj tree
finish_asm_stmt(int volatile_p,tree string,tree output_operands,tree input_operands,tree clobbers,tree labels,bool inline_p)147038fd1498Szrj finish_asm_stmt (int volatile_p, tree string, tree output_operands,
147158e805e6Szrj tree input_operands, tree clobbers, tree labels, bool inline_p)
147238fd1498Szrj {
147338fd1498Szrj tree r;
147438fd1498Szrj tree t;
147538fd1498Szrj int ninputs = list_length (input_operands);
147638fd1498Szrj int noutputs = list_length (output_operands);
147738fd1498Szrj
147838fd1498Szrj if (!processing_template_decl)
147938fd1498Szrj {
148038fd1498Szrj const char *constraint;
148138fd1498Szrj const char **oconstraints;
148238fd1498Szrj bool allows_mem, allows_reg, is_inout;
148338fd1498Szrj tree operand;
148438fd1498Szrj int i;
148538fd1498Szrj
148638fd1498Szrj oconstraints = XALLOCAVEC (const char *, noutputs);
148738fd1498Szrj
148838fd1498Szrj string = resolve_asm_operand_names (string, output_operands,
148938fd1498Szrj input_operands, labels);
149038fd1498Szrj
149138fd1498Szrj for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
149238fd1498Szrj {
149338fd1498Szrj operand = TREE_VALUE (t);
149438fd1498Szrj
149538fd1498Szrj /* ??? Really, this should not be here. Users should be using a
149638fd1498Szrj proper lvalue, dammit. But there's a long history of using
149738fd1498Szrj casts in the output operands. In cases like longlong.h, this
149838fd1498Szrj becomes a primitive form of typechecking -- if the cast can be
149938fd1498Szrj removed, then the output operand had a type of the proper width;
150038fd1498Szrj otherwise we'll get an error. Gross, but ... */
150138fd1498Szrj STRIP_NOPS (operand);
150238fd1498Szrj
150338fd1498Szrj operand = mark_lvalue_use (operand);
150438fd1498Szrj
150538fd1498Szrj if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
150638fd1498Szrj operand = error_mark_node;
150738fd1498Szrj
150838fd1498Szrj if (operand != error_mark_node
150938fd1498Szrj && (TREE_READONLY (operand)
151038fd1498Szrj || CP_TYPE_CONST_P (TREE_TYPE (operand))
151138fd1498Szrj /* Functions are not modifiable, even though they are
151238fd1498Szrj lvalues. */
151338fd1498Szrj || TREE_CODE (TREE_TYPE (operand)) == FUNCTION_TYPE
151438fd1498Szrj || TREE_CODE (TREE_TYPE (operand)) == METHOD_TYPE
151538fd1498Szrj /* If it's an aggregate and any field is const, then it is
151638fd1498Szrj effectively const. */
151738fd1498Szrj || (CLASS_TYPE_P (TREE_TYPE (operand))
151838fd1498Szrj && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
151938fd1498Szrj cxx_readonly_error (operand, lv_asm);
152038fd1498Szrj
152138fd1498Szrj tree *op = &operand;
152238fd1498Szrj while (TREE_CODE (*op) == COMPOUND_EXPR)
152338fd1498Szrj op = &TREE_OPERAND (*op, 1);
152438fd1498Szrj switch (TREE_CODE (*op))
152538fd1498Szrj {
152638fd1498Szrj case PREINCREMENT_EXPR:
152738fd1498Szrj case PREDECREMENT_EXPR:
152838fd1498Szrj case MODIFY_EXPR:
152938fd1498Szrj *op = genericize_compound_lvalue (*op);
153038fd1498Szrj op = &TREE_OPERAND (*op, 1);
153138fd1498Szrj break;
153238fd1498Szrj default:
153338fd1498Szrj break;
153438fd1498Szrj }
153538fd1498Szrj
153638fd1498Szrj constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
153738fd1498Szrj oconstraints[i] = constraint;
153838fd1498Szrj
153938fd1498Szrj if (parse_output_constraint (&constraint, i, ninputs, noutputs,
154038fd1498Szrj &allows_mem, &allows_reg, &is_inout))
154138fd1498Szrj {
154238fd1498Szrj /* If the operand is going to end up in memory,
154338fd1498Szrj mark it addressable. */
154438fd1498Szrj if (!allows_reg && !cxx_mark_addressable (*op))
154538fd1498Szrj operand = error_mark_node;
154638fd1498Szrj }
154738fd1498Szrj else
154838fd1498Szrj operand = error_mark_node;
154938fd1498Szrj
155038fd1498Szrj TREE_VALUE (t) = operand;
155138fd1498Szrj }
155238fd1498Szrj
155338fd1498Szrj for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t))
155438fd1498Szrj {
155538fd1498Szrj constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
155638fd1498Szrj bool constraint_parsed
155738fd1498Szrj = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
155838fd1498Szrj oconstraints, &allows_mem, &allows_reg);
155938fd1498Szrj /* If the operand is going to end up in memory, don't call
156038fd1498Szrj decay_conversion. */
156138fd1498Szrj if (constraint_parsed && !allows_reg && allows_mem)
156238fd1498Szrj operand = mark_lvalue_use (TREE_VALUE (t));
156338fd1498Szrj else
156438fd1498Szrj operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error);
156538fd1498Szrj
156638fd1498Szrj /* If the type of the operand hasn't been determined (e.g.,
156738fd1498Szrj because it involves an overloaded function), then issue
156838fd1498Szrj an error message. There's no context available to
156938fd1498Szrj resolve the overloading. */
157038fd1498Szrj if (TREE_TYPE (operand) == unknown_type_node)
157138fd1498Szrj {
157238fd1498Szrj error ("type of asm operand %qE could not be determined",
157338fd1498Szrj TREE_VALUE (t));
157438fd1498Szrj operand = error_mark_node;
157538fd1498Szrj }
157638fd1498Szrj
157738fd1498Szrj if (constraint_parsed)
157838fd1498Szrj {
157938fd1498Szrj /* If the operand is going to end up in memory,
158038fd1498Szrj mark it addressable. */
158138fd1498Szrj if (!allows_reg && allows_mem)
158238fd1498Szrj {
158338fd1498Szrj /* Strip the nops as we allow this case. FIXME, this really
158438fd1498Szrj should be rejected or made deprecated. */
158538fd1498Szrj STRIP_NOPS (operand);
158638fd1498Szrj
158738fd1498Szrj tree *op = &operand;
158838fd1498Szrj while (TREE_CODE (*op) == COMPOUND_EXPR)
158938fd1498Szrj op = &TREE_OPERAND (*op, 1);
159038fd1498Szrj switch (TREE_CODE (*op))
159138fd1498Szrj {
159238fd1498Szrj case PREINCREMENT_EXPR:
159338fd1498Szrj case PREDECREMENT_EXPR:
159438fd1498Szrj case MODIFY_EXPR:
159538fd1498Szrj *op = genericize_compound_lvalue (*op);
159638fd1498Szrj op = &TREE_OPERAND (*op, 1);
159738fd1498Szrj break;
159838fd1498Szrj default:
159938fd1498Szrj break;
160038fd1498Szrj }
160138fd1498Szrj
160238fd1498Szrj if (!cxx_mark_addressable (*op))
160338fd1498Szrj operand = error_mark_node;
160438fd1498Szrj }
160538fd1498Szrj else if (!allows_reg && !allows_mem)
160638fd1498Szrj {
160738fd1498Szrj /* If constraint allows neither register nor memory,
160838fd1498Szrj try harder to get a constant. */
160938fd1498Szrj tree constop = maybe_constant_value (operand);
161038fd1498Szrj if (TREE_CONSTANT (constop))
161138fd1498Szrj operand = constop;
161238fd1498Szrj }
161338fd1498Szrj }
161438fd1498Szrj else
161538fd1498Szrj operand = error_mark_node;
161638fd1498Szrj
161738fd1498Szrj TREE_VALUE (t) = operand;
161838fd1498Szrj }
161938fd1498Szrj }
162038fd1498Szrj
162138fd1498Szrj r = build_stmt (input_location, ASM_EXPR, string,
162238fd1498Szrj output_operands, input_operands,
162338fd1498Szrj clobbers, labels);
162438fd1498Szrj ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
162558e805e6Szrj ASM_INLINE_P (r) = inline_p;
162638fd1498Szrj r = maybe_cleanup_point_expr_void (r);
162738fd1498Szrj return add_stmt (r);
162838fd1498Szrj }
162938fd1498Szrj
163038fd1498Szrj /* Finish a label with the indicated NAME. Returns the new label. */
163138fd1498Szrj
163238fd1498Szrj tree
finish_label_stmt(tree name)163338fd1498Szrj finish_label_stmt (tree name)
163438fd1498Szrj {
163538fd1498Szrj tree decl = define_label (input_location, name);
163638fd1498Szrj
163738fd1498Szrj if (decl == error_mark_node)
163838fd1498Szrj return error_mark_node;
163938fd1498Szrj
164038fd1498Szrj add_stmt (build_stmt (input_location, LABEL_EXPR, decl));
164138fd1498Szrj
164238fd1498Szrj return decl;
164338fd1498Szrj }
164438fd1498Szrj
164538fd1498Szrj /* Finish a series of declarations for local labels. G++ allows users
164638fd1498Szrj to declare "local" labels, i.e., labels with scope. This extension
164738fd1498Szrj is useful when writing code involving statement-expressions. */
164838fd1498Szrj
164938fd1498Szrj void
finish_label_decl(tree name)165038fd1498Szrj finish_label_decl (tree name)
165138fd1498Szrj {
165238fd1498Szrj if (!at_function_scope_p ())
165338fd1498Szrj {
165438fd1498Szrj error ("__label__ declarations are only allowed in function scopes");
165538fd1498Szrj return;
165638fd1498Szrj }
165738fd1498Szrj
165838fd1498Szrj add_decl_expr (declare_local_label (name));
165938fd1498Szrj }
166038fd1498Szrj
166138fd1498Szrj /* When DECL goes out of scope, make sure that CLEANUP is executed. */
166238fd1498Szrj
166338fd1498Szrj void
finish_decl_cleanup(tree decl,tree cleanup)166438fd1498Szrj finish_decl_cleanup (tree decl, tree cleanup)
166538fd1498Szrj {
166638fd1498Szrj push_cleanup (decl, cleanup, false);
166738fd1498Szrj }
166838fd1498Szrj
166938fd1498Szrj /* If the current scope exits with an exception, run CLEANUP. */
167038fd1498Szrj
167138fd1498Szrj void
finish_eh_cleanup(tree cleanup)167238fd1498Szrj finish_eh_cleanup (tree cleanup)
167338fd1498Szrj {
167438fd1498Szrj push_cleanup (NULL, cleanup, true);
167538fd1498Szrj }
167638fd1498Szrj
167738fd1498Szrj /* The MEM_INITS is a list of mem-initializers, in reverse of the
167838fd1498Szrj order they were written by the user. Each node is as for
167938fd1498Szrj emit_mem_initializers. */
168038fd1498Szrj
168138fd1498Szrj void
finish_mem_initializers(tree mem_inits)168238fd1498Szrj finish_mem_initializers (tree mem_inits)
168338fd1498Szrj {
168438fd1498Szrj /* Reorder the MEM_INITS so that they are in the order they appeared
168538fd1498Szrj in the source program. */
168638fd1498Szrj mem_inits = nreverse (mem_inits);
168738fd1498Szrj
168838fd1498Szrj if (processing_template_decl)
168938fd1498Szrj {
169038fd1498Szrj tree mem;
169138fd1498Szrj
169238fd1498Szrj for (mem = mem_inits; mem; mem = TREE_CHAIN (mem))
169338fd1498Szrj {
169438fd1498Szrj /* If the TREE_PURPOSE is a TYPE_PACK_EXPANSION, skip the
169538fd1498Szrj check for bare parameter packs in the TREE_VALUE, because
169638fd1498Szrj any parameter packs in the TREE_VALUE have already been
169738fd1498Szrj bound as part of the TREE_PURPOSE. See
169838fd1498Szrj make_pack_expansion for more information. */
169938fd1498Szrj if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION
170038fd1498Szrj && check_for_bare_parameter_packs (TREE_VALUE (mem)))
170138fd1498Szrj TREE_VALUE (mem) = error_mark_node;
170238fd1498Szrj }
170338fd1498Szrj
170438fd1498Szrj add_stmt (build_min_nt_loc (UNKNOWN_LOCATION,
170538fd1498Szrj CTOR_INITIALIZER, mem_inits));
170638fd1498Szrj }
170738fd1498Szrj else
170838fd1498Szrj emit_mem_initializers (mem_inits);
170938fd1498Szrj }
171038fd1498Szrj
171138fd1498Szrj /* Obfuscate EXPR if it looks like an id-expression or member access so
171238fd1498Szrj that the call to finish_decltype in do_auto_deduction will give the
171338fd1498Szrj right result. */
171438fd1498Szrj
171538fd1498Szrj tree
force_paren_expr(tree expr)171638fd1498Szrj force_paren_expr (tree expr)
171738fd1498Szrj {
171838fd1498Szrj /* This is only needed for decltype(auto) in C++14. */
171938fd1498Szrj if (cxx_dialect < cxx14)
172038fd1498Szrj return expr;
172138fd1498Szrj
172238fd1498Szrj /* If we're in unevaluated context, we can't be deducing a
172338fd1498Szrj return/initializer type, so we don't need to mess with this. */
172438fd1498Szrj if (cp_unevaluated_operand)
172538fd1498Szrj return expr;
172638fd1498Szrj
172738fd1498Szrj if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
172838fd1498Szrj && TREE_CODE (expr) != SCOPE_REF)
172938fd1498Szrj return expr;
173038fd1498Szrj
173138fd1498Szrj if (TREE_CODE (expr) == COMPONENT_REF
173238fd1498Szrj || TREE_CODE (expr) == SCOPE_REF)
173338fd1498Szrj REF_PARENTHESIZED_P (expr) = true;
173438fd1498Szrj else if (processing_template_decl)
173538fd1498Szrj expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
173638fd1498Szrj else if (VAR_P (expr) && DECL_HARD_REGISTER (expr))
173738fd1498Szrj /* We can't bind a hard register variable to a reference. */;
173838fd1498Szrj else
173938fd1498Szrj {
174038fd1498Szrj cp_lvalue_kind kind = lvalue_kind (expr);
174138fd1498Szrj if ((kind & ~clk_class) != clk_none)
174238fd1498Szrj {
174338fd1498Szrj tree type = unlowered_expr_type (expr);
174438fd1498Szrj bool rval = !!(kind & clk_rvalueref);
174538fd1498Szrj type = cp_build_reference_type (type, rval);
174638fd1498Szrj /* This inhibits warnings in, eg, cxx_mark_addressable
174738fd1498Szrj (c++/60955). */
174838fd1498Szrj warning_sentinel s (extra_warnings);
174938fd1498Szrj expr = build_static_cast (type, expr, tf_error);
175038fd1498Szrj if (expr != error_mark_node)
175138fd1498Szrj REF_PARENTHESIZED_P (expr) = true;
175238fd1498Szrj }
175338fd1498Szrj }
175438fd1498Szrj
175538fd1498Szrj return expr;
175638fd1498Szrj }
175738fd1498Szrj
175838fd1498Szrj /* If T is an id-expression obfuscated by force_paren_expr, undo the
175938fd1498Szrj obfuscation and return the underlying id-expression. Otherwise
176038fd1498Szrj return T. */
176138fd1498Szrj
176238fd1498Szrj tree
maybe_undo_parenthesized_ref(tree t)176338fd1498Szrj maybe_undo_parenthesized_ref (tree t)
176438fd1498Szrj {
176538fd1498Szrj if (cxx_dialect < cxx14)
176638fd1498Szrj return t;
176738fd1498Szrj
176838fd1498Szrj if (INDIRECT_REF_P (t) && REF_PARENTHESIZED_P (t))
176938fd1498Szrj {
177038fd1498Szrj t = TREE_OPERAND (t, 0);
177138fd1498Szrj while (TREE_CODE (t) == NON_LVALUE_EXPR
177238fd1498Szrj || TREE_CODE (t) == NOP_EXPR)
177338fd1498Szrj t = TREE_OPERAND (t, 0);
177438fd1498Szrj
177538fd1498Szrj gcc_assert (TREE_CODE (t) == ADDR_EXPR
177638fd1498Szrj || TREE_CODE (t) == STATIC_CAST_EXPR);
177738fd1498Szrj t = TREE_OPERAND (t, 0);
177838fd1498Szrj }
177938fd1498Szrj else if (TREE_CODE (t) == PAREN_EXPR)
178038fd1498Szrj t = TREE_OPERAND (t, 0);
178138fd1498Szrj
178238fd1498Szrj return t;
178338fd1498Szrj }
178438fd1498Szrj
178538fd1498Szrj /* Finish a parenthesized expression EXPR. */
178638fd1498Szrj
178738fd1498Szrj cp_expr
finish_parenthesized_expr(cp_expr expr)178838fd1498Szrj finish_parenthesized_expr (cp_expr expr)
178938fd1498Szrj {
179038fd1498Szrj if (EXPR_P (expr))
179138fd1498Szrj /* This inhibits warnings in c_common_truthvalue_conversion. */
179238fd1498Szrj TREE_NO_WARNING (expr) = 1;
179338fd1498Szrj
179438fd1498Szrj if (TREE_CODE (expr) == OFFSET_REF
179538fd1498Szrj || TREE_CODE (expr) == SCOPE_REF)
179638fd1498Szrj /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
179738fd1498Szrj enclosed in parentheses. */
179838fd1498Szrj PTRMEM_OK_P (expr) = 0;
179938fd1498Szrj
180038fd1498Szrj if (TREE_CODE (expr) == STRING_CST)
180138fd1498Szrj PAREN_STRING_LITERAL_P (expr) = 1;
180238fd1498Szrj
180338fd1498Szrj expr = cp_expr (force_paren_expr (expr), expr.get_location ());
180438fd1498Szrj
180538fd1498Szrj return expr;
180638fd1498Szrj }
180738fd1498Szrj
180838fd1498Szrj /* Finish a reference to a non-static data member (DECL) that is not
180938fd1498Szrj preceded by `.' or `->'. */
181038fd1498Szrj
181138fd1498Szrj tree
finish_non_static_data_member(tree decl,tree object,tree qualifying_scope)181238fd1498Szrj finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
181338fd1498Szrj {
181438fd1498Szrj gcc_assert (TREE_CODE (decl) == FIELD_DECL);
181538fd1498Szrj bool try_omp_private = !object && omp_private_member_map;
181638fd1498Szrj tree ret;
181738fd1498Szrj
181838fd1498Szrj if (!object)
181938fd1498Szrj {
182038fd1498Szrj tree scope = qualifying_scope;
182138fd1498Szrj if (scope == NULL_TREE)
182238fd1498Szrj scope = context_for_name_lookup (decl);
182338fd1498Szrj object = maybe_dummy_object (scope, NULL);
182438fd1498Szrj }
182538fd1498Szrj
182638fd1498Szrj object = maybe_resolve_dummy (object, true);
182738fd1498Szrj if (object == error_mark_node)
182838fd1498Szrj return error_mark_node;
182938fd1498Szrj
183038fd1498Szrj /* DR 613/850: Can use non-static data members without an associated
183138fd1498Szrj object in sizeof/decltype/alignof. */
183238fd1498Szrj if (is_dummy_object (object) && cp_unevaluated_operand == 0
183338fd1498Szrj && (!processing_template_decl || !current_class_ref))
183438fd1498Szrj {
183538fd1498Szrj if (current_function_decl
183638fd1498Szrj && DECL_STATIC_FUNCTION_P (current_function_decl))
183738fd1498Szrj error ("invalid use of member %qD in static member function", decl);
183838fd1498Szrj else
183938fd1498Szrj error ("invalid use of non-static data member %qD", decl);
184038fd1498Szrj inform (DECL_SOURCE_LOCATION (decl), "declared here");
184138fd1498Szrj
184238fd1498Szrj return error_mark_node;
184338fd1498Szrj }
184438fd1498Szrj
184538fd1498Szrj if (current_class_ptr)
184638fd1498Szrj TREE_USED (current_class_ptr) = 1;
184738fd1498Szrj if (processing_template_decl && !qualifying_scope)
184838fd1498Szrj {
184938fd1498Szrj tree type = TREE_TYPE (decl);
185038fd1498Szrj
185138fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
185238fd1498Szrj /* Quals on the object don't matter. */;
185338fd1498Szrj else if (PACK_EXPANSION_P (type))
185438fd1498Szrj /* Don't bother trying to represent this. */
185538fd1498Szrj type = NULL_TREE;
185638fd1498Szrj else
185738fd1498Szrj {
185838fd1498Szrj /* Set the cv qualifiers. */
185938fd1498Szrj int quals = cp_type_quals (TREE_TYPE (object));
186038fd1498Szrj
186138fd1498Szrj if (DECL_MUTABLE_P (decl))
186238fd1498Szrj quals &= ~TYPE_QUAL_CONST;
186338fd1498Szrj
186438fd1498Szrj quals |= cp_type_quals (TREE_TYPE (decl));
186538fd1498Szrj type = cp_build_qualified_type (type, quals);
186638fd1498Szrj }
186738fd1498Szrj
186838fd1498Szrj ret = (convert_from_reference
186938fd1498Szrj (build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
187038fd1498Szrj }
187138fd1498Szrj /* If PROCESSING_TEMPLATE_DECL is nonzero here, then
187238fd1498Szrj QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF
187338fd1498Szrj for now. */
187438fd1498Szrj else if (processing_template_decl)
187538fd1498Szrj ret = build_qualified_name (TREE_TYPE (decl),
187638fd1498Szrj qualifying_scope,
187738fd1498Szrj decl,
187838fd1498Szrj /*template_p=*/false);
187938fd1498Szrj else
188038fd1498Szrj {
188138fd1498Szrj tree access_type = TREE_TYPE (object);
188238fd1498Szrj
188338fd1498Szrj perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
188438fd1498Szrj decl, tf_warning_or_error);
188538fd1498Szrj
188638fd1498Szrj /* If the data member was named `C::M', convert `*this' to `C'
188738fd1498Szrj first. */
188838fd1498Szrj if (qualifying_scope)
188938fd1498Szrj {
189038fd1498Szrj tree binfo = NULL_TREE;
189138fd1498Szrj object = build_scoped_ref (object, qualifying_scope,
189238fd1498Szrj &binfo);
189338fd1498Szrj }
189438fd1498Szrj
189538fd1498Szrj ret = build_class_member_access_expr (object, decl,
189638fd1498Szrj /*access_path=*/NULL_TREE,
189738fd1498Szrj /*preserve_reference=*/false,
189838fd1498Szrj tf_warning_or_error);
189938fd1498Szrj }
190038fd1498Szrj if (try_omp_private)
190138fd1498Szrj {
190238fd1498Szrj tree *v = omp_private_member_map->get (decl);
190338fd1498Szrj if (v)
190438fd1498Szrj ret = convert_from_reference (*v);
190538fd1498Szrj }
190638fd1498Szrj return ret;
190738fd1498Szrj }
190838fd1498Szrj
190938fd1498Szrj /* If we are currently parsing a template and we encountered a typedef
191038fd1498Szrj TYPEDEF_DECL that is being accessed though CONTEXT, this function
191138fd1498Szrj adds the typedef to a list tied to the current template.
191238fd1498Szrj At template instantiation time, that list is walked and access check
191338fd1498Szrj performed for each typedef.
191438fd1498Szrj LOCATION is the location of the usage point of TYPEDEF_DECL. */
191538fd1498Szrj
191638fd1498Szrj void
add_typedef_to_current_template_for_access_check(tree typedef_decl,tree context,location_t location)191738fd1498Szrj add_typedef_to_current_template_for_access_check (tree typedef_decl,
191838fd1498Szrj tree context,
191938fd1498Szrj location_t location)
192038fd1498Szrj {
192138fd1498Szrj tree template_info = NULL;
192238fd1498Szrj tree cs = current_scope ();
192338fd1498Szrj
192438fd1498Szrj if (!is_typedef_decl (typedef_decl)
192538fd1498Szrj || !context
192638fd1498Szrj || !CLASS_TYPE_P (context)
192738fd1498Szrj || !cs)
192838fd1498Szrj return;
192938fd1498Szrj
193038fd1498Szrj if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)
193138fd1498Szrj template_info = get_template_info (cs);
193238fd1498Szrj
193338fd1498Szrj if (template_info
193438fd1498Szrj && TI_TEMPLATE (template_info)
193538fd1498Szrj && !currently_open_class (context))
193638fd1498Szrj append_type_to_template_for_access_check (cs, typedef_decl,
193738fd1498Szrj context, location);
193838fd1498Szrj }
193938fd1498Szrj
194038fd1498Szrj /* DECL was the declaration to which a qualified-id resolved. Issue
194138fd1498Szrj an error message if it is not accessible. If OBJECT_TYPE is
194238fd1498Szrj non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the
194338fd1498Szrj type of `*x', or `x', respectively. If the DECL was named as
194438fd1498Szrj `A::B' then NESTED_NAME_SPECIFIER is `A'. */
194538fd1498Szrj
194638fd1498Szrj void
check_accessibility_of_qualified_id(tree decl,tree object_type,tree nested_name_specifier)194738fd1498Szrj check_accessibility_of_qualified_id (tree decl,
194838fd1498Szrj tree object_type,
194938fd1498Szrj tree nested_name_specifier)
195038fd1498Szrj {
195138fd1498Szrj tree scope;
195238fd1498Szrj tree qualifying_type = NULL_TREE;
195338fd1498Szrj
195438fd1498Szrj /* If we are parsing a template declaration and if decl is a typedef,
195538fd1498Szrj add it to a list tied to the template.
195638fd1498Szrj At template instantiation time, that list will be walked and
195738fd1498Szrj access check performed. */
195838fd1498Szrj add_typedef_to_current_template_for_access_check (decl,
195938fd1498Szrj nested_name_specifier
196038fd1498Szrj ? nested_name_specifier
196138fd1498Szrj : DECL_CONTEXT (decl),
196238fd1498Szrj input_location);
196338fd1498Szrj
196438fd1498Szrj /* If we're not checking, return immediately. */
196538fd1498Szrj if (deferred_access_no_check)
196638fd1498Szrj return;
196738fd1498Szrj
196838fd1498Szrj /* Determine the SCOPE of DECL. */
196938fd1498Szrj scope = context_for_name_lookup (decl);
197038fd1498Szrj /* If the SCOPE is not a type, then DECL is not a member. */
197138fd1498Szrj if (!TYPE_P (scope))
197238fd1498Szrj return;
197338fd1498Szrj /* Compute the scope through which DECL is being accessed. */
197438fd1498Szrj if (object_type
197538fd1498Szrj /* OBJECT_TYPE might not be a class type; consider:
197638fd1498Szrj
197738fd1498Szrj class A { typedef int I; };
197838fd1498Szrj I *p;
197938fd1498Szrj p->A::I::~I();
198038fd1498Szrj
198138fd1498Szrj In this case, we will have "A::I" as the DECL, but "I" as the
198238fd1498Szrj OBJECT_TYPE. */
198338fd1498Szrj && CLASS_TYPE_P (object_type)
198438fd1498Szrj && DERIVED_FROM_P (scope, object_type))
198538fd1498Szrj /* If we are processing a `->' or `.' expression, use the type of the
198638fd1498Szrj left-hand side. */
198738fd1498Szrj qualifying_type = object_type;
198838fd1498Szrj else if (nested_name_specifier)
198938fd1498Szrj {
199038fd1498Szrj /* If the reference is to a non-static member of the
199138fd1498Szrj current class, treat it as if it were referenced through
199238fd1498Szrj `this'. */
199338fd1498Szrj tree ct;
199438fd1498Szrj if (DECL_NONSTATIC_MEMBER_P (decl)
199538fd1498Szrj && current_class_ptr
199638fd1498Szrj && DERIVED_FROM_P (scope, ct = current_nonlambda_class_type ()))
199738fd1498Szrj qualifying_type = ct;
199838fd1498Szrj /* Otherwise, use the type indicated by the
199938fd1498Szrj nested-name-specifier. */
200038fd1498Szrj else
200138fd1498Szrj qualifying_type = nested_name_specifier;
200238fd1498Szrj }
200338fd1498Szrj else
200438fd1498Szrj /* Otherwise, the name must be from the current class or one of
200538fd1498Szrj its bases. */
200638fd1498Szrj qualifying_type = currently_open_derived_class (scope);
200738fd1498Szrj
200838fd1498Szrj if (qualifying_type
200938fd1498Szrj /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
201038fd1498Szrj or similar in a default argument value. */
201138fd1498Szrj && CLASS_TYPE_P (qualifying_type)
201238fd1498Szrj && !dependent_type_p (qualifying_type))
201338fd1498Szrj perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
201438fd1498Szrj decl, tf_warning_or_error);
201538fd1498Szrj }
201638fd1498Szrj
201738fd1498Szrj /* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the
201838fd1498Szrj class named to the left of the "::" operator. DONE is true if this
201938fd1498Szrj expression is a complete postfix-expression; it is false if this
202038fd1498Szrj expression is followed by '->', '[', '(', etc. ADDRESS_P is true
202138fd1498Szrj iff this expression is the operand of '&'. TEMPLATE_P is true iff
202238fd1498Szrj the qualified-id was of the form "A::template B". TEMPLATE_ARG_P
202338fd1498Szrj is true iff this qualified name appears as a template argument. */
202438fd1498Szrj
202538fd1498Szrj tree
finish_qualified_id_expr(tree qualifying_class,tree expr,bool done,bool address_p,bool template_p,bool template_arg_p,tsubst_flags_t complain)202638fd1498Szrj finish_qualified_id_expr (tree qualifying_class,
202738fd1498Szrj tree expr,
202838fd1498Szrj bool done,
202938fd1498Szrj bool address_p,
203038fd1498Szrj bool template_p,
203138fd1498Szrj bool template_arg_p,
203238fd1498Szrj tsubst_flags_t complain)
203338fd1498Szrj {
203438fd1498Szrj gcc_assert (TYPE_P (qualifying_class));
203538fd1498Szrj
203638fd1498Szrj if (error_operand_p (expr))
203738fd1498Szrj return error_mark_node;
203838fd1498Szrj
203938fd1498Szrj if ((DECL_P (expr) || BASELINK_P (expr))
204038fd1498Szrj && !mark_used (expr, complain))
204138fd1498Szrj return error_mark_node;
204238fd1498Szrj
204338fd1498Szrj if (template_p)
204438fd1498Szrj {
204538fd1498Szrj if (TREE_CODE (expr) == UNBOUND_CLASS_TEMPLATE)
204638fd1498Szrj {
204738fd1498Szrj /* cp_parser_lookup_name thought we were looking for a type,
204838fd1498Szrj but we're actually looking for a declaration. */
204938fd1498Szrj qualifying_class = TYPE_CONTEXT (expr);
205038fd1498Szrj expr = TYPE_IDENTIFIER (expr);
205138fd1498Szrj }
205238fd1498Szrj else
205338fd1498Szrj check_template_keyword (expr);
205438fd1498Szrj }
205538fd1498Szrj
205638fd1498Szrj /* If EXPR occurs as the operand of '&', use special handling that
205738fd1498Szrj permits a pointer-to-member. */
205838fd1498Szrj if (address_p && done)
205938fd1498Szrj {
206038fd1498Szrj if (TREE_CODE (expr) == SCOPE_REF)
206138fd1498Szrj expr = TREE_OPERAND (expr, 1);
206238fd1498Szrj expr = build_offset_ref (qualifying_class, expr,
206338fd1498Szrj /*address_p=*/true, complain);
206438fd1498Szrj return expr;
206538fd1498Szrj }
206638fd1498Szrj
206738fd1498Szrj /* No need to check access within an enum. */
206838fd1498Szrj if (TREE_CODE (qualifying_class) == ENUMERAL_TYPE
206938fd1498Szrj && TREE_CODE (expr) != IDENTIFIER_NODE)
207038fd1498Szrj return expr;
207138fd1498Szrj
207238fd1498Szrj /* Within the scope of a class, turn references to non-static
207338fd1498Szrj members into expression of the form "this->...". */
207438fd1498Szrj if (template_arg_p)
207538fd1498Szrj /* But, within a template argument, we do not want make the
207638fd1498Szrj transformation, as there is no "this" pointer. */
207738fd1498Szrj ;
207838fd1498Szrj else if (TREE_CODE (expr) == FIELD_DECL)
207938fd1498Szrj {
208038fd1498Szrj push_deferring_access_checks (dk_no_check);
208138fd1498Szrj expr = finish_non_static_data_member (expr, NULL_TREE,
208238fd1498Szrj qualifying_class);
208338fd1498Szrj pop_deferring_access_checks ();
208438fd1498Szrj }
208538fd1498Szrj else if (BASELINK_P (expr))
208638fd1498Szrj {
208738fd1498Szrj /* See if any of the functions are non-static members. */
208838fd1498Szrj /* If so, the expression may be relative to 'this'. */
208938fd1498Szrj if (!shared_member_p (expr)
209038fd1498Szrj && current_class_ptr
209138fd1498Szrj && DERIVED_FROM_P (qualifying_class,
209238fd1498Szrj current_nonlambda_class_type ()))
209338fd1498Szrj expr = (build_class_member_access_expr
209438fd1498Szrj (maybe_dummy_object (qualifying_class, NULL),
209538fd1498Szrj expr,
209638fd1498Szrj BASELINK_ACCESS_BINFO (expr),
209738fd1498Szrj /*preserve_reference=*/false,
209838fd1498Szrj complain));
209938fd1498Szrj else if (done)
210038fd1498Szrj /* The expression is a qualified name whose address is not
210138fd1498Szrj being taken. */
210238fd1498Szrj expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
210338fd1498Szrj complain);
210438fd1498Szrj }
210538fd1498Szrj else
210638fd1498Szrj {
210738fd1498Szrj /* In a template, return a SCOPE_REF for most qualified-ids
210838fd1498Szrj so that we can check access at instantiation time. But if
210938fd1498Szrj we're looking at a member of the current instantiation, we
211038fd1498Szrj know we have access and building up the SCOPE_REF confuses
211138fd1498Szrj non-type template argument handling. */
211238fd1498Szrj if (processing_template_decl
211338fd1498Szrj && (!currently_open_class (qualifying_class)
211458e805e6Szrj || TREE_CODE (expr) == IDENTIFIER_NODE
211558e805e6Szrj || TREE_CODE (expr) == TEMPLATE_ID_EXPR
211638fd1498Szrj || TREE_CODE (expr) == BIT_NOT_EXPR))
211738fd1498Szrj expr = build_qualified_name (TREE_TYPE (expr),
211838fd1498Szrj qualifying_class, expr,
211938fd1498Szrj template_p);
212038fd1498Szrj
212138fd1498Szrj expr = convert_from_reference (expr);
212238fd1498Szrj }
212338fd1498Szrj
212438fd1498Szrj return expr;
212538fd1498Szrj }
212638fd1498Szrj
212738fd1498Szrj /* Begin a statement-expression. The value returned must be passed to
212838fd1498Szrj finish_stmt_expr. */
212938fd1498Szrj
213038fd1498Szrj tree
begin_stmt_expr(void)213138fd1498Szrj begin_stmt_expr (void)
213238fd1498Szrj {
213338fd1498Szrj return push_stmt_list ();
213438fd1498Szrj }
213538fd1498Szrj
213638fd1498Szrj /* Process the final expression of a statement expression. EXPR can be
213738fd1498Szrj NULL, if the final expression is empty. Return a STATEMENT_LIST
213838fd1498Szrj containing all the statements in the statement-expression, or
213938fd1498Szrj ERROR_MARK_NODE if there was an error. */
214038fd1498Szrj
214138fd1498Szrj tree
finish_stmt_expr_expr(tree expr,tree stmt_expr)214238fd1498Szrj finish_stmt_expr_expr (tree expr, tree stmt_expr)
214338fd1498Szrj {
214438fd1498Szrj if (error_operand_p (expr))
214538fd1498Szrj {
214638fd1498Szrj /* The type of the statement-expression is the type of the last
214738fd1498Szrj expression. */
214838fd1498Szrj TREE_TYPE (stmt_expr) = error_mark_node;
214938fd1498Szrj return error_mark_node;
215038fd1498Szrj }
215138fd1498Szrj
215238fd1498Szrj /* If the last statement does not have "void" type, then the value
215338fd1498Szrj of the last statement is the value of the entire expression. */
215438fd1498Szrj if (expr)
215538fd1498Szrj {
215638fd1498Szrj tree type = TREE_TYPE (expr);
215738fd1498Szrj
215838fd1498Szrj if (type && type_unknown_p (type))
215938fd1498Szrj {
216038fd1498Szrj error ("a statement expression is an insufficient context"
216138fd1498Szrj " for overload resolution");
216238fd1498Szrj TREE_TYPE (stmt_expr) = error_mark_node;
216338fd1498Szrj return error_mark_node;
216438fd1498Szrj }
216538fd1498Szrj else if (processing_template_decl)
216638fd1498Szrj {
216738fd1498Szrj expr = build_stmt (input_location, EXPR_STMT, expr);
216838fd1498Szrj expr = add_stmt (expr);
216938fd1498Szrj /* Mark the last statement so that we can recognize it as such at
217038fd1498Szrj template-instantiation time. */
217138fd1498Szrj EXPR_STMT_STMT_EXPR_RESULT (expr) = 1;
217238fd1498Szrj }
217338fd1498Szrj else if (VOID_TYPE_P (type))
217438fd1498Szrj {
217538fd1498Szrj /* Just treat this like an ordinary statement. */
217638fd1498Szrj expr = finish_expr_stmt (expr);
217738fd1498Szrj }
217838fd1498Szrj else
217938fd1498Szrj {
218038fd1498Szrj /* It actually has a value we need to deal with. First, force it
218138fd1498Szrj to be an rvalue so that we won't need to build up a copy
218238fd1498Szrj constructor call later when we try to assign it to something. */
218338fd1498Szrj expr = force_rvalue (expr, tf_warning_or_error);
218438fd1498Szrj if (error_operand_p (expr))
218538fd1498Szrj return error_mark_node;
218638fd1498Szrj
218738fd1498Szrj /* Update for array-to-pointer decay. */
218838fd1498Szrj type = TREE_TYPE (expr);
218938fd1498Szrj
219038fd1498Szrj /* Wrap it in a CLEANUP_POINT_EXPR and add it to the list like a
219138fd1498Szrj normal statement, but don't convert to void or actually add
219238fd1498Szrj the EXPR_STMT. */
219338fd1498Szrj if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
219438fd1498Szrj expr = maybe_cleanup_point_expr (expr);
219538fd1498Szrj add_stmt (expr);
219638fd1498Szrj }
219738fd1498Szrj
219838fd1498Szrj /* The type of the statement-expression is the type of the last
219938fd1498Szrj expression. */
220038fd1498Szrj TREE_TYPE (stmt_expr) = type;
220138fd1498Szrj }
220238fd1498Szrj
220338fd1498Szrj return stmt_expr;
220438fd1498Szrj }
220538fd1498Szrj
220638fd1498Szrj /* Finish a statement-expression. EXPR should be the value returned
220738fd1498Szrj by the previous begin_stmt_expr. Returns an expression
220838fd1498Szrj representing the statement-expression. */
220938fd1498Szrj
221038fd1498Szrj tree
finish_stmt_expr(tree stmt_expr,bool has_no_scope)221138fd1498Szrj finish_stmt_expr (tree stmt_expr, bool has_no_scope)
221238fd1498Szrj {
221338fd1498Szrj tree type;
221438fd1498Szrj tree result;
221538fd1498Szrj
221638fd1498Szrj if (error_operand_p (stmt_expr))
221738fd1498Szrj {
221838fd1498Szrj pop_stmt_list (stmt_expr);
221938fd1498Szrj return error_mark_node;
222038fd1498Szrj }
222138fd1498Szrj
222238fd1498Szrj gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST);
222338fd1498Szrj
222438fd1498Szrj type = TREE_TYPE (stmt_expr);
222538fd1498Szrj result = pop_stmt_list (stmt_expr);
222638fd1498Szrj TREE_TYPE (result) = type;
222738fd1498Szrj
222838fd1498Szrj if (processing_template_decl)
222938fd1498Szrj {
223038fd1498Szrj result = build_min (STMT_EXPR, type, result);
223138fd1498Szrj TREE_SIDE_EFFECTS (result) = 1;
223238fd1498Szrj STMT_EXPR_NO_SCOPE (result) = has_no_scope;
223338fd1498Szrj }
223438fd1498Szrj else if (CLASS_TYPE_P (type))
223538fd1498Szrj {
223638fd1498Szrj /* Wrap the statement-expression in a TARGET_EXPR so that the
223738fd1498Szrj temporary object created by the final expression is destroyed at
223838fd1498Szrj the end of the full-expression containing the
223938fd1498Szrj statement-expression. */
224038fd1498Szrj result = force_target_expr (type, result, tf_warning_or_error);
224138fd1498Szrj }
224238fd1498Szrj
224338fd1498Szrj return result;
224438fd1498Szrj }
224538fd1498Szrj
224638fd1498Szrj /* Returns the expression which provides the value of STMT_EXPR. */
224738fd1498Szrj
224838fd1498Szrj tree
stmt_expr_value_expr(tree stmt_expr)224938fd1498Szrj stmt_expr_value_expr (tree stmt_expr)
225038fd1498Szrj {
225138fd1498Szrj tree t = STMT_EXPR_STMT (stmt_expr);
225238fd1498Szrj
225338fd1498Szrj if (TREE_CODE (t) == BIND_EXPR)
225438fd1498Szrj t = BIND_EXPR_BODY (t);
225538fd1498Szrj
225638fd1498Szrj if (TREE_CODE (t) == STATEMENT_LIST && STATEMENT_LIST_TAIL (t))
225738fd1498Szrj t = STATEMENT_LIST_TAIL (t)->stmt;
225838fd1498Szrj
225938fd1498Szrj if (TREE_CODE (t) == EXPR_STMT)
226038fd1498Szrj t = EXPR_STMT_EXPR (t);
226138fd1498Szrj
226238fd1498Szrj return t;
226338fd1498Szrj }
226438fd1498Szrj
226538fd1498Szrj /* Return TRUE iff EXPR_STMT is an empty list of
226638fd1498Szrj expression statements. */
226738fd1498Szrj
226838fd1498Szrj bool
empty_expr_stmt_p(tree expr_stmt)226938fd1498Szrj empty_expr_stmt_p (tree expr_stmt)
227038fd1498Szrj {
227138fd1498Szrj tree body = NULL_TREE;
227238fd1498Szrj
227338fd1498Szrj if (expr_stmt == void_node)
227438fd1498Szrj return true;
227538fd1498Szrj
227638fd1498Szrj if (expr_stmt)
227738fd1498Szrj {
227838fd1498Szrj if (TREE_CODE (expr_stmt) == EXPR_STMT)
227938fd1498Szrj body = EXPR_STMT_EXPR (expr_stmt);
228038fd1498Szrj else if (TREE_CODE (expr_stmt) == STATEMENT_LIST)
228138fd1498Szrj body = expr_stmt;
228238fd1498Szrj }
228338fd1498Szrj
228438fd1498Szrj if (body)
228538fd1498Szrj {
228638fd1498Szrj if (TREE_CODE (body) == STATEMENT_LIST)
228738fd1498Szrj return tsi_end_p (tsi_start (body));
228838fd1498Szrj else
228938fd1498Szrj return empty_expr_stmt_p (body);
229038fd1498Szrj }
229138fd1498Szrj return false;
229238fd1498Szrj }
229338fd1498Szrj
229438fd1498Szrj /* Perform Koenig lookup. FN is the postfix-expression representing
229538fd1498Szrj the function (or functions) to call; ARGS are the arguments to the
229638fd1498Szrj call. Returns the functions to be considered by overload resolution. */
229738fd1498Szrj
229838fd1498Szrj cp_expr
perform_koenig_lookup(cp_expr fn,vec<tree,va_gc> * args,tsubst_flags_t complain)229938fd1498Szrj perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
230038fd1498Szrj tsubst_flags_t complain)
230138fd1498Szrj {
230238fd1498Szrj tree identifier = NULL_TREE;
230338fd1498Szrj tree functions = NULL_TREE;
230438fd1498Szrj tree tmpl_args = NULL_TREE;
230538fd1498Szrj bool template_id = false;
230638fd1498Szrj location_t loc = fn.get_location ();
230738fd1498Szrj
230838fd1498Szrj if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
230938fd1498Szrj {
231038fd1498Szrj /* Use a separate flag to handle null args. */
231138fd1498Szrj template_id = true;
231238fd1498Szrj tmpl_args = TREE_OPERAND (fn, 1);
231338fd1498Szrj fn = TREE_OPERAND (fn, 0);
231438fd1498Szrj }
231538fd1498Szrj
231638fd1498Szrj /* Find the name of the overloaded function. */
231738fd1498Szrj if (identifier_p (fn))
231838fd1498Szrj identifier = fn;
231938fd1498Szrj else
232038fd1498Szrj {
232138fd1498Szrj functions = fn;
232238fd1498Szrj identifier = OVL_NAME (functions);
232338fd1498Szrj }
232438fd1498Szrj
232538fd1498Szrj /* A call to a namespace-scope function using an unqualified name.
232638fd1498Szrj
232738fd1498Szrj Do Koenig lookup -- unless any of the arguments are
232838fd1498Szrj type-dependent. */
232938fd1498Szrj if (!any_type_dependent_arguments_p (args)
233038fd1498Szrj && !any_dependent_template_arguments_p (tmpl_args))
233138fd1498Szrj {
233238fd1498Szrj fn = lookup_arg_dependent (identifier, functions, args);
233338fd1498Szrj if (!fn)
233438fd1498Szrj {
233538fd1498Szrj /* The unqualified name could not be resolved. */
233638fd1498Szrj if (complain & tf_error)
233738fd1498Szrj fn = unqualified_fn_lookup_error (cp_expr (identifier, loc));
233838fd1498Szrj else
233938fd1498Szrj fn = identifier;
234038fd1498Szrj }
234138fd1498Szrj }
234238fd1498Szrj
234338fd1498Szrj if (fn && template_id && fn != error_mark_node)
234438fd1498Szrj fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args);
234538fd1498Szrj
234638fd1498Szrj return fn;
234738fd1498Szrj }
234838fd1498Szrj
234938fd1498Szrj /* Generate an expression for `FN (ARGS)'. This may change the
235038fd1498Szrj contents of ARGS.
235138fd1498Szrj
235238fd1498Szrj If DISALLOW_VIRTUAL is true, the call to FN will be not generated
235338fd1498Szrj as a virtual call, even if FN is virtual. (This flag is set when
235438fd1498Szrj encountering an expression where the function name is explicitly
235538fd1498Szrj qualified. For example a call to `X::f' never generates a virtual
235638fd1498Szrj call.)
235738fd1498Szrj
235838fd1498Szrj Returns code for the call. */
235938fd1498Szrj
236038fd1498Szrj tree
finish_call_expr(tree fn,vec<tree,va_gc> ** args,bool disallow_virtual,bool koenig_p,tsubst_flags_t complain)236138fd1498Szrj finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
236238fd1498Szrj bool koenig_p, tsubst_flags_t complain)
236338fd1498Szrj {
236438fd1498Szrj tree result;
236538fd1498Szrj tree orig_fn;
236638fd1498Szrj vec<tree, va_gc> *orig_args = NULL;
236738fd1498Szrj
236838fd1498Szrj if (fn == error_mark_node)
236938fd1498Szrj return error_mark_node;
237038fd1498Szrj
237138fd1498Szrj gcc_assert (!TYPE_P (fn));
237238fd1498Szrj
237338fd1498Szrj /* If FN may be a FUNCTION_DECL obfuscated by force_paren_expr, undo
237438fd1498Szrj it so that we can tell this is a call to a known function. */
237538fd1498Szrj fn = maybe_undo_parenthesized_ref (fn);
237638fd1498Szrj
237738fd1498Szrj orig_fn = fn;
237838fd1498Szrj
237938fd1498Szrj if (processing_template_decl)
238038fd1498Szrj {
238138fd1498Szrj /* If FN is a local extern declaration or set thereof, look them up
238238fd1498Szrj again at instantiation time. */
238338fd1498Szrj if (is_overloaded_fn (fn))
238438fd1498Szrj {
238538fd1498Szrj tree ifn = get_first_fn (fn);
238638fd1498Szrj if (TREE_CODE (ifn) == FUNCTION_DECL
238738fd1498Szrj && DECL_LOCAL_FUNCTION_P (ifn))
238838fd1498Szrj orig_fn = DECL_NAME (ifn);
238938fd1498Szrj }
239038fd1498Szrj
239138fd1498Szrj /* If the call expression is dependent, build a CALL_EXPR node
239238fd1498Szrj with no type; type_dependent_expression_p recognizes
239338fd1498Szrj expressions with no type as being dependent. */
239438fd1498Szrj if (type_dependent_expression_p (fn)
239538fd1498Szrj || any_type_dependent_arguments_p (*args))
239638fd1498Szrj {
239738fd1498Szrj result = build_min_nt_call_vec (orig_fn, *args);
239838fd1498Szrj SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
239938fd1498Szrj KOENIG_LOOKUP_P (result) = koenig_p;
240038fd1498Szrj if (is_overloaded_fn (fn))
240138fd1498Szrj {
240238fd1498Szrj fn = get_fns (fn);
240338fd1498Szrj lookup_keep (fn, true);
240438fd1498Szrj }
240538fd1498Szrj
240638fd1498Szrj if (cfun)
240738fd1498Szrj {
240838fd1498Szrj bool abnormal = true;
240938fd1498Szrj for (lkp_iterator iter (fn); abnormal && iter; ++iter)
241038fd1498Szrj {
241138fd1498Szrj tree fndecl = *iter;
241238fd1498Szrj if (TREE_CODE (fndecl) != FUNCTION_DECL
241338fd1498Szrj || !TREE_THIS_VOLATILE (fndecl))
241438fd1498Szrj abnormal = false;
241538fd1498Szrj }
241638fd1498Szrj /* FIXME: Stop warning about falling off end of non-void
241738fd1498Szrj function. But this is wrong. Even if we only see
241838fd1498Szrj no-return fns at this point, we could select a
241938fd1498Szrj future-defined return fn during instantiation. Or
242038fd1498Szrj vice-versa. */
242138fd1498Szrj if (abnormal)
242238fd1498Szrj current_function_returns_abnormally = 1;
242338fd1498Szrj }
242438fd1498Szrj return result;
242538fd1498Szrj }
242638fd1498Szrj orig_args = make_tree_vector_copy (*args);
242738fd1498Szrj if (!BASELINK_P (fn)
242838fd1498Szrj && TREE_CODE (fn) != PSEUDO_DTOR_EXPR
242938fd1498Szrj && TREE_TYPE (fn) != unknown_type_node)
243038fd1498Szrj fn = build_non_dependent_expr (fn);
243138fd1498Szrj make_args_non_dependent (*args);
243238fd1498Szrj }
243338fd1498Szrj
243438fd1498Szrj if (TREE_CODE (fn) == COMPONENT_REF)
243538fd1498Szrj {
243638fd1498Szrj tree member = TREE_OPERAND (fn, 1);
243738fd1498Szrj if (BASELINK_P (member))
243838fd1498Szrj {
243938fd1498Szrj tree object = TREE_OPERAND (fn, 0);
244038fd1498Szrj return build_new_method_call (object, member,
244138fd1498Szrj args, NULL_TREE,
244238fd1498Szrj (disallow_virtual
244338fd1498Szrj ? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL
244438fd1498Szrj : LOOKUP_NORMAL),
244538fd1498Szrj /*fn_p=*/NULL,
244638fd1498Szrj complain);
244738fd1498Szrj }
244838fd1498Szrj }
244938fd1498Szrj
245038fd1498Szrj /* Per 13.3.1.1, '(&f)(...)' is the same as '(f)(...)'. */
245138fd1498Szrj if (TREE_CODE (fn) == ADDR_EXPR
245238fd1498Szrj && TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
245338fd1498Szrj fn = TREE_OPERAND (fn, 0);
245438fd1498Szrj
245538fd1498Szrj if (is_overloaded_fn (fn))
245638fd1498Szrj fn = baselink_for_fns (fn);
245738fd1498Szrj
245838fd1498Szrj result = NULL_TREE;
245938fd1498Szrj if (BASELINK_P (fn))
246038fd1498Szrj {
246138fd1498Szrj tree object;
246238fd1498Szrj
246338fd1498Szrj /* A call to a member function. From [over.call.func]:
246438fd1498Szrj
246538fd1498Szrj If the keyword this is in scope and refers to the class of
246638fd1498Szrj that member function, or a derived class thereof, then the
246738fd1498Szrj function call is transformed into a qualified function call
246838fd1498Szrj using (*this) as the postfix-expression to the left of the
246938fd1498Szrj . operator.... [Otherwise] a contrived object of type T
247038fd1498Szrj becomes the implied object argument.
247138fd1498Szrj
247238fd1498Szrj In this situation:
247338fd1498Szrj
247438fd1498Szrj struct A { void f(); };
247538fd1498Szrj struct B : public A {};
247638fd1498Szrj struct C : public A { void g() { B::f(); }};
247738fd1498Szrj
247838fd1498Szrj "the class of that member function" refers to `A'. But 11.2
247938fd1498Szrj [class.access.base] says that we need to convert 'this' to B* as
248038fd1498Szrj part of the access, so we pass 'B' to maybe_dummy_object. */
248138fd1498Szrj
248238fd1498Szrj if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (get_first_fn (fn)))
248338fd1498Szrj {
248438fd1498Szrj /* A constructor call always uses a dummy object. (This constructor
248538fd1498Szrj call which has the form A::A () is actually invalid and we are
248638fd1498Szrj going to reject it later in build_new_method_call.) */
248738fd1498Szrj object = build_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)));
248838fd1498Szrj }
248938fd1498Szrj else
249038fd1498Szrj object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
249138fd1498Szrj NULL);
249238fd1498Szrj
249338fd1498Szrj result = build_new_method_call (object, fn, args, NULL_TREE,
249438fd1498Szrj (disallow_virtual
249538fd1498Szrj ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
249638fd1498Szrj : LOOKUP_NORMAL),
249738fd1498Szrj /*fn_p=*/NULL,
249838fd1498Szrj complain);
249938fd1498Szrj }
250038fd1498Szrj else if (is_overloaded_fn (fn))
250138fd1498Szrj {
250238fd1498Szrj /* If the function is an overloaded builtin, resolve it. */
250338fd1498Szrj if (TREE_CODE (fn) == FUNCTION_DECL
250438fd1498Szrj && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
250538fd1498Szrj || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD))
250638fd1498Szrj result = resolve_overloaded_builtin (input_location, fn, *args);
250738fd1498Szrj
250838fd1498Szrj if (!result)
250938fd1498Szrj {
251038fd1498Szrj if (warn_sizeof_pointer_memaccess
251138fd1498Szrj && (complain & tf_warning)
251238fd1498Szrj && !vec_safe_is_empty (*args)
251338fd1498Szrj && !processing_template_decl)
251438fd1498Szrj {
251538fd1498Szrj location_t sizeof_arg_loc[3];
251638fd1498Szrj tree sizeof_arg[3];
251738fd1498Szrj unsigned int i;
251838fd1498Szrj for (i = 0; i < 3; i++)
251938fd1498Szrj {
252038fd1498Szrj tree t;
252138fd1498Szrj
252238fd1498Szrj sizeof_arg_loc[i] = UNKNOWN_LOCATION;
252338fd1498Szrj sizeof_arg[i] = NULL_TREE;
252438fd1498Szrj if (i >= (*args)->length ())
252538fd1498Szrj continue;
252638fd1498Szrj t = (**args)[i];
252738fd1498Szrj if (TREE_CODE (t) != SIZEOF_EXPR)
252838fd1498Szrj continue;
252938fd1498Szrj if (SIZEOF_EXPR_TYPE_P (t))
253038fd1498Szrj sizeof_arg[i] = TREE_TYPE (TREE_OPERAND (t, 0));
253138fd1498Szrj else
253238fd1498Szrj sizeof_arg[i] = TREE_OPERAND (t, 0);
253338fd1498Szrj sizeof_arg_loc[i] = EXPR_LOCATION (t);
253438fd1498Szrj }
253538fd1498Szrj sizeof_pointer_memaccess_warning
253638fd1498Szrj (sizeof_arg_loc, fn, *args,
253738fd1498Szrj sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
253838fd1498Szrj }
253938fd1498Szrj
254038fd1498Szrj /* A call to a namespace-scope function. */
254138fd1498Szrj result = build_new_function_call (fn, args, complain);
254238fd1498Szrj }
254338fd1498Szrj }
254438fd1498Szrj else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
254538fd1498Szrj {
254638fd1498Szrj if (!vec_safe_is_empty (*args))
254738fd1498Szrj error ("arguments to destructor are not allowed");
254838fd1498Szrj /* Mark the pseudo-destructor call as having side-effects so
254938fd1498Szrj that we do not issue warnings about its use. */
255038fd1498Szrj result = build1 (NOP_EXPR,
255138fd1498Szrj void_type_node,
255238fd1498Szrj TREE_OPERAND (fn, 0));
255338fd1498Szrj TREE_SIDE_EFFECTS (result) = 1;
255438fd1498Szrj }
255538fd1498Szrj else if (CLASS_TYPE_P (TREE_TYPE (fn)))
255638fd1498Szrj /* If the "function" is really an object of class type, it might
255738fd1498Szrj have an overloaded `operator ()'. */
255838fd1498Szrj result = build_op_call (fn, args, complain);
255938fd1498Szrj
256038fd1498Szrj if (!result)
256138fd1498Szrj /* A call where the function is unknown. */
256238fd1498Szrj result = cp_build_function_call_vec (fn, args, complain);
256338fd1498Szrj
256438fd1498Szrj if (processing_template_decl && result != error_mark_node)
256538fd1498Szrj {
256638fd1498Szrj if (INDIRECT_REF_P (result))
256738fd1498Szrj result = TREE_OPERAND (result, 0);
256838fd1498Szrj result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
256938fd1498Szrj SET_EXPR_LOCATION (result, input_location);
257038fd1498Szrj KOENIG_LOOKUP_P (result) = koenig_p;
257138fd1498Szrj release_tree_vector (orig_args);
257238fd1498Szrj result = convert_from_reference (result);
257338fd1498Szrj }
257438fd1498Szrj
257538fd1498Szrj /* Free or retain OVERLOADs from lookup. */
257638fd1498Szrj if (is_overloaded_fn (orig_fn))
257738fd1498Szrj lookup_keep (get_fns (orig_fn), processing_template_decl);
257838fd1498Szrj
257938fd1498Szrj return result;
258038fd1498Szrj }
258138fd1498Szrj
258238fd1498Szrj /* Finish a call to a postfix increment or decrement or EXPR. (Which
258338fd1498Szrj is indicated by CODE, which should be POSTINCREMENT_EXPR or
258438fd1498Szrj POSTDECREMENT_EXPR.) */
258538fd1498Szrj
258638fd1498Szrj cp_expr
finish_increment_expr(cp_expr expr,enum tree_code code)258738fd1498Szrj finish_increment_expr (cp_expr expr, enum tree_code code)
258838fd1498Szrj {
258938fd1498Szrj /* input_location holds the location of the trailing operator token.
259038fd1498Szrj Build a location of the form:
259138fd1498Szrj expr++
259238fd1498Szrj ~~~~^~
259338fd1498Szrj with the caret at the operator token, ranging from the start
259438fd1498Szrj of EXPR to the end of the operator token. */
259538fd1498Szrj location_t combined_loc = make_location (input_location,
259638fd1498Szrj expr.get_start (),
259738fd1498Szrj get_finish (input_location));
259838fd1498Szrj cp_expr result = build_x_unary_op (combined_loc, code, expr,
259938fd1498Szrj tf_warning_or_error);
260038fd1498Szrj /* TODO: build_x_unary_op doesn't honor the location, so set it here. */
260138fd1498Szrj result.set_location (combined_loc);
260238fd1498Szrj return result;
260338fd1498Szrj }
260438fd1498Szrj
260538fd1498Szrj /* Finish a use of `this'. Returns an expression for `this'. */
260638fd1498Szrj
260738fd1498Szrj tree
finish_this_expr(void)260838fd1498Szrj finish_this_expr (void)
260938fd1498Szrj {
261038fd1498Szrj tree result = NULL_TREE;
261138fd1498Szrj
261238fd1498Szrj if (current_class_ptr)
261338fd1498Szrj {
261438fd1498Szrj tree type = TREE_TYPE (current_class_ref);
261538fd1498Szrj
261638fd1498Szrj /* In a lambda expression, 'this' refers to the captured 'this'. */
261738fd1498Szrj if (LAMBDA_TYPE_P (type))
261838fd1498Szrj result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true);
261938fd1498Szrj else
262038fd1498Szrj result = current_class_ptr;
262138fd1498Szrj }
262238fd1498Szrj
262338fd1498Szrj if (result)
262438fd1498Szrj /* The keyword 'this' is a prvalue expression. */
262538fd1498Szrj return rvalue (result);
262638fd1498Szrj
262738fd1498Szrj tree fn = current_nonlambda_function ();
262838fd1498Szrj if (fn && DECL_STATIC_FUNCTION_P (fn))
262938fd1498Szrj error ("%<this%> is unavailable for static member functions");
263038fd1498Szrj else if (fn)
263138fd1498Szrj error ("invalid use of %<this%> in non-member function");
263238fd1498Szrj else
263338fd1498Szrj error ("invalid use of %<this%> at top level");
263438fd1498Szrj return error_mark_node;
263538fd1498Szrj }
263638fd1498Szrj
263738fd1498Szrj /* Finish a pseudo-destructor expression. If SCOPE is NULL, the
263838fd1498Szrj expression was of the form `OBJECT.~DESTRUCTOR' where DESTRUCTOR is
263938fd1498Szrj the TYPE for the type given. If SCOPE is non-NULL, the expression
264038fd1498Szrj was of the form `OBJECT.SCOPE::~DESTRUCTOR'. */
264138fd1498Szrj
264238fd1498Szrj tree
finish_pseudo_destructor_expr(tree object,tree scope,tree destructor,location_t loc)264338fd1498Szrj finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
264438fd1498Szrj location_t loc)
264538fd1498Szrj {
264638fd1498Szrj if (object == error_mark_node || destructor == error_mark_node)
264738fd1498Szrj return error_mark_node;
264838fd1498Szrj
264938fd1498Szrj gcc_assert (TYPE_P (destructor));
265038fd1498Szrj
265138fd1498Szrj if (!processing_template_decl)
265238fd1498Szrj {
265338fd1498Szrj if (scope == error_mark_node)
265438fd1498Szrj {
265538fd1498Szrj error_at (loc, "invalid qualifying scope in pseudo-destructor name");
265638fd1498Szrj return error_mark_node;
265738fd1498Szrj }
265838fd1498Szrj if (is_auto (destructor))
265938fd1498Szrj destructor = TREE_TYPE (object);
266038fd1498Szrj if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
266138fd1498Szrj {
266238fd1498Szrj error_at (loc,
266338fd1498Szrj "qualified type %qT does not match destructor name ~%qT",
266438fd1498Szrj scope, destructor);
266538fd1498Szrj return error_mark_node;
266638fd1498Szrj }
266738fd1498Szrj
266838fd1498Szrj
266938fd1498Szrj /* [expr.pseudo] says both:
267038fd1498Szrj
267138fd1498Szrj The type designated by the pseudo-destructor-name shall be
267238fd1498Szrj the same as the object type.
267338fd1498Szrj
267438fd1498Szrj and:
267538fd1498Szrj
267638fd1498Szrj The cv-unqualified versions of the object type and of the
267738fd1498Szrj type designated by the pseudo-destructor-name shall be the
267838fd1498Szrj same type.
267938fd1498Szrj
268038fd1498Szrj We implement the more generous second sentence, since that is
268138fd1498Szrj what most other compilers do. */
268238fd1498Szrj if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
268338fd1498Szrj destructor))
268438fd1498Szrj {
268538fd1498Szrj error_at (loc, "%qE is not of type %qT", object, destructor);
268638fd1498Szrj return error_mark_node;
268738fd1498Szrj }
268838fd1498Szrj }
268938fd1498Szrj
269038fd1498Szrj return build3_loc (loc, PSEUDO_DTOR_EXPR, void_type_node, object,
269138fd1498Szrj scope, destructor);
269238fd1498Szrj }
269338fd1498Szrj
269438fd1498Szrj /* Finish an expression of the form CODE EXPR. */
269538fd1498Szrj
269638fd1498Szrj cp_expr
finish_unary_op_expr(location_t op_loc,enum tree_code code,cp_expr expr,tsubst_flags_t complain)269738fd1498Szrj finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
269838fd1498Szrj tsubst_flags_t complain)
269938fd1498Szrj {
270038fd1498Szrj /* Build a location of the form:
270138fd1498Szrj ++expr
270238fd1498Szrj ^~~~~~
270338fd1498Szrj with the caret at the operator token, ranging from the start
270438fd1498Szrj of the operator token to the end of EXPR. */
270538fd1498Szrj location_t combined_loc = make_location (op_loc,
270638fd1498Szrj op_loc, expr.get_finish ());
270738fd1498Szrj cp_expr result = build_x_unary_op (combined_loc, code, expr, complain);
270838fd1498Szrj /* TODO: build_x_unary_op doesn't always honor the location. */
270938fd1498Szrj result.set_location (combined_loc);
271038fd1498Szrj
271158e805e6Szrj if (result == error_mark_node)
271258e805e6Szrj return result;
271338fd1498Szrj
271438fd1498Szrj if (!(complain & tf_warning))
271538fd1498Szrj return result;
271638fd1498Szrj
271758e805e6Szrj tree result_ovl = result;
271858e805e6Szrj tree expr_ovl = expr;
271938fd1498Szrj
272038fd1498Szrj if (!processing_template_decl)
272138fd1498Szrj expr_ovl = cp_fully_fold (expr_ovl);
272238fd1498Szrj
272338fd1498Szrj if (!CONSTANT_CLASS_P (expr_ovl)
272438fd1498Szrj || TREE_OVERFLOW_P (expr_ovl))
272538fd1498Szrj return result;
272638fd1498Szrj
272738fd1498Szrj if (!processing_template_decl)
272838fd1498Szrj result_ovl = cp_fully_fold (result_ovl);
272938fd1498Szrj
273038fd1498Szrj if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
273138fd1498Szrj overflow_warning (combined_loc, result_ovl);
273238fd1498Szrj
273338fd1498Szrj return result;
273438fd1498Szrj }
273538fd1498Szrj
273638fd1498Szrj /* Finish a compound-literal expression or C++11 functional cast with aggregate
273738fd1498Szrj initializer. TYPE is the type to which the CONSTRUCTOR in COMPOUND_LITERAL
273838fd1498Szrj is being cast. */
273938fd1498Szrj
274038fd1498Szrj tree
finish_compound_literal(tree type,tree compound_literal,tsubst_flags_t complain,fcl_t fcl_context)274138fd1498Szrj finish_compound_literal (tree type, tree compound_literal,
274238fd1498Szrj tsubst_flags_t complain,
274338fd1498Szrj fcl_t fcl_context)
274438fd1498Szrj {
274538fd1498Szrj if (type == error_mark_node)
274638fd1498Szrj return error_mark_node;
274738fd1498Szrj
274838fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
274938fd1498Szrj {
275038fd1498Szrj compound_literal
275138fd1498Szrj = finish_compound_literal (TREE_TYPE (type), compound_literal,
275238fd1498Szrj complain, fcl_context);
275338fd1498Szrj return cp_build_c_cast (type, compound_literal, complain);
275438fd1498Szrj }
275538fd1498Szrj
275638fd1498Szrj if (!TYPE_OBJ_P (type))
275738fd1498Szrj {
275838fd1498Szrj if (complain & tf_error)
275938fd1498Szrj error ("compound literal of non-object type %qT", type);
276038fd1498Szrj return error_mark_node;
276138fd1498Szrj }
276238fd1498Szrj
276338fd1498Szrj if (tree anode = type_uses_auto (type))
276438fd1498Szrj if (CLASS_PLACEHOLDER_TEMPLATE (anode))
276538fd1498Szrj {
276638fd1498Szrj type = do_auto_deduction (type, compound_literal, anode, complain,
276738fd1498Szrj adc_variable_type);
276838fd1498Szrj if (type == error_mark_node)
276938fd1498Szrj return error_mark_node;
277038fd1498Szrj }
277138fd1498Szrj
277238fd1498Szrj if (processing_template_decl)
277338fd1498Szrj {
277438fd1498Szrj TREE_TYPE (compound_literal) = type;
277538fd1498Szrj /* Mark the expression as a compound literal. */
277638fd1498Szrj TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
277738fd1498Szrj if (fcl_context == fcl_c99)
277838fd1498Szrj CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
277938fd1498Szrj return compound_literal;
278038fd1498Szrj }
278138fd1498Szrj
278238fd1498Szrj type = complete_type (type);
278338fd1498Szrj
278438fd1498Szrj if (TYPE_NON_AGGREGATE_CLASS (type))
278538fd1498Szrj {
278638fd1498Szrj /* Trying to deal with a CONSTRUCTOR instead of a TREE_LIST
278738fd1498Szrj everywhere that deals with function arguments would be a pain, so
278838fd1498Szrj just wrap it in a TREE_LIST. The parser set a flag so we know
278938fd1498Szrj that it came from T{} rather than T({}). */
279038fd1498Szrj CONSTRUCTOR_IS_DIRECT_INIT (compound_literal) = 1;
279138fd1498Szrj compound_literal = build_tree_list (NULL_TREE, compound_literal);
279238fd1498Szrj return build_functional_cast (type, compound_literal, complain);
279338fd1498Szrj }
279438fd1498Szrj
279538fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE
279638fd1498Szrj && check_array_initializer (NULL_TREE, type, compound_literal))
279738fd1498Szrj return error_mark_node;
279838fd1498Szrj compound_literal = reshape_init (type, compound_literal, complain);
279938fd1498Szrj if (SCALAR_TYPE_P (type)
280038fd1498Szrj && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)
280138fd1498Szrj && !check_narrowing (type, compound_literal, complain))
280238fd1498Szrj return error_mark_node;
280338fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE
280438fd1498Szrj && TYPE_DOMAIN (type) == NULL_TREE)
280538fd1498Szrj {
280638fd1498Szrj cp_complete_array_type_or_error (&type, compound_literal,
280738fd1498Szrj false, complain);
280838fd1498Szrj if (type == error_mark_node)
280938fd1498Szrj return error_mark_node;
281038fd1498Szrj }
281138fd1498Szrj compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL,
281238fd1498Szrj complain);
281338fd1498Szrj if (TREE_CODE (compound_literal) == CONSTRUCTOR)
281438fd1498Szrj {
281538fd1498Szrj TREE_HAS_CONSTRUCTOR (compound_literal) = true;
281638fd1498Szrj if (fcl_context == fcl_c99)
281738fd1498Szrj CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
281838fd1498Szrj }
281938fd1498Szrj
282038fd1498Szrj /* Put static/constant array temporaries in static variables. */
282138fd1498Szrj /* FIXME all C99 compound literals should be variables rather than C++
282238fd1498Szrj temporaries, unless they are used as an aggregate initializer. */
282338fd1498Szrj if ((!at_function_scope_p () || CP_TYPE_CONST_P (type))
282438fd1498Szrj && fcl_context == fcl_c99
282538fd1498Szrj && TREE_CODE (type) == ARRAY_TYPE
282638fd1498Szrj && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
282738fd1498Szrj && initializer_constant_valid_p (compound_literal, type))
282838fd1498Szrj {
282938fd1498Szrj tree decl = create_temporary_var (type);
283038fd1498Szrj DECL_INITIAL (decl) = compound_literal;
283138fd1498Szrj TREE_STATIC (decl) = 1;
283238fd1498Szrj if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type))
283338fd1498Szrj {
283438fd1498Szrj /* 5.19 says that a constant expression can include an
283538fd1498Szrj lvalue-rvalue conversion applied to "a glvalue of literal type
283638fd1498Szrj that refers to a non-volatile temporary object initialized
283738fd1498Szrj with a constant expression". Rather than try to communicate
283838fd1498Szrj that this VAR_DECL is a temporary, just mark it constexpr. */
283938fd1498Szrj DECL_DECLARED_CONSTEXPR_P (decl) = true;
284038fd1498Szrj DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
284138fd1498Szrj TREE_CONSTANT (decl) = true;
284238fd1498Szrj }
284338fd1498Szrj cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
284438fd1498Szrj decl = pushdecl_top_level (decl);
284538fd1498Szrj DECL_NAME (decl) = make_anon_name ();
284638fd1498Szrj SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
284738fd1498Szrj /* Make sure the destructor is callable. */
284838fd1498Szrj tree clean = cxx_maybe_build_cleanup (decl, complain);
284938fd1498Szrj if (clean == error_mark_node)
285038fd1498Szrj return error_mark_node;
285138fd1498Szrj return decl;
285238fd1498Szrj }
285338fd1498Szrj
285438fd1498Szrj /* Represent other compound literals with TARGET_EXPR so we produce
285538fd1498Szrj an lvalue, but can elide copies. */
285638fd1498Szrj if (!VECTOR_TYPE_P (type))
285738fd1498Szrj compound_literal = get_target_expr_sfinae (compound_literal, complain);
285838fd1498Szrj
285938fd1498Szrj return compound_literal;
286038fd1498Szrj }
286138fd1498Szrj
286238fd1498Szrj /* Return the declaration for the function-name variable indicated by
286338fd1498Szrj ID. */
286438fd1498Szrj
286538fd1498Szrj tree
finish_fname(tree id)286638fd1498Szrj finish_fname (tree id)
286738fd1498Szrj {
286838fd1498Szrj tree decl;
286938fd1498Szrj
287038fd1498Szrj decl = fname_decl (input_location, C_RID_CODE (id), id);
287138fd1498Szrj if (processing_template_decl && current_function_decl
287238fd1498Szrj && decl != error_mark_node)
287338fd1498Szrj decl = DECL_NAME (decl);
287438fd1498Szrj return decl;
287538fd1498Szrj }
287638fd1498Szrj
287738fd1498Szrj /* Finish a translation unit. */
287838fd1498Szrj
287938fd1498Szrj void
finish_translation_unit(void)288038fd1498Szrj finish_translation_unit (void)
288138fd1498Szrj {
288238fd1498Szrj /* In case there were missing closebraces,
288338fd1498Szrj get us back to the global binding level. */
288438fd1498Szrj pop_everything ();
288538fd1498Szrj while (current_namespace != global_namespace)
288638fd1498Szrj pop_namespace ();
288738fd1498Szrj
288838fd1498Szrj /* Do file scope __FUNCTION__ et al. */
288938fd1498Szrj finish_fname_decls ();
289038fd1498Szrj }
289138fd1498Szrj
289238fd1498Szrj /* Finish a template type parameter, specified as AGGR IDENTIFIER.
289338fd1498Szrj Returns the parameter. */
289438fd1498Szrj
289538fd1498Szrj tree
finish_template_type_parm(tree aggr,tree identifier)289638fd1498Szrj finish_template_type_parm (tree aggr, tree identifier)
289738fd1498Szrj {
289838fd1498Szrj if (aggr != class_type_node)
289938fd1498Szrj {
290038fd1498Szrj permerror (input_location, "template type parameters must use the keyword %<class%> or %<typename%>");
290138fd1498Szrj aggr = class_type_node;
290238fd1498Szrj }
290338fd1498Szrj
290438fd1498Szrj return build_tree_list (aggr, identifier);
290538fd1498Szrj }
290638fd1498Szrj
290738fd1498Szrj /* Finish a template template parameter, specified as AGGR IDENTIFIER.
290838fd1498Szrj Returns the parameter. */
290938fd1498Szrj
291038fd1498Szrj tree
finish_template_template_parm(tree aggr,tree identifier)291138fd1498Szrj finish_template_template_parm (tree aggr, tree identifier)
291238fd1498Szrj {
291338fd1498Szrj tree decl = build_decl (input_location,
291438fd1498Szrj TYPE_DECL, identifier, NULL_TREE);
291538fd1498Szrj
291638fd1498Szrj tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
291738fd1498Szrj DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
291838fd1498Szrj DECL_TEMPLATE_RESULT (tmpl) = decl;
291938fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
292038fd1498Szrj
292138fd1498Szrj // Associate the constraints with the underlying declaration,
292238fd1498Szrj // not the template.
292338fd1498Szrj tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
292438fd1498Szrj tree constr = build_constraints (reqs, NULL_TREE);
292538fd1498Szrj set_constraints (decl, constr);
292638fd1498Szrj
292738fd1498Szrj end_template_decl ();
292838fd1498Szrj
292938fd1498Szrj gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
293038fd1498Szrj
293138fd1498Szrj check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl),
293238fd1498Szrj /*is_primary=*/true, /*is_partial=*/false,
293338fd1498Szrj /*is_friend=*/0);
293438fd1498Szrj
293538fd1498Szrj return finish_template_type_parm (aggr, tmpl);
293638fd1498Szrj }
293738fd1498Szrj
293838fd1498Szrj /* ARGUMENT is the default-argument value for a template template
293938fd1498Szrj parameter. If ARGUMENT is invalid, issue error messages and return
294038fd1498Szrj the ERROR_MARK_NODE. Otherwise, ARGUMENT itself is returned. */
294138fd1498Szrj
294238fd1498Szrj tree
check_template_template_default_arg(tree argument)294338fd1498Szrj check_template_template_default_arg (tree argument)
294438fd1498Szrj {
294538fd1498Szrj if (TREE_CODE (argument) != TEMPLATE_DECL
294638fd1498Szrj && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM
294738fd1498Szrj && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
294838fd1498Szrj {
294938fd1498Szrj if (TREE_CODE (argument) == TYPE_DECL)
295038fd1498Szrj error ("invalid use of type %qT as a default value for a template "
295138fd1498Szrj "template-parameter", TREE_TYPE (argument));
295238fd1498Szrj else
295338fd1498Szrj error ("invalid default argument for a template template parameter");
295438fd1498Szrj return error_mark_node;
295538fd1498Szrj }
295638fd1498Szrj
295738fd1498Szrj return argument;
295838fd1498Szrj }
295938fd1498Szrj
296038fd1498Szrj /* Begin a class definition, as indicated by T. */
296138fd1498Szrj
296238fd1498Szrj tree
begin_class_definition(tree t)296338fd1498Szrj begin_class_definition (tree t)
296438fd1498Szrj {
296538fd1498Szrj if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
296638fd1498Szrj return error_mark_node;
296738fd1498Szrj
296838fd1498Szrj if (processing_template_parmlist)
296938fd1498Szrj {
297038fd1498Szrj error ("definition of %q#T inside template parameter list", t);
297138fd1498Szrj return error_mark_node;
297238fd1498Szrj }
297338fd1498Szrj
297438fd1498Szrj /* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733
297538fd1498Szrj are passed the same as decimal scalar types. */
297638fd1498Szrj if (TREE_CODE (t) == RECORD_TYPE
297738fd1498Szrj && !processing_template_decl)
297838fd1498Szrj {
297938fd1498Szrj tree ns = TYPE_CONTEXT (t);
298038fd1498Szrj if (ns && TREE_CODE (ns) == NAMESPACE_DECL
298138fd1498Szrj && DECL_CONTEXT (ns) == std_node
298238fd1498Szrj && DECL_NAME (ns)
298338fd1498Szrj && id_equal (DECL_NAME (ns), "decimal"))
298438fd1498Szrj {
298538fd1498Szrj const char *n = TYPE_NAME_STRING (t);
298638fd1498Szrj if ((strcmp (n, "decimal32") == 0)
298738fd1498Szrj || (strcmp (n, "decimal64") == 0)
298838fd1498Szrj || (strcmp (n, "decimal128") == 0))
298938fd1498Szrj TYPE_TRANSPARENT_AGGR (t) = 1;
299038fd1498Szrj }
299138fd1498Szrj }
299238fd1498Szrj
299338fd1498Szrj /* A non-implicit typename comes from code like:
299438fd1498Szrj
299538fd1498Szrj template <typename T> struct A {
299638fd1498Szrj template <typename U> struct A<T>::B ...
299738fd1498Szrj
299838fd1498Szrj This is erroneous. */
299938fd1498Szrj else if (TREE_CODE (t) == TYPENAME_TYPE)
300038fd1498Szrj {
300138fd1498Szrj error ("invalid definition of qualified type %qT", t);
300238fd1498Szrj t = error_mark_node;
300338fd1498Szrj }
300438fd1498Szrj
300538fd1498Szrj if (t == error_mark_node || ! MAYBE_CLASS_TYPE_P (t))
300638fd1498Szrj {
300738fd1498Szrj t = make_class_type (RECORD_TYPE);
300838fd1498Szrj pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
300938fd1498Szrj }
301038fd1498Szrj
301138fd1498Szrj if (TYPE_BEING_DEFINED (t))
301238fd1498Szrj {
301338fd1498Szrj t = make_class_type (TREE_CODE (t));
301438fd1498Szrj pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
301538fd1498Szrj }
301638fd1498Szrj maybe_process_partial_specialization (t);
301738fd1498Szrj pushclass (t);
301838fd1498Szrj TYPE_BEING_DEFINED (t) = 1;
301938fd1498Szrj class_binding_level->defining_class_p = 1;
302038fd1498Szrj
302138fd1498Szrj if (flag_pack_struct)
302238fd1498Szrj {
302338fd1498Szrj tree v;
302438fd1498Szrj TYPE_PACKED (t) = 1;
302538fd1498Szrj /* Even though the type is being defined for the first time
302638fd1498Szrj here, there might have been a forward declaration, so there
302738fd1498Szrj might be cv-qualified variants of T. */
302838fd1498Szrj for (v = TYPE_NEXT_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v))
302938fd1498Szrj TYPE_PACKED (v) = 1;
303038fd1498Szrj }
303138fd1498Szrj /* Reset the interface data, at the earliest possible
303238fd1498Szrj moment, as it might have been set via a class foo;
303338fd1498Szrj before. */
303438fd1498Szrj if (! TYPE_UNNAMED_P (t))
303538fd1498Szrj {
303638fd1498Szrj struct c_fileinfo *finfo = \
303738fd1498Szrj get_fileinfo (LOCATION_FILE (input_location));
303838fd1498Szrj CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
303938fd1498Szrj SET_CLASSTYPE_INTERFACE_UNKNOWN_X
304038fd1498Szrj (t, finfo->interface_unknown);
304138fd1498Szrj }
304238fd1498Szrj reset_specialization();
304338fd1498Szrj
304438fd1498Szrj /* Make a declaration for this class in its own scope. */
304538fd1498Szrj build_self_reference ();
304638fd1498Szrj
304738fd1498Szrj return t;
304838fd1498Szrj }
304938fd1498Szrj
305038fd1498Szrj /* Finish the member declaration given by DECL. */
305138fd1498Szrj
305238fd1498Szrj void
finish_member_declaration(tree decl)305338fd1498Szrj finish_member_declaration (tree decl)
305438fd1498Szrj {
305538fd1498Szrj if (decl == error_mark_node || decl == NULL_TREE)
305638fd1498Szrj return;
305738fd1498Szrj
305838fd1498Szrj if (decl == void_type_node)
305938fd1498Szrj /* The COMPONENT was a friend, not a member, and so there's
306038fd1498Szrj nothing for us to do. */
306138fd1498Szrj return;
306238fd1498Szrj
306338fd1498Szrj /* We should see only one DECL at a time. */
306438fd1498Szrj gcc_assert (DECL_CHAIN (decl) == NULL_TREE);
306538fd1498Szrj
306638fd1498Szrj /* Don't add decls after definition. */
306738fd1498Szrj gcc_assert (TYPE_BEING_DEFINED (current_class_type)
306838fd1498Szrj /* We can add lambda types when late parsing default
306938fd1498Szrj arguments. */
307038fd1498Szrj || LAMBDA_TYPE_P (TREE_TYPE (decl)));
307138fd1498Szrj
307238fd1498Szrj /* Set up access control for DECL. */
307338fd1498Szrj TREE_PRIVATE (decl)
307438fd1498Szrj = (current_access_specifier == access_private_node);
307538fd1498Szrj TREE_PROTECTED (decl)
307638fd1498Szrj = (current_access_specifier == access_protected_node);
307738fd1498Szrj if (TREE_CODE (decl) == TEMPLATE_DECL)
307838fd1498Szrj {
307938fd1498Szrj TREE_PRIVATE (DECL_TEMPLATE_RESULT (decl)) = TREE_PRIVATE (decl);
308038fd1498Szrj TREE_PROTECTED (DECL_TEMPLATE_RESULT (decl)) = TREE_PROTECTED (decl);
308138fd1498Szrj }
308238fd1498Szrj
308338fd1498Szrj /* Mark the DECL as a member of the current class, unless it's
308438fd1498Szrj a member of an enumeration. */
308538fd1498Szrj if (TREE_CODE (decl) != CONST_DECL)
308638fd1498Szrj DECL_CONTEXT (decl) = current_class_type;
308738fd1498Szrj
308838fd1498Szrj if (TREE_CODE (decl) == USING_DECL)
308938fd1498Szrj /* For now, ignore class-scope USING_DECLS, so that debugging
309038fd1498Szrj backends do not see them. */
309138fd1498Szrj DECL_IGNORED_P (decl) = 1;
309238fd1498Szrj
309338fd1498Szrj /* Check for bare parameter packs in the non-static data member
309438fd1498Szrj declaration. */
309538fd1498Szrj if (TREE_CODE (decl) == FIELD_DECL)
309638fd1498Szrj {
309738fd1498Szrj if (check_for_bare_parameter_packs (TREE_TYPE (decl)))
309838fd1498Szrj TREE_TYPE (decl) = error_mark_node;
309938fd1498Szrj if (check_for_bare_parameter_packs (DECL_ATTRIBUTES (decl)))
310038fd1498Szrj DECL_ATTRIBUTES (decl) = NULL_TREE;
310138fd1498Szrj }
310238fd1498Szrj
310338fd1498Szrj /* [dcl.link]
310438fd1498Szrj
310538fd1498Szrj A C language linkage is ignored for the names of class members
310638fd1498Szrj and the member function type of class member functions. */
310738fd1498Szrj if (DECL_LANG_SPECIFIC (decl))
310838fd1498Szrj SET_DECL_LANGUAGE (decl, lang_cplusplus);
310938fd1498Szrj
311038fd1498Szrj bool add = false;
311138fd1498Szrj
311238fd1498Szrj /* Functions and non-functions are added differently. */
311338fd1498Szrj if (DECL_DECLARES_FUNCTION_P (decl))
311438fd1498Szrj add = add_method (current_class_type, decl, false);
311538fd1498Szrj /* Enter the DECL into the scope of the class, if the class
311638fd1498Szrj isn't a closure (whose fields are supposed to be unnamed). */
311738fd1498Szrj else if (CLASSTYPE_LAMBDA_EXPR (current_class_type)
311838fd1498Szrj || pushdecl_class_level (decl))
311938fd1498Szrj add = true;
312038fd1498Szrj
312138fd1498Szrj if (add)
312238fd1498Szrj {
312338fd1498Szrj /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
312438fd1498Szrj go at the beginning. The reason is that
312538fd1498Szrj legacy_nonfn_member_lookup searches the list in order, and we
312638fd1498Szrj want a field name to override a type name so that the "struct
312738fd1498Szrj stat hack" will work. In particular:
312838fd1498Szrj
312938fd1498Szrj struct S { enum E { }; static const int E = 5; int ary[S::E]; } s;
313038fd1498Szrj
313138fd1498Szrj is valid. */
313238fd1498Szrj
313338fd1498Szrj if (TREE_CODE (decl) == TYPE_DECL)
313438fd1498Szrj TYPE_FIELDS (current_class_type)
313538fd1498Szrj = chainon (TYPE_FIELDS (current_class_type), decl);
313638fd1498Szrj else
313738fd1498Szrj {
313838fd1498Szrj DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type);
313938fd1498Szrj TYPE_FIELDS (current_class_type) = decl;
314038fd1498Szrj }
314138fd1498Szrj
314238fd1498Szrj maybe_add_class_template_decl_list (current_class_type, decl,
314338fd1498Szrj /*friend_p=*/0);
314438fd1498Szrj }
314538fd1498Szrj }
314638fd1498Szrj
314738fd1498Szrj /* Finish processing a complete template declaration. The PARMS are
314838fd1498Szrj the template parameters. */
314938fd1498Szrj
315038fd1498Szrj void
finish_template_decl(tree parms)315138fd1498Szrj finish_template_decl (tree parms)
315238fd1498Szrj {
315338fd1498Szrj if (parms)
315438fd1498Szrj end_template_decl ();
315538fd1498Szrj else
315638fd1498Szrj end_specialization ();
315738fd1498Szrj }
315838fd1498Szrj
315938fd1498Szrj // Returns the template type of the class scope being entered. If we're
316038fd1498Szrj // entering a constrained class scope. TYPE is the class template
316138fd1498Szrj // scope being entered and we may need to match the intended type with
316238fd1498Szrj // a constrained specialization. For example:
316338fd1498Szrj //
316438fd1498Szrj // template<Object T>
316538fd1498Szrj // struct S { void f(); }; #1
316638fd1498Szrj //
316738fd1498Szrj // template<Object T>
316838fd1498Szrj // void S<T>::f() { } #2
316938fd1498Szrj //
317038fd1498Szrj // We check, in #2, that S<T> refers precisely to the type declared by
317138fd1498Szrj // #1 (i.e., that the constraints match). Note that the following should
317238fd1498Szrj // be an error since there is no specialization of S<T> that is
317338fd1498Szrj // unconstrained, but this is not diagnosed here.
317438fd1498Szrj //
317538fd1498Szrj // template<typename T>
317638fd1498Szrj // void S<T>::f() { }
317738fd1498Szrj //
317838fd1498Szrj // We cannot diagnose this problem here since this function also matches
317938fd1498Szrj // qualified template names that are not part of a definition. For example:
318038fd1498Szrj //
318138fd1498Szrj // template<Integral T, Floating_point U>
318238fd1498Szrj // typename pair<T, U>::first_type void f(T, U);
318338fd1498Szrj //
318438fd1498Szrj // Here, it is unlikely that there is a partial specialization of
318538fd1498Szrj // pair constrained for for Integral and Floating_point arguments.
318638fd1498Szrj //
318738fd1498Szrj // The general rule is: if a constrained specialization with matching
318838fd1498Szrj // constraints is found return that type. Also note that if TYPE is not a
318938fd1498Szrj // class-type (e.g. a typename type), then no fixup is needed.
319038fd1498Szrj
319138fd1498Szrj static tree
fixup_template_type(tree type)319238fd1498Szrj fixup_template_type (tree type)
319338fd1498Szrj {
319438fd1498Szrj // Find the template parameter list at the a depth appropriate to
319538fd1498Szrj // the scope we're trying to enter.
319638fd1498Szrj tree parms = current_template_parms;
319738fd1498Szrj int depth = template_class_depth (type);
319838fd1498Szrj for (int n = processing_template_decl; n > depth && parms; --n)
319938fd1498Szrj parms = TREE_CHAIN (parms);
320038fd1498Szrj if (!parms)
320138fd1498Szrj return type;
320238fd1498Szrj tree cur_reqs = TEMPLATE_PARMS_CONSTRAINTS (parms);
320338fd1498Szrj tree cur_constr = build_constraints (cur_reqs, NULL_TREE);
320438fd1498Szrj
320538fd1498Szrj // Search for a specialization whose type and constraints match.
320638fd1498Szrj tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
320738fd1498Szrj tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
320838fd1498Szrj while (specs)
320938fd1498Szrj {
321038fd1498Szrj tree spec_constr = get_constraints (TREE_VALUE (specs));
321138fd1498Szrj
321238fd1498Szrj // If the type and constraints match a specialization, then we
321338fd1498Szrj // are entering that type.
321438fd1498Szrj if (same_type_p (type, TREE_TYPE (specs))
321538fd1498Szrj && equivalent_constraints (cur_constr, spec_constr))
321638fd1498Szrj return TREE_TYPE (specs);
321738fd1498Szrj specs = TREE_CHAIN (specs);
321838fd1498Szrj }
321938fd1498Szrj
322038fd1498Szrj // If no specialization matches, then must return the type
322138fd1498Szrj // previously found.
322238fd1498Szrj return type;
322338fd1498Szrj }
322438fd1498Szrj
322538fd1498Szrj /* Finish processing a template-id (which names a type) of the form
322638fd1498Szrj NAME < ARGS >. Return the TYPE_DECL for the type named by the
322738fd1498Szrj template-id. If ENTERING_SCOPE is nonzero we are about to enter
322838fd1498Szrj the scope of template-id indicated. */
322938fd1498Szrj
323038fd1498Szrj tree
finish_template_type(tree name,tree args,int entering_scope)323138fd1498Szrj finish_template_type (tree name, tree args, int entering_scope)
323238fd1498Szrj {
323338fd1498Szrj tree type;
323438fd1498Szrj
323538fd1498Szrj type = lookup_template_class (name, args,
323638fd1498Szrj NULL_TREE, NULL_TREE, entering_scope,
323738fd1498Szrj tf_warning_or_error | tf_user);
323838fd1498Szrj
323938fd1498Szrj /* If we might be entering the scope of a partial specialization,
324038fd1498Szrj find the one with the right constraints. */
324138fd1498Szrj if (flag_concepts
324238fd1498Szrj && entering_scope
324338fd1498Szrj && CLASS_TYPE_P (type)
324438fd1498Szrj && CLASSTYPE_TEMPLATE_INFO (type)
324538fd1498Szrj && dependent_type_p (type)
324638fd1498Szrj && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
324738fd1498Szrj type = fixup_template_type (type);
324838fd1498Szrj
324938fd1498Szrj if (type == error_mark_node)
325038fd1498Szrj return type;
325138fd1498Szrj else if (CLASS_TYPE_P (type) && !alias_type_or_template_p (type))
325238fd1498Szrj return TYPE_STUB_DECL (type);
325338fd1498Szrj else
325438fd1498Szrj return TYPE_NAME (type);
325538fd1498Szrj }
325638fd1498Szrj
325738fd1498Szrj /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER.
325838fd1498Szrj Return a TREE_LIST containing the ACCESS_SPECIFIER and the
325938fd1498Szrj BASE_CLASS, or NULL_TREE if an error occurred. The
326038fd1498Szrj ACCESS_SPECIFIER is one of
326138fd1498Szrj access_{default,public,protected_private}_node. For a virtual base
326238fd1498Szrj we set TREE_TYPE. */
326338fd1498Szrj
326438fd1498Szrj tree
finish_base_specifier(tree base,tree access,bool virtual_p)326538fd1498Szrj finish_base_specifier (tree base, tree access, bool virtual_p)
326638fd1498Szrj {
326738fd1498Szrj tree result;
326838fd1498Szrj
326938fd1498Szrj if (base == error_mark_node)
327038fd1498Szrj {
327138fd1498Szrj error ("invalid base-class specification");
327238fd1498Szrj result = NULL_TREE;
327338fd1498Szrj }
327438fd1498Szrj else if (! MAYBE_CLASS_TYPE_P (base))
327538fd1498Szrj {
327638fd1498Szrj error ("%qT is not a class type", base);
327738fd1498Szrj result = NULL_TREE;
327838fd1498Szrj }
327938fd1498Szrj else
328038fd1498Szrj {
328138fd1498Szrj if (cp_type_quals (base) != 0)
328238fd1498Szrj {
328338fd1498Szrj /* DR 484: Can a base-specifier name a cv-qualified
328438fd1498Szrj class type? */
328538fd1498Szrj base = TYPE_MAIN_VARIANT (base);
328638fd1498Szrj }
328738fd1498Szrj result = build_tree_list (access, base);
328838fd1498Szrj if (virtual_p)
328938fd1498Szrj TREE_TYPE (result) = integer_type_node;
329038fd1498Szrj }
329138fd1498Szrj
329238fd1498Szrj return result;
329338fd1498Szrj }
329438fd1498Szrj
329538fd1498Szrj /* If FNS is a member function, a set of member functions, or a
329638fd1498Szrj template-id referring to one or more member functions, return a
329738fd1498Szrj BASELINK for FNS, incorporating the current access context.
329838fd1498Szrj Otherwise, return FNS unchanged. */
329938fd1498Szrj
330038fd1498Szrj tree
baselink_for_fns(tree fns)330138fd1498Szrj baselink_for_fns (tree fns)
330238fd1498Szrj {
330338fd1498Szrj tree scope;
330438fd1498Szrj tree cl;
330538fd1498Szrj
330638fd1498Szrj if (BASELINK_P (fns)
330738fd1498Szrj || error_operand_p (fns))
330838fd1498Szrj return fns;
330938fd1498Szrj
331038fd1498Szrj scope = ovl_scope (fns);
331138fd1498Szrj if (!CLASS_TYPE_P (scope))
331238fd1498Szrj return fns;
331338fd1498Szrj
331438fd1498Szrj cl = currently_open_derived_class (scope);
331538fd1498Szrj if (!cl)
331638fd1498Szrj cl = scope;
331738fd1498Szrj cl = TYPE_BINFO (cl);
331838fd1498Szrj return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
331938fd1498Szrj }
332038fd1498Szrj
332138fd1498Szrj /* Returns true iff DECL is a variable from a function outside
332238fd1498Szrj the current one. */
332338fd1498Szrj
332438fd1498Szrj static bool
outer_var_p(tree decl)332538fd1498Szrj outer_var_p (tree decl)
332638fd1498Szrj {
332738fd1498Szrj return ((VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)
332838fd1498Szrj && DECL_FUNCTION_SCOPE_P (decl)
332938fd1498Szrj /* Don't get confused by temporaries. */
333038fd1498Szrj && DECL_NAME (decl)
333138fd1498Szrj && (DECL_CONTEXT (decl) != current_function_decl
333238fd1498Szrj || parsing_nsdmi ()));
333338fd1498Szrj }
333438fd1498Szrj
333538fd1498Szrj /* As above, but also checks that DECL is automatic. */
333638fd1498Szrj
333738fd1498Szrj bool
outer_automatic_var_p(tree decl)333838fd1498Szrj outer_automatic_var_p (tree decl)
333938fd1498Szrj {
334038fd1498Szrj return (outer_var_p (decl)
334138fd1498Szrj && !TREE_STATIC (decl));
334238fd1498Szrj }
334338fd1498Szrj
334438fd1498Szrj /* DECL satisfies outer_automatic_var_p. Possibly complain about it or
334538fd1498Szrj rewrite it for lambda capture.
334638fd1498Szrj
334738fd1498Szrj If ODR_USE is true, we're being called from mark_use, and we complain about
334838fd1498Szrj use of constant variables. If ODR_USE is false, we're being called for the
334938fd1498Szrj id-expression, and we do lambda capture. */
335038fd1498Szrj
335138fd1498Szrj tree
process_outer_var_ref(tree decl,tsubst_flags_t complain,bool odr_use)335238fd1498Szrj process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
335338fd1498Szrj {
335438fd1498Szrj if (cp_unevaluated_operand)
335538fd1498Szrj /* It's not a use (3.2) if we're in an unevaluated context. */
335638fd1498Szrj return decl;
335738fd1498Szrj if (decl == error_mark_node)
335838fd1498Szrj return decl;
335938fd1498Szrj
336038fd1498Szrj tree context = DECL_CONTEXT (decl);
336138fd1498Szrj tree containing_function = current_function_decl;
336238fd1498Szrj tree lambda_stack = NULL_TREE;
336338fd1498Szrj tree lambda_expr = NULL_TREE;
336438fd1498Szrj tree initializer = convert_from_reference (decl);
336538fd1498Szrj
336638fd1498Szrj /* Mark it as used now even if the use is ill-formed. */
336738fd1498Szrj if (!mark_used (decl, complain))
336838fd1498Szrj return error_mark_node;
336938fd1498Szrj
337038fd1498Szrj if (parsing_nsdmi ())
337138fd1498Szrj containing_function = NULL_TREE;
337238fd1498Szrj
337338fd1498Szrj if (containing_function && LAMBDA_FUNCTION_P (containing_function))
337438fd1498Szrj {
337538fd1498Szrj /* Check whether we've already built a proxy. */
337638fd1498Szrj tree var = decl;
337738fd1498Szrj while (is_normal_capture_proxy (var))
337838fd1498Szrj var = DECL_CAPTURED_VARIABLE (var);
337938fd1498Szrj tree d = retrieve_local_specialization (var);
338038fd1498Szrj
338138fd1498Szrj if (d && d != decl && is_capture_proxy (d))
338238fd1498Szrj {
338338fd1498Szrj if (DECL_CONTEXT (d) == containing_function)
338438fd1498Szrj /* We already have an inner proxy. */
338538fd1498Szrj return d;
338638fd1498Szrj else
338738fd1498Szrj /* We need to capture an outer proxy. */
338838fd1498Szrj return process_outer_var_ref (d, complain, odr_use);
338938fd1498Szrj }
339038fd1498Szrj }
339138fd1498Szrj
339238fd1498Szrj /* If we are in a lambda function, we can move out until we hit
339338fd1498Szrj 1. the context,
339438fd1498Szrj 2. a non-lambda function, or
339538fd1498Szrj 3. a non-default capturing lambda function. */
339638fd1498Szrj while (context != containing_function
339738fd1498Szrj /* containing_function can be null with invalid generic lambdas. */
339838fd1498Szrj && containing_function
339938fd1498Szrj && LAMBDA_FUNCTION_P (containing_function))
340038fd1498Szrj {
340138fd1498Szrj tree closure = DECL_CONTEXT (containing_function);
340238fd1498Szrj lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);
340338fd1498Szrj
340438fd1498Szrj if (TYPE_CLASS_SCOPE_P (closure))
340538fd1498Szrj /* A lambda in an NSDMI (c++/64496). */
340638fd1498Szrj break;
340738fd1498Szrj
340838fd1498Szrj if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
340938fd1498Szrj == CPLD_NONE)
341038fd1498Szrj break;
341138fd1498Szrj
341238fd1498Szrj lambda_stack = tree_cons (NULL_TREE,
341338fd1498Szrj lambda_expr,
341438fd1498Szrj lambda_stack);
341538fd1498Szrj
341638fd1498Szrj containing_function
341738fd1498Szrj = decl_function_context (containing_function);
341838fd1498Szrj }
341938fd1498Szrj
342038fd1498Szrj /* In a lambda within a template, wait until instantiation
342158e805e6Szrj time to implicitly capture a dependent type. */
342238fd1498Szrj if (context == containing_function
342358e805e6Szrj && dependent_type_p (TREE_TYPE (decl)))
342438fd1498Szrj return decl;
342538fd1498Szrj
342638fd1498Szrj if (lambda_expr && VAR_P (decl)
342738fd1498Szrj && DECL_ANON_UNION_VAR_P (decl))
342838fd1498Szrj {
342938fd1498Szrj if (complain & tf_error)
343038fd1498Szrj error ("cannot capture member %qD of anonymous union", decl);
343138fd1498Szrj return error_mark_node;
343238fd1498Szrj }
343338fd1498Szrj /* Do lambda capture when processing the id-expression, not when
343438fd1498Szrj odr-using a variable. */
343538fd1498Szrj if (!odr_use && context == containing_function)
343638fd1498Szrj {
343738fd1498Szrj decl = add_default_capture (lambda_stack,
343838fd1498Szrj /*id=*/DECL_NAME (decl),
343938fd1498Szrj initializer);
344038fd1498Szrj }
344138fd1498Szrj /* Only an odr-use of an outer automatic variable causes an
344238fd1498Szrj error, and a constant variable can decay to a prvalue
344338fd1498Szrj constant without odr-use. So don't complain yet. */
344438fd1498Szrj else if (!odr_use && decl_constant_var_p (decl))
344538fd1498Szrj return decl;
344638fd1498Szrj else if (lambda_expr)
344738fd1498Szrj {
344838fd1498Szrj if (complain & tf_error)
344938fd1498Szrj {
345038fd1498Szrj error ("%qD is not captured", decl);
345138fd1498Szrj tree closure = LAMBDA_EXPR_CLOSURE (lambda_expr);
345238fd1498Szrj if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
345338fd1498Szrj == CPLD_NONE)
345438fd1498Szrj inform (location_of (closure),
345538fd1498Szrj "the lambda has no capture-default");
345638fd1498Szrj else if (TYPE_CLASS_SCOPE_P (closure))
345738fd1498Szrj inform (UNKNOWN_LOCATION, "lambda in local class %q+T cannot "
345838fd1498Szrj "capture variables from the enclosing context",
345938fd1498Szrj TYPE_CONTEXT (closure));
346038fd1498Szrj inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl);
346138fd1498Szrj }
346238fd1498Szrj return error_mark_node;
346338fd1498Szrj }
346438fd1498Szrj else
346538fd1498Szrj {
346638fd1498Szrj if (complain & tf_error)
346738fd1498Szrj {
346838fd1498Szrj error (VAR_P (decl)
346938fd1498Szrj ? G_("use of local variable with automatic storage from "
347038fd1498Szrj "containing function")
347138fd1498Szrj : G_("use of parameter from containing function"));
347238fd1498Szrj inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl);
347338fd1498Szrj }
347438fd1498Szrj return error_mark_node;
347538fd1498Szrj }
347638fd1498Szrj return decl;
347738fd1498Szrj }
347838fd1498Szrj
347938fd1498Szrj /* ID_EXPRESSION is a representation of parsed, but unprocessed,
348038fd1498Szrj id-expression. (See cp_parser_id_expression for details.) SCOPE,
348138fd1498Szrj if non-NULL, is the type or namespace used to explicitly qualify
348238fd1498Szrj ID_EXPRESSION. DECL is the entity to which that name has been
348338fd1498Szrj resolved.
348438fd1498Szrj
348538fd1498Szrj *CONSTANT_EXPRESSION_P is true if we are presently parsing a
348638fd1498Szrj constant-expression. In that case, *NON_CONSTANT_EXPRESSION_P will
348738fd1498Szrj be set to true if this expression isn't permitted in a
348838fd1498Szrj constant-expression, but it is otherwise not set by this function.
348938fd1498Szrj *ALLOW_NON_CONSTANT_EXPRESSION_P is true if we are parsing a
349038fd1498Szrj constant-expression, but a non-constant expression is also
349138fd1498Szrj permissible.
349238fd1498Szrj
349338fd1498Szrj DONE is true if this expression is a complete postfix-expression;
349438fd1498Szrj it is false if this expression is followed by '->', '[', '(', etc.
349538fd1498Szrj ADDRESS_P is true iff this expression is the operand of '&'.
349638fd1498Szrj TEMPLATE_P is true iff the qualified-id was of the form
349738fd1498Szrj "A::template B". TEMPLATE_ARG_P is true iff this qualified name
349838fd1498Szrj appears as a template argument.
349938fd1498Szrj
350038fd1498Szrj If an error occurs, and it is the kind of error that might cause
350138fd1498Szrj the parser to abort a tentative parse, *ERROR_MSG is filled in. It
350238fd1498Szrj is the caller's responsibility to issue the message. *ERROR_MSG
350338fd1498Szrj will be a string with static storage duration, so the caller need
350438fd1498Szrj not "free" it.
350538fd1498Szrj
350638fd1498Szrj Return an expression for the entity, after issuing appropriate
350738fd1498Szrj diagnostics. This function is also responsible for transforming a
350838fd1498Szrj reference to a non-static member into a COMPONENT_REF that makes
350938fd1498Szrj the use of "this" explicit.
351038fd1498Szrj
351138fd1498Szrj Upon return, *IDK will be filled in appropriately. */
351238fd1498Szrj cp_expr
finish_id_expression(tree id_expression,tree decl,tree scope,cp_id_kind * idk,bool integral_constant_expression_p,bool allow_non_integral_constant_expression_p,bool * non_integral_constant_expression_p,bool template_p,bool done,bool address_p,bool template_arg_p,const char ** error_msg,location_t location)351338fd1498Szrj finish_id_expression (tree id_expression,
351438fd1498Szrj tree decl,
351538fd1498Szrj tree scope,
351638fd1498Szrj cp_id_kind *idk,
351738fd1498Szrj bool integral_constant_expression_p,
351838fd1498Szrj bool allow_non_integral_constant_expression_p,
351938fd1498Szrj bool *non_integral_constant_expression_p,
352038fd1498Szrj bool template_p,
352138fd1498Szrj bool done,
352238fd1498Szrj bool address_p,
352338fd1498Szrj bool template_arg_p,
352438fd1498Szrj const char **error_msg,
352538fd1498Szrj location_t location)
352638fd1498Szrj {
352738fd1498Szrj decl = strip_using_decl (decl);
352838fd1498Szrj
352938fd1498Szrj /* Initialize the output parameters. */
353038fd1498Szrj *idk = CP_ID_KIND_NONE;
353138fd1498Szrj *error_msg = NULL;
353238fd1498Szrj
353338fd1498Szrj if (id_expression == error_mark_node)
353438fd1498Szrj return error_mark_node;
353538fd1498Szrj /* If we have a template-id, then no further lookup is
353638fd1498Szrj required. If the template-id was for a template-class, we
353738fd1498Szrj will sometimes have a TYPE_DECL at this point. */
353838fd1498Szrj else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
353938fd1498Szrj || TREE_CODE (decl) == TYPE_DECL)
354038fd1498Szrj ;
354138fd1498Szrj /* Look up the name. */
354238fd1498Szrj else
354338fd1498Szrj {
354438fd1498Szrj if (decl == error_mark_node)
354538fd1498Szrj {
354638fd1498Szrj /* Name lookup failed. */
354738fd1498Szrj if (scope
354838fd1498Szrj && (!TYPE_P (scope)
354938fd1498Szrj || (!dependent_type_p (scope)
355038fd1498Szrj && !(identifier_p (id_expression)
355138fd1498Szrj && IDENTIFIER_CONV_OP_P (id_expression)
355238fd1498Szrj && dependent_type_p (TREE_TYPE (id_expression))))))
355338fd1498Szrj {
355438fd1498Szrj /* If the qualifying type is non-dependent (and the name
355538fd1498Szrj does not name a conversion operator to a dependent
355638fd1498Szrj type), issue an error. */
355738fd1498Szrj qualified_name_lookup_error (scope, id_expression, decl, location);
355838fd1498Szrj return error_mark_node;
355938fd1498Szrj }
356038fd1498Szrj else if (!scope)
356138fd1498Szrj {
356238fd1498Szrj /* It may be resolved via Koenig lookup. */
356338fd1498Szrj *idk = CP_ID_KIND_UNQUALIFIED;
356438fd1498Szrj return id_expression;
356538fd1498Szrj }
356638fd1498Szrj else
356738fd1498Szrj decl = id_expression;
356838fd1498Szrj }
356938fd1498Szrj /* If DECL is a variable that would be out of scope under
357038fd1498Szrj ANSI/ISO rules, but in scope in the ARM, name lookup
357138fd1498Szrj will succeed. Issue a diagnostic here. */
357238fd1498Szrj else
357338fd1498Szrj decl = check_for_out_of_scope_variable (decl);
357438fd1498Szrj
357538fd1498Szrj /* Remember that the name was used in the definition of
357638fd1498Szrj the current class so that we can check later to see if
357738fd1498Szrj the meaning would have been different after the class
357838fd1498Szrj was entirely defined. */
357938fd1498Szrj if (!scope && decl != error_mark_node && identifier_p (id_expression))
358038fd1498Szrj maybe_note_name_used_in_class (id_expression, decl);
358138fd1498Szrj
358238fd1498Szrj /* A use in unevaluated operand might not be instantiated appropriately
358338fd1498Szrj if tsubst_copy builds a dummy parm, or if we never instantiate a
358438fd1498Szrj generic lambda, so mark it now. */
358538fd1498Szrj if (processing_template_decl && cp_unevaluated_operand)
358638fd1498Szrj mark_type_use (decl);
358738fd1498Szrj
358838fd1498Szrj /* Disallow uses of local variables from containing functions, except
358938fd1498Szrj within lambda-expressions. */
359038fd1498Szrj if (outer_automatic_var_p (decl))
359138fd1498Szrj {
359238fd1498Szrj decl = process_outer_var_ref (decl, tf_warning_or_error);
359338fd1498Szrj if (decl == error_mark_node)
359438fd1498Szrj return error_mark_node;
359538fd1498Szrj }
359638fd1498Szrj
359738fd1498Szrj /* Also disallow uses of function parameters outside the function
359838fd1498Szrj body, except inside an unevaluated context (i.e. decltype). */
359938fd1498Szrj if (TREE_CODE (decl) == PARM_DECL
360038fd1498Szrj && DECL_CONTEXT (decl) == NULL_TREE
360138fd1498Szrj && !cp_unevaluated_operand)
360238fd1498Szrj {
360338fd1498Szrj *error_msg = G_("use of parameter outside function body");
360438fd1498Szrj return error_mark_node;
360538fd1498Szrj }
360638fd1498Szrj }
360738fd1498Szrj
360838fd1498Szrj /* If we didn't find anything, or what we found was a type,
360938fd1498Szrj then this wasn't really an id-expression. */
361038fd1498Szrj if (TREE_CODE (decl) == TEMPLATE_DECL
361138fd1498Szrj && !DECL_FUNCTION_TEMPLATE_P (decl))
361238fd1498Szrj {
361338fd1498Szrj *error_msg = G_("missing template arguments");
361438fd1498Szrj return error_mark_node;
361538fd1498Szrj }
361638fd1498Szrj else if (TREE_CODE (decl) == TYPE_DECL
361738fd1498Szrj || TREE_CODE (decl) == NAMESPACE_DECL)
361838fd1498Szrj {
361938fd1498Szrj *error_msg = G_("expected primary-expression");
362038fd1498Szrj return error_mark_node;
362138fd1498Szrj }
362238fd1498Szrj
362338fd1498Szrj /* If the name resolved to a template parameter, there is no
362438fd1498Szrj need to look it up again later. */
362538fd1498Szrj if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl))
362638fd1498Szrj || TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
362738fd1498Szrj {
362838fd1498Szrj tree r;
362938fd1498Szrj
363038fd1498Szrj *idk = CP_ID_KIND_NONE;
363138fd1498Szrj if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
363238fd1498Szrj decl = TEMPLATE_PARM_DECL (decl);
363338fd1498Szrj r = convert_from_reference (DECL_INITIAL (decl));
363438fd1498Szrj
363538fd1498Szrj if (integral_constant_expression_p
363638fd1498Szrj && !dependent_type_p (TREE_TYPE (decl))
363738fd1498Szrj && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r))))
363838fd1498Szrj {
363938fd1498Szrj if (!allow_non_integral_constant_expression_p)
364038fd1498Szrj error ("template parameter %qD of type %qT is not allowed in "
364138fd1498Szrj "an integral constant expression because it is not of "
364238fd1498Szrj "integral or enumeration type", decl, TREE_TYPE (decl));
364338fd1498Szrj *non_integral_constant_expression_p = true;
364438fd1498Szrj }
364538fd1498Szrj return r;
364638fd1498Szrj }
364738fd1498Szrj else
364838fd1498Szrj {
364938fd1498Szrj bool dependent_p = type_dependent_expression_p (decl);
365038fd1498Szrj
365138fd1498Szrj /* If the declaration was explicitly qualified indicate
365238fd1498Szrj that. The semantics of `A::f(3)' are different than
365338fd1498Szrj `f(3)' if `f' is virtual. */
365438fd1498Szrj *idk = (scope
365538fd1498Szrj ? CP_ID_KIND_QUALIFIED
365638fd1498Szrj : (TREE_CODE (decl) == TEMPLATE_ID_EXPR
365738fd1498Szrj ? CP_ID_KIND_TEMPLATE_ID
365838fd1498Szrj : (dependent_p
365938fd1498Szrj ? CP_ID_KIND_UNQUALIFIED_DEPENDENT
366038fd1498Szrj : CP_ID_KIND_UNQUALIFIED)));
366138fd1498Szrj
366238fd1498Szrj if (dependent_p
366338fd1498Szrj && DECL_P (decl)
366438fd1498Szrj && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
366538fd1498Szrj /* Dependent type attributes on the decl mean that the TREE_TYPE is
366638fd1498Szrj wrong, so just return the identifier. */
366738fd1498Szrj return id_expression;
366838fd1498Szrj
366938fd1498Szrj if (TREE_CODE (decl) == NAMESPACE_DECL)
367038fd1498Szrj {
367138fd1498Szrj error ("use of namespace %qD as expression", decl);
367238fd1498Szrj return error_mark_node;
367338fd1498Szrj }
367438fd1498Szrj else if (DECL_CLASS_TEMPLATE_P (decl))
367538fd1498Szrj {
367638fd1498Szrj error ("use of class template %qT as expression", decl);
367738fd1498Szrj return error_mark_node;
367838fd1498Szrj }
367938fd1498Szrj else if (TREE_CODE (decl) == TREE_LIST)
368038fd1498Szrj {
368138fd1498Szrj /* Ambiguous reference to base members. */
368238fd1498Szrj error ("request for member %qD is ambiguous in "
368338fd1498Szrj "multiple inheritance lattice", id_expression);
368438fd1498Szrj print_candidates (decl);
368538fd1498Szrj return error_mark_node;
368638fd1498Szrj }
368738fd1498Szrj
368838fd1498Szrj /* Mark variable-like entities as used. Functions are similarly
368938fd1498Szrj marked either below or after overload resolution. */
369038fd1498Szrj if ((VAR_P (decl)
369138fd1498Szrj || TREE_CODE (decl) == PARM_DECL
369238fd1498Szrj || TREE_CODE (decl) == CONST_DECL
369338fd1498Szrj || TREE_CODE (decl) == RESULT_DECL)
369438fd1498Szrj && !mark_used (decl))
369538fd1498Szrj return error_mark_node;
369638fd1498Szrj
369738fd1498Szrj /* Only certain kinds of names are allowed in constant
369838fd1498Szrj expression. Template parameters have already
369938fd1498Szrj been handled above. */
370038fd1498Szrj if (! error_operand_p (decl)
370138fd1498Szrj && !dependent_p
370238fd1498Szrj && integral_constant_expression_p
370338fd1498Szrj && ! decl_constant_var_p (decl)
370438fd1498Szrj && TREE_CODE (decl) != CONST_DECL
370538fd1498Szrj && ! builtin_valid_in_constant_expr_p (decl))
370638fd1498Szrj {
370738fd1498Szrj if (!allow_non_integral_constant_expression_p)
370838fd1498Szrj {
370938fd1498Szrj error ("%qD cannot appear in a constant-expression", decl);
371038fd1498Szrj return error_mark_node;
371138fd1498Szrj }
371238fd1498Szrj *non_integral_constant_expression_p = true;
371338fd1498Szrj }
371438fd1498Szrj
371538fd1498Szrj tree wrap;
371638fd1498Szrj if (VAR_P (decl)
371738fd1498Szrj && !cp_unevaluated_operand
371838fd1498Szrj && !processing_template_decl
371938fd1498Szrj && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
372038fd1498Szrj && CP_DECL_THREAD_LOCAL_P (decl)
372138fd1498Szrj && (wrap = get_tls_wrapper_fn (decl)))
372238fd1498Szrj {
372338fd1498Szrj /* Replace an evaluated use of the thread_local variable with
372438fd1498Szrj a call to its wrapper. */
372538fd1498Szrj decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
372638fd1498Szrj }
372738fd1498Szrj else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
372838fd1498Szrj && !dependent_p
372938fd1498Szrj && variable_template_p (TREE_OPERAND (decl, 0)))
373038fd1498Szrj {
373138fd1498Szrj decl = finish_template_variable (decl);
373238fd1498Szrj mark_used (decl);
373338fd1498Szrj decl = convert_from_reference (decl);
373438fd1498Szrj }
373538fd1498Szrj else if (scope)
373638fd1498Szrj {
373738fd1498Szrj if (TREE_CODE (decl) == SCOPE_REF)
373838fd1498Szrj {
373938fd1498Szrj gcc_assert (same_type_p (scope, TREE_OPERAND (decl, 0)));
374038fd1498Szrj decl = TREE_OPERAND (decl, 1);
374138fd1498Szrj }
374238fd1498Szrj
374338fd1498Szrj decl = (adjust_result_of_qualified_name_lookup
374438fd1498Szrj (decl, scope, current_nonlambda_class_type()));
374538fd1498Szrj
374638fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
374738fd1498Szrj mark_used (decl);
374838fd1498Szrj
374938fd1498Szrj if (TYPE_P (scope))
375038fd1498Szrj decl = finish_qualified_id_expr (scope,
375138fd1498Szrj decl,
375238fd1498Szrj done,
375338fd1498Szrj address_p,
375438fd1498Szrj template_p,
375538fd1498Szrj template_arg_p,
375638fd1498Szrj tf_warning_or_error);
375738fd1498Szrj else
375838fd1498Szrj decl = convert_from_reference (decl);
375938fd1498Szrj }
376038fd1498Szrj else if (TREE_CODE (decl) == FIELD_DECL)
376138fd1498Szrj {
376238fd1498Szrj /* Since SCOPE is NULL here, this is an unqualified name.
376338fd1498Szrj Access checking has been performed during name lookup
376438fd1498Szrj already. Turn off checking to avoid duplicate errors. */
376538fd1498Szrj push_deferring_access_checks (dk_no_check);
376638fd1498Szrj decl = finish_non_static_data_member (decl, NULL_TREE,
376738fd1498Szrj /*qualifying_scope=*/NULL_TREE);
376838fd1498Szrj pop_deferring_access_checks ();
376938fd1498Szrj }
377038fd1498Szrj else if (is_overloaded_fn (decl))
377138fd1498Szrj {
377238fd1498Szrj tree first_fn = get_first_fn (decl);
377338fd1498Szrj
377438fd1498Szrj if (TREE_CODE (first_fn) == TEMPLATE_DECL)
377538fd1498Szrj first_fn = DECL_TEMPLATE_RESULT (first_fn);
377638fd1498Szrj
377738fd1498Szrj /* [basic.def.odr]: "A function whose name appears as a
377838fd1498Szrj potentially-evaluated expression is odr-used if it is the unique
377938fd1498Szrj lookup result".
378038fd1498Szrj
378138fd1498Szrj But only mark it if it's a complete postfix-expression; in a call,
378238fd1498Szrj ADL might select a different function, and we'll call mark_used in
378338fd1498Szrj build_over_call. */
378438fd1498Szrj if (done
378538fd1498Szrj && !really_overloaded_fn (decl)
378638fd1498Szrj && !mark_used (first_fn))
378738fd1498Szrj return error_mark_node;
378838fd1498Szrj
378938fd1498Szrj if (!template_arg_p
379058e805e6Szrj && (TREE_CODE (first_fn) == USING_DECL
379158e805e6Szrj || (TREE_CODE (first_fn) == FUNCTION_DECL
379238fd1498Szrj && DECL_FUNCTION_MEMBER_P (first_fn)
379358e805e6Szrj && !shared_member_p (decl))))
379438fd1498Szrj {
379538fd1498Szrj /* A set of member functions. */
379638fd1498Szrj decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
379738fd1498Szrj return finish_class_member_access_expr (decl, id_expression,
379838fd1498Szrj /*template_p=*/false,
379938fd1498Szrj tf_warning_or_error);
380038fd1498Szrj }
380138fd1498Szrj
380238fd1498Szrj decl = baselink_for_fns (decl);
380338fd1498Szrj }
380438fd1498Szrj else
380538fd1498Szrj {
380638fd1498Szrj if (DECL_P (decl) && DECL_NONLOCAL (decl)
380738fd1498Szrj && DECL_CLASS_SCOPE_P (decl))
380838fd1498Szrj {
380938fd1498Szrj tree context = context_for_name_lookup (decl);
381038fd1498Szrj if (context != current_class_type)
381138fd1498Szrj {
381238fd1498Szrj tree path = currently_open_derived_class (context);
381338fd1498Szrj perform_or_defer_access_check (TYPE_BINFO (path),
381438fd1498Szrj decl, decl,
381538fd1498Szrj tf_warning_or_error);
381638fd1498Szrj }
381738fd1498Szrj }
381838fd1498Szrj
381938fd1498Szrj decl = convert_from_reference (decl);
382038fd1498Szrj }
382138fd1498Szrj }
382238fd1498Szrj
382338fd1498Szrj return cp_expr (decl, location);
382438fd1498Szrj }
382538fd1498Szrj
382638fd1498Szrj /* Implement the __typeof keyword: Return the type of EXPR, suitable for
382738fd1498Szrj use as a type-specifier. */
382838fd1498Szrj
382938fd1498Szrj tree
finish_typeof(tree expr)383038fd1498Szrj finish_typeof (tree expr)
383138fd1498Szrj {
383238fd1498Szrj tree type;
383338fd1498Szrj
383438fd1498Szrj if (type_dependent_expression_p (expr))
383538fd1498Szrj {
383638fd1498Szrj type = cxx_make_type (TYPEOF_TYPE);
383738fd1498Szrj TYPEOF_TYPE_EXPR (type) = expr;
383838fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (type);
383938fd1498Szrj
384038fd1498Szrj return type;
384138fd1498Szrj }
384238fd1498Szrj
384338fd1498Szrj expr = mark_type_use (expr);
384438fd1498Szrj
384538fd1498Szrj type = unlowered_expr_type (expr);
384638fd1498Szrj
384738fd1498Szrj if (!type || type == unknown_type_node)
384838fd1498Szrj {
384938fd1498Szrj error ("type of %qE is unknown", expr);
385038fd1498Szrj return error_mark_node;
385138fd1498Szrj }
385238fd1498Szrj
385338fd1498Szrj return type;
385438fd1498Szrj }
385538fd1498Szrj
385638fd1498Szrj /* Implement the __underlying_type keyword: Return the underlying
385738fd1498Szrj type of TYPE, suitable for use as a type-specifier. */
385838fd1498Szrj
385938fd1498Szrj tree
finish_underlying_type(tree type)386038fd1498Szrj finish_underlying_type (tree type)
386138fd1498Szrj {
386238fd1498Szrj tree underlying_type;
386338fd1498Szrj
386438fd1498Szrj if (processing_template_decl)
386538fd1498Szrj {
386638fd1498Szrj underlying_type = cxx_make_type (UNDERLYING_TYPE);
386738fd1498Szrj UNDERLYING_TYPE_TYPE (underlying_type) = type;
386838fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (underlying_type);
386938fd1498Szrj
387038fd1498Szrj return underlying_type;
387138fd1498Szrj }
387238fd1498Szrj
387338fd1498Szrj if (!complete_type_or_else (type, NULL_TREE))
387438fd1498Szrj return error_mark_node;
387538fd1498Szrj
387638fd1498Szrj if (TREE_CODE (type) != ENUMERAL_TYPE)
387738fd1498Szrj {
387838fd1498Szrj error ("%qT is not an enumeration type", type);
387938fd1498Szrj return error_mark_node;
388038fd1498Szrj }
388138fd1498Szrj
388238fd1498Szrj underlying_type = ENUM_UNDERLYING_TYPE (type);
388338fd1498Szrj
388438fd1498Szrj /* Fixup necessary in this case because ENUM_UNDERLYING_TYPE
388538fd1498Szrj includes TYPE_MIN_VALUE and TYPE_MAX_VALUE information.
388638fd1498Szrj See finish_enum_value_list for details. */
388738fd1498Szrj if (!ENUM_FIXED_UNDERLYING_TYPE_P (type))
388838fd1498Szrj underlying_type
388938fd1498Szrj = c_common_type_for_mode (TYPE_MODE (underlying_type),
389038fd1498Szrj TYPE_UNSIGNED (underlying_type));
389138fd1498Szrj
389238fd1498Szrj return underlying_type;
389338fd1498Szrj }
389438fd1498Szrj
389538fd1498Szrj /* Implement the __direct_bases keyword: Return the direct base classes
389638fd1498Szrj of type. */
389738fd1498Szrj
389838fd1498Szrj tree
calculate_direct_bases(tree type,tsubst_flags_t complain)389938fd1498Szrj calculate_direct_bases (tree type, tsubst_flags_t complain)
390038fd1498Szrj {
390138fd1498Szrj if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)
390238fd1498Szrj || !NON_UNION_CLASS_TYPE_P (type))
390338fd1498Szrj return make_tree_vec (0);
390438fd1498Szrj
390538fd1498Szrj vec<tree, va_gc> *vector = make_tree_vector ();
390638fd1498Szrj vec<tree, va_gc> *base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
390738fd1498Szrj tree binfo;
390838fd1498Szrj unsigned i;
390938fd1498Szrj
391038fd1498Szrj /* Virtual bases are initialized first */
391138fd1498Szrj for (i = 0; base_binfos->iterate (i, &binfo); i++)
391238fd1498Szrj if (BINFO_VIRTUAL_P (binfo))
391338fd1498Szrj vec_safe_push (vector, binfo);
391438fd1498Szrj
391538fd1498Szrj /* Now non-virtuals */
391638fd1498Szrj for (i = 0; base_binfos->iterate (i, &binfo); i++)
391738fd1498Szrj if (!BINFO_VIRTUAL_P (binfo))
391838fd1498Szrj vec_safe_push (vector, binfo);
391938fd1498Szrj
392038fd1498Szrj tree bases_vec = make_tree_vec (vector->length ());
392138fd1498Szrj
392238fd1498Szrj for (i = 0; i < vector->length (); ++i)
392338fd1498Szrj TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE ((*vector)[i]);
392438fd1498Szrj
392538fd1498Szrj release_tree_vector (vector);
392638fd1498Szrj return bases_vec;
392738fd1498Szrj }
392838fd1498Szrj
392938fd1498Szrj /* Implement the __bases keyword: Return the base classes
393038fd1498Szrj of type */
393138fd1498Szrj
393238fd1498Szrj /* Find morally non-virtual base classes by walking binfo hierarchy */
393338fd1498Szrj /* Virtual base classes are handled separately in finish_bases */
393438fd1498Szrj
393538fd1498Szrj static tree
dfs_calculate_bases_pre(tree binfo,void *)393638fd1498Szrj dfs_calculate_bases_pre (tree binfo, void * /*data_*/)
393738fd1498Szrj {
393838fd1498Szrj /* Don't walk bases of virtual bases */
393938fd1498Szrj return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
394038fd1498Szrj }
394138fd1498Szrj
394238fd1498Szrj static tree
dfs_calculate_bases_post(tree binfo,void * data_)394338fd1498Szrj dfs_calculate_bases_post (tree binfo, void *data_)
394438fd1498Szrj {
394538fd1498Szrj vec<tree, va_gc> **data = ((vec<tree, va_gc> **) data_);
394638fd1498Szrj if (!BINFO_VIRTUAL_P (binfo))
394738fd1498Szrj vec_safe_push (*data, BINFO_TYPE (binfo));
394838fd1498Szrj return NULL_TREE;
394938fd1498Szrj }
395038fd1498Szrj
395138fd1498Szrj /* Calculates the morally non-virtual base classes of a class */
395238fd1498Szrj static vec<tree, va_gc> *
calculate_bases_helper(tree type)395338fd1498Szrj calculate_bases_helper (tree type)
395438fd1498Szrj {
395538fd1498Szrj vec<tree, va_gc> *vector = make_tree_vector ();
395638fd1498Szrj
395738fd1498Szrj /* Now add non-virtual base classes in order of construction */
395838fd1498Szrj if (TYPE_BINFO (type))
395938fd1498Szrj dfs_walk_all (TYPE_BINFO (type),
396038fd1498Szrj dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
396138fd1498Szrj return vector;
396238fd1498Szrj }
396338fd1498Szrj
396438fd1498Szrj tree
calculate_bases(tree type,tsubst_flags_t complain)396538fd1498Szrj calculate_bases (tree type, tsubst_flags_t complain)
396638fd1498Szrj {
396738fd1498Szrj if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)
396838fd1498Szrj || !NON_UNION_CLASS_TYPE_P (type))
396938fd1498Szrj return make_tree_vec (0);
397038fd1498Szrj
397138fd1498Szrj vec<tree, va_gc> *vector = make_tree_vector ();
397238fd1498Szrj tree bases_vec = NULL_TREE;
397338fd1498Szrj unsigned i;
397438fd1498Szrj vec<tree, va_gc> *vbases;
397538fd1498Szrj vec<tree, va_gc> *nonvbases;
397638fd1498Szrj tree binfo;
397738fd1498Szrj
397838fd1498Szrj /* First go through virtual base classes */
397938fd1498Szrj for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
398038fd1498Szrj vec_safe_iterate (vbases, i, &binfo); i++)
398138fd1498Szrj {
398238fd1498Szrj vec<tree, va_gc> *vbase_bases
398338fd1498Szrj = calculate_bases_helper (BINFO_TYPE (binfo));
398438fd1498Szrj vec_safe_splice (vector, vbase_bases);
398538fd1498Szrj release_tree_vector (vbase_bases);
398638fd1498Szrj }
398738fd1498Szrj
398838fd1498Szrj /* Now for the non-virtual bases */
398938fd1498Szrj nonvbases = calculate_bases_helper (type);
399038fd1498Szrj vec_safe_splice (vector, nonvbases);
399138fd1498Szrj release_tree_vector (nonvbases);
399238fd1498Szrj
399338fd1498Szrj /* Note that during error recovery vector->length can even be zero. */
399438fd1498Szrj if (vector->length () > 1)
399538fd1498Szrj {
399638fd1498Szrj /* Last element is entire class, so don't copy */
399738fd1498Szrj bases_vec = make_tree_vec (vector->length () - 1);
399838fd1498Szrj
399938fd1498Szrj for (i = 0; i < vector->length () - 1; ++i)
400038fd1498Szrj TREE_VEC_ELT (bases_vec, i) = (*vector)[i];
400138fd1498Szrj }
400238fd1498Szrj else
400338fd1498Szrj bases_vec = make_tree_vec (0);
400438fd1498Szrj
400538fd1498Szrj release_tree_vector (vector);
400638fd1498Szrj return bases_vec;
400738fd1498Szrj }
400838fd1498Szrj
400938fd1498Szrj tree
finish_bases(tree type,bool direct)401038fd1498Szrj finish_bases (tree type, bool direct)
401138fd1498Szrj {
401238fd1498Szrj tree bases = NULL_TREE;
401338fd1498Szrj
401438fd1498Szrj if (!processing_template_decl)
401538fd1498Szrj {
401638fd1498Szrj /* Parameter packs can only be used in templates */
401738fd1498Szrj error ("Parameter pack __bases only valid in template declaration");
401838fd1498Szrj return error_mark_node;
401938fd1498Szrj }
402038fd1498Szrj
402138fd1498Szrj bases = cxx_make_type (BASES);
402238fd1498Szrj BASES_TYPE (bases) = type;
402338fd1498Szrj BASES_DIRECT (bases) = direct;
402438fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (bases);
402538fd1498Szrj
402638fd1498Szrj return bases;
402738fd1498Szrj }
402838fd1498Szrj
402938fd1498Szrj /* Perform C++-specific checks for __builtin_offsetof before calling
403038fd1498Szrj fold_offsetof. */
403138fd1498Szrj
403238fd1498Szrj tree
finish_offsetof(tree object_ptr,tree expr,location_t loc)403338fd1498Szrj finish_offsetof (tree object_ptr, tree expr, location_t loc)
403438fd1498Szrj {
403538fd1498Szrj /* If we're processing a template, we can't finish the semantics yet.
403638fd1498Szrj Otherwise we can fold the entire expression now. */
403738fd1498Szrj if (processing_template_decl)
403838fd1498Szrj {
403938fd1498Szrj expr = build2 (OFFSETOF_EXPR, size_type_node, expr, object_ptr);
404038fd1498Szrj SET_EXPR_LOCATION (expr, loc);
404138fd1498Szrj return expr;
404238fd1498Szrj }
404338fd1498Szrj
404438fd1498Szrj if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
404538fd1498Szrj {
404638fd1498Szrj error ("cannot apply %<offsetof%> to destructor %<~%T%>",
404738fd1498Szrj TREE_OPERAND (expr, 2));
404838fd1498Szrj return error_mark_node;
404938fd1498Szrj }
405038fd1498Szrj if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
405138fd1498Szrj || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
405238fd1498Szrj || TREE_TYPE (expr) == unknown_type_node)
405338fd1498Szrj {
405438fd1498Szrj while (TREE_CODE (expr) == COMPONENT_REF
405538fd1498Szrj || TREE_CODE (expr) == COMPOUND_EXPR)
405638fd1498Szrj expr = TREE_OPERAND (expr, 1);
405738fd1498Szrj
405838fd1498Szrj if (DECL_P (expr))
405938fd1498Szrj {
406038fd1498Szrj error ("cannot apply %<offsetof%> to member function %qD", expr);
406138fd1498Szrj inform (DECL_SOURCE_LOCATION (expr), "declared here");
406238fd1498Szrj }
406338fd1498Szrj else
406438fd1498Szrj error ("cannot apply %<offsetof%> to member function");
406538fd1498Szrj return error_mark_node;
406638fd1498Szrj }
406738fd1498Szrj if (TREE_CODE (expr) == CONST_DECL)
406838fd1498Szrj {
406938fd1498Szrj error ("cannot apply %<offsetof%> to an enumerator %qD", expr);
407038fd1498Szrj return error_mark_node;
407138fd1498Szrj }
407238fd1498Szrj if (REFERENCE_REF_P (expr))
407338fd1498Szrj expr = TREE_OPERAND (expr, 0);
407438fd1498Szrj if (!complete_type_or_else (TREE_TYPE (TREE_TYPE (object_ptr)), object_ptr))
407538fd1498Szrj return error_mark_node;
407638fd1498Szrj if (warn_invalid_offsetof
407738fd1498Szrj && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr)))
407838fd1498Szrj && CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr)))
407938fd1498Szrj && cp_unevaluated_operand == 0)
408038fd1498Szrj warning_at (loc, OPT_Winvalid_offsetof, "offsetof within "
408138fd1498Szrj "non-standard-layout type %qT is conditionally-supported",
408238fd1498Szrj TREE_TYPE (TREE_TYPE (object_ptr)));
408338fd1498Szrj return fold_offsetof (expr);
408438fd1498Szrj }
408538fd1498Szrj
408638fd1498Szrj /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR. This
408738fd1498Szrj function is broken out from the above for the benefit of the tree-ssa
408838fd1498Szrj project. */
408938fd1498Szrj
409038fd1498Szrj void
simplify_aggr_init_expr(tree * tp)409138fd1498Szrj simplify_aggr_init_expr (tree *tp)
409238fd1498Szrj {
409338fd1498Szrj tree aggr_init_expr = *tp;
409438fd1498Szrj
409538fd1498Szrj /* Form an appropriate CALL_EXPR. */
409638fd1498Szrj tree fn = AGGR_INIT_EXPR_FN (aggr_init_expr);
409738fd1498Szrj tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr);
409838fd1498Szrj tree type = TREE_TYPE (slot);
409938fd1498Szrj
410038fd1498Szrj tree call_expr;
410138fd1498Szrj enum style_t { ctor, arg, pcc } style;
410238fd1498Szrj
410338fd1498Szrj if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
410438fd1498Szrj style = ctor;
410538fd1498Szrj #ifdef PCC_STATIC_STRUCT_RETURN
410638fd1498Szrj else if (1)
410738fd1498Szrj style = pcc;
410838fd1498Szrj #endif
410938fd1498Szrj else
411038fd1498Szrj {
411138fd1498Szrj gcc_assert (TREE_ADDRESSABLE (type));
411238fd1498Szrj style = arg;
411338fd1498Szrj }
411438fd1498Szrj
411538fd1498Szrj call_expr = build_call_array_loc (input_location,
411638fd1498Szrj TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
411738fd1498Szrj fn,
411838fd1498Szrj aggr_init_expr_nargs (aggr_init_expr),
411938fd1498Szrj AGGR_INIT_EXPR_ARGP (aggr_init_expr));
412038fd1498Szrj TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr);
412138fd1498Szrj CALL_FROM_THUNK_P (call_expr) = AGGR_INIT_FROM_THUNK_P (aggr_init_expr);
412238fd1498Szrj CALL_EXPR_OPERATOR_SYNTAX (call_expr)
412338fd1498Szrj = CALL_EXPR_OPERATOR_SYNTAX (aggr_init_expr);
412438fd1498Szrj CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (aggr_init_expr);
412538fd1498Szrj CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (aggr_init_expr);
412638fd1498Szrj
412738fd1498Szrj if (style == ctor)
412838fd1498Szrj {
412938fd1498Szrj /* Replace the first argument to the ctor with the address of the
413038fd1498Szrj slot. */
413138fd1498Szrj cxx_mark_addressable (slot);
413238fd1498Szrj CALL_EXPR_ARG (call_expr, 0) =
413338fd1498Szrj build1 (ADDR_EXPR, build_pointer_type (type), slot);
413438fd1498Szrj }
413538fd1498Szrj else if (style == arg)
413638fd1498Szrj {
413738fd1498Szrj /* Just mark it addressable here, and leave the rest to
413838fd1498Szrj expand_call{,_inline}. */
413938fd1498Szrj cxx_mark_addressable (slot);
414038fd1498Szrj CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true;
414138fd1498Szrj call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr);
414238fd1498Szrj }
414338fd1498Szrj else if (style == pcc)
414438fd1498Szrj {
414538fd1498Szrj /* If we're using the non-reentrant PCC calling convention, then we
414638fd1498Szrj need to copy the returned value out of the static buffer into the
414738fd1498Szrj SLOT. */
414838fd1498Szrj push_deferring_access_checks (dk_no_check);
414938fd1498Szrj call_expr = build_aggr_init (slot, call_expr,
415038fd1498Szrj DIRECT_BIND | LOOKUP_ONLYCONVERTING,
415138fd1498Szrj tf_warning_or_error);
415238fd1498Szrj pop_deferring_access_checks ();
415338fd1498Szrj call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
415438fd1498Szrj }
415538fd1498Szrj
415638fd1498Szrj if (AGGR_INIT_ZERO_FIRST (aggr_init_expr))
415738fd1498Szrj {
415838fd1498Szrj tree init = build_zero_init (type, NULL_TREE,
415938fd1498Szrj /*static_storage_p=*/false);
416038fd1498Szrj init = build2 (INIT_EXPR, void_type_node, slot, init);
416138fd1498Szrj call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr),
416238fd1498Szrj init, call_expr);
416338fd1498Szrj }
416438fd1498Szrj
416538fd1498Szrj *tp = call_expr;
416638fd1498Szrj }
416738fd1498Szrj
416838fd1498Szrj /* Emit all thunks to FN that should be emitted when FN is emitted. */
416938fd1498Szrj
417038fd1498Szrj void
emit_associated_thunks(tree fn)417138fd1498Szrj emit_associated_thunks (tree fn)
417238fd1498Szrj {
417338fd1498Szrj /* When we use vcall offsets, we emit thunks with the virtual
417438fd1498Szrj functions to which they thunk. The whole point of vcall offsets
417538fd1498Szrj is so that you can know statically the entire set of thunks that
417638fd1498Szrj will ever be needed for a given virtual function, thereby
417738fd1498Szrj enabling you to output all the thunks with the function itself. */
417838fd1498Szrj if (DECL_VIRTUAL_P (fn)
417938fd1498Szrj /* Do not emit thunks for extern template instantiations. */
418038fd1498Szrj && ! DECL_REALLY_EXTERN (fn))
418138fd1498Szrj {
418238fd1498Szrj tree thunk;
418338fd1498Szrj
418438fd1498Szrj for (thunk = DECL_THUNKS (fn); thunk; thunk = DECL_CHAIN (thunk))
418538fd1498Szrj {
418638fd1498Szrj if (!THUNK_ALIAS (thunk))
418738fd1498Szrj {
418838fd1498Szrj use_thunk (thunk, /*emit_p=*/1);
418938fd1498Szrj if (DECL_RESULT_THUNK_P (thunk))
419038fd1498Szrj {
419138fd1498Szrj tree probe;
419238fd1498Szrj
419338fd1498Szrj for (probe = DECL_THUNKS (thunk);
419438fd1498Szrj probe; probe = DECL_CHAIN (probe))
419538fd1498Szrj use_thunk (probe, /*emit_p=*/1);
419638fd1498Szrj }
419738fd1498Szrj }
419838fd1498Szrj else
419938fd1498Szrj gcc_assert (!DECL_THUNKS (thunk));
420038fd1498Szrj }
420138fd1498Szrj }
420238fd1498Szrj }
420338fd1498Szrj
420438fd1498Szrj /* Generate RTL for FN. */
420538fd1498Szrj
420638fd1498Szrj bool
expand_or_defer_fn_1(tree fn)420738fd1498Szrj expand_or_defer_fn_1 (tree fn)
420838fd1498Szrj {
420938fd1498Szrj /* When the parser calls us after finishing the body of a template
421038fd1498Szrj function, we don't really want to expand the body. */
421138fd1498Szrj if (processing_template_decl)
421238fd1498Szrj {
421338fd1498Szrj /* Normally, collection only occurs in rest_of_compilation. So,
421438fd1498Szrj if we don't collect here, we never collect junk generated
421538fd1498Szrj during the processing of templates until we hit a
421638fd1498Szrj non-template function. It's not safe to do this inside a
421738fd1498Szrj nested class, though, as the parser may have local state that
421838fd1498Szrj is not a GC root. */
421938fd1498Szrj if (!function_depth)
422038fd1498Szrj ggc_collect ();
422138fd1498Szrj return false;
422238fd1498Szrj }
422338fd1498Szrj
422438fd1498Szrj gcc_assert (DECL_SAVED_TREE (fn));
422538fd1498Szrj
422638fd1498Szrj /* We make a decision about linkage for these functions at the end
422738fd1498Szrj of the compilation. Until that point, we do not want the back
422838fd1498Szrj end to output them -- but we do want it to see the bodies of
422938fd1498Szrj these functions so that it can inline them as appropriate. */
423038fd1498Szrj if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
423138fd1498Szrj {
423238fd1498Szrj if (DECL_INTERFACE_KNOWN (fn))
423338fd1498Szrj /* We've already made a decision as to how this function will
423438fd1498Szrj be handled. */;
423538fd1498Szrj else if (!at_eof)
423638fd1498Szrj tentative_decl_linkage (fn);
423738fd1498Szrj else
423838fd1498Szrj import_export_decl (fn);
423938fd1498Szrj
424038fd1498Szrj /* If the user wants us to keep all inline functions, then mark
424138fd1498Szrj this function as needed so that finish_file will make sure to
424238fd1498Szrj output it later. Similarly, all dllexport'd functions must
424338fd1498Szrj be emitted; there may be callers in other DLLs. */
424438fd1498Szrj if (DECL_DECLARED_INLINE_P (fn)
424538fd1498Szrj && !DECL_REALLY_EXTERN (fn)
424638fd1498Szrj && (flag_keep_inline_functions
424738fd1498Szrj || (flag_keep_inline_dllexport
424838fd1498Szrj && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
424938fd1498Szrj {
425038fd1498Szrj mark_needed (fn);
425138fd1498Szrj DECL_EXTERNAL (fn) = 0;
425238fd1498Szrj }
425338fd1498Szrj }
425438fd1498Szrj
425538fd1498Szrj /* If this is a constructor or destructor body, we have to clone
425638fd1498Szrj it. */
425738fd1498Szrj if (maybe_clone_body (fn))
425838fd1498Szrj {
425938fd1498Szrj /* We don't want to process FN again, so pretend we've written
426038fd1498Szrj it out, even though we haven't. */
426138fd1498Szrj TREE_ASM_WRITTEN (fn) = 1;
426238fd1498Szrj /* If this is a constexpr function, keep DECL_SAVED_TREE. */
426338fd1498Szrj if (!DECL_DECLARED_CONSTEXPR_P (fn))
426438fd1498Szrj DECL_SAVED_TREE (fn) = NULL_TREE;
426538fd1498Szrj return false;
426638fd1498Szrj }
426738fd1498Szrj
426838fd1498Szrj /* There's no reason to do any of the work here if we're only doing
426938fd1498Szrj semantic analysis; this code just generates RTL. */
427038fd1498Szrj if (flag_syntax_only)
427138fd1498Szrj return false;
427238fd1498Szrj
427338fd1498Szrj return true;
427438fd1498Szrj }
427538fd1498Szrj
427638fd1498Szrj void
expand_or_defer_fn(tree fn)427738fd1498Szrj expand_or_defer_fn (tree fn)
427838fd1498Szrj {
427938fd1498Szrj if (expand_or_defer_fn_1 (fn))
428038fd1498Szrj {
428138fd1498Szrj function_depth++;
428238fd1498Szrj
428338fd1498Szrj /* Expand or defer, at the whim of the compilation unit manager. */
428438fd1498Szrj cgraph_node::finalize_function (fn, function_depth > 1);
428538fd1498Szrj emit_associated_thunks (fn);
428638fd1498Szrj
428738fd1498Szrj function_depth--;
428838fd1498Szrj }
428938fd1498Szrj }
429038fd1498Szrj
429138fd1498Szrj struct nrv_data
429238fd1498Szrj {
nrv_datanrv_data429338fd1498Szrj nrv_data () : visited (37) {}
429438fd1498Szrj
429538fd1498Szrj tree var;
429638fd1498Szrj tree result;
429738fd1498Szrj hash_table<nofree_ptr_hash <tree_node> > visited;
429838fd1498Szrj };
429938fd1498Szrj
430038fd1498Szrj /* Helper function for walk_tree, used by finalize_nrv below. */
430138fd1498Szrj
430238fd1498Szrj static tree
finalize_nrv_r(tree * tp,int * walk_subtrees,void * data)430338fd1498Szrj finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
430438fd1498Szrj {
430538fd1498Szrj struct nrv_data *dp = (struct nrv_data *)data;
430638fd1498Szrj tree_node **slot;
430738fd1498Szrj
430838fd1498Szrj /* No need to walk into types. There wouldn't be any need to walk into
430938fd1498Szrj non-statements, except that we have to consider STMT_EXPRs. */
431038fd1498Szrj if (TYPE_P (*tp))
431138fd1498Szrj *walk_subtrees = 0;
431238fd1498Szrj /* Change all returns to just refer to the RESULT_DECL; this is a nop,
431338fd1498Szrj but differs from using NULL_TREE in that it indicates that we care
431438fd1498Szrj about the value of the RESULT_DECL. */
431538fd1498Szrj else if (TREE_CODE (*tp) == RETURN_EXPR)
431638fd1498Szrj TREE_OPERAND (*tp, 0) = dp->result;
431738fd1498Szrj /* Change all cleanups for the NRV to only run when an exception is
431838fd1498Szrj thrown. */
431938fd1498Szrj else if (TREE_CODE (*tp) == CLEANUP_STMT
432038fd1498Szrj && CLEANUP_DECL (*tp) == dp->var)
432138fd1498Szrj CLEANUP_EH_ONLY (*tp) = 1;
432238fd1498Szrj /* Replace the DECL_EXPR for the NRV with an initialization of the
432338fd1498Szrj RESULT_DECL, if needed. */
432438fd1498Szrj else if (TREE_CODE (*tp) == DECL_EXPR
432538fd1498Szrj && DECL_EXPR_DECL (*tp) == dp->var)
432638fd1498Szrj {
432738fd1498Szrj tree init;
432838fd1498Szrj if (DECL_INITIAL (dp->var)
432938fd1498Szrj && DECL_INITIAL (dp->var) != error_mark_node)
433038fd1498Szrj init = build2 (INIT_EXPR, void_type_node, dp->result,
433138fd1498Szrj DECL_INITIAL (dp->var));
433238fd1498Szrj else
433338fd1498Szrj init = build_empty_stmt (EXPR_LOCATION (*tp));
433438fd1498Szrj DECL_INITIAL (dp->var) = NULL_TREE;
433538fd1498Szrj SET_EXPR_LOCATION (init, EXPR_LOCATION (*tp));
433638fd1498Szrj *tp = init;
433738fd1498Szrj }
433838fd1498Szrj /* And replace all uses of the NRV with the RESULT_DECL. */
433938fd1498Szrj else if (*tp == dp->var)
434038fd1498Szrj *tp = dp->result;
434138fd1498Szrj
434238fd1498Szrj /* Avoid walking into the same tree more than once. Unfortunately, we
434338fd1498Szrj can't just use walk_tree_without duplicates because it would only call
434438fd1498Szrj us for the first occurrence of dp->var in the function body. */
434538fd1498Szrj slot = dp->visited.find_slot (*tp, INSERT);
434638fd1498Szrj if (*slot)
434738fd1498Szrj *walk_subtrees = 0;
434838fd1498Szrj else
434938fd1498Szrj *slot = *tp;
435038fd1498Szrj
435138fd1498Szrj /* Keep iterating. */
435238fd1498Szrj return NULL_TREE;
435338fd1498Szrj }
435438fd1498Szrj
435538fd1498Szrj /* Called from finish_function to implement the named return value
435638fd1498Szrj optimization by overriding all the RETURN_EXPRs and pertinent
435738fd1498Szrj CLEANUP_STMTs and replacing all occurrences of VAR with RESULT, the
435838fd1498Szrj RESULT_DECL for the function. */
435938fd1498Szrj
436038fd1498Szrj void
finalize_nrv(tree * tp,tree var,tree result)436138fd1498Szrj finalize_nrv (tree *tp, tree var, tree result)
436238fd1498Szrj {
436338fd1498Szrj struct nrv_data data;
436438fd1498Szrj
436538fd1498Szrj /* Copy name from VAR to RESULT. */
436638fd1498Szrj DECL_NAME (result) = DECL_NAME (var);
436738fd1498Szrj /* Don't forget that we take its address. */
436838fd1498Szrj TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (var);
436938fd1498Szrj /* Finally set DECL_VALUE_EXPR to avoid assigning
437038fd1498Szrj a stack slot at -O0 for the original var and debug info
437138fd1498Szrj uses RESULT location for VAR. */
437238fd1498Szrj SET_DECL_VALUE_EXPR (var, result);
437338fd1498Szrj DECL_HAS_VALUE_EXPR_P (var) = 1;
437438fd1498Szrj
437538fd1498Szrj data.var = var;
437638fd1498Szrj data.result = result;
437738fd1498Szrj cp_walk_tree (tp, finalize_nrv_r, &data, 0);
437838fd1498Szrj }
437938fd1498Szrj
438038fd1498Szrj /* Create CP_OMP_CLAUSE_INFO for clause C. Returns true if it is invalid. */
438138fd1498Szrj
438238fd1498Szrj bool
cxx_omp_create_clause_info(tree c,tree type,bool need_default_ctor,bool need_copy_ctor,bool need_copy_assignment,bool need_dtor)438338fd1498Szrj cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
438438fd1498Szrj bool need_copy_ctor, bool need_copy_assignment,
438538fd1498Szrj bool need_dtor)
438638fd1498Szrj {
438738fd1498Szrj int save_errorcount = errorcount;
438838fd1498Szrj tree info, t;
438938fd1498Szrj
439038fd1498Szrj /* Always allocate 3 elements for simplicity. These are the
439138fd1498Szrj function decls for the ctor, dtor, and assignment op.
439238fd1498Szrj This layout is known to the three lang hooks,
439338fd1498Szrj cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
439438fd1498Szrj and cxx_omp_clause_assign_op. */
439538fd1498Szrj info = make_tree_vec (3);
439638fd1498Szrj CP_OMP_CLAUSE_INFO (c) = info;
439738fd1498Szrj
439838fd1498Szrj if (need_default_ctor || need_copy_ctor)
439938fd1498Szrj {
440038fd1498Szrj if (need_default_ctor)
440138fd1498Szrj t = get_default_ctor (type);
440238fd1498Szrj else
440338fd1498Szrj t = get_copy_ctor (type, tf_warning_or_error);
440438fd1498Szrj
440538fd1498Szrj if (t && !trivial_fn_p (t))
440638fd1498Szrj TREE_VEC_ELT (info, 0) = t;
440738fd1498Szrj }
440838fd1498Szrj
440938fd1498Szrj if (need_dtor && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
441038fd1498Szrj TREE_VEC_ELT (info, 1) = get_dtor (type, tf_warning_or_error);
441138fd1498Szrj
441238fd1498Szrj if (need_copy_assignment)
441338fd1498Szrj {
441438fd1498Szrj t = get_copy_assign (type);
441538fd1498Szrj
441638fd1498Szrj if (t && !trivial_fn_p (t))
441738fd1498Szrj TREE_VEC_ELT (info, 2) = t;
441838fd1498Szrj }
441938fd1498Szrj
442038fd1498Szrj return errorcount != save_errorcount;
442138fd1498Szrj }
442238fd1498Szrj
442338fd1498Szrj /* If DECL is DECL_OMP_PRIVATIZED_MEMBER, return corresponding
442438fd1498Szrj FIELD_DECL, otherwise return DECL itself. */
442538fd1498Szrj
442638fd1498Szrj static tree
omp_clause_decl_field(tree decl)442738fd1498Szrj omp_clause_decl_field (tree decl)
442838fd1498Szrj {
442938fd1498Szrj if (VAR_P (decl)
443038fd1498Szrj && DECL_HAS_VALUE_EXPR_P (decl)
443138fd1498Szrj && DECL_ARTIFICIAL (decl)
443238fd1498Szrj && DECL_LANG_SPECIFIC (decl)
443338fd1498Szrj && DECL_OMP_PRIVATIZED_MEMBER (decl))
443438fd1498Szrj {
443538fd1498Szrj tree f = DECL_VALUE_EXPR (decl);
443638fd1498Szrj if (INDIRECT_REF_P (f))
443738fd1498Szrj f = TREE_OPERAND (f, 0);
443838fd1498Szrj if (TREE_CODE (f) == COMPONENT_REF)
443938fd1498Szrj {
444038fd1498Szrj f = TREE_OPERAND (f, 1);
444138fd1498Szrj gcc_assert (TREE_CODE (f) == FIELD_DECL);
444238fd1498Szrj return f;
444338fd1498Szrj }
444438fd1498Szrj }
444538fd1498Szrj return NULL_TREE;
444638fd1498Szrj }
444738fd1498Szrj
444838fd1498Szrj /* Adjust DECL if needed for printing using %qE. */
444938fd1498Szrj
445038fd1498Szrj static tree
omp_clause_printable_decl(tree decl)445138fd1498Szrj omp_clause_printable_decl (tree decl)
445238fd1498Szrj {
445338fd1498Szrj tree t = omp_clause_decl_field (decl);
445438fd1498Szrj if (t)
445538fd1498Szrj return t;
445638fd1498Szrj return decl;
445738fd1498Szrj }
445838fd1498Szrj
445938fd1498Szrj /* For a FIELD_DECL F and corresponding DECL_OMP_PRIVATIZED_MEMBER
446038fd1498Szrj VAR_DECL T that doesn't need a DECL_EXPR added, record it for
446138fd1498Szrj privatization. */
446238fd1498Szrj
446338fd1498Szrj static void
omp_note_field_privatization(tree f,tree t)446438fd1498Szrj omp_note_field_privatization (tree f, tree t)
446538fd1498Szrj {
446638fd1498Szrj if (!omp_private_member_map)
446738fd1498Szrj omp_private_member_map = new hash_map<tree, tree>;
446838fd1498Szrj tree &v = omp_private_member_map->get_or_insert (f);
446938fd1498Szrj if (v == NULL_TREE)
447038fd1498Szrj {
447138fd1498Szrj v = t;
447238fd1498Szrj omp_private_member_vec.safe_push (f);
447338fd1498Szrj /* Signal that we don't want to create DECL_EXPR for this dummy var. */
447438fd1498Szrj omp_private_member_vec.safe_push (integer_zero_node);
447538fd1498Szrj }
447638fd1498Szrj }
447738fd1498Szrj
447838fd1498Szrj /* Privatize FIELD_DECL T, return corresponding DECL_OMP_PRIVATIZED_MEMBER
447938fd1498Szrj dummy VAR_DECL. */
448038fd1498Szrj
448138fd1498Szrj tree
omp_privatize_field(tree t,bool shared)448238fd1498Szrj omp_privatize_field (tree t, bool shared)
448338fd1498Szrj {
448438fd1498Szrj tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
448538fd1498Szrj if (m == error_mark_node)
448638fd1498Szrj return error_mark_node;
448738fd1498Szrj if (!omp_private_member_map && !shared)
448838fd1498Szrj omp_private_member_map = new hash_map<tree, tree>;
448938fd1498Szrj if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
449038fd1498Szrj {
449138fd1498Szrj gcc_assert (INDIRECT_REF_P (m));
449238fd1498Szrj m = TREE_OPERAND (m, 0);
449338fd1498Szrj }
449438fd1498Szrj tree vb = NULL_TREE;
449538fd1498Szrj tree &v = shared ? vb : omp_private_member_map->get_or_insert (t);
449638fd1498Szrj if (v == NULL_TREE)
449738fd1498Szrj {
449838fd1498Szrj v = create_temporary_var (TREE_TYPE (m));
449938fd1498Szrj retrofit_lang_decl (v);
450038fd1498Szrj DECL_OMP_PRIVATIZED_MEMBER (v) = 1;
450138fd1498Szrj SET_DECL_VALUE_EXPR (v, m);
450238fd1498Szrj DECL_HAS_VALUE_EXPR_P (v) = 1;
450338fd1498Szrj if (!shared)
450438fd1498Szrj omp_private_member_vec.safe_push (t);
450538fd1498Szrj }
450638fd1498Szrj return v;
450738fd1498Szrj }
450838fd1498Szrj
450938fd1498Szrj /* Helper function for handle_omp_array_sections. Called recursively
451038fd1498Szrj to handle multiple array-section-subscripts. C is the clause,
451138fd1498Szrj T current expression (initially OMP_CLAUSE_DECL), which is either
451238fd1498Szrj a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound
451338fd1498Szrj expression if specified, TREE_VALUE length expression if specified,
451438fd1498Szrj TREE_CHAIN is what it has been specified after, or some decl.
451538fd1498Szrj TYPES vector is populated with array section types, MAYBE_ZERO_LEN
451638fd1498Szrj set to true if any of the array-section-subscript could have length
451738fd1498Szrj of zero (explicit or implicit), FIRST_NON_ONE is the index of the
451838fd1498Szrj first array-section-subscript which is known not to have length
451938fd1498Szrj of one. Given say:
452038fd1498Szrj map(a[:b][2:1][:c][:2][:d][e:f][2:5])
452138fd1498Szrj FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c]
452238fd1498Szrj all are or may have length of 1, array-section-subscript [:2] is the
452338fd1498Szrj first one known not to have length 1. For array-section-subscript
452438fd1498Szrj <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't
452538fd1498Szrj 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we
452638fd1498Szrj can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above
452738fd1498Szrj case though, as some lengths could be zero. */
452838fd1498Szrj
452938fd1498Szrj static tree
handle_omp_array_sections_1(tree c,tree t,vec<tree> & types,bool & maybe_zero_len,unsigned int & first_non_one,enum c_omp_region_type ort)453038fd1498Szrj handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
453138fd1498Szrj bool &maybe_zero_len, unsigned int &first_non_one,
453238fd1498Szrj enum c_omp_region_type ort)
453338fd1498Szrj {
453438fd1498Szrj tree ret, low_bound, length, type;
453538fd1498Szrj if (TREE_CODE (t) != TREE_LIST)
453638fd1498Szrj {
453738fd1498Szrj if (error_operand_p (t))
453838fd1498Szrj return error_mark_node;
453938fd1498Szrj if (REFERENCE_REF_P (t)
454038fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
454138fd1498Szrj t = TREE_OPERAND (t, 0);
454238fd1498Szrj ret = t;
454338fd1498Szrj if (TREE_CODE (t) == COMPONENT_REF
454438fd1498Szrj && ort == C_ORT_OMP
454538fd1498Szrj && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
454638fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
454738fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
454838fd1498Szrj && !type_dependent_expression_p (t))
454938fd1498Szrj {
455038fd1498Szrj if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
455138fd1498Szrj && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
455238fd1498Szrj {
455338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
455438fd1498Szrj "bit-field %qE in %qs clause",
455538fd1498Szrj t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
455638fd1498Szrj return error_mark_node;
455738fd1498Szrj }
455838fd1498Szrj while (TREE_CODE (t) == COMPONENT_REF)
455938fd1498Szrj {
456038fd1498Szrj if (TREE_TYPE (TREE_OPERAND (t, 0))
456138fd1498Szrj && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
456238fd1498Szrj {
456338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
456438fd1498Szrj "%qE is a member of a union", t);
456538fd1498Szrj return error_mark_node;
456638fd1498Szrj }
456738fd1498Szrj t = TREE_OPERAND (t, 0);
456838fd1498Szrj }
456938fd1498Szrj if (REFERENCE_REF_P (t))
457038fd1498Szrj t = TREE_OPERAND (t, 0);
457138fd1498Szrj }
457238fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
457338fd1498Szrj {
457438fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
457538fd1498Szrj return NULL_TREE;
457638fd1498Szrj if (DECL_P (t))
457738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
457838fd1498Szrj "%qD is not a variable in %qs clause", t,
457938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
458038fd1498Szrj else
458138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
458238fd1498Szrj "%qE is not a variable in %qs clause", t,
458338fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
458438fd1498Szrj return error_mark_node;
458538fd1498Szrj }
458638fd1498Szrj else if (TREE_CODE (t) == PARM_DECL
458738fd1498Szrj && DECL_ARTIFICIAL (t)
458838fd1498Szrj && DECL_NAME (t) == this_identifier)
458938fd1498Szrj {
459038fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
459138fd1498Szrj "%<this%> allowed in OpenMP only in %<declare simd%>"
459238fd1498Szrj " clauses");
459338fd1498Szrj return error_mark_node;
459438fd1498Szrj }
459538fd1498Szrj else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
459638fd1498Szrj && VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
459738fd1498Szrj {
459838fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
459938fd1498Szrj "%qD is threadprivate variable in %qs clause", t,
460038fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
460138fd1498Szrj return error_mark_node;
460238fd1498Szrj }
460338fd1498Szrj if (type_dependent_expression_p (ret))
460438fd1498Szrj return NULL_TREE;
460538fd1498Szrj ret = convert_from_reference (ret);
460638fd1498Szrj return ret;
460738fd1498Szrj }
460838fd1498Szrj
460938fd1498Szrj if (ort == C_ORT_OMP
461038fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
461138fd1498Szrj && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
461238fd1498Szrj TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
461338fd1498Szrj ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
461438fd1498Szrj maybe_zero_len, first_non_one, ort);
461538fd1498Szrj if (ret == error_mark_node || ret == NULL_TREE)
461638fd1498Szrj return ret;
461738fd1498Szrj
461838fd1498Szrj type = TREE_TYPE (ret);
461938fd1498Szrj low_bound = TREE_PURPOSE (t);
462038fd1498Szrj length = TREE_VALUE (t);
462138fd1498Szrj if ((low_bound && type_dependent_expression_p (low_bound))
462238fd1498Szrj || (length && type_dependent_expression_p (length)))
462338fd1498Szrj return NULL_TREE;
462438fd1498Szrj
462538fd1498Szrj if (low_bound == error_mark_node || length == error_mark_node)
462638fd1498Szrj return error_mark_node;
462738fd1498Szrj
462838fd1498Szrj if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound)))
462938fd1498Szrj {
463038fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
463138fd1498Szrj "low bound %qE of array section does not have integral type",
463238fd1498Szrj low_bound);
463338fd1498Szrj return error_mark_node;
463438fd1498Szrj }
463538fd1498Szrj if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length)))
463638fd1498Szrj {
463738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
463838fd1498Szrj "length %qE of array section does not have integral type",
463938fd1498Szrj length);
464038fd1498Szrj return error_mark_node;
464138fd1498Szrj }
464238fd1498Szrj if (low_bound)
464338fd1498Szrj low_bound = mark_rvalue_use (low_bound);
464438fd1498Szrj if (length)
464538fd1498Szrj length = mark_rvalue_use (length);
464638fd1498Szrj /* We need to reduce to real constant-values for checks below. */
464738fd1498Szrj if (length)
464838fd1498Szrj length = fold_simple (length);
464938fd1498Szrj if (low_bound)
465038fd1498Szrj low_bound = fold_simple (low_bound);
465138fd1498Szrj if (low_bound
465238fd1498Szrj && TREE_CODE (low_bound) == INTEGER_CST
465338fd1498Szrj && TYPE_PRECISION (TREE_TYPE (low_bound))
465438fd1498Szrj > TYPE_PRECISION (sizetype))
465538fd1498Szrj low_bound = fold_convert (sizetype, low_bound);
465638fd1498Szrj if (length
465738fd1498Szrj && TREE_CODE (length) == INTEGER_CST
465838fd1498Szrj && TYPE_PRECISION (TREE_TYPE (length))
465938fd1498Szrj > TYPE_PRECISION (sizetype))
466038fd1498Szrj length = fold_convert (sizetype, length);
466138fd1498Szrj if (low_bound == NULL_TREE)
466238fd1498Szrj low_bound = integer_zero_node;
466338fd1498Szrj
466438fd1498Szrj if (length != NULL_TREE)
466538fd1498Szrj {
466638fd1498Szrj if (!integer_nonzerop (length))
466738fd1498Szrj {
466838fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
466938fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
467038fd1498Szrj {
467138fd1498Szrj if (integer_zerop (length))
467238fd1498Szrj {
467338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
467438fd1498Szrj "zero length array section in %qs clause",
467538fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
467638fd1498Szrj return error_mark_node;
467738fd1498Szrj }
467838fd1498Szrj }
467938fd1498Szrj else
468038fd1498Szrj maybe_zero_len = true;
468138fd1498Szrj }
468238fd1498Szrj if (first_non_one == types.length ()
468338fd1498Szrj && (TREE_CODE (length) != INTEGER_CST || integer_onep (length)))
468438fd1498Szrj first_non_one++;
468538fd1498Szrj }
468638fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE)
468738fd1498Szrj {
468838fd1498Szrj if (length == NULL_TREE
468938fd1498Szrj && (TYPE_DOMAIN (type) == NULL_TREE
469038fd1498Szrj || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE))
469138fd1498Szrj {
469238fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
469338fd1498Szrj "for unknown bound array type length expression must "
469438fd1498Szrj "be specified");
469538fd1498Szrj return error_mark_node;
469638fd1498Szrj }
469738fd1498Szrj if (TREE_CODE (low_bound) == INTEGER_CST
469838fd1498Szrj && tree_int_cst_sgn (low_bound) == -1)
469938fd1498Szrj {
470038fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
470138fd1498Szrj "negative low bound in array section in %qs clause",
470238fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
470338fd1498Szrj return error_mark_node;
470438fd1498Szrj }
470538fd1498Szrj if (length != NULL_TREE
470638fd1498Szrj && TREE_CODE (length) == INTEGER_CST
470738fd1498Szrj && tree_int_cst_sgn (length) == -1)
470838fd1498Szrj {
470938fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
471038fd1498Szrj "negative length in array section in %qs clause",
471138fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
471238fd1498Szrj return error_mark_node;
471338fd1498Szrj }
471438fd1498Szrj if (TYPE_DOMAIN (type)
471538fd1498Szrj && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
471638fd1498Szrj && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
471738fd1498Szrj == INTEGER_CST)
471838fd1498Szrj {
471938fd1498Szrj tree size
472038fd1498Szrj = fold_convert (sizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
472138fd1498Szrj size = size_binop (PLUS_EXPR, size, size_one_node);
472238fd1498Szrj if (TREE_CODE (low_bound) == INTEGER_CST)
472338fd1498Szrj {
472438fd1498Szrj if (tree_int_cst_lt (size, low_bound))
472538fd1498Szrj {
472638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
472738fd1498Szrj "low bound %qE above array section size "
472838fd1498Szrj "in %qs clause", low_bound,
472938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
473038fd1498Szrj return error_mark_node;
473138fd1498Szrj }
473238fd1498Szrj if (tree_int_cst_equal (size, low_bound))
473338fd1498Szrj {
473438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
473538fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
473638fd1498Szrj {
473738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
473838fd1498Szrj "zero length array section in %qs clause",
473938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
474038fd1498Szrj return error_mark_node;
474138fd1498Szrj }
474238fd1498Szrj maybe_zero_len = true;
474338fd1498Szrj }
474438fd1498Szrj else if (length == NULL_TREE
474538fd1498Szrj && first_non_one == types.length ()
474638fd1498Szrj && tree_int_cst_equal
474738fd1498Szrj (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
474838fd1498Szrj low_bound))
474938fd1498Szrj first_non_one++;
475038fd1498Szrj }
475138fd1498Szrj else if (length == NULL_TREE)
475238fd1498Szrj {
475338fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
475438fd1498Szrj && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
475538fd1498Szrj maybe_zero_len = true;
475638fd1498Szrj if (first_non_one == types.length ())
475738fd1498Szrj first_non_one++;
475838fd1498Szrj }
475938fd1498Szrj if (length && TREE_CODE (length) == INTEGER_CST)
476038fd1498Szrj {
476138fd1498Szrj if (tree_int_cst_lt (size, length))
476238fd1498Szrj {
476338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
476438fd1498Szrj "length %qE above array section size "
476538fd1498Szrj "in %qs clause", length,
476638fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
476738fd1498Szrj return error_mark_node;
476838fd1498Szrj }
476938fd1498Szrj if (TREE_CODE (low_bound) == INTEGER_CST)
477038fd1498Szrj {
477138fd1498Szrj tree lbpluslen
477238fd1498Szrj = size_binop (PLUS_EXPR,
477338fd1498Szrj fold_convert (sizetype, low_bound),
477438fd1498Szrj fold_convert (sizetype, length));
477538fd1498Szrj if (TREE_CODE (lbpluslen) == INTEGER_CST
477638fd1498Szrj && tree_int_cst_lt (size, lbpluslen))
477738fd1498Szrj {
477838fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
477938fd1498Szrj "high bound %qE above array section size "
478038fd1498Szrj "in %qs clause", lbpluslen,
478138fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
478238fd1498Szrj return error_mark_node;
478338fd1498Szrj }
478438fd1498Szrj }
478538fd1498Szrj }
478638fd1498Szrj }
478738fd1498Szrj else if (length == NULL_TREE)
478838fd1498Szrj {
478938fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
479038fd1498Szrj && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
479138fd1498Szrj maybe_zero_len = true;
479238fd1498Szrj if (first_non_one == types.length ())
479338fd1498Szrj first_non_one++;
479438fd1498Szrj }
479538fd1498Szrj
479638fd1498Szrj /* For [lb:] we will need to evaluate lb more than once. */
479738fd1498Szrj if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
479838fd1498Szrj {
479938fd1498Szrj tree lb = cp_save_expr (low_bound);
480038fd1498Szrj if (lb != low_bound)
480138fd1498Szrj {
480238fd1498Szrj TREE_PURPOSE (t) = lb;
480338fd1498Szrj low_bound = lb;
480438fd1498Szrj }
480538fd1498Szrj }
480638fd1498Szrj }
480738fd1498Szrj else if (TREE_CODE (type) == POINTER_TYPE)
480838fd1498Szrj {
480938fd1498Szrj if (length == NULL_TREE)
481038fd1498Szrj {
481138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
481238fd1498Szrj "for pointer type length expression must be specified");
481338fd1498Szrj return error_mark_node;
481438fd1498Szrj }
481538fd1498Szrj if (length != NULL_TREE
481638fd1498Szrj && TREE_CODE (length) == INTEGER_CST
481738fd1498Szrj && tree_int_cst_sgn (length) == -1)
481838fd1498Szrj {
481938fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
482038fd1498Szrj "negative length in array section in %qs clause",
482138fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
482238fd1498Szrj return error_mark_node;
482338fd1498Szrj }
482438fd1498Szrj /* If there is a pointer type anywhere but in the very first
482538fd1498Szrj array-section-subscript, the array section can't be contiguous. */
482638fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
482738fd1498Szrj && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST)
482838fd1498Szrj {
482938fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
483038fd1498Szrj "array section is not contiguous in %qs clause",
483138fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
483238fd1498Szrj return error_mark_node;
483338fd1498Szrj }
483438fd1498Szrj }
483538fd1498Szrj else
483638fd1498Szrj {
483738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
483838fd1498Szrj "%qE does not have pointer or array type", ret);
483938fd1498Szrj return error_mark_node;
484038fd1498Szrj }
484138fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
484238fd1498Szrj types.safe_push (TREE_TYPE (ret));
484338fd1498Szrj /* We will need to evaluate lb more than once. */
484438fd1498Szrj tree lb = cp_save_expr (low_bound);
484538fd1498Szrj if (lb != low_bound)
484638fd1498Szrj {
484738fd1498Szrj TREE_PURPOSE (t) = lb;
484838fd1498Szrj low_bound = lb;
484938fd1498Szrj }
485038fd1498Szrj ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, false);
485138fd1498Szrj return ret;
485238fd1498Szrj }
485338fd1498Szrj
485438fd1498Szrj /* Handle array sections for clause C. */
485538fd1498Szrj
485638fd1498Szrj static bool
handle_omp_array_sections(tree c,enum c_omp_region_type ort)485738fd1498Szrj handle_omp_array_sections (tree c, enum c_omp_region_type ort)
485838fd1498Szrj {
485938fd1498Szrj bool maybe_zero_len = false;
486038fd1498Szrj unsigned int first_non_one = 0;
486138fd1498Szrj auto_vec<tree, 10> types;
486238fd1498Szrj tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
486338fd1498Szrj maybe_zero_len, first_non_one,
486438fd1498Szrj ort);
486538fd1498Szrj if (first == error_mark_node)
486638fd1498Szrj return true;
486738fd1498Szrj if (first == NULL_TREE)
486838fd1498Szrj return false;
486938fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
487038fd1498Szrj {
487138fd1498Szrj tree t = OMP_CLAUSE_DECL (c);
487238fd1498Szrj tree tem = NULL_TREE;
487338fd1498Szrj if (processing_template_decl)
487438fd1498Szrj return false;
487538fd1498Szrj /* Need to evaluate side effects in the length expressions
487638fd1498Szrj if any. */
487738fd1498Szrj while (TREE_CODE (t) == TREE_LIST)
487838fd1498Szrj {
487938fd1498Szrj if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t)))
488038fd1498Szrj {
488138fd1498Szrj if (tem == NULL_TREE)
488238fd1498Szrj tem = TREE_VALUE (t);
488338fd1498Szrj else
488438fd1498Szrj tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem),
488538fd1498Szrj TREE_VALUE (t), tem);
488638fd1498Szrj }
488738fd1498Szrj t = TREE_CHAIN (t);
488838fd1498Szrj }
488938fd1498Szrj if (tem)
489038fd1498Szrj first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
489138fd1498Szrj OMP_CLAUSE_DECL (c) = first;
489238fd1498Szrj }
489338fd1498Szrj else
489438fd1498Szrj {
489538fd1498Szrj unsigned int num = types.length (), i;
489638fd1498Szrj tree t, side_effects = NULL_TREE, size = NULL_TREE;
489738fd1498Szrj tree condition = NULL_TREE;
489838fd1498Szrj
489938fd1498Szrj if (int_size_in_bytes (TREE_TYPE (first)) <= 0)
490038fd1498Szrj maybe_zero_len = true;
490138fd1498Szrj if (processing_template_decl && maybe_zero_len)
490238fd1498Szrj return false;
490338fd1498Szrj
490438fd1498Szrj for (i = num, t = OMP_CLAUSE_DECL (c); i > 0;
490538fd1498Szrj t = TREE_CHAIN (t))
490638fd1498Szrj {
490738fd1498Szrj tree low_bound = TREE_PURPOSE (t);
490838fd1498Szrj tree length = TREE_VALUE (t);
490938fd1498Szrj
491038fd1498Szrj i--;
491138fd1498Szrj if (low_bound
491238fd1498Szrj && TREE_CODE (low_bound) == INTEGER_CST
491338fd1498Szrj && TYPE_PRECISION (TREE_TYPE (low_bound))
491438fd1498Szrj > TYPE_PRECISION (sizetype))
491538fd1498Szrj low_bound = fold_convert (sizetype, low_bound);
491638fd1498Szrj if (length
491738fd1498Szrj && TREE_CODE (length) == INTEGER_CST
491838fd1498Szrj && TYPE_PRECISION (TREE_TYPE (length))
491938fd1498Szrj > TYPE_PRECISION (sizetype))
492038fd1498Szrj length = fold_convert (sizetype, length);
492138fd1498Szrj if (low_bound == NULL_TREE)
492238fd1498Szrj low_bound = integer_zero_node;
492338fd1498Szrj if (!maybe_zero_len && i > first_non_one)
492438fd1498Szrj {
492538fd1498Szrj if (integer_nonzerop (low_bound))
492638fd1498Szrj goto do_warn_noncontiguous;
492738fd1498Szrj if (length != NULL_TREE
492838fd1498Szrj && TREE_CODE (length) == INTEGER_CST
492938fd1498Szrj && TYPE_DOMAIN (types[i])
493038fd1498Szrj && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))
493138fd1498Szrj && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])))
493238fd1498Szrj == INTEGER_CST)
493338fd1498Szrj {
493438fd1498Szrj tree size;
493538fd1498Szrj size = size_binop (PLUS_EXPR,
493638fd1498Szrj TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
493738fd1498Szrj size_one_node);
493838fd1498Szrj if (!tree_int_cst_equal (length, size))
493938fd1498Szrj {
494038fd1498Szrj do_warn_noncontiguous:
494138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
494238fd1498Szrj "array section is not contiguous in %qs "
494338fd1498Szrj "clause",
494438fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
494538fd1498Szrj return true;
494638fd1498Szrj }
494738fd1498Szrj }
494838fd1498Szrj if (!processing_template_decl
494938fd1498Szrj && length != NULL_TREE
495038fd1498Szrj && TREE_SIDE_EFFECTS (length))
495138fd1498Szrj {
495238fd1498Szrj if (side_effects == NULL_TREE)
495338fd1498Szrj side_effects = length;
495438fd1498Szrj else
495538fd1498Szrj side_effects = build2 (COMPOUND_EXPR,
495638fd1498Szrj TREE_TYPE (side_effects),
495738fd1498Szrj length, side_effects);
495838fd1498Szrj }
495938fd1498Szrj }
496038fd1498Szrj else if (processing_template_decl)
496138fd1498Szrj continue;
496238fd1498Szrj else
496338fd1498Szrj {
496438fd1498Szrj tree l;
496538fd1498Szrj
496638fd1498Szrj if (i > first_non_one
496738fd1498Szrj && ((length && integer_nonzerop (length))
496838fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
496938fd1498Szrj continue;
497038fd1498Szrj if (length)
497138fd1498Szrj l = fold_convert (sizetype, length);
497238fd1498Szrj else
497338fd1498Szrj {
497438fd1498Szrj l = size_binop (PLUS_EXPR,
497538fd1498Szrj TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])),
497638fd1498Szrj size_one_node);
497738fd1498Szrj l = size_binop (MINUS_EXPR, l,
497838fd1498Szrj fold_convert (sizetype, low_bound));
497938fd1498Szrj }
498038fd1498Szrj if (i > first_non_one)
498138fd1498Szrj {
498238fd1498Szrj l = fold_build2 (NE_EXPR, boolean_type_node, l,
498338fd1498Szrj size_zero_node);
498438fd1498Szrj if (condition == NULL_TREE)
498538fd1498Szrj condition = l;
498638fd1498Szrj else
498738fd1498Szrj condition = fold_build2 (BIT_AND_EXPR, boolean_type_node,
498838fd1498Szrj l, condition);
498938fd1498Szrj }
499038fd1498Szrj else if (size == NULL_TREE)
499138fd1498Szrj {
499238fd1498Szrj size = size_in_bytes (TREE_TYPE (types[i]));
499338fd1498Szrj tree eltype = TREE_TYPE (types[num - 1]);
499438fd1498Szrj while (TREE_CODE (eltype) == ARRAY_TYPE)
499538fd1498Szrj eltype = TREE_TYPE (eltype);
499638fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
499738fd1498Szrj size = size_binop (EXACT_DIV_EXPR, size,
499838fd1498Szrj size_in_bytes (eltype));
499938fd1498Szrj size = size_binop (MULT_EXPR, size, l);
500038fd1498Szrj if (condition)
500138fd1498Szrj size = fold_build3 (COND_EXPR, sizetype, condition,
500238fd1498Szrj size, size_zero_node);
500338fd1498Szrj }
500438fd1498Szrj else
500538fd1498Szrj size = size_binop (MULT_EXPR, size, l);
500638fd1498Szrj }
500738fd1498Szrj }
500838fd1498Szrj if (!processing_template_decl)
500938fd1498Szrj {
501038fd1498Szrj if (side_effects)
501138fd1498Szrj size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
501238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
501338fd1498Szrj {
501438fd1498Szrj size = size_binop (MINUS_EXPR, size, size_one_node);
501538fd1498Szrj tree index_type = build_index_type (size);
501638fd1498Szrj tree eltype = TREE_TYPE (first);
501738fd1498Szrj while (TREE_CODE (eltype) == ARRAY_TYPE)
501838fd1498Szrj eltype = TREE_TYPE (eltype);
501938fd1498Szrj tree type = build_array_type (eltype, index_type);
502038fd1498Szrj tree ptype = build_pointer_type (eltype);
502138fd1498Szrj if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
502238fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
502338fd1498Szrj t = convert_from_reference (t);
502438fd1498Szrj else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
502538fd1498Szrj t = build_fold_addr_expr (t);
502638fd1498Szrj tree t2 = build_fold_addr_expr (first);
502738fd1498Szrj t2 = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
502838fd1498Szrj ptrdiff_type_node, t2);
502938fd1498Szrj t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
503038fd1498Szrj ptrdiff_type_node, t2,
503138fd1498Szrj fold_convert_loc (OMP_CLAUSE_LOCATION (c),
503238fd1498Szrj ptrdiff_type_node, t));
503338fd1498Szrj if (tree_fits_shwi_p (t2))
503438fd1498Szrj t = build2 (MEM_REF, type, t,
503538fd1498Szrj build_int_cst (ptype, tree_to_shwi (t2)));
503638fd1498Szrj else
503738fd1498Szrj {
503838fd1498Szrj t2 = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
503938fd1498Szrj sizetype, t2);
504038fd1498Szrj t = build2_loc (OMP_CLAUSE_LOCATION (c), POINTER_PLUS_EXPR,
504138fd1498Szrj TREE_TYPE (t), t, t2);
504238fd1498Szrj t = build2 (MEM_REF, type, t, build_int_cst (ptype, 0));
504338fd1498Szrj }
504438fd1498Szrj OMP_CLAUSE_DECL (c) = t;
504538fd1498Szrj return false;
504638fd1498Szrj }
504738fd1498Szrj OMP_CLAUSE_DECL (c) = first;
504838fd1498Szrj OMP_CLAUSE_SIZE (c) = size;
504938fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
505038fd1498Szrj || (TREE_CODE (t) == COMPONENT_REF
505138fd1498Szrj && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE))
505238fd1498Szrj return false;
505338fd1498Szrj if (ort == C_ORT_OMP || ort == C_ORT_ACC)
505438fd1498Szrj switch (OMP_CLAUSE_MAP_KIND (c))
505538fd1498Szrj {
505638fd1498Szrj case GOMP_MAP_ALLOC:
505738fd1498Szrj case GOMP_MAP_TO:
505838fd1498Szrj case GOMP_MAP_FROM:
505938fd1498Szrj case GOMP_MAP_TOFROM:
506038fd1498Szrj case GOMP_MAP_ALWAYS_TO:
506138fd1498Szrj case GOMP_MAP_ALWAYS_FROM:
506238fd1498Szrj case GOMP_MAP_ALWAYS_TOFROM:
506338fd1498Szrj case GOMP_MAP_RELEASE:
506438fd1498Szrj case GOMP_MAP_DELETE:
506538fd1498Szrj case GOMP_MAP_FORCE_TO:
506638fd1498Szrj case GOMP_MAP_FORCE_FROM:
506738fd1498Szrj case GOMP_MAP_FORCE_TOFROM:
506838fd1498Szrj case GOMP_MAP_FORCE_PRESENT:
506938fd1498Szrj OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
507038fd1498Szrj break;
507138fd1498Szrj default:
507238fd1498Szrj break;
507338fd1498Szrj }
507438fd1498Szrj tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
507538fd1498Szrj OMP_CLAUSE_MAP);
507638fd1498Szrj if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
507738fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
507838fd1498Szrj else if (TREE_CODE (t) == COMPONENT_REF)
507938fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
508038fd1498Szrj else if (REFERENCE_REF_P (t)
508138fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
508238fd1498Szrj {
508338fd1498Szrj t = TREE_OPERAND (t, 0);
508438fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
508538fd1498Szrj }
508638fd1498Szrj else
508738fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
508838fd1498Szrj if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
508938fd1498Szrj && !cxx_mark_addressable (t))
509038fd1498Szrj return false;
509138fd1498Szrj OMP_CLAUSE_DECL (c2) = t;
509238fd1498Szrj t = build_fold_addr_expr (first);
509338fd1498Szrj t = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
509438fd1498Szrj ptrdiff_type_node, t);
509538fd1498Szrj tree ptr = OMP_CLAUSE_DECL (c2);
509638fd1498Szrj ptr = convert_from_reference (ptr);
509738fd1498Szrj if (!POINTER_TYPE_P (TREE_TYPE (ptr)))
509838fd1498Szrj ptr = build_fold_addr_expr (ptr);
509938fd1498Szrj t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR,
510038fd1498Szrj ptrdiff_type_node, t,
510138fd1498Szrj fold_convert_loc (OMP_CLAUSE_LOCATION (c),
510238fd1498Szrj ptrdiff_type_node, ptr));
510338fd1498Szrj OMP_CLAUSE_SIZE (c2) = t;
510438fd1498Szrj OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
510538fd1498Szrj OMP_CLAUSE_CHAIN (c) = c2;
510638fd1498Szrj ptr = OMP_CLAUSE_DECL (c2);
510738fd1498Szrj if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
510838fd1498Szrj && TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
510938fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (ptr))))
511038fd1498Szrj {
511138fd1498Szrj tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
511238fd1498Szrj OMP_CLAUSE_MAP);
511338fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c3, OMP_CLAUSE_MAP_KIND (c2));
511438fd1498Szrj OMP_CLAUSE_DECL (c3) = ptr;
511538fd1498Szrj if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER)
511638fd1498Szrj OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr);
511738fd1498Szrj else
511838fd1498Szrj OMP_CLAUSE_DECL (c2) = convert_from_reference (ptr);
511938fd1498Szrj OMP_CLAUSE_SIZE (c3) = size_zero_node;
512038fd1498Szrj OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
512138fd1498Szrj OMP_CLAUSE_CHAIN (c2) = c3;
512238fd1498Szrj }
512338fd1498Szrj }
512438fd1498Szrj }
512538fd1498Szrj return false;
512638fd1498Szrj }
512738fd1498Szrj
512838fd1498Szrj /* Return identifier to look up for omp declare reduction. */
512938fd1498Szrj
513038fd1498Szrj tree
omp_reduction_id(enum tree_code reduction_code,tree reduction_id,tree type)513138fd1498Szrj omp_reduction_id (enum tree_code reduction_code, tree reduction_id, tree type)
513238fd1498Szrj {
513338fd1498Szrj const char *p = NULL;
513438fd1498Szrj const char *m = NULL;
513538fd1498Szrj switch (reduction_code)
513638fd1498Szrj {
513738fd1498Szrj case PLUS_EXPR:
513838fd1498Szrj case MULT_EXPR:
513938fd1498Szrj case MINUS_EXPR:
514038fd1498Szrj case BIT_AND_EXPR:
514138fd1498Szrj case BIT_XOR_EXPR:
514238fd1498Szrj case BIT_IOR_EXPR:
514338fd1498Szrj case TRUTH_ANDIF_EXPR:
514438fd1498Szrj case TRUTH_ORIF_EXPR:
514538fd1498Szrj reduction_id = ovl_op_identifier (false, reduction_code);
514638fd1498Szrj break;
514738fd1498Szrj case MIN_EXPR:
514838fd1498Szrj p = "min";
514938fd1498Szrj break;
515038fd1498Szrj case MAX_EXPR:
515138fd1498Szrj p = "max";
515238fd1498Szrj break;
515338fd1498Szrj default:
515438fd1498Szrj break;
515538fd1498Szrj }
515638fd1498Szrj
515738fd1498Szrj if (p == NULL)
515838fd1498Szrj {
515938fd1498Szrj if (TREE_CODE (reduction_id) != IDENTIFIER_NODE)
516038fd1498Szrj return error_mark_node;
516138fd1498Szrj p = IDENTIFIER_POINTER (reduction_id);
516238fd1498Szrj }
516338fd1498Szrj
516438fd1498Szrj if (type != NULL_TREE)
516538fd1498Szrj m = mangle_type_string (TYPE_MAIN_VARIANT (type));
516638fd1498Szrj
516738fd1498Szrj const char prefix[] = "omp declare reduction ";
516838fd1498Szrj size_t lenp = sizeof (prefix);
516938fd1498Szrj if (strncmp (p, prefix, lenp - 1) == 0)
517038fd1498Szrj lenp = 1;
517138fd1498Szrj size_t len = strlen (p);
517238fd1498Szrj size_t lenm = m ? strlen (m) + 1 : 0;
517338fd1498Szrj char *name = XALLOCAVEC (char, lenp + len + lenm);
517438fd1498Szrj if (lenp > 1)
517538fd1498Szrj memcpy (name, prefix, lenp - 1);
517638fd1498Szrj memcpy (name + lenp - 1, p, len + 1);
517738fd1498Szrj if (m)
517838fd1498Szrj {
517938fd1498Szrj name[lenp + len - 1] = '~';
518038fd1498Szrj memcpy (name + lenp + len, m, lenm);
518138fd1498Szrj }
518238fd1498Szrj return get_identifier (name);
518338fd1498Szrj }
518438fd1498Szrj
518538fd1498Szrj /* Lookup OpenMP UDR ID for TYPE, return the corresponding artificial
518638fd1498Szrj FUNCTION_DECL or NULL_TREE if not found. */
518738fd1498Szrj
518838fd1498Szrj static tree
omp_reduction_lookup(location_t loc,tree id,tree type,tree * baselinkp,vec<tree> * ambiguousp)518938fd1498Szrj omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp,
519038fd1498Szrj vec<tree> *ambiguousp)
519138fd1498Szrj {
519238fd1498Szrj tree orig_id = id;
519338fd1498Szrj tree baselink = NULL_TREE;
519438fd1498Szrj if (identifier_p (id))
519538fd1498Szrj {
519638fd1498Szrj cp_id_kind idk;
519738fd1498Szrj bool nonint_cst_expression_p;
519838fd1498Szrj const char *error_msg;
519938fd1498Szrj id = omp_reduction_id (ERROR_MARK, id, type);
520038fd1498Szrj tree decl = lookup_name (id);
520138fd1498Szrj if (decl == NULL_TREE)
520238fd1498Szrj decl = error_mark_node;
520338fd1498Szrj id = finish_id_expression (id, decl, NULL_TREE, &idk, false, true,
520438fd1498Szrj &nonint_cst_expression_p, false, true, false,
520538fd1498Szrj false, &error_msg, loc);
520638fd1498Szrj if (idk == CP_ID_KIND_UNQUALIFIED
520738fd1498Szrj && identifier_p (id))
520838fd1498Szrj {
520938fd1498Szrj vec<tree, va_gc> *args = NULL;
521038fd1498Szrj vec_safe_push (args, build_reference_type (type));
521138fd1498Szrj id = perform_koenig_lookup (id, args, tf_none);
521238fd1498Szrj }
521338fd1498Szrj }
521438fd1498Szrj else if (TREE_CODE (id) == SCOPE_REF)
521538fd1498Szrj id = lookup_qualified_name (TREE_OPERAND (id, 0),
521638fd1498Szrj omp_reduction_id (ERROR_MARK,
521738fd1498Szrj TREE_OPERAND (id, 1),
521838fd1498Szrj type),
521938fd1498Szrj false, false);
522038fd1498Szrj tree fns = id;
522138fd1498Szrj id = NULL_TREE;
522238fd1498Szrj if (fns && is_overloaded_fn (fns))
522338fd1498Szrj {
522438fd1498Szrj for (lkp_iterator iter (get_fns (fns)); iter; ++iter)
522538fd1498Szrj {
522638fd1498Szrj tree fndecl = *iter;
522738fd1498Szrj if (TREE_CODE (fndecl) == FUNCTION_DECL)
522838fd1498Szrj {
522938fd1498Szrj tree argtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
523038fd1498Szrj if (same_type_p (TREE_TYPE (argtype), type))
523138fd1498Szrj {
523238fd1498Szrj id = fndecl;
523338fd1498Szrj break;
523438fd1498Szrj }
523538fd1498Szrj }
523638fd1498Szrj }
523738fd1498Szrj
523838fd1498Szrj if (id && BASELINK_P (fns))
523938fd1498Szrj {
524038fd1498Szrj if (baselinkp)
524138fd1498Szrj *baselinkp = fns;
524238fd1498Szrj else
524338fd1498Szrj baselink = fns;
524438fd1498Szrj }
524538fd1498Szrj }
524638fd1498Szrj
524738fd1498Szrj if (!id && CLASS_TYPE_P (type) && TYPE_BINFO (type))
524838fd1498Szrj {
524938fd1498Szrj vec<tree> ambiguous = vNULL;
525038fd1498Szrj tree binfo = TYPE_BINFO (type), base_binfo, ret = NULL_TREE;
525138fd1498Szrj unsigned int ix;
525238fd1498Szrj if (ambiguousp == NULL)
525338fd1498Szrj ambiguousp = &ambiguous;
525438fd1498Szrj for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
525538fd1498Szrj {
525638fd1498Szrj id = omp_reduction_lookup (loc, orig_id, BINFO_TYPE (base_binfo),
525738fd1498Szrj baselinkp ? baselinkp : &baselink,
525838fd1498Szrj ambiguousp);
525938fd1498Szrj if (id == NULL_TREE)
526038fd1498Szrj continue;
526138fd1498Szrj if (!ambiguousp->is_empty ())
526238fd1498Szrj ambiguousp->safe_push (id);
526338fd1498Szrj else if (ret != NULL_TREE)
526438fd1498Szrj {
526538fd1498Szrj ambiguousp->safe_push (ret);
526638fd1498Szrj ambiguousp->safe_push (id);
526738fd1498Szrj ret = NULL_TREE;
526838fd1498Szrj }
526938fd1498Szrj else
527038fd1498Szrj ret = id;
527138fd1498Szrj }
527238fd1498Szrj if (ambiguousp != &ambiguous)
527338fd1498Szrj return ret;
527438fd1498Szrj if (!ambiguous.is_empty ())
527538fd1498Szrj {
527638fd1498Szrj const char *str = _("candidates are:");
527738fd1498Szrj unsigned int idx;
527838fd1498Szrj tree udr;
527938fd1498Szrj error_at (loc, "user defined reduction lookup is ambiguous");
528038fd1498Szrj FOR_EACH_VEC_ELT (ambiguous, idx, udr)
528138fd1498Szrj {
528238fd1498Szrj inform (DECL_SOURCE_LOCATION (udr), "%s %#qD", str, udr);
528338fd1498Szrj if (idx == 0)
528438fd1498Szrj str = get_spaces (str);
528538fd1498Szrj }
528638fd1498Szrj ambiguous.release ();
528738fd1498Szrj ret = error_mark_node;
528838fd1498Szrj baselink = NULL_TREE;
528938fd1498Szrj }
529038fd1498Szrj id = ret;
529138fd1498Szrj }
529238fd1498Szrj if (id && baselink)
529338fd1498Szrj perform_or_defer_access_check (BASELINK_BINFO (baselink),
529438fd1498Szrj id, id, tf_warning_or_error);
529538fd1498Szrj return id;
529638fd1498Szrj }
529738fd1498Szrj
529838fd1498Szrj /* Helper function for cp_parser_omp_declare_reduction_exprs
529938fd1498Szrj and tsubst_omp_udr.
530038fd1498Szrj Remove CLEANUP_STMT for data (omp_priv variable).
530138fd1498Szrj Also append INIT_EXPR for DECL_INITIAL of omp_priv after its
530238fd1498Szrj DECL_EXPR. */
530338fd1498Szrj
530438fd1498Szrj tree
cp_remove_omp_priv_cleanup_stmt(tree * tp,int * walk_subtrees,void * data)530538fd1498Szrj cp_remove_omp_priv_cleanup_stmt (tree *tp, int *walk_subtrees, void *data)
530638fd1498Szrj {
530738fd1498Szrj if (TYPE_P (*tp))
530838fd1498Szrj *walk_subtrees = 0;
530938fd1498Szrj else if (TREE_CODE (*tp) == CLEANUP_STMT && CLEANUP_DECL (*tp) == (tree) data)
531038fd1498Szrj *tp = CLEANUP_BODY (*tp);
531138fd1498Szrj else if (TREE_CODE (*tp) == DECL_EXPR)
531238fd1498Szrj {
531338fd1498Szrj tree decl = DECL_EXPR_DECL (*tp);
531438fd1498Szrj if (!processing_template_decl
531538fd1498Szrj && decl == (tree) data
531638fd1498Szrj && DECL_INITIAL (decl)
531738fd1498Szrj && DECL_INITIAL (decl) != error_mark_node)
531838fd1498Szrj {
531938fd1498Szrj tree list = NULL_TREE;
532038fd1498Szrj append_to_statement_list_force (*tp, &list);
532138fd1498Szrj tree init_expr = build2 (INIT_EXPR, void_type_node,
532238fd1498Szrj decl, DECL_INITIAL (decl));
532338fd1498Szrj DECL_INITIAL (decl) = NULL_TREE;
532438fd1498Szrj append_to_statement_list_force (init_expr, &list);
532538fd1498Szrj *tp = list;
532638fd1498Szrj }
532738fd1498Szrj }
532838fd1498Szrj return NULL_TREE;
532938fd1498Szrj }
533038fd1498Szrj
533138fd1498Szrj /* Data passed from cp_check_omp_declare_reduction to
533238fd1498Szrj cp_check_omp_declare_reduction_r. */
533338fd1498Szrj
533438fd1498Szrj struct cp_check_omp_declare_reduction_data
533538fd1498Szrj {
533638fd1498Szrj location_t loc;
533738fd1498Szrj tree stmts[7];
533838fd1498Szrj bool combiner_p;
533938fd1498Szrj };
534038fd1498Szrj
534138fd1498Szrj /* Helper function for cp_check_omp_declare_reduction, called via
534238fd1498Szrj cp_walk_tree. */
534338fd1498Szrj
534438fd1498Szrj static tree
cp_check_omp_declare_reduction_r(tree * tp,int *,void * data)534538fd1498Szrj cp_check_omp_declare_reduction_r (tree *tp, int *, void *data)
534638fd1498Szrj {
534738fd1498Szrj struct cp_check_omp_declare_reduction_data *udr_data
534838fd1498Szrj = (struct cp_check_omp_declare_reduction_data *) data;
534938fd1498Szrj if (SSA_VAR_P (*tp)
535038fd1498Szrj && !DECL_ARTIFICIAL (*tp)
535138fd1498Szrj && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 0 : 3])
535238fd1498Szrj && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 1 : 4]))
535338fd1498Szrj {
535438fd1498Szrj location_t loc = udr_data->loc;
535538fd1498Szrj if (udr_data->combiner_p)
535638fd1498Szrj error_at (loc, "%<#pragma omp declare reduction%> combiner refers to "
535738fd1498Szrj "variable %qD which is not %<omp_out%> nor %<omp_in%>",
535838fd1498Szrj *tp);
535938fd1498Szrj else
536038fd1498Szrj error_at (loc, "%<#pragma omp declare reduction%> initializer refers "
536138fd1498Szrj "to variable %qD which is not %<omp_priv%> nor "
536238fd1498Szrj "%<omp_orig%>",
536338fd1498Szrj *tp);
536438fd1498Szrj return *tp;
536538fd1498Szrj }
536638fd1498Szrj return NULL_TREE;
536738fd1498Szrj }
536838fd1498Szrj
536938fd1498Szrj /* Diagnose violation of OpenMP #pragma omp declare reduction restrictions. */
537038fd1498Szrj
537138fd1498Szrj void
cp_check_omp_declare_reduction(tree udr)537238fd1498Szrj cp_check_omp_declare_reduction (tree udr)
537338fd1498Szrj {
537438fd1498Szrj tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (udr)));
537538fd1498Szrj gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
537638fd1498Szrj type = TREE_TYPE (type);
537738fd1498Szrj int i;
537838fd1498Szrj location_t loc = DECL_SOURCE_LOCATION (udr);
537938fd1498Szrj
538038fd1498Szrj if (type == error_mark_node)
538138fd1498Szrj return;
538238fd1498Szrj if (ARITHMETIC_TYPE_P (type))
538338fd1498Szrj {
538438fd1498Szrj static enum tree_code predef_codes[]
538538fd1498Szrj = { PLUS_EXPR, MULT_EXPR, MINUS_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR,
538638fd1498Szrj BIT_IOR_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR };
538738fd1498Szrj for (i = 0; i < 8; i++)
538838fd1498Szrj {
538938fd1498Szrj tree id = omp_reduction_id (predef_codes[i], NULL_TREE, NULL_TREE);
539038fd1498Szrj const char *n1 = IDENTIFIER_POINTER (DECL_NAME (udr));
539138fd1498Szrj const char *n2 = IDENTIFIER_POINTER (id);
539238fd1498Szrj if (strncmp (n1, n2, IDENTIFIER_LENGTH (id)) == 0
539338fd1498Szrj && (n1[IDENTIFIER_LENGTH (id)] == '~'
539438fd1498Szrj || n1[IDENTIFIER_LENGTH (id)] == '\0'))
539538fd1498Szrj break;
539638fd1498Szrj }
539738fd1498Szrj
539838fd1498Szrj if (i == 8
539938fd1498Szrj && TREE_CODE (type) != COMPLEX_EXPR)
540038fd1498Szrj {
540138fd1498Szrj const char prefix_minmax[] = "omp declare reduction m";
540238fd1498Szrj size_t prefix_size = sizeof (prefix_minmax) - 1;
540338fd1498Szrj const char *n = IDENTIFIER_POINTER (DECL_NAME (udr));
540438fd1498Szrj if (strncmp (IDENTIFIER_POINTER (DECL_NAME (udr)),
540538fd1498Szrj prefix_minmax, prefix_size) == 0
540638fd1498Szrj && ((n[prefix_size] == 'i' && n[prefix_size + 1] == 'n')
540738fd1498Szrj || (n[prefix_size] == 'a' && n[prefix_size + 1] == 'x'))
540838fd1498Szrj && (n[prefix_size + 2] == '~' || n[prefix_size + 2] == '\0'))
540938fd1498Szrj i = 0;
541038fd1498Szrj }
541138fd1498Szrj if (i < 8)
541238fd1498Szrj {
541338fd1498Szrj error_at (loc, "predeclared arithmetic type %qT in "
541438fd1498Szrj "%<#pragma omp declare reduction%>", type);
541538fd1498Szrj return;
541638fd1498Szrj }
541738fd1498Szrj }
541838fd1498Szrj else if (TREE_CODE (type) == FUNCTION_TYPE
541938fd1498Szrj || TREE_CODE (type) == METHOD_TYPE
542038fd1498Szrj || TREE_CODE (type) == ARRAY_TYPE)
542138fd1498Szrj {
542238fd1498Szrj error_at (loc, "function or array type %qT in "
542338fd1498Szrj "%<#pragma omp declare reduction%>", type);
542438fd1498Szrj return;
542538fd1498Szrj }
542638fd1498Szrj else if (TREE_CODE (type) == REFERENCE_TYPE)
542738fd1498Szrj {
542838fd1498Szrj error_at (loc, "reference type %qT in %<#pragma omp declare reduction%>",
542938fd1498Szrj type);
543038fd1498Szrj return;
543138fd1498Szrj }
543238fd1498Szrj else if (TYPE_QUALS_NO_ADDR_SPACE (type))
543338fd1498Szrj {
543438fd1498Szrj error_at (loc, "const, volatile or __restrict qualified type %qT in "
543538fd1498Szrj "%<#pragma omp declare reduction%>", type);
543638fd1498Szrj return;
543738fd1498Szrj }
543838fd1498Szrj
543938fd1498Szrj tree body = DECL_SAVED_TREE (udr);
544038fd1498Szrj if (body == NULL_TREE || TREE_CODE (body) != STATEMENT_LIST)
544138fd1498Szrj return;
544238fd1498Szrj
544338fd1498Szrj tree_stmt_iterator tsi;
544438fd1498Szrj struct cp_check_omp_declare_reduction_data data;
544538fd1498Szrj memset (data.stmts, 0, sizeof data.stmts);
544638fd1498Szrj for (i = 0, tsi = tsi_start (body);
544738fd1498Szrj i < 7 && !tsi_end_p (tsi);
544838fd1498Szrj i++, tsi_next (&tsi))
544938fd1498Szrj data.stmts[i] = tsi_stmt (tsi);
545038fd1498Szrj data.loc = loc;
545138fd1498Szrj gcc_assert (tsi_end_p (tsi));
545238fd1498Szrj if (i >= 3)
545338fd1498Szrj {
545438fd1498Szrj gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR
545538fd1498Szrj && TREE_CODE (data.stmts[1]) == DECL_EXPR);
545638fd1498Szrj if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])))
545738fd1498Szrj return;
545838fd1498Szrj data.combiner_p = true;
545938fd1498Szrj if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r,
546038fd1498Szrj &data, NULL))
546138fd1498Szrj TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
546238fd1498Szrj }
546338fd1498Szrj if (i >= 6)
546438fd1498Szrj {
546538fd1498Szrj gcc_assert (TREE_CODE (data.stmts[3]) == DECL_EXPR
546638fd1498Szrj && TREE_CODE (data.stmts[4]) == DECL_EXPR);
546738fd1498Szrj data.combiner_p = false;
546838fd1498Szrj if (cp_walk_tree (&data.stmts[5], cp_check_omp_declare_reduction_r,
546938fd1498Szrj &data, NULL)
547038fd1498Szrj || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])),
547138fd1498Szrj cp_check_omp_declare_reduction_r, &data, NULL))
547238fd1498Szrj TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
547338fd1498Szrj if (i == 7)
547438fd1498Szrj gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR);
547538fd1498Szrj }
547638fd1498Szrj }
547738fd1498Szrj
547838fd1498Szrj /* Helper function of finish_omp_clauses. Clone STMT as if we were making
547938fd1498Szrj an inline call. But, remap
548038fd1498Szrj the OMP_DECL1 VAR_DECL (omp_out resp. omp_orig) to PLACEHOLDER
548138fd1498Szrj and OMP_DECL2 VAR_DECL (omp_in resp. omp_priv) to DECL. */
548238fd1498Szrj
548338fd1498Szrj static tree
clone_omp_udr(tree stmt,tree omp_decl1,tree omp_decl2,tree decl,tree placeholder)548438fd1498Szrj clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2,
548538fd1498Szrj tree decl, tree placeholder)
548638fd1498Szrj {
548738fd1498Szrj copy_body_data id;
548838fd1498Szrj hash_map<tree, tree> decl_map;
548938fd1498Szrj
549038fd1498Szrj decl_map.put (omp_decl1, placeholder);
549138fd1498Szrj decl_map.put (omp_decl2, decl);
549238fd1498Szrj memset (&id, 0, sizeof (id));
549338fd1498Szrj id.src_fn = DECL_CONTEXT (omp_decl1);
549438fd1498Szrj id.dst_fn = current_function_decl;
549538fd1498Szrj id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn);
549638fd1498Szrj id.decl_map = &decl_map;
549738fd1498Szrj
549838fd1498Szrj id.copy_decl = copy_decl_no_change;
549938fd1498Szrj id.transform_call_graph_edges = CB_CGE_DUPLICATE;
550038fd1498Szrj id.transform_new_cfg = true;
550138fd1498Szrj id.transform_return_to_modify = false;
550238fd1498Szrj id.transform_lang_insert_block = NULL;
550338fd1498Szrj id.eh_lp_nr = 0;
550438fd1498Szrj walk_tree (&stmt, copy_tree_body_r, &id, NULL);
550538fd1498Szrj return stmt;
550638fd1498Szrj }
550738fd1498Szrj
550838fd1498Szrj /* Helper function of finish_omp_clauses, called via cp_walk_tree.
550938fd1498Szrj Find OMP_CLAUSE_PLACEHOLDER (passed in DATA) in *TP. */
551038fd1498Szrj
551138fd1498Szrj static tree
find_omp_placeholder_r(tree * tp,int *,void * data)551238fd1498Szrj find_omp_placeholder_r (tree *tp, int *, void *data)
551338fd1498Szrj {
551438fd1498Szrj if (*tp == (tree) data)
551538fd1498Szrj return *tp;
551638fd1498Szrj return NULL_TREE;
551738fd1498Szrj }
551838fd1498Szrj
551938fd1498Szrj /* Helper function of finish_omp_clauses. Handle OMP_CLAUSE_REDUCTION C.
552038fd1498Szrj Return true if there is some error and the clause should be removed. */
552138fd1498Szrj
552238fd1498Szrj static bool
finish_omp_reduction_clause(tree c,bool * need_default_ctor,bool * need_dtor)552338fd1498Szrj finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
552438fd1498Szrj {
552538fd1498Szrj tree t = OMP_CLAUSE_DECL (c);
552638fd1498Szrj bool predefined = false;
552738fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
552838fd1498Szrj {
552938fd1498Szrj gcc_assert (processing_template_decl);
553038fd1498Szrj return false;
553138fd1498Szrj }
553238fd1498Szrj tree type = TREE_TYPE (t);
553338fd1498Szrj if (TREE_CODE (t) == MEM_REF)
553438fd1498Szrj type = TREE_TYPE (type);
553538fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
553638fd1498Szrj type = TREE_TYPE (type);
553738fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE)
553838fd1498Szrj {
553938fd1498Szrj tree oatype = type;
554038fd1498Szrj gcc_assert (TREE_CODE (t) != MEM_REF);
554138fd1498Szrj while (TREE_CODE (type) == ARRAY_TYPE)
554238fd1498Szrj type = TREE_TYPE (type);
554338fd1498Szrj if (!processing_template_decl)
554438fd1498Szrj {
554538fd1498Szrj t = require_complete_type (t);
554638fd1498Szrj if (t == error_mark_node)
554738fd1498Szrj return true;
554838fd1498Szrj tree size = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (oatype),
554938fd1498Szrj TYPE_SIZE_UNIT (type));
555038fd1498Szrj if (integer_zerop (size))
555138fd1498Szrj {
555238fd1498Szrj error ("%qE in %<reduction%> clause is a zero size array",
555338fd1498Szrj omp_clause_printable_decl (t));
555438fd1498Szrj return true;
555538fd1498Szrj }
555638fd1498Szrj size = size_binop (MINUS_EXPR, size, size_one_node);
555738fd1498Szrj tree index_type = build_index_type (size);
555838fd1498Szrj tree atype = build_array_type (type, index_type);
555938fd1498Szrj tree ptype = build_pointer_type (type);
556038fd1498Szrj if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
556138fd1498Szrj t = build_fold_addr_expr (t);
556238fd1498Szrj t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0));
556338fd1498Szrj OMP_CLAUSE_DECL (c) = t;
556438fd1498Szrj }
556538fd1498Szrj }
556638fd1498Szrj if (type == error_mark_node)
556738fd1498Szrj return true;
556838fd1498Szrj else if (ARITHMETIC_TYPE_P (type))
556938fd1498Szrj switch (OMP_CLAUSE_REDUCTION_CODE (c))
557038fd1498Szrj {
557138fd1498Szrj case PLUS_EXPR:
557238fd1498Szrj case MULT_EXPR:
557338fd1498Szrj case MINUS_EXPR:
557438fd1498Szrj predefined = true;
557538fd1498Szrj break;
557638fd1498Szrj case MIN_EXPR:
557738fd1498Szrj case MAX_EXPR:
557838fd1498Szrj if (TREE_CODE (type) == COMPLEX_TYPE)
557938fd1498Szrj break;
558038fd1498Szrj predefined = true;
558138fd1498Szrj break;
558238fd1498Szrj case BIT_AND_EXPR:
558338fd1498Szrj case BIT_IOR_EXPR:
558438fd1498Szrj case BIT_XOR_EXPR:
558538fd1498Szrj if (FLOAT_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
558638fd1498Szrj break;
558738fd1498Szrj predefined = true;
558838fd1498Szrj break;
558938fd1498Szrj case TRUTH_ANDIF_EXPR:
559038fd1498Szrj case TRUTH_ORIF_EXPR:
559138fd1498Szrj if (FLOAT_TYPE_P (type))
559238fd1498Szrj break;
559338fd1498Szrj predefined = true;
559438fd1498Szrj break;
559538fd1498Szrj default:
559638fd1498Szrj break;
559738fd1498Szrj }
559838fd1498Szrj else if (TYPE_READONLY (type))
559938fd1498Szrj {
560038fd1498Szrj error ("%qE has const type for %<reduction%>",
560138fd1498Szrj omp_clause_printable_decl (t));
560238fd1498Szrj return true;
560338fd1498Szrj }
560438fd1498Szrj else if (!processing_template_decl)
560538fd1498Szrj {
560638fd1498Szrj t = require_complete_type (t);
560738fd1498Szrj if (t == error_mark_node)
560838fd1498Szrj return true;
560938fd1498Szrj OMP_CLAUSE_DECL (c) = t;
561038fd1498Szrj }
561138fd1498Szrj
561238fd1498Szrj if (predefined)
561338fd1498Szrj {
561438fd1498Szrj OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE;
561538fd1498Szrj return false;
561638fd1498Szrj }
561738fd1498Szrj else if (processing_template_decl)
561838fd1498Szrj {
561938fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node)
562038fd1498Szrj return true;
562138fd1498Szrj return false;
562238fd1498Szrj }
562338fd1498Szrj
562438fd1498Szrj tree id = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
562538fd1498Szrj
562638fd1498Szrj type = TYPE_MAIN_VARIANT (type);
562738fd1498Szrj OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE;
562838fd1498Szrj if (id == NULL_TREE)
562938fd1498Szrj id = omp_reduction_id (OMP_CLAUSE_REDUCTION_CODE (c),
563038fd1498Szrj NULL_TREE, NULL_TREE);
563138fd1498Szrj id = omp_reduction_lookup (OMP_CLAUSE_LOCATION (c), id, type, NULL, NULL);
563238fd1498Szrj if (id)
563338fd1498Szrj {
563438fd1498Szrj if (id == error_mark_node)
563538fd1498Szrj return true;
563638fd1498Szrj mark_used (id);
563738fd1498Szrj tree body = DECL_SAVED_TREE (id);
563838fd1498Szrj if (!body)
563938fd1498Szrj return true;
564038fd1498Szrj if (TREE_CODE (body) == STATEMENT_LIST)
564138fd1498Szrj {
564238fd1498Szrj tree_stmt_iterator tsi;
564338fd1498Szrj tree placeholder = NULL_TREE, decl_placeholder = NULL_TREE;
564438fd1498Szrj int i;
564538fd1498Szrj tree stmts[7];
564638fd1498Szrj tree atype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (id)));
564738fd1498Szrj atype = TREE_TYPE (atype);
564838fd1498Szrj bool need_static_cast = !same_type_p (type, atype);
564938fd1498Szrj memset (stmts, 0, sizeof stmts);
565038fd1498Szrj for (i = 0, tsi = tsi_start (body);
565138fd1498Szrj i < 7 && !tsi_end_p (tsi);
565238fd1498Szrj i++, tsi_next (&tsi))
565338fd1498Szrj stmts[i] = tsi_stmt (tsi);
565438fd1498Szrj gcc_assert (tsi_end_p (tsi));
565538fd1498Szrj
565638fd1498Szrj if (i >= 3)
565738fd1498Szrj {
565838fd1498Szrj gcc_assert (TREE_CODE (stmts[0]) == DECL_EXPR
565938fd1498Szrj && TREE_CODE (stmts[1]) == DECL_EXPR);
566038fd1498Szrj placeholder = build_lang_decl (VAR_DECL, NULL_TREE, type);
566138fd1498Szrj DECL_ARTIFICIAL (placeholder) = 1;
566238fd1498Szrj DECL_IGNORED_P (placeholder) = 1;
566338fd1498Szrj OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = placeholder;
566438fd1498Szrj if (TREE_CODE (t) == MEM_REF)
566538fd1498Szrj {
566638fd1498Szrj decl_placeholder = build_lang_decl (VAR_DECL, NULL_TREE,
566738fd1498Szrj type);
566838fd1498Szrj DECL_ARTIFICIAL (decl_placeholder) = 1;
566938fd1498Szrj DECL_IGNORED_P (decl_placeholder) = 1;
567038fd1498Szrj OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = decl_placeholder;
567138fd1498Szrj }
567238fd1498Szrj if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0])))
567338fd1498Szrj cxx_mark_addressable (placeholder);
567438fd1498Szrj if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
567538fd1498Szrj && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
567638fd1498Szrj != REFERENCE_TYPE)
567738fd1498Szrj cxx_mark_addressable (decl_placeholder ? decl_placeholder
567838fd1498Szrj : OMP_CLAUSE_DECL (c));
567938fd1498Szrj tree omp_out = placeholder;
568038fd1498Szrj tree omp_in = decl_placeholder ? decl_placeholder
568138fd1498Szrj : convert_from_reference (OMP_CLAUSE_DECL (c));
568238fd1498Szrj if (need_static_cast)
568338fd1498Szrj {
568438fd1498Szrj tree rtype = build_reference_type (atype);
568538fd1498Szrj omp_out = build_static_cast (rtype, omp_out,
568638fd1498Szrj tf_warning_or_error);
568738fd1498Szrj omp_in = build_static_cast (rtype, omp_in,
568838fd1498Szrj tf_warning_or_error);
568938fd1498Szrj if (omp_out == error_mark_node || omp_in == error_mark_node)
569038fd1498Szrj return true;
569138fd1498Szrj omp_out = convert_from_reference (omp_out);
569238fd1498Szrj omp_in = convert_from_reference (omp_in);
569338fd1498Szrj }
569438fd1498Szrj OMP_CLAUSE_REDUCTION_MERGE (c)
569538fd1498Szrj = clone_omp_udr (stmts[2], DECL_EXPR_DECL (stmts[0]),
569638fd1498Szrj DECL_EXPR_DECL (stmts[1]), omp_in, omp_out);
569738fd1498Szrj }
569838fd1498Szrj if (i >= 6)
569938fd1498Szrj {
570038fd1498Szrj gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
570138fd1498Szrj && TREE_CODE (stmts[4]) == DECL_EXPR);
570238fd1498Szrj if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
570338fd1498Szrj cxx_mark_addressable (decl_placeholder ? decl_placeholder
570438fd1498Szrj : OMP_CLAUSE_DECL (c));
570538fd1498Szrj if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
570638fd1498Szrj cxx_mark_addressable (placeholder);
570738fd1498Szrj tree omp_priv = decl_placeholder ? decl_placeholder
570838fd1498Szrj : convert_from_reference (OMP_CLAUSE_DECL (c));
570938fd1498Szrj tree omp_orig = placeholder;
571038fd1498Szrj if (need_static_cast)
571138fd1498Szrj {
571238fd1498Szrj if (i == 7)
571338fd1498Szrj {
571438fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
571538fd1498Szrj "user defined reduction with constructor "
571638fd1498Szrj "initializer for base class %qT", atype);
571738fd1498Szrj return true;
571838fd1498Szrj }
571938fd1498Szrj tree rtype = build_reference_type (atype);
572038fd1498Szrj omp_priv = build_static_cast (rtype, omp_priv,
572138fd1498Szrj tf_warning_or_error);
572238fd1498Szrj omp_orig = build_static_cast (rtype, omp_orig,
572338fd1498Szrj tf_warning_or_error);
572438fd1498Szrj if (omp_priv == error_mark_node
572538fd1498Szrj || omp_orig == error_mark_node)
572638fd1498Szrj return true;
572738fd1498Szrj omp_priv = convert_from_reference (omp_priv);
572838fd1498Szrj omp_orig = convert_from_reference (omp_orig);
572938fd1498Szrj }
573038fd1498Szrj if (i == 6)
573138fd1498Szrj *need_default_ctor = true;
573238fd1498Szrj OMP_CLAUSE_REDUCTION_INIT (c)
573338fd1498Szrj = clone_omp_udr (stmts[5], DECL_EXPR_DECL (stmts[4]),
573438fd1498Szrj DECL_EXPR_DECL (stmts[3]),
573538fd1498Szrj omp_priv, omp_orig);
573638fd1498Szrj if (cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
573738fd1498Szrj find_omp_placeholder_r, placeholder, NULL))
573838fd1498Szrj OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
573938fd1498Szrj }
574038fd1498Szrj else if (i >= 3)
574138fd1498Szrj {
574238fd1498Szrj if (CLASS_TYPE_P (type) && !pod_type_p (type))
574338fd1498Szrj *need_default_ctor = true;
574438fd1498Szrj else
574538fd1498Szrj {
574638fd1498Szrj tree init;
574738fd1498Szrj tree v = decl_placeholder ? decl_placeholder
574838fd1498Szrj : convert_from_reference (t);
574938fd1498Szrj if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
575038fd1498Szrj init = build_constructor (TREE_TYPE (v), NULL);
575138fd1498Szrj else
575238fd1498Szrj init = fold_convert (TREE_TYPE (v), integer_zero_node);
575338fd1498Szrj OMP_CLAUSE_REDUCTION_INIT (c)
575438fd1498Szrj = build2 (INIT_EXPR, TREE_TYPE (v), v, init);
575538fd1498Szrj }
575638fd1498Szrj }
575738fd1498Szrj }
575838fd1498Szrj }
575938fd1498Szrj if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
576038fd1498Szrj *need_dtor = true;
576138fd1498Szrj else
576238fd1498Szrj {
576338fd1498Szrj error ("user defined reduction not found for %qE",
576438fd1498Szrj omp_clause_printable_decl (t));
576538fd1498Szrj return true;
576638fd1498Szrj }
576738fd1498Szrj if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
576838fd1498Szrj gcc_assert (TYPE_SIZE_UNIT (type)
576938fd1498Szrj && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST);
577038fd1498Szrj return false;
577138fd1498Szrj }
577238fd1498Szrj
577338fd1498Szrj /* Called from finish_struct_1. linear(this) or linear(this:step)
577438fd1498Szrj clauses might not be finalized yet because the class has been incomplete
577538fd1498Szrj when parsing #pragma omp declare simd methods. Fix those up now. */
577638fd1498Szrj
577738fd1498Szrj void
finish_omp_declare_simd_methods(tree t)577838fd1498Szrj finish_omp_declare_simd_methods (tree t)
577938fd1498Szrj {
578038fd1498Szrj if (processing_template_decl)
578138fd1498Szrj return;
578238fd1498Szrj
578338fd1498Szrj for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
578438fd1498Szrj {
578538fd1498Szrj if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
578638fd1498Szrj continue;
578738fd1498Szrj tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
578838fd1498Szrj if (!ods || !TREE_VALUE (ods))
578938fd1498Szrj continue;
579038fd1498Szrj for (tree c = TREE_VALUE (TREE_VALUE (ods)); c; c = OMP_CLAUSE_CHAIN (c))
579138fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
579238fd1498Szrj && integer_zerop (OMP_CLAUSE_DECL (c))
579338fd1498Szrj && OMP_CLAUSE_LINEAR_STEP (c)
579438fd1498Szrj && TREE_CODE (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))
579538fd1498Szrj == POINTER_TYPE)
579638fd1498Szrj {
579738fd1498Szrj tree s = OMP_CLAUSE_LINEAR_STEP (c);
579838fd1498Szrj s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s);
579938fd1498Szrj s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MULT_EXPR,
580038fd1498Szrj sizetype, s, TYPE_SIZE_UNIT (t));
580138fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c) = s;
580238fd1498Szrj }
580338fd1498Szrj }
580438fd1498Szrj }
580538fd1498Szrj
580638fd1498Szrj /* Adjust sink depend clause to take into account pointer offsets.
580738fd1498Szrj
580838fd1498Szrj Return TRUE if there was a problem processing the offset, and the
580938fd1498Szrj whole clause should be removed. */
581038fd1498Szrj
581138fd1498Szrj static bool
cp_finish_omp_clause_depend_sink(tree sink_clause)581238fd1498Szrj cp_finish_omp_clause_depend_sink (tree sink_clause)
581338fd1498Szrj {
581438fd1498Szrj tree t = OMP_CLAUSE_DECL (sink_clause);
581538fd1498Szrj gcc_assert (TREE_CODE (t) == TREE_LIST);
581638fd1498Szrj
581738fd1498Szrj /* Make sure we don't adjust things twice for templates. */
581838fd1498Szrj if (processing_template_decl)
581938fd1498Szrj return false;
582038fd1498Szrj
582138fd1498Szrj for (; t; t = TREE_CHAIN (t))
582238fd1498Szrj {
582338fd1498Szrj tree decl = TREE_VALUE (t);
582438fd1498Szrj if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
582538fd1498Szrj {
582638fd1498Szrj tree offset = TREE_PURPOSE (t);
582738fd1498Szrj bool neg = wi::neg_p (wi::to_wide (offset));
582838fd1498Szrj offset = fold_unary (ABS_EXPR, TREE_TYPE (offset), offset);
582938fd1498Szrj decl = mark_rvalue_use (decl);
583038fd1498Szrj decl = convert_from_reference (decl);
583138fd1498Szrj tree t2 = pointer_int_sum (OMP_CLAUSE_LOCATION (sink_clause),
583238fd1498Szrj neg ? MINUS_EXPR : PLUS_EXPR,
583338fd1498Szrj decl, offset);
583438fd1498Szrj t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause),
583538fd1498Szrj MINUS_EXPR, sizetype,
583638fd1498Szrj fold_convert (sizetype, t2),
583738fd1498Szrj fold_convert (sizetype, decl));
583838fd1498Szrj if (t2 == error_mark_node)
583938fd1498Szrj return true;
584038fd1498Szrj TREE_PURPOSE (t) = t2;
584138fd1498Szrj }
584238fd1498Szrj }
584338fd1498Szrj return false;
584438fd1498Szrj }
584538fd1498Szrj
584638fd1498Szrj /* For all elements of CLAUSES, validate them vs OpenMP constraints.
584738fd1498Szrj Remove any elements from the list that are invalid. */
584838fd1498Szrj
584938fd1498Szrj tree
finish_omp_clauses(tree clauses,enum c_omp_region_type ort)585038fd1498Szrj finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
585138fd1498Szrj {
585238fd1498Szrj bitmap_head generic_head, firstprivate_head, lastprivate_head;
585338fd1498Szrj bitmap_head aligned_head, map_head, map_field_head, oacc_reduction_head;
585438fd1498Szrj tree c, t, *pc;
585538fd1498Szrj tree safelen = NULL_TREE;
585638fd1498Szrj bool branch_seen = false;
585738fd1498Szrj bool copyprivate_seen = false;
585838fd1498Szrj bool ordered_seen = false;
585938fd1498Szrj bool oacc_async = false;
586038fd1498Szrj
586138fd1498Szrj bitmap_obstack_initialize (NULL);
586238fd1498Szrj bitmap_initialize (&generic_head, &bitmap_default_obstack);
586338fd1498Szrj bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
586438fd1498Szrj bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
586538fd1498Szrj bitmap_initialize (&aligned_head, &bitmap_default_obstack);
586638fd1498Szrj bitmap_initialize (&map_head, &bitmap_default_obstack);
586738fd1498Szrj bitmap_initialize (&map_field_head, &bitmap_default_obstack);
586838fd1498Szrj bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
586938fd1498Szrj
587038fd1498Szrj if (ort & C_ORT_ACC)
587138fd1498Szrj for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
587238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC)
587338fd1498Szrj {
587438fd1498Szrj oacc_async = true;
587538fd1498Szrj break;
587638fd1498Szrj }
587738fd1498Szrj
587838fd1498Szrj for (pc = &clauses, c = clauses; c ; c = *pc)
587938fd1498Szrj {
588038fd1498Szrj bool remove = false;
588138fd1498Szrj bool field_ok = false;
588238fd1498Szrj
588338fd1498Szrj switch (OMP_CLAUSE_CODE (c))
588438fd1498Szrj {
588538fd1498Szrj case OMP_CLAUSE_SHARED:
588638fd1498Szrj field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
588738fd1498Szrj goto check_dup_generic;
588838fd1498Szrj case OMP_CLAUSE_PRIVATE:
588938fd1498Szrj field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
589038fd1498Szrj goto check_dup_generic;
589138fd1498Szrj case OMP_CLAUSE_REDUCTION:
589238fd1498Szrj field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
589338fd1498Szrj t = OMP_CLAUSE_DECL (c);
589438fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
589538fd1498Szrj {
589638fd1498Szrj if (handle_omp_array_sections (c, ort))
589738fd1498Szrj {
589838fd1498Szrj remove = true;
589938fd1498Szrj break;
590038fd1498Szrj }
590138fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
590238fd1498Szrj {
590338fd1498Szrj while (TREE_CODE (t) == TREE_LIST)
590438fd1498Szrj t = TREE_CHAIN (t);
590538fd1498Szrj }
590638fd1498Szrj else
590738fd1498Szrj {
590838fd1498Szrj gcc_assert (TREE_CODE (t) == MEM_REF);
590938fd1498Szrj t = TREE_OPERAND (t, 0);
591038fd1498Szrj if (TREE_CODE (t) == POINTER_PLUS_EXPR)
591138fd1498Szrj t = TREE_OPERAND (t, 0);
591238fd1498Szrj if (TREE_CODE (t) == ADDR_EXPR
591338fd1498Szrj || INDIRECT_REF_P (t))
591438fd1498Szrj t = TREE_OPERAND (t, 0);
591538fd1498Szrj }
591638fd1498Szrj tree n = omp_clause_decl_field (t);
591738fd1498Szrj if (n)
591838fd1498Szrj t = n;
591938fd1498Szrj goto check_dup_generic_t;
592038fd1498Szrj }
592138fd1498Szrj if (oacc_async)
592238fd1498Szrj cxx_mark_addressable (t);
592338fd1498Szrj goto check_dup_generic;
592438fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
592538fd1498Szrj copyprivate_seen = true;
592638fd1498Szrj field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
592738fd1498Szrj goto check_dup_generic;
592838fd1498Szrj case OMP_CLAUSE_COPYIN:
592938fd1498Szrj goto check_dup_generic;
593038fd1498Szrj case OMP_CLAUSE_LINEAR:
593138fd1498Szrj field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
593238fd1498Szrj t = OMP_CLAUSE_DECL (c);
593338fd1498Szrj if (ort != C_ORT_OMP_DECLARE_SIMD
593438fd1498Szrj && OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_DEFAULT)
593538fd1498Szrj {
593638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
593738fd1498Szrj "modifier should not be specified in %<linear%> "
593838fd1498Szrj "clause on %<simd%> or %<for%> constructs");
593938fd1498Szrj OMP_CLAUSE_LINEAR_KIND (c) = OMP_CLAUSE_LINEAR_DEFAULT;
594038fd1498Szrj }
594138fd1498Szrj if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL)
594238fd1498Szrj && !type_dependent_expression_p (t))
594338fd1498Szrj {
594438fd1498Szrj tree type = TREE_TYPE (t);
594538fd1498Szrj if ((OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
594638fd1498Szrj || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL)
594738fd1498Szrj && TREE_CODE (type) != REFERENCE_TYPE)
594838fd1498Szrj {
594938fd1498Szrj error ("linear clause with %qs modifier applied to "
595038fd1498Szrj "non-reference variable with %qT type",
595138fd1498Szrj OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
595238fd1498Szrj ? "ref" : "uval", TREE_TYPE (t));
595338fd1498Szrj remove = true;
595438fd1498Szrj break;
595538fd1498Szrj }
595638fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
595738fd1498Szrj type = TREE_TYPE (type);
595838fd1498Szrj if (OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_REF)
595938fd1498Szrj {
596038fd1498Szrj if (!INTEGRAL_TYPE_P (type)
596138fd1498Szrj && TREE_CODE (type) != POINTER_TYPE)
596238fd1498Szrj {
596338fd1498Szrj error ("linear clause applied to non-integral non-pointer"
596438fd1498Szrj " variable with %qT type", TREE_TYPE (t));
596538fd1498Szrj remove = true;
596638fd1498Szrj break;
596738fd1498Szrj }
596838fd1498Szrj }
596938fd1498Szrj }
597038fd1498Szrj t = OMP_CLAUSE_LINEAR_STEP (c);
597138fd1498Szrj if (t == NULL_TREE)
597238fd1498Szrj t = integer_one_node;
597338fd1498Szrj if (t == error_mark_node)
597438fd1498Szrj {
597538fd1498Szrj remove = true;
597638fd1498Szrj break;
597738fd1498Szrj }
597838fd1498Szrj else if (!type_dependent_expression_p (t)
597938fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t))
598038fd1498Szrj && (ort != C_ORT_OMP_DECLARE_SIMD
598138fd1498Szrj || TREE_CODE (t) != PARM_DECL
598238fd1498Szrj || TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
598338fd1498Szrj || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (t)))))
598438fd1498Szrj {
598538fd1498Szrj error ("linear step expression must be integral");
598638fd1498Szrj remove = true;
598738fd1498Szrj break;
598838fd1498Szrj }
598938fd1498Szrj else
599038fd1498Szrj {
599138fd1498Szrj t = mark_rvalue_use (t);
599238fd1498Szrj if (ort == C_ORT_OMP_DECLARE_SIMD && TREE_CODE (t) == PARM_DECL)
599338fd1498Szrj {
599438fd1498Szrj OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c) = 1;
599538fd1498Szrj goto check_dup_generic;
599638fd1498Szrj }
599738fd1498Szrj if (!processing_template_decl
599838fd1498Szrj && (VAR_P (OMP_CLAUSE_DECL (c))
599938fd1498Szrj || TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL))
600038fd1498Szrj {
600138fd1498Szrj if (ort == C_ORT_OMP_DECLARE_SIMD)
600238fd1498Szrj {
600338fd1498Szrj t = maybe_constant_value (t);
600438fd1498Szrj if (TREE_CODE (t) != INTEGER_CST)
600538fd1498Szrj {
600638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
600738fd1498Szrj "%<linear%> clause step %qE is neither "
600838fd1498Szrj "constant nor a parameter", t);
600938fd1498Szrj remove = true;
601038fd1498Szrj break;
601138fd1498Szrj }
601238fd1498Szrj }
601338fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
601438fd1498Szrj tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
601538fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
601638fd1498Szrj type = TREE_TYPE (type);
601738fd1498Szrj if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF)
601838fd1498Szrj {
601938fd1498Szrj type = build_pointer_type (type);
602038fd1498Szrj tree d = fold_convert (type, OMP_CLAUSE_DECL (c));
602138fd1498Szrj t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
602238fd1498Szrj d, t);
602338fd1498Szrj t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
602438fd1498Szrj MINUS_EXPR, sizetype,
602538fd1498Szrj fold_convert (sizetype, t),
602638fd1498Szrj fold_convert (sizetype, d));
602738fd1498Szrj if (t == error_mark_node)
602838fd1498Szrj {
602938fd1498Szrj remove = true;
603038fd1498Szrj break;
603138fd1498Szrj }
603238fd1498Szrj }
603338fd1498Szrj else if (TREE_CODE (type) == POINTER_TYPE
603438fd1498Szrj /* Can't multiply the step yet if *this
603538fd1498Szrj is still incomplete type. */
603638fd1498Szrj && (ort != C_ORT_OMP_DECLARE_SIMD
603738fd1498Szrj || TREE_CODE (OMP_CLAUSE_DECL (c)) != PARM_DECL
603838fd1498Szrj || !DECL_ARTIFICIAL (OMP_CLAUSE_DECL (c))
603938fd1498Szrj || DECL_NAME (OMP_CLAUSE_DECL (c))
604038fd1498Szrj != this_identifier
604138fd1498Szrj || !TYPE_BEING_DEFINED (TREE_TYPE (type))))
604238fd1498Szrj {
604338fd1498Szrj tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
604438fd1498Szrj t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
604538fd1498Szrj d, t);
604638fd1498Szrj t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
604738fd1498Szrj MINUS_EXPR, sizetype,
604838fd1498Szrj fold_convert (sizetype, t),
604938fd1498Szrj fold_convert (sizetype, d));
605038fd1498Szrj if (t == error_mark_node)
605138fd1498Szrj {
605238fd1498Szrj remove = true;
605338fd1498Szrj break;
605438fd1498Szrj }
605538fd1498Szrj }
605638fd1498Szrj else
605738fd1498Szrj t = fold_convert (type, t);
605838fd1498Szrj }
605938fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c) = t;
606038fd1498Szrj }
606138fd1498Szrj goto check_dup_generic;
606238fd1498Szrj check_dup_generic:
606338fd1498Szrj t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
606438fd1498Szrj if (t)
606538fd1498Szrj {
606638fd1498Szrj if (!remove && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED)
606738fd1498Szrj omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
606838fd1498Szrj }
606938fd1498Szrj else
607038fd1498Szrj t = OMP_CLAUSE_DECL (c);
607138fd1498Szrj check_dup_generic_t:
607238fd1498Szrj if (t == current_class_ptr
607338fd1498Szrj && (ort != C_ORT_OMP_DECLARE_SIMD
607438fd1498Szrj || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
607538fd1498Szrj && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
607638fd1498Szrj {
607738fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
607838fd1498Szrj " clauses");
607938fd1498Szrj remove = true;
608038fd1498Szrj break;
608138fd1498Szrj }
608238fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
608338fd1498Szrj && (!field_ok || TREE_CODE (t) != FIELD_DECL))
608438fd1498Szrj {
608538fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
608638fd1498Szrj break;
608738fd1498Szrj if (DECL_P (t))
608838fd1498Szrj error ("%qD is not a variable in clause %qs", t,
608938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
609038fd1498Szrj else
609138fd1498Szrj error ("%qE is not a variable in clause %qs", t,
609238fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
609338fd1498Szrj remove = true;
609438fd1498Szrj }
609538fd1498Szrj else if (ort == C_ORT_ACC
609638fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
609738fd1498Szrj {
609838fd1498Szrj if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
609938fd1498Szrj {
610038fd1498Szrj error ("%qD appears more than once in reduction clauses", t);
610138fd1498Szrj remove = true;
610238fd1498Szrj }
610338fd1498Szrj else
610438fd1498Szrj bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
610538fd1498Szrj }
610638fd1498Szrj else if (bitmap_bit_p (&generic_head, DECL_UID (t))
610738fd1498Szrj || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
610838fd1498Szrj || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
610938fd1498Szrj {
611038fd1498Szrj error ("%qD appears more than once in data clauses", t);
611138fd1498Szrj remove = true;
611238fd1498Szrj }
611338fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
611438fd1498Szrj && bitmap_bit_p (&map_head, DECL_UID (t)))
611538fd1498Szrj {
611638fd1498Szrj if (ort == C_ORT_ACC)
611738fd1498Szrj error ("%qD appears more than once in data clauses", t);
611838fd1498Szrj else
611938fd1498Szrj error ("%qD appears both in data and map clauses", t);
612038fd1498Szrj remove = true;
612138fd1498Szrj }
612238fd1498Szrj else
612338fd1498Szrj bitmap_set_bit (&generic_head, DECL_UID (t));
612438fd1498Szrj if (!field_ok)
612538fd1498Szrj break;
612638fd1498Szrj handle_field_decl:
612738fd1498Szrj if (!remove
612838fd1498Szrj && TREE_CODE (t) == FIELD_DECL
612938fd1498Szrj && t == OMP_CLAUSE_DECL (c)
613038fd1498Szrj && ort != C_ORT_ACC)
613138fd1498Szrj {
613238fd1498Szrj OMP_CLAUSE_DECL (c)
613338fd1498Szrj = omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
613438fd1498Szrj == OMP_CLAUSE_SHARED));
613538fd1498Szrj if (OMP_CLAUSE_DECL (c) == error_mark_node)
613638fd1498Szrj remove = true;
613738fd1498Szrj }
613838fd1498Szrj break;
613938fd1498Szrj
614038fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
614138fd1498Szrj t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
614238fd1498Szrj if (t)
614338fd1498Szrj omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
614438fd1498Szrj else
614538fd1498Szrj t = OMP_CLAUSE_DECL (c);
614638fd1498Szrj if (ort != C_ORT_ACC && t == current_class_ptr)
614738fd1498Szrj {
614838fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
614938fd1498Szrj " clauses");
615038fd1498Szrj remove = true;
615138fd1498Szrj break;
615238fd1498Szrj }
615338fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
615438fd1498Szrj && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP
615538fd1498Szrj || TREE_CODE (t) != FIELD_DECL))
615638fd1498Szrj {
615738fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
615838fd1498Szrj break;
615938fd1498Szrj if (DECL_P (t))
616038fd1498Szrj error ("%qD is not a variable in clause %<firstprivate%>", t);
616138fd1498Szrj else
616238fd1498Szrj error ("%qE is not a variable in clause %<firstprivate%>", t);
616338fd1498Szrj remove = true;
616438fd1498Szrj }
616538fd1498Szrj else if (bitmap_bit_p (&generic_head, DECL_UID (t))
616638fd1498Szrj || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
616738fd1498Szrj {
616838fd1498Szrj error ("%qD appears more than once in data clauses", t);
616938fd1498Szrj remove = true;
617038fd1498Szrj }
617138fd1498Szrj else if (bitmap_bit_p (&map_head, DECL_UID (t)))
617238fd1498Szrj {
617338fd1498Szrj if (ort == C_ORT_ACC)
617438fd1498Szrj error ("%qD appears more than once in data clauses", t);
617538fd1498Szrj else
617638fd1498Szrj error ("%qD appears both in data and map clauses", t);
617738fd1498Szrj remove = true;
617838fd1498Szrj }
617938fd1498Szrj else
618038fd1498Szrj bitmap_set_bit (&firstprivate_head, DECL_UID (t));
618138fd1498Szrj goto handle_field_decl;
618238fd1498Szrj
618338fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
618438fd1498Szrj t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
618538fd1498Szrj if (t)
618638fd1498Szrj omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
618738fd1498Szrj else
618838fd1498Szrj t = OMP_CLAUSE_DECL (c);
618938fd1498Szrj if (t == current_class_ptr)
619038fd1498Szrj {
619138fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
619238fd1498Szrj " clauses");
619338fd1498Szrj remove = true;
619438fd1498Szrj break;
619538fd1498Szrj }
619638fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
619738fd1498Szrj && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP
619838fd1498Szrj || TREE_CODE (t) != FIELD_DECL))
619938fd1498Szrj {
620038fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
620138fd1498Szrj break;
620238fd1498Szrj if (DECL_P (t))
620338fd1498Szrj error ("%qD is not a variable in clause %<lastprivate%>", t);
620438fd1498Szrj else
620538fd1498Szrj error ("%qE is not a variable in clause %<lastprivate%>", t);
620638fd1498Szrj remove = true;
620738fd1498Szrj }
620838fd1498Szrj else if (bitmap_bit_p (&generic_head, DECL_UID (t))
620938fd1498Szrj || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
621038fd1498Szrj {
621138fd1498Szrj error ("%qD appears more than once in data clauses", t);
621238fd1498Szrj remove = true;
621338fd1498Szrj }
621438fd1498Szrj else
621538fd1498Szrj bitmap_set_bit (&lastprivate_head, DECL_UID (t));
621638fd1498Szrj goto handle_field_decl;
621738fd1498Szrj
621838fd1498Szrj case OMP_CLAUSE_IF:
621938fd1498Szrj t = OMP_CLAUSE_IF_EXPR (c);
622038fd1498Szrj t = maybe_convert_cond (t);
622138fd1498Szrj if (t == error_mark_node)
622238fd1498Szrj remove = true;
622338fd1498Szrj else if (!processing_template_decl)
622438fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
622538fd1498Szrj OMP_CLAUSE_IF_EXPR (c) = t;
622638fd1498Szrj break;
622738fd1498Szrj
622838fd1498Szrj case OMP_CLAUSE_FINAL:
622938fd1498Szrj t = OMP_CLAUSE_FINAL_EXPR (c);
623038fd1498Szrj t = maybe_convert_cond (t);
623138fd1498Szrj if (t == error_mark_node)
623238fd1498Szrj remove = true;
623338fd1498Szrj else if (!processing_template_decl)
623438fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
623538fd1498Szrj OMP_CLAUSE_FINAL_EXPR (c) = t;
623638fd1498Szrj break;
623738fd1498Szrj
623838fd1498Szrj case OMP_CLAUSE_GANG:
623938fd1498Szrj /* Operand 1 is the gang static: argument. */
624038fd1498Szrj t = OMP_CLAUSE_OPERAND (c, 1);
624138fd1498Szrj if (t != NULL_TREE)
624238fd1498Szrj {
624338fd1498Szrj if (t == error_mark_node)
624438fd1498Szrj remove = true;
624538fd1498Szrj else if (!type_dependent_expression_p (t)
624638fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
624738fd1498Szrj {
624838fd1498Szrj error ("%<gang%> static expression must be integral");
624938fd1498Szrj remove = true;
625038fd1498Szrj }
625138fd1498Szrj else
625238fd1498Szrj {
625338fd1498Szrj t = mark_rvalue_use (t);
625438fd1498Szrj if (!processing_template_decl)
625538fd1498Szrj {
625638fd1498Szrj t = maybe_constant_value (t);
625738fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
625838fd1498Szrj && tree_int_cst_sgn (t) != 1
625938fd1498Szrj && t != integer_minus_one_node)
626038fd1498Szrj {
626138fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
626238fd1498Szrj "%<gang%> static value must be "
626338fd1498Szrj "positive");
626438fd1498Szrj t = integer_one_node;
626538fd1498Szrj }
626638fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
626738fd1498Szrj }
626838fd1498Szrj }
626938fd1498Szrj OMP_CLAUSE_OPERAND (c, 1) = t;
627038fd1498Szrj }
627138fd1498Szrj /* Check operand 0, the num argument. */
627238fd1498Szrj /* FALLTHRU */
627338fd1498Szrj
627438fd1498Szrj case OMP_CLAUSE_WORKER:
627538fd1498Szrj case OMP_CLAUSE_VECTOR:
627638fd1498Szrj if (OMP_CLAUSE_OPERAND (c, 0) == NULL_TREE)
627738fd1498Szrj break;
627838fd1498Szrj /* FALLTHRU */
627938fd1498Szrj
628038fd1498Szrj case OMP_CLAUSE_NUM_TASKS:
628138fd1498Szrj case OMP_CLAUSE_NUM_TEAMS:
628238fd1498Szrj case OMP_CLAUSE_NUM_THREADS:
628338fd1498Szrj case OMP_CLAUSE_NUM_GANGS:
628438fd1498Szrj case OMP_CLAUSE_NUM_WORKERS:
628538fd1498Szrj case OMP_CLAUSE_VECTOR_LENGTH:
628638fd1498Szrj t = OMP_CLAUSE_OPERAND (c, 0);
628738fd1498Szrj if (t == error_mark_node)
628838fd1498Szrj remove = true;
628938fd1498Szrj else if (!type_dependent_expression_p (t)
629038fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
629138fd1498Szrj {
629238fd1498Szrj switch (OMP_CLAUSE_CODE (c))
629338fd1498Szrj {
629438fd1498Szrj case OMP_CLAUSE_GANG:
629538fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
629638fd1498Szrj "%<gang%> num expression must be integral"); break;
629738fd1498Szrj case OMP_CLAUSE_VECTOR:
629838fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
629938fd1498Szrj "%<vector%> length expression must be integral");
630038fd1498Szrj break;
630138fd1498Szrj case OMP_CLAUSE_WORKER:
630238fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
630338fd1498Szrj "%<worker%> num expression must be integral");
630438fd1498Szrj break;
630538fd1498Szrj default:
630638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
630738fd1498Szrj "%qs expression must be integral",
630838fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
630938fd1498Szrj }
631038fd1498Szrj remove = true;
631138fd1498Szrj }
631238fd1498Szrj else
631338fd1498Szrj {
631438fd1498Szrj t = mark_rvalue_use (t);
631538fd1498Szrj if (!processing_template_decl)
631638fd1498Szrj {
631738fd1498Szrj t = maybe_constant_value (t);
631838fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
631938fd1498Szrj && tree_int_cst_sgn (t) != 1)
632038fd1498Szrj {
632138fd1498Szrj switch (OMP_CLAUSE_CODE (c))
632238fd1498Szrj {
632338fd1498Szrj case OMP_CLAUSE_GANG:
632438fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
632538fd1498Szrj "%<gang%> num value must be positive");
632638fd1498Szrj break;
632738fd1498Szrj case OMP_CLAUSE_VECTOR:
632838fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
632938fd1498Szrj "%<vector%> length value must be "
633038fd1498Szrj "positive");
633138fd1498Szrj break;
633238fd1498Szrj case OMP_CLAUSE_WORKER:
633338fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
633438fd1498Szrj "%<worker%> num value must be "
633538fd1498Szrj "positive");
633638fd1498Szrj break;
633738fd1498Szrj default:
633838fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
633938fd1498Szrj "%qs value must be positive",
634038fd1498Szrj omp_clause_code_name
634138fd1498Szrj [OMP_CLAUSE_CODE (c)]);
634238fd1498Szrj }
634338fd1498Szrj t = integer_one_node;
634438fd1498Szrj }
634538fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
634638fd1498Szrj }
634738fd1498Szrj OMP_CLAUSE_OPERAND (c, 0) = t;
634838fd1498Szrj }
634938fd1498Szrj break;
635038fd1498Szrj
635138fd1498Szrj case OMP_CLAUSE_SCHEDULE:
635238fd1498Szrj if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
635338fd1498Szrj {
635438fd1498Szrj const char *p = NULL;
635538fd1498Szrj switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
635638fd1498Szrj {
635738fd1498Szrj case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break;
635838fd1498Szrj case OMP_CLAUSE_SCHEDULE_DYNAMIC: break;
635938fd1498Szrj case OMP_CLAUSE_SCHEDULE_GUIDED: break;
636038fd1498Szrj case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break;
636138fd1498Szrj case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break;
636238fd1498Szrj default: gcc_unreachable ();
636338fd1498Szrj }
636438fd1498Szrj if (p)
636538fd1498Szrj {
636638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
636738fd1498Szrj "%<nonmonotonic%> modifier specified for %qs "
636838fd1498Szrj "schedule kind", p);
636938fd1498Szrj OMP_CLAUSE_SCHEDULE_KIND (c)
637038fd1498Szrj = (enum omp_clause_schedule_kind)
637138fd1498Szrj (OMP_CLAUSE_SCHEDULE_KIND (c)
637238fd1498Szrj & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
637338fd1498Szrj }
637438fd1498Szrj }
637538fd1498Szrj
637638fd1498Szrj t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
637738fd1498Szrj if (t == NULL)
637838fd1498Szrj ;
637938fd1498Szrj else if (t == error_mark_node)
638038fd1498Szrj remove = true;
638138fd1498Szrj else if (!type_dependent_expression_p (t)
638238fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
638338fd1498Szrj {
638438fd1498Szrj error ("schedule chunk size expression must be integral");
638538fd1498Szrj remove = true;
638638fd1498Szrj }
638738fd1498Szrj else
638838fd1498Szrj {
638938fd1498Szrj t = mark_rvalue_use (t);
639038fd1498Szrj if (!processing_template_decl)
639138fd1498Szrj {
639238fd1498Szrj t = maybe_constant_value (t);
639338fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
639438fd1498Szrj && tree_int_cst_sgn (t) != 1)
639538fd1498Szrj {
639638fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
639738fd1498Szrj "chunk size value must be positive");
639838fd1498Szrj t = integer_one_node;
639938fd1498Szrj }
640038fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
640138fd1498Szrj }
640238fd1498Szrj OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
640338fd1498Szrj }
640438fd1498Szrj break;
640538fd1498Szrj
640638fd1498Szrj case OMP_CLAUSE_SIMDLEN:
640738fd1498Szrj case OMP_CLAUSE_SAFELEN:
640838fd1498Szrj t = OMP_CLAUSE_OPERAND (c, 0);
640938fd1498Szrj if (t == error_mark_node)
641038fd1498Szrj remove = true;
641138fd1498Szrj else if (!type_dependent_expression_p (t)
641238fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
641338fd1498Szrj {
641438fd1498Szrj error ("%qs length expression must be integral",
641538fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
641638fd1498Szrj remove = true;
641738fd1498Szrj }
641838fd1498Szrj else
641938fd1498Szrj {
642038fd1498Szrj t = mark_rvalue_use (t);
642138fd1498Szrj if (!processing_template_decl)
642238fd1498Szrj {
642338fd1498Szrj t = maybe_constant_value (t);
642438fd1498Szrj if (TREE_CODE (t) != INTEGER_CST
642538fd1498Szrj || tree_int_cst_sgn (t) != 1)
642638fd1498Szrj {
642738fd1498Szrj error ("%qs length expression must be positive constant"
642838fd1498Szrj " integer expression",
642938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
643038fd1498Szrj remove = true;
643138fd1498Szrj }
643238fd1498Szrj }
643338fd1498Szrj OMP_CLAUSE_OPERAND (c, 0) = t;
643438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SAFELEN)
643538fd1498Szrj safelen = c;
643638fd1498Szrj }
643738fd1498Szrj break;
643838fd1498Szrj
643938fd1498Szrj case OMP_CLAUSE_ASYNC:
644038fd1498Szrj t = OMP_CLAUSE_ASYNC_EXPR (c);
644138fd1498Szrj if (t == error_mark_node)
644238fd1498Szrj remove = true;
644338fd1498Szrj else if (!type_dependent_expression_p (t)
644438fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
644538fd1498Szrj {
644638fd1498Szrj error ("%<async%> expression must be integral");
644738fd1498Szrj remove = true;
644838fd1498Szrj }
644938fd1498Szrj else
645038fd1498Szrj {
645138fd1498Szrj t = mark_rvalue_use (t);
645238fd1498Szrj if (!processing_template_decl)
645338fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
645438fd1498Szrj OMP_CLAUSE_ASYNC_EXPR (c) = t;
645538fd1498Szrj }
645638fd1498Szrj break;
645738fd1498Szrj
645838fd1498Szrj case OMP_CLAUSE_WAIT:
645938fd1498Szrj t = OMP_CLAUSE_WAIT_EXPR (c);
646038fd1498Szrj if (t == error_mark_node)
646138fd1498Szrj remove = true;
646238fd1498Szrj else if (!processing_template_decl)
646338fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
646438fd1498Szrj OMP_CLAUSE_WAIT_EXPR (c) = t;
646538fd1498Szrj break;
646638fd1498Szrj
646738fd1498Szrj case OMP_CLAUSE_THREAD_LIMIT:
646838fd1498Szrj t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
646938fd1498Szrj if (t == error_mark_node)
647038fd1498Szrj remove = true;
647138fd1498Szrj else if (!type_dependent_expression_p (t)
647238fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
647338fd1498Szrj {
647438fd1498Szrj error ("%<thread_limit%> expression must be integral");
647538fd1498Szrj remove = true;
647638fd1498Szrj }
647738fd1498Szrj else
647838fd1498Szrj {
647938fd1498Szrj t = mark_rvalue_use (t);
648038fd1498Szrj if (!processing_template_decl)
648138fd1498Szrj {
648238fd1498Szrj t = maybe_constant_value (t);
648338fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
648438fd1498Szrj && tree_int_cst_sgn (t) != 1)
648538fd1498Szrj {
648638fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
648738fd1498Szrj "%<thread_limit%> value must be positive");
648838fd1498Szrj t = integer_one_node;
648938fd1498Szrj }
649038fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
649138fd1498Szrj }
649238fd1498Szrj OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
649338fd1498Szrj }
649438fd1498Szrj break;
649538fd1498Szrj
649638fd1498Szrj case OMP_CLAUSE_DEVICE:
649738fd1498Szrj t = OMP_CLAUSE_DEVICE_ID (c);
649838fd1498Szrj if (t == error_mark_node)
649938fd1498Szrj remove = true;
650038fd1498Szrj else if (!type_dependent_expression_p (t)
650138fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
650238fd1498Szrj {
650338fd1498Szrj error ("%<device%> id must be integral");
650438fd1498Szrj remove = true;
650538fd1498Szrj }
650638fd1498Szrj else
650738fd1498Szrj {
650838fd1498Szrj t = mark_rvalue_use (t);
650938fd1498Szrj if (!processing_template_decl)
651038fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
651138fd1498Szrj OMP_CLAUSE_DEVICE_ID (c) = t;
651238fd1498Szrj }
651338fd1498Szrj break;
651438fd1498Szrj
651538fd1498Szrj case OMP_CLAUSE_DIST_SCHEDULE:
651638fd1498Szrj t = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c);
651738fd1498Szrj if (t == NULL)
651838fd1498Szrj ;
651938fd1498Szrj else if (t == error_mark_node)
652038fd1498Szrj remove = true;
652138fd1498Szrj else if (!type_dependent_expression_p (t)
652238fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
652338fd1498Szrj {
652438fd1498Szrj error ("%<dist_schedule%> chunk size expression must be "
652538fd1498Szrj "integral");
652638fd1498Szrj remove = true;
652738fd1498Szrj }
652838fd1498Szrj else
652938fd1498Szrj {
653038fd1498Szrj t = mark_rvalue_use (t);
653138fd1498Szrj if (!processing_template_decl)
653238fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
653338fd1498Szrj OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
653438fd1498Szrj }
653538fd1498Szrj break;
653638fd1498Szrj
653738fd1498Szrj case OMP_CLAUSE_ALIGNED:
653838fd1498Szrj t = OMP_CLAUSE_DECL (c);
653938fd1498Szrj if (t == current_class_ptr && ort != C_ORT_OMP_DECLARE_SIMD)
654038fd1498Szrj {
654138fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
654238fd1498Szrj " clauses");
654338fd1498Szrj remove = true;
654438fd1498Szrj break;
654538fd1498Szrj }
654638fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
654738fd1498Szrj {
654838fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
654938fd1498Szrj break;
655038fd1498Szrj if (DECL_P (t))
655138fd1498Szrj error ("%qD is not a variable in %<aligned%> clause", t);
655238fd1498Szrj else
655338fd1498Szrj error ("%qE is not a variable in %<aligned%> clause", t);
655438fd1498Szrj remove = true;
655538fd1498Szrj }
655638fd1498Szrj else if (!type_dependent_expression_p (t)
655738fd1498Szrj && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
655838fd1498Szrj && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE
655938fd1498Szrj && (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
656038fd1498Szrj || (!POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t)))
656138fd1498Szrj && (TREE_CODE (TREE_TYPE (TREE_TYPE (t)))
656238fd1498Szrj != ARRAY_TYPE))))
656338fd1498Szrj {
656438fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
656538fd1498Szrj "%qE in %<aligned%> clause is neither a pointer nor "
656638fd1498Szrj "an array nor a reference to pointer or array", t);
656738fd1498Szrj remove = true;
656838fd1498Szrj }
656938fd1498Szrj else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
657038fd1498Szrj {
657138fd1498Szrj error ("%qD appears more than once in %<aligned%> clauses", t);
657238fd1498Szrj remove = true;
657338fd1498Szrj }
657438fd1498Szrj else
657538fd1498Szrj bitmap_set_bit (&aligned_head, DECL_UID (t));
657638fd1498Szrj t = OMP_CLAUSE_ALIGNED_ALIGNMENT (c);
657738fd1498Szrj if (t == error_mark_node)
657838fd1498Szrj remove = true;
657938fd1498Szrj else if (t == NULL_TREE)
658038fd1498Szrj break;
658138fd1498Szrj else if (!type_dependent_expression_p (t)
658238fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
658338fd1498Szrj {
658438fd1498Szrj error ("%<aligned%> clause alignment expression must "
658538fd1498Szrj "be integral");
658638fd1498Szrj remove = true;
658738fd1498Szrj }
658838fd1498Szrj else
658938fd1498Szrj {
659038fd1498Szrj t = mark_rvalue_use (t);
659138fd1498Szrj if (!processing_template_decl)
659238fd1498Szrj {
659338fd1498Szrj t = maybe_constant_value (t);
659438fd1498Szrj if (TREE_CODE (t) != INTEGER_CST
659538fd1498Szrj || tree_int_cst_sgn (t) != 1)
659638fd1498Szrj {
659738fd1498Szrj error ("%<aligned%> clause alignment expression must be "
659838fd1498Szrj "positive constant integer expression");
659938fd1498Szrj remove = true;
660038fd1498Szrj }
660138fd1498Szrj }
660238fd1498Szrj OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
660338fd1498Szrj }
660438fd1498Szrj break;
660538fd1498Szrj
660638fd1498Szrj case OMP_CLAUSE_DEPEND:
660738fd1498Szrj t = OMP_CLAUSE_DECL (c);
660838fd1498Szrj if (t == NULL_TREE)
660938fd1498Szrj {
661038fd1498Szrj gcc_assert (OMP_CLAUSE_DEPEND_KIND (c)
661138fd1498Szrj == OMP_CLAUSE_DEPEND_SOURCE);
661238fd1498Szrj break;
661338fd1498Szrj }
661438fd1498Szrj if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
661538fd1498Szrj {
661638fd1498Szrj if (cp_finish_omp_clause_depend_sink (c))
661738fd1498Szrj remove = true;
661838fd1498Szrj break;
661938fd1498Szrj }
662038fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
662138fd1498Szrj {
662238fd1498Szrj if (handle_omp_array_sections (c, ort))
662338fd1498Szrj remove = true;
662438fd1498Szrj break;
662538fd1498Szrj }
662638fd1498Szrj if (t == error_mark_node)
662738fd1498Szrj remove = true;
662838fd1498Szrj else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
662938fd1498Szrj {
663038fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
663138fd1498Szrj break;
663238fd1498Szrj if (DECL_P (t))
663338fd1498Szrj error ("%qD is not a variable in %<depend%> clause", t);
663438fd1498Szrj else
663538fd1498Szrj error ("%qE is not a variable in %<depend%> clause", t);
663638fd1498Szrj remove = true;
663738fd1498Szrj }
663838fd1498Szrj else if (t == current_class_ptr)
663938fd1498Szrj {
664038fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
664138fd1498Szrj " clauses");
664238fd1498Szrj remove = true;
664338fd1498Szrj }
664438fd1498Szrj else if (!processing_template_decl
664538fd1498Szrj && !cxx_mark_addressable (t))
664638fd1498Szrj remove = true;
664738fd1498Szrj break;
664838fd1498Szrj
664938fd1498Szrj case OMP_CLAUSE_MAP:
665038fd1498Szrj case OMP_CLAUSE_TO:
665138fd1498Szrj case OMP_CLAUSE_FROM:
665238fd1498Szrj case OMP_CLAUSE__CACHE_:
665338fd1498Szrj t = OMP_CLAUSE_DECL (c);
665438fd1498Szrj if (TREE_CODE (t) == TREE_LIST)
665538fd1498Szrj {
665638fd1498Szrj if (handle_omp_array_sections (c, ort))
665738fd1498Szrj remove = true;
665838fd1498Szrj else
665938fd1498Szrj {
666038fd1498Szrj t = OMP_CLAUSE_DECL (c);
666138fd1498Szrj if (TREE_CODE (t) != TREE_LIST
666238fd1498Szrj && !type_dependent_expression_p (t)
666338fd1498Szrj && !cp_omp_mappable_type (TREE_TYPE (t)))
666438fd1498Szrj {
666538fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
666638fd1498Szrj "array section does not have mappable type "
666738fd1498Szrj "in %qs clause",
666838fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
666938fd1498Szrj remove = true;
667038fd1498Szrj }
667138fd1498Szrj while (TREE_CODE (t) == ARRAY_REF)
667238fd1498Szrj t = TREE_OPERAND (t, 0);
667338fd1498Szrj if (TREE_CODE (t) == COMPONENT_REF
667438fd1498Szrj && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
667538fd1498Szrj {
667638fd1498Szrj while (TREE_CODE (t) == COMPONENT_REF)
667738fd1498Szrj t = TREE_OPERAND (t, 0);
667838fd1498Szrj if (REFERENCE_REF_P (t))
667938fd1498Szrj t = TREE_OPERAND (t, 0);
668038fd1498Szrj if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
668138fd1498Szrj break;
668238fd1498Szrj if (bitmap_bit_p (&map_head, DECL_UID (t)))
668338fd1498Szrj {
668438fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
668538fd1498Szrj error ("%qD appears more than once in motion"
668638fd1498Szrj " clauses", t);
668738fd1498Szrj else if (ort == C_ORT_ACC)
668838fd1498Szrj error ("%qD appears more than once in data"
668938fd1498Szrj " clauses", t);
669038fd1498Szrj else
669138fd1498Szrj error ("%qD appears more than once in map"
669238fd1498Szrj " clauses", t);
669338fd1498Szrj remove = true;
669438fd1498Szrj }
669538fd1498Szrj else
669638fd1498Szrj {
669738fd1498Szrj bitmap_set_bit (&map_head, DECL_UID (t));
669838fd1498Szrj bitmap_set_bit (&map_field_head, DECL_UID (t));
669938fd1498Szrj }
670038fd1498Szrj }
670138fd1498Szrj }
670238fd1498Szrj break;
670338fd1498Szrj }
670438fd1498Szrj if (t == error_mark_node)
670538fd1498Szrj {
670638fd1498Szrj remove = true;
670738fd1498Szrj break;
670838fd1498Szrj }
670938fd1498Szrj if (REFERENCE_REF_P (t)
671038fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
671138fd1498Szrj {
671238fd1498Szrj t = TREE_OPERAND (t, 0);
671338fd1498Szrj OMP_CLAUSE_DECL (c) = t;
671438fd1498Szrj }
671538fd1498Szrj if (TREE_CODE (t) == COMPONENT_REF
671638fd1498Szrj && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
671738fd1498Szrj && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
671838fd1498Szrj {
671938fd1498Szrj if (type_dependent_expression_p (t))
672038fd1498Szrj break;
672138fd1498Szrj if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
672238fd1498Szrj && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
672338fd1498Szrj {
672438fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
672538fd1498Szrj "bit-field %qE in %qs clause",
672638fd1498Szrj t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
672738fd1498Szrj remove = true;
672838fd1498Szrj }
672938fd1498Szrj else if (!cp_omp_mappable_type (TREE_TYPE (t)))
673038fd1498Szrj {
673138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
673238fd1498Szrj "%qE does not have a mappable type in %qs clause",
673338fd1498Szrj t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
673438fd1498Szrj remove = true;
673538fd1498Szrj }
673638fd1498Szrj while (TREE_CODE (t) == COMPONENT_REF)
673738fd1498Szrj {
673838fd1498Szrj if (TREE_TYPE (TREE_OPERAND (t, 0))
673938fd1498Szrj && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
674038fd1498Szrj == UNION_TYPE))
674138fd1498Szrj {
674238fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
674338fd1498Szrj "%qE is a member of a union", t);
674438fd1498Szrj remove = true;
674538fd1498Szrj break;
674638fd1498Szrj }
674738fd1498Szrj t = TREE_OPERAND (t, 0);
674838fd1498Szrj }
674938fd1498Szrj if (remove)
675038fd1498Szrj break;
675138fd1498Szrj if (REFERENCE_REF_P (t))
675238fd1498Szrj t = TREE_OPERAND (t, 0);
675338fd1498Szrj if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
675438fd1498Szrj {
675538fd1498Szrj if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
675638fd1498Szrj goto handle_map_references;
675738fd1498Szrj }
675838fd1498Szrj }
675938fd1498Szrj if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
676038fd1498Szrj {
676138fd1498Szrj if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
676238fd1498Szrj break;
676338fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
676438fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
676538fd1498Szrj || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
676638fd1498Szrj break;
676738fd1498Szrj if (DECL_P (t))
676838fd1498Szrj error ("%qD is not a variable in %qs clause", t,
676938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
677038fd1498Szrj else
677138fd1498Szrj error ("%qE is not a variable in %qs clause", t,
677238fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
677338fd1498Szrj remove = true;
677438fd1498Szrj }
677538fd1498Szrj else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
677638fd1498Szrj {
677738fd1498Szrj error ("%qD is threadprivate variable in %qs clause", t,
677838fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
677938fd1498Szrj remove = true;
678038fd1498Szrj }
678138fd1498Szrj else if (ort != C_ORT_ACC && t == current_class_ptr)
678238fd1498Szrj {
678338fd1498Szrj error ("%<this%> allowed in OpenMP only in %<declare simd%>"
678438fd1498Szrj " clauses");
678538fd1498Szrj remove = true;
678638fd1498Szrj break;
678738fd1498Szrj }
678838fd1498Szrj else if (!processing_template_decl
678938fd1498Szrj && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
679038fd1498Szrj && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
679138fd1498Szrj || (OMP_CLAUSE_MAP_KIND (c)
679238fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_POINTER))
679338fd1498Szrj && !cxx_mark_addressable (t))
679438fd1498Szrj remove = true;
679538fd1498Szrj else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
679638fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
679738fd1498Szrj || (OMP_CLAUSE_MAP_KIND (c)
679838fd1498Szrj == GOMP_MAP_FIRSTPRIVATE_POINTER)))
679938fd1498Szrj && t == OMP_CLAUSE_DECL (c)
680038fd1498Szrj && !type_dependent_expression_p (t)
680138fd1498Szrj && !cp_omp_mappable_type ((TREE_CODE (TREE_TYPE (t))
680238fd1498Szrj == REFERENCE_TYPE)
680338fd1498Szrj ? TREE_TYPE (TREE_TYPE (t))
680438fd1498Szrj : TREE_TYPE (t)))
680538fd1498Szrj {
680638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
680738fd1498Szrj "%qD does not have a mappable type in %qs clause", t,
680838fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
680938fd1498Szrj remove = true;
681038fd1498Szrj }
681138fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
681238fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR
681338fd1498Szrj && !type_dependent_expression_p (t)
681438fd1498Szrj && !POINTER_TYPE_P (TREE_TYPE (t)))
681538fd1498Szrj {
681638fd1498Szrj error ("%qD is not a pointer variable", t);
681738fd1498Szrj remove = true;
681838fd1498Szrj }
681938fd1498Szrj else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
682038fd1498Szrj && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
682138fd1498Szrj {
682238fd1498Szrj if (bitmap_bit_p (&generic_head, DECL_UID (t))
682338fd1498Szrj || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
682438fd1498Szrj {
682538fd1498Szrj error ("%qD appears more than once in data clauses", t);
682638fd1498Szrj remove = true;
682738fd1498Szrj }
682838fd1498Szrj else if (bitmap_bit_p (&map_head, DECL_UID (t)))
682938fd1498Szrj {
683038fd1498Szrj if (ort == C_ORT_ACC)
683138fd1498Szrj error ("%qD appears more than once in data clauses", t);
683238fd1498Szrj else
683338fd1498Szrj error ("%qD appears both in data and map clauses", t);
683438fd1498Szrj remove = true;
683538fd1498Szrj }
683638fd1498Szrj else
683738fd1498Szrj bitmap_set_bit (&generic_head, DECL_UID (t));
683838fd1498Szrj }
683938fd1498Szrj else if (bitmap_bit_p (&map_head, DECL_UID (t)))
684038fd1498Szrj {
684138fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
684238fd1498Szrj error ("%qD appears more than once in motion clauses", t);
684338fd1498Szrj if (ort == C_ORT_ACC)
684438fd1498Szrj error ("%qD appears more than once in data clauses", t);
684538fd1498Szrj else
684638fd1498Szrj error ("%qD appears more than once in map clauses", t);
684738fd1498Szrj remove = true;
684838fd1498Szrj }
684938fd1498Szrj else if (bitmap_bit_p (&generic_head, DECL_UID (t))
685038fd1498Szrj || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
685138fd1498Szrj {
685238fd1498Szrj if (ort == C_ORT_ACC)
685338fd1498Szrj error ("%qD appears more than once in data clauses", t);
685438fd1498Szrj else
685538fd1498Szrj error ("%qD appears both in data and map clauses", t);
685638fd1498Szrj remove = true;
685738fd1498Szrj }
685838fd1498Szrj else
685938fd1498Szrj {
686038fd1498Szrj bitmap_set_bit (&map_head, DECL_UID (t));
686138fd1498Szrj if (t != OMP_CLAUSE_DECL (c)
686238fd1498Szrj && TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
686338fd1498Szrj bitmap_set_bit (&map_field_head, DECL_UID (t));
686438fd1498Szrj }
686538fd1498Szrj handle_map_references:
686638fd1498Szrj if (!remove
686738fd1498Szrj && !processing_template_decl
686838fd1498Szrj && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
686938fd1498Szrj && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == REFERENCE_TYPE)
687038fd1498Szrj {
687138fd1498Szrj t = OMP_CLAUSE_DECL (c);
687238fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
687338fd1498Szrj {
687438fd1498Szrj OMP_CLAUSE_DECL (c) = build_simple_mem_ref (t);
687538fd1498Szrj if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
687638fd1498Szrj OMP_CLAUSE_SIZE (c)
687738fd1498Szrj = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (t)));
687838fd1498Szrj }
687938fd1498Szrj else if (OMP_CLAUSE_MAP_KIND (c)
688038fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_POINTER
688138fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c)
688238fd1498Szrj != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
688338fd1498Szrj && (OMP_CLAUSE_MAP_KIND (c)
688438fd1498Szrj != GOMP_MAP_ALWAYS_POINTER))
688538fd1498Szrj {
688638fd1498Szrj tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
688738fd1498Szrj OMP_CLAUSE_MAP);
688838fd1498Szrj if (TREE_CODE (t) == COMPONENT_REF)
688938fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
689038fd1498Szrj else
689138fd1498Szrj OMP_CLAUSE_SET_MAP_KIND (c2,
689238fd1498Szrj GOMP_MAP_FIRSTPRIVATE_REFERENCE);
689338fd1498Szrj OMP_CLAUSE_DECL (c2) = t;
689438fd1498Szrj OMP_CLAUSE_SIZE (c2) = size_zero_node;
689538fd1498Szrj OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
689638fd1498Szrj OMP_CLAUSE_CHAIN (c) = c2;
689738fd1498Szrj OMP_CLAUSE_DECL (c) = build_simple_mem_ref (t);
689838fd1498Szrj if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
689938fd1498Szrj OMP_CLAUSE_SIZE (c)
690038fd1498Szrj = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (t)));
690138fd1498Szrj c = c2;
690238fd1498Szrj }
690338fd1498Szrj }
690438fd1498Szrj break;
690538fd1498Szrj
690638fd1498Szrj case OMP_CLAUSE_TO_DECLARE:
690738fd1498Szrj case OMP_CLAUSE_LINK:
690838fd1498Szrj t = OMP_CLAUSE_DECL (c);
690938fd1498Szrj if (TREE_CODE (t) == FUNCTION_DECL
691038fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
691138fd1498Szrj ;
691238fd1498Szrj else if (!VAR_P (t))
691338fd1498Szrj {
691438fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
691538fd1498Szrj {
691638fd1498Szrj if (TREE_CODE (t) == TEMPLATE_ID_EXPR)
691738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
691838fd1498Szrj "template %qE in clause %qs", t,
691938fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
692038fd1498Szrj else if (really_overloaded_fn (t))
692138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
692238fd1498Szrj "overloaded function name %qE in clause %qs", t,
692338fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
692438fd1498Szrj else
692538fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
692638fd1498Szrj "%qE is neither a variable nor a function name "
692738fd1498Szrj "in clause %qs", t,
692838fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
692938fd1498Szrj }
693038fd1498Szrj else
693138fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
693238fd1498Szrj "%qE is not a variable in clause %qs", t,
693338fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
693438fd1498Szrj remove = true;
693538fd1498Szrj }
693638fd1498Szrj else if (DECL_THREAD_LOCAL_P (t))
693738fd1498Szrj {
693838fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
693938fd1498Szrj "%qD is threadprivate variable in %qs clause", t,
694038fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
694138fd1498Szrj remove = true;
694238fd1498Szrj }
694338fd1498Szrj else if (!cp_omp_mappable_type (TREE_TYPE (t)))
694438fd1498Szrj {
694538fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
694638fd1498Szrj "%qD does not have a mappable type in %qs clause", t,
694738fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
694838fd1498Szrj remove = true;
694938fd1498Szrj }
695038fd1498Szrj if (remove)
695138fd1498Szrj break;
695238fd1498Szrj if (bitmap_bit_p (&generic_head, DECL_UID (t)))
695338fd1498Szrj {
695438fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
695538fd1498Szrj "%qE appears more than once on the same "
695638fd1498Szrj "%<declare target%> directive", t);
695738fd1498Szrj remove = true;
695838fd1498Szrj }
695938fd1498Szrj else
696038fd1498Szrj bitmap_set_bit (&generic_head, DECL_UID (t));
696138fd1498Szrj break;
696238fd1498Szrj
696338fd1498Szrj case OMP_CLAUSE_UNIFORM:
696438fd1498Szrj t = OMP_CLAUSE_DECL (c);
696538fd1498Szrj if (TREE_CODE (t) != PARM_DECL)
696638fd1498Szrj {
696738fd1498Szrj if (processing_template_decl)
696838fd1498Szrj break;
696938fd1498Szrj if (DECL_P (t))
697038fd1498Szrj error ("%qD is not an argument in %<uniform%> clause", t);
697138fd1498Szrj else
697238fd1498Szrj error ("%qE is not an argument in %<uniform%> clause", t);
697338fd1498Szrj remove = true;
697438fd1498Szrj break;
697538fd1498Szrj }
697638fd1498Szrj /* map_head bitmap is used as uniform_head if declare_simd. */
697738fd1498Szrj bitmap_set_bit (&map_head, DECL_UID (t));
697838fd1498Szrj goto check_dup_generic;
697938fd1498Szrj
698038fd1498Szrj case OMP_CLAUSE_GRAINSIZE:
698138fd1498Szrj t = OMP_CLAUSE_GRAINSIZE_EXPR (c);
698238fd1498Szrj if (t == error_mark_node)
698338fd1498Szrj remove = true;
698438fd1498Szrj else if (!type_dependent_expression_p (t)
698538fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
698638fd1498Szrj {
698738fd1498Szrj error ("%<grainsize%> expression must be integral");
698838fd1498Szrj remove = true;
698938fd1498Szrj }
699038fd1498Szrj else
699138fd1498Szrj {
699238fd1498Szrj t = mark_rvalue_use (t);
699338fd1498Szrj if (!processing_template_decl)
699438fd1498Szrj {
699538fd1498Szrj t = maybe_constant_value (t);
699638fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
699738fd1498Szrj && tree_int_cst_sgn (t) != 1)
699838fd1498Szrj {
699938fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
700038fd1498Szrj "%<grainsize%> value must be positive");
700138fd1498Szrj t = integer_one_node;
700238fd1498Szrj }
700338fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
700438fd1498Szrj }
700538fd1498Szrj OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
700638fd1498Szrj }
700738fd1498Szrj break;
700838fd1498Szrj
700938fd1498Szrj case OMP_CLAUSE_PRIORITY:
701038fd1498Szrj t = OMP_CLAUSE_PRIORITY_EXPR (c);
701138fd1498Szrj if (t == error_mark_node)
701238fd1498Szrj remove = true;
701338fd1498Szrj else if (!type_dependent_expression_p (t)
701438fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
701538fd1498Szrj {
701638fd1498Szrj error ("%<priority%> expression must be integral");
701738fd1498Szrj remove = true;
701838fd1498Szrj }
701938fd1498Szrj else
702038fd1498Szrj {
702138fd1498Szrj t = mark_rvalue_use (t);
702238fd1498Szrj if (!processing_template_decl)
702338fd1498Szrj {
702438fd1498Szrj t = maybe_constant_value (t);
702538fd1498Szrj if (TREE_CODE (t) == INTEGER_CST
702638fd1498Szrj && tree_int_cst_sgn (t) == -1)
702738fd1498Szrj {
702838fd1498Szrj warning_at (OMP_CLAUSE_LOCATION (c), 0,
702938fd1498Szrj "%<priority%> value must be non-negative");
703038fd1498Szrj t = integer_one_node;
703138fd1498Szrj }
703238fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
703338fd1498Szrj }
703438fd1498Szrj OMP_CLAUSE_PRIORITY_EXPR (c) = t;
703538fd1498Szrj }
703638fd1498Szrj break;
703738fd1498Szrj
703838fd1498Szrj case OMP_CLAUSE_HINT:
703938fd1498Szrj t = OMP_CLAUSE_HINT_EXPR (c);
704038fd1498Szrj if (t == error_mark_node)
704138fd1498Szrj remove = true;
704238fd1498Szrj else if (!type_dependent_expression_p (t)
704338fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
704438fd1498Szrj {
704538fd1498Szrj error ("%<num_tasks%> expression must be integral");
704638fd1498Szrj remove = true;
704738fd1498Szrj }
704838fd1498Szrj else
704938fd1498Szrj {
705038fd1498Szrj t = mark_rvalue_use (t);
705138fd1498Szrj if (!processing_template_decl)
705238fd1498Szrj {
705338fd1498Szrj t = maybe_constant_value (t);
705438fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
705538fd1498Szrj }
705638fd1498Szrj OMP_CLAUSE_HINT_EXPR (c) = t;
705738fd1498Szrj }
705838fd1498Szrj break;
705938fd1498Szrj
706038fd1498Szrj case OMP_CLAUSE_IS_DEVICE_PTR:
706138fd1498Szrj case OMP_CLAUSE_USE_DEVICE_PTR:
706238fd1498Szrj field_ok = (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP;
706338fd1498Szrj t = OMP_CLAUSE_DECL (c);
706438fd1498Szrj if (!type_dependent_expression_p (t))
706538fd1498Szrj {
706638fd1498Szrj tree type = TREE_TYPE (t);
706738fd1498Szrj if (TREE_CODE (type) != POINTER_TYPE
706838fd1498Szrj && TREE_CODE (type) != ARRAY_TYPE
706938fd1498Szrj && (TREE_CODE (type) != REFERENCE_TYPE
707038fd1498Szrj || (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
707138fd1498Szrj && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)))
707238fd1498Szrj {
707338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
707438fd1498Szrj "%qs variable is neither a pointer, nor an array "
707538fd1498Szrj "nor reference to pointer or array",
707638fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
707738fd1498Szrj remove = true;
707838fd1498Szrj }
707938fd1498Szrj }
708038fd1498Szrj goto check_dup_generic;
708138fd1498Szrj
708238fd1498Szrj case OMP_CLAUSE_NOWAIT:
708338fd1498Szrj case OMP_CLAUSE_DEFAULT:
708438fd1498Szrj case OMP_CLAUSE_UNTIED:
708538fd1498Szrj case OMP_CLAUSE_COLLAPSE:
708638fd1498Szrj case OMP_CLAUSE_MERGEABLE:
708738fd1498Szrj case OMP_CLAUSE_PARALLEL:
708838fd1498Szrj case OMP_CLAUSE_FOR:
708938fd1498Szrj case OMP_CLAUSE_SECTIONS:
709038fd1498Szrj case OMP_CLAUSE_TASKGROUP:
709138fd1498Szrj case OMP_CLAUSE_PROC_BIND:
709238fd1498Szrj case OMP_CLAUSE_NOGROUP:
709338fd1498Szrj case OMP_CLAUSE_THREADS:
709438fd1498Szrj case OMP_CLAUSE_SIMD:
709538fd1498Szrj case OMP_CLAUSE_DEFAULTMAP:
709638fd1498Szrj case OMP_CLAUSE_AUTO:
709738fd1498Szrj case OMP_CLAUSE_INDEPENDENT:
709838fd1498Szrj case OMP_CLAUSE_SEQ:
709938fd1498Szrj break;
710038fd1498Szrj
710138fd1498Szrj case OMP_CLAUSE_TILE:
710238fd1498Szrj for (tree list = OMP_CLAUSE_TILE_LIST (c); !remove && list;
710338fd1498Szrj list = TREE_CHAIN (list))
710438fd1498Szrj {
710538fd1498Szrj t = TREE_VALUE (list);
710638fd1498Szrj
710738fd1498Szrj if (t == error_mark_node)
710838fd1498Szrj remove = true;
710938fd1498Szrj else if (!type_dependent_expression_p (t)
711038fd1498Szrj && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
711138fd1498Szrj {
711238fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
711338fd1498Szrj "%<tile%> argument needs integral type");
711438fd1498Szrj remove = true;
711538fd1498Szrj }
711638fd1498Szrj else
711738fd1498Szrj {
711838fd1498Szrj t = mark_rvalue_use (t);
711938fd1498Szrj if (!processing_template_decl)
712038fd1498Szrj {
712138fd1498Szrj /* Zero is used to indicate '*', we permit you
712238fd1498Szrj to get there via an ICE of value zero. */
712338fd1498Szrj t = maybe_constant_value (t);
712438fd1498Szrj if (!tree_fits_shwi_p (t)
712538fd1498Szrj || tree_to_shwi (t) < 0)
712638fd1498Szrj {
712738fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
712838fd1498Szrj "%<tile%> argument needs positive "
712938fd1498Szrj "integral constant");
713038fd1498Szrj remove = true;
713138fd1498Szrj }
713238fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
713338fd1498Szrj }
713438fd1498Szrj }
713538fd1498Szrj
713638fd1498Szrj /* Update list item. */
713738fd1498Szrj TREE_VALUE (list) = t;
713838fd1498Szrj }
713938fd1498Szrj break;
714038fd1498Szrj
714138fd1498Szrj case OMP_CLAUSE_ORDERED:
714238fd1498Szrj ordered_seen = true;
714338fd1498Szrj break;
714438fd1498Szrj
714538fd1498Szrj case OMP_CLAUSE_INBRANCH:
714638fd1498Szrj case OMP_CLAUSE_NOTINBRANCH:
714738fd1498Szrj if (branch_seen)
714838fd1498Szrj {
714938fd1498Szrj error ("%<inbranch%> clause is incompatible with "
715038fd1498Szrj "%<notinbranch%>");
715138fd1498Szrj remove = true;
715238fd1498Szrj }
715338fd1498Szrj branch_seen = true;
715438fd1498Szrj break;
715538fd1498Szrj
715638fd1498Szrj default:
715738fd1498Szrj gcc_unreachable ();
715838fd1498Szrj }
715938fd1498Szrj
716038fd1498Szrj if (remove)
716138fd1498Szrj *pc = OMP_CLAUSE_CHAIN (c);
716238fd1498Szrj else
716338fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
716438fd1498Szrj }
716538fd1498Szrj
716638fd1498Szrj for (pc = &clauses, c = clauses; c ; c = *pc)
716738fd1498Szrj {
716838fd1498Szrj enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
716938fd1498Szrj bool remove = false;
717038fd1498Szrj bool need_complete_type = false;
717138fd1498Szrj bool need_default_ctor = false;
717238fd1498Szrj bool need_copy_ctor = false;
717338fd1498Szrj bool need_copy_assignment = false;
717438fd1498Szrj bool need_implicitly_determined = false;
717538fd1498Szrj bool need_dtor = false;
717638fd1498Szrj tree type, inner_type;
717738fd1498Szrj
717838fd1498Szrj switch (c_kind)
717938fd1498Szrj {
718038fd1498Szrj case OMP_CLAUSE_SHARED:
718138fd1498Szrj need_implicitly_determined = true;
718238fd1498Szrj break;
718338fd1498Szrj case OMP_CLAUSE_PRIVATE:
718438fd1498Szrj need_complete_type = true;
718538fd1498Szrj need_default_ctor = true;
718638fd1498Szrj need_dtor = true;
718738fd1498Szrj need_implicitly_determined = true;
718838fd1498Szrj break;
718938fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
719038fd1498Szrj need_complete_type = true;
719138fd1498Szrj need_copy_ctor = true;
719238fd1498Szrj need_dtor = true;
719338fd1498Szrj need_implicitly_determined = true;
719438fd1498Szrj break;
719538fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
719638fd1498Szrj need_complete_type = true;
719738fd1498Szrj need_copy_assignment = true;
719838fd1498Szrj need_implicitly_determined = true;
719938fd1498Szrj break;
720038fd1498Szrj case OMP_CLAUSE_REDUCTION:
720138fd1498Szrj need_implicitly_determined = true;
720238fd1498Szrj break;
720338fd1498Szrj case OMP_CLAUSE_LINEAR:
720438fd1498Szrj if (ort != C_ORT_OMP_DECLARE_SIMD)
720538fd1498Szrj need_implicitly_determined = true;
720638fd1498Szrj else if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c)
720738fd1498Szrj && !bitmap_bit_p (&map_head,
720838fd1498Szrj DECL_UID (OMP_CLAUSE_LINEAR_STEP (c))))
720938fd1498Szrj {
721038fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
721138fd1498Szrj "%<linear%> clause step is a parameter %qD not "
721238fd1498Szrj "specified in %<uniform%> clause",
721338fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c));
721438fd1498Szrj *pc = OMP_CLAUSE_CHAIN (c);
721538fd1498Szrj continue;
721638fd1498Szrj }
721738fd1498Szrj break;
721838fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
721938fd1498Szrj need_copy_assignment = true;
722038fd1498Szrj break;
722138fd1498Szrj case OMP_CLAUSE_COPYIN:
722238fd1498Szrj need_copy_assignment = true;
722338fd1498Szrj break;
722438fd1498Szrj case OMP_CLAUSE_SIMDLEN:
722538fd1498Szrj if (safelen
722638fd1498Szrj && !processing_template_decl
722738fd1498Szrj && tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen),
722838fd1498Szrj OMP_CLAUSE_SIMDLEN_EXPR (c)))
722938fd1498Szrj {
723038fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
723138fd1498Szrj "%<simdlen%> clause value is bigger than "
723238fd1498Szrj "%<safelen%> clause value");
723338fd1498Szrj OMP_CLAUSE_SIMDLEN_EXPR (c)
723438fd1498Szrj = OMP_CLAUSE_SAFELEN_EXPR (safelen);
723538fd1498Szrj }
723638fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
723738fd1498Szrj continue;
723838fd1498Szrj case OMP_CLAUSE_SCHEDULE:
723938fd1498Szrj if (ordered_seen
724038fd1498Szrj && (OMP_CLAUSE_SCHEDULE_KIND (c)
724138fd1498Szrj & OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
724238fd1498Szrj {
724338fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
724438fd1498Szrj "%<nonmonotonic%> schedule modifier specified "
724538fd1498Szrj "together with %<ordered%> clause");
724638fd1498Szrj OMP_CLAUSE_SCHEDULE_KIND (c)
724738fd1498Szrj = (enum omp_clause_schedule_kind)
724838fd1498Szrj (OMP_CLAUSE_SCHEDULE_KIND (c)
724938fd1498Szrj & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
725038fd1498Szrj }
725138fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
725238fd1498Szrj continue;
725338fd1498Szrj case OMP_CLAUSE_NOWAIT:
725438fd1498Szrj if (copyprivate_seen)
725538fd1498Szrj {
725638fd1498Szrj error_at (OMP_CLAUSE_LOCATION (c),
725738fd1498Szrj "%<nowait%> clause must not be used together "
725838fd1498Szrj "with %<copyprivate%>");
725938fd1498Szrj *pc = OMP_CLAUSE_CHAIN (c);
726038fd1498Szrj continue;
726138fd1498Szrj }
726238fd1498Szrj /* FALLTHRU */
726338fd1498Szrj default:
726438fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
726538fd1498Szrj continue;
726638fd1498Szrj }
726738fd1498Szrj
726838fd1498Szrj t = OMP_CLAUSE_DECL (c);
726938fd1498Szrj if (processing_template_decl
727038fd1498Szrj && !VAR_P (t) && TREE_CODE (t) != PARM_DECL)
727138fd1498Szrj {
727238fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
727338fd1498Szrj continue;
727438fd1498Szrj }
727538fd1498Szrj
727638fd1498Szrj switch (c_kind)
727738fd1498Szrj {
727838fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
727938fd1498Szrj if (!bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
728038fd1498Szrj {
728138fd1498Szrj need_default_ctor = true;
728238fd1498Szrj need_dtor = true;
728338fd1498Szrj }
728438fd1498Szrj break;
728538fd1498Szrj
728638fd1498Szrj case OMP_CLAUSE_REDUCTION:
728738fd1498Szrj if (finish_omp_reduction_clause (c, &need_default_ctor,
728838fd1498Szrj &need_dtor))
728938fd1498Szrj remove = true;
729038fd1498Szrj else
729138fd1498Szrj t = OMP_CLAUSE_DECL (c);
729238fd1498Szrj break;
729338fd1498Szrj
729438fd1498Szrj case OMP_CLAUSE_COPYIN:
729538fd1498Szrj if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
729638fd1498Szrj {
729738fd1498Szrj error ("%qE must be %<threadprivate%> for %<copyin%>", t);
729838fd1498Szrj remove = true;
729938fd1498Szrj }
730038fd1498Szrj break;
730138fd1498Szrj
730238fd1498Szrj default:
730338fd1498Szrj break;
730438fd1498Szrj }
730538fd1498Szrj
730638fd1498Szrj if (need_complete_type || need_copy_assignment)
730738fd1498Szrj {
730838fd1498Szrj t = require_complete_type (t);
730938fd1498Szrj if (t == error_mark_node)
731038fd1498Szrj remove = true;
731138fd1498Szrj else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
731238fd1498Szrj && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
731338fd1498Szrj remove = true;
731438fd1498Szrj }
731538fd1498Szrj if (need_implicitly_determined)
731638fd1498Szrj {
731738fd1498Szrj const char *share_name = NULL;
731838fd1498Szrj
731938fd1498Szrj if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
732038fd1498Szrj share_name = "threadprivate";
732158e805e6Szrj else switch (cxx_omp_predetermined_sharing_1 (t))
732238fd1498Szrj {
732338fd1498Szrj case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
732438fd1498Szrj break;
732538fd1498Szrj case OMP_CLAUSE_DEFAULT_SHARED:
732638fd1498Szrj /* const vars may be specified in firstprivate clause. */
732738fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
732838fd1498Szrj && cxx_omp_const_qual_no_mutable (t))
732938fd1498Szrj break;
733038fd1498Szrj share_name = "shared";
733138fd1498Szrj break;
733238fd1498Szrj case OMP_CLAUSE_DEFAULT_PRIVATE:
733338fd1498Szrj share_name = "private";
733438fd1498Szrj break;
733538fd1498Szrj default:
733638fd1498Szrj gcc_unreachable ();
733738fd1498Szrj }
733838fd1498Szrj if (share_name)
733938fd1498Szrj {
734038fd1498Szrj error ("%qE is predetermined %qs for %qs",
734138fd1498Szrj omp_clause_printable_decl (t), share_name,
734238fd1498Szrj omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
734338fd1498Szrj remove = true;
734438fd1498Szrj }
734538fd1498Szrj }
734638fd1498Szrj
734738fd1498Szrj /* We're interested in the base element, not arrays. */
734838fd1498Szrj inner_type = type = TREE_TYPE (t);
734938fd1498Szrj if ((need_complete_type
735038fd1498Szrj || need_copy_assignment
735138fd1498Szrj || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
735238fd1498Szrj && TREE_CODE (inner_type) == REFERENCE_TYPE)
735338fd1498Szrj inner_type = TREE_TYPE (inner_type);
735438fd1498Szrj while (TREE_CODE (inner_type) == ARRAY_TYPE)
735538fd1498Szrj inner_type = TREE_TYPE (inner_type);
735638fd1498Szrj
735738fd1498Szrj /* Check for special function availability by building a call to one.
735838fd1498Szrj Save the results, because later we won't be in the right context
735938fd1498Szrj for making these queries. */
736038fd1498Szrj if (CLASS_TYPE_P (inner_type)
736138fd1498Szrj && COMPLETE_TYPE_P (inner_type)
736238fd1498Szrj && (need_default_ctor || need_copy_ctor
736338fd1498Szrj || need_copy_assignment || need_dtor)
736438fd1498Szrj && !type_dependent_expression_p (t)
736538fd1498Szrj && cxx_omp_create_clause_info (c, inner_type, need_default_ctor,
736638fd1498Szrj need_copy_ctor, need_copy_assignment,
736738fd1498Szrj need_dtor))
736838fd1498Szrj remove = true;
736938fd1498Szrj
737038fd1498Szrj if (!remove
737138fd1498Szrj && c_kind == OMP_CLAUSE_SHARED
737238fd1498Szrj && processing_template_decl)
737338fd1498Szrj {
737438fd1498Szrj t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
737538fd1498Szrj if (t)
737638fd1498Szrj OMP_CLAUSE_DECL (c) = t;
737738fd1498Szrj }
737838fd1498Szrj
737938fd1498Szrj if (remove)
738038fd1498Szrj *pc = OMP_CLAUSE_CHAIN (c);
738138fd1498Szrj else
738238fd1498Szrj pc = &OMP_CLAUSE_CHAIN (c);
738338fd1498Szrj }
738438fd1498Szrj
738538fd1498Szrj bitmap_obstack_release (NULL);
738638fd1498Szrj return clauses;
738738fd1498Szrj }
738838fd1498Szrj
738938fd1498Szrj /* Start processing OpenMP clauses that can include any
739038fd1498Szrj privatization clauses for non-static data members. */
739138fd1498Szrj
739238fd1498Szrj tree
push_omp_privatization_clauses(bool ignore_next)739338fd1498Szrj push_omp_privatization_clauses (bool ignore_next)
739438fd1498Szrj {
739538fd1498Szrj if (omp_private_member_ignore_next)
739638fd1498Szrj {
739738fd1498Szrj omp_private_member_ignore_next = ignore_next;
739838fd1498Szrj return NULL_TREE;
739938fd1498Szrj }
740038fd1498Szrj omp_private_member_ignore_next = ignore_next;
740138fd1498Szrj if (omp_private_member_map)
740238fd1498Szrj omp_private_member_vec.safe_push (error_mark_node);
740338fd1498Szrj return push_stmt_list ();
740438fd1498Szrj }
740538fd1498Szrj
740638fd1498Szrj /* Revert remapping of any non-static data members since
740738fd1498Szrj the last push_omp_privatization_clauses () call. */
740838fd1498Szrj
740938fd1498Szrj void
pop_omp_privatization_clauses(tree stmt)741038fd1498Szrj pop_omp_privatization_clauses (tree stmt)
741138fd1498Szrj {
741238fd1498Szrj if (stmt == NULL_TREE)
741338fd1498Szrj return;
741438fd1498Szrj stmt = pop_stmt_list (stmt);
741538fd1498Szrj if (omp_private_member_map)
741638fd1498Szrj {
741738fd1498Szrj while (!omp_private_member_vec.is_empty ())
741838fd1498Szrj {
741938fd1498Szrj tree t = omp_private_member_vec.pop ();
742038fd1498Szrj if (t == error_mark_node)
742138fd1498Szrj {
742238fd1498Szrj add_stmt (stmt);
742338fd1498Szrj return;
742438fd1498Szrj }
742538fd1498Szrj bool no_decl_expr = t == integer_zero_node;
742638fd1498Szrj if (no_decl_expr)
742738fd1498Szrj t = omp_private_member_vec.pop ();
742838fd1498Szrj tree *v = omp_private_member_map->get (t);
742938fd1498Szrj gcc_assert (v);
743038fd1498Szrj if (!no_decl_expr)
743138fd1498Szrj add_decl_expr (*v);
743238fd1498Szrj omp_private_member_map->remove (t);
743338fd1498Szrj }
743438fd1498Szrj delete omp_private_member_map;
743538fd1498Szrj omp_private_member_map = NULL;
743638fd1498Szrj }
743738fd1498Szrj add_stmt (stmt);
743838fd1498Szrj }
743938fd1498Szrj
744038fd1498Szrj /* Remember OpenMP privatization clauses mapping and clear it.
744138fd1498Szrj Used for lambdas. */
744238fd1498Szrj
744338fd1498Szrj void
save_omp_privatization_clauses(vec<tree> & save)744438fd1498Szrj save_omp_privatization_clauses (vec<tree> &save)
744538fd1498Szrj {
744638fd1498Szrj save = vNULL;
744738fd1498Szrj if (omp_private_member_ignore_next)
744838fd1498Szrj save.safe_push (integer_one_node);
744938fd1498Szrj omp_private_member_ignore_next = false;
745038fd1498Szrj if (!omp_private_member_map)
745138fd1498Szrj return;
745238fd1498Szrj
745338fd1498Szrj while (!omp_private_member_vec.is_empty ())
745438fd1498Szrj {
745538fd1498Szrj tree t = omp_private_member_vec.pop ();
745638fd1498Szrj if (t == error_mark_node)
745738fd1498Szrj {
745838fd1498Szrj save.safe_push (t);
745938fd1498Szrj continue;
746038fd1498Szrj }
746138fd1498Szrj tree n = t;
746238fd1498Szrj if (t == integer_zero_node)
746338fd1498Szrj t = omp_private_member_vec.pop ();
746438fd1498Szrj tree *v = omp_private_member_map->get (t);
746538fd1498Szrj gcc_assert (v);
746638fd1498Szrj save.safe_push (*v);
746738fd1498Szrj save.safe_push (t);
746838fd1498Szrj if (n != t)
746938fd1498Szrj save.safe_push (n);
747038fd1498Szrj }
747138fd1498Szrj delete omp_private_member_map;
747238fd1498Szrj omp_private_member_map = NULL;
747338fd1498Szrj }
747438fd1498Szrj
747538fd1498Szrj /* Restore OpenMP privatization clauses mapping saved by the
747638fd1498Szrj above function. */
747738fd1498Szrj
747838fd1498Szrj void
restore_omp_privatization_clauses(vec<tree> & save)747938fd1498Szrj restore_omp_privatization_clauses (vec<tree> &save)
748038fd1498Szrj {
748138fd1498Szrj gcc_assert (omp_private_member_vec.is_empty ());
748238fd1498Szrj omp_private_member_ignore_next = false;
748338fd1498Szrj if (save.is_empty ())
748438fd1498Szrj return;
748538fd1498Szrj if (save.length () == 1 && save[0] == integer_one_node)
748638fd1498Szrj {
748738fd1498Szrj omp_private_member_ignore_next = true;
748838fd1498Szrj save.release ();
748938fd1498Szrj return;
749038fd1498Szrj }
749138fd1498Szrj
749238fd1498Szrj omp_private_member_map = new hash_map <tree, tree>;
749338fd1498Szrj while (!save.is_empty ())
749438fd1498Szrj {
749538fd1498Szrj tree t = save.pop ();
749638fd1498Szrj tree n = t;
749738fd1498Szrj if (t != error_mark_node)
749838fd1498Szrj {
749938fd1498Szrj if (t == integer_one_node)
750038fd1498Szrj {
750138fd1498Szrj omp_private_member_ignore_next = true;
750238fd1498Szrj gcc_assert (save.is_empty ());
750338fd1498Szrj break;
750438fd1498Szrj }
750538fd1498Szrj if (t == integer_zero_node)
750638fd1498Szrj t = save.pop ();
750738fd1498Szrj tree &v = omp_private_member_map->get_or_insert (t);
750838fd1498Szrj v = save.pop ();
750938fd1498Szrj }
751038fd1498Szrj omp_private_member_vec.safe_push (t);
751138fd1498Szrj if (n != t)
751238fd1498Szrj omp_private_member_vec.safe_push (n);
751338fd1498Szrj }
751438fd1498Szrj save.release ();
751538fd1498Szrj }
751638fd1498Szrj
751738fd1498Szrj /* For all variables in the tree_list VARS, mark them as thread local. */
751838fd1498Szrj
751938fd1498Szrj void
finish_omp_threadprivate(tree vars)752038fd1498Szrj finish_omp_threadprivate (tree vars)
752138fd1498Szrj {
752238fd1498Szrj tree t;
752338fd1498Szrj
752438fd1498Szrj /* Mark every variable in VARS to be assigned thread local storage. */
752538fd1498Szrj for (t = vars; t; t = TREE_CHAIN (t))
752638fd1498Szrj {
752738fd1498Szrj tree v = TREE_PURPOSE (t);
752838fd1498Szrj
752938fd1498Szrj if (error_operand_p (v))
753038fd1498Szrj ;
753138fd1498Szrj else if (!VAR_P (v))
753238fd1498Szrj error ("%<threadprivate%> %qD is not file, namespace "
753338fd1498Szrj "or block scope variable", v);
753438fd1498Szrj /* If V had already been marked threadprivate, it doesn't matter
753538fd1498Szrj whether it had been used prior to this point. */
753638fd1498Szrj else if (TREE_USED (v)
753738fd1498Szrj && (DECL_LANG_SPECIFIC (v) == NULL
753838fd1498Szrj || !CP_DECL_THREADPRIVATE_P (v)))
753938fd1498Szrj error ("%qE declared %<threadprivate%> after first use", v);
754038fd1498Szrj else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
754138fd1498Szrj error ("automatic variable %qE cannot be %<threadprivate%>", v);
754238fd1498Szrj else if (! COMPLETE_TYPE_P (complete_type (TREE_TYPE (v))))
754338fd1498Szrj error ("%<threadprivate%> %qE has incomplete type", v);
754438fd1498Szrj else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v))
754538fd1498Szrj && CP_DECL_CONTEXT (v) != current_class_type)
754638fd1498Szrj error ("%<threadprivate%> %qE directive not "
754738fd1498Szrj "in %qT definition", v, CP_DECL_CONTEXT (v));
754838fd1498Szrj else
754938fd1498Szrj {
755038fd1498Szrj /* Allocate a LANG_SPECIFIC structure for V, if needed. */
755138fd1498Szrj if (DECL_LANG_SPECIFIC (v) == NULL)
755238fd1498Szrj {
755338fd1498Szrj retrofit_lang_decl (v);
755438fd1498Szrj
755538fd1498Szrj /* Make sure that DECL_DISCRIMINATOR_P continues to be true
755638fd1498Szrj after the allocation of the lang_decl structure. */
755738fd1498Szrj if (DECL_DISCRIMINATOR_P (v))
755838fd1498Szrj DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1;
755938fd1498Szrj }
756038fd1498Szrj
756138fd1498Szrj if (! CP_DECL_THREAD_LOCAL_P (v))
756238fd1498Szrj {
756338fd1498Szrj CP_DECL_THREAD_LOCAL_P (v) = true;
756438fd1498Szrj set_decl_tls_model (v, decl_default_tls_model (v));
756538fd1498Szrj /* If rtl has been already set for this var, call
756638fd1498Szrj make_decl_rtl once again, so that encode_section_info
756738fd1498Szrj has a chance to look at the new decl flags. */
756838fd1498Szrj if (DECL_RTL_SET_P (v))
756938fd1498Szrj make_decl_rtl (v);
757038fd1498Szrj }
757138fd1498Szrj CP_DECL_THREADPRIVATE_P (v) = 1;
757238fd1498Szrj }
757338fd1498Szrj }
757438fd1498Szrj }
757538fd1498Szrj
757638fd1498Szrj /* Build an OpenMP structured block. */
757738fd1498Szrj
757838fd1498Szrj tree
begin_omp_structured_block(void)757938fd1498Szrj begin_omp_structured_block (void)
758038fd1498Szrj {
758138fd1498Szrj return do_pushlevel (sk_omp);
758238fd1498Szrj }
758338fd1498Szrj
758438fd1498Szrj tree
finish_omp_structured_block(tree block)758538fd1498Szrj finish_omp_structured_block (tree block)
758638fd1498Szrj {
758738fd1498Szrj return do_poplevel (block);
758838fd1498Szrj }
758938fd1498Szrj
759038fd1498Szrj /* Similarly, except force the retention of the BLOCK. */
759138fd1498Szrj
759238fd1498Szrj tree
begin_omp_parallel(void)759338fd1498Szrj begin_omp_parallel (void)
759438fd1498Szrj {
759538fd1498Szrj keep_next_level (true);
759638fd1498Szrj return begin_omp_structured_block ();
759738fd1498Szrj }
759838fd1498Szrj
759938fd1498Szrj /* Generate OACC_DATA, with CLAUSES and BLOCK as its compound
760038fd1498Szrj statement. */
760138fd1498Szrj
760238fd1498Szrj tree
finish_oacc_data(tree clauses,tree block)760338fd1498Szrj finish_oacc_data (tree clauses, tree block)
760438fd1498Szrj {
760538fd1498Szrj tree stmt;
760638fd1498Szrj
760738fd1498Szrj block = finish_omp_structured_block (block);
760838fd1498Szrj
760938fd1498Szrj stmt = make_node (OACC_DATA);
761038fd1498Szrj TREE_TYPE (stmt) = void_type_node;
761138fd1498Szrj OACC_DATA_CLAUSES (stmt) = clauses;
761238fd1498Szrj OACC_DATA_BODY (stmt) = block;
761338fd1498Szrj
761438fd1498Szrj return add_stmt (stmt);
761538fd1498Szrj }
761638fd1498Szrj
761738fd1498Szrj /* Generate OACC_HOST_DATA, with CLAUSES and BLOCK as its compound
761838fd1498Szrj statement. */
761938fd1498Szrj
762038fd1498Szrj tree
finish_oacc_host_data(tree clauses,tree block)762138fd1498Szrj finish_oacc_host_data (tree clauses, tree block)
762238fd1498Szrj {
762338fd1498Szrj tree stmt;
762438fd1498Szrj
762538fd1498Szrj block = finish_omp_structured_block (block);
762638fd1498Szrj
762738fd1498Szrj stmt = make_node (OACC_HOST_DATA);
762838fd1498Szrj TREE_TYPE (stmt) = void_type_node;
762938fd1498Szrj OACC_HOST_DATA_CLAUSES (stmt) = clauses;
763038fd1498Szrj OACC_HOST_DATA_BODY (stmt) = block;
763138fd1498Szrj
763238fd1498Szrj return add_stmt (stmt);
763338fd1498Szrj }
763438fd1498Szrj
763538fd1498Szrj /* Generate OMP construct CODE, with BODY and CLAUSES as its compound
763638fd1498Szrj statement. */
763738fd1498Szrj
763838fd1498Szrj tree
finish_omp_construct(enum tree_code code,tree body,tree clauses)763938fd1498Szrj finish_omp_construct (enum tree_code code, tree body, tree clauses)
764038fd1498Szrj {
764138fd1498Szrj body = finish_omp_structured_block (body);
764238fd1498Szrj
764338fd1498Szrj tree stmt = make_node (code);
764438fd1498Szrj TREE_TYPE (stmt) = void_type_node;
764538fd1498Szrj OMP_BODY (stmt) = body;
764638fd1498Szrj OMP_CLAUSES (stmt) = clauses;
764738fd1498Szrj
764838fd1498Szrj return add_stmt (stmt);
764938fd1498Szrj }
765038fd1498Szrj
765138fd1498Szrj tree
finish_omp_parallel(tree clauses,tree body)765238fd1498Szrj finish_omp_parallel (tree clauses, tree body)
765338fd1498Szrj {
765438fd1498Szrj tree stmt;
765538fd1498Szrj
765638fd1498Szrj body = finish_omp_structured_block (body);
765738fd1498Szrj
765838fd1498Szrj stmt = make_node (OMP_PARALLEL);
765938fd1498Szrj TREE_TYPE (stmt) = void_type_node;
766038fd1498Szrj OMP_PARALLEL_CLAUSES (stmt) = clauses;
766138fd1498Szrj OMP_PARALLEL_BODY (stmt) = body;
766238fd1498Szrj
766338fd1498Szrj return add_stmt (stmt);
766438fd1498Szrj }
766538fd1498Szrj
766638fd1498Szrj tree
begin_omp_task(void)766738fd1498Szrj begin_omp_task (void)
766838fd1498Szrj {
766938fd1498Szrj keep_next_level (true);
767038fd1498Szrj return begin_omp_structured_block ();
767138fd1498Szrj }
767238fd1498Szrj
767338fd1498Szrj tree
finish_omp_task(tree clauses,tree body)767438fd1498Szrj finish_omp_task (tree clauses, tree body)
767538fd1498Szrj {
767638fd1498Szrj tree stmt;
767738fd1498Szrj
767838fd1498Szrj body = finish_omp_structured_block (body);
767938fd1498Szrj
768038fd1498Szrj stmt = make_node (OMP_TASK);
768138fd1498Szrj TREE_TYPE (stmt) = void_type_node;
768238fd1498Szrj OMP_TASK_CLAUSES (stmt) = clauses;
768338fd1498Szrj OMP_TASK_BODY (stmt) = body;
768438fd1498Szrj
768538fd1498Szrj return add_stmt (stmt);
768638fd1498Szrj }
768738fd1498Szrj
768838fd1498Szrj /* Helper function for finish_omp_for. Convert Ith random access iterator
768938fd1498Szrj into integral iterator. Return FALSE if successful. */
769038fd1498Szrj
769138fd1498Szrj static bool
handle_omp_for_class_iterator(int i,location_t locus,enum tree_code code,tree declv,tree orig_declv,tree initv,tree condv,tree incrv,tree * body,tree * pre_body,tree & clauses,tree * lastp,int collapse,int ordered)769238fd1498Szrj handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
769338fd1498Szrj tree declv, tree orig_declv, tree initv,
769438fd1498Szrj tree condv, tree incrv, tree *body,
769538fd1498Szrj tree *pre_body, tree &clauses, tree *lastp,
769638fd1498Szrj int collapse, int ordered)
769738fd1498Szrj {
769838fd1498Szrj tree diff, iter_init, iter_incr = NULL, last;
769938fd1498Szrj tree incr_var = NULL, orig_pre_body, orig_body, c;
770038fd1498Szrj tree decl = TREE_VEC_ELT (declv, i);
770138fd1498Szrj tree init = TREE_VEC_ELT (initv, i);
770238fd1498Szrj tree cond = TREE_VEC_ELT (condv, i);
770338fd1498Szrj tree incr = TREE_VEC_ELT (incrv, i);
770438fd1498Szrj tree iter = decl;
770538fd1498Szrj location_t elocus = locus;
770638fd1498Szrj
770738fd1498Szrj if (init && EXPR_HAS_LOCATION (init))
770838fd1498Szrj elocus = EXPR_LOCATION (init);
770938fd1498Szrj
771038fd1498Szrj cond = cp_fully_fold (cond);
771138fd1498Szrj switch (TREE_CODE (cond))
771238fd1498Szrj {
771338fd1498Szrj case GT_EXPR:
771438fd1498Szrj case GE_EXPR:
771538fd1498Szrj case LT_EXPR:
771638fd1498Szrj case LE_EXPR:
771738fd1498Szrj case NE_EXPR:
771838fd1498Szrj if (TREE_OPERAND (cond, 1) == iter)
771938fd1498Szrj cond = build2 (swap_tree_comparison (TREE_CODE (cond)),
772038fd1498Szrj TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0));
772138fd1498Szrj if (TREE_OPERAND (cond, 0) != iter)
772238fd1498Szrj cond = error_mark_node;
772338fd1498Szrj else
772438fd1498Szrj {
772538fd1498Szrj tree tem = build_x_binary_op (EXPR_LOCATION (cond),
772638fd1498Szrj TREE_CODE (cond),
772738fd1498Szrj iter, ERROR_MARK,
772838fd1498Szrj TREE_OPERAND (cond, 1), ERROR_MARK,
772938fd1498Szrj NULL, tf_warning_or_error);
773038fd1498Szrj if (error_operand_p (tem))
773138fd1498Szrj return true;
773238fd1498Szrj }
773338fd1498Szrj break;
773438fd1498Szrj default:
773538fd1498Szrj cond = error_mark_node;
773638fd1498Szrj break;
773738fd1498Szrj }
773838fd1498Szrj if (cond == error_mark_node)
773938fd1498Szrj {
774038fd1498Szrj error_at (elocus, "invalid controlling predicate");
774138fd1498Szrj return true;
774238fd1498Szrj }
774338fd1498Szrj diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
774438fd1498Szrj ERROR_MARK, iter, ERROR_MARK, NULL,
774538fd1498Szrj tf_warning_or_error);
774638fd1498Szrj diff = cp_fully_fold (diff);
774738fd1498Szrj if (error_operand_p (diff))
774838fd1498Szrj return true;
774938fd1498Szrj if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
775038fd1498Szrj {
775138fd1498Szrj error_at (elocus, "difference between %qE and %qD does not have integer type",
775238fd1498Szrj TREE_OPERAND (cond, 1), iter);
775338fd1498Szrj return true;
775438fd1498Szrj }
775538fd1498Szrj if (!c_omp_check_loop_iv_exprs (locus, orig_declv,
775638fd1498Szrj TREE_VEC_ELT (declv, i), NULL_TREE,
775738fd1498Szrj cond, cp_walk_subtrees))
775838fd1498Szrj return true;
775938fd1498Szrj
776038fd1498Szrj switch (TREE_CODE (incr))
776138fd1498Szrj {
776238fd1498Szrj case PREINCREMENT_EXPR:
776338fd1498Szrj case PREDECREMENT_EXPR:
776438fd1498Szrj case POSTINCREMENT_EXPR:
776538fd1498Szrj case POSTDECREMENT_EXPR:
776638fd1498Szrj if (TREE_OPERAND (incr, 0) != iter)
776738fd1498Szrj {
776838fd1498Szrj incr = error_mark_node;
776938fd1498Szrj break;
777038fd1498Szrj }
777138fd1498Szrj iter_incr = build_x_unary_op (EXPR_LOCATION (incr),
777238fd1498Szrj TREE_CODE (incr), iter,
777338fd1498Szrj tf_warning_or_error);
777438fd1498Szrj if (error_operand_p (iter_incr))
777538fd1498Szrj return true;
777638fd1498Szrj else if (TREE_CODE (incr) == PREINCREMENT_EXPR
777738fd1498Szrj || TREE_CODE (incr) == POSTINCREMENT_EXPR)
777838fd1498Szrj incr = integer_one_node;
777938fd1498Szrj else
778038fd1498Szrj incr = integer_minus_one_node;
778138fd1498Szrj break;
778238fd1498Szrj case MODIFY_EXPR:
778338fd1498Szrj if (TREE_OPERAND (incr, 0) != iter)
778438fd1498Szrj incr = error_mark_node;
778538fd1498Szrj else if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
778638fd1498Szrj || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
778738fd1498Szrj {
778838fd1498Szrj tree rhs = TREE_OPERAND (incr, 1);
778938fd1498Szrj if (TREE_OPERAND (rhs, 0) == iter)
779038fd1498Szrj {
779138fd1498Szrj if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 1)))
779238fd1498Szrj != INTEGER_TYPE)
779338fd1498Szrj incr = error_mark_node;
779438fd1498Szrj else
779538fd1498Szrj {
779638fd1498Szrj iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs),
779738fd1498Szrj iter, TREE_CODE (rhs),
779838fd1498Szrj TREE_OPERAND (rhs, 1),
779938fd1498Szrj tf_warning_or_error);
780038fd1498Szrj if (error_operand_p (iter_incr))
780138fd1498Szrj return true;
780238fd1498Szrj incr = TREE_OPERAND (rhs, 1);
780338fd1498Szrj incr = cp_convert (TREE_TYPE (diff), incr,
780438fd1498Szrj tf_warning_or_error);
780538fd1498Szrj if (TREE_CODE (rhs) == MINUS_EXPR)
780638fd1498Szrj {
780738fd1498Szrj incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
780838fd1498Szrj incr = fold_simple (incr);
780938fd1498Szrj }
781038fd1498Szrj if (TREE_CODE (incr) != INTEGER_CST
781138fd1498Szrj && (TREE_CODE (incr) != NOP_EXPR
781238fd1498Szrj || (TREE_CODE (TREE_OPERAND (incr, 0))
781338fd1498Szrj != INTEGER_CST)))
781438fd1498Szrj iter_incr = NULL;
781538fd1498Szrj }
781638fd1498Szrj }
781738fd1498Szrj else if (TREE_OPERAND (rhs, 1) == iter)
781838fd1498Szrj {
781938fd1498Szrj if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) != INTEGER_TYPE
782038fd1498Szrj || TREE_CODE (rhs) != PLUS_EXPR)
782138fd1498Szrj incr = error_mark_node;
782238fd1498Szrj else
782338fd1498Szrj {
782438fd1498Szrj iter_incr = build_x_binary_op (EXPR_LOCATION (rhs),
782538fd1498Szrj PLUS_EXPR,
782638fd1498Szrj TREE_OPERAND (rhs, 0),
782738fd1498Szrj ERROR_MARK, iter,
782838fd1498Szrj ERROR_MARK, NULL,
782938fd1498Szrj tf_warning_or_error);
783038fd1498Szrj if (error_operand_p (iter_incr))
783138fd1498Szrj return true;
783238fd1498Szrj iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs),
783338fd1498Szrj iter, NOP_EXPR,
783438fd1498Szrj iter_incr,
783538fd1498Szrj tf_warning_or_error);
783638fd1498Szrj if (error_operand_p (iter_incr))
783738fd1498Szrj return true;
783838fd1498Szrj incr = TREE_OPERAND (rhs, 0);
783938fd1498Szrj iter_incr = NULL;
784038fd1498Szrj }
784138fd1498Szrj }
784238fd1498Szrj else
784338fd1498Szrj incr = error_mark_node;
784438fd1498Szrj }
784538fd1498Szrj else
784638fd1498Szrj incr = error_mark_node;
784738fd1498Szrj break;
784838fd1498Szrj default:
784938fd1498Szrj incr = error_mark_node;
785038fd1498Szrj break;
785138fd1498Szrj }
785238fd1498Szrj
785338fd1498Szrj if (incr == error_mark_node)
785438fd1498Szrj {
785538fd1498Szrj error_at (elocus, "invalid increment expression");
785638fd1498Szrj return true;
785738fd1498Szrj }
785838fd1498Szrj
785938fd1498Szrj incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
786038fd1498Szrj bool taskloop_iv_seen = false;
786138fd1498Szrj for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
786238fd1498Szrj if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
786338fd1498Szrj && OMP_CLAUSE_DECL (c) == iter)
786438fd1498Szrj {
786538fd1498Szrj if (code == OMP_TASKLOOP)
786638fd1498Szrj {
786738fd1498Szrj taskloop_iv_seen = true;
786838fd1498Szrj OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c) = 1;
786938fd1498Szrj }
787038fd1498Szrj break;
787138fd1498Szrj }
787238fd1498Szrj else if (code == OMP_TASKLOOP
787338fd1498Szrj && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
787438fd1498Szrj && OMP_CLAUSE_DECL (c) == iter)
787538fd1498Szrj {
787638fd1498Szrj taskloop_iv_seen = true;
787738fd1498Szrj OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1;
787838fd1498Szrj }
787938fd1498Szrj
788038fd1498Szrj decl = create_temporary_var (TREE_TYPE (diff));
788138fd1498Szrj pushdecl (decl);
788238fd1498Szrj add_decl_expr (decl);
788338fd1498Szrj last = create_temporary_var (TREE_TYPE (diff));
788438fd1498Szrj pushdecl (last);
788538fd1498Szrj add_decl_expr (last);
788638fd1498Szrj if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST
788738fd1498Szrj && (!ordered || (i < collapse && collapse > 1)))
788838fd1498Szrj {
788938fd1498Szrj incr_var = create_temporary_var (TREE_TYPE (diff));
789038fd1498Szrj pushdecl (incr_var);
789138fd1498Szrj add_decl_expr (incr_var);
789238fd1498Szrj }
789338fd1498Szrj gcc_assert (stmts_are_full_exprs_p ());
789438fd1498Szrj tree diffvar = NULL_TREE;
789538fd1498Szrj if (code == OMP_TASKLOOP)
789638fd1498Szrj {
789738fd1498Szrj if (!taskloop_iv_seen)
789838fd1498Szrj {
789938fd1498Szrj tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
790038fd1498Szrj OMP_CLAUSE_DECL (ivc) = iter;
790138fd1498Szrj cxx_omp_finish_clause (ivc, NULL);
790238fd1498Szrj OMP_CLAUSE_CHAIN (ivc) = clauses;
790338fd1498Szrj clauses = ivc;
790438fd1498Szrj }
790538fd1498Szrj tree lvc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE);
790638fd1498Szrj OMP_CLAUSE_DECL (lvc) = last;
790738fd1498Szrj OMP_CLAUSE_CHAIN (lvc) = clauses;
790838fd1498Szrj clauses = lvc;
790938fd1498Szrj diffvar = create_temporary_var (TREE_TYPE (diff));
791038fd1498Szrj pushdecl (diffvar);
791138fd1498Szrj add_decl_expr (diffvar);
791238fd1498Szrj }
791338fd1498Szrj
791438fd1498Szrj orig_pre_body = *pre_body;
791538fd1498Szrj *pre_body = push_stmt_list ();
791638fd1498Szrj if (orig_pre_body)
791738fd1498Szrj add_stmt (orig_pre_body);
791838fd1498Szrj if (init != NULL)
791938fd1498Szrj finish_expr_stmt (build_x_modify_expr (elocus,
792038fd1498Szrj iter, NOP_EXPR, init,
792138fd1498Szrj tf_warning_or_error));
792238fd1498Szrj init = build_int_cst (TREE_TYPE (diff), 0);
792338fd1498Szrj if (c && iter_incr == NULL
792438fd1498Szrj && (!ordered || (i < collapse && collapse > 1)))
792538fd1498Szrj {
792638fd1498Szrj if (incr_var)
792738fd1498Szrj {
792838fd1498Szrj finish_expr_stmt (build_x_modify_expr (elocus,
792938fd1498Szrj incr_var, NOP_EXPR,
793038fd1498Szrj incr, tf_warning_or_error));
793138fd1498Szrj incr = incr_var;
793238fd1498Szrj }
793338fd1498Szrj iter_incr = build_x_modify_expr (elocus,
793438fd1498Szrj iter, PLUS_EXPR, incr,
793538fd1498Szrj tf_warning_or_error);
793638fd1498Szrj }
793738fd1498Szrj if (c && ordered && i < collapse && collapse > 1)
793838fd1498Szrj iter_incr = incr;
793938fd1498Szrj finish_expr_stmt (build_x_modify_expr (elocus,
794038fd1498Szrj last, NOP_EXPR, init,
794138fd1498Szrj tf_warning_or_error));
794238fd1498Szrj if (diffvar)
794338fd1498Szrj {
794438fd1498Szrj finish_expr_stmt (build_x_modify_expr (elocus,
794538fd1498Szrj diffvar, NOP_EXPR,
794638fd1498Szrj diff, tf_warning_or_error));
794738fd1498Szrj diff = diffvar;
794838fd1498Szrj }
794938fd1498Szrj *pre_body = pop_stmt_list (*pre_body);
795038fd1498Szrj
795138fd1498Szrj cond = cp_build_binary_op (elocus,
795238fd1498Szrj TREE_CODE (cond), decl, diff,
795338fd1498Szrj tf_warning_or_error);
795438fd1498Szrj incr = build_modify_expr (elocus, decl, NULL_TREE, PLUS_EXPR,
795538fd1498Szrj elocus, incr, NULL_TREE);
795638fd1498Szrj
795738fd1498Szrj orig_body = *body;
795838fd1498Szrj *body = push_stmt_list ();
795938fd1498Szrj iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last);
796038fd1498Szrj iter_init = build_x_modify_expr (elocus,
796138fd1498Szrj iter, PLUS_EXPR, iter_init,
796238fd1498Szrj tf_warning_or_error);
796338fd1498Szrj if (iter_init != error_mark_node)
796438fd1498Szrj iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
796538fd1498Szrj finish_expr_stmt (iter_init);
796638fd1498Szrj finish_expr_stmt (build_x_modify_expr (elocus,
796738fd1498Szrj last, NOP_EXPR, decl,
796838fd1498Szrj tf_warning_or_error));
796938fd1498Szrj add_stmt (orig_body);
797038fd1498Szrj *body = pop_stmt_list (*body);
797138fd1498Szrj
797238fd1498Szrj if (c)
797338fd1498Szrj {
797438fd1498Szrj OMP_CLAUSE_LASTPRIVATE_STMT (c) = push_stmt_list ();
797538fd1498Szrj if (!ordered)
797638fd1498Szrj finish_expr_stmt (iter_incr);
797738fd1498Szrj else
797838fd1498Szrj {
797938fd1498Szrj iter_init = decl;
798038fd1498Szrj if (i < collapse && collapse > 1 && !error_operand_p (iter_incr))
798138fd1498Szrj iter_init = build2 (PLUS_EXPR, TREE_TYPE (diff),
798238fd1498Szrj iter_init, iter_incr);
798338fd1498Szrj iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), iter_init, last);
798438fd1498Szrj iter_init = build_x_modify_expr (elocus,
798538fd1498Szrj iter, PLUS_EXPR, iter_init,
798638fd1498Szrj tf_warning_or_error);
798738fd1498Szrj if (iter_init != error_mark_node)
798838fd1498Szrj iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
798938fd1498Szrj finish_expr_stmt (iter_init);
799038fd1498Szrj }
799138fd1498Szrj OMP_CLAUSE_LASTPRIVATE_STMT (c)
799238fd1498Szrj = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
799338fd1498Szrj }
799438fd1498Szrj
799538fd1498Szrj TREE_VEC_ELT (declv, i) = decl;
799638fd1498Szrj TREE_VEC_ELT (initv, i) = init;
799738fd1498Szrj TREE_VEC_ELT (condv, i) = cond;
799838fd1498Szrj TREE_VEC_ELT (incrv, i) = incr;
799938fd1498Szrj *lastp = last;
800038fd1498Szrj
800138fd1498Szrj return false;
800238fd1498Szrj }
800338fd1498Szrj
800438fd1498Szrj /* Build and validate an OMP_FOR statement. CLAUSES, BODY, COND, INCR
800538fd1498Szrj are directly for their associated operands in the statement. DECL
800638fd1498Szrj and INIT are a combo; if DECL is NULL then INIT ought to be a
800738fd1498Szrj MODIFY_EXPR, and the DECL should be extracted. PRE_BODY are
800838fd1498Szrj optional statements that need to go before the loop into its
800938fd1498Szrj sk_omp scope. */
801038fd1498Szrj
801138fd1498Szrj tree
finish_omp_for(location_t locus,enum tree_code code,tree declv,tree orig_declv,tree initv,tree condv,tree incrv,tree body,tree pre_body,vec<tree> * orig_inits,tree clauses)801238fd1498Szrj finish_omp_for (location_t locus, enum tree_code code, tree declv,
801338fd1498Szrj tree orig_declv, tree initv, tree condv, tree incrv,
801438fd1498Szrj tree body, tree pre_body, vec<tree> *orig_inits, tree clauses)
801538fd1498Szrj {
801638fd1498Szrj tree omp_for = NULL, orig_incr = NULL;
801738fd1498Szrj tree decl = NULL, init, cond, incr;
801838fd1498Szrj tree last = NULL_TREE;
801938fd1498Szrj location_t elocus;
802038fd1498Szrj int i;
802138fd1498Szrj int collapse = 1;
802238fd1498Szrj int ordered = 0;
802338fd1498Szrj
802438fd1498Szrj gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
802538fd1498Szrj gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
802638fd1498Szrj gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
802738fd1498Szrj if (TREE_VEC_LENGTH (declv) > 1)
802838fd1498Szrj {
802938fd1498Szrj tree c;
803038fd1498Szrj
803138fd1498Szrj c = omp_find_clause (clauses, OMP_CLAUSE_TILE);
803238fd1498Szrj if (c)
803338fd1498Szrj collapse = list_length (OMP_CLAUSE_TILE_LIST (c));
803438fd1498Szrj else
803538fd1498Szrj {
803638fd1498Szrj c = omp_find_clause (clauses, OMP_CLAUSE_COLLAPSE);
803738fd1498Szrj if (c)
803838fd1498Szrj collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
803938fd1498Szrj if (collapse != TREE_VEC_LENGTH (declv))
804038fd1498Szrj ordered = TREE_VEC_LENGTH (declv);
804138fd1498Szrj }
804238fd1498Szrj }
804338fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
804438fd1498Szrj {
804538fd1498Szrj decl = TREE_VEC_ELT (declv, i);
804638fd1498Szrj init = TREE_VEC_ELT (initv, i);
804738fd1498Szrj cond = TREE_VEC_ELT (condv, i);
804838fd1498Szrj incr = TREE_VEC_ELT (incrv, i);
804938fd1498Szrj elocus = locus;
805038fd1498Szrj
805138fd1498Szrj if (decl == NULL)
805238fd1498Szrj {
805338fd1498Szrj if (init != NULL)
805438fd1498Szrj switch (TREE_CODE (init))
805538fd1498Szrj {
805638fd1498Szrj case MODIFY_EXPR:
805738fd1498Szrj decl = TREE_OPERAND (init, 0);
805838fd1498Szrj init = TREE_OPERAND (init, 1);
805938fd1498Szrj break;
806038fd1498Szrj case MODOP_EXPR:
806138fd1498Szrj if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
806238fd1498Szrj {
806338fd1498Szrj decl = TREE_OPERAND (init, 0);
806438fd1498Szrj init = TREE_OPERAND (init, 2);
806538fd1498Szrj }
806638fd1498Szrj break;
806738fd1498Szrj default:
806838fd1498Szrj break;
806938fd1498Szrj }
807038fd1498Szrj
807138fd1498Szrj if (decl == NULL)
807238fd1498Szrj {
807338fd1498Szrj error_at (locus,
807438fd1498Szrj "expected iteration declaration or initialization");
807538fd1498Szrj return NULL;
807638fd1498Szrj }
807738fd1498Szrj }
807838fd1498Szrj
807938fd1498Szrj if (init && EXPR_HAS_LOCATION (init))
808038fd1498Szrj elocus = EXPR_LOCATION (init);
808138fd1498Szrj
808238fd1498Szrj if (cond == NULL)
808338fd1498Szrj {
808438fd1498Szrj error_at (elocus, "missing controlling predicate");
808538fd1498Szrj return NULL;
808638fd1498Szrj }
808738fd1498Szrj
808838fd1498Szrj if (incr == NULL)
808938fd1498Szrj {
809038fd1498Szrj error_at (elocus, "missing increment expression");
809138fd1498Szrj return NULL;
809238fd1498Szrj }
809338fd1498Szrj
809438fd1498Szrj TREE_VEC_ELT (declv, i) = decl;
809538fd1498Szrj TREE_VEC_ELT (initv, i) = init;
809638fd1498Szrj }
809738fd1498Szrj
809838fd1498Szrj if (orig_inits)
809938fd1498Szrj {
810038fd1498Szrj bool fail = false;
810138fd1498Szrj tree orig_init;
810238fd1498Szrj FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
810338fd1498Szrj if (orig_init
810438fd1498Szrj && !c_omp_check_loop_iv_exprs (locus, declv,
810538fd1498Szrj TREE_VEC_ELT (declv, i), orig_init,
810638fd1498Szrj NULL_TREE, cp_walk_subtrees))
810738fd1498Szrj fail = true;
810838fd1498Szrj if (fail)
810938fd1498Szrj return NULL;
811038fd1498Szrj }
811138fd1498Szrj
811238fd1498Szrj if (dependent_omp_for_p (declv, initv, condv, incrv))
811338fd1498Szrj {
811438fd1498Szrj tree stmt;
811538fd1498Szrj
811638fd1498Szrj stmt = make_node (code);
811738fd1498Szrj
811838fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
811938fd1498Szrj {
812038fd1498Szrj /* This is really just a place-holder. We'll be decomposing this
812138fd1498Szrj again and going through the cp_build_modify_expr path below when
812238fd1498Szrj we instantiate the thing. */
812338fd1498Szrj TREE_VEC_ELT (initv, i)
812438fd1498Szrj = build2 (MODIFY_EXPR, void_type_node, TREE_VEC_ELT (declv, i),
812538fd1498Szrj TREE_VEC_ELT (initv, i));
812638fd1498Szrj }
812738fd1498Szrj
812838fd1498Szrj TREE_TYPE (stmt) = void_type_node;
812938fd1498Szrj OMP_FOR_INIT (stmt) = initv;
813038fd1498Szrj OMP_FOR_COND (stmt) = condv;
813138fd1498Szrj OMP_FOR_INCR (stmt) = incrv;
813238fd1498Szrj OMP_FOR_BODY (stmt) = body;
813338fd1498Szrj OMP_FOR_PRE_BODY (stmt) = pre_body;
813438fd1498Szrj OMP_FOR_CLAUSES (stmt) = clauses;
813538fd1498Szrj
813638fd1498Szrj SET_EXPR_LOCATION (stmt, locus);
813738fd1498Szrj return add_stmt (stmt);
813838fd1498Szrj }
813938fd1498Szrj
814038fd1498Szrj if (!orig_declv)
814138fd1498Szrj orig_declv = copy_node (declv);
814238fd1498Szrj
814338fd1498Szrj if (processing_template_decl)
814438fd1498Szrj orig_incr = make_tree_vec (TREE_VEC_LENGTH (incrv));
814538fd1498Szrj
814638fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (declv); )
814738fd1498Szrj {
814838fd1498Szrj decl = TREE_VEC_ELT (declv, i);
814938fd1498Szrj init = TREE_VEC_ELT (initv, i);
815038fd1498Szrj cond = TREE_VEC_ELT (condv, i);
815138fd1498Szrj incr = TREE_VEC_ELT (incrv, i);
815238fd1498Szrj if (orig_incr)
815338fd1498Szrj TREE_VEC_ELT (orig_incr, i) = incr;
815438fd1498Szrj elocus = locus;
815538fd1498Szrj
815638fd1498Szrj if (init && EXPR_HAS_LOCATION (init))
815738fd1498Szrj elocus = EXPR_LOCATION (init);
815838fd1498Szrj
815938fd1498Szrj if (!DECL_P (decl))
816038fd1498Szrj {
816138fd1498Szrj error_at (elocus, "expected iteration declaration or initialization");
816238fd1498Szrj return NULL;
816338fd1498Szrj }
816438fd1498Szrj
816538fd1498Szrj if (incr && TREE_CODE (incr) == MODOP_EXPR)
816638fd1498Szrj {
816738fd1498Szrj if (orig_incr)
816838fd1498Szrj TREE_VEC_ELT (orig_incr, i) = incr;
816938fd1498Szrj incr = cp_build_modify_expr (elocus, TREE_OPERAND (incr, 0),
817038fd1498Szrj TREE_CODE (TREE_OPERAND (incr, 1)),
817138fd1498Szrj TREE_OPERAND (incr, 2),
817238fd1498Szrj tf_warning_or_error);
817338fd1498Szrj }
817438fd1498Szrj
817538fd1498Szrj if (CLASS_TYPE_P (TREE_TYPE (decl)))
817638fd1498Szrj {
817738fd1498Szrj if (code == OMP_SIMD)
817838fd1498Szrj {
817938fd1498Szrj error_at (elocus, "%<#pragma omp simd%> used with class "
818038fd1498Szrj "iteration variable %qE", decl);
818138fd1498Szrj return NULL;
818238fd1498Szrj }
818338fd1498Szrj if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv,
818438fd1498Szrj initv, condv, incrv, &body,
818538fd1498Szrj &pre_body, clauses, &last,
818638fd1498Szrj collapse, ordered))
818738fd1498Szrj return NULL;
818838fd1498Szrj continue;
818938fd1498Szrj }
819038fd1498Szrj
819138fd1498Szrj if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
819238fd1498Szrj && !TYPE_PTR_P (TREE_TYPE (decl)))
819338fd1498Szrj {
819438fd1498Szrj error_at (elocus, "invalid type for iteration variable %qE", decl);
819538fd1498Szrj return NULL;
819638fd1498Szrj }
819738fd1498Szrj
819838fd1498Szrj if (!processing_template_decl)
819938fd1498Szrj {
820038fd1498Szrj init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
820138fd1498Szrj init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init,
820238fd1498Szrj tf_warning_or_error);
820338fd1498Szrj }
820438fd1498Szrj else
820538fd1498Szrj init = build2 (MODIFY_EXPR, void_type_node, decl, init);
820638fd1498Szrj if (cond
820738fd1498Szrj && TREE_SIDE_EFFECTS (cond)
820838fd1498Szrj && COMPARISON_CLASS_P (cond)
820938fd1498Szrj && !processing_template_decl)
821038fd1498Szrj {
821138fd1498Szrj tree t = TREE_OPERAND (cond, 0);
821238fd1498Szrj if (TREE_SIDE_EFFECTS (t)
821338fd1498Szrj && t != decl
821438fd1498Szrj && (TREE_CODE (t) != NOP_EXPR
821538fd1498Szrj || TREE_OPERAND (t, 0) != decl))
821638fd1498Szrj TREE_OPERAND (cond, 0)
821738fd1498Szrj = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
821838fd1498Szrj
821938fd1498Szrj t = TREE_OPERAND (cond, 1);
822038fd1498Szrj if (TREE_SIDE_EFFECTS (t)
822138fd1498Szrj && t != decl
822238fd1498Szrj && (TREE_CODE (t) != NOP_EXPR
822338fd1498Szrj || TREE_OPERAND (t, 0) != decl))
822438fd1498Szrj TREE_OPERAND (cond, 1)
822538fd1498Szrj = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
822638fd1498Szrj }
822738fd1498Szrj if (decl == error_mark_node || init == error_mark_node)
822838fd1498Szrj return NULL;
822938fd1498Szrj
823038fd1498Szrj TREE_VEC_ELT (declv, i) = decl;
823138fd1498Szrj TREE_VEC_ELT (initv, i) = init;
823238fd1498Szrj TREE_VEC_ELT (condv, i) = cond;
823338fd1498Szrj TREE_VEC_ELT (incrv, i) = incr;
823438fd1498Szrj i++;
823538fd1498Szrj }
823638fd1498Szrj
823738fd1498Szrj if (IS_EMPTY_STMT (pre_body))
823838fd1498Szrj pre_body = NULL;
823938fd1498Szrj
824038fd1498Szrj omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
824138fd1498Szrj incrv, body, pre_body);
824238fd1498Szrj
824338fd1498Szrj /* Check for iterators appearing in lb, b or incr expressions. */
824438fd1498Szrj if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees))
824538fd1498Szrj omp_for = NULL_TREE;
824638fd1498Szrj
824738fd1498Szrj if (omp_for == NULL)
824838fd1498Szrj {
824938fd1498Szrj return NULL;
825038fd1498Szrj }
825138fd1498Szrj
825238fd1498Szrj add_stmt (omp_for);
825338fd1498Szrj
825438fd1498Szrj for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
825538fd1498Szrj {
825638fd1498Szrj decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i), 0);
825738fd1498Szrj incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i);
825838fd1498Szrj
825938fd1498Szrj if (TREE_CODE (incr) != MODIFY_EXPR)
826038fd1498Szrj continue;
826138fd1498Szrj
826238fd1498Szrj if (TREE_SIDE_EFFECTS (TREE_OPERAND (incr, 1))
826338fd1498Szrj && BINARY_CLASS_P (TREE_OPERAND (incr, 1))
826438fd1498Szrj && !processing_template_decl)
826538fd1498Szrj {
826638fd1498Szrj tree t = TREE_OPERAND (TREE_OPERAND (incr, 1), 0);
826738fd1498Szrj if (TREE_SIDE_EFFECTS (t)
826838fd1498Szrj && t != decl
826938fd1498Szrj && (TREE_CODE (t) != NOP_EXPR
827038fd1498Szrj || TREE_OPERAND (t, 0) != decl))
827138fd1498Szrj TREE_OPERAND (TREE_OPERAND (incr, 1), 0)
827238fd1498Szrj = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
827338fd1498Szrj
827438fd1498Szrj t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1);
827538fd1498Szrj if (TREE_SIDE_EFFECTS (t)
827638fd1498Szrj && t != decl
827738fd1498Szrj && (TREE_CODE (t) != NOP_EXPR
827838fd1498Szrj || TREE_OPERAND (t, 0) != decl))
827938fd1498Szrj TREE_OPERAND (TREE_OPERAND (incr, 1), 1)
828038fd1498Szrj = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
828138fd1498Szrj }
828238fd1498Szrj
828338fd1498Szrj if (orig_incr)
828438fd1498Szrj TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i) = TREE_VEC_ELT (orig_incr, i);
828538fd1498Szrj }
828638fd1498Szrj OMP_FOR_CLAUSES (omp_for) = clauses;
828738fd1498Szrj
828838fd1498Szrj /* For simd loops with non-static data member iterators, we could have added
828938fd1498Szrj OMP_CLAUSE_LINEAR clauses without OMP_CLAUSE_LINEAR_STEP. As we know the
829038fd1498Szrj step at this point, fill it in. */
829138fd1498Szrj if (code == OMP_SIMD && !processing_template_decl
829238fd1498Szrj && TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)) == 1)
829338fd1498Szrj for (tree c = omp_find_clause (clauses, OMP_CLAUSE_LINEAR); c;
829438fd1498Szrj c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_LINEAR))
829538fd1498Szrj if (OMP_CLAUSE_LINEAR_STEP (c) == NULL_TREE)
829638fd1498Szrj {
829738fd1498Szrj decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0), 0);
829838fd1498Szrj gcc_assert (decl == OMP_CLAUSE_DECL (c));
829938fd1498Szrj incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0);
830038fd1498Szrj tree step, stept;
830138fd1498Szrj switch (TREE_CODE (incr))
830238fd1498Szrj {
830338fd1498Szrj case PREINCREMENT_EXPR:
830438fd1498Szrj case POSTINCREMENT_EXPR:
830538fd1498Szrj /* c_omp_for_incr_canonicalize_ptr() should have been
830638fd1498Szrj called to massage things appropriately. */
830738fd1498Szrj gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
830838fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1);
830938fd1498Szrj break;
831038fd1498Szrj case PREDECREMENT_EXPR:
831138fd1498Szrj case POSTDECREMENT_EXPR:
831238fd1498Szrj /* c_omp_for_incr_canonicalize_ptr() should have been
831338fd1498Szrj called to massage things appropriately. */
831438fd1498Szrj gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
831538fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c)
831638fd1498Szrj = build_int_cst (TREE_TYPE (decl), -1);
831738fd1498Szrj break;
831838fd1498Szrj case MODIFY_EXPR:
831938fd1498Szrj gcc_assert (TREE_OPERAND (incr, 0) == decl);
832038fd1498Szrj incr = TREE_OPERAND (incr, 1);
832138fd1498Szrj switch (TREE_CODE (incr))
832238fd1498Szrj {
832338fd1498Szrj case PLUS_EXPR:
832438fd1498Szrj if (TREE_OPERAND (incr, 1) == decl)
832538fd1498Szrj step = TREE_OPERAND (incr, 0);
832638fd1498Szrj else
832738fd1498Szrj step = TREE_OPERAND (incr, 1);
832838fd1498Szrj break;
832938fd1498Szrj case MINUS_EXPR:
833038fd1498Szrj case POINTER_PLUS_EXPR:
833138fd1498Szrj gcc_assert (TREE_OPERAND (incr, 0) == decl);
833238fd1498Szrj step = TREE_OPERAND (incr, 1);
833338fd1498Szrj break;
833438fd1498Szrj default:
833538fd1498Szrj gcc_unreachable ();
833638fd1498Szrj }
833738fd1498Szrj stept = TREE_TYPE (decl);
833838fd1498Szrj if (POINTER_TYPE_P (stept))
833938fd1498Szrj stept = sizetype;
834038fd1498Szrj step = fold_convert (stept, step);
834138fd1498Szrj if (TREE_CODE (incr) == MINUS_EXPR)
834238fd1498Szrj step = fold_build1 (NEGATE_EXPR, stept, step);
834338fd1498Szrj OMP_CLAUSE_LINEAR_STEP (c) = step;
834438fd1498Szrj break;
834538fd1498Szrj default:
834638fd1498Szrj gcc_unreachable ();
834738fd1498Szrj }
834838fd1498Szrj }
834938fd1498Szrj
835038fd1498Szrj return omp_for;
835138fd1498Szrj }
835238fd1498Szrj
835338fd1498Szrj void
finish_omp_atomic(enum tree_code code,enum tree_code opcode,tree lhs,tree rhs,tree v,tree lhs1,tree rhs1,bool seq_cst)835438fd1498Szrj finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
835538fd1498Szrj tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
835638fd1498Szrj {
835738fd1498Szrj tree orig_lhs;
835838fd1498Szrj tree orig_rhs;
835938fd1498Szrj tree orig_v;
836038fd1498Szrj tree orig_lhs1;
836138fd1498Szrj tree orig_rhs1;
836238fd1498Szrj bool dependent_p;
836338fd1498Szrj tree stmt;
836438fd1498Szrj
836538fd1498Szrj orig_lhs = lhs;
836638fd1498Szrj orig_rhs = rhs;
836738fd1498Szrj orig_v = v;
836838fd1498Szrj orig_lhs1 = lhs1;
836938fd1498Szrj orig_rhs1 = rhs1;
837038fd1498Szrj dependent_p = false;
837138fd1498Szrj stmt = NULL_TREE;
837238fd1498Szrj
837338fd1498Szrj /* Even in a template, we can detect invalid uses of the atomic
837438fd1498Szrj pragma if neither LHS nor RHS is type-dependent. */
837538fd1498Szrj if (processing_template_decl)
837638fd1498Szrj {
837738fd1498Szrj dependent_p = (type_dependent_expression_p (lhs)
837838fd1498Szrj || (rhs && type_dependent_expression_p (rhs))
837938fd1498Szrj || (v && type_dependent_expression_p (v))
838038fd1498Szrj || (lhs1 && type_dependent_expression_p (lhs1))
838138fd1498Szrj || (rhs1 && type_dependent_expression_p (rhs1)));
838238fd1498Szrj if (!dependent_p)
838338fd1498Szrj {
838438fd1498Szrj lhs = build_non_dependent_expr (lhs);
838538fd1498Szrj if (rhs)
838638fd1498Szrj rhs = build_non_dependent_expr (rhs);
838738fd1498Szrj if (v)
838838fd1498Szrj v = build_non_dependent_expr (v);
838938fd1498Szrj if (lhs1)
839038fd1498Szrj lhs1 = build_non_dependent_expr (lhs1);
839138fd1498Szrj if (rhs1)
839238fd1498Szrj rhs1 = build_non_dependent_expr (rhs1);
839338fd1498Szrj }
839438fd1498Szrj }
839538fd1498Szrj if (!dependent_p)
839638fd1498Szrj {
839738fd1498Szrj bool swapped = false;
839838fd1498Szrj if (rhs1 && cp_tree_equal (lhs, rhs))
839938fd1498Szrj {
840038fd1498Szrj std::swap (rhs, rhs1);
840138fd1498Szrj swapped = !commutative_tree_code (opcode);
840238fd1498Szrj }
840338fd1498Szrj if (rhs1 && !cp_tree_equal (lhs, rhs1))
840438fd1498Szrj {
840538fd1498Szrj if (code == OMP_ATOMIC)
840638fd1498Szrj error ("%<#pragma omp atomic update%> uses two different "
840738fd1498Szrj "expressions for memory");
840838fd1498Szrj else
840938fd1498Szrj error ("%<#pragma omp atomic capture%> uses two different "
841038fd1498Szrj "expressions for memory");
841138fd1498Szrj return;
841238fd1498Szrj }
841338fd1498Szrj if (lhs1 && !cp_tree_equal (lhs, lhs1))
841438fd1498Szrj {
841538fd1498Szrj if (code == OMP_ATOMIC)
841638fd1498Szrj error ("%<#pragma omp atomic update%> uses two different "
841738fd1498Szrj "expressions for memory");
841838fd1498Szrj else
841938fd1498Szrj error ("%<#pragma omp atomic capture%> uses two different "
842038fd1498Szrj "expressions for memory");
842138fd1498Szrj return;
842238fd1498Szrj }
842338fd1498Szrj stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
842438fd1498Szrj v, lhs1, rhs1, swapped, seq_cst,
842538fd1498Szrj processing_template_decl != 0);
842638fd1498Szrj if (stmt == error_mark_node)
842738fd1498Szrj return;
842838fd1498Szrj }
842938fd1498Szrj if (processing_template_decl)
843038fd1498Szrj {
843138fd1498Szrj if (code == OMP_ATOMIC_READ)
843238fd1498Szrj {
843338fd1498Szrj stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
843438fd1498Szrj OMP_ATOMIC_READ, orig_lhs);
843538fd1498Szrj OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
843638fd1498Szrj stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
843738fd1498Szrj }
843838fd1498Szrj else
843938fd1498Szrj {
844038fd1498Szrj if (opcode == NOP_EXPR)
844138fd1498Szrj stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
844238fd1498Szrj else
844338fd1498Szrj stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
844438fd1498Szrj if (orig_rhs1)
844538fd1498Szrj stmt = build_min_nt_loc (EXPR_LOCATION (orig_rhs1),
844638fd1498Szrj COMPOUND_EXPR, orig_rhs1, stmt);
844738fd1498Szrj if (code != OMP_ATOMIC)
844838fd1498Szrj {
844938fd1498Szrj stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
845038fd1498Szrj code, orig_lhs1, stmt);
845138fd1498Szrj OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
845238fd1498Szrj stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
845338fd1498Szrj }
845438fd1498Szrj }
845538fd1498Szrj stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
845638fd1498Szrj OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
845738fd1498Szrj }
845838fd1498Szrj finish_expr_stmt (stmt);
845938fd1498Szrj }
846038fd1498Szrj
846138fd1498Szrj void
finish_omp_barrier(void)846238fd1498Szrj finish_omp_barrier (void)
846338fd1498Szrj {
846438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
846538fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
846638fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
846738fd1498Szrj release_tree_vector (vec);
846838fd1498Szrj finish_expr_stmt (stmt);
846938fd1498Szrj }
847038fd1498Szrj
847138fd1498Szrj void
finish_omp_flush(void)847238fd1498Szrj finish_omp_flush (void)
847338fd1498Szrj {
847438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
847538fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
847638fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
847738fd1498Szrj release_tree_vector (vec);
847838fd1498Szrj finish_expr_stmt (stmt);
847938fd1498Szrj }
848038fd1498Szrj
848138fd1498Szrj void
finish_omp_taskwait(void)848238fd1498Szrj finish_omp_taskwait (void)
848338fd1498Szrj {
848438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
848538fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
848638fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
848738fd1498Szrj release_tree_vector (vec);
848838fd1498Szrj finish_expr_stmt (stmt);
848938fd1498Szrj }
849038fd1498Szrj
849138fd1498Szrj void
finish_omp_taskyield(void)849238fd1498Szrj finish_omp_taskyield (void)
849338fd1498Szrj {
849438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
849538fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
849638fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
849738fd1498Szrj release_tree_vector (vec);
849838fd1498Szrj finish_expr_stmt (stmt);
849938fd1498Szrj }
850038fd1498Szrj
850138fd1498Szrj void
finish_omp_cancel(tree clauses)850238fd1498Szrj finish_omp_cancel (tree clauses)
850338fd1498Szrj {
850438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
850538fd1498Szrj int mask = 0;
850638fd1498Szrj if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL))
850738fd1498Szrj mask = 1;
850838fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_FOR))
850938fd1498Szrj mask = 2;
851038fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS))
851138fd1498Szrj mask = 4;
851238fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP))
851338fd1498Szrj mask = 8;
851438fd1498Szrj else
851538fd1498Szrj {
851638fd1498Szrj error ("%<#pragma omp cancel%> must specify one of "
851738fd1498Szrj "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
851838fd1498Szrj return;
851938fd1498Szrj }
852038fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
852138fd1498Szrj tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
852238fd1498Szrj if (ifc != NULL_TREE)
852338fd1498Szrj {
852458e805e6Szrj if (!processing_template_decl)
852558e805e6Szrj ifc = maybe_convert_cond (OMP_CLAUSE_IF_EXPR (ifc));
852658e805e6Szrj else
852758e805e6Szrj ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
852858e805e6Szrj OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK,
852958e805e6Szrj integer_zero_node, ERROR_MARK,
853058e805e6Szrj NULL, tf_warning_or_error);
853138fd1498Szrj }
853238fd1498Szrj else
853338fd1498Szrj ifc = boolean_true_node;
853438fd1498Szrj vec->quick_push (build_int_cst (integer_type_node, mask));
853538fd1498Szrj vec->quick_push (ifc);
853638fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
853738fd1498Szrj release_tree_vector (vec);
853838fd1498Szrj finish_expr_stmt (stmt);
853938fd1498Szrj }
854038fd1498Szrj
854138fd1498Szrj void
finish_omp_cancellation_point(tree clauses)854238fd1498Szrj finish_omp_cancellation_point (tree clauses)
854338fd1498Szrj {
854438fd1498Szrj tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
854538fd1498Szrj int mask = 0;
854638fd1498Szrj if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL))
854738fd1498Szrj mask = 1;
854838fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_FOR))
854938fd1498Szrj mask = 2;
855038fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS))
855138fd1498Szrj mask = 4;
855238fd1498Szrj else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP))
855338fd1498Szrj mask = 8;
855438fd1498Szrj else
855538fd1498Szrj {
855638fd1498Szrj error ("%<#pragma omp cancellation point%> must specify one of "
855738fd1498Szrj "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
855838fd1498Szrj return;
855938fd1498Szrj }
856038fd1498Szrj vec<tree, va_gc> *vec
856138fd1498Szrj = make_tree_vector_single (build_int_cst (integer_type_node, mask));
856238fd1498Szrj tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
856338fd1498Szrj release_tree_vector (vec);
856438fd1498Szrj finish_expr_stmt (stmt);
856538fd1498Szrj }
856638fd1498Szrj
856738fd1498Szrj /* Begin a __transaction_atomic or __transaction_relaxed statement.
856838fd1498Szrj If PCOMPOUND is non-null, this is for a function-transaction-block, and we
856938fd1498Szrj should create an extra compound stmt. */
857038fd1498Szrj
857138fd1498Szrj tree
begin_transaction_stmt(location_t loc,tree * pcompound,int flags)857238fd1498Szrj begin_transaction_stmt (location_t loc, tree *pcompound, int flags)
857338fd1498Szrj {
857438fd1498Szrj tree r;
857538fd1498Szrj
857638fd1498Szrj if (pcompound)
857738fd1498Szrj *pcompound = begin_compound_stmt (0);
857838fd1498Szrj
857938fd1498Szrj r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE);
858038fd1498Szrj
858138fd1498Szrj /* Only add the statement to the function if support enabled. */
858238fd1498Szrj if (flag_tm)
858338fd1498Szrj add_stmt (r);
858438fd1498Szrj else
858538fd1498Szrj error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0
858638fd1498Szrj ? G_("%<__transaction_relaxed%> without "
858738fd1498Szrj "transactional memory support enabled")
858838fd1498Szrj : G_("%<__transaction_atomic%> without "
858938fd1498Szrj "transactional memory support enabled")));
859038fd1498Szrj
859138fd1498Szrj TRANSACTION_EXPR_BODY (r) = push_stmt_list ();
859238fd1498Szrj TREE_SIDE_EFFECTS (r) = 1;
859338fd1498Szrj return r;
859438fd1498Szrj }
859538fd1498Szrj
859638fd1498Szrj /* End a __transaction_atomic or __transaction_relaxed statement.
859738fd1498Szrj If COMPOUND_STMT is non-null, this is for a function-transaction-block,
859838fd1498Szrj and we should end the compound. If NOEX is non-NULL, we wrap the body in
859938fd1498Szrj a MUST_NOT_THROW_EXPR with NOEX as condition. */
860038fd1498Szrj
860138fd1498Szrj void
finish_transaction_stmt(tree stmt,tree compound_stmt,int flags,tree noex)860238fd1498Szrj finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex)
860338fd1498Szrj {
860438fd1498Szrj TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt));
860538fd1498Szrj TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0;
860638fd1498Szrj TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0;
860738fd1498Szrj TRANSACTION_EXPR_IS_STMT (stmt) = 1;
860838fd1498Szrj
860938fd1498Szrj /* noexcept specifications are not allowed for function transactions. */
861038fd1498Szrj gcc_assert (!(noex && compound_stmt));
861138fd1498Szrj if (noex)
861238fd1498Szrj {
861338fd1498Szrj tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt),
861438fd1498Szrj noex);
861538fd1498Szrj protected_set_expr_location
861638fd1498Szrj (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt)));
861738fd1498Szrj TREE_SIDE_EFFECTS (body) = 1;
861838fd1498Szrj TRANSACTION_EXPR_BODY (stmt) = body;
861938fd1498Szrj }
862038fd1498Szrj
862138fd1498Szrj if (compound_stmt)
862238fd1498Szrj finish_compound_stmt (compound_stmt);
862338fd1498Szrj }
862438fd1498Szrj
862538fd1498Szrj /* Build a __transaction_atomic or __transaction_relaxed expression. If
862638fd1498Szrj NOEX is non-NULL, we wrap the body in a MUST_NOT_THROW_EXPR with NOEX as
862738fd1498Szrj condition. */
862838fd1498Szrj
862938fd1498Szrj tree
build_transaction_expr(location_t loc,tree expr,int flags,tree noex)863038fd1498Szrj build_transaction_expr (location_t loc, tree expr, int flags, tree noex)
863138fd1498Szrj {
863238fd1498Szrj tree ret;
863338fd1498Szrj if (noex)
863438fd1498Szrj {
863538fd1498Szrj expr = build_must_not_throw_expr (expr, noex);
863638fd1498Szrj protected_set_expr_location (expr, loc);
863738fd1498Szrj TREE_SIDE_EFFECTS (expr) = 1;
863838fd1498Szrj }
863938fd1498Szrj ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr);
864038fd1498Szrj if (flags & TM_STMT_ATTR_RELAXED)
864138fd1498Szrj TRANSACTION_EXPR_RELAXED (ret) = 1;
864238fd1498Szrj TREE_SIDE_EFFECTS (ret) = 1;
864338fd1498Szrj SET_EXPR_LOCATION (ret, loc);
864438fd1498Szrj return ret;
864538fd1498Szrj }
864638fd1498Szrj
864738fd1498Szrj void
init_cp_semantics(void)864838fd1498Szrj init_cp_semantics (void)
864938fd1498Szrj {
865038fd1498Szrj }
865138fd1498Szrj
865238fd1498Szrj /* Build a STATIC_ASSERT for a static assertion with the condition
865338fd1498Szrj CONDITION and the message text MESSAGE. LOCATION is the location
865438fd1498Szrj of the static assertion in the source code. When MEMBER_P, this
865538fd1498Szrj static assertion is a member of a class. */
865638fd1498Szrj void
finish_static_assert(tree condition,tree message,location_t location,bool member_p)865738fd1498Szrj finish_static_assert (tree condition, tree message, location_t location,
865838fd1498Szrj bool member_p)
865938fd1498Szrj {
866038fd1498Szrj tsubst_flags_t complain = tf_warning_or_error;
866138fd1498Szrj
866238fd1498Szrj if (message == NULL_TREE
866338fd1498Szrj || message == error_mark_node
866438fd1498Szrj || condition == NULL_TREE
866538fd1498Szrj || condition == error_mark_node)
866638fd1498Szrj return;
866738fd1498Szrj
866838fd1498Szrj if (check_for_bare_parameter_packs (condition))
866938fd1498Szrj condition = error_mark_node;
867038fd1498Szrj
867138fd1498Szrj if (instantiation_dependent_expression_p (condition))
867238fd1498Szrj {
867338fd1498Szrj /* We're in a template; build a STATIC_ASSERT and put it in
867438fd1498Szrj the right place. */
867538fd1498Szrj tree assertion;
867638fd1498Szrj
867738fd1498Szrj assertion = make_node (STATIC_ASSERT);
867838fd1498Szrj STATIC_ASSERT_CONDITION (assertion) = condition;
867938fd1498Szrj STATIC_ASSERT_MESSAGE (assertion) = message;
868038fd1498Szrj STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
868138fd1498Szrj
868238fd1498Szrj if (member_p)
868338fd1498Szrj maybe_add_class_template_decl_list (current_class_type,
868438fd1498Szrj assertion,
868538fd1498Szrj /*friend_p=*/0);
868638fd1498Szrj else
868738fd1498Szrj add_stmt (assertion);
868838fd1498Szrj
868938fd1498Szrj return;
869038fd1498Szrj }
869138fd1498Szrj
869238fd1498Szrj /* Fold the expression and convert it to a boolean value. */
869338fd1498Szrj condition = perform_implicit_conversion_flags (boolean_type_node, condition,
869438fd1498Szrj complain, LOOKUP_NORMAL);
869538fd1498Szrj condition = fold_non_dependent_expr (condition);
869638fd1498Szrj
869738fd1498Szrj if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
869838fd1498Szrj /* Do nothing; the condition is satisfied. */
869938fd1498Szrj ;
870038fd1498Szrj else
870138fd1498Szrj {
870238fd1498Szrj location_t saved_loc = input_location;
870338fd1498Szrj
870438fd1498Szrj input_location = location;
870538fd1498Szrj if (TREE_CODE (condition) == INTEGER_CST
870638fd1498Szrj && integer_zerop (condition))
870738fd1498Szrj {
870838fd1498Szrj int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
870938fd1498Szrj (TREE_TYPE (TREE_TYPE (message))));
871038fd1498Szrj int len = TREE_STRING_LENGTH (message) / sz - 1;
871138fd1498Szrj /* Report the error. */
871238fd1498Szrj if (len == 0)
871338fd1498Szrj error ("static assertion failed");
871438fd1498Szrj else
871538fd1498Szrj error ("static assertion failed: %s",
871638fd1498Szrj TREE_STRING_POINTER (message));
871738fd1498Szrj }
871838fd1498Szrj else if (condition && condition != error_mark_node)
871938fd1498Szrj {
872038fd1498Szrj error ("non-constant condition for static assertion");
872138fd1498Szrj if (require_rvalue_constant_expression (condition))
872238fd1498Szrj cxx_constant_value (condition);
872338fd1498Szrj }
872438fd1498Szrj input_location = saved_loc;
872538fd1498Szrj }
872638fd1498Szrj }
872738fd1498Szrj
872838fd1498Szrj /* Implements the C++0x decltype keyword. Returns the type of EXPR,
872938fd1498Szrj suitable for use as a type-specifier.
873038fd1498Szrj
873138fd1498Szrj ID_EXPRESSION_OR_MEMBER_ACCESS_P is true when EXPR was parsed as an
873238fd1498Szrj id-expression or a class member access, FALSE when it was parsed as
873338fd1498Szrj a full expression. */
873438fd1498Szrj
873538fd1498Szrj tree
finish_decltype_type(tree expr,bool id_expression_or_member_access_p,tsubst_flags_t complain)873638fd1498Szrj finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
873738fd1498Szrj tsubst_flags_t complain)
873838fd1498Szrj {
873938fd1498Szrj tree type = NULL_TREE;
874038fd1498Szrj
874138fd1498Szrj if (!expr || error_operand_p (expr))
874238fd1498Szrj return error_mark_node;
874338fd1498Szrj
874438fd1498Szrj if (TYPE_P (expr)
874538fd1498Szrj || TREE_CODE (expr) == TYPE_DECL
874638fd1498Szrj || (TREE_CODE (expr) == BIT_NOT_EXPR
874738fd1498Szrj && TYPE_P (TREE_OPERAND (expr, 0))))
874838fd1498Szrj {
874938fd1498Szrj if (complain & tf_error)
875038fd1498Szrj error ("argument to decltype must be an expression");
875138fd1498Szrj return error_mark_node;
875238fd1498Szrj }
875338fd1498Szrj
875438fd1498Szrj /* Depending on the resolution of DR 1172, we may later need to distinguish
875538fd1498Szrj instantiation-dependent but not type-dependent expressions so that, say,
875638fd1498Szrj A<decltype(sizeof(T))>::U doesn't require 'typename'. */
875738fd1498Szrj if (instantiation_dependent_uneval_expression_p (expr))
875838fd1498Szrj {
875938fd1498Szrj type = cxx_make_type (DECLTYPE_TYPE);
876038fd1498Szrj DECLTYPE_TYPE_EXPR (type) = expr;
876138fd1498Szrj DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
876238fd1498Szrj = id_expression_or_member_access_p;
876338fd1498Szrj SET_TYPE_STRUCTURAL_EQUALITY (type);
876438fd1498Szrj
876538fd1498Szrj return type;
876638fd1498Szrj }
876738fd1498Szrj
876838fd1498Szrj /* The type denoted by decltype(e) is defined as follows: */
876938fd1498Szrj
877038fd1498Szrj expr = resolve_nondeduced_context (expr, complain);
877138fd1498Szrj
877238fd1498Szrj if (invalid_nonstatic_memfn_p (input_location, expr, complain))
877338fd1498Szrj return error_mark_node;
877438fd1498Szrj
877538fd1498Szrj if (type_unknown_p (expr))
877638fd1498Szrj {
877738fd1498Szrj if (complain & tf_error)
877838fd1498Szrj error ("decltype cannot resolve address of overloaded function");
877938fd1498Szrj return error_mark_node;
878038fd1498Szrj }
878138fd1498Szrj
878238fd1498Szrj /* To get the size of a static data member declared as an array of
878338fd1498Szrj unknown bound, we need to instantiate it. */
878438fd1498Szrj if (VAR_P (expr)
878538fd1498Szrj && VAR_HAD_UNKNOWN_BOUND (expr)
878638fd1498Szrj && DECL_TEMPLATE_INSTANTIATION (expr))
878738fd1498Szrj instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
878838fd1498Szrj
878938fd1498Szrj if (id_expression_or_member_access_p)
879038fd1498Szrj {
879138fd1498Szrj /* If e is an id-expression or a class member access (5.2.5
879238fd1498Szrj [expr.ref]), decltype(e) is defined as the type of the entity
879338fd1498Szrj named by e. If there is no such entity, or e names a set of
879438fd1498Szrj overloaded functions, the program is ill-formed. */
879538fd1498Szrj if (identifier_p (expr))
879638fd1498Szrj expr = lookup_name (expr);
879738fd1498Szrj
879838fd1498Szrj if (INDIRECT_REF_P (expr))
879938fd1498Szrj /* This can happen when the expression is, e.g., "a.b". Just
880038fd1498Szrj look at the underlying operand. */
880138fd1498Szrj expr = TREE_OPERAND (expr, 0);
880238fd1498Szrj
880338fd1498Szrj if (TREE_CODE (expr) == OFFSET_REF
880438fd1498Szrj || TREE_CODE (expr) == MEMBER_REF
880538fd1498Szrj || TREE_CODE (expr) == SCOPE_REF)
880638fd1498Szrj /* We're only interested in the field itself. If it is a
880738fd1498Szrj BASELINK, we will need to see through it in the next
880838fd1498Szrj step. */
880938fd1498Szrj expr = TREE_OPERAND (expr, 1);
881038fd1498Szrj
881138fd1498Szrj if (BASELINK_P (expr))
881238fd1498Szrj /* See through BASELINK nodes to the underlying function. */
881338fd1498Szrj expr = BASELINK_FUNCTIONS (expr);
881438fd1498Szrj
881538fd1498Szrj /* decltype of a decomposition name drops references in the tuple case
881638fd1498Szrj (unlike decltype of a normal variable) and keeps cv-qualifiers from
881738fd1498Szrj the containing object in the other cases (unlike decltype of a member
881838fd1498Szrj access expression). */
881938fd1498Szrj if (DECL_DECOMPOSITION_P (expr))
882038fd1498Szrj {
882138fd1498Szrj if (DECL_HAS_VALUE_EXPR_P (expr))
882238fd1498Szrj /* Expr is an array or struct subobject proxy, handle
882338fd1498Szrj bit-fields properly. */
882438fd1498Szrj return unlowered_expr_type (expr);
882538fd1498Szrj else
882638fd1498Szrj /* Expr is a reference variable for the tuple case. */
882738fd1498Szrj return lookup_decomp_type (expr);
882838fd1498Szrj }
882938fd1498Szrj
883038fd1498Szrj switch (TREE_CODE (expr))
883138fd1498Szrj {
883238fd1498Szrj case FIELD_DECL:
883338fd1498Szrj if (DECL_BIT_FIELD_TYPE (expr))
883438fd1498Szrj {
883538fd1498Szrj type = DECL_BIT_FIELD_TYPE (expr);
883638fd1498Szrj break;
883738fd1498Szrj }
883838fd1498Szrj /* Fall through for fields that aren't bitfields. */
883938fd1498Szrj gcc_fallthrough ();
884038fd1498Szrj
884138fd1498Szrj case FUNCTION_DECL:
884238fd1498Szrj case VAR_DECL:
884338fd1498Szrj case CONST_DECL:
884438fd1498Szrj case PARM_DECL:
884538fd1498Szrj case RESULT_DECL:
884638fd1498Szrj case TEMPLATE_PARM_INDEX:
884738fd1498Szrj expr = mark_type_use (expr);
884838fd1498Szrj type = TREE_TYPE (expr);
884938fd1498Szrj break;
885038fd1498Szrj
885138fd1498Szrj case ERROR_MARK:
885238fd1498Szrj type = error_mark_node;
885338fd1498Szrj break;
885438fd1498Szrj
885538fd1498Szrj case COMPONENT_REF:
885638fd1498Szrj case COMPOUND_EXPR:
885738fd1498Szrj mark_type_use (expr);
885838fd1498Szrj type = is_bitfield_expr_with_lowered_type (expr);
885938fd1498Szrj if (!type)
886038fd1498Szrj type = TREE_TYPE (TREE_OPERAND (expr, 1));
886138fd1498Szrj break;
886238fd1498Szrj
886338fd1498Szrj case BIT_FIELD_REF:
886438fd1498Szrj gcc_unreachable ();
886538fd1498Szrj
886638fd1498Szrj case INTEGER_CST:
886738fd1498Szrj case PTRMEM_CST:
886838fd1498Szrj /* We can get here when the id-expression refers to an
886938fd1498Szrj enumerator or non-type template parameter. */
887038fd1498Szrj type = TREE_TYPE (expr);
887138fd1498Szrj break;
887238fd1498Szrj
887338fd1498Szrj default:
887438fd1498Szrj /* Handle instantiated template non-type arguments. */
887538fd1498Szrj type = TREE_TYPE (expr);
887638fd1498Szrj break;
887738fd1498Szrj }
887838fd1498Szrj }
887938fd1498Szrj else
888038fd1498Szrj {
888138fd1498Szrj /* Within a lambda-expression:
888238fd1498Szrj
888338fd1498Szrj Every occurrence of decltype((x)) where x is a possibly
888438fd1498Szrj parenthesized id-expression that names an entity of
888538fd1498Szrj automatic storage duration is treated as if x were
888638fd1498Szrj transformed into an access to a corresponding data member
888738fd1498Szrj of the closure type that would have been declared if x
888838fd1498Szrj were a use of the denoted entity. */
888938fd1498Szrj if (outer_automatic_var_p (expr)
889038fd1498Szrj && current_function_decl
889138fd1498Szrj && LAMBDA_FUNCTION_P (current_function_decl))
889238fd1498Szrj type = capture_decltype (expr);
889338fd1498Szrj else if (error_operand_p (expr))
889438fd1498Szrj type = error_mark_node;
889538fd1498Szrj else if (expr == current_class_ptr)
889638fd1498Szrj /* If the expression is just "this", we want the
889738fd1498Szrj cv-unqualified pointer for the "this" type. */
889838fd1498Szrj type = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
889938fd1498Szrj else
890038fd1498Szrj {
890138fd1498Szrj /* Otherwise, where T is the type of e, if e is an lvalue,
890238fd1498Szrj decltype(e) is defined as T&; if an xvalue, T&&; otherwise, T. */
890338fd1498Szrj cp_lvalue_kind clk = lvalue_kind (expr);
890438fd1498Szrj type = unlowered_expr_type (expr);
890538fd1498Szrj gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
890638fd1498Szrj
890738fd1498Szrj /* For vector types, pick a non-opaque variant. */
890838fd1498Szrj if (VECTOR_TYPE_P (type))
890938fd1498Szrj type = strip_typedefs (type);
891038fd1498Szrj
891138fd1498Szrj if (clk != clk_none && !(clk & clk_class))
891238fd1498Szrj type = cp_build_reference_type (type, (clk & clk_rvalueref));
891338fd1498Szrj }
891438fd1498Szrj }
891538fd1498Szrj
891638fd1498Szrj return type;
891738fd1498Szrj }
891838fd1498Szrj
891938fd1498Szrj /* Called from trait_expr_value to evaluate either __has_nothrow_assign or
892038fd1498Szrj __has_nothrow_copy, depending on assign_p. Returns true iff all
892138fd1498Szrj the copy {ctor,assign} fns are nothrow. */
892238fd1498Szrj
892338fd1498Szrj static bool
classtype_has_nothrow_assign_or_copy_p(tree type,bool assign_p)892438fd1498Szrj classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p)
892538fd1498Szrj {
892638fd1498Szrj tree fns = NULL_TREE;
892738fd1498Szrj
892838fd1498Szrj if (assign_p || TYPE_HAS_COPY_CTOR (type))
892938fd1498Szrj fns = get_class_binding (type, assign_p ? assign_op_identifier
893038fd1498Szrj : ctor_identifier);
893138fd1498Szrj
893238fd1498Szrj bool saw_copy = false;
893338fd1498Szrj for (ovl_iterator iter (fns); iter; ++iter)
893438fd1498Szrj {
893538fd1498Szrj tree fn = *iter;
893638fd1498Szrj
893738fd1498Szrj if (copy_fn_p (fn) > 0)
893838fd1498Szrj {
893938fd1498Szrj saw_copy = true;
894038fd1498Szrj maybe_instantiate_noexcept (fn);
894138fd1498Szrj if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
894238fd1498Szrj return false;
894338fd1498Szrj }
894438fd1498Szrj }
894538fd1498Szrj
894638fd1498Szrj return saw_copy;
894738fd1498Szrj }
894838fd1498Szrj
894938fd1498Szrj /* Actually evaluates the trait. */
895038fd1498Szrj
895138fd1498Szrj static bool
trait_expr_value(cp_trait_kind kind,tree type1,tree type2)895238fd1498Szrj trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
895338fd1498Szrj {
895438fd1498Szrj enum tree_code type_code1;
895538fd1498Szrj tree t;
895638fd1498Szrj
895738fd1498Szrj type_code1 = TREE_CODE (type1);
895838fd1498Szrj
895938fd1498Szrj switch (kind)
896038fd1498Szrj {
896138fd1498Szrj case CPTK_HAS_NOTHROW_ASSIGN:
896238fd1498Szrj type1 = strip_array_types (type1);
896338fd1498Szrj return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
896438fd1498Szrj && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2)
896538fd1498Szrj || (CLASS_TYPE_P (type1)
896638fd1498Szrj && classtype_has_nothrow_assign_or_copy_p (type1,
896738fd1498Szrj true))));
896838fd1498Szrj
896938fd1498Szrj case CPTK_HAS_TRIVIAL_ASSIGN:
897038fd1498Szrj /* ??? The standard seems to be missing the "or array of such a class
897138fd1498Szrj type" wording for this trait. */
897238fd1498Szrj type1 = strip_array_types (type1);
897338fd1498Szrj return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE
897438fd1498Szrj && (trivial_type_p (type1)
897538fd1498Szrj || (CLASS_TYPE_P (type1)
897638fd1498Szrj && TYPE_HAS_TRIVIAL_COPY_ASSIGN (type1))));
897738fd1498Szrj
897838fd1498Szrj case CPTK_HAS_NOTHROW_CONSTRUCTOR:
897938fd1498Szrj type1 = strip_array_types (type1);
898038fd1498Szrj return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
898138fd1498Szrj || (CLASS_TYPE_P (type1)
898238fd1498Szrj && (t = locate_ctor (type1))
898338fd1498Szrj && (maybe_instantiate_noexcept (t),
898438fd1498Szrj TYPE_NOTHROW_P (TREE_TYPE (t)))));
898538fd1498Szrj
898638fd1498Szrj case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
898738fd1498Szrj type1 = strip_array_types (type1);
898838fd1498Szrj return (trivial_type_p (type1)
898938fd1498Szrj || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1)));
899038fd1498Szrj
899138fd1498Szrj case CPTK_HAS_NOTHROW_COPY:
899238fd1498Szrj type1 = strip_array_types (type1);
899338fd1498Szrj return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2)
899438fd1498Szrj || (CLASS_TYPE_P (type1)
899538fd1498Szrj && classtype_has_nothrow_assign_or_copy_p (type1, false)));
899638fd1498Szrj
899738fd1498Szrj case CPTK_HAS_TRIVIAL_COPY:
899838fd1498Szrj /* ??? The standard seems to be missing the "or array of such a class
899938fd1498Szrj type" wording for this trait. */
900038fd1498Szrj type1 = strip_array_types (type1);
900138fd1498Szrj return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
900238fd1498Szrj || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_COPY_CTOR (type1)));
900338fd1498Szrj
900438fd1498Szrj case CPTK_HAS_TRIVIAL_DESTRUCTOR:
900538fd1498Szrj type1 = strip_array_types (type1);
900638fd1498Szrj return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE
900738fd1498Szrj || (CLASS_TYPE_P (type1)
900838fd1498Szrj && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1)));
900938fd1498Szrj
901038fd1498Szrj case CPTK_HAS_VIRTUAL_DESTRUCTOR:
901138fd1498Szrj return type_has_virtual_destructor (type1);
901238fd1498Szrj
901338fd1498Szrj case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
901438fd1498Szrj return type_has_unique_obj_representations (type1);
901538fd1498Szrj
901638fd1498Szrj case CPTK_IS_ABSTRACT:
901738fd1498Szrj return ABSTRACT_CLASS_TYPE_P (type1);
901838fd1498Szrj
901938fd1498Szrj case CPTK_IS_AGGREGATE:
902038fd1498Szrj return CP_AGGREGATE_TYPE_P (type1);
902138fd1498Szrj
902238fd1498Szrj case CPTK_IS_BASE_OF:
902338fd1498Szrj return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
902438fd1498Szrj && (same_type_ignoring_top_level_qualifiers_p (type1, type2)
902538fd1498Szrj || DERIVED_FROM_P (type1, type2)));
902638fd1498Szrj
902738fd1498Szrj case CPTK_IS_CLASS:
902838fd1498Szrj return NON_UNION_CLASS_TYPE_P (type1);
902938fd1498Szrj
903038fd1498Szrj case CPTK_IS_EMPTY:
903138fd1498Szrj return NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1);
903238fd1498Szrj
903338fd1498Szrj case CPTK_IS_ENUM:
903438fd1498Szrj return type_code1 == ENUMERAL_TYPE;
903538fd1498Szrj
903638fd1498Szrj case CPTK_IS_FINAL:
903738fd1498Szrj return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1);
903838fd1498Szrj
903938fd1498Szrj case CPTK_IS_LITERAL_TYPE:
904038fd1498Szrj return literal_type_p (type1);
904138fd1498Szrj
904238fd1498Szrj case CPTK_IS_POD:
904338fd1498Szrj return pod_type_p (type1);
904438fd1498Szrj
904538fd1498Szrj case CPTK_IS_POLYMORPHIC:
904638fd1498Szrj return CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1);
904738fd1498Szrj
904838fd1498Szrj case CPTK_IS_SAME_AS:
904938fd1498Szrj return same_type_p (type1, type2);
905038fd1498Szrj
905138fd1498Szrj case CPTK_IS_STD_LAYOUT:
905238fd1498Szrj return std_layout_type_p (type1);
905338fd1498Szrj
905438fd1498Szrj case CPTK_IS_TRIVIAL:
905538fd1498Szrj return trivial_type_p (type1);
905638fd1498Szrj
905738fd1498Szrj case CPTK_IS_TRIVIALLY_ASSIGNABLE:
905838fd1498Szrj return is_trivially_xible (MODIFY_EXPR, type1, type2);
905938fd1498Szrj
906038fd1498Szrj case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
906138fd1498Szrj return is_trivially_xible (INIT_EXPR, type1, type2);
906238fd1498Szrj
906338fd1498Szrj case CPTK_IS_TRIVIALLY_COPYABLE:
906438fd1498Szrj return trivially_copyable_p (type1);
906538fd1498Szrj
906638fd1498Szrj case CPTK_IS_UNION:
906738fd1498Szrj return type_code1 == UNION_TYPE;
906838fd1498Szrj
906938fd1498Szrj case CPTK_IS_ASSIGNABLE:
907038fd1498Szrj return is_xible (MODIFY_EXPR, type1, type2);
907138fd1498Szrj
907238fd1498Szrj case CPTK_IS_CONSTRUCTIBLE:
907338fd1498Szrj return is_xible (INIT_EXPR, type1, type2);
907438fd1498Szrj
907538fd1498Szrj default:
907638fd1498Szrj gcc_unreachable ();
907738fd1498Szrj return false;
907838fd1498Szrj }
907938fd1498Szrj }
908038fd1498Szrj
908138fd1498Szrj /* If TYPE is an array of unknown bound, or (possibly cv-qualified)
908238fd1498Szrj void, or a complete type, returns true, otherwise false. */
908338fd1498Szrj
908438fd1498Szrj static bool
check_trait_type(tree type)908538fd1498Szrj check_trait_type (tree type)
908638fd1498Szrj {
908738fd1498Szrj if (type == NULL_TREE)
908838fd1498Szrj return true;
908938fd1498Szrj
909038fd1498Szrj if (TREE_CODE (type) == TREE_LIST)
909138fd1498Szrj return (check_trait_type (TREE_VALUE (type))
909238fd1498Szrj && check_trait_type (TREE_CHAIN (type)));
909338fd1498Szrj
909438fd1498Szrj if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
909538fd1498Szrj && COMPLETE_TYPE_P (TREE_TYPE (type)))
909638fd1498Szrj return true;
909738fd1498Szrj
909838fd1498Szrj if (VOID_TYPE_P (type))
909938fd1498Szrj return true;
910038fd1498Szrj
910138fd1498Szrj return !!complete_type_or_else (strip_array_types (type), NULL_TREE);
910238fd1498Szrj }
910338fd1498Szrj
910438fd1498Szrj /* Process a trait expression. */
910538fd1498Szrj
910638fd1498Szrj tree
finish_trait_expr(cp_trait_kind kind,tree type1,tree type2)910738fd1498Szrj finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
910838fd1498Szrj {
910938fd1498Szrj if (type1 == error_mark_node
911038fd1498Szrj || type2 == error_mark_node)
911138fd1498Szrj return error_mark_node;
911238fd1498Szrj
911338fd1498Szrj if (processing_template_decl)
911438fd1498Szrj {
911538fd1498Szrj tree trait_expr = make_node (TRAIT_EXPR);
911638fd1498Szrj TREE_TYPE (trait_expr) = boolean_type_node;
911738fd1498Szrj TRAIT_EXPR_TYPE1 (trait_expr) = type1;
911838fd1498Szrj TRAIT_EXPR_TYPE2 (trait_expr) = type2;
911938fd1498Szrj TRAIT_EXPR_KIND (trait_expr) = kind;
912038fd1498Szrj return trait_expr;
912138fd1498Szrj }
912238fd1498Szrj
912338fd1498Szrj switch (kind)
912438fd1498Szrj {
912538fd1498Szrj case CPTK_HAS_NOTHROW_ASSIGN:
912638fd1498Szrj case CPTK_HAS_TRIVIAL_ASSIGN:
912738fd1498Szrj case CPTK_HAS_NOTHROW_CONSTRUCTOR:
912838fd1498Szrj case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
912938fd1498Szrj case CPTK_HAS_NOTHROW_COPY:
913038fd1498Szrj case CPTK_HAS_TRIVIAL_COPY:
913138fd1498Szrj case CPTK_HAS_TRIVIAL_DESTRUCTOR:
913238fd1498Szrj case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
913338fd1498Szrj case CPTK_HAS_VIRTUAL_DESTRUCTOR:
913438fd1498Szrj case CPTK_IS_ABSTRACT:
913538fd1498Szrj case CPTK_IS_AGGREGATE:
913638fd1498Szrj case CPTK_IS_EMPTY:
913738fd1498Szrj case CPTK_IS_FINAL:
913838fd1498Szrj case CPTK_IS_LITERAL_TYPE:
913938fd1498Szrj case CPTK_IS_POD:
914038fd1498Szrj case CPTK_IS_POLYMORPHIC:
914138fd1498Szrj case CPTK_IS_STD_LAYOUT:
914238fd1498Szrj case CPTK_IS_TRIVIAL:
914338fd1498Szrj case CPTK_IS_TRIVIALLY_COPYABLE:
914438fd1498Szrj if (!check_trait_type (type1))
914538fd1498Szrj return error_mark_node;
914638fd1498Szrj break;
914738fd1498Szrj
914838fd1498Szrj case CPTK_IS_ASSIGNABLE:
914938fd1498Szrj case CPTK_IS_CONSTRUCTIBLE:
915038fd1498Szrj break;
915138fd1498Szrj
915238fd1498Szrj case CPTK_IS_TRIVIALLY_ASSIGNABLE:
915338fd1498Szrj case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
915438fd1498Szrj if (!check_trait_type (type1)
915538fd1498Szrj || !check_trait_type (type2))
915638fd1498Szrj return error_mark_node;
915738fd1498Szrj break;
915838fd1498Szrj
915938fd1498Szrj case CPTK_IS_BASE_OF:
916038fd1498Szrj if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
916138fd1498Szrj && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
916238fd1498Szrj && !complete_type_or_else (type2, NULL_TREE))
916338fd1498Szrj /* We already issued an error. */
916438fd1498Szrj return error_mark_node;
916538fd1498Szrj break;
916638fd1498Szrj
916738fd1498Szrj case CPTK_IS_CLASS:
916838fd1498Szrj case CPTK_IS_ENUM:
916938fd1498Szrj case CPTK_IS_UNION:
917038fd1498Szrj case CPTK_IS_SAME_AS:
917138fd1498Szrj break;
917238fd1498Szrj
917338fd1498Szrj default:
917438fd1498Szrj gcc_unreachable ();
917538fd1498Szrj }
917638fd1498Szrj
917738fd1498Szrj return (trait_expr_value (kind, type1, type2)
917838fd1498Szrj ? boolean_true_node : boolean_false_node);
917938fd1498Szrj }
918038fd1498Szrj
918138fd1498Szrj /* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64,
918238fd1498Szrj which is ignored for C++. */
918338fd1498Szrj
918438fd1498Szrj void
set_float_const_decimal64(void)918538fd1498Szrj set_float_const_decimal64 (void)
918638fd1498Szrj {
918738fd1498Szrj }
918838fd1498Szrj
918938fd1498Szrj void
clear_float_const_decimal64(void)919038fd1498Szrj clear_float_const_decimal64 (void)
919138fd1498Szrj {
919238fd1498Szrj }
919338fd1498Szrj
919438fd1498Szrj bool
float_const_decimal64_p(void)919538fd1498Szrj float_const_decimal64_p (void)
919638fd1498Szrj {
919738fd1498Szrj return 0;
919838fd1498Szrj }
919938fd1498Szrj
920038fd1498Szrj
920138fd1498Szrj /* Return true if T designates the implied `this' parameter. */
920238fd1498Szrj
920338fd1498Szrj bool
is_this_parameter(tree t)920438fd1498Szrj is_this_parameter (tree t)
920538fd1498Szrj {
920638fd1498Szrj if (!DECL_P (t) || DECL_NAME (t) != this_identifier)
920738fd1498Szrj return false;
920838fd1498Szrj gcc_assert (TREE_CODE (t) == PARM_DECL || is_capture_proxy (t)
920938fd1498Szrj || (cp_binding_oracle && TREE_CODE (t) == VAR_DECL));
921038fd1498Szrj return true;
921138fd1498Szrj }
921238fd1498Szrj
921338fd1498Szrj /* Insert the deduced return type for an auto function. */
921438fd1498Szrj
921538fd1498Szrj void
apply_deduced_return_type(tree fco,tree return_type)921638fd1498Szrj apply_deduced_return_type (tree fco, tree return_type)
921738fd1498Szrj {
921838fd1498Szrj tree result;
921938fd1498Szrj
922038fd1498Szrj if (return_type == error_mark_node)
922138fd1498Szrj return;
922238fd1498Szrj
922338fd1498Szrj if (DECL_CONV_FN_P (fco))
922438fd1498Szrj DECL_NAME (fco) = make_conv_op_name (return_type);
922538fd1498Szrj
922638fd1498Szrj TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco));
922738fd1498Szrj
922838fd1498Szrj result = DECL_RESULT (fco);
922938fd1498Szrj if (result == NULL_TREE)
923038fd1498Szrj return;
923138fd1498Szrj if (TREE_TYPE (result) == return_type)
923238fd1498Szrj return;
923338fd1498Szrj
923438fd1498Szrj if (!processing_template_decl && !VOID_TYPE_P (return_type)
923538fd1498Szrj && !complete_type_or_else (return_type, NULL_TREE))
923638fd1498Szrj return;
923738fd1498Szrj
923838fd1498Szrj /* We already have a DECL_RESULT from start_preparsed_function.
923938fd1498Szrj Now we need to redo the work it and allocate_struct_function
924038fd1498Szrj did to reflect the new type. */
924138fd1498Szrj gcc_assert (current_function_decl == fco);
924238fd1498Szrj result = build_decl (input_location, RESULT_DECL, NULL_TREE,
924338fd1498Szrj TYPE_MAIN_VARIANT (return_type));
924438fd1498Szrj DECL_ARTIFICIAL (result) = 1;
924538fd1498Szrj DECL_IGNORED_P (result) = 1;
924638fd1498Szrj cp_apply_type_quals_to_decl (cp_type_quals (return_type),
924738fd1498Szrj result);
924838fd1498Szrj
924938fd1498Szrj DECL_RESULT (fco) = result;
925038fd1498Szrj
925138fd1498Szrj if (!processing_template_decl)
925238fd1498Szrj {
925338fd1498Szrj bool aggr = aggregate_value_p (result, fco);
925438fd1498Szrj #ifdef PCC_STATIC_STRUCT_RETURN
925538fd1498Szrj cfun->returns_pcc_struct = aggr;
925638fd1498Szrj #endif
925738fd1498Szrj cfun->returns_struct = aggr;
925838fd1498Szrj }
925938fd1498Szrj
926038fd1498Szrj }
926138fd1498Szrj
926238fd1498Szrj /* DECL is a local variable or parameter from the surrounding scope of a
926338fd1498Szrj lambda-expression. Returns the decltype for a use of the capture field
926438fd1498Szrj for DECL even if it hasn't been captured yet. */
926538fd1498Szrj
926638fd1498Szrj static tree
capture_decltype(tree decl)926738fd1498Szrj capture_decltype (tree decl)
926838fd1498Szrj {
926938fd1498Szrj tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
927038fd1498Szrj /* FIXME do lookup instead of list walk? */
927138fd1498Szrj tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam));
927238fd1498Szrj tree type;
927338fd1498Szrj
927438fd1498Szrj if (cap)
927538fd1498Szrj type = TREE_TYPE (TREE_PURPOSE (cap));
927638fd1498Szrj else
927738fd1498Szrj switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam))
927838fd1498Szrj {
927938fd1498Szrj case CPLD_NONE:
928038fd1498Szrj error ("%qD is not captured", decl);
928138fd1498Szrj return error_mark_node;
928238fd1498Szrj
928338fd1498Szrj case CPLD_COPY:
928438fd1498Szrj type = TREE_TYPE (decl);
928538fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE
928638fd1498Szrj && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
928738fd1498Szrj type = TREE_TYPE (type);
928838fd1498Szrj break;
928938fd1498Szrj
929038fd1498Szrj case CPLD_REFERENCE:
929138fd1498Szrj type = TREE_TYPE (decl);
929238fd1498Szrj if (TREE_CODE (type) != REFERENCE_TYPE)
929338fd1498Szrj type = build_reference_type (TREE_TYPE (decl));
929438fd1498Szrj break;
929538fd1498Szrj
929638fd1498Szrj default:
929738fd1498Szrj gcc_unreachable ();
929838fd1498Szrj }
929938fd1498Szrj
930038fd1498Szrj if (TREE_CODE (type) != REFERENCE_TYPE)
930138fd1498Szrj {
930238fd1498Szrj if (!LAMBDA_EXPR_MUTABLE_P (lam))
930338fd1498Szrj type = cp_build_qualified_type (type, (cp_type_quals (type)
930438fd1498Szrj |TYPE_QUAL_CONST));
930538fd1498Szrj type = build_reference_type (type);
930638fd1498Szrj }
930738fd1498Szrj return type;
930838fd1498Szrj }
930938fd1498Szrj
931038fd1498Szrj /* Build a unary fold expression of EXPR over OP. If IS_RIGHT is true,
931138fd1498Szrj this is a right unary fold. Otherwise it is a left unary fold. */
931238fd1498Szrj
931338fd1498Szrj static tree
finish_unary_fold_expr(tree expr,int op,tree_code dir)931438fd1498Szrj finish_unary_fold_expr (tree expr, int op, tree_code dir)
931538fd1498Szrj {
931638fd1498Szrj // Build a pack expansion (assuming expr has pack type).
931738fd1498Szrj if (!uses_parameter_packs (expr))
931838fd1498Szrj {
931938fd1498Szrj error_at (location_of (expr), "operand of fold expression has no "
932038fd1498Szrj "unexpanded parameter packs");
932138fd1498Szrj return error_mark_node;
932238fd1498Szrj }
932338fd1498Szrj tree pack = make_pack_expansion (expr);
932438fd1498Szrj
932538fd1498Szrj // Build the fold expression.
932638fd1498Szrj tree code = build_int_cstu (integer_type_node, abs (op));
932738fd1498Szrj tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack);
932838fd1498Szrj FOLD_EXPR_MODIFY_P (fold) = (op < 0);
932938fd1498Szrj return fold;
933038fd1498Szrj }
933138fd1498Szrj
933238fd1498Szrj tree
finish_left_unary_fold_expr(tree expr,int op)933338fd1498Szrj finish_left_unary_fold_expr (tree expr, int op)
933438fd1498Szrj {
933538fd1498Szrj return finish_unary_fold_expr (expr, op, UNARY_LEFT_FOLD_EXPR);
933638fd1498Szrj }
933738fd1498Szrj
933838fd1498Szrj tree
finish_right_unary_fold_expr(tree expr,int op)933938fd1498Szrj finish_right_unary_fold_expr (tree expr, int op)
934038fd1498Szrj {
934138fd1498Szrj return finish_unary_fold_expr (expr, op, UNARY_RIGHT_FOLD_EXPR);
934238fd1498Szrj }
934338fd1498Szrj
934438fd1498Szrj /* Build a binary fold expression over EXPR1 and EXPR2. The
934538fd1498Szrj associativity of the fold is determined by EXPR1 and EXPR2 (whichever
934638fd1498Szrj has an unexpanded parameter pack). */
934738fd1498Szrj
934838fd1498Szrj tree
finish_binary_fold_expr(tree pack,tree init,int op,tree_code dir)934938fd1498Szrj finish_binary_fold_expr (tree pack, tree init, int op, tree_code dir)
935038fd1498Szrj {
935138fd1498Szrj pack = make_pack_expansion (pack);
935238fd1498Szrj tree code = build_int_cstu (integer_type_node, abs (op));
935338fd1498Szrj tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack, init);
935438fd1498Szrj FOLD_EXPR_MODIFY_P (fold) = (op < 0);
935538fd1498Szrj return fold;
935638fd1498Szrj }
935738fd1498Szrj
935838fd1498Szrj tree
finish_binary_fold_expr(tree expr1,tree expr2,int op)935938fd1498Szrj finish_binary_fold_expr (tree expr1, tree expr2, int op)
936038fd1498Szrj {
936138fd1498Szrj // Determine which expr has an unexpanded parameter pack and
936238fd1498Szrj // set the pack and initial term.
936338fd1498Szrj bool pack1 = uses_parameter_packs (expr1);
936438fd1498Szrj bool pack2 = uses_parameter_packs (expr2);
936538fd1498Szrj if (pack1 && !pack2)
936638fd1498Szrj return finish_binary_fold_expr (expr1, expr2, op, BINARY_RIGHT_FOLD_EXPR);
936738fd1498Szrj else if (pack2 && !pack1)
936838fd1498Szrj return finish_binary_fold_expr (expr2, expr1, op, BINARY_LEFT_FOLD_EXPR);
936938fd1498Szrj else
937038fd1498Szrj {
937138fd1498Szrj if (pack1)
937238fd1498Szrj error ("both arguments in binary fold have unexpanded parameter packs");
937338fd1498Szrj else
937438fd1498Szrj error ("no unexpanded parameter packs in binary fold");
937538fd1498Szrj }
937638fd1498Szrj return error_mark_node;
937738fd1498Szrj }
937838fd1498Szrj
937938fd1498Szrj /* Finish __builtin_launder (arg). */
938038fd1498Szrj
938138fd1498Szrj tree
finish_builtin_launder(location_t loc,tree arg,tsubst_flags_t complain)938238fd1498Szrj finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain)
938338fd1498Szrj {
938438fd1498Szrj tree orig_arg = arg;
938538fd1498Szrj if (!type_dependent_expression_p (arg))
938638fd1498Szrj arg = decay_conversion (arg, complain);
938738fd1498Szrj if (error_operand_p (arg))
938838fd1498Szrj return error_mark_node;
938938fd1498Szrj if (!type_dependent_expression_p (arg)
939038fd1498Szrj && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
939138fd1498Szrj {
939238fd1498Szrj error_at (loc, "non-pointer argument to %<__builtin_launder%>");
939338fd1498Szrj return error_mark_node;
939438fd1498Szrj }
939538fd1498Szrj if (processing_template_decl)
939638fd1498Szrj arg = orig_arg;
939738fd1498Szrj return build_call_expr_internal_loc (loc, IFN_LAUNDER,
939838fd1498Szrj TREE_TYPE (arg), 1, arg);
939938fd1498Szrj }
940038fd1498Szrj
940138fd1498Szrj #include "gt-cp-semantics.h"
9402