File indexing completed on 2024-04-14 05:32:07

0001 /*
0002     SPDX-FileCopyrightText: 2017 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef CLAZY_PREPROCESSOR_VISITOR_H
0008 #define CLAZY_PREPROCESSOR_VISITOR_H
0009 
0010 // Each check can visit the preprocessor, but doing things per-check can be
0011 // time consuming and we might want to do them only once.
0012 // For example, getting the Qt version can be done once and the result shared
0013 // with all checks
0014 
0015 #include "checkbase.h"
0016 
0017 #include <clang/Lex/PPCallbacks.h>
0018 #include <llvm/ADT/StringRef.h>
0019 
0020 #include <string>
0021 #include <unordered_map>
0022 #include <vector>
0023 
0024 namespace clang
0025 {
0026 class CompilerInstance;
0027 class SourceManager;
0028 class SourceRange;
0029 class Token;
0030 class MacroDefinition;
0031 class MacroArgs;
0032 class SourceLocation;
0033 }
0034 
0035 using uint = unsigned;
0036 
0037 class PreProcessorVisitor : public clang::PPCallbacks
0038 {
0039     PreProcessorVisitor(const PreProcessorVisitor &) = delete;
0040 
0041 public:
0042     explicit PreProcessorVisitor(const clang::CompilerInstance &ci);
0043 
0044     // Returns for example 050601 (Qt 5.6.1), or -1 if we don't know the version
0045     int qtVersion() const
0046     {
0047         return m_qtVersion;
0048     }
0049 
0050     bool isBetweenQtNamespaceMacros(clang::SourceLocation loc);
0051 
0052     // Returns true if QT_NO_KEYWORDS is defined
0053     bool isQT_NO_KEYWORDS() const
0054     {
0055         return m_isQtNoKeywords;
0056     }
0057 
0058     bool hasInclude(const std::string &fileName, bool IsAngled) const;
0059     clang::SourceLocation endOfIncludeSection() const;
0060 
0061 protected:
0062     void MacroExpands(const clang::Token &MacroNameTok, const clang::MacroDefinition &, clang::SourceRange range, const clang::MacroArgs *) override;
0063     void InclusionDirective(clang::SourceLocation HashLoc,
0064                             const clang::Token &IncludeTok,
0065                             clang::StringRef FileName,
0066                             bool IsAngled,
0067                             clang::CharSourceRange FilenameRange,
0068                             clazy::OptionalFileEntryRef File,
0069                             clang::StringRef SearchPath,
0070                             clang::StringRef RelativePath,
0071                             const clang::Module *Imported,
0072                             clang::SrcMgr::CharacteristicKind FileType) override;
0073 
0074 private:
0075     std::string getTokenSpelling(const clang::MacroDefinition &) const;
0076     void updateQtVersion();
0077     void handleQtNamespaceMacro(clang::SourceLocation loc, clang::StringRef name);
0078 
0079     const clang::CompilerInstance &m_ci;
0080     int m_qtMajorVersion = -1;
0081     int m_qtMinorVersion = -1;
0082     int m_qtPatchVersion = -1;
0083     int m_qtVersion = -1;
0084     bool m_isQtNoKeywords = false;
0085 
0086     // Indexed by FileId, has a list of QT_BEGIN_NAMESPACE/QT_END_NAMESPACE location
0087     std::unordered_map<uint, std::vector<clang::SourceRange>> m_q_namespace_macro_locations;
0088     const clang::SourceManager &m_sm;
0089 
0090     struct IncludeInfo {
0091         clang::StringRef fileName;
0092         bool IsAngled;
0093         clang::CharSourceRange filenameRange;
0094     };
0095 
0096     std::vector<IncludeInfo> m_includeInfo;
0097 };
0098 
0099 #endif