1 //===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the PPConditionalDirectiveRecord class, which maintains
10 // a record of conditional directive regions.
12 //===----------------------------------------------------------------------===//
13 #include "clang/Lex/PPConditionalDirectiveRecord.h"
14 #include "llvm/Support/Capacity.h"
16 using namespace clang
;
18 PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager
&SM
)
20 CondDirectiveStack
.push_back(SourceLocation());
23 bool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective(
24 SourceRange Range
) const {
25 if (Range
.isInvalid())
28 CondDirectiveLocsTy::const_iterator low
= llvm::lower_bound(
29 CondDirectiveLocs
, Range
.getBegin(), CondDirectiveLoc::Comp(SourceMgr
));
30 if (low
== CondDirectiveLocs
.end())
33 if (SourceMgr
.isBeforeInTranslationUnit(Range
.getEnd(), low
->getLoc()))
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();
43 return low
->getRegionLoc() != uppRegion
;
46 SourceLocation
PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc(
47 SourceLocation Loc
) const {
49 return SourceLocation();
50 if (CondDirectiveLocs
.empty())
51 return SourceLocation();
53 if (SourceMgr
.isBeforeInTranslationUnit(CondDirectiveLocs
.back().getLoc(),
55 return CondDirectiveStack
.back();
57 CondDirectiveLocsTy::const_iterator low
= llvm::lower_bound(
58 CondDirectiveLocs
, Loc
, CondDirectiveLoc::Comp(SourceMgr
));
59 assert(low
!= CondDirectiveLocs
.end());
60 return low
->getRegionLoc();
63 void PPConditionalDirectiveRecord::addCondDirectiveLoc(
64 CondDirectiveLoc DirLoc
) {
65 // Ignore directives in system headers.
66 if (SourceMgr
.isInSystemHeader(DirLoc
.getLoc()))
69 assert(CondDirectiveLocs
.empty() ||
70 SourceMgr
.isBeforeInTranslationUnit(CondDirectiveLocs
.back().getLoc(),
72 CondDirectiveLocs
.push_back(DirLoc
);
75 void PPConditionalDirectiveRecord::If(SourceLocation Loc
,
76 SourceRange ConditionRange
,
77 ConditionValueKind ConditionValue
) {
78 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
79 CondDirectiveStack
.push_back(Loc
);
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
);
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
);
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
;
104 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc
, const Token
&,
105 const MacroDefinition
&) {
106 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
107 CondDirectiveStack
.back() = Loc
;
109 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc
, SourceRange
,
111 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
112 CondDirectiveStack
.back() = Loc
;
115 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc
, const Token
&,
116 const MacroDefinition
&) {
117 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
118 CondDirectiveStack
.back() = Loc
;
120 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc
, SourceRange
,
122 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
123 CondDirectiveStack
.back() = Loc
;
126 void PPConditionalDirectiveRecord::Else(SourceLocation Loc
,
127 SourceLocation IfLoc
) {
128 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
129 CondDirectiveStack
.back() = Loc
;
132 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc
,
133 SourceLocation IfLoc
) {
134 addCondDirectiveLoc(CondDirectiveLoc(Loc
, CondDirectiveStack
.back()));
135 assert(!CondDirectiveStack
.empty());
136 CondDirectiveStack
.pop_back();
139 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
140 return llvm::capacity_in_bytes(CondDirectiveLocs
);