File indexing completed on 2024-04-28 16:57:51
0001 /* 0002 This file is part of the clazy static checker. 0003 0004 Copyright (C) 2017 Sergio Martins <smartins@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #ifndef CLAZY_PREPROCESSOR_VISITOR_H 0023 #define CLAZY_PREPROCESSOR_VISITOR_H 0024 0025 // Each check can visit the preprocessor, but doing things per-check can be 0026 // time consuming and we might want to do them only once. 0027 // For example, getting the Qt version can be done once and the result shared 0028 // with all checks 0029 0030 #include "checkbase.h" 0031 0032 #include <clang/Lex/PPCallbacks.h> 0033 #include <llvm/ADT/StringRef.h> 0034 0035 #include <string> 0036 #include <unordered_map> 0037 #include <vector> 0038 0039 namespace clang { 0040 class CompilerInstance; 0041 class SourceManager; 0042 class SourceRange; 0043 class Token; 0044 class MacroDefinition; 0045 class MacroArgs; 0046 class SourceLocation; 0047 } 0048 0049 using uint = unsigned; 0050 0051 class PreProcessorVisitor 0052 : public clang::PPCallbacks 0053 { 0054 PreProcessorVisitor(const PreProcessorVisitor &) = delete; 0055 public: 0056 explicit PreProcessorVisitor(const clang::CompilerInstance &ci); 0057 0058 // Returns for example 050601 (Qt 5.6.1), or -1 if we don't know the version 0059 int qtVersion() const { return m_qtVersion; } 0060 0061 bool isBetweenQtNamespaceMacros(clang::SourceLocation loc); 0062 0063 // Returns true if QT_NO_KEYWORDS is defined 0064 bool isQT_NO_KEYWORDS() const { return m_isQtNoKeywords; } 0065 0066 bool hasInclude(const std::string& fileName, bool IsAngled) const; 0067 clang::SourceLocation endOfIncludeSection() const; 0068 0069 protected: 0070 void MacroExpands(const clang::Token &MacroNameTok, const clang::MacroDefinition &, 0071 clang::SourceRange range, const clang::MacroArgs *) override; 0072 void InclusionDirective (clang::SourceLocation HashLoc, const clang::Token &IncludeTok, 0073 clang::StringRef FileName, bool IsAngled, clang::CharSourceRange FilenameRange, 0074 const clang::FileEntry *File, clang::StringRef SearchPath, clang::StringRef RelativePath, 0075 const clang::Module *Imported, clang::SrcMgr::CharacteristicKind FileType) override; 0076 private: 0077 std::string getTokenSpelling(const clang::MacroDefinition &) const; 0078 void updateQtVersion(); 0079 void handleQtNamespaceMacro(clang::SourceLocation loc, clang::StringRef name); 0080 0081 const clang::CompilerInstance &m_ci; 0082 int m_qtMajorVersion = -1; 0083 int m_qtMinorVersion = -1; 0084 int m_qtPatchVersion = -1; 0085 int m_qtVersion = -1; 0086 bool m_isQtNoKeywords = false; 0087 0088 // Indexed by FileId, has a list of QT_BEGIN_NAMESPACE/QT_END_NAMESPACE location 0089 std::unordered_map<uint, std::vector<clang::SourceRange>> m_q_namespace_macro_locations; 0090 const clang::SourceManager &m_sm; 0091 0092 struct IncludeInfo { 0093 clang::StringRef fileName; 0094 bool IsAngled; 0095 clang::CharSourceRange filenameRange; 0096 }; 0097 0098 std::vector<IncludeInfo> m_includeInfo; 0099 }; 0100 0101 #endif