xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/semantics.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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