Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5092,6 +5092,11 @@ DefaultFatal, NoSFINAE; def note_template_recursion_depth : Note< "use -ftemplate-depth=N to increase recursive template instantiation depth">; +def err_integer_sequence_length_exceeded + : Error<"'__make_integer_seq' exceeded maximum limit of %0">; +def note_integer_sequence_length_exceeded + : Note<"use -fint-seq-limit=N to increase '__make_integer_seq' " + "limit">; def err_template_instantiate_within_definition : Error< "%select{implicit|explicit}0 instantiation of template %1 within its" Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -362,6 +362,8 @@ "maximum constexpr call depth") BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576, "maximum constexpr evaluation steps") +BENIGN_LANGOPT(MakeIntSeqSize, 32, 16777216, + "maximum value for __make_integer_seq") BENIGN_LANGOPT(EnableNewConstInterp, 1, 0, "enable the experimental new constant interpreter") BENIGN_LANGOPT(BracketDepth, 32, 256, Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2626,6 +2626,7 @@ Group; def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">, Group; +def fint_seq_limit_EQ : Joined<["-"], "fint-seq-limit=">, Group; def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">, Group, HelpText<"Generate a YAML optimization record file">; @@ -5679,6 +5680,9 @@ def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">, HelpText<"Maximum number of 'operator->'s to call for a member access">, MarshallingInfoInt, "256">; +def fint_seq_limit : Separate<["-"], "fint-seq-limit">, + HelpText<"Maximum value of the __make_integer_seq builtin">, + MarshallingInfoInt, "16777216">; def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">, HelpText<"Maximum depth of recursive constexpr function calls">, MarshallingInfoInt, "512">; Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5617,6 +5617,11 @@ CmdArgs.push_back(A->getValue()); } + if (Arg *A = Args.getLastArg(options::OPT_fint_seq_limit_EQ)) { + CmdArgs.push_back("-fint-seq-limit"); + CmdArgs.push_back(A->getValue()); + } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { CmdArgs.push_back("-fconstexpr-depth"); CmdArgs.push_back(A->getValue()); Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -3452,6 +3452,18 @@ return QualType(); } + // The below loop ends up taking a very long time and causing an OOM crash + // if 'N' is too large. Limit to a command-line specified value. + if (NumArgs > SemaRef.getLangOpts().MakeIntSeqSize) { + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::err_integer_sequence_length_exceeded) + << SemaRef.getLangOpts().MakeIntSeqSize; + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::note_integer_sequence_length_exceeded) + << SemaRef.getLangOpts().MakeIntSeqSize; + return QualType(); + } + QualType ArgTy = NumArgsArg.getIntegralType(); TemplateArgumentListInfo SyntheticTemplateArgs; // The type argument gets reused as the first template argument in the Index: clang/test/SemaCXX/make_integer_seq.cpp =================================================================== --- clang/test/SemaCXX/make_integer_seq.cpp +++ clang/test/SemaCXX/make_integer_seq.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify=expected,smalllimit -fint-seq-limit 500 -std=c++11 %s static_assert(__has_builtin(__make_integer_seq), ""); @@ -51,3 +52,18 @@ __make_integer_seq<__make_integer_seq, int, 10> PR28494; // expected-error{{different template parameters}} // expected-note@make_integer_seq.cpp:* {{template parameter has a different kind}} // expected-note@make_integer_seq.cpp:* {{previous template template parameter is here}} + +__make_integer_seq PR48246; +// smalllimit-error@-1{{'__make_integer_seq' exceeded maximum limit of 500}} +// smalllimit-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}} + +// Default value is ~16.7 million, so without the command line option, fail. +__make_integer_seq PR48246_b; +// expected-error@-1{{'__make_integer_seq' exceeded maximum limit of}} +// expected-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}} + +using size_t = unsigned long long; + +__make_integer_seq PR48246_c; +// expected-error@-1{{'__make_integer_seq' exceeded maximum limit of}} +// expected-note@-2 {{use -fint-seq-limit=N to increase '__make_integer_seq' limit}}