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