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                                       bool ConditionValue) {
     81   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
     82   CondDirectiveStack.push_back(Loc);
     83 }
     84 
     85 void PPConditionalDirectiveRecord::Ifdef(SourceLocation Loc,
     86                                          const Token &MacroNameTok,
     87                                          const MacroDirective *MD) {
     88   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
     89   CondDirectiveStack.push_back(Loc);
     90 }
     91 
     92 void PPConditionalDirectiveRecord::Ifndef(SourceLocation Loc,
     93                                           const Token &MacroNameTok,
     94                                           const MacroDirective *MD) {
     95   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
     96   CondDirectiveStack.push_back(Loc);
     97 }
     98 
     99 void PPConditionalDirectiveRecord::Elif(SourceLocation Loc,
    100                                         SourceRange ConditionRange,
    101                                         bool ConditionValue,
    102                                         SourceLocation IfLoc) {
    103   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    104   CondDirectiveStack.back() = Loc;
    105 }
    106 
    107 void PPConditionalDirectiveRecord::Else(SourceLocation Loc,
    108                                         SourceLocation IfLoc) {
    109   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    110   CondDirectiveStack.back() = Loc;
    111 }
    112 
    113 void PPConditionalDirectiveRecord::Endif(SourceLocation Loc,
    114                                          SourceLocation IfLoc) {
    115   addCondDirectiveLoc(CondDirectiveLoc(Loc, CondDirectiveStack.back()));
    116   assert(!CondDirectiveStack.empty());
    117   CondDirectiveStack.pop_back();
    118 }
    119 
    120 size_t PPConditionalDirectiveRecord::getTotalMemory() const {
    121   return llvm::capacity_in_bytes(CondDirectiveLocs);
    122 }
    123