1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#ifndef LUPDATEPREPROCESSORACTION_H
5#define LUPDATEPREPROCESSORACTION_H
6
7#include "cpp_clang.h"
8#include "synchronized.h"
9
10QT_WARNING_PUSH
11QT_WARNING_DISABLE_MSVC(4100)
12QT_WARNING_DISABLE_MSVC(4146)
13QT_WARNING_DISABLE_MSVC(4267)
14QT_WARNING_DISABLE_MSVC(4624)
15QT_WARNING_DISABLE_GCC("-Wnonnull")
16
17#include <clang/Frontend/CompilerInstance.h>
18#include <clang/Frontend/FrontendActions.h>
19#include <clang/Tooling/Tooling.h>
20#include <clang/Lex/PPCallbacks.h>
21#include <clang/Lex/Preprocessor.h>
22
23QT_WARNING_POP
24
25#include <memory>
26
27QT_BEGIN_NAMESPACE
28
29class LupdatePPCallbacks : public clang::PPCallbacks
30{
31public:
32 LupdatePPCallbacks(WriteSynchronizedRef<TranslationRelatedStore> *stores, clang::Preprocessor &pp)
33 : m_preprocessor(pp)
34 , m_stores(stores)
35 {
36 const auto &sm = m_preprocessor.getSourceManager();
37 m_inputFile = sm.getFileEntryForID(FID: sm.getMainFileID())->getName();
38 }
39
40 ~LupdatePPCallbacks() override
41 {
42 m_stores->emplace_bulk(values: std::move(m_ppStores));
43 }
44
45private:
46 void MacroExpands(const clang::Token &token, const clang::MacroDefinition &macroDefinition,
47 clang::SourceRange sourceRange, const clang::MacroArgs *macroArgs) override;
48
49 void storeMacroArguments(const std::vector<QString> &args, TranslationRelatedStore *store);
50
51 void SourceRangeSkipped(clang::SourceRange sourceRange, clang::SourceLocation endifLoc) override;
52 void InclusionDirective(clang::SourceLocation /*hashLoc*/, const clang::Token &/*includeTok*/,
53 clang::StringRef /*fileName*/, bool /*isAngled*/,
54 clang::CharSourceRange /*filenameRange*/,
55#if (LUPDATE_CLANG_VERSION >= LUPDATE_CLANG_VERSION_CHECK(16,0,0))
56 const clang::OptionalFileEntryRef file,
57#elif (LUPDATE_CLANG_VERSION >= LUPDATE_CLANG_VERSION_CHECK(15,0,0))
58 const clang::Optional<clang::FileEntryRef> file,
59#else
60 const clang::FileEntry *file,
61#endif
62 clang::StringRef /*searchPath*/, clang::StringRef /*relativePath*/,
63 const clang::Module */*imported*/,
64 clang::SrcMgr::CharacteristicKind /*fileType*/) override;
65
66 std::string m_inputFile;
67 clang::Preprocessor &m_preprocessor;
68
69 TranslationStores m_ppStores;
70 WriteSynchronizedRef<TranslationRelatedStore> *m_stores { nullptr };
71};
72
73class LupdatePreprocessorAction : public clang::PreprocessOnlyAction
74{
75public:
76 LupdatePreprocessorAction(WriteSynchronizedRef<TranslationRelatedStore> *stores)
77 : m_stores(stores)
78 {}
79
80private:
81 void ExecuteAction() override
82 {
83 auto &preprocessor = getCompilerInstance().getPreprocessor();
84 preprocessor.SetSuppressIncludeNotFoundError(true);
85 auto callbacks = new LupdatePPCallbacks(m_stores, preprocessor);
86 preprocessor.addPPCallbacks(C: std::unique_ptr<clang::PPCallbacks>(callbacks));
87
88 clang::PreprocessOnlyAction::ExecuteAction();
89 }
90
91private:
92 WriteSynchronizedRef<TranslationRelatedStore> *m_stores { nullptr };
93};
94
95class LupdatePreprocessorActionFactory : public clang::tooling::FrontendActionFactory
96{
97public:
98 explicit LupdatePreprocessorActionFactory(WriteSynchronizedRef<TranslationRelatedStore> *stores)
99 : m_stores(stores)
100 {}
101
102#if (LUPDATE_CLANG_VERSION >= LUPDATE_CLANG_VERSION_CHECK(10,0,0))
103 std::unique_ptr<clang::FrontendAction> create() override
104 {
105 return std::make_unique<LupdatePreprocessorAction>(args&: m_stores);
106 }
107#else
108 clang::FrontendAction *create() override
109 {
110 return new LupdatePreprocessorAction(m_stores);
111 }
112#endif
113
114private:
115 WriteSynchronizedRef<TranslationRelatedStore> *m_stores { nullptr };
116};
117
118QT_END_NAMESPACE
119
120#endif
121

source code of qttools/src/linguist/lupdate/lupdatepreprocessoraction.h