Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -905,11 +905,13 @@ /// Whether this parameter is an ObjC method parameter or not. unsigned IsObjCMethodParam : 1; + enum { NumScopeDepthOrObjCQualsBits = 7 }; + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was /// declared. - unsigned ScopeDepthOrObjCQuals : 7; + unsigned ScopeDepthOrObjCQuals : NumScopeDepthOrObjCQualsBits; /// The number of parameters preceding this parameter in the /// function parameter scope in which it was declared. @@ -1613,6 +1615,10 @@ return ParmVarDeclBits.ScopeDepthOrObjCQuals; } + static constexpr unsigned getMaxFunctionScopeDepth() { + return (1u << ParmVarDeclBitfields::NumScopeDepthOrObjCQualsBits) - 1; + } + /// Returns the index of this parameter in its prototype or method scope. unsigned getFunctionScopeIndex() const { return getParameterIndex(); Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -326,6 +326,8 @@ def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; +def err_function_scope_depth_exceeded : Error< + "function scope depth exceeded maximum of %0">, DefaultFatal; def err_missing_comma_before_ellipsis : Error< "C requires a comma prior to the ellipsis in a variadic function type">; def err_unexpected_typedef_ident : Error< Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -6576,6 +6576,18 @@ Actions.containsUnexpandedParameterPacks(ParmDeclarator)) DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator); + // Avoid exceeding the maximum function scope depth. + // See https://bugs.llvm.org/show_bug.cgi?id=19607 + // Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with + // getFunctionPrototypeDepth() - 1. + if (getCurScope()->getFunctionPrototypeDepth() - 1 > + ParmVarDecl::getMaxFunctionScopeDepth()) { + Diag(DSStart, diag::err_function_scope_depth_exceeded) + << ParmVarDecl::getMaxFunctionScopeDepth(); + cutOffParsing(); + return; + } + // Inform the actions module about the parameter declarator, so it gets // added to the current scope. Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator); Index: clang/test/Parser/nested_function_prototype_overflow.cpp =================================================================== --- /dev/null +++ clang/test/Parser/nested_function_prototype_overflow.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only +// RUN: not %clang_cc1 %s -fsyntax-only -DFAIL 2>&1 | FileCheck %s + +void foo(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)( +#ifdef FAIL +void (*f)() +#endif +))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); +// CHECK: fatal error: function scope depth exceeded maximum of 127 Index: clang/test/Parser/nested_lambda_overflow.cpp =================================================================== --- /dev/null +++ clang/test/Parser/nested_lambda_overflow.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -fsyntax-only +// RUN: not %clang_cc1 %s -fsyntax-only -DFAIL 2>&1 | FileCheck %s + +auto foo = [](void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)(void (*f)( +#ifdef FAIL +void (*f)() +#endif +))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) {}; +// CHECK: fatal error: function scope depth exceeded maximum of 127