1 //===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the PPConditionalDirectiveRecord class, which maintains
11 //  a record of conditional directive regions.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/Lex/PPConditionalDirectiveRecord.h"
15 #include "llvm/Support/Capacity.h"
16 
17 using namespace clang;
18 
PPConditionalDirectiveRecord(SourceManager & SM)19 PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
20   : SourceMgr(SM) {
21   CondDirectiveStack.push_back(SourceLocation());
22 }
23 
rangeIntersectsConditionalDirective(SourceRange Range) const24 bool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective(
25                                                       SourceRange Range) const {
26   if (Range.isInvalid())
27     return false;
28 
29   CondDirectiveLocsTy::const_iterator
30     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
31                            Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
32   if (low == CondDirectiveLocs.end())
33     return false;
34 
35   if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
36     return false;
37 
38   CondDirectiveLocsTy::const_iterator
39     upp = std::upper_bound(low, CondDirectiveLocs.end(),
40                            Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
41   SourceLocation uppRegion;
42   if (upp != CondDirectiveLocs.end())
43     uppRegion = upp->getRegionLoc();
44 
45   return low->getRegionLoc() != uppRegion;
46 }
47 
findConditionalDirectiveRegionLoc(SourceLocation Loc) const48 SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc(
49                                                      SourceLocation Loc) const {
50   if (Loc.isInvalid())
51     return SourceLocation();
52   if (CondDirectiveLocs.empty())
53     return SourceLocation();
54 
55   if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
56                                           Loc))
57     return CondDirectiveStack.back();
58 
59   CondDirectiveLocsTy::const_iterator
60     low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
61                            Loc, CondDirectiveLoc::Comp(SourceMgr));
62   assert(low != CondDirectiveLocs.end());
63   return low->getRegionLoc();
64 }
65 
addCondDirectiveLoc(CondDirectiveLoc DirLoc)66 void PPConditionalDirectiveRecord::addCondDirectiveLoc(
67                                                       CondDirectiveLoc DirLoc) {
68   // Ignore directives in system headers.
69   if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
70     return;
71 
72   assert(CondDirectiveLocs.empty() ||
73          SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
74                                              DirLoc.getLoc()));
75   CondDirectiveLocs.push_back(DirLoc);
76 }
77 
If(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue)78 void PPConditionalDirectiveRecord::If(SourceLocation Loc,
79                                       SourceRange ConditionRange,
80                                       ConditionValueKind ConditionValue) {
81   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
82   CondDirectiveStack.push_back(Loc);
83 }
84 
Ifdef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)85 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
86                                          const Token &MacroNameTok,
87                                          const MacroDefinition &MD) {
88   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
89   CondDirectiveStack.push_back(Loc);
90 }
91 
Ifndef(SourceLocation Loc,const Token & MacroNameTok,const MacroDefinition & MD)92 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
93                                           const Token &MacroNameTok,
94                                           const MacroDefinition &MD) {
95   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
96   CondDirectiveStack.push_back(Loc);
97 }
98 
Elif(SourceLocation Loc,SourceRange ConditionRange,ConditionValueKind ConditionValue,SourceLocation IfLoc)99 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
100                                         SourceRange ConditionRange,
101                                         ConditionValueKind ConditionValue,
102                                         SourceLocation IfLoc) {
103   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
104   CondDirectiveStack.back() = Loc;
105 }
106 
Else(SourceLocation Loc,SourceLocation IfLoc)107 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
108                                         SourceLocation IfLoc) {
109   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
110   CondDirectiveStack.back() = Loc;
111 }
112 
Endif(SourceLocation Loc,SourceLocation IfLoc)113 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
114                                          SourceLocation IfLoc) {
115   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
116   assert(!CondDirectiveStack.empty());
117   CondDirectiveStack.pop_back();
118 }
119 
getTotalMemory() const120 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
121   return llvm::capacity_in_bytes(CondDirectiveLocs);
122 }
123