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 16using namespace clang; 17 18PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM) 19 : SourceMgr(SM) { 20 CondDirectiveStack.push_back(SourceLocation()); 21} 22 23bool 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 46SourceLocation 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 63void 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 75void PPConditionalDirectiveRecord::If(SourceLocation Loc, 76 SourceRange ConditionRange, 77 ConditionValueKind ConditionValue) { 78 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 79 CondDirectiveStack.push_back(Loc); 80} 81 82void 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 89void 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 96void 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 104void PPConditionalDirectiveRecord::Else(SourceLocation Loc, 105 SourceLocation IfLoc) { 106 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 107 CondDirectiveStack.back() = Loc; 108} 109 110void PPConditionalDirectiveRecord::Endif(SourceLocation Loc, 111 SourceLocation IfLoc) { 112 addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back())); 113 assert(!CondDirectiveStack.empty()); 114 CondDirectiveStack.pop_back(); 115} 116 117size_t PPConditionalDirectiveRecord::getTotalMemory() const { 118 return llvm::capacity_in_bytes(CondDirectiveLocs); 119} 120