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(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       CondDirectiveLocs, Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
30   if (low == CondDirectiveLocs.end())
31     return false;
32 
33   if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
34     return false;
35 
36   CondDirectiveLocsTy::const_iterator
37     upp = std::upper_bound(low, CondDirectiveLocs.end(),
38                            Range.getEnd(), 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(CondDirectiveLocs.back().getLoc(),
54                                           Loc))
55     return CondDirectiveStack.back();
56 
57   CondDirectiveLocsTy::const_iterator low = llvm::lower_bound(
58       CondDirectiveLocs, Loc, 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(DirLoc.getLoc()))
67     return;
68 
69   assert(CondDirectiveLocs.empty() ||
70          SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
71                                              DirLoc.getLoc()));
72   CondDirectiveLocs.push_back(DirLoc);
73 }
74 
75 void PPConditionalDirectiveRecord::If(SourceLocation Loc,
76                                       SourceRange ConditionRange,
77                                       ConditionValueKind ConditionValue) {
78   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
79   CondDirectiveStack.push_back(Loc);
80 }
81 
82 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
83                                          const Token &MacroNameTok,
84                                          const MacroDefinition &MD) {
85   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
86   CondDirectiveStack.push_back(Loc);
87 }
88 
89 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
90                                           const Token &MacroNameTok,
91                                           const MacroDefinition &MD) {
92   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
93   CondDirectiveStack.push_back(Loc);
94 }
95 
96 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
97                                         SourceRange ConditionRange,
98                                         ConditionValueKind ConditionValue,
99                                         SourceLocation IfLoc) {
100   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
101   CondDirectiveStack.back() = Loc;
102 }
103 
104 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &,
105                                            const MacroDefinition &) {
106   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
107   CondDirectiveStack.back() = Loc;
108 }
109 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange,
110                                            SourceLocation) {
111   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
112   CondDirectiveStack.back() = Loc;
113 }
114 
115 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &,
116                                             const MacroDefinition &) {
117   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
118   CondDirectiveStack.back() = Loc;
119 }
120 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange,
121                                             SourceLocation) {
122   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
123   CondDirectiveStack.back() = Loc;
124 }
125 
126 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
127                                         SourceLocation IfLoc) {
128   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
129   CondDirectiveStack.back() = Loc;
130 }
131 
132 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
133                                          SourceLocation IfLoc) {
134   addCondDirectiveLoc(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(CondDirectiveLocs);
141 }
142