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
16using namespace clang;
17
18PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
19 : SourceMgr(SM) {
20 CondDirectiveStack.push_back(Elt: SourceLocation());
21}
22
23bool 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
46SourceLocation 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
63void 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
75void 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
82void 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
89void 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
96void 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
104void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &,
105 const MacroDefinition &) {
106 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
107 CondDirectiveStack.back() = Loc;
108}
109void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange,
110 SourceLocation) {
111 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
112 CondDirectiveStack.back() = Loc;
113}
114
115void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &,
116 const MacroDefinition &) {
117 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
118 CondDirectiveStack.back() = Loc;
119}
120void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange,
121 SourceLocation) {
122 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
123 CondDirectiveStack.back() = Loc;
124}
125
126void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
127 SourceLocation IfLoc) {
128 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
129 CondDirectiveStack.back() = Loc;
130}
131
132void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
133 SourceLocation IfLoc) {
134 addCondDirectiveLoc(DirLoc: CondDirectiveLoc(Loc, CondDirectiveStack.back()));
135 assert(!CondDirectiveStack.empty());
136 CondDirectiveStack.pop_back();
137}
138
139size_t PPConditionalDirectiveRecord::getTotalMemory() const {
140 return llvm::capacity_in_bytes(x: CondDirectiveLocs);
141}
142