forked from qt-creator/qt-creator
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: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
a27cd12538
commit
0bcddcd014
@@ -1549,6 +1549,7 @@ CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snaps
|
|||||||
: _snapshot(snapshot)
|
: _snapshot(snapshot)
|
||||||
, _control(QSharedPointer<Control>(new Control))
|
, _control(QSharedPointer<Control>(new Control))
|
||||||
, _expandTemplates(false)
|
, _expandTemplates(false)
|
||||||
|
, _depth(0)
|
||||||
{
|
{
|
||||||
_globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
|
_globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
|
||||||
_currentLookupScope = _globalNamespace;
|
_currentLookupScope = _globalNamespace;
|
||||||
@@ -1978,8 +1979,13 @@ void CreateBindings::initializeSubst(Clone &cloner,
|
|||||||
{
|
{
|
||||||
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
|
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
|
||||||
|
|
||||||
|
if (_depth > 15)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++_depth;
|
||||||
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
|
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
|
||||||
resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
|
resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
|
||||||
|
--_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CPlusPlus
|
} // namespace CPlusPlus
|
||||||
|
@@ -209,6 +209,7 @@ private:
|
|||||||
LookupScope *_globalNamespace;
|
LookupScope *_globalNamespace;
|
||||||
LookupScope *_currentLookupScope;
|
LookupScope *_currentLookupScope;
|
||||||
bool _expandTemplates;
|
bool _expandTemplates;
|
||||||
|
int _depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPLUSPLUS_EXPORT LookupContext
|
class CPLUSPLUS_EXPORT LookupContext
|
||||||
|
@@ -225,6 +225,8 @@ private slots:
|
|||||||
void test_checksymbols_infiniteLoop_data();
|
void test_checksymbols_infiniteLoop_data();
|
||||||
void test_checksymbols_infiniteLoop();
|
void test_checksymbols_infiniteLoop();
|
||||||
|
|
||||||
|
void test_checksymbols_infiniteLoop_BUG15141();
|
||||||
|
|
||||||
void test_parentOfBlock();
|
void test_parentOfBlock();
|
||||||
|
|
||||||
void findField();
|
void findField();
|
||||||
@@ -1122,6 +1124,25 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop()
|
|||||||
TestCase::runCheckSymbols(document1, snapshot);
|
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()
|
void tst_CheckSymbols::test_parentOfBlock()
|
||||||
{
|
{
|
||||||
const QByteArray source = "void C::f()\n"
|
const QByteArray source = "void C::f()\n"
|
||||||
|
Reference in New Issue
Block a user