Hatred's Log Place

DON'T PANIC!

Feb 12, 2022 - 3 minute read - Programming

Qt Creator: подтасовка триплета архитектуры для кодовой модели

Что текущий основной парсер, что грядущий (или нагрянувший, как посмотреть) парсер на clangd работают поверх libclang и сотоварищи и умеют разбирать то, что умеет собирать clang.

Внезапно, он умеет не всё. И это не всё, к примеру, отлично умеет GCC. Вот то, с чем я столкнулся сам:

Под катом будет хак, который я использовал, что бы запуститься и работать с этим добром. 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.