17e3c74bcSHaojian Wu //===--- CollectMacros.h -----------------------------------------*- C++-*-===// 27e3c74bcSHaojian Wu // 37e3c74bcSHaojian Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47e3c74bcSHaojian Wu // See https://llvm.org/LICENSE.txt for license information. 57e3c74bcSHaojian Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67e3c74bcSHaojian Wu // 77e3c74bcSHaojian Wu //===----------------------------------------------------------------------===// 87e3c74bcSHaojian Wu 95bd643d3SChristian Kühnel #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H 105bd643d3SChristian Kühnel #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H 117e3c74bcSHaojian Wu 127e3c74bcSHaojian Wu #include "Protocol.h" 137e3c74bcSHaojian Wu #include "SourceCode.h" 142054ed05SUtkarsh Saxena #include "index/SymbolID.h" 153ddfea07SHaojian Wu #include "clang/Basic/SourceLocation.h" 167e3c74bcSHaojian Wu #include "clang/Lex/PPCallbacks.h" 17002c4b7bSHaojian Wu #include "clang/Lex/Preprocessor.h" 182054ed05SUtkarsh Saxena #include "llvm/ADT/DenseMap.h" 197298bcf7SHaojian Wu #include <cstddef> 207e3c74bcSHaojian Wu #include <string> 217e3c74bcSHaojian Wu 227e3c74bcSHaojian Wu namespace clang { 237e3c74bcSHaojian Wu namespace clangd { 247e3c74bcSHaojian Wu 252e25be0bSAleksandr Platonov struct MacroOccurrence { 267298bcf7SHaojian Wu // Half-open range (end offset is exclusive) inside the main file. 277298bcf7SHaojian Wu size_t StartOffset; 287298bcf7SHaojian Wu size_t EndOffset; 297298bcf7SHaojian Wu 302e25be0bSAleksandr Platonov bool IsDefinition; 31002c4b7bSHaojian Wu // True if the occurence is used in a conditional directive, e.g. #ifdef MACRO 32002c4b7bSHaojian Wu bool InConditionalDirective; 337298bcf7SHaojian Wu 347298bcf7SHaojian Wu Range toRange(const SourceManager &SM) const; 352e25be0bSAleksandr Platonov }; 362e25be0bSAleksandr Platonov 372e25be0bSAleksandr Platonov struct MainFileMacros { 382e25be0bSAleksandr Platonov llvm::StringSet<> Names; 392e25be0bSAleksandr Platonov llvm::DenseMap<SymbolID, std::vector<MacroOccurrence>> MacroRefs; 402054ed05SUtkarsh Saxena // Somtimes it is not possible to compute the SymbolID for the Macro, e.g. a 412054ed05SUtkarsh Saxena // reference to an undefined macro. Store them separately, e.g. for semantic 422054ed05SUtkarsh Saxena // highlighting. 432e25be0bSAleksandr Platonov std::vector<MacroOccurrence> UnknownMacros; 44b2e6c2b9SNathan Ridge // Ranges skipped by the preprocessor due to being inactive. 45b2e6c2b9SNathan Ridge std::vector<Range> SkippedRanges; 467e3c74bcSHaojian Wu }; 477e3c74bcSHaojian Wu 482fa81d20SHaojian Wu /// Collects macro references (e.g. definitions, expansions) in the main file. 492fa81d20SHaojian Wu /// It is used to: 507e3c74bcSHaojian Wu /// - collect macros in the preamble section of the main file (in Preamble.cpp) 517e3c74bcSHaojian Wu /// - collect macros after the preamble of the main file (in ParsedAST.cpp) 527e3c74bcSHaojian Wu class CollectMainFileMacros : public PPCallbacks { 537e3c74bcSHaojian Wu public: 54002c4b7bSHaojian Wu explicit CollectMainFileMacros(const Preprocessor &PP, MainFileMacros &Out) 55002c4b7bSHaojian Wu : SM(PP.getSourceManager()), PP(PP), Out(Out) {} 567e3c74bcSHaojian Wu 577e3c74bcSHaojian Wu void FileChanged(SourceLocation Loc, FileChangeReason, 58002c4b7bSHaojian Wu SrcMgr::CharacteristicKind, FileID) override; 597e3c74bcSHaojian Wu 60002c4b7bSHaojian Wu void MacroDefined(const Token &MacroName, const MacroDirective *MD) override; 617e3c74bcSHaojian Wu 627e3c74bcSHaojian Wu void MacroExpands(const Token &MacroName, const MacroDefinition &MD, 63002c4b7bSHaojian Wu SourceRange Range, const MacroArgs *Args) override; 647e3c74bcSHaojian Wu 652fa81d20SHaojian Wu void MacroUndefined(const clang::Token &MacroName, 662fa81d20SHaojian Wu const clang::MacroDefinition &MD, 67002c4b7bSHaojian Wu const clang::MacroDirective *Undef) override; 682fa81d20SHaojian Wu 692fa81d20SHaojian Wu void Ifdef(SourceLocation Loc, const Token &MacroName, 70002c4b7bSHaojian Wu const MacroDefinition &MD) override; 712fa81d20SHaojian Wu void Ifndef(SourceLocation Loc, const Token &MacroName, 72002c4b7bSHaojian Wu const MacroDefinition &MD) override; 733ddfea07SHaojian Wu using PPCallbacks::Elifdef; 743ddfea07SHaojian Wu using PPCallbacks::Elifndef; 753ddfea07SHaojian Wu void Elifdef(SourceLocation Loc, const Token &MacroNameTok, 763ddfea07SHaojian Wu const MacroDefinition &MD) override; 773ddfea07SHaojian Wu void Elifndef(SourceLocation Loc, const Token &MacroNameTok, 783ddfea07SHaojian Wu const MacroDefinition &MD) override; 792fa81d20SHaojian Wu 802fa81d20SHaojian Wu void Defined(const Token &MacroName, const MacroDefinition &MD, 81002c4b7bSHaojian Wu SourceRange Range) override; 822fa81d20SHaojian Wu 83002c4b7bSHaojian Wu void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override; 84b2e6c2b9SNathan Ridge 85*ee6961dbSNathan Ridge // Called when the AST build is done to disable further recording 86*ee6961dbSNathan Ridge // of macros by this class. This is needed because some clang-tidy 87*ee6961dbSNathan Ridge // checks can trigger PP callbacks by calling directly into the 88*ee6961dbSNathan Ridge // preprocessor. Such calls are not interleaved with FileChanged() 89*ee6961dbSNathan Ridge // in the expected way, leading this class to erroneously process 90*ee6961dbSNathan Ridge // macros that are not in the main file. 91*ee6961dbSNathan Ridge void doneParse() { InMainFile = false; } 92*ee6961dbSNathan Ridge 937e3c74bcSHaojian Wu private: 942e25be0bSAleksandr Platonov void add(const Token &MacroNameTok, const MacroInfo *MI, 95002c4b7bSHaojian Wu bool IsDefinition = false, bool InConditionalDirective = false); 967e3c74bcSHaojian Wu const SourceManager &SM; 97002c4b7bSHaojian Wu const Preprocessor &PP; 987e3c74bcSHaojian Wu bool InMainFile = true; 997e3c74bcSHaojian Wu MainFileMacros &Out; 1007e3c74bcSHaojian Wu }; 1017e3c74bcSHaojian Wu 102d75fb1eeSDavid Goldman /// Represents a `#pragma mark` in the main file. 103d75fb1eeSDavid Goldman /// 104d75fb1eeSDavid Goldman /// There can be at most one pragma mark per line. 105d75fb1eeSDavid Goldman struct PragmaMark { 106d75fb1eeSDavid Goldman Range Rng; 107d75fb1eeSDavid Goldman std::string Trivia; 108d75fb1eeSDavid Goldman }; 109d75fb1eeSDavid Goldman 110d75fb1eeSDavid Goldman /// Collect all pragma marks from the main file. 111d75fb1eeSDavid Goldman std::unique_ptr<PPCallbacks> 112d75fb1eeSDavid Goldman collectPragmaMarksCallback(const SourceManager &, std::vector<PragmaMark> &Out); 113d75fb1eeSDavid Goldman 1147e3c74bcSHaojian Wu } // namespace clangd 1157e3c74bcSHaojian Wu } // namespace clang 1167e3c74bcSHaojian Wu 1175bd643d3SChristian Kühnel #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTMACROS_H 118