summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2017-02-21 14:18:07 +0100
committerNikolai Kosjar <nikolai.kosjar@qt.io>2017-02-23 14:49:31 +0000
commitfe27f947b916a6b7333be50127c219bafb3d2353 (patch)
tree20afb0bdc7efb186bddb5abf0a62f2a5e029e695
parent4637b3fed7a456ec664ae9ba1de5c03b32aa12fd (diff)
downloadqt-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.cpp39
-rw-r--r--tests/auto/cplusplus/lookup/tst_lookup.cpp46
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"