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 defines the PPConditionalDirectiveRecord class, which maintains 11 // a record of conditional directive regions. 12 // 13 //===----------------------------------------------------------------------===// 14 #ifndef LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H 15 #define LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H 16 17 #include "clang/Basic/SourceLocation.h" 18 #include "clang/Lex/PPCallbacks.h" 19 #include "llvm/ADT/SmallVector.h" 20 #include <vector> 21 22 namespace clang { 23 24 /// \brief Records preprocessor conditional directive regions and allows 25 /// querying in which region source locations belong to. 26 class PPConditionalDirectiveRecord : public PPCallbacks { 27 SourceManager &SourceMgr; 28 29 SmallVector<SourceLocation, 6> CondDirectiveStack; 30 31 class CondDirectiveLoc { 32 SourceLocation Loc; 33 SourceLocation RegionLoc; 34 35 public: CondDirectiveLoc(SourceLocation Loc,SourceLocation RegionLoc)36 CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc) 37 : Loc(Loc), RegionLoc(RegionLoc) {} 38 getLoc()39 SourceLocation getLoc() const { return Loc; } getRegionLoc()40 SourceLocation getRegionLoc() const { return RegionLoc; } 41 42 class Comp { 43 SourceManager &SM; 44 public: Comp(SourceManager & SM)45 explicit Comp(SourceManager &SM) : SM(SM) {} operator()46 bool operator()(const CondDirectiveLoc &LHS, 47 const CondDirectiveLoc &RHS) { 48 return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc()); 49 } operator()50 bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) { 51 return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS); 52 } operator()53 bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) { 54 return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc()); 55 } 56 }; 57 }; 58 59 typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; 60 /// \brief The locations of conditional directives in source order. 61 CondDirectiveLocsTy CondDirectiveLocs; 62 63 void addCondDirectiveLoc(CondDirectiveLoc DirLoc); 64 65 public: 66 /// \brief Construct a new preprocessing record. 67 explicit PPConditionalDirectiveRecord(SourceManager &SM); 68 69 size_t getTotalMemory() const; 70 getSourceManager()71 SourceManager &getSourceManager() const { return SourceMgr; } 72 73 /// \brief Returns true if the given range intersects with a conditional 74 /// directive. if a \#if/\#endif block is fully contained within the range, 75 /// this function will return false. 76 bool rangeIntersectsConditionalDirective(SourceRange Range) const; 77 78 /// \brief Returns true if the given locations are in different regions, 79 /// separated by conditional directive blocks. areInDifferentConditionalDirectiveRegion(SourceLocation LHS,SourceLocation RHS)80 bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, 81 SourceLocation RHS) const { 82 return findConditionalDirectiveRegionLoc(LHS) != 83 findConditionalDirectiveRegionLoc(RHS); 84 } 85 86 SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const; 87 88 private: 89 void If(SourceLocation Loc, SourceRange ConditionRange, 90 ConditionValueKind ConditionValue) override; 91 void Elif(SourceLocation Loc, SourceRange ConditionRange, 92 ConditionValueKind ConditionValue, SourceLocation IfLoc) override; 93 void Ifdef(SourceLocation Loc, const Token &MacroNameTok, 94 const MacroDefinition &MD) override; 95 void Ifndef(SourceLocation Loc, const Token &MacroNameTok, 96 const MacroDefinition &MD) override; 97 void Else(SourceLocation Loc, SourceLocation IfLoc) override; 98 void Endif(SourceLocation Loc, SourceLocation IfLoc) override; 99 }; 100 101 } // end namespace clang 102 103 #endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H 104