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)
|
||||
, _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"
|
||||
|
Reference in New Issue
Block a user