Author: Mark de Wever Date: 2019-11-09T15:33:01+01:00 New Revision: b9be5ce8f3e0e697a61ad16e2c669de6ea8f8739
URL: https://github.com/llvm/llvm-project/commit/b9be5ce8f3e0e697a61ad16e2c669de6ea8f8739 DIFF: https://github.com/llvm/llvm-project/commit/b9be5ce8f3e0e697a61ad16e2c669de6ea8f8739.diff LOG: [Parser] Warn when ScopeDepthOrObjCQuals overflows Before when the overflow occured an assertion was triggered. Now check whether the maximum has been reached and warn properly. This patch fixes the original submission of PR19607. Differential Revision: https://reviews.llvm.org/D63975 Added: clang/test/Parser/nested_blocks_overflow.cpp clang/test/Parser/nested_function_prototype_overflow.cpp clang/test/Parser/nested_lambda_overflow.cpp Modified: clang/include/clang/AST/Decl.h clang/include/clang/Basic/DiagnosticParseKinds.td clang/lib/Parse/ParseDecl.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 16094c0988fa..31adfc5c368a 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -921,11 +921,13 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { /// 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. @@ -1650,6 +1652,10 @@ class ParmVarDecl : public VarDecl { 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(); diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 7c9f4da778a6..dc9f677ec5b6 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -325,6 +325,8 @@ def err_for_range_expected_decl : Error< 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< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c41eb74a9cf3..e5c17a3131ab 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6566,6 +6566,19 @@ void Parser::ParseParameterDeclarationClause( ParsedAttributes &FirstArgAttrs, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, SourceLocation &EllipsisLoc) { + + // 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(Tok.getLocation(), diag::err_function_scope_depth_exceeded) + << ParmVarDecl::getMaxFunctionScopeDepth(); + cutOffParsing(); + return; + } + do { // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq // before deciding this was a parameter-declaration-clause. diff --git a/clang/test/Parser/nested_blocks_overflow.cpp b/clang/test/Parser/nested_blocks_overflow.cpp new file mode 100644 index 000000000000..e8366a8d56a2 --- /dev/null +++ b/clang/test/Parser/nested_blocks_overflow.cpp @@ -0,0 +1,54 @@ +// RUN: %clang %s -fsyntax-only -fblocks -fbracket-depth=512 +// RUN: not %clang %s -fsyntax-only -fblocks -fbracket-depth=512 -DFAIL 2>&1 | FileCheck %s + +template <class T> int foo(T &&t); + +void bar(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( + +^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo(^(int x = foo( + +#ifdef FAIL +^(int x = foo( +#endif + +^(int x = foo(1)){} + +#ifdef FAIL +)){} +#endif + +)){})){})){})){})){})){} + +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)); + +// CHECK: fatal error: function scope depth exceeded maximum of 127 diff --git a/clang/test/Parser/nested_function_prototype_overflow.cpp b/clang/test/Parser/nested_function_prototype_overflow.cpp new file mode 100644 index 000000000000..29b382d8c3b2 --- /dev/null +++ b/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 diff --git a/clang/test/Parser/nested_lambda_overflow.cpp b/clang/test/Parser/nested_lambda_overflow.cpp new file mode 100644 index 000000000000..afaa9dca635c --- /dev/null +++ b/clang/test/Parser/nested_lambda_overflow.cpp @@ -0,0 +1,55 @@ +// RUN: %clang %s -fsyntax-only -fbracket-depth=512 +// RUN: not %clang %s -fsyntax-only -fbracket-depth=512 -DFAIL 2>&1 | FileCheck %s + +template <class T> int foo(T &&t); + +void bar(int x = foo( + +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( + +[](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo([](int x = foo( + +#ifdef FAIL +[](int x = foo( +#endif + +[](int x = foo(1)){} + +#ifdef FAIL +)){} +#endif + +)){})){})){})){})){})){} + +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)){})){})){})){})){})){})){})){} +)); + +// CHECK: fatal error: function scope depth exceeded maximum of 127 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits