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
Pipeline #14068 passed with stage
in 54 minutes and 14 seconds
......@@ -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);
......@@ -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::newRow("guard-ifdef") << QStringLiteral(
"#ifndef GUARD\n"
"#define GUARD\n"
"int something;\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;
auto context = DUChain::self()->chainForDocument(impl.url());
QCOMPARE(context->problems().size(), 0);
context = DUChain::self()->chainForDocument(header.url());
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