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
17using namespace clang;
18
19PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
20  : SourceMgr(SM) {
21  CondDirectiveStack.push_back(SourceLocation());
22}
23
24bool 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
48SourceLocation 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
66void 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
78void PPConditionalDirectiveRecord::If(SourceLocation Loc,
79                                      SourceRange ConditionRange,
80                                      ConditionValueKind ConditionValue) {
81  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
82  CondDirectiveStack.push_back(Loc);
83}
84
85void 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
92void 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
99void 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
107void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
108                                        SourceLocation IfLoc) {
109  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
110  CondDirectiveStack.back() = Loc;
111}
112
113void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
114                                         SourceLocation IfLoc) {
115  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
116  assert(!CondDirectiveStack.empty());
117  CondDirectiveStack.pop_back();
118}
119
120size_t PPConditionalDirectiveRecord::getTotalMemory() const {
121  return llvm::capacity_in_bytes(CondDirectiveLocs);
122}
123