diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index e60fb31d8c8..354112e96cc 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -121,6 +121,7 @@ static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
 					     bool *);
 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
 static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
+static tree handle_consteval_attribute (tree *, tree, tree, int, bool *);
 static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
 static tree handle_vector_size_attribute (tree *, tree, tree, int,
@@ -394,6 +395,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_tm_attribute, NULL },
   { "transaction_may_cancel_outer", 0, 0, false, true, false, false,
 			      handle_tm_attribute, NULL },
+  { "consteval",	      1, -1, false, true, true, false,
+			      handle_consteval_attribute, NULL },
   /* ??? These two attributes didn't make the transition from the
      Intel language document to the multi-vendor language document.  */
   { "transaction_pure",       0, 0, false, true,  false, false,
@@ -4032,6 +4035,56 @@ handle_tm_wrap_attribute (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 
+/* Handle consteval(argno1, [argno2, ...]).
+The attrbute expects at least one arg which is INTEGER_CST and denotes the
+position of parameter starting from 1.  */
+
+static tree
+handle_consteval_attribute (tree *node, tree name, tree args,
+			    int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree fntype = *node;
+  int nargs = type_num_arguments (fntype);
+  int argno = 0;
+
+  for (tree ap = args; ap; ap = TREE_CHAIN (ap), argno++)
+    {
+      tree val = TREE_VALUE (ap);
+      if (TREE_CODE (val) != INTEGER_CST)
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute %i value %qE is not an integer constant "
+		   "ignoing attribute.",
+		   name, argno, val);
+	  *no_add_attrs = true;
+	  return NULL_TREE;
+	}
+      int pos = TREE_INT_CST_LOW (val);
+      if (pos < 1 || pos > nargs)
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute %i value %qE does not refer to "
+		   "a function parameter, ignoring attribute.",
+		   name, argno, val);
+	  *no_add_attrs = true;
+	  return NULL_TREE;
+	}
+
+      tree param_type = type_argument_type (fntype, pos);
+      if (!TYPE_READONLY (param_type))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute has value %qE, but parameter %i is not const "
+		   "qualified, ignoring attribute. ",
+		   name, val, pos);
+	  *no_add_attrs = true;
+	  return NULL_TREE;
+	}
+    }
+
+  return NULL_TREE;
+}
+
 /* Ignore the given attribute.  Used when this attribute may be usefully
    overridden by the target, but is not used generically.  */
 
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 00ac3c5278b..365a8001ab0 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5953,6 +5953,43 @@ attribute_fallthrough_p (tree attr)
 }
 
 
+static void
+check_function_consteval_attr (const_tree fndecl, const_tree fntype,
+			       int nargs, tree *argarray,
+			       vec<location_t> *arglocs)
+{
+  tree consteval_params
+    = lookup_attribute ("consteval", TYPE_ATTRIBUTES (fntype));
+
+  if (!consteval_params)
+    return;
+
+  for (int i = 0; i < nargs; i++)
+    {
+      tree ap;
+      for (ap = TREE_VALUE (consteval_params); ap; ap = TREE_CHAIN (ap))
+	{
+	  tree val = TREE_VALUE (ap);
+	  gcc_assert (TREE_CODE (val) == INTEGER_CST);
+	  int pos = TREE_INT_CST_LOW (val);
+	  if ((i + 1) == pos)
+	    break;
+	}
+      if (ap) /* Expected constant.  */
+	{
+	  tree arg = argarray[i];
+	  if (!CONSTANT_CLASS_P (arg))
+	    {
+	      error_at ((*arglocs)[i],
+			"argument %d is not a constant.", i + 1);
+	      inform (DECL_SOURCE_LOCATION (fndecl),
+		      "Function %qE has parameter %i with consteval attribute.",
+		      DECL_NAME (fndecl), i + 1);
+	    }
+	}
+    }
+}
+
 /* Check for valid arguments being passed to a function with FNTYPE.
    There are NARGS arguments in the array ARGARRAY.  LOC should be used
    for diagnostics.  Return true if either -Wnonnull or -Wrestrict has
@@ -6002,6 +6039,8 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
 	}
     }
 
+  check_function_consteval_attr (fndecl, fntype, nargs, argarray, arglocs);
+
   /* check_function_restrict sets the DECL_READ_P for arguments
      so it must be called unconditionally.  */
   warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
