From 5c86789c7e4ea7989384bc386cae28ee4348761e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 24 Sep 2020 15:43:17 +0200 Subject: qdoc: Unify clang diagnostics reporting Clang's diagnostics are silenced unless debug is enabled with --debug. Change-Id: I1c79c56b6f0d4fd676de99c4a00c951499d4e3a6 Reviewed-by: Paul Wicking --- src/qdoc/clangcodeparser.cpp | 73 ++++++++++++++++++++++++-------------------- src/qdoc/clangcodeparser.h | 11 ++++--- src/qdoc/utilities.cpp | 2 ++ src/qdoc/utilities.h | 1 + 4 files changed, 50 insertions(+), 37 deletions(-) diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp index ffae9205f..b91a9bfe7 100644 --- a/src/qdoc/clangcodeparser.cpp +++ b/src/qdoc/clangcodeparser.cpp @@ -68,6 +68,10 @@ QT_BEGIN_NAMESPACE +// We're printing diagnostics in ClangCodeParser::printDiagnostics, +// so avoid clang itself printing them. +static const auto kClangDontDisplayDiagnostics = 0; + static CXTranslationUnit_Flags flags_ = static_cast(0); static CXIndex index_ = nullptr; @@ -1078,7 +1082,6 @@ ClangCodeParser::~ClangCodeParser() void ClangCodeParser::initializeParser() { Config &config = Config::instance(); - m_printParsingErrors = 1; m_version = config.getString(CONFIG_VERSION); const auto args = config.getStringList(CONFIG_INCLUDEPATHS); QSet seen; @@ -1241,22 +1244,11 @@ static QList includePathsFromHeaders(const QHash & } /*! - Load the include paths into \a moreArgs and return false. - If no include paths were provided, try to guess reasonable - include paths but return true, so the clang diagnostics - can be turned off during PCH creation. - - The use case for returning true is the QtPlatformHeaders - module when running qdoc on macOS. For some reason, the - include paths are not passed to qdoc, so it guesses them. - This results in clang reporting a large number of errors - during the PCH build. The errors are useles, except that - it probably means the build system isn't working correctly - for QtPlatformHeaders when running qdoc. + Load the include paths into \a moreArgs. If no include paths + were provided, try to guess reasonable include paths. */ -bool ClangCodeParser::getMoreArgs() +void ClangCodeParser::getMoreArgs() { - bool guessedIncludePaths = false; if (m_includePaths.isEmpty()) { /* The include paths provided are inadequate. Make a list @@ -1264,7 +1256,6 @@ bool ClangCodeParser::getMoreArgs() that list instead. */ qCWarning(lcQdoc) << "No include paths passed to qdoc; guessing reasonable include paths"; - guessedIncludePaths = true; auto forest = qdb_->searchOrder(); QByteArray version = qdb_->version().toUtf8(); @@ -1274,8 +1265,6 @@ bool ClangCodeParser::getMoreArgs() } else { m_moreArgs = m_includePaths; } - - return guessedIncludePaths; } /*! @@ -1381,14 +1370,16 @@ void ClangCodeParser::buildPCH() } tmpHeaderFile.close(); } - if (m_printParsingErrors == 0) - qCWarning(lcQdoc) << "clang not printing errors; include paths were guessed"; + CXErrorCode err = clang_parseTranslationUnit2(index_, tmpHeader.toLatin1().data(), m_args.data(), static_cast(m_args.size()), nullptr, 0, flags_ | CXTranslationUnit_ForSerialization, &tu); qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << tmpHeader << m_args << ") returns" << err; + + printDiagnostics(tu); + if (!err && tu) { m_pchName = m_pchFileDir->path().toUtf8() + "/" + module + ".pch"; auto error = clang_saveTranslationUnit(tu, m_pchName.constData(), @@ -1420,16 +1411,16 @@ void ClangCodeParser::buildPCH() void ClangCodeParser::precompileHeaders() { getDefaultArgs(); - if (getMoreArgs()) - m_printParsingErrors = 0; + getMoreArgs(); for (const auto &p : qAsConst(m_moreArgs)) m_args.push_back(p.constData()); flags_ = static_cast(CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies | CXTranslationUnit_KeepGoing); - // 1 as 2nd parameter tells clang to report parser errors. - index_ = clang_createIndex(1, m_printParsingErrors); + + index_ = clang_createIndex(1, kClangDontDisplayDiagnostics); + buildPCH(); clang_disposeIndex(index_); } @@ -1459,7 +1450,8 @@ void ClangCodeParser::parseSourceFile(const Location & /*location*/, const QStri flags_ = static_cast(CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies | CXTranslationUnit_KeepGoing); - index_ = clang_createIndex(1, 0); + + index_ = clang_createIndex(1, kClangDontDisplayDiagnostics); getDefaultArgs(); if (!m_pchName.isEmpty() && !filePath.endsWith(".mm")) { @@ -1477,6 +1469,8 @@ void ClangCodeParser::parseSourceFile(const Location & /*location*/, const QStri static_cast(m_args.size()), nullptr, 0, flags_, &tu); qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << filePath << m_args << ") returns" << err; + printDiagnostics(tu); + if (err || !tu) { qWarning() << "(qdoc) Could not parse source file" << filePath << " error code:" << err; clang_disposeIndex(index_); @@ -1635,8 +1629,8 @@ Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnArg CXTranslationUnit_Flags flags = static_cast( CXTranslationUnit_Incomplete | CXTranslationUnit_SkipFunctionBodies | CXTranslationUnit_KeepGoing); - // Change 2nd parameter to 1 to make clang report errors. - CXIndex index = clang_createIndex(1, Utilities::debugging() ? 1 : 0); + + CXIndex index = clang_createIndex(1, kClangDontDisplayDiagnostics); std::vector args(std::begin(defaultArgs_), std::end(defaultArgs_)); // Add the defines from the qdocconf file. @@ -1663,6 +1657,7 @@ Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnArg &unsavedFile, 1, flags, &tu); qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << dummyFileName << args << ") returns" << err; + printDiagnostics(tu); if (err || !tu) { location.error(QStringLiteral("clang could not parse \\fn %1").arg(fnArg)); clang_disposeTranslationUnit(tu); @@ -1707,12 +1702,7 @@ Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnArg } if (report) { location.warning( - QStringLiteral("clang found diagnostics parsing \\fn %1").arg(fnArg)); - for (unsigned i = 0; i < diagnosticCount; ++i) { - CXDiagnostic diagnostic = clang_getDiagnostic(tu, i); - location.report(QStringLiteral(" %1").arg( - fromCXString(clang_formatDiagnostic(diagnostic, 0)))); - } + QStringLiteral("clang couldn't find function when parsing \\fn %1").arg(fnArg)); } } } @@ -1722,4 +1712,21 @@ Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnArg return fnNode; } +void ClangCodeParser::printDiagnostics(const CXTranslationUnit &translationUnit) const +{ + if (!lcQdocClang().isDebugEnabled()) + return; + + static const auto displayOptions = CXDiagnosticDisplayOptions::CXDiagnostic_DisplaySourceLocation + | CXDiagnosticDisplayOptions::CXDiagnostic_DisplayColumn + | CXDiagnosticDisplayOptions::CXDiagnostic_DisplayOption; + + for (unsigned i = 0, numDiagnostics = clang_getNumDiagnostics(translationUnit); i < numDiagnostics; ++i) { + auto diagnostic = clang_getDiagnostic(translationUnit, i); + auto formattedDiagnostic = clang_formatDiagnostic(diagnostic, displayOptions); + qCDebug(lcQdocClang) << clang_getCString(formattedDiagnostic); + clang_disposeString(formattedDiagnostic); + } +} + QT_END_NAMESPACE diff --git a/src/qdoc/clangcodeparser.h b/src/qdoc/clangcodeparser.h index e34adb026..9c09365d4 100644 --- a/src/qdoc/clangcodeparser.h +++ b/src/qdoc/clangcodeparser.h @@ -44,6 +44,8 @@ #include +typedef struct CXTranslationUnitImpl *CXTranslationUnit; + QT_BEGIN_NAMESPACE class ClangCodeParser : public CppCodeParser @@ -63,12 +65,13 @@ public: static const QByteArray &fn() { return s_fn; } private: - void getDefaultArgs(); - bool getMoreArgs(); + void getDefaultArgs(); // FIXME: Clean up API + void getMoreArgs(); // FIXME: Clean up API + void buildPCH(); -private: - int m_printParsingErrors {}; + void printDiagnostics(const CXTranslationUnit &translationUnit) const; + QString m_version {}; QHash m_allHeaders {}; // file name->path QList m_includePaths {}; diff --git a/src/qdoc/utilities.cpp b/src/qdoc/utilities.cpp index fac225e27..e9ef60571 100644 --- a/src/qdoc/utilities.cpp +++ b/src/qdoc/utilities.cpp @@ -31,6 +31,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQdoc, "qt.qdoc") +Q_LOGGING_CATEGORY(lcQdocClang, "qt.qdoc.clang") /*! \namespace Utilities @@ -41,6 +42,7 @@ namespace Utilities { static inline void setDebugEnabled(bool value) { const_cast(lcQdoc()).setEnabled(QtDebugMsg, value); + const_cast(lcQdocClang()).setEnabled(QtDebugMsg, value); } void startDebugging(const QString &message) diff --git a/src/qdoc/utilities.h b/src/qdoc/utilities.h index 2ffdb8f42..a30c252a9 100644 --- a/src/qdoc/utilities.h +++ b/src/qdoc/utilities.h @@ -35,6 +35,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQdoc) +Q_DECLARE_LOGGING_CATEGORY(lcQdocClang) namespace Utilities { void startDebugging(const QString &message); -- cgit v1.2.1