Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 0698385b authored by Bernd Buschinski's avatar Bernd Buschinski

Fix missing header guard warning for a standalone header being always present

Meaning a header that is not included in any other source file in your project.
Such a header would always have the "missing include guard" warning, regardless
if guards are present or not.

This is caused by clang_isFileMultipleIncludeGuarded returning 0 (not guarded) for
standalone header. I added a clang_Location_isFromMainFile check, which checks if
the "source location" is in the main file, which (if we only have a header) is true.
parent d348a833
......@@ -559,8 +559,11 @@ QList<ProblemPointer> ParseSession::problemsForFile(CXFile file) const
// see also TestDUChain::testReparseIncludeGuard
const QString path = QDir(ClangString(clang_getFileName(file)).toString()).canonicalPath();
const IndexedString indexedPath(path);
const auto location = clang_getLocationForOffset(d->m_unit, file, 0);
if (ClangHelpers::isHeader(path) && !clang_isFileMultipleIncludeGuarded(unit(), file)
&& !clang_Location_isInSystemHeader(clang_getLocationForOffset(d->m_unit, file, 0)))
&& !clang_Location_isInSystemHeader(location)
// clang_isFileMultipleIncludeGuarded always returns 0 in case our only file is the header
&& !clang_Location_isFromMainFile(location))
{
QExplicitlySharedDataPointer<StaticAssistantProblem> problem(new StaticAssistantProblem);
problem->setSeverity(IProblem::Warning);
......
......@@ -1616,6 +1616,58 @@ void TestDUChain::testReparseIncludeGuard()
}
}
void TestDUChain::testIncludeGuardHeaderHeaderOnly()
{
QFETCH(QString, code);
// test that we do NOT get a warning for single standalone header file with include guards
TestFile header(code, QStringLiteral("h"));
QVERIFY(header.parseAndWait(TopDUContext::Features(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::AST)));
{
DUChainReadLocker lock;
QCOMPARE(header.topContext()->problems().size(), 0);
}
}
void TestDUChain::testIncludeGuardHeaderHeaderOnly_data()
{
QTest::addColumn<QString>("code");
QTest::newRow("guard-ifdef") << QStringLiteral(
"#ifndef GUARD\n"
"#define GUARD\n"
"int something;\n"
"#endif\n"
);
QTest::newRow("guard-pragma") << QStringLiteral(
"#pragma once\n"
"int something;\n"
);
}
void TestDUChain::testIncludeGuardHeaderWarning()
{
// test that we do get a warning for a header file without include guards
TestFile header(QStringLiteral("int something;\n"), QStringLiteral("h"));
TestFile impl("#include \"" + header.url().str() + "\"\n", QStringLiteral("cpp"));
QVERIFY(impl.parseAndWait(TopDUContext::Features(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::AST | TopDUContext::ForceUpdate)));
{
DUChainReadLocker lock;
QVERIFY(impl.topContext());
auto context = DUChain::self()->chainForDocument(impl.url());
QVERIFY(context);
QCOMPARE(context->problems().size(), 0);
context = DUChain::self()->chainForDocument(header.url());
QVERIFY(context);
QCOMPARE(context->problems().size(), 1);
}
}
void TestDUChain::testExternC()
{
auto code = R"(extern "C" { void foo(); })";
......
......@@ -87,6 +87,9 @@ private Q_SLOTS:
void testActiveDocumentsGetBestPriority();
void testUsesCreatedForDeclarations();
void testReparseIncludeGuard();
void testIncludeGuardHeaderHeaderOnly();
void testIncludeGuardHeaderHeaderOnly_data();
void testIncludeGuardHeaderWarning();
void testExternC();
void testLambda();
void testReparseUnchanged_data();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment