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}} +};