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 low = llvm::lower_bound( 29 CondDirectiveLocs, Range.getBegin(), CondDirectiveLoc::Comp(SourceMgr)); 30 if (low == CondDirectiveLocs.end()) 31 return false; 32 33 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), low->getLoc())) 34 return false; 35 36 CondDirectiveLocsTy::const_iterator 37 upp = std::upper_bound(low, CondDirectiveLocs.end(), 38 Range.getEnd(), CondDirectiveLoc::Comp(SourceMgr)); 39 SourceLocation uppRegion; 40 if (upp != CondDirectiveLocs.end()) 41 uppRegion = upp->getRegionLoc(); 42 43 return low->getRegionLoc() != uppRegion; 44 } 45 46 SourceLocation PPConditionalDirectiveRecord::findConditionalDirectiveRegionLoc( 47 SourceLocation Loc) const { 48 if (Loc.isInvalid()) 49 return SourceLocation(); 50 if (CondDirectiveLocs.empty()) 51 return SourceLocation(); 52 53 if (SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), 54 Loc)) 55 return CondDirectiveStack.back(); 56 57 CondDirectiveLocsTy::const_iterator low = llvm::lower_bound( 58 CondDirectiveLocs, Loc, CondDirectiveLoc::Comp(SourceMgr)); 59 assert(low != CondDirectiveLocs.end()); 60 return low->getRegionLoc(); 61 } 62 63 void PPConditionalDirectiveRecord::addCondDirectiveLoc( 64 CondDirectiveLoc DirLoc) { 65 // Ignore directives in system headers. 66 if (SourceMgr.isInSystemHeader(DirLoc.getLoc())) 67 return; 68 69 assert(CondDirectiveLocs.empty() || 70 SourceMgr.isBeforeInTranslationUnit(CondDirectiveLocs.back().getLoc(), 71 DirLoc.getLoc())); 72 CondDirectiveLocs.push_back(DirLoc); 73 } 74 75 void PPConditionalDirectiveRecord::If(SourceLocation Loc, 76 SourceRange ConditionRange, 77 ConditionValueKind ConditionValue) { 78 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 79 CondDirectiveStack.push_back(Loc); 80 } 81 82 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc, 83 const Token &MacroNameTok, 84 const MacroDefinition &MD) { 85 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 86 CondDirectiveStack.push_back(Loc); 87 } 88 89 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc, 90 const Token &MacroNameTok, 91 const MacroDefinition &MD) { 92 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 93 CondDirectiveStack.push_back(Loc); 94 } 95 96 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc, 97 SourceRange ConditionRange, 98 ConditionValueKind ConditionValue, 99 SourceLocation IfLoc) { 100 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 101 CondDirectiveStack.back() = Loc; 102 } 103 104 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, const Token &, 105 const MacroDefinition &) { 106 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 107 CondDirectiveStack.back() = Loc; 108 } 109 void PPConditionalDirectiveRecord::Elifdef(SourceLocation Loc, SourceRange, 110 SourceLocation) { 111 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 112 CondDirectiveStack.back() = Loc; 113 } 114 115 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, const Token &, 116 const MacroDefinition &) { 117 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 118 CondDirectiveStack.back() = Loc; 119 } 120 void PPConditionalDirectiveRecord::Elifndef(SourceLocation Loc, SourceRange, 121 SourceLocation) { 122 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 123 CondDirectiveStack.back() = Loc; 124 } 125 126 void PPConditionalDirectiveRecord::Else(SourceLocation Loc, 127 SourceLocation IfLoc) { 128 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 129 CondDirectiveStack.back() = Loc; 130 } 131 132 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc, 133 SourceLocation IfLoc) { 134 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 135 assert(!CondDirectiveStack.empty()); 136 CondDirectiveStack.pop_back(); 137 } 138 139 size_t PPConditionalDirectiveRecord::getTotalMemory() const { 140 return llvm::capacity_in_bytes(CondDirectiveLocs); 141 } 142