Что текущий основной парсер, что грядущий (или нагрянувший, как посмотреть) парсер на clangd работают поверх libclang и сотоварищи и умеют разбирать то, что умеет собирать clang.
Внезапно, он умеет не всё. И это не всё, к примеру, отлично умеет GCC. Вот то, с чем я столкнулся сам:
- ESP32 - архитектура (настраиваемая) Xtensa. Кратко (и возможно неточно), можно почитать на Википедии.
-
MicroBlaze - 32/64 bit RISC софтовый микропроцессор от Xilinx. Кратко тоже смотрим на
Википедии. Для работы с ним, к слову, писал
asio-gdbproxy (
MitM-like поддержка RTOS в GDB).
- Его ещё раньше рассматривал в этой заметке: Qt Creator и MicroBlaze
Под катом будет хак, который я использовал, что бы запуститься и работать с этим добром. UPD: хак больше не работает, так как этот код вообще удалён из репозитория QtC ветки master на момент 23.05.2022.
Но сейчас не об этом. Просматривая изменения в апстриме, наткнулся на этот коммит:
И визуально это выглядит так:
Похоже, жизнь станет проще. К сожалению, мне сейчас не на чем проверить. Как только дойдут руки, то обязательно это сделаю. Как минимум, есть ещё нюанс с неподдерживаемыми параметрами командной строки, но оно сейчас обходится так:
# Hack QtC Clang:
# https://bugreports.qt.io/browse/QTCREATORBUG-22329
export QTC_CLANG_CMD_OPTIONS_BLACKLIST="-mxl-soft-mul;-mlongcalls;-fstrict-volatile-bitfields"
Данная функциональность, судя по этому списку изменений будет доступна в Qt Creator 7.0, т.е. совсем скоро:
Ну а ниже, как обещал - костыль. Требует пересборки Qt Creator из исходников.
UPD: 23.05.2022: этого кода больше нет в master ветке, сохраняю только для истории.
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
index 0383a1028f..6aedc231c4 100644
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.cpp
@@ -106,22 +106,48 @@ void TranslationUnitUpdater::createTranslationUnitIfNeeded()
if (!m_cxTranslationUnit) {
m_cxTranslationUnit = CXTranslationUnit();
- const auto args = commandLineArguments();
- if (isVerboseModeEnabled())
- args.print();
-
- UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
-
- m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
- nullptr,
- args.data(),
- args.count(),
- unsaved.data(),
- unsaved.count(),
- defaultParseOptions(),
- &m_cxTranslationUnit);
-
-
+ auto compilationArguments = m_in.compilationArguments;
+
+ for (int i = 0; i < 2; ++i) {
+ const auto args = CommandLineArguments(m_in.filePath.constData(),
+ compilationArguments,
+ isVerboseModeEnabled());
+ if (isVerboseModeEnabled())
+ args.print();
+
+ UnsavedFilesShallowArguments unsaved = m_in.unsavedFiles.shallowArguments();
+
+ m_parseErrorCode = clang_parseTranslationUnit2(m_cxIndex,
+ nullptr,
+ args.data(),
+ args.count(),
+ unsaved.data(),
+ unsaved.count(),
+ defaultParseOptions(),
+ &m_cxTranslationUnit);
+
+
+
+ if (parseWasSuccessful()) {
+ break;
+ }
+
+ // Give a second chance without `--target=xxx` option:
+ // LLVM does not support all GCC targets, like: Microblaze, Xtensa and so on
+ // in such cases, parsing fails. By default, LLVM fallback to i386 or x86_64 targets
+ // according -m32/-m64 options.
+ int j;
+ for (j = 0; j < compilationArguments.count(); ++j) {
+ if (compilationArguments.at(j).startsWith("--target="))
+ break;
+ }
+ if (j < compilationArguments.count()) {
+ compilationArguments.remove(j);
+ } else {
+ // `--target=` not found
+ break;
+ }
+ }
if (parseWasSuccessful()) {
updateIncludeFilePaths();
@@ -217,11 +243,4 @@ bool TranslationUnitUpdater::reparseWasSuccessful() const
return m_reparseErrorCode == 0;
}
-CommandLineArguments TranslationUnitUpdater::commandLineArguments() const
-{
- return CommandLineArguments(m_in.filePath.constData(),
- m_in.compilationArguments,
- isVerboseModeEnabled());
-}
-
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/source/clangtranslationunitupdater.h b/src/tools/clangbackend/source/clangtranslationunitupdater.h
index a0f0d0ba3b..fa535e2c69 100644
--- a/src/tools/clangbackend/source/clangtranslationunitupdater.h
+++ b/src/tools/clangbackend/source/clangtranslationunitupdater.h
@@ -85,7 +85,6 @@ public:
TranslationUnitUpdateResult update(UpdateMode mode);
- CommandLineArguments commandLineArguments() const;
static uint defaultParseOptions();
private:
Собственно здесь и убирается --target=
которому передаётся триплет, в случае если разбор с ним не удался. И пытаемся сделать fall-back на основе -m32
/-m64
.
А вылавливать косяки в кодовой модели, пока, можно так:
# Clang Code model debug
export QT_LOGGING_RULES=qtc.clang*=true
export QTC_CLANG_NO_DIAGNOSTIC_CHECK=1
Почему пока? Потому, как эти флаги к встроенной реализации поверх libclang. Разработчики же сейчас взяли курс на миграцию на clangd.