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