Commit 0bcddcd0 authored by Orgad Shaneh's avatar Orgad Shaneh Committed by Orgad Shaneh

C++: Limit template instantiation depth

A recursive template generates infinite expansions.

Consider the following example:

template <class R1>
struct Base
{
};

template<typename R>
struct Derived :
  Base<
    typename Derived<typename Base<R>::type>::type,
    typename Derived<typename Base<R>::type>::type
  >::type
{};

R is instantiated as Base<R>::type, which causes another
instantiation of R into Base<Base<R>> etc...

This is not a solution, but a workaround.

Task-number: QTCREATORBUG-15141
Change-Id: Ib04f70275e07919e2cb6c7fb61a2045bd52f4a7d
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@theqtcompany.com>
parent a27cd125
......@@ -1549,6 +1549,7 @@ CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snaps
: _snapshot(snapshot)
, _control(QSharedPointer<Control>(new Control))
, _expandTemplates(false)
, _depth(0)
{
_globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
_currentLookupScope = _globalNamespace;
......@@ -1978,8 +1979,13 @@ void CreateBindings::initializeSubst(Clone &cloner,
{
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
if (_depth > 15)
return;
++_depth;
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
--_depth;
}
} // namespace CPlusPlus
......@@ -209,6 +209,7 @@ private:
LookupScope *_globalNamespace;
LookupScope *_currentLookupScope;
bool _expandTemplates;
int _depth;
};
class CPLUSPLUS_EXPORT LookupContext
......
......@@ -225,6 +225,8 @@ private slots:
void test_checksymbols_infiniteLoop_data();
void test_checksymbols_infiniteLoop();
void test_checksymbols_infiniteLoop_BUG15141();
void test_parentOfBlock();
void findField();
......@@ -1122,6 +1124,25 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop()
TestCase::runCheckSymbols(document1, snapshot);
}
void tst_CheckSymbols::test_checksymbols_infiniteLoop_BUG15141()
{
QByteArray source =
"template <class R1>\n"
"struct Base\n"
"{\n"
"};\n"
"\n"
"template<typename R>\n"
"struct Derived :\n"
" Base<\n"
" typename Derived<typename Base<R>::type>::type,\n"
" typename Derived<typename Base<R>::type>::type\n"
" >::type\n"
"{};\n";
BaseTestCase tc(source);
}
void tst_CheckSymbols::test_parentOfBlock()
{
const QByteArray source = "void C::f()\n"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment