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/AST/Decl.h>
25#include <clang/Basic/Version.h>
26#include <clang/Lex/MacroInfo.h>
27#include <clang/Lex/PPCallbacks.h>
28#if CLANG_VERSION_MAJOR == 15
29#include <llvm/ADT/Optional.h>
30#endif
31
32namespace clang {
33class Preprocessor;
34}
35
36class Annotator;
37
38class PreprocessorCallback : public clang::PPCallbacks
39{
40 Annotator &annotator;
41 clang::Preprocessor &PP;
42 bool disabled = false; // To prevent recurstion
43 bool seenPragma = false; // To detect _Pragma in expansion
44 bool recoverIncludePath; // If we should try to find the include paths harder
45
46public:
47 PreprocessorCallback(Annotator &fm, clang::Preprocessor &PP, bool recoverIncludePath)
48 : annotator(fm)
49 , PP(PP)
50 , recoverIncludePath(recoverIncludePath)
51 {
52 }
53
54#if CLANG_VERSION_MAJOR != 3 || CLANG_VERSION_MINOR >= 7
55 using MyMacroDefinition = const clang::MacroDefinition &;
56#else
57 using MyMacroDefinition = const clang::MacroDirective *;
58#endif
59
60 void MacroExpands(const clang::Token &MacroNameTok, MyMacroDefinition MD,
61 clang::SourceRange Range, const clang::MacroArgs *Args) override;
62
63 void MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD) override;
64
65 void MacroUndefined(const clang::Token &MacroNameTok, MyMacroDefinition MD
66#if CLANG_VERSION_MAJOR >= 5
67 ,
68 const clang::MacroDirective *
69#endif
70 ) override;
71
72 void InclusionDirective(clang::SourceLocation HashLoc, const clang::Token &IncludeTok,
73 llvm::StringRef FileName, bool IsAngled,
74 clang::CharSourceRange FilenameRange,
75#if CLANG_VERSION_MAJOR >= 16
76 clang::OptionalFileEntryRef File,
77#elif CLANG_VERSION_MAJOR >= 15
78 llvm::Optional<clang::FileEntryRef> File,
79#else
80 const clang::FileEntry *File,
81#endif
82 llvm::StringRef SearchPath, llvm::StringRef RelativePath,
83 const clang::Module *Imported
84#if CLANG_VERSION_MAJOR >= 7
85 ,
86 clang::SrcMgr::CharacteristicKind
87#endif
88
89 ) override;
90
91#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR < 5
92 typedef bool ConditionValueKind; // It's an enum in clang 3.5
93#endif
94
95 void PragmaDirective(clang::SourceLocation Loc, clang::PragmaIntroducerKind Introducer) override
96 {
97 seenPragma = true;
98 }
99
100 virtual void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
101 ConditionValueKind ConditionValue) override
102 {
103 HandlePPCond(Loc, IfLoc: Loc);
104 }
105 virtual void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
106 MyMacroDefinition MD) override
107 {
108 HandlePPCond(Loc, IfLoc: Loc);
109 Defined(MacroNameTok, MD, Range: Loc);
110 }
111 virtual void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok,
112 MyMacroDefinition MD) override
113 {
114 HandlePPCond(Loc, IfLoc: Loc);
115 Defined(MacroNameTok, MD, Range: Loc);
116 }
117 virtual void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange,
118 ConditionValueKind ConditionValue, clang::SourceLocation IfLoc) override
119 {
120 ElifMapping[Loc] = IfLoc;
121 HandlePPCond(Loc, IfLoc);
122 }
123 virtual void Else(clang::SourceLocation Loc, clang::SourceLocation IfLoc) override
124 {
125 HandlePPCond(Loc, IfLoc);
126 }
127 virtual void Endif(clang::SourceLocation Loc, clang::SourceLocation IfLoc) override
128 {
129 HandlePPCond(Loc, IfLoc);
130 }
131
132 virtual void Defined(const clang::Token &MacroNameTok, MyMacroDefinition MD,
133 clang::SourceRange Range) override;
134
135private:
136 std::map<clang::SourceLocation, clang::SourceLocation> ElifMapping; // Map an elif location to
137 // the real if;
138 void HandlePPCond(clang::SourceLocation Loc, clang::SourceLocation IfLoc);
139};
140

source code of codebrowser/generator/preprocessorcallback.h