1249261Sdim//===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=//
2249261Sdim//
3249261Sdim//                     The LLVM Compiler Infrastructure
4249261Sdim//
5249261Sdim// This file is distributed under the University of Illinois Open Source
6249261Sdim// License. See LICENSE.TXT for details.
7249261Sdim//
8249261Sdim//===----------------------------------------------------------------------===//
9249261Sdim//
10249261Sdim//  This file implements the PPConditionalDirectiveRecord class, which maintains
11249261Sdim//  a record of conditional directive regions.
12249261Sdim//
13249261Sdim//===----------------------------------------------------------------------===//
14249261Sdim#include "clang/Lex/PPConditionalDirectiveRecord.h"
15249261Sdim#include "llvm/Support/Capacity.h"
16249261Sdim
17249261Sdimusing namespace clang;
18249261Sdim
19249261SdimPPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
20249261Sdim  : SourceMgr(SM) {
21249261Sdim  CondDirectiveStack.push_back(SourceLocation());
22249261Sdim}
23249261Sdim
24249261Sdimbool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective(
25249261Sdim                                                      SourceRange Range) const {
26249261Sdim  if (Range.isInvalid())
27249261Sdim    return false;
28249261Sdim
29249261Sdim  CondDirectiveLocsTy::const_iterator
30249261Sdim    low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
31249261Sdim                           Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr));
32249261Sdim  if (low == CondDirectiveLocs.end())
33249261Sdim    return false;
34249261Sdim
35249261Sdim  if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc()))
36249261Sdim    return false;
37249261Sdim
38249261Sdim  CondDirectiveLocsTy::const_iterator
39249261Sdim    upp = std::upper_bound(low, CondDirectiveLocs.end(),
40249261Sdim                           Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr));
41249261Sdim  SourceLocation uppRegion;
42249261Sdim  if (upp != CondDirectiveLocs.end())
43249261Sdim    uppRegion = upp->getRegionLoc();
44249261Sdim
45249261Sdim  return low->getRegionLoc() != uppRegion;
46249261Sdim}
47249261Sdim
48249261SdimSourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc(
49249261Sdim                                                     SourceLocation Loc) const {
50249261Sdim  if (Loc.isInvalid())
51249261Sdim    return SourceLocation();
52249261Sdim  if (CondDirectiveLocs.empty())
53249261Sdim    return SourceLocation();
54249261Sdim
55249261Sdim  if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
56249261Sdim                                          Loc))
57249261Sdim    return CondDirectiveStack.back();
58249261Sdim
59249261Sdim  CondDirectiveLocsTy::const_iterator
60249261Sdim    low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(),
61249261Sdim                           Loc, CondDirectiveLoc::Comp(SourceMgr));
62249261Sdim  assert(low != CondDirectiveLocs.end());
63249261Sdim  return low->getRegionLoc();
64249261Sdim}
65249261Sdim
66249261Sdimvoid PPConditionalDirectiveRecord::addCondDirectiveLoc(
67249261Sdim                                                      CondDirectiveLoc DirLoc) {
68249261Sdim  // Ignore directives in system headers.
69249261Sdim  if (SourceMgr.isInSystemHeader(DirLoc.getLoc()))
70249261Sdim    return;
71249261Sdim
72249261Sdim  assert(CondDirectiveLocs.empty() ||
73249261Sdim         SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(),
74249261Sdim                                             DirLoc.getLoc()));
75249261Sdim  CondDirectiveLocs.push_back(DirLoc);
76249261Sdim}
77249261Sdim
78249261Sdimvoid PPConditionalDirectiveRecord::If(SourceLocation Loc,
79263509Sdim                                      SourceRange ConditionRange,
80263509Sdim                                      bool ConditionValue) {
81249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
82249261Sdim  CondDirectiveStack.push_back(Loc);
83249261Sdim}
84249261Sdim
85249261Sdimvoid PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
86249261Sdim                                         const Token &MacroNameTok,
87249261Sdim                                         const MacroDirective *MD) {
88249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
89249261Sdim  CondDirectiveStack.push_back(Loc);
90249261Sdim}
91249261Sdim
92249261Sdimvoid PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
93249261Sdim                                          const Token &MacroNameTok,
94249261Sdim                                          const MacroDirective *MD) {
95249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
96249261Sdim  CondDirectiveStack.push_back(Loc);
97249261Sdim}
98249261Sdim
99249261Sdimvoid PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
100249261Sdim                                        SourceRange ConditionRange,
101263509Sdim                                        bool ConditionValue,
102249261Sdim                                        SourceLocation IfLoc) {
103249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
104249261Sdim  CondDirectiveStack.back() = Loc;
105249261Sdim}
106249261Sdim
107249261Sdimvoid PPConditionalDirectiveRecord::Else(SourceLocation Loc,
108249261Sdim                                        SourceLocation IfLoc) {
109249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
110249261Sdim  CondDirectiveStack.back() = Loc;
111249261Sdim}
112249261Sdim
113249261Sdimvoid PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
114249261Sdim                                         SourceLocation IfLoc) {
115249261Sdim  addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
116249261Sdim  assert(!CondDirectiveStack.empty());
117249261Sdim  CondDirectiveStack.pop_back();
118249261Sdim}
119249261Sdim
120249261Sdimsize_t PPConditionalDirectiveRecord::getTotalMemory() const {
121249261Sdim  return llvm::capacity_in_bytes(CondDirectiveLocs);
122249261Sdim}
123