1 //===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the PPConditionalDirectiveRecord class, which maintains
11 // a record of conditional directive regions.
13 //===----------------------------------------------------------------------===//
14 #include "clang/Lex/PPConditionalDirectiveRecord.h"
15 #include "llvm/Support/Capacity.h"
17 using namespace clang;
19 PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
21 CondDirectiveStack.push_back(SourceLocation());
24 bool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective(
25 SourceRange Range) const {
26 if (Range.isInvalid())
29 CondDirectiveLocsTy::const_iterator
30 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
31 Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
32 if (low == CondDirectiveLocs.end())
35 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
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();
45 return low->getRegionLoc() != uppRegion;
48 SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc(
49 SourceLocation Loc) const {
51 return SourceLocation();
52 if (CondDirectiveLocs.empty())
53 return SourceLocation();
55 if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
57 return CondDirectiveStack.back();
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();
66 void PPConditionalDirectiveRecord::addCondDirectiveLoc(
67 CondDirectiveLoc DirLoc) {
68 // Ignore directives in system headers.
69 if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
72 assert(CondDirectiveLocs.empty() ||
73 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
75 CondDirectiveLocs.push_back(DirLoc);
78 void PPConditionalDirectiveRecord::If(SourceLocation Loc,
79 SourceRange ConditionRange) {
80 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
81 CondDirectiveStack.push_back(Loc);
84 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
85 const Token &MacroNameTok,
86 const MacroDirective *MD) {
87 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
88 CondDirectiveStack.push_back(Loc);
91 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
92 const Token &MacroNameTok,
93 const MacroDirective *MD) {
94 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
95 CondDirectiveStack.push_back(Loc);
98 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
99 SourceRange ConditionRange,
100 SourceLocation IfLoc) {
101 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
102 CondDirectiveStack.back() = Loc;
105 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
106 SourceLocation IfLoc) {
107 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
108 CondDirectiveStack.back() = Loc;
111 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
112 SourceLocation IfLoc) {
113 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
114 assert(!CondDirectiveStack.empty());
115 CondDirectiveStack.pop_back();
118 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
119 return llvm::capacity_in_bytes(CondDirectiveLocs);