Home | History | Annotate | Line # | Download | only in Lex
      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::Else(SourceLocation Loc,
    105                                         SourceLocation IfLoc) {
    106   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    107   CondDirectiveStack.back() = Loc;
    108 }
    109 
    110 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
    111                                          SourceLocation IfLoc) {
    112   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    113   assert(!CondDirectiveStack.empty());
    114   CondDirectiveStack.pop_back();
    115 }
    116 
    117 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
    118   return llvm::capacity_in_bytes(CondDirectiveLocs);
    119 }
    120