1 //===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- C++ -*-=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the PPConditionalDirectiveRecord class, which maintains 10 // a record of conditional directive regions. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "clang/Lex/PPConditionalDirectiveRecord.h" 14 #include "llvm/Support/Capacity.h" 15 16 using namespace clang; 17 18 PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM) 19 : SourceMgr(SM) { 20 CondDirectiveStack.push_back(SourceLocation()); 21 } 22 23 bool PPConditionalDirectiveRecord::rangeIntersectsConditionalDirective( 24 SourceRange Range) const { 25 if (Range.isInvalid()) 26 return false; 27 28 CondDirectiveLocsTy::const_iterator 29 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(), 30 Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr)); 31 if (low == CondDirectiveLocs.end()) 32 return false; 33 34 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc())) 35 return false; 36 37 CondDirectiveLocsTy::const_iterator 38 upp = std::upper_bound(low, CondDirectiveLocs.end(), 39 Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr)); 40 SourceLocation uppRegion; 41 if (upp != CondDirectiveLocs.end()) 42 uppRegion = upp->getRegionLoc(); 43 44 return low->getRegionLoc() != uppRegion; 45 } 46 47 SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc( 48 SourceLocation Loc) const { 49 if (Loc.isInvalid()) 50 return SourceLocation(); 51 if (CondDirectiveLocs.empty()) 52 return SourceLocation(); 53 54 if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), 55 Loc)) 56 return CondDirectiveStack.back(); 57 58 CondDirectiveLocsTy::const_iterator 59 low = std::lower_bound(CondDirectiveLocs.begin(), CondDirectiveLocs.end(), 60 Loc, CondDirectiveLoc::Comp(SourceMgr)); 61 assert(low != CondDirectiveLocs.end()); 62 return low->getRegionLoc(); 63 } 64 65 void PPConditionalDirectiveRecord::addCondDirectiveLoc( 66 CondDirectiveLoc DirLoc) { 67 // Ignore directives in system headers. 68 if (SourceMgr.isInSystemHeader(DirLoc.getLoc())) 69 return; 70 71 assert(CondDirectiveLocs.empty() || 72 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), 73 DirLoc.getLoc())); 74 CondDirectiveLocs.push_back(DirLoc); 75 } 76 77 void PPConditionalDirectiveRecord::If(SourceLocation Loc, 78 SourceRange ConditionRange, 79 ConditionValueKind ConditionValue) { 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 MacroDefinition &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 MacroDefinition &MD) { 94 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 95 CondDirectiveStack.push_back(Loc); 96 } 97 98 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc, 99 SourceRange ConditionRange, 100 ConditionValueKind ConditionValue, 101 SourceLocation IfLoc) { 102 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 103 CondDirectiveStack.back() = Loc; 104 } 105 106 void PPConditionalDirectiveRecord::Else(SourceLocation Loc, 107 SourceLocation IfLoc) { 108 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 109 CondDirectiveStack.back() = Loc; 110 } 111 112 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc, 113 SourceLocation IfLoc) { 114 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 115 assert(!CondDirectiveStack.empty()); 116 CondDirectiveStack.pop_back(); 117 } 118 119 size_t PPConditionalDirectiveRecord::getTotalMemory() const { 120 return llvm::capacity_in_bytes(CondDirectiveLocs); 121 } 122