diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index ef64e6b..519c3fa 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1089,6 +1089,10 @@ extern void c_genericize (tree);
 extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
 extern tree c_build_bind_expr (location_t, tree, tree);
 
+/* In c-lex.c  */
+extern bool conflict_marker_at_location_p (location_t start_loc,
+					   location_t *out_loc);
+
 /* In c-pch.c  */
 extern void pch_init (void);
 extern void pch_cpp_save_state (void);
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 9c86ba7..dd598c6 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -1263,3 +1263,70 @@ lex_charconst (const cpp_token *token)
 
   return value;
 }
+
+/* Determine if LINE begins with a conflict marker.
+   If so, write to *OUT_LEN with the length of the marker.  */
+
+static bool
+conflict_marker_within_line_p (const char *line, int *out_len)
+{
+  if (0 == strncmp (line, "<<<<<<<", 7))
+    {
+      *out_len = 7;
+      return true;
+    }
+  if (0 == strncmp (line, "=======", 7))
+    {
+      *out_len = 7;
+      return true;
+    }
+  if (0 == strncmp (line, ">>>>>>>", 7))
+    {
+      *out_len = 7;
+      return true;
+    }
+
+  return false;
+}
+
+/* Helper function for c_parser_error and cp_parser_error.
+   Given an error occurring at a "<<", ">>" or "==" token at START_LOC,
+   determine if this is a conflict marker.
+   If it returns true, *OUT_LOC is written to with the location/range
+   of the marker.  */
+
+bool
+conflict_marker_at_location_p (location_t start_loc, location_t *out_loc)
+{
+  /* It must not be in a macro expansion.  */
+  if (linemap_location_from_macro_expansion_p (line_table, start_loc))
+    return false;
+
+  /* It must be at the start of the line.  */
+  expanded_location exploc = expand_location (start_loc);
+  if (exploc.column != 1)
+    return false;
+
+  const char *line = location_get_source_line (exploc.file, exploc.line,
+					       NULL);
+  /* If we can't read the source file (e.g. when handling a .i file)
+     don't attempt to detect conflict markers.  */
+  if (!line)
+    return false;
+
+  /* Does "line" start with a conflict marker?  */
+  int marker_len;
+  if (!conflict_marker_within_line_p (line, &marker_len))
+    return false;
+
+  /* We have a conflict marker.  Construct a location of the form:
+       <<<<<<<
+       ^~~~~~~
+     with start == caret, finishing at the end of the marker.  */
+  location_t finish_loc
+    = linemap_position_for_loc_and_offset (line_table, start_loc,
+					   marker_len - 1);
+  *out_loc = make_location (start_loc, start_loc, finish_loc);
+
+  return true;
+}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 124c30b..5014c8d 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -850,6 +850,20 @@ c_parser_error (c_parser *parser, const char *gmsgid)
   parser->error = true;
   if (!gmsgid)
     return;
+
+  /* If this is actually a conflict marker, report it as such.  */
+  if (token->type == CPP_LSHIFT
+      || token->type == CPP_RSHIFT
+      || token->type == CPP_EQ_EQ)
+    {
+      location_t marker_loc;
+      if (conflict_marker_at_location_p (token->location, &marker_loc))
+	{
+	  error_at (marker_loc, "version control conflict marker in file");
+	  return;
+	}
+    }
+
   /* This diagnostic makes more sense if it is tagged to the line of
      the token we just peeked at.  */
   c_parser_set_source_position_from_token (token);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a420cf1..8bdaed7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2713,6 +2713,19 @@ cp_parser_error (cp_parser* parser, const char* gmsgid)
 	  return;
 	}
 
+      /* If this is actually a conflict marker, report it as such.  */
+      if (token->type == CPP_LSHIFT
+	  || token->type == CPP_RSHIFT
+	  || token->type == CPP_EQ_EQ)
+	{
+	  location_t marker_loc;
+	  if (conflict_marker_at_location_p (token->location, &marker_loc))
+	    {
+	      error_at (marker_loc, "version control conflict marker in file");
+	      return;
+	    }
+	}
+
       c_parse_error (gmsgid,
 		     /* Because c_parser_error does not understand
 			CPP_KEYWORD, keywords are treated like
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-1.c b/gcc/testsuite/c-c++-common/conflict-markers-1.c
new file mode 100644
index 0000000..752f146
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-1.c
@@ -0,0 +1,9 @@
+int p;
+
+<<<<<<< HEAD /* { dg-error "conflict marker" } */
+extern int some_var;
+=======      /* { dg-error "conflict marker" } */
+extern short some_var; /* this line would lead to a warning */
+>>>>>>> Some commit message  /* { dg-error "conflict marker" } */
+
+int q;
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-10.c b/gcc/testsuite/c-c++-common/conflict-markers-10.c
new file mode 100644
index 0000000..279406f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-10.c
@@ -0,0 +1,23 @@
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+<<<<<<< HEAD /* { dg-error "conflict marker" } */
+/* { dg-begin-multiline-output "" }
+ <<<<<<< HEAD
+ ^~~~~~~
+   { dg-end-multiline-output "" } */
+
+extern int some_var;
+
+=======      /* { dg-error "conflict marker" } */
+/* { dg-begin-multiline-output "" }
+ =======
+ ^~~~~~~
+   { dg-end-multiline-output "" } */
+
+extern short some_var; /* this line would lead to a warning */
+
+>>>>>>> Some commit message  /* { dg-error "conflict marker" } */
+/* { dg-begin-multiline-output "" }
+ >>>>>>>
+ ^~~~~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-11.c b/gcc/testsuite/c-c++-common/conflict-markers-11.c
new file mode 100644
index 0000000..8771453
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-11.c
@@ -0,0 +1,14 @@
+/* Verify that we only report conflict markers at the start of lines.  */
+int p;
+
+ <<<<<<< HEAD /* { dg-error "expected identifier|expected unqualified-id" } */
+
+int q;
+
+ =======      /* { dg-error "expected identifier|expected unqualified-id" } */
+
+int r;
+
+ >>>>>>> Some commit message  /* { dg-error "expected identifier|expected unqualified-id" } */
+
+int s;
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-2.c b/gcc/testsuite/c-c++-common/conflict-markers-2.c
new file mode 100644
index 0000000..f06d043
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-2.c
@@ -0,0 +1,2 @@
+/* This should not be flagged as a conflict marker.  */
+const char *msg = "<<<<<<< ";
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-3.c b/gcc/testsuite/c-c++-common/conflict-markers-3.c
new file mode 100644
index 0000000..f149ecc
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-3.c
@@ -0,0 +1,11 @@
+/* Ensure we can handle unterminated conflict markers.  */
+
+int p;
+
+<<<<<<< HEAD  /* { dg-error "conflict marker" } */
+
+int q;
+
+<<<<<<< HEAD  /* { dg-error "conflict marker" } */
+
+int r;
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-4.c b/gcc/testsuite/c-c++-common/conflict-markers-4.c
new file mode 100644
index 0000000..a3c53ea
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-4.c
@@ -0,0 +1,11 @@
+/* Ensure we can handle mismatched conflict markers.  */
+
+int p;
+
+>>>>>>> Some commit message  /* { dg-error "conflict marker" } */
+
+int q;
+
+>>>>>>> Some other commit message  /* { dg-error "conflict marker" } */
+
+int r;
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-5.c b/gcc/testsuite/c-c++-common/conflict-markers-5.c
new file mode 100644
index 0000000..b55c9c3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-5.c
@@ -0,0 +1,11 @@
+/* Ensure we can handle mismatched conflict markers.  */
+
+int p;
+
+=======  /* { dg-error "conflict marker" } */
+
+int q;
+
+=======  /* { dg-error "conflict marker" } */
+
+int r;
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-6.c b/gcc/testsuite/c-c++-common/conflict-markers-6.c
new file mode 100644
index 0000000..081e289
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-6.c
@@ -0,0 +1,38 @@
+/* Branch coverage of conflict marker detection:
+   none of these should be reported as conflict markers.  */
+
+int a0;
+
+<< HEAD  /* { dg-error "expected" } */
+
+int a1;
+
+<<<< HEAD  /* { dg-error "expected" } */
+
+int a2;
+
+<<<<<< HEAD  /* { dg-error "expected" } */
+
+int b0;
+
+== HEAD  /* { dg-error "expected" } */
+
+int b1;
+
+==== HEAD  /* { dg-error "expected" } */
+
+int b2;
+
+====== HEAD  /* { dg-error "expected" } */
+
+int c0;
+
+>> HEAD  /* { dg-error "expected" } */
+
+int c1;
+
+>>>> HEAD  /* { dg-error "expected" } */
+
+int c2;
+
+>>>>>> HEAD  /* { dg-error "expected" } */
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-7.c b/gcc/testsuite/c-c++-common/conflict-markers-7.c
new file mode 100644
index 0000000..e68f84d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-7.c
@@ -0,0 +1,6 @@
+/* It's valid to stringize the "<<<<<<<"; don't
+   report it as a conflict marker.  */
+#define str(s) #s
+const char *s = str(
+<<<<<<<
+);
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-8.c b/gcc/testsuite/c-c++-common/conflict-markers-8.c
new file mode 100644
index 0000000..be2e121
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-8.c
@@ -0,0 +1,4 @@
+/* A macro that's never expanded shouldn't be reported as a
+   conflict marker.  */
+#define foo \
+<<<<<<<
diff --git a/gcc/testsuite/c-c++-common/conflict-markers-9.c b/gcc/testsuite/c-c++-common/conflict-markers-9.c
new file mode 100644
index 0000000..5c1e663
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/conflict-markers-9.c
@@ -0,0 +1,8 @@
+/* It's valid to have
+<<<<<<<
+   inside both
+   comments (as above), and within string literals.  */
+const char *s = "\
+<<<<<<<";
+
+/* The above shouldn't be reported as errors.  */
diff --git a/gcc/testsuite/g++.dg/conflict-markers-1.C b/gcc/testsuite/g++.dg/conflict-markers-1.C
new file mode 100644
index 0000000..ae19193
--- /dev/null
+++ b/gcc/testsuite/g++.dg/conflict-markers-1.C
@@ -0,0 +1,13 @@
+/* Ensure that we don't complain about patch conflict markers on
+   valid template argument lists, valid in C++11 onwards.  */
+// { dg-options "-std=c++11" }
+
+template <typename T>
+struct foo
+{
+  T t;
+};
+
+foo <foo <foo <foo <foo <foo <foo <int
+>>>>>>> f;
+// The above line is valid C++11, and isn't a patch conflict marker
