forked from qt-creator/qt-creator
C++: Avoid inline namespaces in generated code
Task-number: QTCREATORBUG-16086 Change-Id: Ic2f3fd38ae6cc93725bc214c24320f40a0a519a8 Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -230,6 +230,32 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2)
|
|||||||
return QByteArray(s1->fileName()) == QByteArray(s2->fileName());
|
return QByteArray(s1->fileName()) == QByteArray(s2->fileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const Name *toName(const QList<const Name *> &names, Control *control)
|
||||||
|
{
|
||||||
|
const Name *n = 0;
|
||||||
|
for (int i = names.size() - 1; i >= 0; --i) {
|
||||||
|
if (! n)
|
||||||
|
n = names.at(i);
|
||||||
|
else
|
||||||
|
n = control->qualifiedNameId(names.at(i), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isInlineNamespace(ClassOrNamespace *con, const Name *name)
|
||||||
|
{
|
||||||
|
const QList<LookupItem> items = con->find(name);
|
||||||
|
if (!items.isEmpty()) {
|
||||||
|
if (const Symbol *declaration = items.first().declaration() ) {
|
||||||
|
if (const Namespace *ns = declaration->asNamespace())
|
||||||
|
return ns->isInline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control)
|
const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control)
|
||||||
{
|
{
|
||||||
const Name *n = 0;
|
const Name *n = 0;
|
||||||
@@ -245,8 +271,17 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
|||||||
if (target) {
|
if (target) {
|
||||||
const QList<LookupItem> tresults = target->lookup(n);
|
const QList<LookupItem> tresults = target->lookup(n);
|
||||||
foreach (const LookupItem &tr, tresults) {
|
foreach (const LookupItem &tr, tresults) {
|
||||||
if (symbolIdentical(tr.declaration(), symbol))
|
if (symbolIdentical(tr.declaration(), symbol)) {
|
||||||
return n;
|
// eliminate inline namespaces
|
||||||
|
QList<const Name *> minimal = names.mid(i);
|
||||||
|
for (int i = minimal.size() - 2; i >= 0; --i) {
|
||||||
|
const Name *candidate = toName(minimal.mid(0, i + 1), control);
|
||||||
|
if (isInlineNamespace(target, candidate))
|
||||||
|
minimal.removeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toName(minimal, control);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <cplusplus/Literals.h>
|
#include <cplusplus/Literals.h>
|
||||||
#include <cplusplus/LookupContext.h>
|
#include <cplusplus/LookupContext.h>
|
||||||
#include <cplusplus/Name.h>
|
#include <cplusplus/Name.h>
|
||||||
|
#include <cplusplus/NamePrettyPrinter.h>
|
||||||
#include <cplusplus/Overview.h>
|
#include <cplusplus/Overview.h>
|
||||||
#include <cplusplus/ResolveExpression.h>
|
#include <cplusplus/ResolveExpression.h>
|
||||||
#include <cplusplus/Symbols.h>
|
#include <cplusplus/Symbols.h>
|
||||||
@@ -99,6 +100,9 @@ private slots:
|
|||||||
void templates_3();
|
void templates_3();
|
||||||
void templates_4();
|
void templates_4();
|
||||||
void templates_5();
|
void templates_5();
|
||||||
|
|
||||||
|
void minimalname_data();
|
||||||
|
void minimalname();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Lookup::base_class_defined_1()
|
void tst_Lookup::base_class_defined_1()
|
||||||
@@ -631,5 +635,47 @@ void tst_Lookup::templates_5()
|
|||||||
QVERIFY(doc->diagnosticMessages().isEmpty());
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_Lookup::minimalname_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QByteArray>("source");
|
||||||
|
QTest::addColumn<int>("index");
|
||||||
|
|
||||||
|
QTest::newRow("inlineNamespace1")
|
||||||
|
<< QByteArray("namespace std { inline namespace __cxx11 { class string{}; } }\n")
|
||||||
|
<< 0;
|
||||||
|
|
||||||
|
// This case is extracted from libstdc++ 5.4.0.
|
||||||
|
// The inline namespace is re-opened as non-inline, which is not standard
|
||||||
|
// compliant. However, gcc does this and clang only issues a warning.
|
||||||
|
QTest::newRow("inlineNamespace2")
|
||||||
|
<< QByteArray("namespace std { inline namespace __cxx11 {} }\n"
|
||||||
|
"namespace std { namespace __cxx11 { class string{}; } }\n")
|
||||||
|
<< 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_Lookup::minimalname()
|
||||||
|
{
|
||||||
|
QFETCH(QByteArray, source);
|
||||||
|
QFETCH(int, index);
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("minimalname");
|
||||||
|
doc->setUtf8Source(source);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
LookupContext ctx(doc, snapshot);
|
||||||
|
Control control;
|
||||||
|
Symbol *symbol = doc->globalSymbolAt(unsigned(index))
|
||||||
|
->asNamespace()->memberAt(0)->asNamespace()->memberAt(0);
|
||||||
|
|
||||||
|
const Name *minimalName = LookupContext::minimalName(symbol, ctx.globalNamespace(), &control);
|
||||||
|
|
||||||
|
Overview oo;
|
||||||
|
const QString minimalNameAsString = NamePrettyPrinter(&oo)(minimalName);
|
||||||
|
QCOMPARE(minimalNameAsString, QString::fromUtf8("std::string"));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_Lookup)
|
QTEST_APPLESS_MAIN(tst_Lookup)
|
||||||
#include "tst_lookup.moc"
|
#include "tst_lookup.moc"
|
||||||
|
|||||||
Reference in New Issue
Block a user