diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index 3e2d02a818e8b6474f75f4e32af1fe40f70f6da6..9ab83a9a84aa2f124dd5e38a2bfd0d85d684dc00 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -3036,7 +3036,7 @@ check_address_or_pointer_of_packed_member (tree type, tree rhs)
 	  rhs = TREE_TYPE (rhs);	/* Pointer type.  */
 	  /* We could be called while processing a template and RHS could be
 	     a functor.  In that case it's a class, not a pointer.  */
-	  if (!POINTER_TYPE_P (rhs))
+	  if (!rhs || !POINTER_TYPE_P (rhs))
 	    return NULL_TREE;
 	  rhs = TREE_TYPE (rhs);	/* Function type.  */
 	  rhstype = TREE_TYPE (rhs);
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index e31aeb8e68b84bbc0cf247d2eeb563c80f498dff..0d8b780ba2ff6fd24eb876986a1a420ba4094598 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -8851,15 +8851,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t complain)
       rhs = BASELINK_FUNCTIONS (rhs);
     }
 
-  /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot
-     deduce any type information.  */
-  if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
-    {
-      if (complain & tf_error)
-	error ("not enough type information");
-      return error_mark_node;
-    }
-
   /* There are only a few kinds of expressions that may have a type
      dependent on overload resolution.  */
   gcc_assert (TREE_CODE (rhs) == ADDR_EXPR
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6e84c2d77bb1cbd50652feb110f3558efe178b04..c05760e6789d035bd949ff5ff0e42b75015e736b 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -8208,7 +8208,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case MODOP_EXPR:
       /* GCC internal stuff.  */
     case VA_ARG_EXPR:
-    case NON_DEPENDENT_EXPR:
     case BASELINK:
     case OFFSET_REF:
       if (!ctx->quiet)
@@ -10077,14 +10076,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case BIND_EXPR:
       return RECUR (BIND_EXPR_BODY (t), want_rval);
 
-    case NON_DEPENDENT_EXPR:
-      /* Treat NON_DEPENDENT_EXPR as non-constant: it's not handled by
-	 constexpr evaluation or tsubst, so fold_non_dependent_expr can't
-	 do anything useful with it.  And we shouldn't see it in a context
-	 where a constant expression is strictly required, hence the assert.  */
-      gcc_checking_assert (!(flags & tf_error));
-      return false;
-
     case CLEANUP_POINT_EXPR:
     case MUST_NOT_THROW_EXPR:
     case TRY_CATCH_EXPR:
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 3493d3c6ed33101eaf6d2e0cac4a653896d23941..df3cc82079789b271443003a8732af3f2343ce0d 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1421,8 +1421,7 @@ coro_validate_builtin_call (tree call, tsubst_flags_t)
 	location_t loc = EXPR_LOCATION (arg);
 
 	/* We expect alignof expressions in templates.  */
-	if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
-	    && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
+	if (TREE_CODE (arg) == ALIGNOF_EXPR)
 	  ;
 	else if (!TREE_CONSTANT (arg))
 	  {
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 93b027b80ce858ab0620a106f181e0ad2aeb1baa..2093ae02466e4182e842b6ab8e8aedf676d95ca2 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -525,7 +525,6 @@ cp_common_init_ts (void)
   MARK_TS_EXP (MUST_NOT_THROW_EXPR);
   MARK_TS_EXP (NEW_EXPR);
   MARK_TS_EXP (NOEXCEPT_EXPR);
-  MARK_TS_EXP (NON_DEPENDENT_EXPR);
   MARK_TS_EXP (OFFSETOF_EXPR);
   MARK_TS_EXP (OFFSET_REF);
   MARK_TS_EXP (PSEUDO_DTOR_EXPR);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 0e66ca70e00caa1dc4beada1024ace32954e2aaf..d78005e50b97b7e18599ac6765963e7c13ae2d49 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -262,17 +262,6 @@ DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1)
 DEFTREECODE (NOEXCEPT_EXPR, "noexcept_expr", tcc_unary, 1)
 DEFTREECODE (SPACESHIP_EXPR, "spaceship_expr", tcc_expression, 2)
 
-/* A placeholder for an expression that is not type-dependent, but
-   does occur in a template.  When an expression that is not
-   type-dependent appears in a larger expression, we must compute the
-   type of that larger expression.  That computation would normally
-   modify the original expression, which would change the mangling of
-   that expression if it appeared in a template argument list.  In
-   that situation, we create a NON_DEPENDENT_EXPR to take the place of
-   the original expression.  The expression is the only operand -- it
-   is only needed for diagnostics.  */
-DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", tcc_expression, 1)
-
 /* CTOR_INITIALIZER is a placeholder in template code for a call to
    setup_vtbl_pointer (and appears in all functions, not just ctors).  */
 DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", tcc_expression, 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8c75d03612fa5697c79161a3dbc6d3c86726fc7c..d6c6842cac1da8cdb788d8b4dd4416d247957c59 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7491,7 +7491,7 @@ extern bool any_value_dependent_elements_p      (const_tree);
 extern bool dependent_omp_for_p			(tree, tree, tree, tree);
 extern tree resolve_typename_type		(tree, bool);
 extern tree template_for_substitution		(tree);
-extern tree build_non_dependent_expr		(tree);
+inline tree build_non_dependent_expr		(tree t) { return t; } // XXX remove
 extern void make_args_non_dependent		(vec<tree, va_gc> *);
 extern bool reregister_specialization		(tree, tree, tree);
 extern tree instantiate_non_dependent_expr	(tree, tsubst_flags_t = tf_error);
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 96abfae7725e9219a4c946493a06f98ddd5bb73f..4dfb39fb60bf4cdc5a47b1ae4b585108d35ce619 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -1048,7 +1048,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
     call = TARGET_EXPR_INITIAL (expr);
   location_t loc = cp_expr_loc_or_input_loc (call);
   tree callee = cp_get_callee (call);
-  if (!callee)
+  if (!callee || !TREE_TYPE (callee))
     return;
 
   tree type = TREE_TYPE (callee);
@@ -1056,6 +1056,8 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
     type = TYPE_PTRMEMFUNC_FN_TYPE (type);
   if (INDIRECT_TYPE_P (type))
     type = TREE_TYPE (type);
+  if (!FUNC_OR_METHOD_TYPE_P (type))
+    return;
 
   tree rettype = TREE_TYPE (type);
   tree fn = cp_get_fndecl_from_callee (callee);
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index eb16e63425f5c599847700a32f37a048d0735a36..6a82358f370716d1ee7c30fb937d4147616aa492 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -1207,7 +1207,6 @@ cxx_pretty_printer::expression (tree t)
       assignment_expression (t);
       break;
 
-    case NON_DEPENDENT_EXPR:
     case MUST_NOT_THROW_EXPR:
       expression (TREE_OPERAND (t, 0));
       break;
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 767478cf5fdf8d2ee2c2ade5ea58ab35b03da1de..0ed69bca6fc977f3ffe476e5bc40a127bf13c77b 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1510,10 +1510,6 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
       dump_decl (pp, BASELINK_FUNCTIONS (t), flags);
       break;
 
-    case NON_DEPENDENT_EXPR:
-      dump_expr (pp, t, flags);
-      break;
-
     case TEMPLATE_TYPE_PARM:
       if (flags & TFF_DECL_SPECIFIERS)
 	pp->declaration (t);
@@ -2942,10 +2938,6 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
       pp_cxx_right_paren (pp);
       break;
 
-    case NON_DEPENDENT_EXPR:
-      dump_expr (pp, TREE_OPERAND (t, 0), flags);
-      break;
-
     case ARGUMENT_PACK_SELECT:
       dump_template_argument (pp, ARGUMENT_PACK_SELECT_FROM_PACK (t), flags);
       break;
diff --git a/gcc/cp/expr.cc b/gcc/cp/expr.cc
index cdd29c15fc32f3b821a742bb9bbec92f298c2572..8371a245d95c8adf8c6a36346e3182536d6f6e6a 100644
--- a/gcc/cp/expr.cc
+++ b/gcc/cp/expr.cc
@@ -147,7 +147,6 @@ mark_use (tree expr, bool rvalue_p, bool read_p,
 	}
       break;
     case COMPONENT_REF:
-    case NON_DEPENDENT_EXPR:
       recurse_op[0] = true;
       break;
     case COMPOUND_EXPR:
@@ -371,7 +370,6 @@ mark_exp_read (tree exp)
     case ADDR_EXPR:
     case INDIRECT_REF:
     case FLOAT_EXPR:
-    case NON_DEPENDENT_EXPR:
     case VIEW_CONVERT_EXPR:
       mark_exp_read (TREE_OPERAND (exp, 0));
       break;
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7cbf903ae29bfd908811a39229c9a15fa8b7f832..85a487aa5ad900cb74adae512a2291db5915c50e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -29294,98 +29294,6 @@ resolve_typename_type (tree type, bool only_current_p)
   return result;
 }
 
-/* EXPR is an expression which is not type-dependent.  Return a proxy
-   for EXPR that can be used to compute the types of larger
-   expressions containing EXPR.  */
-
-tree
-build_non_dependent_expr (tree expr)
-{
-  tree orig_expr = expr;
-  tree inner_expr;
-
-  /* When checking, try to get a constant value for all non-dependent
-     expressions in order to expose bugs in *_dependent_expression_p
-     and constexpr.  This can affect code generation, see PR70704, so
-     only do this for -fchecking=2.  */
-  if (flag_checking > 1
-      && cxx_dialect >= cxx11
-      /* Don't do this during nsdmi parsing as it can lead to
-	 unexpected recursive instantiations.  */
-      && !parsing_nsdmi ()
-      /* Don't do this during concept processing either and for
-         the same reason.  */
-      && !processing_constraint_expression_p ())
-    fold_non_dependent_expr (expr, tf_none);
-
-  STRIP_ANY_LOCATION_WRAPPER (expr);
-
-  /* Preserve OVERLOADs; the functions must be available to resolve
-     types.  */
-  inner_expr = expr;
-  if (TREE_CODE (inner_expr) == STMT_EXPR)
-    inner_expr = stmt_expr_value_expr (inner_expr);
-  if (TREE_CODE (inner_expr) == ADDR_EXPR)
-    inner_expr = TREE_OPERAND (inner_expr, 0);
-  if (TREE_CODE (inner_expr) == COMPONENT_REF)
-    inner_expr = TREE_OPERAND (inner_expr, 1);
-  if (is_overloaded_fn (inner_expr)
-      || TREE_CODE (inner_expr) == OFFSET_REF)
-    return orig_expr;
-  /* There is no need to return a proxy for a variable, parameter
-     or enumerator.  */
-  if (VAR_P (expr) || TREE_CODE (expr) == PARM_DECL
-      || TREE_CODE (expr) == CONST_DECL)
-    return orig_expr;
-  /* Preserve string constants; conversions from string constants to
-     "char *" are allowed, even though normally a "const char *"
-     cannot be used to initialize a "char *".  */
-  if (TREE_CODE (expr) == STRING_CST)
-    return orig_expr;
-  /* Preserve void and arithmetic constants, as an optimization -- there is no
-     reason to create a new node.  */
-  if (TREE_CODE (expr) == VOID_CST
-      || TREE_CODE (expr) == INTEGER_CST
-      || TREE_CODE (expr) == REAL_CST)
-    return orig_expr;
-  /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
-     There is at least one place where we want to know that a
-     particular expression is a throw-expression: when checking a ?:
-     expression, there are special rules if the second or third
-     argument is a throw-expression.  */
-  if (TREE_CODE (expr) == THROW_EXPR)
-    return orig_expr;
-
-  /* Don't wrap an initializer list, we need to be able to look inside.  */
-  if (BRACE_ENCLOSED_INITIALIZER_P (expr))
-    return orig_expr;
-
-  /* Don't wrap a dummy object, we need to be able to test for it.  */
-  if (is_dummy_object (expr))
-    return orig_expr;
-
-  if (TREE_CODE (expr) == COND_EXPR)
-    return build3 (COND_EXPR,
-		   TREE_TYPE (expr),
-		   build_non_dependent_expr (TREE_OPERAND (expr, 0)),
-		   (TREE_OPERAND (expr, 1)
-		    ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
-		    : build_non_dependent_expr (TREE_OPERAND (expr, 0))),
-		   build_non_dependent_expr (TREE_OPERAND (expr, 2)));
-  if (TREE_CODE (expr) == COMPOUND_EXPR)
-    return build2 (COMPOUND_EXPR,
-		   TREE_TYPE (expr),
-		   TREE_OPERAND (expr, 0),
-		   build_non_dependent_expr (TREE_OPERAND (expr, 1)));
-
-  /* If the type is unknown, it can't really be non-dependent */
-  gcc_assert (TREE_TYPE (expr) != unknown_type_node);
-
-  /* Otherwise, build a NON_DEPENDENT_EXPR.  */
-  return build1_loc (EXPR_LOCATION (orig_expr), NON_DEPENDENT_EXPR,
-		     TREE_TYPE (expr), expr);
-}
-
 /* ARGS is a vector of expressions as arguments to a function call.
    Replace the arguments with equivalent non-dependent expressions.
    This modifies ARGS in place.  */
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index eaf882f8854eb770dc4e3d0d4951664446902f01..a3d61d3e7c985aa4ea9b962b480e786aa7ea7768 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -308,7 +308,6 @@ lvalue_kind (const_tree ref)
 	 its argument unmodified and we assign it to a const_tree.  */
       return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
 
-    case NON_DEPENDENT_EXPR:
     case PAREN_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
@@ -412,10 +411,6 @@ cp_stabilize_reference (tree ref)
   STRIP_ANY_LOCATION_WRAPPER (ref);
   switch (TREE_CODE (ref))
     {
-    case NON_DEPENDENT_EXPR:
-      /* We aren't actually evaluating this.  */
-      return ref;
-
     /* We need to treat specially anything stabilize_reference doesn't
        handle specifically.  */
     case VAR_DECL:
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 8132bd7fccc2669c3801c45aca0df07aa9ac678c..2cfa3c8a935d32f5700bc3943cc0f04b6dc73347 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -4844,9 +4844,6 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
       || warning_suppressed_p (op, OPT_Waddress))
     return;
 
-  if (TREE_CODE (op) == NON_DEPENDENT_EXPR)
-    op = TREE_OPERAND (op, 0);
-
   tree cop = fold_for_warn (op);
 
   if (TREE_CODE (cop) == NON_LVALUE_EXPR)
@@ -5405,7 +5402,9 @@ cp_build_binary_op (const op_location_t &location,
 	    type0 = TREE_TYPE (type0);
 	  if (!TYPE_P (type1))
 	    type1 = TREE_TYPE (type1);
-	  if (INDIRECT_TYPE_P (type0) && same_type_p (TREE_TYPE (type0), type1))
+	  if (type0
+	      && INDIRECT_TYPE_P (type0)
+	      && same_type_p (TREE_TYPE (type0), type1))
 	    {
 	      if (!(TREE_CODE (first_arg) == PARM_DECL
 		    && DECL_ARRAY_PARAMETER_P (first_arg)
@@ -5422,7 +5421,9 @@ cp_build_binary_op (const op_location_t &location,
 			      "first %<sizeof%> operand was declared here");
 		}
 	    }
-	  else if (TREE_CODE (type0) == ARRAY_TYPE
+	  else if (!dependent_type_p (type0)
+		   && !dependent_type_p (type1)
+		   && TREE_CODE (type0) == ARRAY_TYPE
 		   && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0)))
 		   /* Set by finish_parenthesized_expr.  */
 		   && !warning_suppressed_p (op1, OPT_Wsizeof_array_div)
@@ -7399,6 +7400,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
 					 complain);
       if (arg != error_mark_node)
 	{
+	  if (processing_template_decl)
+	    return build1_loc (location, TRUTH_NOT_EXPR, boolean_type_node, arg);
 	  val = invert_truthvalue_loc (location, arg);
 	  if (obvalue_p (val))
 	    val = non_lvalue_loc (location, val);
diff --git a/gcc/testsuite/g++.dg/concepts/var-concept3.C b/gcc/testsuite/g++.dg/concepts/var-concept3.C
index 6fd96a5042e27d8f38f125bfbbcf3946eb7780d5..b4483ebca89fafb166b86895516382ab02f170a7 100644
--- a/gcc/testsuite/g++.dg/concepts/var-concept3.C
+++ b/gcc/testsuite/g++.dg/concepts/var-concept3.C
@@ -12,7 +12,7 @@ template<typename T>
 
 
 template<typename U>
-  requires C1<U>() // { dg-error "cannot be used as a function" }
+  requires C1<U>() // { dg-error "cannot call a concept" }
   void f1(U) { }
 
 template<typename U>