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