Home | History | Annotate | Download | only in Lex
      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 
     17 using namespace clang;
     18 
     19 PPConditionalDirectiveRecord::PPConditionalDirectiveRecord(SourceManager &SM)
     20   : SourceMgr(SM) {
     21   CondDirectiveStack.push_back(SourceLocation());
     22 }
     23 
     24 bool 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 
     48 SourceLocation 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 
     66 void 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 
     78 void PPConditionalDirectiveRecord::If(SourceLocation Loc,
     79                                       SourceRange ConditionRange) {
     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 MacroDirective *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 MacroDirective *MD) {
     94   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
     95   CondDirectiveStack.push_back(Loc);
     96 }
     97 
     98 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
     99                                         SourceRange ConditionRange,
    100                                         SourceLocation IfLoc) {
    101   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    102   CondDirectiveStack.back() = Loc;
    103 }
    104 
    105 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
    106                                         SourceLocation IfLoc) {
    107   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    108   CondDirectiveStack.back() = Loc;
    109 }
    110 
    111 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
    112                                          SourceLocation IfLoc) {
    113   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    114   assert(!CondDirectiveStack.empty());
    115   CondDirectiveStack.pop_back();
    116 }
    117 
    118 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
    119   return llvm::capacity_in_bytes(CondDirectiveLocs);
    120 }
    121