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
21namespace clang {
22
23/// Records preprocessor conditional directive regions and allows
24/// querying in which region source locations belong to.
25class 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:
35    CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc)
36      : Loc(Loc), RegionLoc(RegionLoc) {}
37
38    SourceLocation getLoc() const { return Loc; }
39    SourceLocation getRegionLoc() const { return RegionLoc; }
40
41    class Comp {
42      SourceManager &SM;
43    public:
44      explicit Comp(SourceManager &SM) : SM(SM) {}
45      bool operator()(const CondDirectiveLoc &LHS,
46                      const CondDirectiveLoc &RHS) {
47        return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc());
48      }
49      bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) {
50        return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS);
51      }
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
64public:
65  /// Construct a new preprocessing record.
66  explicit PPConditionalDirectiveRecord(SourceManager &SM);
67
68  size_t getTotalMemory() const;
69
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.
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
87private:
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 Else(SourceLocation Loc, SourceLocation IfLoc) override;
97  void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
98};
99
100} // end namespace clang
101
102#endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
103