1/****************************************************************************
2 * Copyright (C) 2012-2016 Woboq GmbH
3 * Olivier Goffart <contact at woboq.com>
4 * https://woboq.com/codebrowser.html
5 *
6 * This file is part of the Woboq Code Browser.
7 *
8 * Commercial License Usage:
9 * Licensees holding valid commercial licenses provided by Woboq may use
10 * this file in accordance with the terms contained in a written agreement
11 * between the licensee and Woboq.
12 * For further information see https://woboq.com/codebrowser.html
13 *
14 * Alternatively, this work may be used under a Creative Commons
15 * Attribution-NonCommercial-ShareAlike 3.0 (CC-BY-NC-SA 3.0) License.
16 * http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US
17 * This license does not allow you to use the code browser to assist the
18 * development of your commercial software. If you intent to do so, consider
19 * purchasing a commercial licence.
20 ****************************************************************************/
21
22
23#pragma once
24#include <clang/Lex/PPCallbacks.h>
25#include <clang/Lex/MacroInfo.h>
26#include <clang/Basic/Version.h>
27#include <clang/AST/Decl.h>
28
29namespace clang {
30class Preprocessor;
31}
32
33class Annotator;
34
35class PreprocessorCallback : public clang::PPCallbacks {
36 Annotator &annotator;
37 clang::Preprocessor &PP;
38 bool disabled = false; // To prevent recurstion
39 bool seenPragma = false; // To detect _Pragma in expansion
40 bool recoverIncludePath; // If we should try to find the include paths harder
41
42public:
43 PreprocessorCallback(Annotator &fm, clang::Preprocessor &PP, bool recoverIncludePath)
44 : annotator(fm), PP(PP), recoverIncludePath(recoverIncludePath) {}
45
46#if CLANG_VERSION_MAJOR != 3 || CLANG_VERSION_MINOR >= 7
47 using MyMacroDefinition = const clang::MacroDefinition &;
48#else
49 using MyMacroDefinition = const clang::MacroDirective*;
50#endif
51
52 void MacroExpands(const clang::Token& MacroNameTok, MyMacroDefinition MD,
53 clang::SourceRange Range, const clang::MacroArgs *Args) override;
54
55 void MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD) override;
56
57 void MacroUndefined(const clang::Token &MacroNameTok, MyMacroDefinition MD
58#if CLANG_VERSION_MAJOR >= 5
59 , const clang::MacroDirective *
60#endif
61 ) override;
62
63 bool FileNotFound(llvm::StringRef FileName, llvm::SmallVectorImpl<char> &RecoveryPath) override;
64 void InclusionDirective(clang::SourceLocation HashLoc, const clang::Token& IncludeTok, llvm::StringRef FileName,
65 bool IsAngled, clang::CharSourceRange FilenameRange, const clang::FileEntry* File,
66 llvm::StringRef SearchPath, llvm::StringRef RelativePath, const clang::Module* Imported
67#if CLANG_VERSION_MAJOR >= 7
68 , clang::SrcMgr::CharacteristicKind
69#endif
70
71 ) override;
72
73#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR < 5
74 typedef bool ConditionValueKind; // It's an enum in clang 3.5
75#endif
76
77 void PragmaDirective(clang::SourceLocation Loc, clang::PragmaIntroducerKind Introducer) override
78 { seenPragma = true; }
79
80 virtual void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, ConditionValueKind ConditionValue) override
81 { HandlePPCond(Loc, Loc); }
82 virtual void Ifndef(clang::SourceLocation Loc, const clang::Token& MacroNameTok, MyMacroDefinition MD) override
83 { HandlePPCond(Loc, Loc); Defined(MacroNameTok, MD, Loc); }
84 virtual void Ifdef(clang::SourceLocation Loc, const clang::Token& MacroNameTok, MyMacroDefinition MD) override
85 { HandlePPCond(Loc, Loc); Defined(MacroNameTok, MD, Loc); }
86 virtual void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange, ConditionValueKind ConditionValue, clang::SourceLocation IfLoc) override {
87 ElifMapping[Loc] = IfLoc;
88 HandlePPCond(Loc, IfLoc);
89 }
90 virtual void Else(clang::SourceLocation Loc, clang::SourceLocation IfLoc) override
91 { HandlePPCond(Loc, IfLoc); }
92 virtual void Endif(clang::SourceLocation Loc, clang::SourceLocation IfLoc) override
93 { HandlePPCond(Loc, IfLoc); }
94
95 virtual void Defined(const clang::Token &MacroNameTok, MyMacroDefinition MD,
96 clang::SourceRange Range) override;
97
98private:
99 std::map<clang::SourceLocation, clang::SourceLocation> ElifMapping; // Map an elif location to the real if;
100 void HandlePPCond(clang::SourceLocation Loc, clang::SourceLocation IfLoc);
101};
102