1 | //===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- 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 | // This file implements the PPConditionalDirectiveRecord class, which maintains |
10 | // a record of conditional directive regions. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | #include "clang/Lex/PPConditionalDirectiveRecord.h" |
14 | #include "llvm/Support/Capacity.h" |
15 | |
16 | using namespace clang; |
17 | |
18 | PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM) |
19 | : SourceMgr(SM) { |
20 | CondDirectiveStack.push_back(Elt: SourceLocation()); |
21 | } |
22 | |
23 | bool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective( |
24 | SourceRange Range) const { |
25 | if (Range.isInvalid()) |
26 | return false; |
27 | |
28 | CondDirectiveLocsTy::const_iterator low = llvm::lower_bound( |
29 | Range: CondDirectiveLocs, Value: Range.getBegin(), C: CondDirectiveLoc::Comp(SourceMgr)); |
30 | if (low == CondDirectiveLocs.end()) |
31 | return false; |
32 | |
33 | if (SourceMgr.isBeforeInTranslationUnit(LHS: Range.getEnd(), RHS: low->getLoc())) |
34 | return false; |
35 | |
36 | CondDirectiveLocsTy::const_iterator |
37 | upp = std::upper_bound(first: low, last: CondDirectiveLocs.end(), |
38 | val: Range.getEnd(), comp: CondDirectiveLoc::Comp(SourceMgr)); |
39 | SourceLocation uppRegion; |
40 | if (upp != CondDirectiveLocs.end()) |
41 | uppRegion = upp->getRegionLoc(); |
42 | |
43 | return low->getRegionLoc() != uppRegion; |
44 | } |
45 | |
46 | SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc( |
47 | SourceLocation Loc) const { |
48 | if (Loc.isInvalid()) |
49 | return SourceLocation(); |
50 | if (CondDirectiveLocs.empty()) |
51 | return SourceLocation(); |
52 | |
53 | if (SourceMgr.isBeforeInTranslationUnit(LHS: CondDirectiveLocs.back().getLoc(), |
54 | RHS: Loc)) |
55 | return CondDirectiveStack.back(); |
56 | |
57 | CondDirectiveLocsTy::const_iterator low = llvm::lower_bound( |
58 | Range: CondDirectiveLocs, Value&: Loc, C: CondDirectiveLoc::Comp(SourceMgr)); |
59 | assert(low != CondDirectiveLocs.end()); |
60 | return low->getRegionLoc(); |
61 | } |
62 | |
63 | void PPConditionalDirectiveRecord::addCondDirectiveLoc( |
64 | CondDirectiveLoc DirLoc) { |
65 | // Ignore directives in system headers. |
66 | if (SourceMgr.isInSystemHeader(Loc: DirLoc.getLoc())) |
67 | return; |
68 | |
69 | assert(CondDirectiveLocs.empty() || |
70 | SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), |
71 | DirLoc.getLoc())); |
72 | CondDirectiveLocs.push_back(x: DirLoc); |
73 | } |
74 | |
75 | void PPConditionalDirectiveRecord::If(SourceLocation Loc, |
76 | SourceRange ConditionRange, |
77 | ConditionValueKind ConditionValue) { |
78 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
79 | CondDirectiveStack.push_back(Elt: Loc); |
80 | } |
81 | |
82 | void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc, |
83 | const Token &MacroNameTok, |
84 | const MacroDefinition &MD) { |
85 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
86 | CondDirectiveStack.push_back(Elt: Loc); |
87 | } |
88 | |
89 | void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc, |
90 | const Token &MacroNameTok, |
91 | const MacroDefinition &MD) { |
92 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
93 | CondDirectiveStack.push_back(Elt: Loc); |
94 | } |
95 | |
96 | void PPConditionalDirectiveRecord::Elif(SourceLocation Loc, |
97 | SourceRange ConditionRange, |
98 | ConditionValueKind ConditionValue, |
99 | SourceLocation IfLoc) { |
100 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
101 | CondDirectiveStack.back() = Loc; |
102 | } |
103 | |
104 | void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &, |
105 | const MacroDefinition &) { |
106 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
107 | CondDirectiveStack.back() = Loc; |
108 | } |
109 | void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange, |
110 | SourceLocation) { |
111 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
112 | CondDirectiveStack.back() = Loc; |
113 | } |
114 | |
115 | void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &, |
116 | const MacroDefinition &) { |
117 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
118 | CondDirectiveStack.back() = Loc; |
119 | } |
120 | void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange, |
121 | SourceLocation) { |
122 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
123 | CondDirectiveStack.back() = Loc; |
124 | } |
125 | |
126 | void PPConditionalDirectiveRecord::Else(SourceLocation Loc, |
127 | SourceLocation IfLoc) { |
128 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
129 | CondDirectiveStack.back() = Loc; |
130 | } |
131 | |
132 | void PPConditionalDirectiveRecord::Endif(SourceLocation Loc, |
133 | SourceLocation IfLoc) { |
134 | addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back())); |
135 | assert(!CondDirectiveStack.empty()); |
136 | CondDirectiveStack.pop_back(); |
137 | } |
138 | |
139 | size_t PPConditionalDirectiveRecord::getTotalMemory() const { |
140 | return llvm::capacity_in_bytes(x: CondDirectiveLocs); |
141 | } |
142 | |