Do not update SSA in lto-stremaer-in
[gcc.git] / gcc / cp / semantics.c
index fa6962454bf4357980eccf056f813953b8689d59..17de39eea5489af212e46fb30dfe047e19dd0498 100644 (file)
@@ -723,6 +723,28 @@ begin_if_stmt (void)
   return r;
 }
 
+/* Returns true if FN, a CALL_EXPR, is a call to
+   std::is_constant_evaluated or __builtin_is_constant_evaluated.  */
+
+static bool
+is_std_constant_evaluated_p (tree fn)
+{
+  /* std::is_constant_evaluated takes no arguments.  */
+  if (call_expr_nargs (fn) != 0)
+    return false;
+
+  tree fndecl = cp_get_callee_fndecl_nofold (fn);
+  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+                        BUILT_IN_FRONTEND))
+    return true;
+
+  if (!decl_in_std_namespace_p (fndecl))
+    return false;
+
+  tree name = DECL_NAME (fndecl);
+  return name && id_equal (name, "is_constant_evaluated");
+}
+
 /* Process the COND of an if-statement, which may be given by
    IF_STMT.  */
 
@@ -738,6 +760,20 @@ finish_if_stmt_cond (tree cond, tree if_stmt)
         converted to bool.  */
       && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node)
     {
+      /* if constexpr (std::is_constant_evaluated()) is always true,
+        so give the user a clue.  */
+      if (warn_tautological_compare)
+       {
+         tree t = cond;
+         if (TREE_CODE (t) == CLEANUP_POINT_EXPR)
+           t = TREE_OPERAND (t, 0);
+         if (TREE_CODE (t) == CALL_EXPR
+             && is_std_constant_evaluated_p (t))
+           warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare,
+                       "%qs always evaluates to true in %<if constexpr%>",
+                       "std::is_constant_evaluated");
+       }
+
       cond = instantiate_non_dependent_expr (cond);
       cond = cxx_constant_value (cond, NULL_TREE);
     }
@@ -774,6 +810,18 @@ finish_else_clause (tree if_stmt)
   ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt));
 }
 
+/* Callback for cp_walk_tree to mark all {VAR,PARM}_DECLs in a tree as
+   read.  */
+
+static tree
+maybe_mark_exp_read_r (tree *tp, int *, void *)
+{
+  tree t = *tp;
+  if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+    mark_exp_read (t);
+  return NULL_TREE;
+}
+
 /* Finish an if-statement.  */
 
 void
@@ -781,6 +829,16 @@ finish_if_stmt (tree if_stmt)
 {
   tree scope = IF_SCOPE (if_stmt);
   IF_SCOPE (if_stmt) = NULL;
+  if (IF_STMT_CONSTEXPR_P (if_stmt))
+    {
+      /* Prevent various -Wunused warnings.  We might not instantiate
+        either of these branches, so we would not mark the variables
+        used in that branch as read.  */
+      cp_walk_tree_without_duplicates (&THEN_CLAUSE (if_stmt),
+                                      maybe_mark_exp_read_r, NULL);
+      cp_walk_tree_without_duplicates (&ELSE_CLAUSE (if_stmt),
+                                      maybe_mark_exp_read_r, NULL);
+    }
   add_stmt (do_poplevel (scope));
 }
 
@@ -1185,10 +1243,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
   if (!processing_template_decl)
     {
       /* Convert the condition to an integer or enumeration type.  */
+      tree orig_cond = cond;
       cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true);
       if (cond == NULL_TREE)
        {
-         error ("switch quantity not an integer");
+         error_at (cp_expr_loc_or_input_loc (orig_cond),
+                   "switch quantity not an integer");
          cond = error_mark_node;
        }
       /* We want unlowered type here to handle enum bit-fields.  */
@@ -1484,8 +1544,9 @@ finish_compound_stmt (tree stmt)
    considered volatile, and whether it is asm inline.  */
 
 tree
-finish_asm_stmt (int volatile_p, tree string, tree output_operands,
-                tree input_operands, tree clobbers, tree labels, bool inline_p)
+finish_asm_stmt (location_t loc, int volatile_p, tree string,
+                tree output_operands, tree input_operands, tree clobbers,
+                tree labels, bool inline_p)
 {
   tree r;
   tree t;
@@ -1532,7 +1593,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
                     effectively const.  */
                  || (CLASS_TYPE_P (TREE_TYPE (operand))
                      && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
-           cxx_readonly_error (input_location, operand, lv_asm);
+           cxx_readonly_error (loc, operand, lv_asm);
 
          tree *op = &operand;
          while (TREE_CODE (*op) == COMPOUND_EXPR)
@@ -1585,8 +1646,9 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
             resolve the overloading.  */
          if (TREE_TYPE (operand) == unknown_type_node)
            {
-             error ("type of %<asm%> operand %qE could not be determined",
-                    TREE_VALUE (t));
+             error_at (loc,
+                       "type of %<asm%> operand %qE could not be determined",
+                       TREE_VALUE (t));
              operand = error_mark_node;
            }
 
@@ -1634,7 +1696,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
        }
     }
 
-  r = build_stmt (input_location, ASM_EXPR, string,
+  r = build_stmt (loc, ASM_EXPR, string,
                  output_operands, input_operands,
                  clobbers, labels);
   ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
@@ -1726,10 +1788,10 @@ finish_mem_initializers (tree mem_inits)
 
 /* Obfuscate EXPR if it looks like an id-expression or member access so
    that the call to finish_decltype in do_auto_deduction will give the
-   right result.  */
+   right result.  If EVEN_UNEVAL, do this even in unevaluated context.  */
 
 tree
-force_paren_expr (tree expr)
+force_paren_expr (tree expr, bool even_uneval)
 {
   /* This is only needed for decltype(auto) in C++14.  */
   if (cxx_dialect < cxx14)
@@ -1737,7 +1799,7 @@ force_paren_expr (tree expr)
 
   /* If we're in unevaluated context, we can't be deducing a
      return/initializer type, so we don't need to mess with this.  */
-  if (cp_unevaluated_operand)
+  if (cp_unevaluated_operand && !even_uneval)
     return expr;
 
   if (!DECL_P (tree_strip_any_location_wrapper (expr))
@@ -2527,6 +2589,23 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
                                      /*fn_p=*/NULL,
                                      complain);
     }
+  else if (concept_check_p (fn))
+    {
+      /* FN is actually a template-id referring to a concept definition.  */
+      tree id = unpack_concept_check (fn);
+      tree tmpl = TREE_OPERAND (id, 0);
+      tree args = TREE_OPERAND (id, 1);
+
+      if (!function_concept_p (tmpl))
+       {
+         error_at (EXPR_LOC_OR_LOC (fn, input_location),
+                   "cannot call a concept as a function");
+         return error_mark_node;
+       }
+
+      /* Ensure the result is wrapped as a call expression.  */
+      result = build_concept_check (tmpl, args, tf_warning_or_error);
+    }
   else if (is_overloaded_fn (fn))
     {
       /* If the function is an overloaded builtin, resolve it.  */
@@ -2965,6 +3044,14 @@ finish_translation_unit (void)
 
   /* Do file scope __FUNCTION__ et al.  */
   finish_fname_decls ();
+
+  if (scope_chain->omp_declare_target_attribute)
+    {
+      if (!errorcount)
+       error ("%<#pragma omp declare target%> without corresponding "
+              "%<#pragma omp end declare target%>");
+      scope_chain->omp_declare_target_attribute = 0;
+    }
 }
 
 /* Finish a template type parameter, specified as AGGR IDENTIFIER.
@@ -2996,8 +3083,8 @@ finish_template_template_parm (tree aggr, tree identifier)
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   DECL_ARTIFICIAL (decl) = 1;
 
-  // Associate the constraints with the underlying declaration,
-  // not the template.
+  /* Associate the constraints with the underlying declaration,
+     not the template.  */
   tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
   tree constr = build_constraints (reqs, NULL_TREE);
   set_constraints (decl, constr);
@@ -3771,9 +3858,10 @@ finish_id_expression_1 (tree id_expression,
       if (! error_operand_p (decl)
          && !dependent_p
          && integral_constant_expression_p
-         && ! decl_constant_var_p (decl)
+         && !decl_constant_var_p (decl)
          && TREE_CODE (decl) != CONST_DECL
-         && ! builtin_valid_in_constant_expr_p (decl))
+         && !builtin_valid_in_constant_expr_p (decl)
+         && !concept_check_p (decl))
        {
          if (!allow_non_integral_constant_expression_p)
            {
@@ -3789,12 +3877,18 @@ finish_id_expression_1 (tree id_expression,
        decl = wrap;
       else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
               && !dependent_p
-              && variable_template_p (TREE_OPERAND (decl, 0)))
+              && variable_template_p (TREE_OPERAND (decl, 0))
+              && !concept_check_p (decl))
        {
          decl = finish_template_variable (decl);
          mark_used (decl);
          decl = convert_from_reference (decl);
        }
+      else if (concept_check_p (decl))
+       {
+         /* Nothing more to do. All of the analysis for concept checks
+            is done by build_conept_id, called from the parser.  */
+       }
       else if (scope)
        {
          if (TREE_CODE (decl) == SCOPE_REF)
@@ -3809,6 +3903,8 @@ finish_id_expression_1 (tree id_expression,
          if (TREE_CODE (decl) == FUNCTION_DECL)
            mark_used (decl);
 
+         cp_warn_deprecated_use_scopes (scope);
+
          if (TYPE_P (scope))
            decl = finish_qualified_id_expr (scope,
                                             decl,
@@ -4321,7 +4417,9 @@ expand_or_defer_fn_1 (tree fn)
       if (DECL_INTERFACE_KNOWN (fn))
        /* We've already made a decision as to how this function will
           be handled.  */;
-      else if (!at_eof)
+      else if (!at_eof
+              || DECL_IMMEDIATE_FUNCTION_P (fn)
+              || DECL_OMP_DECLARE_REDUCTION_P (fn))
        tentative_decl_linkage (fn);
       else
        import_export_decl (fn);
@@ -4332,6 +4430,8 @@ expand_or_defer_fn_1 (tree fn)
         be emitted; there may be callers in other DLLs.  */
       if (DECL_DECLARED_INLINE_P (fn)
          && !DECL_REALLY_EXTERN (fn)
+         && !DECL_IMMEDIATE_FUNCTION_P (fn)
+         && !DECL_OMP_DECLARE_REDUCTION_P (fn)
          && (flag_keep_inline_functions
              || (flag_keep_inline_dllexport
                  && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4364,6 +4464,9 @@ expand_or_defer_fn_1 (tree fn)
       return false;
     }
 
+  if (DECL_OMP_DECLARE_REDUCTION_P (fn))
+    return false;
+
   return true;
 }
 
@@ -4953,6 +5056,17 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
       TREE_PURPOSE (t) = lb;
       low_bound = lb;
     }
+  /* Temporarily disable -fstrong-eval-order for array reductions.
+     The SAVE_EXPR and COMPOUND_EXPR added if low_bound has side-effects
+     is something the middle-end can't cope with and more importantly,
+     it needs to be the actual base variable that is privatized, not some
+     temporary assigned previous value of it.  That, together with OpenMP
+     saying how many times the side-effects are evaluated is unspecified,
+     makes int *a, *b; ... reduction(+:a[a = b, 3:10]) really unspecified.  */
+  warning_sentinel s (flag_strong_eval_order,
+                     OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+                     || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION);
   ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, false);
   return ret;
 }
@@ -6146,7 +6260,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead.  */
   bitmap_initialize (&map_head, &bitmap_default_obstack);
   bitmap_initialize (&map_field_head, &bitmap_default_obstack);
-  /* If ort == C_ORT_OMP used as nontemporal_head instead.  */
+  /* If ort == C_ORT_OMP used as nontemporal_head or use_device_xxx_head
+     instead.  */
   bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
 
   if (ort & C_ORT_ACC)
@@ -6404,13 +6519,19 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                          omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
              remove = true;
            }
-         else if (ort == C_ORT_ACC
-                  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+         else if ((ort == C_ORT_ACC
+                   && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+                  || (ort == C_ORT_OMP
+                      && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
+                          || (OMP_CLAUSE_CODE (c)
+                              == OMP_CLAUSE_USE_DEVICE_ADDR))))
            {
              if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
                {
                  error_at (OMP_CLAUSE_LOCATION (c),
-                           "%qD appears more than once in reduction clauses",
+                           ort == C_ORT_ACC
+                           ? "%qD appears more than once in reduction clauses"
+                           : "%qD appears more than once in data clauses",
                            t);
                  remove = true;
                }
@@ -7059,7 +7180,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                remove = true;
              else
                {
-                 t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+                 t = cp_build_indirect_ref (OMP_CLAUSE_LOCATION (c),
+                                            addr, RO_UNARY_STAR,
                                             tf_warning_or_error);
                  if (t == error_mark_node)
                    remove = true;
@@ -7524,20 +7646,41 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            {
              tree type = TREE_TYPE (t);
              if (!TYPE_PTR_P (type)
-                 && TREE_CODE (type) != ARRAY_TYPE
-                 && (!TYPE_REF_P (type)
-                     || (!TYPE_PTR_P (TREE_TYPE (type))
-                         && TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)))
+                 && (!TYPE_REF_P (type) || !TYPE_PTR_P (TREE_TYPE (type))))
                {
-                 error_at (OMP_CLAUSE_LOCATION (c),
-                           "%qs variable is neither a pointer, nor an array "
-                           "nor reference to pointer or array",
-                           omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
-                 remove = true;
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
+                     && ort == C_ORT_OMP)
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%qs variable is neither a pointer "
+                               "nor reference to pointer",
+                               omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     remove = true;
+                   }
+                 else if (TREE_CODE (type) != ARRAY_TYPE
+                          && (!TYPE_REF_P (type)
+                              || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE))
+                   {
+                     error_at (OMP_CLAUSE_LOCATION (c),
+                               "%qs variable is neither a pointer, nor an "
+                               "array nor reference to pointer or array",
+                               omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     remove = true;
+                   }
                }
            }
          goto check_dup_generic;
 
+       case OMP_CLAUSE_USE_DEVICE_ADDR:
+         field_ok = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (!processing_template_decl
+             && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
+             && !TYPE_REF_P (TREE_TYPE (t))
+             && !cxx_mark_addressable (t))
+           remove = true;
+         goto check_dup_generic;
+
        case OMP_CLAUSE_NOWAIT:
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
@@ -7548,6 +7691,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        case OMP_CLAUSE_SECTIONS:
        case OMP_CLAUSE_TASKGROUP:
        case OMP_CLAUSE_PROC_BIND:
+       case OMP_CLAUSE_DEVICE_TYPE:
        case OMP_CLAUSE_NOGROUP:
        case OMP_CLAUSE_THREADS:
        case OMP_CLAUSE_SIMD:
@@ -7874,6 +8018,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
              break;
            case OMP_CLAUSE_DEFAULT_SHARED:
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+                 && c_omp_predefined_variable (t))
+               /* The __func__ variable and similar function-local predefined
+                  variables may be listed in a shared or firstprivate
+                  clause.  */
+               break;
              if (VAR_P (t)
                  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
                  && TREE_STATIC (t)
@@ -8271,7 +8422,6 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   if (init && EXPR_HAS_LOCATION (init))
     elocus = EXPR_LOCATION (init);
 
-  cond = cp_fully_fold (cond);
   switch (TREE_CODE (cond))
     {
     case GT_EXPR:
@@ -9166,7 +9316,7 @@ finish_omp_depobj (location_t loc, tree depobj,
       if (addr == error_mark_node)
        depobj = error_mark_node;
       else
-       depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+       depobj = cp_build_indirect_ref (loc, addr, RO_UNARY_STAR,
                                        tf_warning_or_error);
     }
 
@@ -9411,6 +9561,9 @@ finish_static_assert (tree condition, tree message, location_t location,
       return;
     }
 
+  /* Save the condition in case it was a concept check.  */
+  tree orig_condition = condition;
+
   /* Fold the expression and convert it to a boolean value. */
   condition = perform_implicit_conversion_flags (boolean_type_node, condition,
                                                 complain, LOOKUP_NORMAL);
@@ -9437,6 +9590,10 @@ finish_static_assert (tree condition, tree message, location_t location,
          else
             error ("static assertion failed: %s",
                   TREE_STRING_POINTER (message));
+
+         /* Actually explain the failure if this is a concept check.  */
+         if (concept_check_p (orig_condition))
+           diagnose_constraints (location, orig_condition, NULL_TREE);
        }
       else if (condition && condition != error_mark_node)
        {
@@ -9828,7 +9985,7 @@ check_trait_type (tree type)
 /* Process a trait expression.  */
 
 tree
-finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
+finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
 {
   if (type1 == error_mark_node
       || type2 == error_mark_node)
@@ -9841,6 +9998,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       TRAIT_EXPR_TYPE1 (trait_expr) = type1;
       TRAIT_EXPR_TYPE2 (trait_expr) = type2;
       TRAIT_EXPR_KIND (trait_expr) = kind;
+      TRAIT_EXPR_LOCATION (trait_expr) = loc;
       return trait_expr;
     }
 
@@ -9898,8 +10056,9 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
       gcc_unreachable ();
     }
 
-  return (trait_expr_value (kind, type1, type2)
-         ? boolean_true_node : boolean_false_node);
+tree val = (trait_expr_value (kind, type1, type2)
+           ? boolean_true_node : boolean_false_node);
+ return maybe_wrap_with_location (val, loc);
 }
 
 /* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64,
@@ -9980,7 +10139,6 @@ apply_deduced_return_type (tree fco, tree return_type)
 #endif
       cfun->returns_struct = aggr;
     }
-
 }
 
 /* DECL is a local variable or parameter from the surrounding scope of a
@@ -10037,7 +10195,7 @@ capture_decltype (tree decl)
 static tree
 finish_unary_fold_expr (tree expr, int op, tree_code dir)
 {
-  // Build a pack expansion (assuming expr has pack type).
+  /* Build a pack expansion (assuming expr has pack type).  */
   if (!uses_parameter_packs (expr))
     {
       error_at (location_of (expr), "operand of fold expression has no "
@@ -10046,7 +10204,7 @@ finish_unary_fold_expr (tree expr, int op, tree_code dir)
     }
   tree pack = make_pack_expansion (expr);
 
-  // Build the fold expression.
+  /* Build the fold expression.  */
   tree code = build_int_cstu (integer_type_node, abs (op));
   tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack);
   FOLD_EXPR_MODIFY_P (fold) = (op < 0);