[clang] [clang] Prevent stack overflow on deeply nested template arguments (PR #224393)
Daniel Petrovic via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 18 05:06:47 PDT 2026
https://github.com/daniel-petrovic updated https://github.com/llvm/llvm-project/pull/224393
>From 69c059ef8c75952e0c3aa6895c0917d0b78a046d Mon Sep 17 00:00:00 2001
From: Daniel Petrovic <daniel-dev at hotmail.de>
Date: Thu, 17 Sep 2026 21:44:57 +0200
Subject: [PATCH 1/2] [clang] Prevent stack overflow on deeply nested template
arguments
Limit template argument nesting and diagnose before exhausting the
parser stack.
Fixes #224114
---
clang/docs/ReleaseNotes.md | 4 ++
clang/docs/UsersManual.md | 5 +++
.../clang/Basic/DiagnosticParseKinds.td | 6 +++
clang/include/clang/Parse/Parser.h | 8 ++++
clang/lib/Parse/ParseTemplate.cpp | 39 +++++++++++++++++++
clang/test/Parser/template-argument-depth.cpp | 27 +++++++++++++
6 files changed, 89 insertions(+)
create mode 100644 clang/test/Parser/template-argument-depth.cpp
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f4a34a37aff52..09fbd65fbdab3 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -608,6 +608,10 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when a using-declaration naming an unresolvable member of a
dependent base was shadowed by an invalid using-declaration. (#GH209427)
+- Fixed a stack overflow (segfault) when parsing deeply nested template
+ arguments such as ``S<S<S<...>>>``. The parser now rejects nesting deeper
+ than ``-ftemplate-depth`` with a diagnostic. (#GH224114)
+
- Fixed a CTAD bug when combining with concepts. (#GH124715)
- Fixed a regression where an internal-linkage function (e.g. a `static` or
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 3bec20612c048..4b21d1137c83b 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -4446,6 +4446,11 @@ The default is 1048576, and the limit can be disabled with `-fconstexpr-steps=0`
Sets the limit for recursively nested template instantiations to N. The
default is 1024.
+
+This option also limits how deeply template arguments may be nested in the
+source (e.g. the number of levels in ``S<S<S<...>>>``). Nesting deeper than
+the limit is rejected with a diagnostic instead of overflowing the parser's
+stack.
:::
:::{option} -foperator-arrow-depth=N
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 594d158d25e92..bc5c58363a36a 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -675,6 +675,12 @@ def err_bracket_depth_exceeded : Error<
"bracket nesting level exceeded maximum of %0">, DefaultFatal;
def note_bracket_depth : Note<
"use -fbracket-depth=N to increase maximum nesting level">;
+def err_template_argument_depth_exceeded : Error<
+ "template argument nesting depth exceeded maximum of %0">, DefaultFatal;
+def err_template_argument_stack_exhausted : Error<
+ "stack nearly exhausted while parsing nested template arguments">, DefaultFatal;
+def note_template_argument_depth : Note<
+ "use -ftemplate-depth=N to increase maximum template argument nesting depth">;
def err_misplaced_ellipsis_in_declaration : Error<
"'...' must %select{immediately precede declared identifier|"
"be innermost component of anonymous pack declaration}0">;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index e9bab81b095fd..f4f05b56e5d82 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7930,6 +7930,14 @@ class Parser : public CodeCompletionHandler {
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
+ /// The current nesting depth of template argument lists being parsed. Each
+ /// level of nested template-ids (e.g. `A<B<C<...>>>`) recurses through the
+ /// parser's type/template disambiguation machinery, so without a limit the
+ /// parser's stack would overflow on deeply nested template arguments. This
+ /// is used to enforce a maximum nesting depth analogous to -ftemplate-depth
+ /// (see https://github.com/llvm/llvm-project/issues/224114).
+ unsigned TemplateArgumentDepth = 0;
+
/// RAII class that manages the template parameter depth.
class TemplateParameterDepthRAII {
unsigned &Depth;
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 1e5aa55338309..5d0949128eb63 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticParse.h"
+#include "clang/Basic/Stack.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
@@ -22,6 +23,23 @@
#include "clang/Sema/Scope.h"
using namespace clang;
+namespace {
+/// RAII class that manages the template argument nesting depth. Recursing into
+/// a nested template-id (e.g. the inner `S<...>` of `S<S<...>>`) dips through
+/// the parser's type/template disambiguation machinery, so deeply nested
+/// template arguments could overflow the parser's stack. The depth is tracked
+/// so that `Parser::ParseTemplateArgumentList` can enforce a maximum.
+class TemplateArgumentDepthRAII {
+ unsigned &Depth;
+
+public:
+ explicit TemplateArgumentDepthRAII(unsigned &Depth) : Depth(Depth) {
+ ++Depth;
+ }
+ ~TemplateArgumentDepthRAII() { --Depth; }
+};
+} // namespace
+
unsigned Parser::ReenterTemplateScopes(MultiParseScope &S, Decl *D) {
return Actions.ActOnReenterTemplateScope(D, [&] {
S.Enter(Scope::TemplateParamScope);
@@ -1384,6 +1402,27 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
ColonProtectionRAIIObject ColonProtection(*this, false);
+ // Nested template-ids (e.g. `S<S<S<...>>>`) recurse through the parser's
+ // type/template disambiguation machinery, which is deeply recursive. Bound
+ // the nesting depth to avoid overflowing the parser's stack (see
+ // https://github.com/llvm/llvm-project/issues/224114). The bounds follow
+ // -ftemplate-depth when available, and additionally bail out if we're
+ // genuinely low on stack space (which keeps even huge -ftemplate-depth
+ // overrides from overflowing the stack).
+ TemplateArgumentDepthRAII Depth(TemplateArgumentDepth);
+ bool DepthLimitExceeded =
+ TemplateArgumentDepth > getLangOpts().InstantiationDepth;
+ if (DepthLimitExceeded || isStackNearlyExhausted()) {
+ if (DepthLimitExceeded) {
+ Diag(OpenLoc, diag::err_template_argument_depth_exceeded)
+ << getLangOpts().InstantiationDepth;
+ Diag(OpenLoc, diag::note_template_argument_depth);
+ } else {
+ Diag(OpenLoc, diag::err_template_argument_stack_exhausted);
+ }
+ return true;
+ }
+
auto RunSignatureHelp = [&] {
if (!Template)
return QualType();
diff --git a/clang/test/Parser/template-argument-depth.cpp b/clang/test/Parser/template-argument-depth.cpp
new file mode 100644
index 0000000000000..a8eabf15dcde6
--- /dev/null
+++ b/clang/test/Parser/template-argument-depth.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -ftemplate-depth=64 -DRAISED %s
+// RUN: not %clang_cc1 -fsyntax-only -std=c++20 -ftemplate-depth=16 -DFAIL %s 2>&1 | FileCheck %s
+//
+// Parsing deeply nested template argument lists such as S<S<S<...>>> used to
+// overflow the parser's stack and crash (see
+// https://github.com/llvm/llvm-project/issues/224114). The parser now enforces
+// a maximum template argument nesting depth controlled by -ftemplate-depth.
+//
+// CHECK: fatal error: template argument nesting depth exceeded maximum of 16
+// CHECK-NOT: stack nearly exhausted
+// expected-no-diagnostics
+
+template <typename T> struct S {};
+
+// This nesting is well within the default -ftemplate-depth limit.
+using NoError = S<S<S<S<S<int>>>>>;
+
+#ifdef FAIL
+// Nesting deeper than -ftemplate-depth=16 must be rejected, not crash.
+using Trigger = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<int>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
+#endif
+
+#ifdef RAISED
+// Raising -ftemplate-depth increases the parser's allowance.
+using Raised = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<int>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
+#endif
>From 5c9edff0e21040724b7bd3838c674ba0501fda9c Mon Sep 17 00:00:00 2001
From: Daniel Petrovic <daniel-dev at hotmail.de>
Date: Fri, 18 Sep 2026 13:56:43 +0200
Subject: [PATCH 2/2] [clang] Fix stack exhaustion if parsing deeply nested
template arguments
Stack guard is missing on the path if parsing deeply nested template args.
Run template argument list parser under stack guard.
---
clang/docs/ReleaseNotes.md | 7 +-
clang/docs/UsersManual.md | 5 --
.../clang/Basic/DiagnosticParseKinds.td | 6 --
clang/include/clang/Parse/Parser.h | 8 --
clang/lib/Parse/ParseTemplate.cpp | 84 ++++++-------------
clang/test/Parser/template-argument-depth.cpp | 42 +++++-----
6 files changed, 53 insertions(+), 99 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 09fbd65fbdab3..d70dccd6e6e27 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -608,9 +608,10 @@ features cannot lower the translation-unit ABI level;
- Fixed a crash when a using-declaration naming an unresolvable member of a
dependent base was shadowed by an invalid using-declaration. (#GH209427)
-- Fixed a stack overflow (segfault) when parsing deeply nested template
- arguments such as ``S<S<S<...>>>``. The parser now rejects nesting deeper
- than ``-ftemplate-depth`` with a diagnostic. (#GH224114)
+- Fixed a stack overflow when parsing deeply nested template arguments such
+ as ``S<S<S<...>>>``. Parsing now goes through the existing stack guard, which
+ continues on a fresh stack instead of crashing when the parser's stack is
+ nearly exhausted. (#GH224114)
- Fixed a CTAD bug when combining with concepts. (#GH124715)
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index 4b21d1137c83b..3bec20612c048 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -4446,11 +4446,6 @@ The default is 1048576, and the limit can be disabled with `-fconstexpr-steps=0`
Sets the limit for recursively nested template instantiations to N. The
default is 1024.
-
-This option also limits how deeply template arguments may be nested in the
-source (e.g. the number of levels in ``S<S<S<...>>>``). Nesting deeper than
-the limit is rejected with a diagnostic instead of overflowing the parser's
-stack.
:::
:::{option} -foperator-arrow-depth=N
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index bc5c58363a36a..594d158d25e92 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -675,12 +675,6 @@ def err_bracket_depth_exceeded : Error<
"bracket nesting level exceeded maximum of %0">, DefaultFatal;
def note_bracket_depth : Note<
"use -fbracket-depth=N to increase maximum nesting level">;
-def err_template_argument_depth_exceeded : Error<
- "template argument nesting depth exceeded maximum of %0">, DefaultFatal;
-def err_template_argument_stack_exhausted : Error<
- "stack nearly exhausted while parsing nested template arguments">, DefaultFatal;
-def note_template_argument_depth : Note<
- "use -ftemplate-depth=N to increase maximum template argument nesting depth">;
def err_misplaced_ellipsis_in_declaration : Error<
"'...' must %select{immediately precede declared identifier|"
"be innermost component of anonymous pack declaration}0">;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index f4f05b56e5d82..e9bab81b095fd 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -7930,14 +7930,6 @@ class Parser : public CodeCompletionHandler {
/// The "depth" of the template parameters currently being parsed.
unsigned TemplateParameterDepth;
- /// The current nesting depth of template argument lists being parsed. Each
- /// level of nested template-ids (e.g. `A<B<C<...>>>`) recurses through the
- /// parser's type/template disambiguation machinery, so without a limit the
- /// parser's stack would overflow on deeply nested template arguments. This
- /// is used to enforce a maximum nesting depth analogous to -ftemplate-depth
- /// (see https://github.com/llvm/llvm-project/issues/224114).
- unsigned TemplateArgumentDepth = 0;
-
/// RAII class that manages the template parameter depth.
class TemplateParameterDepthRAII {
unsigned &Depth;
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 5d0949128eb63..53fd4416c6e46 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -14,7 +14,6 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticParse.h"
-#include "clang/Basic/Stack.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
@@ -23,23 +22,6 @@
#include "clang/Sema/Scope.h"
using namespace clang;
-namespace {
-/// RAII class that manages the template argument nesting depth. Recursing into
-/// a nested template-id (e.g. the inner `S<...>` of `S<S<...>>`) dips through
-/// the parser's type/template disambiguation machinery, so deeply nested
-/// template arguments could overflow the parser's stack. The depth is tracked
-/// so that `Parser::ParseTemplateArgumentList` can enforce a maximum.
-class TemplateArgumentDepthRAII {
- unsigned &Depth;
-
-public:
- explicit TemplateArgumentDepthRAII(unsigned &Depth) : Depth(Depth) {
- ++Depth;
- }
- ~TemplateArgumentDepthRAII() { --Depth; }
-};
-} // namespace
-
unsigned Parser::ReenterTemplateScopes(MultiParseScope &S, Decl *D) {
return Actions.ActOnReenterTemplateScope(D, [&] {
S.Enter(Scope::TemplateParamScope);
@@ -1402,27 +1384,6 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
ColonProtectionRAIIObject ColonProtection(*this, false);
- // Nested template-ids (e.g. `S<S<S<...>>>`) recurse through the parser's
- // type/template disambiguation machinery, which is deeply recursive. Bound
- // the nesting depth to avoid overflowing the parser's stack (see
- // https://github.com/llvm/llvm-project/issues/224114). The bounds follow
- // -ftemplate-depth when available, and additionally bail out if we're
- // genuinely low on stack space (which keeps even huge -ftemplate-depth
- // overrides from overflowing the stack).
- TemplateArgumentDepthRAII Depth(TemplateArgumentDepth);
- bool DepthLimitExceeded =
- TemplateArgumentDepth > getLangOpts().InstantiationDepth;
- if (DepthLimitExceeded || isStackNearlyExhausted()) {
- if (DepthLimitExceeded) {
- Diag(OpenLoc, diag::err_template_argument_depth_exceeded)
- << getLangOpts().InstantiationDepth;
- Diag(OpenLoc, diag::note_template_argument_depth);
- } else {
- Diag(OpenLoc, diag::err_template_argument_stack_exhausted);
- }
- return true;
- }
-
auto RunSignatureHelp = [&] {
if (!Template)
return QualType();
@@ -1431,27 +1392,36 @@ bool Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
Template, TemplateArgs, OpenLoc);
};
- do {
- PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
- ParsedTemplateArgument Arg = ParseTemplateArgument();
- SourceLocation EllipsisLoc;
- if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
- Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
-
- if (Arg.isInvalid()) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
- RunSignatureHelp();
- return true;
- }
+ // Nested template-ids (e.g. `S<S<S<...>>>`) recurse through the parser's
+ // type/template disambiguation machinery, which is deeply recursive. Run the
+ // parse with the stack guard so that a deeply nested argument list (see
+ // https://github.com/llvm/llvm-project/issues/224114) continues on a fresh
+ // stack instead of overflowing the parser's stack.
+ bool Invalid = false;
+ StackHandler.runWithSufficientStackSpace(OpenLoc, [&, this]() {
+ do {
+ PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
+ ParsedTemplateArgument Arg = ParseTemplateArgument();
+ SourceLocation EllipsisLoc;
+ if (TryConsumeToken(tok::ellipsis, EllipsisLoc))
+ Arg = Actions.ActOnPackExpansion(Arg, EllipsisLoc);
+
+ if (Arg.isInvalid()) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
+ Invalid = true;
+ return;
+ }
- // Save this template argument.
- TemplateArgs.push_back(Arg);
+ // Save this template argument.
+ TemplateArgs.push_back(Arg);
- // If the next token is a comma, consume it and keep reading
- // arguments.
- } while (TryConsumeToken(tok::comma));
+ // If the next token is a comma, consume it and keep reading
+ // arguments.
+ } while (TryConsumeToken(tok::comma));
+ });
- return false;
+ return Invalid;
}
Parser::DeclGroupPtrTy Parser::ParseExplicitInstantiation(
diff --git a/clang/test/Parser/template-argument-depth.cpp b/clang/test/Parser/template-argument-depth.cpp
index a8eabf15dcde6..fd9e2224aabbf 100644
--- a/clang/test/Parser/template-argument-depth.cpp
+++ b/clang/test/Parser/template-argument-depth.cpp
@@ -1,27 +1,29 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++20 -ftemplate-depth=64 -DRAISED %s
-// RUN: not %clang_cc1 -fsyntax-only -std=c++20 -ftemplate-depth=16 -DFAIL %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
//
// Parsing deeply nested template argument lists such as S<S<S<...>>> used to
// overflow the parser's stack and crash (see
-// https://github.com/llvm/llvm-project/issues/224114). The parser now enforces
-// a maximum template argument nesting depth controlled by -ftemplate-depth.
+// https://github.com/llvm/llvm-project/issues/224114). The parser now runs
+// this recursion through the existing stack guard, which continues parsing on
+// a fresh stack when the parser's stack is nearly exhausted instead of
+// crashing.
//
-// CHECK: fatal error: template argument nesting depth exceeded maximum of 16
-// CHECK-NOT: stack nearly exhausted
-// expected-no-diagnostics
+// REQUIRES: thread_support
+//
+// The UNSUPPORTED lines below are copied from clang/test/SemaTemplate/
+// stack-exhaustion.cpp, which exercises the same stack-guard machinery.
+//
+// FIXME: Detection of, or recovery from, stack exhaustion does not work on
+// NetBSD at the moment. Since this is a best-effort mitigation for exceeding
+// implementation limits, just disable the test.
+// UNSUPPORTED: system-netbsd
+//
+// asan has its own stack-overflow check.
+// UNSUPPORTED: asan
+//
+// expected-warning@* 0-2{{stack nearly exhausted}}
template <typename T> struct S {};
-// This nesting is well within the default -ftemplate-depth limit.
-using NoError = S<S<S<S<S<int>>>>>;
-
-#ifdef FAIL
-// Nesting deeper than -ftemplate-depth=16 must be rejected, not crash.
-using Trigger = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<int>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
-#endif
-
-#ifdef RAISED
-// Raising -ftemplate-depth increases the parser's allowance.
-using Raised = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<int>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
-#endif
+// This nesting (2000 levels) is deep enough to overflow the parser's stack
+// without the stack guard on a typical 8 MiB stack.
+using Trigger = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<int>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
More information about the cfe-commits
mailing list