aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/include/clang/Lex/DependencyDirectivesScanner.h
blob: 9ab24d499b4f10a82f543704840d01ae11eafcdd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===- clang/Lex/DependencyDirectivesScanner.h ---------------------*- C++ -*-//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This is the interface for scanning header and source files to get the
/// minimum necessary preprocessor directives for evaluating includes. It
/// reduces the source down to #define, #include, #import, @import, and any
/// conditional preprocessor logic that contains one of those.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H
#define LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H

#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"

namespace clang {

namespace tok {
enum TokenKind : unsigned short;
}

class DiagnosticsEngine;

namespace dependency_directives_scan {

/// Token lexed as part of dependency directive scanning.
struct Token {
  /// Offset into the original source input.
  unsigned Offset;
  unsigned Length;
  tok::TokenKind Kind;
  unsigned short Flags;

  Token(unsigned Offset, unsigned Length, tok::TokenKind Kind,
        unsigned short Flags)
      : Offset(Offset), Length(Length), Kind(Kind), Flags(Flags) {}

  unsigned getEnd() const { return Offset + Length; }

  bool is(tok::TokenKind K) const { return Kind == K; }
  bool isNot(tok::TokenKind K) const { return Kind != K; }
  bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
    return is(K1) || is(K2);
  }
  template <typename... Ts> bool isOneOf(tok::TokenKind K1, Ts... Ks) const {
    return is(K1) || isOneOf(Ks...);
  }
};

/// Represents the kind of preprocessor directive or a module declaration that
/// is tracked by the scanner in its token output.
enum DirectiveKind : uint8_t {
  pp_none,
  pp_include,
  pp___include_macros,
  pp_define,
  pp_undef,
  pp_import,
  pp_pragma_import,
  pp_pragma_once,
  pp_pragma_push_macro,
  pp_pragma_pop_macro,
  pp_pragma_include_alias,
  pp_include_next,
  pp_if,
  pp_ifdef,
  pp_ifndef,
  pp_elif,
  pp_elifdef,
  pp_elifndef,
  pp_else,
  pp_endif,
  decl_at_import,
  cxx_module_decl,
  cxx_import_decl,
  cxx_export_module_decl,
  cxx_export_import_decl,
  /// Indicates that there are tokens present between the last scanned directive
  /// and eof. The \p Directive::Tokens array will be empty for this kind.
  tokens_present_before_eof,
  pp_eof,
};

/// Represents a directive that's lexed as part of the dependency directives
/// scanning. It's used to track various preprocessor directives that could
/// potentially have an effect on the dependencies.
struct Directive {
  ArrayRef<Token> Tokens;

  /// The kind of token.
  DirectiveKind Kind = pp_none;

  Directive() = default;
  Directive(DirectiveKind K, ArrayRef<Token> Tokens)
      : Tokens(Tokens), Kind(K) {}
};

} // end namespace dependency_directives_scan

/// Scan the input for the preprocessor directives that might have
/// an effect on the dependencies for a compilation unit.
///
/// This function ignores all non-preprocessor code and anything that
/// can't affect what gets included.
///
/// \returns false on success, true on error. If the diagnostic engine is not
/// null, an appropriate error is reported using the given input location
/// with the offset that corresponds to the \p Input buffer offset.
bool scanSourceForDependencyDirectives(
    StringRef Input, SmallVectorImpl<dependency_directives_scan::Token> &Tokens,
    SmallVectorImpl<dependency_directives_scan::Directive> &Directives,
    DiagnosticsEngine *Diags = nullptr,
    SourceLocation InputSourceLoc = SourceLocation());

/// Print the previously scanned dependency directives as minimized source text.
///
/// \param Source The original source text that the dependency directives were
/// scanned from.
/// \param Directives The previously scanned dependency
/// directives.
/// \param OS the stream to print the dependency directives on.
///
/// This is used primarily for testing purposes, during dependency scanning the
/// \p Lexer uses the tokens directly, not their printed version.
void printDependencyDirectivesAsSource(
    StringRef Source,
    ArrayRef<dependency_directives_scan::Directive> Directives,
    llvm::raw_ostream &OS);

} // end namespace clang

#endif // LLVM_CLANG_LEX_DEPENDENCYDIRECTIVESSCANNER_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif