diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b98d47a702f..230a1525c63 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7234,7 +7234,7 @@ extern bool cxx_omp_create_clause_info		(tree, tree, bool, bool,
 						 bool, bool);
 extern tree baselink_for_fns                    (tree);
 extern void finish_static_assert                (tree, tree, location_t,
-                                                 bool);
+						 bool, bool);
 extern tree finish_decltype_type                (tree, bool, tsubst_flags_t);
 extern tree finish_trait_expr			(location_t, enum cp_trait_kind, tree, tree);
 extern tree build_lambda_expr                   (void);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4c819ea1c5d..1ef14279ff7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14886,7 +14886,8 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
 
   /* Complete the static assertion, which may mean either processing
      the static assert now or saving it for template instantiation.  */
-  finish_static_assert (condition, message, assert_loc, member_p);
+  finish_static_assert (condition, message, assert_loc, member_p,
+			/*show_expr_p=*/false);
 }
 
 /* Parse the expression in decltype ( expression ).  */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a2655a0ff52..6ba114c9da3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18492,8 +18492,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	tree condition;
 
 	++c_inhibit_evaluation_warnings;
-        condition = 
-          tsubst_expr (STATIC_ASSERT_CONDITION (t), 
+	condition =
+	  tsubst_expr (STATIC_ASSERT_CONDITION (t),
                        args,
                        complain, in_decl,
                        /*integral_constant_expression_p=*/true);
@@ -18502,7 +18502,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
         finish_static_assert (condition,
                               STATIC_ASSERT_MESSAGE (t),
                               STATIC_ASSERT_SOURCE_LOCATION (t),
-                              /*member_p=*/false);
+			      /*member_p=*/false, /*show_expr_p=*/true);
       }
       break;
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a550db69488..1cc5118748f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9823,13 +9823,53 @@ init_cp_semantics (void)
 {
 }
 
+
+/* If we have a condition in conjunctive normal form (CNF), find the first
+   failing clause.  In other words, given an expression like
+
+     true && true && false && true && false
+
+   return the first 'false'.  EXPR is the expression.  */
+
+static tree
+find_failing_clause_r (tree expr)
+{
+  if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR)
+    {
+      /* First check the left side...  */
+      tree e = find_failing_clause_r (TREE_OPERAND (expr, 0));
+      if (e == NULL_TREE)
+	/* ...if we didn't find a false clause, check the right side.  */
+	e = find_failing_clause_r (TREE_OPERAND (expr, 1));
+      return e;
+    }
+  tree e = contextual_conv_bool (expr, tf_none);
+  e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true);
+  if (integer_zerop (e))
+    /* This is the failing clause.  */
+    return expr;
+  return NULL_TREE;
+}
+
+/* Wrapper for find_failing_clause_r.  */
+
+static tree
+find_failing_clause (tree expr)
+{
+  if (TREE_CODE (expr) != TRUTH_ANDIF_EXPR)
+    return NULL_TREE;
+  return find_failing_clause_r (expr);
+}
+
 /* Build a STATIC_ASSERT for a static assertion with the condition
    CONDITION and the message text MESSAGE.  LOCATION is the location
    of the static assertion in the source code.  When MEMBER_P, this
-   static assertion is a member of a class.  */
+   static assertion is a member of a class.  If SHOW_EXPR_P is true,
+   print the condition (because it was instantiation-dependent).  */
+
 void
 finish_static_assert (tree condition, tree message, location_t location,
-                      bool member_p)
+		      bool member_p, bool show_expr_p)
 {
   tsubst_flags_t complain = tf_warning_or_error;
 
@@ -9867,8 +9907,7 @@ finish_static_assert (tree condition, tree message, location_t location,
   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);
+  condition = contextual_conv_bool (condition, complain);
   condition = fold_non_dependent_expr (condition, complain,
 				       /*manifestly_const_eval=*/true);
 
@@ -9877,21 +9916,38 @@ finish_static_assert (tree condition, tree message, location_t location,
     ;
   else
     {
-      location_t saved_loc = input_location;
+      iloc_sentinel ils (location);
 
-      input_location = location;
-      if (TREE_CODE (condition) == INTEGER_CST
-          && integer_zerop (condition))
+      if (integer_zerop (condition))
 	{
 	  int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
 				     (TREE_TYPE (TREE_TYPE (message))));
 	  int len = TREE_STRING_LENGTH (message) / sz - 1;
+
+	  /* See if we can find which clause was failing (for logical AND).  */
+	  tree bad = find_failing_clause (orig_condition);
+	  /* If not, or its location is unusable, fall back to the previous
+	     location.  */
+	  location_t cloc = location;
+	  if (cp_expr_location (bad) != UNKNOWN_LOCATION)
+	    cloc = cp_expr_location (bad);
+
           /* Report the error. */
 	  if (len == 0)
-            error ("static assertion failed");
+	    {
+	      if (show_expr_p)
+		error_at (cloc, "static assertion failed due to "
+			  "requirement %qE", orig_condition);
+	      else
+		error_at (cloc, "static assertion failed");
+	    }
+	  else if (show_expr_p)
+	    error_at (cloc, "static assertion failed due to "
+		      "requirement %qE: %s", orig_condition,
+		      TREE_STRING_POINTER (message));
 	  else
-            error ("static assertion failed: %s",
-		   TREE_STRING_POINTER (message));
+	    error_at (cloc, "static assertion failed: %s",
+		      TREE_STRING_POINTER (message));
 
 	  /* Actually explain the failure if this is a concept check or a
 	     requires-expression.  */
@@ -9905,7 +9961,6 @@ finish_static_assert (tree condition, tree message, location_t location,
 	  if (require_rvalue_constant_expression (condition))
 	    cxx_constant_value (condition);
 	}
-      input_location = saved_loc;
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/diagnostic/pr87386.C b/gcc/testsuite/g++.dg/diagnostic/pr87386.C
index 85726af9f01..679a5177f64 100644
--- a/gcc/testsuite/g++.dg/diagnostic/pr87386.C
+++ b/gcc/testsuite/g++.dg/diagnostic/pr87386.C
@@ -14,5 +14,5 @@ static_assert (foo::test<int>::value, "foo");		// { dg-error "static assertion f
 static_assert (foo::test<int>::value && true, "bar");	// { dg-error "static assertion failed: bar" }
 /* { dg-begin-multiline-output "" }
  static_assert (foo::test<int>::value && true, "bar");
-                ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
+                ~~~~~~~~~~~~~~~~^~~~~
    { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert1.C b/gcc/testsuite/g++.dg/diagnostic/static_assert1.C
new file mode 100644
index 00000000000..5cfb66a5ad7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert1.C
@@ -0,0 +1,20 @@
+// PR c++/97518
+// { dg-do compile { target c++17 } }
+
+template <typename T, typename U> struct is_same { static constexpr bool value = false; };
+template <typename T> struct is_same<T, T> { static constexpr bool value = true; };
+
+template <typename T> using some_metafunction_t = T;
+
+template <typename T>
+void foo(T ) {
+    using X = T*;
+    using Y = some_metafunction_t<T>;
+
+    static_assert(is_same<X, Y>::value); // { dg-error {static assertion failed due to requirement .is_same<int\*, int>::value.} }
+    static_assert(is_same<X, Y>::value, "foo"); // { dg-error {static assertion failed due to requirement .is_same<int\*, int>::value.: foo} }
+}
+
+void bar() {
+    foo(0);
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/static_assert2.C b/gcc/testsuite/g++.dg/diagnostic/static_assert2.C
new file mode 100644
index 00000000000..542697f99de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/static_assert2.C
@@ -0,0 +1,68 @@
+// PR c++/97518
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+constexpr bool yes () { return true; }
+constexpr bool no () { return false; }
+constexpr bool yay = true;
+constexpr bool nay = false;
+
+void
+bar ()
+{
+  static_assert (true && true && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (true && true && no(), "");
+                                  ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert (yay && nay, ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (yay && nay, "");
+                         ^~~
+   { dg-end-multiline-output "" } */
+  static_assert (yes() && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (yes() && no(), "");
+                           ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert (no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (no() && yes(), "");
+                  ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert (no() && no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (no() && no() && yes(), "");
+                  ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert (yes() && yes() && yes () && no() && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (yes() && yes() && yes () && no() && yes(), "");
+                                              ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert (yes() && yes() && yes () && (no() && yes()), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert (yes() && yes() && yes () && (no() && yes()), "");
+                                               ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert ((yes() && no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert ((yes() && no()) && no(), "");
+                            ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert ((yes() && no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert ((yes() && no()) && no(), "");
+                            ~~^~
+   { dg-end-multiline-output "" } */
+  static_assert ((no() || no()) && yes(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert ((no() || no()) && yes(), "");
+                  ~~~~~~^~~~~~~~
+   { dg-end-multiline-output "" } */
+  static_assert ((yes() || no()) && no(), ""); // { dg-error "static assertion failed" }
+/* { dg-begin-multiline-output "" }
+   static_assert ((yes() || no()) && no(), "");
+                                     ~~^~
+   { dg-end-multiline-output "" } */
+}
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index bab2751a5ce..67a235f9095 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -3642,7 +3642,7 @@ plugin_add_static_assert (cc1_plugin::connection *self,
 
   bool member_p = at_class_scope_p ();
 
-  finish_static_assert (condition, message, loc, member_p);
+  finish_static_assert (condition, message, loc, member_p, false);
 
   return 1;
 }
diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc
index 6f3cd0a2521..d28a4330504 100644
--- a/libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/scoped_allocator/69293_neg.cc
@@ -46,7 +46,7 @@ test01()
   scoped_alloc sa;
   auto p = sa.allocate(1);
   sa.construct(p);  // this is required to be ill-formed
-  // { dg-error "failed: .* uses_allocator is true" "" { target *-*-* } 0 }
+  // { dg-error "failed due to requirement \[^\n\r\]*: .* uses_allocator is true" "" { target *-*-* } 0 }
 }
 
 // Needed because of PR c++/92193
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc
index 423ecc4d90e..b6d925edcd3 100644
--- a/libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/69293_neg.cc
@@ -44,6 +44,6 @@ test01()
 {
   alloc_type a;
   std::tuple<X> t(std::allocator_arg, a); // this is required to be ill-formed
-  // { dg-error "failed: .* uses_allocator is true" "" { target *-*-* } 0 }
+  // { dg-error "failed due to requirement \[^\n\r\]*: .* uses_allocator is true" "" { target *-*-* } 0 }
   // { dg-error "no matching function for call" "" { target c++2a } 0 }
 }
diff --git a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
index c3ff05aa72a..20190feaa0b 100644
--- a/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/uses_allocator/cons_neg.cc
@@ -43,5 +43,5 @@ void test01()
 
   tuple<Type> t(allocator_arg, a, 1);
 }
-// { dg-error "failed: .* uses_allocator is true" "" { target *-*-* } 0 }
+// { dg-error "failed due to requirement \[^\n\r\]*: .* uses_allocator is true" "" { target *-*-* } 0 }
 // { dg-error "no matching function for call" "" { target c++2a } 0 }
diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
index ba252ef34fe..e2066cd59ee 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc
@@ -10,6 +10,6 @@ std::__detail::_Adaptor<std::mt19937, unsigned long> aurng(urng);
 auto x = std::generate_canonical<std::size_t,
 			std::numeric_limits<std::size_t>::digits>(urng);
 
-// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 167 }
+// { dg-error "static assertion failed due to requirement \[^\n\r\]*: template argument must be a floating point type" "" { target *-*-* } 167 }
 
-// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3346 }
+// { dg-error "static assertion failed due to requirement \[^\n\r\]*: template argument must be a floating point type" "" { target *-*-* } 3346 }
