diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-02-21 14:18:07 +0100 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-02-23 14:49:31 +0000 |
commit | fe27f947b916a6b7333be50127c219bafb3d2353 (patch) | |
tree | 20afb0bdc7efb186bddb5abf0a62f2a5e029e695 | |
parent | 4637b3fed7a456ec664ae9ba1de5c03b32aa12fd (diff) | |
download | qt-creator-fe27f947b916a6b7333be50127c219bafb3d2353.tar.gz |
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>
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 39 | ||||
-rw-r--r-- | tests/auto/cplusplus/lookup/tst_lookup.cpp | 46 |
2 files changed, 83 insertions, 2 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 0a9138911e..881c985f86 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -230,6 +230,32 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2) 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 *n = 0; @@ -245,8 +271,17 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, if (target) { const QList<LookupItem> tresults = target->lookup(n); foreach (const LookupItem &tr, tresults) { - if (symbolIdentical(tr.declaration(), symbol)) - return n; + if (symbolIdentical(tr.declaration(), symbol)) { + // 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); + } } } } diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp index eaa015a425..98af0cbc15 100644 --- a/tests/auto/cplusplus/lookup/tst_lookup.cpp +++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp @@ -32,6 +32,7 @@ #include <cplusplus/Literals.h> #include <cplusplus/LookupContext.h> #include <cplusplus/Name.h> +#include <cplusplus/NamePrettyPrinter.h> #include <cplusplus/Overview.h> #include <cplusplus/ResolveExpression.h> #include <cplusplus/Symbols.h> @@ -99,6 +100,9 @@ private slots: void templates_3(); void templates_4(); void templates_5(); + + void minimalname_data(); + void minimalname(); }; void tst_Lookup::base_class_defined_1() @@ -631,5 +635,47 @@ void tst_Lookup::templates_5() 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) #include "tst_lookup.moc" |