forked from qt-creator/qt-creator
C++: fix cloning of templates
Fix instantiation of templates(by cloning original symbols). Assigning of scope for cloned symbol is taken from the symbol which is used to instantiate. Task-number: QTCREATORBUG-9098 Change-Id: I066cc8b5f69333fabdaf2d4466b205baf08bd3f1 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
committed by
Nikolai Kosjar
parent
b55961d225
commit
17cd161a9d
7
src/libs/3rdparty/cplusplus/Symbol.cpp
vendored
7
src/libs/3rdparty/cplusplus/Symbol.cpp
vendored
@@ -105,7 +105,7 @@ Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, const
|
|||||||
|
|
||||||
Symbol::Symbol(Clone *clone, Subst *subst, Symbol *original)
|
Symbol::Symbol(Clone *clone, Subst *subst, Symbol *original)
|
||||||
: _name(clone->name(original->_name, subst)),
|
: _name(clone->name(original->_name, subst)),
|
||||||
_scope(original->_scope),
|
_scope(0),
|
||||||
_next(0),
|
_next(0),
|
||||||
_fileId(clone->control()->stringLiteral(original->fileName(), original->fileNameLength())),
|
_fileId(clone->control()->stringLiteral(original->fileName(), original->fileNameLength())),
|
||||||
_sourceLocation(original->_sourceLocation),
|
_sourceLocation(original->_sourceLocation),
|
||||||
@@ -296,6 +296,11 @@ Block *Symbol::enclosingBlock() const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope *Symbol::scope() const
|
||||||
|
{
|
||||||
|
return _scope;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned Symbol::index() const
|
unsigned Symbol::index() const
|
||||||
{ return _index; }
|
{ return _index; }
|
||||||
|
|
||||||
|
|||||||
1
src/libs/3rdparty/cplusplus/Symbol.h
vendored
1
src/libs/3rdparty/cplusplus/Symbol.h
vendored
@@ -290,6 +290,7 @@ public:
|
|||||||
/// Returns the enclosing Block scope.
|
/// Returns the enclosing Block scope.
|
||||||
Block *enclosingBlock() const;
|
Block *enclosingBlock() const;
|
||||||
|
|
||||||
|
Scope *scope() const;
|
||||||
void setScope(Scope *enclosingScope); // ### make me private
|
void setScope(Scope *enclosingScope); // ### make me private
|
||||||
void resetScope(); // ### make me private
|
void resetScope(); // ### make me private
|
||||||
void setSourceLocation(unsigned sourceLocation, TranslationUnit *translationUnit); // ### make me private
|
void setSourceLocation(unsigned sourceLocation, TranslationUnit *translationUnit); // ### make me private
|
||||||
|
|||||||
@@ -936,6 +936,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
|
|||||||
|
|
||||||
foreach (Symbol *s, reference->symbols()) {
|
foreach (Symbol *s, reference->symbols()) {
|
||||||
Symbol *clone = cloner.symbol(s, &subst);
|
Symbol *clone = cloner.symbol(s, &subst);
|
||||||
|
clone->setScope(s->scope());
|
||||||
instantiation->_symbols.append(clone);
|
instantiation->_symbols.append(clone);
|
||||||
#ifdef DEBUG_LOOKUP
|
#ifdef DEBUG_LOOKUP
|
||||||
Overview oo;oo.showFunctionSignatures = true;
|
Overview oo;oo.showFunctionSignatures = true;
|
||||||
@@ -1089,6 +1090,7 @@ void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *en
|
|||||||
|
|
||||||
foreach (Symbol *s, nestedClassOrNamespace->_symbols) {
|
foreach (Symbol *s, nestedClassOrNamespace->_symbols) {
|
||||||
Symbol *clone = _cloner.symbol(s, &_subst);
|
Symbol *clone = _cloner.symbol(s, &_subst);
|
||||||
|
clone->setScope(s->scope());
|
||||||
nestedClassOrNamespaceInstantiation->_symbols.append(clone);
|
nestedClassOrNamespaceInstantiation->_symbols.append(clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1843,3 +1843,42 @@ void CppToolsPlugin::test_completion_namespace_alias_with_many_namespace_declara
|
|||||||
QVERIFY(completions.contains(QLatin1String("Foo1")));
|
QVERIFY(completions.contains(QLatin1String("Foo1")));
|
||||||
QVERIFY(completions.contains(QLatin1String("Foo2")));
|
QVERIFY(completions.contains(QLatin1String("Foo2")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppToolsPlugin::test_completion_QTCREATORBUG9098()
|
||||||
|
{
|
||||||
|
TestData data;
|
||||||
|
data.srcText =
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class B\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" C<T> c;\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" B<T> b;\n"
|
||||||
|
" void fun()\n"
|
||||||
|
" {\n"
|
||||||
|
" @\n"
|
||||||
|
" // padding so we get the scope right\n"
|
||||||
|
" }\n"
|
||||||
|
"};\n"
|
||||||
|
|
||||||
|
;
|
||||||
|
setup(&data);
|
||||||
|
|
||||||
|
Utils::ChangeSet change;
|
||||||
|
QString txt = QLatin1String("b.");
|
||||||
|
change.insert(data.pos, txt);
|
||||||
|
QTextCursor cursor(data.doc);
|
||||||
|
change.apply(&cursor);
|
||||||
|
data.pos += txt.length();
|
||||||
|
|
||||||
|
QStringList completions = getCompletions(data);
|
||||||
|
|
||||||
|
QCOMPARE(completions.size(), 2);
|
||||||
|
QVERIFY(completions.contains(QLatin1String("c")));
|
||||||
|
QVERIFY(completions.contains(QLatin1String("B")));
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ private slots:
|
|||||||
void test_completion_typedef_using_templates1();
|
void test_completion_typedef_using_templates1();
|
||||||
void test_completion_typedef_using_templates2();
|
void test_completion_typedef_using_templates2();
|
||||||
void test_completion_namespace_alias_with_many_namespace_declarations();
|
void test_completion_namespace_alias_with_many_namespace_declarations();
|
||||||
|
void test_completion_QTCREATORBUG9098();
|
||||||
|
|
||||||
void test_format_pointerdeclaration_in_simpledeclarations();
|
void test_format_pointerdeclaration_in_simpledeclarations();
|
||||||
void test_format_pointerdeclaration_in_simpledeclarations_data();
|
void test_format_pointerdeclaration_in_simpledeclarations_data();
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ private slots:
|
|||||||
void test_checksymbols_QTCREATORBUG8974_danglingPointer();
|
void test_checksymbols_QTCREATORBUG8974_danglingPointer();
|
||||||
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
void operatorAsteriskOfNestedClassOfTemplateClass_QTCREATORBUG9006();
|
||||||
void test_checksymbols_templated_functions();
|
void test_checksymbols_templated_functions();
|
||||||
|
void test_checksymbols_QTCREATORBUG9098();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
void tst_CheckSymbols::test_checksymbols_TypeUse()
|
||||||
@@ -1415,6 +1416,44 @@ void tst_CheckSymbols::test_checksymbols_templated_functions()
|
|||||||
<< Use(6, 17, 1, SemanticInfo::TypeUse)
|
<< Use(6, 17, 1, SemanticInfo::TypeUse)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_CheckSymbols::test_checksymbols_QTCREATORBUG9098()
|
||||||
|
{
|
||||||
|
const QByteArray source =
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class B\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" C<T> c;\n"
|
||||||
|
"};\n"
|
||||||
|
"template <typename T>\n"
|
||||||
|
"class A\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" B<T> b;\n"
|
||||||
|
" void fun()\n"
|
||||||
|
" {\n"
|
||||||
|
" b.c;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
const QList<Use> expectedUses = QList<Use>()
|
||||||
|
<< Use(1, 20, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(2, 7, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(5, 7, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(5, 10, 1, SemanticInfo::FieldUse)
|
||||||
|
<< Use(7, 20, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(8, 7, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(11, 5, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(11, 7, 1, SemanticInfo::TypeUse)
|
||||||
|
<< Use(11, 10, 1, SemanticInfo::FieldUse)
|
||||||
|
<< Use(12, 10, 3, SemanticInfo::FunctionUse)
|
||||||
|
<< Use(14, 9, 1, SemanticInfo::FieldUse)
|
||||||
|
<< Use(14, 11, 1, SemanticInfo::FieldUse)
|
||||||
|
;
|
||||||
|
|
||||||
TestData::check(source, expectedUses);
|
TestData::check(source, expectedUses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user