diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index a607690a14c7e3b3d2ec09d1438bea95ca592c1c..9992c779890e055f199354078a9c85e0b1dea67a 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3107,6 +3107,7 @@ def err_use_of_default_argument_to_function_declared_later : Error<
   "use of default argument to function %0 that is declared later in class %1">;
 def note_default_argument_declared_here : Note<
   "default argument declared here">;
+def err_recursive_default_argument : Error<"recursive evaluation of default argument">;
 
 def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
   "%diff{promoted type $ of K&R function parameter is not compatible with the "
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f766091e54e8eb97328aa98b10fcb232482c493a..f617db915108a42cf7f9e7d7f24711fdccc24055 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4566,6 +4566,13 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
     }
   }
 
+  // If the default argument expression is not set yet, we are building it now.
+  if (!Param->hasInit()) {
+    Diag(Param->getLocStart(), diag::err_recursive_default_argument) << FD;
+    Param->setInvalidDecl();
+    return ExprError();
+  }
+
   // If the default expression creates temporaries, we need to
   // push them to the current stack of expression temporaries so they'll
   // be properly destroyed.
diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index c4d40b4280e96e953256b27d73d2c8c22ae9e1b6..8f77f300572b94c03db6e15a4c720f28c58f8ad1 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -128,3 +128,7 @@ S<1> s;
 
 template <int I1 = I2, int I2 = 1> struct T {};  // expected-error-re {{use of undeclared identifier 'I2'{{$}}}}
 T<0, 1> t;
+
+struct PR28105 {
+  PR28105 (int = 0, int = 0, PR28105 = 0);  // expected-error{{recursive evaluation of default argument}}
+};