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
29     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
30                            Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
31   if (low == CondDirectiveLocs.end())
32     return false;
33 
34   if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
35     return false;
36 
37   CondDirectiveLocsTy::const_iterator
38     upp = std::upper_bound(low, CondDirectiveLocs.end(),
39                            Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
40   SourceLocation uppRegion;
41   if (upp != CondDirectiveLocs.end())
42     uppRegion = upp->getRegionLoc();
43 
44   return low->getRegionLoc() != uppRegion;
45 }
46 
47 SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc(
48                                                      SourceLocation Loc) const {
49   if (Loc.isInvalid())
50     return SourceLocation();
51   if (CondDirectiveLocs.empty())
52     return SourceLocation();
53 
54   if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
55                                           Loc))
56     return CondDirectiveStack.back();
57 
58   CondDirectiveLocsTy::const_iterator
59     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
60                            Loc, CondDirectiveLoc::Comp(SourceMgr));
61   assert(low != CondDirectiveLocs.end());
62   return low->getRegionLoc();
63 }
64 
65 void PPConditionalDirectiveRecord::addCondDirectiveLoc(
66                                                       CondDirectiveLoc DirLoc) {
67   // Ignore directives in system headers.
68   if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
69     return;
70 
71   assert(CondDirectiveLocs.empty() ||
72          SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
73                                              DirLoc.getLoc()));
74   CondDirectiveLocs.push_back(DirLoc);
75 }
76 
77 void PPConditionalDirectiveRecord::If(SourceLocation Loc,
78                                       SourceRange ConditionRange,
79                                       ConditionValueKind ConditionValue) {
80   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
81   CondDirectiveStack.push_back(Loc);
82 }
83 
84 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
85                                          const Token &MacroNameTok,
86                                          const MacroDefinition &MD) {
87   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
88   CondDirectiveStack.push_back(Loc);
89 }
90 
91 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
92                                           const Token &MacroNameTok,
93                                           const MacroDefinition &MD) {
94   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
95   CondDirectiveStack.push_back(Loc);
96 }
97 
98 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
99                                         SourceRange ConditionRange,
100                                         ConditionValueKind ConditionValue,
101                                         SourceLocation IfLoc) {
102   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
103   CondDirectiveStack.back() = Loc;
104 }
105 
106 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
107                                         SourceLocation IfLoc) {
108   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
109   CondDirectiveStack.back() = Loc;
110 }
111 
112 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
113                                          SourceLocation IfLoc) {
114   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
115   assert(!CondDirectiveStack.empty());
116   CondDirectiveStack.pop_back();
117 }
118 
119 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
120   return llvm::capacity_in_bytes(CondDirectiveLocs);
121 }
122