1 //===--- CollectMacros.h -----------------------------------------*- C++-*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H 11 12 #include "AST.h" 13 #include "Protocol.h" 14 #include "SourceCode.h" 15 #include "index/SymbolID.h" 16 #include "clang/Basic/IdentifierTable.h" 17 #include "clang/Lex/PPCallbacks.h" 18 #include "llvm/ADT/DenseMap.h" 19 #include <string> 20 21 namespace clang { 22 namespace clangd { 23 24 struct MainFileMacros { 25 llvm::StringSet<> Names; 26 // Instead of storing SourceLocation, we have to store the token range because 27 // SourceManager from preamble is not available when we build the AST. 28 llvm::DenseMap<SymbolID, std::vector<Range>> MacroRefs; 29 // Somtimes it is not possible to compute the SymbolID for the Macro, e.g. a 30 // reference to an undefined macro. Store them separately, e.g. for semantic 31 // highlighting. 32 std::vector<Range> UnknownMacros; 33 // Ranges skipped by the preprocessor due to being inactive. 34 std::vector<Range> SkippedRanges; 35 }; 36 37 /// Collects macro references (e.g. definitions, expansions) in the main file. 38 /// It is used to: 39 /// - collect macros in the preamble section of the main file (in Preamble.cpp) 40 /// - collect macros after the preamble of the main file (in ParsedAST.cpp) 41 class CollectMainFileMacros : public PPCallbacks { 42 public: CollectMainFileMacros(const SourceManager & SM,MainFileMacros & Out)43 explicit CollectMainFileMacros(const SourceManager &SM, MainFileMacros &Out) 44 : SM(SM), Out(Out) {} 45 FileChanged(SourceLocation Loc,FileChangeReason,SrcMgr::CharacteristicKind,FileID)46 void FileChanged(SourceLocation Loc, FileChangeReason, 47 SrcMgr::CharacteristicKind, FileID) override { 48 InMainFile = isInsideMainFile(Loc, SM); 49 } 50 MacroDefined(const Token & MacroName,const MacroDirective * MD)51 void MacroDefined(const Token &MacroName, const MacroDirective *MD) override { 52 add(MacroName, MD->getMacroInfo()); 53 } 54 MacroExpands(const Token & MacroName,const MacroDefinition & MD,SourceRange Range,const MacroArgs * Args)55 void MacroExpands(const Token &MacroName, const MacroDefinition &MD, 56 SourceRange Range, const MacroArgs *Args) override { 57 add(MacroName, MD.getMacroInfo()); 58 } 59 MacroUndefined(const clang::Token & MacroName,const clang::MacroDefinition & MD,const clang::MacroDirective * Undef)60 void MacroUndefined(const clang::Token &MacroName, 61 const clang::MacroDefinition &MD, 62 const clang::MacroDirective *Undef) override { 63 add(MacroName, MD.getMacroInfo()); 64 } 65 Ifdef(SourceLocation Loc,const Token & MacroName,const MacroDefinition & MD)66 void Ifdef(SourceLocation Loc, const Token &MacroName, 67 const MacroDefinition &MD) override { 68 add(MacroName, MD.getMacroInfo()); 69 } 70 Ifndef(SourceLocation Loc,const Token & MacroName,const MacroDefinition & MD)71 void Ifndef(SourceLocation Loc, const Token &MacroName, 72 const MacroDefinition &MD) override { 73 add(MacroName, MD.getMacroInfo()); 74 } 75 Defined(const Token & MacroName,const MacroDefinition & MD,SourceRange Range)76 void Defined(const Token &MacroName, const MacroDefinition &MD, 77 SourceRange Range) override { 78 add(MacroName, MD.getMacroInfo()); 79 } 80 SourceRangeSkipped(SourceRange R,SourceLocation EndifLoc)81 void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override { 82 if (!InMainFile) 83 return; 84 Position Begin = sourceLocToPosition(SM, R.getBegin()); 85 Position End = sourceLocToPosition(SM, R.getEnd()); 86 Out.SkippedRanges.push_back(Range{Begin, End}); 87 } 88 89 private: 90 void add(const Token &MacroNameTok, const MacroInfo *MI); 91 const SourceManager &SM; 92 bool InMainFile = true; 93 MainFileMacros &Out; 94 }; 95 96 } // namespace clangd 97 } // namespace clang 98 99 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H 100