aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/include/clang/Lex
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang16/include/clang/Lex
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang16/include/clang/Lex')
-rw-r--r--contrib/libs/clang16/include/clang/Lex/CodeCompletionHandler.h88
-rw-r--r--contrib/libs/clang16/include/clang/Lex/DependencyDirectivesScanner.h150
-rw-r--r--contrib/libs/clang16/include/clang/Lex/DirectoryLookup.h213
-rw-r--r--contrib/libs/clang16/include/clang/Lex/ExternalPreprocessorSource.h58
-rw-r--r--contrib/libs/clang16/include/clang/Lex/HeaderMap.h114
-rw-r--r--contrib/libs/clang16/include/clang/Lex/HeaderMapTypes.h53
-rw-r--r--contrib/libs/clang16/include/clang/Lex/HeaderSearch.h952
-rw-r--r--contrib/libs/clang16/include/clang/Lex/HeaderSearchOptions.h299
-rw-r--r--contrib/libs/clang16/include/clang/Lex/LexDiagnostic.h25
-rw-r--r--contrib/libs/clang16/include/clang/Lex/Lexer.h826
-rw-r--r--contrib/libs/clang16/include/clang/Lex/LiteralSupport.h308
-rw-r--r--contrib/libs/clang16/include/clang/Lex/MacroArgs.h148
-rw-r--r--contrib/libs/clang16/include/clang/Lex/MacroInfo.h644
-rw-r--r--contrib/libs/clang16/include/clang/Lex/ModuleLoader.h203
-rw-r--r--contrib/libs/clang16/include/clang/Lex/ModuleMap.h757
-rw-r--r--contrib/libs/clang16/include/clang/Lex/MultipleIncludeOpt.h191
-rw-r--r--contrib/libs/clang16/include/clang/Lex/PPCallbacks.h720
-rw-r--r--contrib/libs/clang16/include/clang/Lex/PPConditionalDirectiveRecord.h121
-rw-r--r--contrib/libs/clang16/include/clang/Lex/Pragma.h139
-rw-r--r--contrib/libs/clang16/include/clang/Lex/PreprocessingRecord.h589
-rw-r--r--contrib/libs/clang16/include/clang/Lex/Preprocessor.h2888
-rw-r--r--contrib/libs/clang16/include/clang/Lex/PreprocessorLexer.h194
-rw-r--r--contrib/libs/clang16/include/clang/Lex/PreprocessorOptions.h280
-rw-r--r--contrib/libs/clang16/include/clang/Lex/ScratchBuffer.h55
-rw-r--r--contrib/libs/clang16/include/clang/Lex/Token.h353
-rw-r--r--contrib/libs/clang16/include/clang/Lex/TokenConcatenation.h82
-rw-r--r--contrib/libs/clang16/include/clang/Lex/TokenLexer.h256
-rw-r--r--contrib/libs/clang16/include/clang/Lex/VariadicMacroSupport.h254
28 files changed, 10960 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/Lex/CodeCompletionHandler.h b/contrib/libs/clang16/include/clang/Lex/CodeCompletionHandler.h
new file mode 100644
index 0000000000..febcb96924
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/CodeCompletionHandler.h
@@ -0,0 +1,88 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- CodeCompletionHandler.h - Preprocessor code completion -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeCompletionHandler interface, which provides
+// code-completion callbacks for the preprocessor.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+#define LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+class IdentifierInfo;
+class MacroInfo;
+
+/// Callback handler that receives notifications when performing code
+/// completion within the preprocessor.
+class CodeCompletionHandler {
+public:
+ virtual ~CodeCompletionHandler();
+
+ /// Callback invoked when performing code completion for a preprocessor
+ /// directive.
+ ///
+ /// This callback will be invoked when the preprocessor processes a '#' at the
+ /// start of a line, followed by the code-completion token.
+ ///
+ /// \param InConditional Whether we're inside a preprocessor conditional
+ /// already.
+ virtual void CodeCompleteDirective(bool InConditional) { }
+
+ /// Callback invoked when performing code completion within a block of
+ /// code that was excluded due to preprocessor conditionals.
+ virtual void CodeCompleteInConditionalExclusion() { }
+
+ /// Callback invoked when performing code completion in a context
+ /// where the name of a macro is expected.
+ ///
+ /// \param IsDefinition Whether this is the definition of a macro, e.g.,
+ /// in a \#define.
+ virtual void CodeCompleteMacroName(bool IsDefinition) { }
+
+ /// Callback invoked when performing code completion in a preprocessor
+ /// expression, such as the condition of an \#if or \#elif directive.
+ virtual void CodeCompletePreprocessorExpression() { }
+
+ /// Callback invoked when performing code completion inside a
+ /// function-like macro argument.
+ ///
+ /// There will be another callback invocation after the macro arguments are
+ /// parsed, so this callback should generally be used to note that the next
+ /// callback is invoked inside a macro argument.
+ virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+ MacroInfo *MacroInfo,
+ unsigned ArgumentIndex) { }
+
+ /// Callback invoked when performing code completion inside the filename
+ /// part of an #include directive. (Also #import, #include_next, etc).
+ /// \p Dir is the directory relative to the include path.
+ virtual void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled) {}
+
+ /// Callback invoked when performing code completion in a part of the
+ /// file where we expect natural language, e.g., a comment, string, or
+ /// \#error directive.
+ virtual void CodeCompleteNaturalLanguage() { }
+};
+
+}
+
+#endif // LLVM_CLANG_LEX_CODECOMPLETIONHANDLER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/DependencyDirectivesScanner.h b/contrib/libs/clang16/include/clang/Lex/DependencyDirectivesScanner.h
new file mode 100644
index 0000000000..9ab24d499b
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/DependencyDirectivesScanner.h
@@ -0,0 +1,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
diff --git a/contrib/libs/clang16/include/clang/Lex/DirectoryLookup.h b/contrib/libs/clang16/include/clang/Lex/DirectoryLookup.h
new file mode 100644
index 0000000000..6bab6b846b
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/DirectoryLookup.h
@@ -0,0 +1,213 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- DirectoryLookup.h - Info for searching for headers -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DirectoryLookup interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+#define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ModuleMap.h"
+
+namespace clang {
+class HeaderMap;
+class HeaderSearch;
+class Module;
+
+/// DirectoryLookup - This class represents one entry in the search list that
+/// specifies the search order for directories in \#include directives. It
+/// represents either a directory, a framework, or a headermap.
+///
+class DirectoryLookup {
+public:
+ enum LookupType_t {
+ LT_NormalDir,
+ LT_Framework,
+ LT_HeaderMap
+ };
+private:
+ union DLU { // This union is discriminated by isHeaderMap.
+ /// Dir - This is the actual directory that we're referring to for a normal
+ /// directory or a framework.
+ DirectoryEntryRef Dir;
+
+ /// Map - This is the HeaderMap if this is a headermap lookup.
+ ///
+ const HeaderMap *Map;
+
+ DLU(DirectoryEntryRef Dir) : Dir(Dir) {}
+ DLU(const HeaderMap *Map) : Map(Map) {}
+ } u;
+
+ /// DirCharacteristic - The type of directory this is: this is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirCharacteristic : 3;
+
+ /// LookupType - This indicates whether this DirectoryLookup object is a
+ /// normal directory, a framework, or a headermap.
+ unsigned LookupType : 2;
+
+ /// Whether this is a header map used when building a framework.
+ unsigned IsIndexHeaderMap : 1;
+
+ /// Whether we've performed an exhaustive search for module maps
+ /// within the subdirectories of this directory.
+ unsigned SearchedAllModuleMaps : 1;
+
+public:
+ /// This ctor *does not take ownership* of 'Dir'.
+ DirectoryLookup(DirectoryEntryRef Dir, SrcMgr::CharacteristicKind DT,
+ bool isFramework)
+ : u(Dir), DirCharacteristic(DT),
+ LookupType(isFramework ? LT_Framework : LT_NormalDir),
+ IsIndexHeaderMap(false), SearchedAllModuleMaps(false) {}
+
+ /// This ctor *does not take ownership* of 'Map'.
+ DirectoryLookup(const HeaderMap *Map, SrcMgr::CharacteristicKind DT,
+ bool isIndexHeaderMap)
+ : u(Map), DirCharacteristic(DT), LookupType(LT_HeaderMap),
+ IsIndexHeaderMap(isIndexHeaderMap), SearchedAllModuleMaps(false) {}
+
+ /// getLookupType - Return the kind of directory lookup that this is: either a
+ /// normal directory, a framework path, or a HeaderMap.
+ LookupType_t getLookupType() const { return (LookupType_t)LookupType; }
+
+ /// getName - Return the directory or filename corresponding to this lookup
+ /// object.
+ StringRef getName() const;
+
+ /// getDir - Return the directory that this entry refers to.
+ ///
+ const DirectoryEntry *getDir() const {
+ return isNormalDir() ? &u.Dir.getDirEntry() : nullptr;
+ }
+
+ OptionalDirectoryEntryRef getDirRef() const {
+ return isNormalDir() ? OptionalDirectoryEntryRef(u.Dir) : std::nullopt;
+ }
+
+ /// getFrameworkDir - Return the directory that this framework refers to.
+ ///
+ const DirectoryEntry *getFrameworkDir() const {
+ return isFramework() ? &u.Dir.getDirEntry() : nullptr;
+ }
+
+ OptionalDirectoryEntryRef getFrameworkDirRef() const {
+ return isFramework() ? OptionalDirectoryEntryRef(u.Dir) : std::nullopt;
+ }
+
+ /// getHeaderMap - Return the directory that this entry refers to.
+ ///
+ const HeaderMap *getHeaderMap() const {
+ return isHeaderMap() ? u.Map : nullptr;
+ }
+
+ /// isNormalDir - Return true if this is a normal directory, not a header map.
+ bool isNormalDir() const { return getLookupType() == LT_NormalDir; }
+
+ /// isFramework - True if this is a framework directory.
+ ///
+ bool isFramework() const { return getLookupType() == LT_Framework; }
+
+ /// isHeaderMap - Return true if this is a header map, not a normal directory.
+ bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
+
+ /// Determine whether we have already searched this entire
+ /// directory for module maps.
+ bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; }
+
+ /// Specify whether we have already searched all of the subdirectories
+ /// for module maps.
+ void setSearchedAllModuleMaps(bool SAMM) {
+ SearchedAllModuleMaps = SAMM;
+ }
+
+ /// DirCharacteristic - The type of directory this is, one of the DirType enum
+ /// values.
+ SrcMgr::CharacteristicKind getDirCharacteristic() const {
+ return (SrcMgr::CharacteristicKind)DirCharacteristic;
+ }
+
+ /// Whether this describes a system header directory.
+ bool isSystemHeaderDirectory() const {
+ return getDirCharacteristic() != SrcMgr::C_User;
+ }
+
+ /// Whether this header map is building a framework or not.
+ bool isIndexHeaderMap() const {
+ return isHeaderMap() && IsIndexHeaderMap;
+ }
+
+ /// LookupFile - Lookup the specified file in this search path, returning it
+ /// if it exists or returning null if not.
+ ///
+ /// \param Filename The file to look up relative to the search paths.
+ ///
+ /// \param HS The header search instance to search with.
+ ///
+ /// \param IncludeLoc the source location of the #include or #import
+ /// directive.
+ ///
+ /// \param SearchPath If not NULL, will be set to the search path relative
+ /// to which the file was found.
+ ///
+ /// \param RelativePath If not NULL, will be set to the path relative to
+ /// SearchPath at which the file was found. This only differs from the
+ /// Filename for framework includes.
+ ///
+ /// \param RequestingModule The module in which the lookup was performed.
+ ///
+ /// \param SuggestedModule If non-null, and the file found is semantically
+ /// part of a known module, this will be set to the module that should
+ /// be imported instead of preprocessing/parsing the file found.
+ ///
+ /// \param [out] InUserSpecifiedSystemFramework If the file is found,
+ /// set to true if the file is located in a framework that has been
+ /// user-specified to be treated as a system framework.
+ ///
+ /// \param [out] IsFrameworkFound For a framework directory set to true if
+ /// specified '.framework' directory is found.
+ ///
+ /// \param [out] MappedName if this is a headermap which maps the filename to
+ /// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this
+ /// vector and point Filename to it.
+ OptionalFileEntryRef
+ LookupFile(StringRef &Filename, HeaderSearch &HS, SourceLocation IncludeLoc,
+ SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound,
+ bool &IsInHeaderMap, SmallVectorImpl<char> &MappedName,
+ bool OpenFile = true) const;
+
+private:
+ OptionalFileEntryRef DoFrameworkLookup(
+ StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const;
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/ExternalPreprocessorSource.h b/contrib/libs/clang16/include/clang/Lex/ExternalPreprocessorSource.h
new file mode 100644
index 0000000000..4c47af39ca
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/ExternalPreprocessorSource.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- ExternalPreprocessorSource.h - Abstract Macro Interface --*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalPreprocessorSource interface, which enables
+// construction of macro definitions from some external source.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H
+#define LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H
+
+namespace clang {
+
+class IdentifierInfo;
+class Module;
+
+/// Abstract interface for external sources of preprocessor
+/// information.
+///
+/// This abstract class allows an external sources (such as the \c ASTReader)
+/// to provide additional preprocessing information.
+class ExternalPreprocessorSource {
+public:
+ virtual ~ExternalPreprocessorSource();
+
+ /// Read the set of macros defined by this external macro source.
+ virtual void ReadDefinedMacros() = 0;
+
+ /// Update an out-of-date identifier.
+ virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
+
+ /// Return the identifier associated with the given ID number.
+ ///
+ /// The ID 0 is associated with the NULL identifier.
+ virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
+
+ /// Map a module ID to a module.
+ virtual Module *getModule(unsigned ModuleID) = 0;
+};
+
+}
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/HeaderMap.h b/contrib/libs/clang16/include/clang/Lex/HeaderMap.h
new file mode 100644
index 0000000000..f1c27e3ded
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/HeaderMap.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HeaderMap interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERMAP_H
+#define LLVM_CLANG_LEX_HEADERMAP_H
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/HeaderMapTypes.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
+#include <optional>
+
+namespace clang {
+
+struct HMapBucket;
+struct HMapHeader;
+
+/// Implementation for \a HeaderMap that doesn't depend on \a FileManager.
+class HeaderMapImpl {
+ std::unique_ptr<const llvm::MemoryBuffer> FileBuffer;
+ bool NeedsBSwap;
+ mutable llvm::StringMap<StringRef> ReverseMap;
+
+public:
+ HeaderMapImpl(std::unique_ptr<const llvm::MemoryBuffer> File, bool NeedsBSwap)
+ : FileBuffer(std::move(File)), NeedsBSwap(NeedsBSwap) {}
+
+ // Check for a valid header and extract the byte swap.
+ static bool checkHeader(const llvm::MemoryBuffer &File, bool &NeedsByteSwap);
+
+ // Make a call for every Key in the map.
+ template <typename Func> void forEachKey(Func Callback) const {
+ const HMapHeader &Hdr = getHeader();
+ unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
+
+ for (unsigned Bucket = 0; Bucket < NumBuckets; ++Bucket) {
+ HMapBucket B = getBucket(Bucket);
+ if (B.Key != HMAP_EmptyBucketKey)
+ if (std::optional<StringRef> Key = getString(B.Key))
+ Callback(*Key);
+ }
+ }
+
+ /// If the specified relative filename is located in this HeaderMap return
+ /// the filename it is mapped to, otherwise return an empty StringRef.
+ StringRef lookupFilename(StringRef Filename,
+ SmallVectorImpl<char> &DestPath) const;
+
+ /// Return the filename of the headermap.
+ StringRef getFileName() const;
+
+ /// Print the contents of this headermap to stderr.
+ void dump() const;
+
+ /// Return key for specifed path.
+ StringRef reverseLookupFilename(StringRef DestPath) const;
+
+private:
+ unsigned getEndianAdjustedWord(unsigned X) const;
+ const HMapHeader &getHeader() const;
+ HMapBucket getBucket(unsigned BucketNo) const;
+
+ /// Look up the specified string in the string table. If the string index is
+ /// not valid, return std::nullopt.
+ std::optional<StringRef> getString(unsigned StrTabIdx) const;
+};
+
+/// This class represents an Apple concept known as a 'header map'. To the
+/// \#include file resolution process, it basically acts like a directory of
+/// symlinks to files. Its advantages are that it is dense and more efficient
+/// to create and process than a directory of symlinks.
+class HeaderMap : private HeaderMapImpl {
+ HeaderMap(std::unique_ptr<const llvm::MemoryBuffer> File, bool BSwap)
+ : HeaderMapImpl(std::move(File), BSwap) {}
+
+public:
+ /// This attempts to load the specified file as a header map. If it doesn't
+ /// look like a HeaderMap, it gives up and returns null.
+ static std::unique_ptr<HeaderMap> Create(const FileEntry *FE,
+ FileManager &FM);
+
+ using HeaderMapImpl::dump;
+ using HeaderMapImpl::forEachKey;
+ using HeaderMapImpl::getFileName;
+ using HeaderMapImpl::lookupFilename;
+ using HeaderMapImpl::reverseLookupFilename;
+};
+
+} // end namespace clang.
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/HeaderMapTypes.h b/contrib/libs/clang16/include/clang/Lex/HeaderMapTypes.h
new file mode 100644
index 0000000000..80710d8031
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/HeaderMapTypes.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- HeaderMapTypes.h - Types for the header map format -------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERMAPTYPES_H
+#define LLVM_CLANG_LEX_HEADERMAPTYPES_H
+
+#include <cstdint>
+
+namespace clang {
+
+enum {
+ HMAP_HeaderMagicNumber = ('h' << 24) | ('m' << 16) | ('a' << 8) | 'p',
+ HMAP_HeaderVersion = 1,
+ HMAP_EmptyBucketKey = 0
+};
+
+struct HMapBucket {
+ uint32_t Key; // Offset (into strings) of key.
+ uint32_t Prefix; // Offset (into strings) of value prefix.
+ uint32_t Suffix; // Offset (into strings) of value suffix.
+};
+
+struct HMapHeader {
+ uint32_t Magic; // Magic word, also indicates byte order.
+ uint16_t Version; // Version number -- currently 1.
+ uint16_t Reserved; // Reserved for future use - zero for now.
+ uint32_t StringsOffset; // Offset to start of string pool.
+ uint32_t NumEntries; // Number of entries in the string table.
+ uint32_t NumBuckets; // Number of buckets (always a power of 2).
+ uint32_t MaxValueLength; // Length of longest result path (excluding nul).
+ // An array of 'NumBuckets' HMapBucket objects follows this header.
+ // Strings follow the buckets, at StringsOffset.
+};
+
+} // end namespace clang.
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/HeaderSearch.h b/contrib/libs/clang16/include/clang/Lex/HeaderSearch.h
new file mode 100644
index 0000000000..9806325025
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/HeaderSearch.h
@@ -0,0 +1,952 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- HeaderSearch.h - Resolve Header File Locations -----------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HeaderSearch interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
+#define LLVM_CLANG_LEX_HEADERSEARCH_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/HeaderMap.h"
+#include "clang/Lex/ModuleMap.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class Triple;
+
+} // namespace llvm
+
+namespace clang {
+
+class DiagnosticsEngine;
+class DirectoryEntry;
+class ExternalPreprocessorSource;
+class FileEntry;
+class FileManager;
+class HeaderSearch;
+class HeaderSearchOptions;
+class IdentifierInfo;
+class LangOptions;
+class Module;
+class Preprocessor;
+class TargetInfo;
+
+/// The preprocessor keeps track of this information for each
+/// file that is \#included.
+struct HeaderFileInfo {
+ // TODO: Whether the file was imported is not a property of the file itself.
+ // It's a preprocessor state, move it there.
+ /// True if this is a \#import'd file.
+ unsigned isImport : 1;
+
+ /// True if this is a \#pragma once file.
+ unsigned isPragmaOnce : 1;
+
+ /// Keep track of whether this is a system header, and if so,
+ /// whether it is C++ clean or not. This can be set by the include paths or
+ /// by \#pragma gcc system_header. This is an instance of
+ /// SrcMgr::CharacteristicKind.
+ unsigned DirInfo : 3;
+
+ /// Whether this header file info was supplied by an external source,
+ /// and has not changed since.
+ unsigned External : 1;
+
+ /// Whether this header is part of a module.
+ unsigned isModuleHeader : 1;
+
+ /// Whether this header is part of the module that we are building.
+ unsigned isCompilingModuleHeader : 1;
+
+ /// Whether this structure is considered to already have been
+ /// "resolved", meaning that it was loaded from the external source.
+ unsigned Resolved : 1;
+
+ /// Whether this is a header inside a framework that is currently
+ /// being built.
+ ///
+ /// When a framework is being built, the headers have not yet been placed
+ /// into the appropriate framework subdirectories, and therefore are
+ /// provided via a header map. This bit indicates when this is one of
+ /// those framework headers.
+ unsigned IndexHeaderMapHeader : 1;
+
+ /// Whether this file has been looked up as a header.
+ unsigned IsValid : 1;
+
+ /// The ID number of the controlling macro.
+ ///
+ /// This ID number will be non-zero when there is a controlling
+ /// macro whose IdentifierInfo may not yet have been loaded from
+ /// external storage.
+ unsigned ControllingMacroID = 0;
+
+ /// If this file has a \#ifndef XXX (or equivalent) guard that
+ /// protects the entire contents of the file, this is the identifier
+ /// for the macro that controls whether or not it has any effect.
+ ///
+ /// Note: Most clients should use getControllingMacro() to access
+ /// the controlling macro of this header, since
+ /// getControllingMacro() is able to load a controlling macro from
+ /// external storage.
+ const IdentifierInfo *ControllingMacro = nullptr;
+
+ /// If this header came from a framework include, this is the name
+ /// of the framework.
+ StringRef Framework;
+
+ HeaderFileInfo()
+ : isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
+ External(false), isModuleHeader(false), isCompilingModuleHeader(false),
+ Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
+
+ /// Retrieve the controlling macro for this header file, if
+ /// any.
+ const IdentifierInfo *
+ getControllingMacro(ExternalPreprocessorSource *External);
+};
+
+/// An external source of header file information, which may supply
+/// information about header files already included.
+class ExternalHeaderFileInfoSource {
+public:
+ virtual ~ExternalHeaderFileInfoSource();
+
+ /// Retrieve the header file information for the given file entry.
+ ///
+ /// \returns Header file information for the given file entry, with the
+ /// \c External bit set. If the file entry is not known, return a
+ /// default-constructed \c HeaderFileInfo.
+ virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
+};
+
+/// This structure is used to record entries in our framework cache.
+struct FrameworkCacheEntry {
+ /// The directory entry which should be used for the cached framework.
+ OptionalDirectoryEntryRef Directory;
+
+ /// Whether this framework has been "user-specified" to be treated as if it
+ /// were a system framework (even if it was found outside a system framework
+ /// directory).
+ bool IsUserSpecifiedSystemFramework;
+};
+
+namespace detail {
+template <bool Const, typename T>
+using Qualified = std::conditional_t<Const, const T, T>;
+
+/// Forward iterator over the search directories of \c HeaderSearch.
+template <bool IsConst>
+struct SearchDirIteratorImpl
+ : llvm::iterator_facade_base<SearchDirIteratorImpl<IsConst>,
+ std::forward_iterator_tag,
+ Qualified<IsConst, DirectoryLookup>> {
+ /// Const -> non-const iterator conversion.
+ template <typename Enable = std::enable_if<IsConst, bool>>
+ SearchDirIteratorImpl(const SearchDirIteratorImpl<false> &Other)
+ : HS(Other.HS), Idx(Other.Idx) {}
+
+ SearchDirIteratorImpl(const SearchDirIteratorImpl &) = default;
+
+ SearchDirIteratorImpl &operator=(const SearchDirIteratorImpl &) = default;
+
+ bool operator==(const SearchDirIteratorImpl &RHS) const {
+ return HS == RHS.HS && Idx == RHS.Idx;
+ }
+
+ SearchDirIteratorImpl &operator++() {
+ assert(*this && "Invalid iterator.");
+ ++Idx;
+ return *this;
+ }
+
+ Qualified<IsConst, DirectoryLookup> &operator*() const {
+ assert(*this && "Invalid iterator.");
+ return HS->SearchDirs[Idx];
+ }
+
+ /// Creates an invalid iterator.
+ SearchDirIteratorImpl(std::nullptr_t) : HS(nullptr), Idx(0) {}
+
+ /// Checks whether the iterator is valid.
+ explicit operator bool() const { return HS != nullptr; }
+
+private:
+ /// The parent \c HeaderSearch. This is \c nullptr for invalid iterator.
+ Qualified<IsConst, HeaderSearch> *HS;
+
+ /// The index of the current element.
+ size_t Idx;
+
+ /// The constructor that creates a valid iterator.
+ SearchDirIteratorImpl(Qualified<IsConst, HeaderSearch> &HS, size_t Idx)
+ : HS(&HS), Idx(Idx) {}
+
+ /// Only HeaderSearch is allowed to instantiate valid iterators.
+ friend HeaderSearch;
+
+ /// Enables const -> non-const conversion.
+ friend SearchDirIteratorImpl<!IsConst>;
+};
+} // namespace detail
+
+using ConstSearchDirIterator = detail::SearchDirIteratorImpl<true>;
+using SearchDirIterator = detail::SearchDirIteratorImpl<false>;
+
+using ConstSearchDirRange = llvm::iterator_range<ConstSearchDirIterator>;
+using SearchDirRange = llvm::iterator_range<SearchDirIterator>;
+
+/// Encapsulates the information needed to find the file referenced
+/// by a \#include or \#include_next, (sub-)framework lookup, etc.
+class HeaderSearch {
+ friend class DirectoryLookup;
+
+ friend ConstSearchDirIterator;
+ friend SearchDirIterator;
+
+ /// Header-search options used to initialize this header search.
+ std::shared_ptr<HeaderSearchOptions> HSOpts;
+
+ /// Mapping from SearchDir to HeaderSearchOptions::UserEntries indices.
+ llvm::DenseMap<unsigned, unsigned> SearchDirToHSEntry;
+
+ DiagnosticsEngine &Diags;
+ FileManager &FileMgr;
+
+ /// \#include search path information. Requests for \#include "x" search the
+ /// directory of the \#including file first, then each directory in SearchDirs
+ /// consecutively. Requests for <x> search the current dir first, then each
+ /// directory in SearchDirs, starting at AngledDirIdx, consecutively. If
+ /// NoCurDirSearch is true, then the check for the file in the current
+ /// directory is suppressed.
+ std::vector<DirectoryLookup> SearchDirs;
+ /// Whether the DirectoryLookup at the corresponding index in SearchDirs has
+ /// been successfully used to lookup a file.
+ std::vector<bool> SearchDirsUsage;
+ unsigned AngledDirIdx = 0;
+ unsigned SystemDirIdx = 0;
+ bool NoCurDirSearch = false;
+
+ /// Maps HeaderMap keys to SearchDir indices. When HeaderMaps are used
+ /// heavily, SearchDirs can start with thousands of HeaderMaps, so this Index
+ /// lets us avoid scanning them all to find a match.
+ llvm::StringMap<unsigned, llvm::BumpPtrAllocator> SearchDirHeaderMapIndex;
+
+ /// The index of the first SearchDir that isn't a header map.
+ unsigned FirstNonHeaderMapSearchDirIdx = 0;
+
+ /// \#include prefixes for which the 'system header' property is
+ /// overridden.
+ ///
+ /// For a \#include "x" or \#include \<x> directive, the last string in this
+ /// list which is a prefix of 'x' determines whether the file is treated as
+ /// a system header.
+ std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes;
+
+ /// The hash used for module cache paths.
+ std::string ModuleHash;
+
+ /// The path to the module cache.
+ std::string ModuleCachePath;
+
+ /// All of the preprocessor-specific data about files that are
+ /// included, indexed by the FileEntry's UID.
+ mutable std::vector<HeaderFileInfo> FileInfo;
+
+ /// Keeps track of each lookup performed by LookupFile.
+ struct LookupFileCacheInfo {
+ /// Starting search directory iterator that the cached search was performed
+ /// from. If there is a hit and this value doesn't match the current query,
+ /// the cache has to be ignored.
+ ConstSearchDirIterator StartIt = nullptr;
+
+ /// The search directory iterator that satisfied the query.
+ ConstSearchDirIterator HitIt = nullptr;
+
+ /// This is non-null if the original filename was mapped to a framework
+ /// include via a headermap.
+ const char *MappedName = nullptr;
+
+ /// Default constructor -- Initialize all members with zero.
+ LookupFileCacheInfo() = default;
+
+ void reset(ConstSearchDirIterator NewStartIt) {
+ StartIt = NewStartIt;
+ MappedName = nullptr;
+ }
+ };
+ llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache;
+
+ /// Collection mapping a framework or subframework
+ /// name like "Carbon" to the Carbon.framework directory.
+ llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap;
+
+ /// Maps include file names (including the quotes or
+ /// angle brackets) to other include file names. This is used to support the
+ /// include_alias pragma for Microsoft compatibility.
+ using IncludeAliasMap =
+ llvm::StringMap<std::string, llvm::BumpPtrAllocator>;
+ std::unique_ptr<IncludeAliasMap> IncludeAliases;
+
+ /// This is a mapping from FileEntry -> HeaderMap, uniquing headermaps.
+ std::vector<std::pair<const FileEntry *, std::unique_ptr<HeaderMap>>> HeaderMaps;
+
+ /// The mapping between modules and headers.
+ mutable ModuleMap ModMap;
+
+ /// Describes whether a given directory has a module map in it.
+ llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap;
+
+ /// Set of module map files we've already loaded, and a flag indicating
+ /// whether they were valid or not.
+ llvm::DenseMap<const FileEntry *, bool> LoadedModuleMaps;
+
+ // A map of discovered headers with their associated include file name.
+ llvm::DenseMap<const FileEntry *, llvm::SmallString<64>> IncludeNames;
+
+ /// Uniqued set of framework names, which is used to track which
+ /// headers were included as framework headers.
+ llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
+
+ /// Entity used to resolve the identifier IDs of controlling
+ /// macros into IdentifierInfo pointers, and keep the identifire up to date,
+ /// as needed.
+ ExternalPreprocessorSource *ExternalLookup = nullptr;
+
+ /// Entity used to look up stored header file information.
+ ExternalHeaderFileInfoSource *ExternalSource = nullptr;
+
+ /// Scan all of the header maps at the beginning of SearchDirs and
+ /// map their keys to the SearchDir index of their header map.
+ void indexInitialHeaderMaps();
+
+public:
+ HeaderSearch(std::shared_ptr<HeaderSearchOptions> HSOpts,
+ SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const TargetInfo *Target);
+ HeaderSearch(const HeaderSearch &) = delete;
+ HeaderSearch &operator=(const HeaderSearch &) = delete;
+
+ /// Retrieve the header-search options with which this header search
+ /// was initialized.
+ HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; }
+
+ FileManager &getFileMgr() const { return FileMgr; }
+
+ DiagnosticsEngine &getDiags() const { return Diags; }
+
+ /// Interface for setting the file search paths.
+ void SetSearchPaths(std::vector<DirectoryLookup> dirs, unsigned angledDirIdx,
+ unsigned systemDirIdx, bool noCurDirSearch,
+ llvm::DenseMap<unsigned, unsigned> searchDirToHSEntry);
+
+ /// Add an additional search path.
+ void AddSearchPath(const DirectoryLookup &dir, bool isAngled);
+
+ /// Add an additional system search path.
+ void AddSystemSearchPath(const DirectoryLookup &dir) {
+ SearchDirs.push_back(dir);
+ SearchDirsUsage.push_back(false);
+ }
+
+ /// Set the list of system header prefixes.
+ void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) {
+ SystemHeaderPrefixes.assign(P.begin(), P.end());
+ }
+
+ /// Checks whether the map exists or not.
+ bool HasIncludeAliasMap() const { return (bool)IncludeAliases; }
+
+ /// Map the source include name to the dest include name.
+ ///
+ /// The Source should include the angle brackets or quotes, the dest
+ /// should not. This allows for distinction between <> and "" headers.
+ void AddIncludeAlias(StringRef Source, StringRef Dest) {
+ if (!IncludeAliases)
+ IncludeAliases.reset(new IncludeAliasMap);
+ (*IncludeAliases)[Source] = std::string(Dest);
+ }
+
+ /// Maps one header file name to a different header
+ /// file name, for use with the include_alias pragma. Note that the source
+ /// file name should include the angle brackets or quotes. Returns StringRef
+ /// as null if the header cannot be mapped.
+ StringRef MapHeaderToIncludeAlias(StringRef Source) {
+ assert(IncludeAliases && "Trying to map headers when there's no map");
+
+ // Do any filename replacements before anything else
+ IncludeAliasMap::const_iterator Iter = IncludeAliases->find(Source);
+ if (Iter != IncludeAliases->end())
+ return Iter->second;
+ return {};
+ }
+
+ /// Set the hash to use for module cache paths.
+ void setModuleHash(StringRef Hash) { ModuleHash = std::string(Hash); }
+
+ /// Set the path to the module cache.
+ void setModuleCachePath(StringRef CachePath) {
+ ModuleCachePath = std::string(CachePath);
+ }
+
+ /// Retrieve the module hash.
+ StringRef getModuleHash() const { return ModuleHash; }
+
+ /// Retrieve the path to the module cache.
+ StringRef getModuleCachePath() const { return ModuleCachePath; }
+
+ /// Consider modules when including files from this directory.
+ void setDirectoryHasModuleMap(const DirectoryEntry* Dir) {
+ DirectoryHasModuleMap[Dir] = true;
+ }
+
+ /// Forget everything we know about headers so far.
+ void ClearFileInfo() {
+ FileInfo.clear();
+ }
+
+ void SetExternalLookup(ExternalPreprocessorSource *EPS) {
+ ExternalLookup = EPS;
+ }
+
+ ExternalPreprocessorSource *getExternalLookup() const {
+ return ExternalLookup;
+ }
+
+ /// Set the external source of header information.
+ void SetExternalSource(ExternalHeaderFileInfoSource *ES) {
+ ExternalSource = ES;
+ }
+
+ /// Set the target information for the header search, if not
+ /// already known.
+ void setTarget(const TargetInfo &Target);
+
+ /// Given a "foo" or \<foo> reference, look up the indicated file,
+ /// return null on failure.
+ ///
+ /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member
+ /// the file was found in, or null if not applicable.
+ ///
+ /// \param IncludeLoc Used for diagnostics if valid.
+ ///
+ /// \param isAngled indicates whether the file reference is a <> reference.
+ ///
+ /// \param CurDir If non-null, the file was found in the specified directory
+ /// search location. This is used to implement \#include_next.
+ ///
+ /// \param Includers Indicates where the \#including file(s) are, in case
+ /// relative searches are needed. In reverse order of inclusion.
+ ///
+ /// \param SearchPath If non-null, will be set to the search path relative
+ /// to which the file was found. If the include path is absolute, SearchPath
+ /// will be set to an empty string.
+ ///
+ /// \param RelativePath If non-null, will be set to the path relative to
+ /// SearchPath at which the file was found. This only differs from the
+ /// Filename for framework includes.
+ ///
+ /// \param SuggestedModule If non-null, and the file found is semantically
+ /// part of a known module, this will be set to the module that should
+ /// be imported instead of preprocessing/parsing the file found.
+ ///
+ /// \param IsMapped If non-null, and the search involved header maps, set to
+ /// true.
+ ///
+ /// \param IsFrameworkFound If non-null, will be set to true if a framework is
+ /// found in any of searched SearchDirs. Will be set to false if a framework
+ /// is found only through header maps. Doesn't guarantee the requested file is
+ /// found.
+ OptionalFileEntryRef LookupFile(
+ StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
+ ConstSearchDirIterator FromDir, ConstSearchDirIterator *CurDir,
+ ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
+ SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
+ bool *IsMapped, bool *IsFrameworkFound, bool SkipCache = false,
+ bool BuildSystemModule = false, bool OpenFile = true,
+ bool CacheFailures = true);
+
+ /// Look up a subframework for the specified \#include file.
+ ///
+ /// For example, if \#include'ing <HIToolbox/HIToolbox.h> from
+ /// within ".../Carbon.framework/Headers/Carbon.h", check to see if
+ /// HIToolbox is a subframework within Carbon.framework. If so, return
+ /// the FileEntry for the designated file, otherwise return null.
+ OptionalFileEntryRef LookupSubframeworkHeader(
+ StringRef Filename, const FileEntry *ContextFileEnt,
+ SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+ Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule);
+
+ /// Look up the specified framework name in our framework cache.
+ /// \returns The DirectoryEntry it is in if we know, null otherwise.
+ FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) {
+ return FrameworkMap[FWName];
+ }
+
+ /// Mark the specified file as a target of a \#include,
+ /// \#include_next, or \#import directive.
+ ///
+ /// \return false if \#including the file will have no effect or true
+ /// if we should include it.
+ bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File,
+ bool isImport, bool ModulesEnabled, Module *M,
+ bool &IsFirstIncludeOfFile);
+
+ /// Return whether the specified file is a normal header,
+ /// a system header, or a C++ friendly system header.
+ SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) {
+ return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo;
+ }
+
+ /// Mark the specified file as a "once only" file due to
+ /// \#pragma once.
+ void MarkFileIncludeOnce(const FileEntry *File) {
+ HeaderFileInfo &FI = getFileInfo(File);
+ FI.isPragmaOnce = true;
+ }
+
+ /// Mark the specified file as a system header, e.g. due to
+ /// \#pragma GCC system_header.
+ void MarkFileSystemHeader(const FileEntry *File) {
+ getFileInfo(File).DirInfo = SrcMgr::C_System;
+ }
+
+ /// Mark the specified file as part of a module.
+ void MarkFileModuleHeader(const FileEntry *FE,
+ ModuleMap::ModuleHeaderRole Role,
+ bool isCompilingModuleHeader);
+
+ /// Mark the specified file as having a controlling macro.
+ ///
+ /// This is used by the multiple-include optimization to eliminate
+ /// no-op \#includes.
+ void SetFileControllingMacro(const FileEntry *File,
+ const IdentifierInfo *ControllingMacro) {
+ getFileInfo(File).ControllingMacro = ControllingMacro;
+ }
+
+ /// Determine whether this file is intended to be safe from
+ /// multiple inclusions, e.g., it has \#pragma once or a controlling
+ /// macro.
+ ///
+ /// This routine does not consider the effect of \#import
+ bool isFileMultipleIncludeGuarded(const FileEntry *File);
+
+ /// Determine whether the given file is known to have ever been \#imported.
+ bool hasFileBeenImported(const FileEntry *File) {
+ const HeaderFileInfo *FI = getExistingFileInfo(File);
+ return FI && FI->isImport;
+ }
+
+ /// Determine which HeaderSearchOptions::UserEntries have been successfully
+ /// used so far and mark their index with 'true' in the resulting bit vector.
+ /// Note: implicit module maps don't contribute to entry usage.
+ std::vector<bool> computeUserEntryUsage() const;
+
+ /// This method returns a HeaderMap for the specified
+ /// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
+ const HeaderMap *CreateHeaderMap(const FileEntry *FE);
+
+ /// Get filenames for all registered header maps.
+ void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const;
+
+ /// Retrieve the name of the cached module file that should be used
+ /// to load the given module.
+ ///
+ /// \param Module The module whose module file name will be returned.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getCachedModuleFileName(Module *Module);
+
+ /// Retrieve the name of the prebuilt module file that should be used
+ /// to load a module with the given name.
+ ///
+ /// \param ModuleName The module whose module file name will be returned.
+ ///
+ /// \param FileMapOnly If true, then only look in the explicit module name
+ // to file name map and skip the directory search.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getPrebuiltModuleFileName(StringRef ModuleName,
+ bool FileMapOnly = false);
+
+ /// Retrieve the name of the prebuilt module file that should be used
+ /// to load the given module.
+ ///
+ /// \param Module The module whose module file name will be returned.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getPrebuiltImplicitModuleFileName(Module *Module);
+
+ /// Retrieve the name of the (to-be-)cached module file that should
+ /// be used to load a module with the given name.
+ ///
+ /// \param ModuleName The module whose module file name will be returned.
+ ///
+ /// \param ModuleMapPath A path that when combined with \c ModuleName
+ /// uniquely identifies this module. See Module::ModuleMap.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getCachedModuleFileName(StringRef ModuleName,
+ StringRef ModuleMapPath);
+
+ /// Lookup a module Search for a module with the given name.
+ ///
+ /// \param ModuleName The name of the module we're looking for.
+ ///
+ /// \param ImportLoc Location of the module include/import.
+ ///
+ /// \param AllowSearch Whether we are allowed to search in the various
+ /// search directories to produce a module definition. If not, this lookup
+ /// will only return an already-known module.
+ ///
+ /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
+ /// in subdirectories.
+ ///
+ /// \returns The module with the given name.
+ Module *lookupModule(StringRef ModuleName,
+ SourceLocation ImportLoc = SourceLocation(),
+ bool AllowSearch = true,
+ bool AllowExtraModuleMapSearch = false);
+
+ /// Try to find a module map file in the given directory, returning
+ /// \c nullptr if none is found.
+ const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir,
+ bool IsFramework);
+
+ /// Determine whether there is a module map that may map the header
+ /// with the given file name to a (sub)module.
+ /// Always returns false if modules are disabled.
+ ///
+ /// \param Filename The name of the file.
+ ///
+ /// \param Root The "root" directory, at which we should stop looking for
+ /// module maps.
+ ///
+ /// \param IsSystem Whether the directories we're looking at are system
+ /// header directories.
+ bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root,
+ bool IsSystem);
+
+ /// Retrieve the module that corresponds to the given file, if any.
+ ///
+ /// \param File The header that we wish to map to a module.
+ /// \param AllowTextual Whether we want to find textual headers too.
+ ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File,
+ bool AllowTextual = false,
+ bool AllowExcluded = false) const;
+
+ /// Retrieve all the modules corresponding to the given file.
+ ///
+ /// \ref findModuleForHeader should typically be used instead of this.
+ ArrayRef<ModuleMap::KnownHeader>
+ findAllModulesForHeader(const FileEntry *File) const;
+
+ /// Read the contents of the given module map file.
+ ///
+ /// \param File The module map file.
+ /// \param IsSystem Whether this file is in a system header directory.
+ /// \param ID If the module map file is already mapped (perhaps as part of
+ /// processing a preprocessed module), the ID of the file.
+ /// \param Offset [inout] An offset within ID to start parsing. On exit,
+ /// filled by the end of the parsed contents (either EOF or the
+ /// location of an end-of-module-map pragma).
+ /// \param OriginalModuleMapFile The original path to the module map file,
+ /// used to resolve paths within the module (this is required when
+ /// building the module from preprocessed source).
+ /// \returns true if an error occurred, false otherwise.
+ bool loadModuleMapFile(const FileEntry *File, bool IsSystem,
+ FileID ID = FileID(), unsigned *Offset = nullptr,
+ StringRef OriginalModuleMapFile = StringRef());
+
+ /// Collect the set of all known, top-level modules.
+ ///
+ /// \param Modules Will be filled with the set of known, top-level modules.
+ void collectAllModules(SmallVectorImpl<Module *> &Modules);
+
+ /// Load all known, top-level system modules.
+ void loadTopLevelSystemModules();
+
+private:
+ /// Lookup a module with the given module name and search-name.
+ ///
+ /// \param ModuleName The name of the module we're looking for.
+ ///
+ /// \param SearchName The "search-name" to derive filesystem paths from
+ /// when looking for the module map; this is usually equal to ModuleName,
+ /// but for compatibility with some buggy frameworks, additional attempts
+ /// may be made to find the module under a related-but-different search-name.
+ ///
+ /// \param ImportLoc Location of the module include/import.
+ ///
+ /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps
+ /// in subdirectories.
+ ///
+ /// \returns The module named ModuleName.
+ Module *lookupModule(StringRef ModuleName, StringRef SearchName,
+ SourceLocation ImportLoc,
+ bool AllowExtraModuleMapSearch = false);
+
+ /// Retrieve the name of the (to-be-)cached module file that should
+ /// be used to load a module with the given name.
+ ///
+ /// \param ModuleName The module whose module file name will be returned.
+ ///
+ /// \param ModuleMapPath A path that when combined with \c ModuleName
+ /// uniquely identifies this module. See Module::ModuleMap.
+ ///
+ /// \param CachePath A path to the module cache.
+ ///
+ /// \returns The name of the module file that corresponds to this module,
+ /// or an empty string if this module does not correspond to any module file.
+ std::string getCachedModuleFileNameImpl(StringRef ModuleName,
+ StringRef ModuleMapPath,
+ StringRef CachePath);
+
+ /// Retrieve a module with the given name, which may be part of the
+ /// given framework.
+ ///
+ /// \param Name The name of the module to retrieve.
+ ///
+ /// \param Dir The framework directory (e.g., ModuleName.framework).
+ ///
+ /// \param IsSystem Whether the framework directory is part of the system
+ /// frameworks.
+ ///
+ /// \returns The module, if found; otherwise, null.
+ Module *loadFrameworkModule(StringRef Name, DirectoryEntryRef Dir,
+ bool IsSystem);
+
+ /// Load all of the module maps within the immediate subdirectories
+ /// of the given search directory.
+ void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir);
+
+ /// Find and suggest a usable module for the given file.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForHeader(const FileEntry *File,
+ const DirectoryEntry *Root,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool IsSystemHeaderDir);
+
+ /// Find and suggest a usable module for the given file, which is part of
+ /// the specified framework.
+ ///
+ /// \return \c true if the file can be used, \c false if we are not permitted to
+ /// find this file due to requirements from \p RequestingModule.
+ bool findUsableModuleForFrameworkHeader(
+ const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework);
+
+ /// Look up the file with the specified name and determine its owning
+ /// module.
+ OptionalFileEntryRef
+ getFileAndSuggestModule(StringRef FileName, SourceLocation IncludeLoc,
+ const DirectoryEntry *Dir, bool IsSystemHeaderDir,
+ Module *RequestingModule,
+ ModuleMap::KnownHeader *SuggestedModule,
+ bool OpenFile = true, bool CacheFailures = true);
+
+ /// Cache the result of a successful lookup at the given include location
+ /// using the search path at \c HitIt.
+ void cacheLookupSuccess(LookupFileCacheInfo &CacheLookup,
+ ConstSearchDirIterator HitIt,
+ SourceLocation IncludeLoc);
+
+ /// Note that a lookup at the given include location was successful using the
+ /// search path at index `HitIdx`.
+ void noteLookupUsage(unsigned HitIdx, SourceLocation IncludeLoc);
+
+public:
+ /// Retrieve the module map.
+ ModuleMap &getModuleMap() { return ModMap; }
+
+ /// Retrieve the module map.
+ const ModuleMap &getModuleMap() const { return ModMap; }
+
+ unsigned header_file_size() const { return FileInfo.size(); }
+
+ /// Return the HeaderFileInfo structure for the specified FileEntry,
+ /// in preparation for updating it in some way.
+ HeaderFileInfo &getFileInfo(const FileEntry *FE);
+
+ /// Return the HeaderFileInfo structure for the specified FileEntry,
+ /// if it has ever been filled in.
+ /// \param WantExternal Whether the caller wants purely-external header file
+ /// info (where \p External is true).
+ const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal = true) const;
+
+ SearchDirIterator search_dir_begin() { return {*this, 0}; }
+ SearchDirIterator search_dir_end() { return {*this, SearchDirs.size()}; }
+ SearchDirRange search_dir_range() {
+ return {search_dir_begin(), search_dir_end()};
+ }
+
+ ConstSearchDirIterator search_dir_begin() const { return quoted_dir_begin(); }
+ ConstSearchDirIterator search_dir_nth(size_t n) const {
+ assert(n < SearchDirs.size());
+ return {*this, n};
+ }
+ ConstSearchDirIterator search_dir_end() const { return system_dir_end(); }
+ ConstSearchDirRange search_dir_range() const {
+ return {search_dir_begin(), search_dir_end()};
+ }
+
+ unsigned search_dir_size() const { return SearchDirs.size(); }
+
+ ConstSearchDirIterator quoted_dir_begin() const { return {*this, 0}; }
+ ConstSearchDirIterator quoted_dir_end() const { return angled_dir_begin(); }
+
+ ConstSearchDirIterator angled_dir_begin() const {
+ return {*this, AngledDirIdx};
+ }
+ ConstSearchDirIterator angled_dir_end() const { return system_dir_begin(); }
+
+ ConstSearchDirIterator system_dir_begin() const {
+ return {*this, SystemDirIdx};
+ }
+ ConstSearchDirIterator system_dir_end() const {
+ return {*this, SearchDirs.size()};
+ }
+
+ /// Get the index of the given search directory.
+ unsigned searchDirIdx(const DirectoryLookup &DL) const;
+
+ /// Retrieve a uniqued framework name.
+ StringRef getUniqueFrameworkName(StringRef Framework);
+
+ /// Retrieve the include name for the header.
+ ///
+ /// \param File The entry for a given header.
+ /// \returns The name of how the file was included when the header's location
+ /// was resolved.
+ StringRef getIncludeNameForHeader(const FileEntry *File) const;
+
+ /// Suggest a path by which the specified file could be found, for use in
+ /// diagnostics to suggest a #include. Returned path will only contain forward
+ /// slashes as separators. MainFile is the absolute path of the file that we
+ /// are generating the diagnostics for. It will try to shorten the path using
+ /// MainFile location, if none of the include search directories were prefix
+ /// of File.
+ ///
+ /// \param IsSystem If non-null, filled in to indicate whether the suggested
+ /// path is relative to a system header directory.
+ std::string suggestPathToFileForDiagnostics(const FileEntry *File,
+ llvm::StringRef MainFile,
+ bool *IsSystem = nullptr);
+
+ /// Suggest a path by which the specified file could be found, for use in
+ /// diagnostics to suggest a #include. Returned path will only contain forward
+ /// slashes as separators. MainFile is the absolute path of the file that we
+ /// are generating the diagnostics for. It will try to shorten the path using
+ /// MainFile location, if none of the include search directories were prefix
+ /// of File.
+ ///
+ /// \param WorkingDir If non-empty, this will be prepended to search directory
+ /// paths that are relative.
+ std::string suggestPathToFileForDiagnostics(llvm::StringRef File,
+ llvm::StringRef WorkingDir,
+ llvm::StringRef MainFile,
+ bool *IsSystem = nullptr);
+
+ void PrintStats();
+
+ size_t getTotalMemory() const;
+
+private:
+ /// Describes what happened when we tried to load a module map file.
+ enum LoadModuleMapResult {
+ /// The module map file had already been loaded.
+ LMM_AlreadyLoaded,
+
+ /// The module map file was loaded by this invocation.
+ LMM_NewlyLoaded,
+
+ /// There is was directory with the given name.
+ LMM_NoDirectory,
+
+ /// There was either no module map file or the module map file was
+ /// invalid.
+ LMM_InvalidModuleMap
+ };
+
+ LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File,
+ bool IsSystem,
+ DirectoryEntryRef Dir,
+ FileID ID = FileID(),
+ unsigned *Offset = nullptr);
+
+ /// Try to load the module map file in the given directory.
+ ///
+ /// \param DirName The name of the directory where we will look for a module
+ /// map file.
+ /// \param IsSystem Whether this is a system header directory.
+ /// \param IsFramework Whether this is a framework directory.
+ ///
+ /// \returns The result of attempting to load the module map file from the
+ /// named directory.
+ LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem,
+ bool IsFramework);
+
+ /// Try to load the module map file in the given directory.
+ ///
+ /// \param Dir The directory where we will look for a module map file.
+ /// \param IsSystem Whether this is a system header directory.
+ /// \param IsFramework Whether this is a framework directory.
+ ///
+ /// \returns The result of attempting to load the module map file from the
+ /// named directory.
+ LoadModuleMapResult loadModuleMapFile(DirectoryEntryRef Dir, bool IsSystem,
+ bool IsFramework);
+};
+
+/// Apply the header search options to get given HeaderSearch object.
+void ApplyHeaderSearchOptions(HeaderSearch &HS,
+ const HeaderSearchOptions &HSOpts,
+ const LangOptions &Lang,
+ const llvm::Triple &triple);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_HEADERSEARCH_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/HeaderSearchOptions.h b/contrib/libs/clang16/include/clang/Lex/HeaderSearchOptions.h
new file mode 100644
index 0000000000..6103349f72
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/HeaderSearchOptions.h
@@ -0,0 +1,299 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- HeaderSearchOptions.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
+#define LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/HashBuilder.h"
+#include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace clang {
+
+namespace frontend {
+
+/// IncludeDirGroup - Identifies the group an include Entry belongs to,
+/// representing its relative positive in the search list.
+/// \#include directives whose paths are enclosed by string quotes ("")
+/// start searching at the Quoted group (specified by '-iquote'),
+/// then search the Angled group, then the System group, etc.
+enum IncludeDirGroup {
+ /// '\#include ""' paths, added by 'gcc -iquote'.
+ Quoted = 0,
+
+ /// Paths for '\#include <>' added by '-I'.
+ Angled,
+
+ /// Like Angled, but marks header maps used when building frameworks.
+ IndexHeaderMap,
+
+ /// Like Angled, but marks system directories.
+ System,
+
+ /// Like System, but headers are implicitly wrapped in extern "C".
+ ExternCSystem,
+
+ /// Like System, but only used for C.
+ CSystem,
+
+ /// Like System, but only used for C++.
+ CXXSystem,
+
+ /// Like System, but only used for ObjC.
+ ObjCSystem,
+
+ /// Like System, but only used for ObjC++.
+ ObjCXXSystem,
+
+ /// Like System, but searched after the system directories.
+ After
+};
+
+} // namespace frontend
+
+/// HeaderSearchOptions - Helper class for storing options related to the
+/// initialization of the HeaderSearch object.
+class HeaderSearchOptions {
+public:
+ struct Entry {
+ std::string Path;
+ frontend::IncludeDirGroup Group;
+ unsigned IsFramework : 1;
+
+ /// IgnoreSysRoot - This is false if an absolute path should be treated
+ /// relative to the sysroot, or true if it should always be the absolute
+ /// path.
+ unsigned IgnoreSysRoot : 1;
+
+ Entry(StringRef path, frontend::IncludeDirGroup group, bool isFramework,
+ bool ignoreSysRoot)
+ : Path(path), Group(group), IsFramework(isFramework),
+ IgnoreSysRoot(ignoreSysRoot) {}
+ };
+
+ struct SystemHeaderPrefix {
+ /// A prefix to be matched against paths in \#include directives.
+ std::string Prefix;
+
+ /// True if paths beginning with this prefix should be treated as system
+ /// headers.
+ bool IsSystemHeader;
+
+ SystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader)
+ : Prefix(Prefix), IsSystemHeader(IsSystemHeader) {}
+ };
+
+ /// If non-empty, the directory to use as a "virtual system root" for include
+ /// paths.
+ std::string Sysroot;
+
+ /// User specified include entries.
+ std::vector<Entry> UserEntries;
+
+ /// User-specified system header prefixes.
+ std::vector<SystemHeaderPrefix> SystemHeaderPrefixes;
+
+ /// The directory which holds the compiler resource files (builtin includes,
+ /// etc.).
+ std::string ResourceDir;
+
+ /// The directory used for the module cache.
+ std::string ModuleCachePath;
+
+ /// The directory used for a user build.
+ std::string ModuleUserBuildPath;
+
+ /// The mapping of module names to prebuilt module files.
+ std::map<std::string, std::string, std::less<>> PrebuiltModuleFiles;
+
+ /// The directories used to load prebuilt module files.
+ std::vector<std::string> PrebuiltModulePaths;
+
+ /// The module/pch container format.
+ std::string ModuleFormat;
+
+ /// Whether we should disable the use of the hash string within the
+ /// module cache.
+ ///
+ /// Note: Only used for testing!
+ unsigned DisableModuleHash : 1;
+
+ /// Implicit module maps. This option is enabld by default when
+ /// modules is enabled.
+ unsigned ImplicitModuleMaps : 1;
+
+ /// Set the 'home directory' of a module map file to the current
+ /// working directory (or the home directory of the module map file that
+ /// contained the 'extern module' directive importing this module map file
+ /// if any) rather than the directory containing the module map file.
+ //
+ /// The home directory is where we look for files named in the module map
+ /// file.
+ unsigned ModuleMapFileHomeIsCwd : 1;
+
+ /// Set the base path of a built module file to be the current working
+ /// directory. This is useful for sharing module files across machines
+ /// that build with different paths without having to rewrite all
+ /// modulemap files to have working directory relative paths.
+ unsigned ModuleFileHomeIsCwd : 1;
+
+ /// Also search for prebuilt implicit modules in the prebuilt module cache
+ /// path.
+ unsigned EnablePrebuiltImplicitModules : 1;
+
+ /// The interval (in seconds) between pruning operations.
+ ///
+ /// This operation is expensive, because it requires Clang to walk through
+ /// the directory structure of the module cache, stat()'ing and removing
+ /// files.
+ ///
+ /// The default value is large, e.g., the operation runs once a week.
+ unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60;
+
+ /// The time (in seconds) after which an unused module file will be
+ /// considered unused and will, therefore, be pruned.
+ ///
+ /// When the module cache is pruned, any module file that has not been
+ /// accessed in this many seconds will be removed. The default value is
+ /// large, e.g., a month, to avoid forcing infrequently-used modules to be
+ /// regenerated often.
+ unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60;
+
+ /// The time in seconds when the build session started.
+ ///
+ /// This time is used by other optimizations in header search and module
+ /// loading.
+ uint64_t BuildSessionTimestamp = 0;
+
+ /// The set of macro names that should be ignored for the purposes
+ /// of computing the module hash.
+ llvm::SmallSetVector<llvm::CachedHashString, 16> ModulesIgnoreMacros;
+
+ /// The set of user-provided virtual filesystem overlay files.
+ std::vector<std::string> VFSOverlayFiles;
+
+ /// Include the compiler builtin includes.
+ unsigned UseBuiltinIncludes : 1;
+
+ /// Include the system standard include search directories.
+ unsigned UseStandardSystemIncludes : 1;
+
+ /// Include the system standard C++ library include search directories.
+ unsigned UseStandardCXXIncludes : 1;
+
+ /// Use libc++ instead of the default libstdc++.
+ unsigned UseLibcxx : 1;
+
+ /// Whether header search information should be output as for -v.
+ unsigned Verbose : 1;
+
+ /// Whether header search should be case-insensitive.
+ unsigned CaseInsensitive : 1;
+
+ /// If true, skip verifying input files used by modules if the
+ /// module was already verified during this build session (see
+ /// \c BuildSessionTimestamp).
+ unsigned ModulesValidateOncePerBuildSession : 1;
+
+ /// Whether to validate system input files when a module is loaded.
+ unsigned ModulesValidateSystemHeaders : 1;
+
+ // Whether the content of input files should be hashed and used to
+ // validate consistency.
+ unsigned ValidateASTInputFilesContent : 1;
+
+ /// Whether the module includes debug information (-gmodules).
+ unsigned UseDebugInfo : 1;
+
+ unsigned ModulesValidateDiagnosticOptions : 1;
+
+ unsigned ModulesHashContent : 1;
+
+ /// Whether we should include all things that could impact the module in the
+ /// hash.
+ ///
+ /// This includes things like the full header search path, and enabled
+ /// diagnostics.
+ unsigned ModulesStrictContextHash : 1;
+
+ HeaderSearchOptions(StringRef _Sysroot = "/")
+ : Sysroot(_Sysroot), ModuleFormat("raw"), DisableModuleHash(false),
+ ImplicitModuleMaps(false), ModuleMapFileHomeIsCwd(false),
+ ModuleFileHomeIsCwd(false), EnablePrebuiltImplicitModules(false),
+ UseBuiltinIncludes(true), UseStandardSystemIncludes(true),
+ UseStandardCXXIncludes(true), UseLibcxx(false), Verbose(false), CaseInsensitive(false),
+ ModulesValidateOncePerBuildSession(false),
+ ModulesValidateSystemHeaders(false),
+ ValidateASTInputFilesContent(false), UseDebugInfo(false),
+ ModulesValidateDiagnosticOptions(true), ModulesHashContent(false),
+ ModulesStrictContextHash(false) {}
+
+ /// AddPath - Add the \p Path path to the specified \p Group list.
+ void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
+ bool IsFramework, bool IgnoreSysRoot) {
+ UserEntries.emplace_back(Path, Group, IsFramework, IgnoreSysRoot);
+ }
+
+ /// AddSystemHeaderPrefix - Override whether \#include directives naming a
+ /// path starting with \p Prefix should be considered as naming a system
+ /// header.
+ void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
+ SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
+ }
+
+ void AddVFSOverlayFile(StringRef Name) {
+ VFSOverlayFiles.push_back(std::string(Name));
+ }
+
+ void AddPrebuiltModulePath(StringRef Name) {
+ PrebuiltModulePaths.push_back(std::string(Name));
+ }
+};
+
+inline llvm::hash_code hash_value(const HeaderSearchOptions::Entry &E) {
+ return llvm::hash_combine(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
+}
+
+template <typename HasherT, llvm::support::endianness Endianness>
+inline void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
+ const HeaderSearchOptions::Entry &E) {
+ HBuilder.add(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
+}
+
+inline llvm::hash_code
+hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
+ return llvm::hash_combine(SHP.Prefix, SHP.IsSystemHeader);
+}
+
+template <typename HasherT, llvm::support::endianness Endianness>
+inline void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
+ const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
+ HBuilder.add(SHP.Prefix, SHP.IsSystemHeader);
+}
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_HEADERSEARCHOPTIONS_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/LexDiagnostic.h b/contrib/libs/clang16/include/clang/Lex/LexDiagnostic.h
new file mode 100644
index 0000000000..3c34d317e8
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/LexDiagnostic.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- DiagnosticLex.h - Diagnostics for liblex ---------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_LEXDIAGNOSTIC_H
+#define LLVM_CLANG_LEX_LEXDIAGNOSTIC_H
+
+#include "clang/Basic/DiagnosticLex.h"
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/Lexer.h b/contrib/libs/clang16/include/clang/Lex/Lexer.h
new file mode 100644
index 0000000000..3cab47f9d3
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/Lexer.h
@@ -0,0 +1,826 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Lexer.h - C Language Family Lexer ------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Lexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_LEXER_H
+#define LLVM_CLANG_LEX_LEXER_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/DependencyDirectivesScanner.h"
+#include "clang/Lex/PreprocessorLexer.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+#include <cstdint>
+#include <optional>
+#include <string>
+
+namespace llvm {
+
+class MemoryBufferRef;
+
+} // namespace llvm
+
+namespace clang {
+
+class DiagnosticBuilder;
+class Preprocessor;
+class SourceManager;
+class LangOptions;
+
+/// ConflictMarkerKind - Kinds of conflict marker which the lexer might be
+/// recovering from.
+enum ConflictMarkerKind {
+ /// Not within a conflict marker.
+ CMK_None,
+
+ /// A normal or diff3 conflict marker, initiated by at least 7 "<"s,
+ /// separated by at least 7 "="s or "|"s, and terminated by at least 7 ">"s.
+ CMK_Normal,
+
+ /// A Perforce-style conflict marker, initiated by 4 ">"s,
+ /// separated by 4 "="s, and terminated by 4 "<"s.
+ CMK_Perforce
+};
+
+/// Describes the bounds (start, size) of the preamble and a flag required by
+/// PreprocessorOptions::PrecompiledPreambleBytes.
+/// The preamble includes the BOM, if any.
+struct PreambleBounds {
+ /// Size of the preamble in bytes.
+ unsigned Size;
+
+ /// Whether the preamble ends at the start of a new line.
+ ///
+ /// Used to inform the lexer as to whether it's starting at the beginning of
+ /// a line after skipping the preamble.
+ bool PreambleEndsAtStartOfLine;
+
+ PreambleBounds(unsigned Size, bool PreambleEndsAtStartOfLine)
+ : Size(Size), PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {}
+};
+
+/// Lexer - This provides a simple interface that turns a text buffer into a
+/// stream of tokens. This provides no support for file reading or buffering,
+/// or buffering/seeking of tokens, only forward lexing is supported. It relies
+/// on the specified Preprocessor object to handle preprocessor directives, etc.
+class Lexer : public PreprocessorLexer {
+ friend class Preprocessor;
+
+ void anchor() override;
+
+ //===--------------------------------------------------------------------===//
+ // Constant configuration values for this lexer.
+
+ // Start of the buffer.
+ const char *BufferStart;
+
+ // End of the buffer.
+ const char *BufferEnd;
+
+ // Location for start of file.
+ SourceLocation FileLoc;
+
+ // LangOpts enabled by this language.
+ // Storing LangOptions as reference here is important from performance point
+ // of view. Lack of reference means that LangOptions copy constructor would be
+ // called by Lexer(..., const LangOptions &LangOpts,...). Given that local
+ // Lexer objects are created thousands times (in Lexer::getRawToken,
+ // Preprocessor::EnterSourceFile and other places) during single module
+ // processing in frontend it would make std::vector<std::string> copy
+ // constructors surprisingly hot.
+ const LangOptions &LangOpts;
+
+ // True if '//' line comments are enabled.
+ bool LineComment;
+
+ // True if lexer for _Pragma handling.
+ bool Is_PragmaLexer;
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //
+
+ /// ExtendedTokenMode - The lexer can optionally keep comments and whitespace
+ /// and return them as tokens. This is used for -C and -CC modes, and
+ /// whitespace preservation can be useful for some clients that want to lex
+ /// the file in raw mode and get every character from the file.
+ ///
+ /// When this is set to 2 it returns comments and whitespace. When set to 1
+ /// it returns comments, when it is set to 0 it returns normal tokens only.
+ unsigned char ExtendedTokenMode;
+
+ //===--------------------------------------------------------------------===//
+ // Context that changes as the file is lexed.
+ // NOTE: any state that mutates when in raw mode must have save/restore code
+ // in Lexer::isNextPPTokenLParen.
+
+ // BufferPtr - Current pointer into the buffer. This is the next character
+ // to be lexed.
+ const char *BufferPtr;
+
+ // IsAtStartOfLine - True if the next lexed token should get the "start of
+ // line" flag set on it.
+ bool IsAtStartOfLine;
+
+ bool IsAtPhysicalStartOfLine;
+
+ bool HasLeadingSpace;
+
+ bool HasLeadingEmptyMacro;
+
+ /// True if this is the first time we're lexing the input file.
+ bool IsFirstTimeLexingFile;
+
+ // NewLinePtr - A pointer to new line character '\n' being lexed. For '\r\n',
+ // it also points to '\n.'
+ const char *NewLinePtr;
+
+ // CurrentConflictMarkerState - The kind of conflict marker we are handling.
+ ConflictMarkerKind CurrentConflictMarkerState;
+
+ /// Non-empty if this \p Lexer is \p isDependencyDirectivesLexer().
+ ArrayRef<dependency_directives_scan::Directive> DepDirectives;
+
+ /// If this \p Lexer is \p isDependencyDirectivesLexer(), it represents the
+ /// next token to use from the current dependency directive.
+ unsigned NextDepDirectiveTokenIndex = 0;
+
+ void InitLexer(const char *BufStart, const char *BufPtr, const char *BufEnd);
+
+public:
+ /// Lexer constructor - Create a new lexer object for the specified buffer
+ /// with the specified preprocessor managing the lexing process. This lexer
+ /// assumes that the associated file buffer and Preprocessor objects will
+ /// outlive it, so it doesn't take ownership of either of them.
+ Lexer(FileID FID, const llvm::MemoryBufferRef &InputFile, Preprocessor &PP,
+ bool IsFirstIncludeOfFile = true);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
+ /// text range will outlive it, so it doesn't take ownership of it.
+ Lexer(SourceLocation FileLoc, const LangOptions &LangOpts,
+ const char *BufStart, const char *BufPtr, const char *BufEnd,
+ bool IsFirstIncludeOfFile = true);
+
+ /// Lexer constructor - Create a new raw lexer object. This object is only
+ /// suitable for calls to 'LexFromRawLexer'. This lexer assumes that the
+ /// text range will outlive it, so it doesn't take ownership of it.
+ Lexer(FileID FID, const llvm::MemoryBufferRef &FromFile,
+ const SourceManager &SM, const LangOptions &LangOpts,
+ bool IsFirstIncludeOfFile = true);
+
+ Lexer(const Lexer &) = delete;
+ Lexer &operator=(const Lexer &) = delete;
+
+ /// Create_PragmaLexer: Lexer constructor - Create a new lexer object for
+ /// _Pragma expansion. This has a variety of magic semantics that this method
+ /// sets up. It returns a new'd Lexer that must be delete'd when done.
+ static Lexer *Create_PragmaLexer(SourceLocation SpellingLoc,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd,
+ unsigned TokLen, Preprocessor &PP);
+
+ /// getFileLoc - Return the File Location for the file we are lexing out of.
+ /// The physical location encodes the location where the characters come from,
+ /// the virtual location encodes where we should *claim* the characters came
+ /// from. Currently this is only used by _Pragma handling.
+ SourceLocation getFileLoc() const { return FileLoc; }
+
+private:
+ /// Lex - Return the next token in the file. If this is the end of file, it
+ /// return the tok::eof token. This implicitly involves the preprocessor.
+ bool Lex(Token &Result);
+
+ /// Called when the preprocessor is in 'dependency scanning lexing mode'.
+ bool LexDependencyDirectiveToken(Token &Result);
+
+ /// Called when the preprocessor is in 'dependency scanning lexing mode' and
+ /// is skipping a conditional block.
+ bool LexDependencyDirectiveTokenWhileSkipping(Token &Result);
+
+ /// True when the preprocessor is in 'dependency scanning lexing mode' and
+ /// created this \p Lexer for lexing a set of dependency directive tokens.
+ bool isDependencyDirectivesLexer() const { return !DepDirectives.empty(); }
+
+ /// Initializes \p Result with data from \p DDTok and advances \p BufferPtr to
+ /// the position just after the token.
+ /// \returns the buffer pointer at the beginning of the token.
+ const char *convertDependencyDirectiveToken(
+ const dependency_directives_scan::Token &DDTok, Token &Result);
+
+public:
+ /// isPragmaLexer - Returns true if this Lexer is being used to lex a pragma.
+ bool isPragmaLexer() const { return Is_PragmaLexer; }
+
+private:
+ /// IndirectLex - An indirect call to 'Lex' that can be invoked via
+ /// the PreprocessorLexer interface.
+ void IndirectLex(Token &Result) override { Lex(Result); }
+
+public:
+ /// LexFromRawLexer - Lex a token from a designated raw lexer (one with no
+ /// associated preprocessor object. Return true if the 'next character to
+ /// read' pointer points at the end of the lexer buffer, false otherwise.
+ bool LexFromRawLexer(Token &Result) {
+ assert(LexingRawMode && "Not already in raw mode!");
+ Lex(Result);
+ // Note that lexing to the end of the buffer doesn't implicitly delete the
+ // lexer when in raw mode.
+ return BufferPtr == BufferEnd;
+ }
+
+ /// isKeepWhitespaceMode - Return true if the lexer should return tokens for
+ /// every character in the file, including whitespace and comments. This
+ /// should only be used in raw mode, as the preprocessor is not prepared to
+ /// deal with the excess tokens.
+ bool isKeepWhitespaceMode() const {
+ return ExtendedTokenMode > 1;
+ }
+
+ /// SetKeepWhitespaceMode - This method lets clients enable or disable
+ /// whitespace retention mode.
+ void SetKeepWhitespaceMode(bool Val) {
+ assert((!Val || LexingRawMode || LangOpts.TraditionalCPP) &&
+ "Can only retain whitespace in raw mode or -traditional-cpp");
+ ExtendedTokenMode = Val ? 2 : 0;
+ }
+
+ /// inKeepCommentMode - Return true if the lexer should return comments as
+ /// tokens.
+ bool inKeepCommentMode() const {
+ return ExtendedTokenMode > 0;
+ }
+
+ /// SetCommentRetentionMode - Change the comment retention mode of the lexer
+ /// to the specified mode. This is really only useful when lexing in raw
+ /// mode, because otherwise the lexer needs to manage this.
+ void SetCommentRetentionState(bool Mode) {
+ assert(!isKeepWhitespaceMode() &&
+ "Can't play with comment retention state when retaining whitespace");
+ ExtendedTokenMode = Mode ? 1 : 0;
+ }
+
+ /// Sets the extended token mode back to its initial value, according to the
+ /// language options and preprocessor. This controls whether the lexer
+ /// produces comment and whitespace tokens.
+ ///
+ /// This requires the lexer to have an associated preprocessor. A standalone
+ /// lexer has nothing to reset to.
+ void resetExtendedTokenMode();
+
+ /// Gets source code buffer.
+ StringRef getBuffer() const {
+ return StringRef(BufferStart, BufferEnd - BufferStart);
+ }
+
+ /// ReadToEndOfLine - Read the rest of the current preprocessor line as an
+ /// uninterpreted string. This switches the lexer out of directive mode.
+ void ReadToEndOfLine(SmallVectorImpl<char> *Result = nullptr);
+
+
+ /// Diag - Forwarding function for diagnostics. This translate a source
+ /// position in the current buffer into a SourceLocation object for rendering.
+ DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const;
+
+ /// getSourceLocation - Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getSourceLocation(const char *Loc, unsigned TokLen = 1) const;
+
+ /// getSourceLocation - Return a source location for the next character in
+ /// the current file.
+ SourceLocation getSourceLocation() override {
+ return getSourceLocation(BufferPtr);
+ }
+
+ /// Return the current location in the buffer.
+ const char *getBufferLocation() const { return BufferPtr; }
+
+ /// Returns the current lexing offset.
+ unsigned getCurrentBufferOffset() {
+ assert(BufferPtr >= BufferStart && "Invalid buffer state");
+ return BufferPtr - BufferStart;
+ }
+
+ /// Set the lexer's buffer pointer to \p Offset.
+ void seek(unsigned Offset, bool IsAtStartOfLine);
+
+ /// Stringify - Convert the specified string into a C string by i) escaping
+ /// '\\' and " characters and ii) replacing newline character(s) with "\\n".
+ /// If Charify is true, this escapes the ' character instead of ".
+ static std::string Stringify(StringRef Str, bool Charify = false);
+
+ /// Stringify - Convert the specified string into a C string by i) escaping
+ /// '\\' and " characters and ii) replacing newline character(s) with "\\n".
+ static void Stringify(SmallVectorImpl<char> &Str);
+
+ /// getSpelling - This method is used to get the spelling of a token into a
+ /// preallocated buffer, instead of as an std::string. The caller is required
+ /// to allocate enough space for the token, which is guaranteed to be at least
+ /// Tok.getLength() bytes long. The length of the actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ static unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ const SourceManager &SourceMgr,
+ const LangOptions &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
+ /// token is the characters used to represent the token in the source file
+ /// after trigraph expansion and escaped-newline folding. In particular, this
+ /// wants to get the true, uncanonicalized, spelling of things like digraphs
+ /// UCNs, etc.
+ static std::string getSpelling(const Token &Tok,
+ const SourceManager &SourceMgr,
+ const LangOptions &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// getSpelling - This method is used to get the spelling of the
+ /// token at the given source location. If, as is usually true, it
+ /// is not necessary to copy any data, then the returned string may
+ /// not point into the provided buffer.
+ ///
+ /// This method lexes at the expansion depth of the given
+ /// location and does not jump to the expansion or spelling
+ /// location.
+ static StringRef getSpelling(SourceLocation loc,
+ SmallVectorImpl<char> &buffer,
+ const SourceManager &SM,
+ const LangOptions &options,
+ bool *invalid = nullptr);
+
+ /// MeasureTokenLength - Relex the token at the specified location and return
+ /// its length in bytes in the input file. If the token needs cleaning (e.g.
+ /// includes a trigraph or an escaped newline) then this count includes bytes
+ /// that are part of that.
+ static unsigned MeasureTokenLength(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Relex the token at the specified location.
+ /// \returns true if there was a failure, false on success.
+ static bool getRawToken(SourceLocation Loc, Token &Result,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool IgnoreWhiteSpace = false);
+
+ /// Given a location any where in a source buffer, find the location
+ /// that corresponds to the beginning of the token in which the original
+ /// source location lands.
+ static SourceLocation GetBeginningOfToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Get the physical length (including trigraphs and escaped newlines) of the
+ /// first \p Characters characters of the token starting at TokStart.
+ static unsigned getTokenPrefixLength(SourceLocation TokStart,
+ unsigned CharNo,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// AdvanceToTokenCharacter - If the current SourceLocation specifies a
+ /// location at the start of a token, return a new location that specifies a
+ /// character within the token. This handles trigraphs and escaped newlines.
+ static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Characters,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return TokStart.getLocWithOffset(
+ getTokenPrefixLength(TokStart, Characters, SM, LangOpts));
+ }
+
+ /// Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Given a token range, produce a corresponding CharSourceRange that
+ /// is not a token range. This allows the source range to be used by
+ /// components that don't have access to the lexer and thus can't find the
+ /// end of the range for themselves.
+ static CharSourceRange getAsCharRange(SourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ SourceLocation End = getLocForEndOfToken(Range.getEnd(), 0, SM, LangOpts);
+ return End.isInvalid() ? CharSourceRange()
+ : CharSourceRange::getCharRange(
+ Range.getBegin(), End);
+ }
+ static CharSourceRange getAsCharRange(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ return Range.isTokenRange()
+ ? getAsCharRange(Range.getAsRange(), SM, LangOpts)
+ : Range;
+ }
+
+ /// Returns true if the given MacroID location points at the first
+ /// token of the macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to
+ /// begin location of the macro.
+ static bool isAtStartOfMacroExpansion(SourceLocation loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation *MacroBegin = nullptr);
+
+ /// Returns true if the given MacroID location points at the last
+ /// token of the macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to
+ /// end location of the macro.
+ static bool isAtEndOfMacroExpansion(SourceLocation loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation *MacroEnd = nullptr);
+
+ /// Accepts a range and returns a character range with file locations.
+ ///
+ /// Returns a null range if a part of the range resides inside a macro
+ /// expansion or the range does not reside on the same FileID.
+ ///
+ /// This function is trying to deal with macros and return a range based on
+ /// file locations. The cases where it can successfully handle macros are:
+ ///
+ /// -begin or end range lies at the start or end of a macro expansion, in
+ /// which case the location will be set to the expansion point, e.g:
+ /// \#define M 1 2
+ /// a M
+ /// If you have a range [a, 2] (where 2 came from the macro), the function
+ /// will return a range for "a M"
+ /// if you have range [a, 1], the function will fail because the range
+ /// overlaps with only a part of the macro
+ ///
+ /// -The macro is a function macro and the range can be mapped to the macro
+ /// arguments, e.g:
+ /// \#define M 1 2
+ /// \#define FM(x) x
+ /// FM(a b M)
+ /// if you have range [b, 2], the function will return the file range "b M"
+ /// inside the macro arguments.
+ /// if you have range [a, 2], the function will return the file range
+ /// "FM(a b M)" since the range includes all of the macro expansion.
+ static CharSourceRange makeFileCharRange(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Returns a string for the source that the range encompasses.
+ static StringRef getSourceText(CharSourceRange Range,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool *Invalid = nullptr);
+
+ /// Retrieve the name of the immediate macro expansion.
+ ///
+ /// This routine starts from a source location, and finds the name of the macro
+ /// responsible for its immediate expansion. It looks through any intervening
+ /// macro argument expansions to compute this. It returns a StringRef which
+ /// refers to the SourceManager-owned buffer of the source where that macro
+ /// name is spelled. Thus, the result shouldn't out-live that SourceManager.
+ static StringRef getImmediateMacroName(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Retrieve the name of the immediate macro expansion.
+ ///
+ /// This routine starts from a source location, and finds the name of the
+ /// macro responsible for its immediate expansion. It looks through any
+ /// intervening macro argument expansions to compute this. It returns a
+ /// StringRef which refers to the SourceManager-owned buffer of the source
+ /// where that macro name is spelled. Thus, the result shouldn't out-live
+ /// that SourceManager.
+ ///
+ /// This differs from Lexer::getImmediateMacroName in that any macro argument
+ /// location will result in the topmost function macro that accepted it.
+ /// e.g.
+ /// \code
+ /// MAC1( MAC2(foo) )
+ /// \endcode
+ /// for location of 'foo' token, this function will return "MAC1" while
+ /// Lexer::getImmediateMacroName will return "MAC2".
+ static StringRef getImmediateMacroNameForDiagnostics(
+ SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts);
+
+ /// Compute the preamble of the given file.
+ ///
+ /// The preamble of a file contains the initial comments, include directives,
+ /// and other preprocessor directives that occur before the code in this
+ /// particular file actually begins. The preamble of the main source file is
+ /// a potential prefix header.
+ ///
+ /// \param Buffer The memory buffer containing the file's contents.
+ ///
+ /// \param MaxLines If non-zero, restrict the length of the preamble
+ /// to fewer than this number of lines.
+ ///
+ /// \returns The offset into the file where the preamble ends and the rest
+ /// of the file begins along with a boolean value indicating whether
+ /// the preamble ends at the beginning of a new line.
+ static PreambleBounds ComputePreamble(StringRef Buffer,
+ const LangOptions &LangOpts,
+ unsigned MaxLines = 0);
+
+ /// Finds the token that comes right after the given location.
+ ///
+ /// Returns the next token, or none if the location is inside a macro.
+ static std::optional<Token> findNextToken(SourceLocation Loc,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+
+ /// Checks that the given token is the first token that occurs after
+ /// the given location (this excludes comments and whitespace). Returns the
+ /// location immediately after the specified token. If the token is not found
+ /// or the location is inside a macro, the returned source location will be
+ /// invalid.
+ static SourceLocation findLocationAfterToken(SourceLocation loc,
+ tok::TokenKind TKind,
+ const SourceManager &SM,
+ const LangOptions &LangOpts,
+ bool SkipTrailingWhitespaceAndNewLine);
+
+ /// Returns true if the given character could appear in an identifier.
+ static bool isAsciiIdentifierContinueChar(char c,
+ const LangOptions &LangOpts);
+
+ /// Checks whether new line pointed by Str is preceded by escape
+ /// sequence.
+ static bool isNewLineEscaped(const char *BufferStart, const char *Str);
+
+ /// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
+ /// emit a warning.
+ static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &LangOpts) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts);
+ }
+
+ /// Returns the leading whitespace for line that corresponds to the given
+ /// location \p Loc.
+ static StringRef getIndentationForLine(SourceLocation Loc,
+ const SourceManager &SM);
+
+ /// Check if this is the first time we're lexing the input file.
+ bool isFirstTimeLexingFile() const { return IsFirstTimeLexingFile; }
+
+private:
+ //===--------------------------------------------------------------------===//
+ // Internal implementation interfaces.
+
+ /// LexTokenInternal - Internal interface to lex a preprocessing token. Called
+ /// by Lex.
+ ///
+ bool LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine);
+
+ bool CheckUnicodeWhitespace(Token &Result, uint32_t C, const char *CurPtr);
+
+ bool LexUnicodeIdentifierStart(Token &Result, uint32_t C, const char *CurPtr);
+
+ /// FormTokenWithChars - When we lex a token, we have identified a span
+ /// starting at BufferPtr, going to TokEnd that forms the token. This method
+ /// takes that range and assigns it to the token as its location and size. In
+ /// addition, since tokens cannot overlap, this also updates BufferPtr to be
+ /// TokEnd.
+ void FormTokenWithChars(Token &Result, const char *TokEnd,
+ tok::TokenKind Kind) {
+ unsigned TokLen = TokEnd-BufferPtr;
+ Result.setLength(TokLen);
+ Result.setLocation(getSourceLocation(BufferPtr, TokLen));
+ Result.setKind(Kind);
+ BufferPtr = TokEnd;
+ }
+
+ /// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
+ /// tok::l_paren token, 0 if it is something else and 2 if there are no more
+ /// tokens in the buffer controlled by this lexer.
+ unsigned isNextPPTokenLParen();
+
+ //===--------------------------------------------------------------------===//
+ // Lexer character reading interfaces.
+
+ // This lexer is built on two interfaces for reading characters, both of which
+ // automatically provide phase 1/2 translation. getAndAdvanceChar is used
+ // when we know that we will be reading a character from the input buffer and
+ // that this character will be part of the result token. This occurs in (f.e.)
+ // string processing, because we know we need to read until we find the
+ // closing '"' character.
+ //
+ // The second interface is the combination of getCharAndSize with
+ // ConsumeChar. getCharAndSize reads a phase 1/2 translated character,
+ // returning it and its size. If the lexer decides that this character is
+ // part of the current token, it calls ConsumeChar on it. This two stage
+ // approach allows us to emit diagnostics for characters (e.g. warnings about
+ // trigraphs), knowing that they only are emitted if the character is
+ // consumed.
+
+ /// isObviouslySimpleCharacter - Return true if the specified character is
+ /// obviously the same in translation phase 1 and translation phase 3. This
+ /// can return false for characters that end up being the same, but it will
+ /// never return true for something that needs to be mapped.
+ static bool isObviouslySimpleCharacter(char C) {
+ return C != '?' && C != '\\';
+ }
+
+ /// getAndAdvanceChar - Read a single 'character' from the specified buffer,
+ /// advance over it, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getAndAdvanceChar(const char *&Ptr, Token &Tok) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) return *Ptr++;
+
+ unsigned Size = 0;
+ char C = getCharAndSizeSlow(Ptr, Size, &Tok);
+ Ptr += Size;
+ return C;
+ }
+
+ /// ConsumeChar - When a character (identified by getCharAndSize) is consumed
+ /// and added to a given token, check to see if there are diagnostics that
+ /// need to be emitted or flags that need to be set on the token. If so, do
+ /// it.
+ const char *ConsumeChar(const char *Ptr, unsigned Size, Token &Tok) {
+ // Normal case, we consumed exactly one token. Just return it.
+ if (Size == 1)
+ return Ptr+Size;
+
+ // Otherwise, re-lex the character with a current token, allowing
+ // diagnostics to be emitted and flags to be set.
+ Size = 0;
+ getCharAndSizeSlow(Ptr, Size, &Tok);
+ return Ptr+Size;
+ }
+
+ /// getCharAndSize - Peek a single 'character' from the specified buffer,
+ /// get its size, and return it. This is tricky in several cases. Here we
+ /// just handle the trivial case and fall-back to the non-inlined
+ /// getCharAndSizeSlow method to handle the hard case.
+ inline char getCharAndSize(const char *Ptr, unsigned &Size) {
+ // If this is not a trigraph and not a UCN or escaped newline, return
+ // quickly.
+ if (isObviouslySimpleCharacter(Ptr[0])) {
+ Size = 1;
+ return *Ptr;
+ }
+
+ Size = 0;
+ return getCharAndSizeSlow(Ptr, Size);
+ }
+
+ /// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize
+ /// method.
+ char getCharAndSizeSlow(const char *Ptr, unsigned &Size,
+ Token *Tok = nullptr);
+
+ /// getEscapedNewLineSize - Return the size of the specified escaped newline,
+ /// or 0 if it is not an escaped newline. P[-1] is known to be a "\" on entry
+ /// to this function.
+ static unsigned getEscapedNewLineSize(const char *P);
+
+ /// SkipEscapedNewLines - If P points to an escaped newline (or a series of
+ /// them), skip over them and return the first non-escaped-newline found,
+ /// otherwise return P.
+ static const char *SkipEscapedNewLines(const char *P);
+
+ /// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
+ /// diagnostic.
+ static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
+ const LangOptions &LangOpts);
+
+ //===--------------------------------------------------------------------===//
+ // Other lexer functions.
+
+ void SetByteOffset(unsigned Offset, bool StartOfLine);
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
+ const char *LexUDSuffix(Token &Result, const char *CurPtr,
+ bool IsStringLiteral);
+
+ // Helper functions to lex the remainder of a token of the specific type.
+
+ // This function handles both ASCII and Unicode identifiers after
+ // the first codepoint of the identifyier has been parsed.
+ bool LexIdentifierContinue(Token &Result, const char *CurPtr);
+
+ bool LexNumericConstant (Token &Result, const char *CurPtr);
+ bool LexStringLiteral (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexRawStringLiteral (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexAngledStringLiteral(Token &Result, const char *CurPtr);
+ bool LexCharConstant (Token &Result, const char *CurPtr,
+ tok::TokenKind Kind);
+ bool LexEndOfFile (Token &Result, const char *CurPtr);
+ bool SkipWhitespace (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipLineComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SkipBlockComment (Token &Result, const char *CurPtr,
+ bool &TokAtPhysicalStartOfLine);
+ bool SaveLineComment (Token &Result, const char *CurPtr);
+
+ bool IsStartOfConflictMarker(const char *CurPtr);
+ bool HandleEndOfConflictMarker(const char *CurPtr);
+
+ bool lexEditorPlaceholder(Token &Result, const char *CurPtr);
+
+ bool isCodeCompletionPoint(const char *CurPtr) const;
+ void cutOffLexing() { BufferPtr = BufferEnd; }
+
+ bool isHexaLiteral(const char *Start, const LangOptions &LangOpts);
+
+ void codeCompleteIncludedFile(const char *PathStart,
+ const char *CompletionPoint, bool IsAngled);
+
+ std::optional<uint32_t>
+ tryReadNumericUCN(const char *&StartPtr, const char *SlashLoc, Token *Result);
+ std::optional<uint32_t> tryReadNamedUCN(const char *&StartPtr,
+ const char *SlashLoc, Token *Result);
+
+ /// Read a universal character name.
+ ///
+ /// \param StartPtr The position in the source buffer after the initial '\'.
+ /// If the UCN is syntactically well-formed (but not
+ /// necessarily valid), this parameter will be updated to
+ /// point to the character after the UCN.
+ /// \param SlashLoc The position in the source buffer of the '\'.
+ /// \param Result The token being formed. Pass \c nullptr to suppress
+ /// diagnostics and handle token formation in the caller.
+ ///
+ /// \return The Unicode codepoint specified by the UCN, or 0 if the UCN is
+ /// invalid.
+ uint32_t tryReadUCN(const char *&StartPtr, const char *SlashLoc, Token *Result);
+
+ /// Try to consume a UCN as part of an identifier at the current
+ /// location.
+ /// \param CurPtr Initially points to the range of characters in the source
+ /// buffer containing the '\'. Updated to point past the end of
+ /// the UCN on success.
+ /// \param Size The number of characters occupied by the '\' (including
+ /// trigraphs and escaped newlines).
+ /// \param Result The token being produced. Marked as containing a UCN on
+ /// success.
+ /// \return \c true if a UCN was lexed and it produced an acceptable
+ /// identifier character, \c false otherwise.
+ bool tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size,
+ Token &Result);
+
+ /// Try to consume an identifier character encoded in UTF-8.
+ /// \param CurPtr Points to the start of the (potential) UTF-8 code unit
+ /// sequence. On success, updated to point past the end of it.
+ /// \return \c true if a UTF-8 sequence mapping to an acceptable identifier
+ /// character was lexed, \c false otherwise.
+ bool tryConsumeIdentifierUTF8Char(const char *&CurPtr);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_LEXER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/LiteralSupport.h b/contrib/libs/clang16/include/clang/Lex/LiteralSupport.h
new file mode 100644
index 0000000000..d20058ca1f
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/LiteralSupport.h
@@ -0,0 +1,308 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- LiteralSupport.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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NumericLiteralParser, CharLiteralParser, and
+// StringLiteralParser interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_LITERALSUPPORT_H
+#define LLVM_CLANG_LEX_LITERALSUPPORT_H
+
+#include "clang/Basic/CharInfo.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+
+class DiagnosticsEngine;
+class Preprocessor;
+class Token;
+class SourceLocation;
+class TargetInfo;
+class SourceManager;
+class LangOptions;
+
+/// Copy characters from Input to Buf, expanding any UCNs.
+void expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input);
+
+/// NumericLiteralParser - This performs strict semantic analysis of the content
+/// of a ppnumber, classifying it as either integer, floating, or erroneous,
+/// determines the radix of the value and can convert it to a useful value.
+class NumericLiteralParser {
+ const SourceManager &SM;
+ const LangOptions &LangOpts;
+ DiagnosticsEngine &Diags;
+
+ const char *const ThisTokBegin;
+ const char *const ThisTokEnd;
+ const char *DigitsBegin, *SuffixBegin; // markers
+ const char *s; // cursor
+
+ unsigned radix;
+
+ bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix;
+
+ SmallString<32> UDSuffixBuf;
+
+public:
+ NumericLiteralParser(StringRef TokSpelling, SourceLocation TokLoc,
+ const SourceManager &SM, const LangOptions &LangOpts,
+ const TargetInfo &Target, DiagnosticsEngine &Diags);
+ bool hadError : 1;
+ bool isUnsigned : 1;
+ bool isLong : 1; // This is *not* set for long long.
+ bool isLongLong : 1;
+ bool isSizeT : 1; // 1z, 1uz (C++2b)
+ bool isHalf : 1; // 1.0h
+ bool isFloat : 1; // 1.0f
+ bool isImaginary : 1; // 1.0i
+ bool isFloat16 : 1; // 1.0f16
+ bool isFloat128 : 1; // 1.0q
+ bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr
+ bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
+ bool isBitInt : 1; // 1wb, 1uwb (C2x)
+ uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
+
+
+ bool isFixedPointLiteral() const {
+ return (saw_period || saw_exponent) && saw_fixed_point_suffix;
+ }
+
+ bool isIntegerLiteral() const {
+ return !saw_period && !saw_exponent && !isFixedPointLiteral();
+ }
+ bool isFloatingLiteral() const {
+ return (saw_period || saw_exponent) && !isFixedPointLiteral();
+ }
+
+ bool hasUDSuffix() const {
+ return saw_ud_suffix;
+ }
+ StringRef getUDSuffix() const {
+ assert(saw_ud_suffix);
+ return UDSuffixBuf;
+ }
+ unsigned getUDSuffixOffset() const {
+ assert(saw_ud_suffix);
+ return SuffixBegin - ThisTokBegin;
+ }
+
+ static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
+
+ unsigned getRadix() const { return radix; }
+
+ /// GetIntegerValue - Convert this numeric literal value to an APInt that
+ /// matches Val's input width. If there is an overflow (i.e., if the unsigned
+ /// value read is larger than the APInt's bits will hold), set Val to the low
+ /// bits of the result and return true. Otherwise, return false.
+ bool GetIntegerValue(llvm::APInt &Val);
+
+ /// GetFloatValue - Convert this numeric literal to a floating value, using
+ /// the specified APFloat fltSemantics (specifying float, double, etc).
+ /// The optional bool isExact (passed-by-reference) has its value
+ /// set to true if the returned APFloat can represent the number in the
+ /// literal exactly, and false otherwise.
+ llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);
+
+ /// GetFixedPointValue - Convert this numeric literal value into a
+ /// scaled integer that represents this value. Returns true if an overflow
+ /// occurred when calculating the integral part of the scaled integer or
+ /// calculating the digit sequence of the exponent.
+ bool GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale);
+
+ /// Get the digits that comprise the literal. This excludes any prefix or
+ /// suffix associated with the literal.
+ StringRef getLiteralDigits() const {
+ assert(!hadError && "cannot reliably get the literal digits with an error");
+ return StringRef(DigitsBegin, SuffixBegin - DigitsBegin);
+ }
+
+private:
+
+ void ParseNumberStartingWithZero(SourceLocation TokLoc);
+ void ParseDecimalOrOctalCommon(SourceLocation TokLoc);
+
+ static bool isDigitSeparator(char C) { return C == '\''; }
+
+ /// Determine whether the sequence of characters [Start, End) contains
+ /// any real digits (not digit separators).
+ bool containsDigits(const char *Start, const char *End) {
+ return Start != End && (Start + 1 != End || !isDigitSeparator(Start[0]));
+ }
+
+ enum CheckSeparatorKind { CSK_BeforeDigits, CSK_AfterDigits };
+
+ /// Ensure that we don't have a digit separator here.
+ void checkSeparator(SourceLocation TokLoc, const char *Pos,
+ CheckSeparatorKind IsAfterDigits);
+
+ /// SkipHexDigits - Read and skip over any hex digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipHexDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && (isHexDigit(*ptr) || isDigitSeparator(*ptr)))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipOctalDigits - Read and skip over any octal digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipOctalDigits(const char *ptr) {
+ while (ptr != ThisTokEnd &&
+ ((*ptr >= '0' && *ptr <= '7') || isDigitSeparator(*ptr)))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipDigits - Read and skip over any digits, up to End.
+ /// Return a pointer to the first non-hex digit or End.
+ const char *SkipDigits(const char *ptr) {
+ while (ptr != ThisTokEnd && (isDigit(*ptr) || isDigitSeparator(*ptr)))
+ ptr++;
+ return ptr;
+ }
+
+ /// SkipBinaryDigits - Read and skip over any binary digits, up to End.
+ /// Return a pointer to the first non-binary digit or End.
+ const char *SkipBinaryDigits(const char *ptr) {
+ while (ptr != ThisTokEnd &&
+ (*ptr == '0' || *ptr == '1' || isDigitSeparator(*ptr)))
+ ptr++;
+ return ptr;
+ }
+
+};
+
+/// CharLiteralParser - Perform interpretation and semantic analysis of a
+/// character literal.
+class CharLiteralParser {
+ uint64_t Value;
+ tok::TokenKind Kind;
+ bool IsMultiChar;
+ bool HadError;
+ SmallString<32> UDSuffixBuf;
+ unsigned UDSuffixOffset;
+public:
+ CharLiteralParser(const char *begin, const char *end,
+ SourceLocation Loc, Preprocessor &PP,
+ tok::TokenKind kind);
+
+ bool hadError() const { return HadError; }
+ bool isOrdinary() const { return Kind == tok::char_constant; }
+ bool isWide() const { return Kind == tok::wide_char_constant; }
+ bool isUTF8() const { return Kind == tok::utf8_char_constant; }
+ bool isUTF16() const { return Kind == tok::utf16_char_constant; }
+ bool isUTF32() const { return Kind == tok::utf32_char_constant; }
+ bool isMultiChar() const { return IsMultiChar; }
+ uint64_t getValue() const { return Value; }
+ StringRef getUDSuffix() const { return UDSuffixBuf; }
+ unsigned getUDSuffixOffset() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixOffset;
+ }
+};
+
+/// StringLiteralParser - This decodes string escape characters and performs
+/// wide string analysis and Translation Phase #6 (concatenation of string
+/// literals) (C99 5.1.1.2p1).
+class StringLiteralParser {
+ const SourceManager &SM;
+ const LangOptions &Features;
+ const TargetInfo &Target;
+ DiagnosticsEngine *Diags;
+
+ unsigned MaxTokenLength;
+ unsigned SizeBound;
+ unsigned CharByteWidth;
+ tok::TokenKind Kind;
+ SmallString<512> ResultBuf;
+ char *ResultPtr; // cursor
+ SmallString<32> UDSuffixBuf;
+ unsigned UDSuffixToken;
+ unsigned UDSuffixOffset;
+public:
+ StringLiteralParser(ArrayRef<Token> StringToks,
+ Preprocessor &PP);
+ StringLiteralParser(ArrayRef<Token> StringToks,
+ const SourceManager &sm, const LangOptions &features,
+ const TargetInfo &target,
+ DiagnosticsEngine *diags = nullptr)
+ : SM(sm), Features(features), Target(target), Diags(diags),
+ MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
+ ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
+ init(StringToks);
+ }
+
+
+ bool hadError;
+ bool Pascal;
+
+ StringRef GetString() const {
+ return StringRef(ResultBuf.data(), GetStringLength());
+ }
+ unsigned GetStringLength() const { return ResultPtr-ResultBuf.data(); }
+
+ unsigned GetNumStringChars() const {
+ return GetStringLength() / CharByteWidth;
+ }
+ /// getOffsetOfStringByte - This function returns the offset of the
+ /// specified byte of the string data represented by Token. This handles
+ /// advancing over escape sequences in the string.
+ ///
+ /// If the Diagnostics pointer is non-null, then this will do semantic
+ /// checking of the string literal and emit errors and warnings.
+ unsigned getOffsetOfStringByte(const Token &TheTok, unsigned ByteNo) const;
+
+ bool isOrdinary() const { return Kind == tok::string_literal; }
+ bool isWide() const { return Kind == tok::wide_string_literal; }
+ bool isUTF8() const { return Kind == tok::utf8_string_literal; }
+ bool isUTF16() const { return Kind == tok::utf16_string_literal; }
+ bool isUTF32() const { return Kind == tok::utf32_string_literal; }
+ bool isPascal() const { return Pascal; }
+
+ StringRef getUDSuffix() const { return UDSuffixBuf; }
+
+ /// Get the index of a token containing a ud-suffix.
+ unsigned getUDSuffixToken() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixToken;
+ }
+ /// Get the spelling offset of the first byte of the ud-suffix.
+ unsigned getUDSuffixOffset() const {
+ assert(!UDSuffixBuf.empty() && "no ud-suffix");
+ return UDSuffixOffset;
+ }
+
+ static bool isValidUDSuffix(const LangOptions &LangOpts, StringRef Suffix);
+
+private:
+ void init(ArrayRef<Token> StringToks);
+ bool CopyStringFragment(const Token &Tok, const char *TokBegin,
+ StringRef Fragment);
+ void DiagnoseLexingError(SourceLocation Loc);
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/MacroArgs.h b/contrib/libs/clang16/include/clang/Lex/MacroArgs.h
new file mode 100644
index 0000000000..db4680423c
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/MacroArgs.h
@@ -0,0 +1,148 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- MacroArgs.h - Formal argument info for Macros ----------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the MacroArgs interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MACROARGS_H
+#define LLVM_CLANG_LEX_MACROARGS_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <vector>
+
+namespace clang {
+ class MacroInfo;
+ class Preprocessor;
+ class SourceLocation;
+
+/// MacroArgs - An instance of this class captures information about
+/// the formal arguments specified to a function-like macro invocation.
+class MacroArgs final
+ : private llvm::TrailingObjects<MacroArgs, Token> {
+
+ friend TrailingObjects;
+ /// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
+ /// arguments. All of the actual argument tokens are allocated immediately
+ /// after the MacroArgs object in memory. This is all of the arguments
+ /// concatenated together, with 'EOF' markers at the end of each argument.
+ unsigned NumUnexpArgTokens;
+
+ /// VarargsElided - True if this is a C99 style varargs macro invocation and
+ /// there was no argument specified for the "..." argument. If the argument
+ /// was specified (even empty) or this isn't a C99 style varargs function, or
+ /// if in strict mode and the C99 varargs macro had only a ... argument, this
+ /// is false.
+ bool VarargsElided;
+
+ /// PreExpArgTokens - Pre-expanded tokens for arguments that need them. Empty
+ /// if not yet computed. This includes the EOF marker at the end of the
+ /// stream.
+ std::vector<std::vector<Token> > PreExpArgTokens;
+
+ /// ArgCache - This is a linked list of MacroArgs objects that the
+ /// Preprocessor owns which we use to avoid thrashing malloc/free.
+ MacroArgs *ArgCache;
+
+ /// MacroArgs - The number of arguments the invoked macro expects.
+ unsigned NumMacroArgs;
+
+ MacroArgs(unsigned NumToks, bool varargsElided, unsigned MacroArgs)
+ : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided),
+ ArgCache(nullptr), NumMacroArgs(MacroArgs) {}
+ ~MacroArgs() = default;
+
+public:
+ /// MacroArgs ctor function - Create a new MacroArgs object with the specified
+ /// macro and argument info.
+ static MacroArgs *create(const MacroInfo *MI,
+ ArrayRef<Token> UnexpArgTokens,
+ bool VarargsElided, Preprocessor &PP);
+
+ /// destroy - Destroy and deallocate the memory for this object.
+ ///
+ void destroy(Preprocessor &PP);
+
+ /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
+ /// by pre-expansion, return false. Otherwise, conservatively return true.
+ bool ArgNeedsPreexpansion(const Token *ArgTok, Preprocessor &PP) const;
+
+ /// getUnexpArgument - Return a pointer to the first token of the unexpanded
+ /// token list for the specified formal.
+ ///
+ const Token *getUnexpArgument(unsigned Arg) const;
+
+ /// getArgLength - Given a pointer to an expanded or unexpanded argument,
+ /// return the number of tokens, not counting the EOF, that make up the
+ /// argument.
+ static unsigned getArgLength(const Token *ArgPtr);
+
+ /// getPreExpArgument - Return the pre-expanded form of the specified
+ /// argument.
+ const std::vector<Token> &
+ getPreExpArgument(unsigned Arg, Preprocessor &PP);
+
+ /// getNumMacroArguments - Return the number of arguments the invoked macro
+ /// expects.
+ unsigned getNumMacroArguments() const { return NumMacroArgs; }
+
+ /// isVarargsElidedUse - Return true if this is a C99 style varargs macro
+ /// invocation and there was no argument specified for the "..." argument. If
+ /// the argument was specified (even empty) or this isn't a C99 style varargs
+ /// function, or if in strict mode and the C99 varargs macro had only a ...
+ /// argument, this returns false.
+ bool isVarargsElidedUse() const { return VarargsElided; }
+
+ /// Returns true if the macro was defined with a variadic (ellipsis) parameter
+ /// AND was invoked with at least one token supplied as a variadic argument
+ /// (after pre-expansion).
+ ///
+ /// \code
+ /// #define F(a) a
+ /// #define V(a, ...) __VA_OPT__(a)
+ /// F() <-- returns false on this invocation.
+ /// V(,a) <-- returns true on this invocation.
+ /// V(,) <-- returns false on this invocation.
+ /// V(,F()) <-- returns false on this invocation.
+ /// \endcode
+ ///
+ bool invokedWithVariadicArgument(const MacroInfo *const MI, Preprocessor &PP);
+
+ /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
+ /// tokens into the literal string token that should be produced by the C #
+ /// preprocessor operator. If Charify is true, then it should be turned into
+ /// a character literal for the Microsoft charize (#@) extension.
+ ///
+ static Token StringifyArgument(const Token *ArgToks,
+ Preprocessor &PP, bool Charify,
+ SourceLocation ExpansionLocStart,
+ SourceLocation ExpansionLocEnd);
+
+
+ /// deallocate - This should only be called by the Preprocessor when managing
+ /// its freelist.
+ MacroArgs *deallocate();
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/MacroInfo.h b/contrib/libs/clang16/include/clang/Lex/MacroInfo.h
new file mode 100644
index 0000000000..7176553f5d
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/MacroInfo.h
@@ -0,0 +1,644 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- MacroInfo.h - Information about #defined identifiers -----*- 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
+/// Defines the clang::MacroInfo and clang::MacroDirective classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MACROINFO_H
+#define LLVM_CLANG_LEX_MACROINFO_H
+
+#include "clang/Lex/Token.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <algorithm>
+#include <cassert>
+
+namespace clang {
+
+class DefMacroDirective;
+class IdentifierInfo;
+class Module;
+class Preprocessor;
+class SourceManager;
+
+/// Encapsulates the data about a macro definition (e.g. its tokens).
+///
+/// There's an instance of this class for every #define.
+class MacroInfo {
+ //===--------------------------------------------------------------------===//
+ // State set when the macro is defined.
+
+ /// The location the macro is defined.
+ SourceLocation Location;
+
+ /// The location of the last token in the macro.
+ SourceLocation EndLocation;
+
+ /// The list of arguments for a function-like macro.
+ ///
+ /// ParameterList points to the first of NumParameters pointers.
+ ///
+ /// This can be empty, for, e.g. "#define X()". In a C99-style variadic
+ /// macro, this includes the \c __VA_ARGS__ identifier on the list.
+ IdentifierInfo **ParameterList = nullptr;
+
+ /// This is the list of tokens that the macro is defined to.
+ const Token *ReplacementTokens = nullptr;
+
+ /// \see ParameterList
+ unsigned NumParameters = 0;
+
+ /// \see ReplacementTokens
+ unsigned NumReplacementTokens = 0;
+
+ /// Length in characters of the macro definition.
+ mutable unsigned DefinitionLength;
+ mutable bool IsDefinitionLengthCached : 1;
+
+ /// True if this macro is function-like, false if it is object-like.
+ bool IsFunctionLike : 1;
+
+ /// True if this macro is of the form "#define X(...)" or
+ /// "#define X(Y,Z,...)".
+ ///
+ /// The __VA_ARGS__ token should be replaced with the contents of "..." in an
+ /// invocation.
+ bool IsC99Varargs : 1;
+
+ /// True if this macro is of the form "#define X(a...)".
+ ///
+ /// The "a" identifier in the replacement list will be replaced with all
+ /// arguments of the macro starting with the specified one.
+ bool IsGNUVarargs : 1;
+
+ /// True if this macro requires processing before expansion.
+ ///
+ /// This is the case for builtin macros such as __LINE__, so long as they have
+ /// not been redefined, but not for regular predefined macros from the
+ /// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
+ bool IsBuiltinMacro : 1;
+
+ /// Whether this macro contains the sequence ", ## __VA_ARGS__"
+ bool HasCommaPasting : 1;
+
+ //===--------------------------------------------------------------------===//
+ // State that changes as the macro is used.
+
+ /// True if we have started an expansion of this macro already.
+ ///
+ /// This disables recursive expansion, which would be quite bad for things
+ /// like \#define A A.
+ bool IsDisabled : 1;
+
+ /// True if this macro is either defined in the main file and has
+ /// been used, or if it is not defined in the main file.
+ ///
+ /// This is used to emit -Wunused-macros diagnostics.
+ bool IsUsed : 1;
+
+ /// True if this macro can be redefined without emitting a warning.
+ bool IsAllowRedefinitionsWithoutWarning : 1;
+
+ /// Must warn if the macro is unused at the end of translation unit.
+ bool IsWarnIfUnused : 1;
+
+ /// Whether this macro was used as header guard.
+ bool UsedForHeaderGuard : 1;
+
+ // Only the Preprocessor gets to create these.
+ MacroInfo(SourceLocation DefLoc);
+
+public:
+ /// Return the location that the macro was defined at.
+ SourceLocation getDefinitionLoc() const { return Location; }
+
+ /// Set the location of the last token in the macro.
+ void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
+
+ /// Return the location of the last token in the macro.
+ SourceLocation getDefinitionEndLoc() const { return EndLocation; }
+
+ /// Get length in characters of the macro definition.
+ unsigned getDefinitionLength(const SourceManager &SM) const {
+ if (IsDefinitionLengthCached)
+ return DefinitionLength;
+ return getDefinitionLengthSlow(SM);
+ }
+
+ /// Return true if the specified macro definition is equal to
+ /// this macro in spelling, arguments, and whitespace.
+ ///
+ /// \param Syntactically if true, the macro definitions can be identical even
+ /// if they use different identifiers for the function macro parameters.
+ /// Otherwise the comparison is lexical and this implements the rules in
+ /// C99 6.10.3.
+ bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
+ bool Syntactically) const;
+
+ /// Set or clear the isBuiltinMacro flag.
+ void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
+
+ /// Set the value of the IsUsed flag.
+ void setIsUsed(bool Val) { IsUsed = Val; }
+
+ /// Set the value of the IsAllowRedefinitionsWithoutWarning flag.
+ void setIsAllowRedefinitionsWithoutWarning(bool Val) {
+ IsAllowRedefinitionsWithoutWarning = Val;
+ }
+
+ /// Set the value of the IsWarnIfUnused flag.
+ void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }
+
+ /// Set the specified list of identifiers as the parameter list for
+ /// this macro.
+ void setParameterList(ArrayRef<IdentifierInfo *> List,
+ llvm::BumpPtrAllocator &PPAllocator) {
+ assert(ParameterList == nullptr && NumParameters == 0 &&
+ "Parameter list already set!");
+ if (List.empty())
+ return;
+
+ NumParameters = List.size();
+ ParameterList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
+ std::copy(List.begin(), List.end(), ParameterList);
+ }
+
+ /// Parameters - The list of parameters for a function-like macro. This can
+ /// be empty, for, e.g. "#define X()".
+ using param_iterator = IdentifierInfo *const *;
+ bool param_empty() const { return NumParameters == 0; }
+ param_iterator param_begin() const { return ParameterList; }
+ param_iterator param_end() const { return ParameterList + NumParameters; }
+ unsigned getNumParams() const { return NumParameters; }
+ ArrayRef<const IdentifierInfo *> params() const {
+ return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters);
+ }
+
+ /// Return the parameter number of the specified identifier,
+ /// or -1 if the identifier is not a formal parameter identifier.
+ int getParameterNum(const IdentifierInfo *Arg) const {
+ for (param_iterator I = param_begin(), E = param_end(); I != E; ++I)
+ if (*I == Arg)
+ return I - param_begin();
+ return -1;
+ }
+
+ /// Function/Object-likeness. Keep track of whether this macro has formal
+ /// parameters.
+ void setIsFunctionLike() { IsFunctionLike = true; }
+ bool isFunctionLike() const { return IsFunctionLike; }
+ bool isObjectLike() const { return !IsFunctionLike; }
+
+ /// Varargs querying methods. This can only be set for function-like macros.
+ void setIsC99Varargs() { IsC99Varargs = true; }
+ void setIsGNUVarargs() { IsGNUVarargs = true; }
+ bool isC99Varargs() const { return IsC99Varargs; }
+ bool isGNUVarargs() const { return IsGNUVarargs; }
+ bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
+
+ /// Return true if this macro requires processing before expansion.
+ ///
+ /// This is true only for builtin macro, such as \__LINE__, whose values
+ /// are not given by fixed textual expansions. Regular predefined macros
+ /// from the "<built-in>" buffer are not reported as builtins by this
+ /// function.
+ bool isBuiltinMacro() const { return IsBuiltinMacro; }
+
+ bool hasCommaPasting() const { return HasCommaPasting; }
+ void setHasCommaPasting() { HasCommaPasting = true; }
+
+ /// Return false if this macro is defined in the main file and has
+ /// not yet been used.
+ bool isUsed() const { return IsUsed; }
+
+ /// Return true if this macro can be redefined without warning.
+ bool isAllowRedefinitionsWithoutWarning() const {
+ return IsAllowRedefinitionsWithoutWarning;
+ }
+
+ /// Return true if we should emit a warning if the macro is unused.
+ bool isWarnIfUnused() const { return IsWarnIfUnused; }
+
+ /// Return the number of tokens that this macro expands to.
+ unsigned getNumTokens() const { return NumReplacementTokens; }
+
+ const Token &getReplacementToken(unsigned Tok) const {
+ assert(Tok < NumReplacementTokens && "Invalid token #");
+ return ReplacementTokens[Tok];
+ }
+
+ using const_tokens_iterator = const Token *;
+
+ const_tokens_iterator tokens_begin() const { return ReplacementTokens; }
+ const_tokens_iterator tokens_end() const {
+ return ReplacementTokens + NumReplacementTokens;
+ }
+ bool tokens_empty() const { return NumReplacementTokens == 0; }
+ ArrayRef<Token> tokens() const {
+ return llvm::ArrayRef(ReplacementTokens, NumReplacementTokens);
+ }
+
+ llvm::MutableArrayRef<Token>
+ allocateTokens(unsigned NumTokens, llvm::BumpPtrAllocator &PPAllocator) {
+ assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
+ "Token list already allocated!");
+ NumReplacementTokens = NumTokens;
+ Token *NewReplacementTokens = PPAllocator.Allocate<Token>(NumTokens);
+ ReplacementTokens = NewReplacementTokens;
+ return llvm::MutableArrayRef(NewReplacementTokens, NumTokens);
+ }
+
+ void setTokens(ArrayRef<Token> Tokens, llvm::BumpPtrAllocator &PPAllocator) {
+ assert(
+ !IsDefinitionLengthCached &&
+ "Changing replacement tokens after definition length got calculated");
+ assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
+ "Token list already set!");
+ if (Tokens.empty())
+ return;
+
+ NumReplacementTokens = Tokens.size();
+ Token *NewReplacementTokens = PPAllocator.Allocate<Token>(Tokens.size());
+ std::copy(Tokens.begin(), Tokens.end(), NewReplacementTokens);
+ ReplacementTokens = NewReplacementTokens;
+ }
+
+ /// Return true if this macro is enabled.
+ ///
+ /// In other words, that we are not currently in an expansion of this macro.
+ bool isEnabled() const { return !IsDisabled; }
+
+ void EnableMacro() {
+ assert(IsDisabled && "Cannot enable an already-enabled macro!");
+ IsDisabled = false;
+ }
+
+ void DisableMacro() {
+ assert(!IsDisabled && "Cannot disable an already-disabled macro!");
+ IsDisabled = true;
+ }
+
+ /// Determine whether this macro was used for a header guard.
+ bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }
+
+ void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }
+
+ void dump() const;
+
+private:
+ friend class Preprocessor;
+
+ unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
+};
+
+/// Encapsulates changes to the "macros namespace" (the location where
+/// the macro name became active, the location where it was undefined, etc.).
+///
+/// MacroDirectives, associated with an identifier, are used to model the macro
+/// history. Usually a macro definition (MacroInfo) is where a macro name
+/// becomes active (MacroDirective) but #pragma push_macro / pop_macro can
+/// create additional DefMacroDirectives for the same MacroInfo.
+class MacroDirective {
+public:
+ enum Kind {
+ MD_Define,
+ MD_Undefine,
+ MD_Visibility
+ };
+
+protected:
+ /// Previous macro directive for the same identifier, or nullptr.
+ MacroDirective *Previous = nullptr;
+
+ SourceLocation Loc;
+
+ /// MacroDirective kind.
+ unsigned MDKind : 2;
+
+ /// True if the macro directive was loaded from a PCH file.
+ unsigned IsFromPCH : 1;
+
+ // Used by VisibilityMacroDirective ----------------------------------------//
+
+ /// Whether the macro has public visibility (when described in a
+ /// module).
+ unsigned IsPublic : 1;
+
+ MacroDirective(Kind K, SourceLocation Loc)
+ : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {}
+
+public:
+ Kind getKind() const { return Kind(MDKind); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// Set previous definition of the macro with the same name.
+ void setPrevious(MacroDirective *Prev) { Previous = Prev; }
+
+ /// Get previous definition of the macro with the same name.
+ const MacroDirective *getPrevious() const { return Previous; }
+
+ /// Get previous definition of the macro with the same name.
+ MacroDirective *getPrevious() { return Previous; }
+
+ /// Return true if the macro directive was loaded from a PCH file.
+ bool isFromPCH() const { return IsFromPCH; }
+
+ void setIsFromPCH() { IsFromPCH = true; }
+
+ class DefInfo {
+ DefMacroDirective *DefDirective = nullptr;
+ SourceLocation UndefLoc;
+ bool IsPublic = true;
+
+ public:
+ DefInfo() = default;
+ DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
+ bool isPublic)
+ : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
+
+ const DefMacroDirective *getDirective() const { return DefDirective; }
+ DefMacroDirective *getDirective() { return DefDirective; }
+
+ inline SourceLocation getLocation() const;
+ inline MacroInfo *getMacroInfo();
+
+ const MacroInfo *getMacroInfo() const {
+ return const_cast<DefInfo *>(this)->getMacroInfo();
+ }
+
+ SourceLocation getUndefLocation() const { return UndefLoc; }
+ bool isUndefined() const { return UndefLoc.isValid(); }
+
+ bool isPublic() const { return IsPublic; }
+
+ bool isValid() const { return DefDirective != nullptr; }
+ bool isInvalid() const { return !isValid(); }
+
+ explicit operator bool() const { return isValid(); }
+
+ inline DefInfo getPreviousDefinition();
+
+ const DefInfo getPreviousDefinition() const {
+ return const_cast<DefInfo *>(this)->getPreviousDefinition();
+ }
+ };
+
+ /// Traverses the macro directives history and returns the next
+ /// macro definition directive along with info about its undefined location
+ /// (if there is one) and if it is public or private.
+ DefInfo getDefinition();
+ const DefInfo getDefinition() const {
+ return const_cast<MacroDirective *>(this)->getDefinition();
+ }
+
+ bool isDefined() const {
+ if (const DefInfo Def = getDefinition())
+ return !Def.isUndefined();
+ return false;
+ }
+
+ const MacroInfo *getMacroInfo() const {
+ return getDefinition().getMacroInfo();
+ }
+ MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
+
+ /// Find macro definition active in the specified source location. If
+ /// this macro was not defined there, return NULL.
+ const DefInfo findDirectiveAtLoc(SourceLocation L,
+ const SourceManager &SM) const;
+
+ void dump() const;
+
+ static bool classof(const MacroDirective *) { return true; }
+};
+
+/// A directive for a defined macro or a macro imported from a module.
+class DefMacroDirective : public MacroDirective {
+ MacroInfo *Info;
+
+public:
+ DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
+ : MacroDirective(MD_Define, Loc), Info(MI) {
+ assert(MI && "MacroInfo is null");
+ }
+ explicit DefMacroDirective(MacroInfo *MI)
+ : DefMacroDirective(MI, MI->getDefinitionLoc()) {}
+
+ /// The data for the macro definition.
+ const MacroInfo *getInfo() const { return Info; }
+ MacroInfo *getInfo() { return Info; }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Define;
+ }
+
+ static bool classof(const DefMacroDirective *) { return true; }
+};
+
+/// A directive for an undefined macro.
+class UndefMacroDirective : public MacroDirective {
+public:
+ explicit UndefMacroDirective(SourceLocation UndefLoc)
+ : MacroDirective(MD_Undefine, UndefLoc) {
+ assert(UndefLoc.isValid() && "Invalid UndefLoc!");
+ }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Undefine;
+ }
+
+ static bool classof(const UndefMacroDirective *) { return true; }
+};
+
+/// A directive for setting the module visibility of a macro.
+class VisibilityMacroDirective : public MacroDirective {
+public:
+ explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
+ : MacroDirective(MD_Visibility, Loc) {
+ IsPublic = Public;
+ }
+
+ /// Determine whether this macro is part of the public API of its
+ /// module.
+ bool isPublic() const { return IsPublic; }
+
+ static bool classof(const MacroDirective *MD) {
+ return MD->getKind() == MD_Visibility;
+ }
+
+ static bool classof(const VisibilityMacroDirective *) { return true; }
+};
+
+inline SourceLocation MacroDirective::DefInfo::getLocation() const {
+ if (isInvalid())
+ return {};
+ return DefDirective->getLocation();
+}
+
+inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
+ if (isInvalid())
+ return nullptr;
+ return DefDirective->getInfo();
+}
+
+inline MacroDirective::DefInfo
+MacroDirective::DefInfo::getPreviousDefinition() {
+ if (isInvalid() || DefDirective->getPrevious() == nullptr)
+ return {};
+ return DefDirective->getPrevious()->getDefinition();
+}
+
+/// Represents a macro directive exported by a module.
+///
+/// There's an instance of this class for every macro #define or #undef that is
+/// the final directive for a macro name within a module. These entities also
+/// represent the macro override graph.
+///
+/// These are stored in a FoldingSet in the preprocessor.
+class ModuleMacro : public llvm::FoldingSetNode {
+ friend class Preprocessor;
+
+ /// The name defined by the macro.
+ IdentifierInfo *II;
+
+ /// The body of the #define, or nullptr if this is a #undef.
+ MacroInfo *Macro;
+
+ /// The module that exports this macro.
+ Module *OwningModule;
+
+ /// The number of module macros that override this one.
+ unsigned NumOverriddenBy = 0;
+
+ /// The number of modules whose macros are directly overridden by this one.
+ unsigned NumOverrides;
+
+ ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides)
+ : II(II), Macro(Macro), OwningModule(OwningModule),
+ NumOverrides(Overrides.size()) {
+ std::copy(Overrides.begin(), Overrides.end(),
+ reinterpret_cast<ModuleMacro **>(this + 1));
+ }
+
+public:
+ static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
+ IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides);
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ return Profile(ID, OwningModule, II);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
+ const IdentifierInfo *II) {
+ ID.AddPointer(OwningModule);
+ ID.AddPointer(II);
+ }
+
+ /// Get the name of the macro.
+ IdentifierInfo *getName() const { return II; }
+
+ /// Get the ID of the module that exports this macro.
+ Module *getOwningModule() const { return OwningModule; }
+
+ /// Get definition for this exported #define, or nullptr if this
+ /// represents a #undef.
+ MacroInfo *getMacroInfo() const { return Macro; }
+
+ /// Iterators over the overridden module IDs.
+ /// \{
+ using overrides_iterator = ModuleMacro *const *;
+
+ overrides_iterator overrides_begin() const {
+ return reinterpret_cast<overrides_iterator>(this + 1);
+ }
+
+ overrides_iterator overrides_end() const {
+ return overrides_begin() + NumOverrides;
+ }
+
+ ArrayRef<ModuleMacro *> overrides() const {
+ return llvm::ArrayRef(overrides_begin(), overrides_end());
+ }
+ /// \}
+
+ /// Get the number of macros that override this one.
+ unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
+};
+
+/// A description of the current definition of a macro.
+///
+/// The definition of a macro comprises a set of (at least one) defining
+/// entities, which are either local MacroDirectives or imported ModuleMacros.
+class MacroDefinition {
+ llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
+ ArrayRef<ModuleMacro *> ModuleMacros;
+
+public:
+ MacroDefinition() = default;
+ MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
+ bool IsAmbiguous)
+ : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
+
+ /// Determine whether there is a definition of this macro.
+ explicit operator bool() const {
+ return getLocalDirective() || !ModuleMacros.empty();
+ }
+
+ /// Get the MacroInfo that should be used for this definition.
+ MacroInfo *getMacroInfo() const {
+ if (!ModuleMacros.empty())
+ return ModuleMacros.back()->getMacroInfo();
+ if (auto *MD = getLocalDirective())
+ return MD->getMacroInfo();
+ return nullptr;
+ }
+
+ /// \c true if the definition is ambiguous, \c false otherwise.
+ bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
+
+ /// Get the latest non-imported, non-\#undef'd macro definition
+ /// for this macro.
+ DefMacroDirective *getLocalDirective() const {
+ return LatestLocalAndAmbiguous.getPointer();
+ }
+
+ /// Get the active module macros for this macro.
+ ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
+
+ template <typename Fn> void forAllDefinitions(Fn F) const {
+ if (auto *MD = getLocalDirective())
+ F(MD->getMacroInfo());
+ for (auto *MM : getModuleMacros())
+ F(MM->getMacroInfo());
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_MACROINFO_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/ModuleLoader.h b/contrib/libs/clang16/include/clang/Lex/ModuleLoader.h
new file mode 100644
index 0000000000..ef6108e3ff
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/ModuleLoader.h
@@ -0,0 +1,203 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- ModuleLoader.h - Module Loader Interface -----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ModuleLoader interface, which is responsible for
+// loading named modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MODULELOADER_H
+#define LLVM_CLANG_LEX_MODULELOADER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/StringRef.h"
+#include <utility>
+
+namespace clang {
+
+class GlobalModuleIndex;
+class IdentifierInfo;
+
+/// A sequence of identifier/location pairs used to describe a particular
+/// module or submodule, e.g., std.vector.
+using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>;
+
+/// Describes the result of attempting to load a module.
+class ModuleLoadResult {
+public:
+ enum LoadResultKind {
+ // We either succeeded or failed to load the named module.
+ Normal,
+
+ // The module exists, but does not actually contain the named submodule.
+ // This should only happen if the named submodule was inferred from an
+ // umbrella directory, but not actually part of the umbrella header.
+ MissingExpected,
+
+ // The module exists but cannot be imported due to a configuration mismatch.
+ ConfigMismatch,
+ };
+ llvm::PointerIntPair<Module *, 2, LoadResultKind> Storage;
+
+ ModuleLoadResult() = default;
+ ModuleLoadResult(Module *M) : Storage(M, Normal) {}
+ ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
+ ModuleLoadResult(Module *M, LoadResultKind Kind) : Storage(M, Kind) {}
+
+ operator bool() const {
+ return Storage.getInt() == Normal && Storage.getPointer();
+ }
+
+ operator Module *() const { return Storage.getPointer(); }
+
+ /// Determines whether this is a normal return, whether or not loading the
+ /// module was successful.
+ bool isNormal() const { return Storage.getInt() == Normal; }
+
+ /// Determines whether the module, which failed to load, was
+ /// actually a submodule that we expected to see (based on implying the
+ /// submodule from header structure), but didn't materialize in the actual
+ /// module.
+ bool isMissingExpected() const { return Storage.getInt() == MissingExpected; }
+
+ /// Determines whether the module failed to load due to a configuration
+ /// mismatch with an explicitly-named .pcm file from the command line.
+ bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; }
+};
+
+/// Abstract interface for a module loader.
+///
+/// This abstract interface describes a module loader, which is responsible
+/// for resolving a module name (e.g., "std") to an actual module file, and
+/// then loading that module.
+class ModuleLoader {
+ // Building a module if true.
+ bool BuildingModule;
+
+public:
+ explicit ModuleLoader(bool BuildingModule = false)
+ : BuildingModule(BuildingModule) {}
+
+ virtual ~ModuleLoader();
+
+ /// Returns true if this instance is building a module.
+ bool buildingModule() const {
+ return BuildingModule;
+ }
+
+ /// Flag indicating whether this instance is building a module.
+ void setBuildingModule(bool BuildingModuleFlag) {
+ BuildingModule = BuildingModuleFlag;
+ }
+
+ /// Attempt to load the given module.
+ ///
+ /// This routine attempts to load the module described by the given
+ /// parameters. If there is a module cache, this may implicitly compile the
+ /// module before loading it.
+ ///
+ /// \param ImportLoc The location of the 'import' keyword.
+ ///
+ /// \param Path The identifiers (and their locations) of the module
+ /// "path", e.g., "std.vector" would be split into "std" and "vector".
+ ///
+ /// \param Visibility The visibility provided for the names in the loaded
+ /// module.
+ ///
+ /// \param IsInclusionDirective Indicates that this module is being loaded
+ /// implicitly, due to the presence of an inclusion directive. Otherwise,
+ /// it is being loaded due to an import declaration.
+ ///
+ /// \returns If successful, returns the loaded module. Otherwise, returns
+ /// NULL to indicate that the module could not be loaded.
+ virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
+ ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) = 0;
+
+ /// Attempt to create the given module from the specified source buffer.
+ /// Does not load the module or make any submodule visible; for that, use
+ /// loadModule and makeModuleVisible.
+ ///
+ /// \param Loc The location at which to create the module.
+ /// \param ModuleName The name of the module to create.
+ /// \param Source The source of the module: a (preprocessed) module map.
+ virtual void createModuleFromSource(SourceLocation Loc, StringRef ModuleName,
+ StringRef Source) = 0;
+
+ /// Make the given module visible.
+ virtual void makeModuleVisible(Module *Mod,
+ Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc) = 0;
+
+ /// Load, create, or return global module.
+ /// This function returns an existing global module index, if one
+ /// had already been loaded or created, or loads one if it
+ /// exists, or creates one if it doesn't exist.
+ /// Also, importantly, if the index doesn't cover all the modules
+ /// in the module map, it will be update to do so here, because
+ /// of its use in searching for needed module imports and
+ /// associated fixit messages.
+ /// \param TriggerLoc The location for what triggered the load.
+ /// \returns Returns null if load failed.
+ virtual GlobalModuleIndex *loadGlobalModuleIndex(
+ SourceLocation TriggerLoc) = 0;
+
+ /// Check global module index for missing imports.
+ /// \param Name The symbol name to look for.
+ /// \param TriggerLoc The location for what triggered the load.
+ /// \returns Returns true if any modules with that symbol found.
+ virtual bool lookupMissingImports(StringRef Name,
+ SourceLocation TriggerLoc) = 0;
+
+ bool HadFatalFailure = false;
+};
+
+/// A module loader that doesn't know how to create or load modules.
+class TrivialModuleLoader : public ModuleLoader {
+public:
+ ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+ Module::NameVisibilityKind Visibility,
+ bool IsInclusionDirective) override {
+ return {};
+ }
+
+ void createModuleFromSource(SourceLocation ImportLoc, StringRef ModuleName,
+ StringRef Source) override {}
+
+ void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
+ SourceLocation ImportLoc) override {}
+
+ GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override {
+ return nullptr;
+ }
+
+ bool lookupMissingImports(StringRef Name,
+ SourceLocation TriggerLoc) override {
+ return false;
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_MODULELOADER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/ModuleMap.h b/contrib/libs/clang16/include/clang/Lex/ModuleMap.h
new file mode 100644
index 0000000000..0791e0b5de
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/ModuleMap.h
@@ -0,0 +1,757 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- ModuleMap.h - Describe the layout of modules -------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ModuleMap interface, which describes the layout of a
+// module as it relates to headers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MODULEMAP_H
+#define LLVM_CLANG_LEX_MODULEMAP_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/Twine.h"
+#include <ctime>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+
+namespace clang {
+
+class DiagnosticsEngine;
+class DirectoryEntry;
+class FileEntry;
+class FileManager;
+class HeaderSearch;
+class SourceManager;
+
+/// A mechanism to observe the actions of the module map parser as it
+/// reads module map files.
+class ModuleMapCallbacks {
+ virtual void anchor();
+
+public:
+ virtual ~ModuleMapCallbacks() = default;
+
+ /// Called when a module map file has been read.
+ ///
+ /// \param FileStart A SourceLocation referring to the start of the file's
+ /// contents.
+ /// \param File The file itself.
+ /// \param IsSystem Whether this is a module map from a system include path.
+ virtual void moduleMapFileRead(SourceLocation FileStart,
+ const FileEntry &File, bool IsSystem) {}
+
+ /// Called when a header is added during module map parsing.
+ ///
+ /// \param Filename The header file itself.
+ virtual void moduleMapAddHeader(StringRef Filename) {}
+
+ /// Called when an umbrella header is added during module map parsing.
+ ///
+ /// \param FileMgr FileManager instance
+ /// \param Header The umbrella header to collect.
+ virtual void moduleMapAddUmbrellaHeader(FileManager *FileMgr,
+ const FileEntry *Header) {}
+};
+
+class ModuleMap {
+ SourceManager &SourceMgr;
+ DiagnosticsEngine &Diags;
+ const LangOptions &LangOpts;
+ const TargetInfo *Target;
+ HeaderSearch &HeaderInfo;
+
+ llvm::SmallVector<std::unique_ptr<ModuleMapCallbacks>, 1> Callbacks;
+
+ /// The directory used for Clang-supplied, builtin include headers,
+ /// such as "stdint.h".
+ const DirectoryEntry *BuiltinIncludeDir = nullptr;
+
+ /// Language options used to parse the module map itself.
+ ///
+ /// These are always simple C language options.
+ LangOptions MMapLangOpts;
+
+ /// The module that the main source file is associated with (the module
+ /// named LangOpts::CurrentModule, if we've loaded it).
+ Module *SourceModule = nullptr;
+
+ /// Submodules of the current module that have not yet been attached to it.
+ /// (Ownership is transferred if/when we create an enclosing module.)
+ llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
+
+ /// The top-level modules that are known.
+ llvm::StringMap<Module *> Modules;
+
+ /// Module loading cache that includes submodules, indexed by IdentifierInfo.
+ /// nullptr is stored for modules that are known to fail to load.
+ llvm::DenseMap<const IdentifierInfo *, Module *> CachedModuleLoads;
+
+ /// Shadow modules created while building this module map.
+ llvm::SmallVector<Module*, 2> ShadowModules;
+
+ /// The number of modules we have created in total.
+ unsigned NumCreatedModules = 0;
+
+ /// In case a module has a export_as entry, it might have a pending link
+ /// name to be determined if that module is imported.
+ llvm::StringMap<llvm::StringSet<>> PendingLinkAsModule;
+
+public:
+ /// Use PendingLinkAsModule information to mark top level link names that
+ /// are going to be replaced by export_as aliases.
+ void resolveLinkAsDependencies(Module *Mod);
+
+ /// Make module to use export_as as the link dependency name if enough
+ /// information is available or add it to a pending list otherwise.
+ void addLinkAsDependency(Module *Mod);
+
+ /// Flags describing the role of a module header.
+ enum ModuleHeaderRole {
+ /// This header is normally included in the module.
+ NormalHeader = 0x0,
+
+ /// This header is included but private.
+ PrivateHeader = 0x1,
+
+ /// This header is part of the module (for layering purposes) but
+ /// should be textually included.
+ TextualHeader = 0x2,
+
+ /// This header is explicitly excluded from the module.
+ ExcludedHeader = 0x4,
+
+ // Caution: Adding an enumerator needs other changes.
+ // Adjust the number of bits for KnownHeader::Storage.
+ // Adjust the HeaderFileInfoTrait::ReadData streaming.
+ // Adjust the HeaderFileInfoTrait::EmitData streaming.
+ // Adjust ModuleMap::addHeader.
+ };
+
+ /// Convert a header kind to a role. Requires Kind to not be HK_Excluded.
+ static ModuleHeaderRole headerKindToRole(Module::HeaderKind Kind);
+
+ /// Convert a header role to a kind.
+ static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role);
+
+ /// Check if the header with the given role is a modular one.
+ static bool isModular(ModuleHeaderRole Role);
+
+ /// A header that is known to reside within a given module,
+ /// whether it was included or excluded.
+ class KnownHeader {
+ llvm::PointerIntPair<Module *, 3, ModuleHeaderRole> Storage;
+
+ public:
+ KnownHeader() : Storage(nullptr, NormalHeader) {}
+ KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) {}
+
+ friend bool operator==(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage == B.Storage;
+ }
+ friend bool operator!=(const KnownHeader &A, const KnownHeader &B) {
+ return A.Storage != B.Storage;
+ }
+
+ /// Retrieve the module the header is stored in.
+ Module *getModule() const { return Storage.getPointer(); }
+
+ /// The role of this header within the module.
+ ModuleHeaderRole getRole() const { return Storage.getInt(); }
+
+ /// Whether this header is available in the module.
+ bool isAvailable() const {
+ return getRole() != ExcludedHeader && getModule()->isAvailable();
+ }
+
+ /// Whether this header is accessible from the specified module.
+ bool isAccessibleFrom(Module *M) const {
+ return !(getRole() & PrivateHeader) ||
+ (M && M->getTopLevelModule() == getModule()->getTopLevelModule());
+ }
+
+ // Whether this known header is valid (i.e., it has an
+ // associated module).
+ explicit operator bool() const {
+ return Storage.getPointer() != nullptr;
+ }
+ };
+
+ using AdditionalModMapsSet = llvm::SmallPtrSet<const FileEntry *, 1>;
+
+private:
+ friend class ModuleMapParser;
+
+ using HeadersMap =
+ llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>;
+
+ /// Mapping from each header to the module that owns the contents of
+ /// that header.
+ HeadersMap Headers;
+
+ /// Map from file sizes to modules with lazy header directives of that size.
+ mutable llvm::DenseMap<off_t, llvm::TinyPtrVector<Module*>> LazyHeadersBySize;
+
+ /// Map from mtimes to modules with lazy header directives with those mtimes.
+ mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>>
+ LazyHeadersByModTime;
+
+ /// Mapping from directories with umbrella headers to the module
+ /// that is generated from the umbrella header.
+ ///
+ /// This mapping is used to map headers that haven't explicitly been named
+ /// in the module map over to the module that includes them via its umbrella
+ /// header.
+ llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs;
+
+ /// A generation counter that is used to test whether modules of the
+ /// same name may shadow or are illegal redefinitions.
+ ///
+ /// Modules from earlier scopes may shadow modules from later ones.
+ /// Modules from the same scope may not have the same name.
+ unsigned CurrentModuleScopeID = 0;
+
+ llvm::DenseMap<Module *, unsigned> ModuleScopeIDs;
+
+ /// The set of attributes that can be attached to a module.
+ struct Attributes {
+ /// Whether this is a system module.
+ unsigned IsSystem : 1;
+
+ /// Whether this is an extern "C" module.
+ unsigned IsExternC : 1;
+
+ /// Whether this is an exhaustive set of configuration macros.
+ unsigned IsExhaustive : 1;
+
+ /// Whether files in this module can only include non-modular headers
+ /// and headers from used modules.
+ unsigned NoUndeclaredIncludes : 1;
+
+ Attributes()
+ : IsSystem(false), IsExternC(false), IsExhaustive(false),
+ NoUndeclaredIncludes(false) {}
+ };
+
+ /// A directory for which framework modules can be inferred.
+ struct InferredDirectory {
+ /// Whether to infer modules from this directory.
+ unsigned InferModules : 1;
+
+ /// The attributes to use for inferred modules.
+ Attributes Attrs;
+
+ /// If \c InferModules is non-zero, the module map file that allowed
+ /// inferred modules. Otherwise, nullptr.
+ const FileEntry *ModuleMapFile;
+
+ /// The names of modules that cannot be inferred within this
+ /// directory.
+ SmallVector<std::string, 2> ExcludedModules;
+
+ InferredDirectory() : InferModules(false) {}
+ };
+
+ /// A mapping from directories to information about inferring
+ /// framework modules from within those directories.
+ llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories;
+
+ /// A mapping from an inferred module to the module map that allowed the
+ /// inference.
+ llvm::DenseMap<const Module *, const FileEntry *> InferredModuleAllowedBy;
+
+ llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps;
+
+ /// Describes whether we haved parsed a particular file as a module
+ /// map.
+ llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap;
+
+ /// Resolve the given export declaration into an actual export
+ /// declaration.
+ ///
+ /// \param Mod The module in which we're resolving the export declaration.
+ ///
+ /// \param Unresolved The export declaration to resolve.
+ ///
+ /// \param Complain Whether this routine should complain about unresolvable
+ /// exports.
+ ///
+ /// \returns The resolved export declaration, which will have a NULL pointer
+ /// if the export could not be resolved.
+ Module::ExportDecl
+ resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved,
+ bool Complain) const;
+
+ /// Resolve the given module id to an actual module.
+ ///
+ /// \param Id The module-id to resolve.
+ ///
+ /// \param Mod The module in which we're resolving the module-id.
+ ///
+ /// \param Complain Whether this routine should complain about unresolvable
+ /// module-ids.
+ ///
+ /// \returns The resolved module, or null if the module-id could not be
+ /// resolved.
+ Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const;
+
+ /// Add an unresolved header to a module.
+ ///
+ /// \param Mod The module in which we're adding the unresolved header
+ /// directive.
+ /// \param Header The unresolved header directive.
+ /// \param NeedsFramework If Mod is not a framework but a missing header would
+ /// be found in case Mod was, set it to true. False otherwise.
+ void addUnresolvedHeader(Module *Mod,
+ Module::UnresolvedHeaderDirective Header,
+ bool &NeedsFramework);
+
+ /// Look up the given header directive to find an actual header file.
+ ///
+ /// \param M The module in which we're resolving the header directive.
+ /// \param Header The header directive to resolve.
+ /// \param RelativePathName Filled in with the relative path name from the
+ /// module to the resolved header.
+ /// \param NeedsFramework If M is not a framework but a missing header would
+ /// be found in case M was, set it to true. False otherwise.
+ /// \return The resolved file, if any.
+ OptionalFileEntryRef
+ findHeader(Module *M, const Module::UnresolvedHeaderDirective &Header,
+ SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework);
+
+ /// Resolve the given header directive.
+ ///
+ /// \param M The module in which we're resolving the header directive.
+ /// \param Header The header directive to resolve.
+ /// \param NeedsFramework If M is not a framework but a missing header would
+ /// be found in case M was, set it to true. False otherwise.
+ void resolveHeader(Module *M, const Module::UnresolvedHeaderDirective &Header,
+ bool &NeedsFramework);
+
+ /// Attempt to resolve the specified header directive as naming a builtin
+ /// header.
+ /// \return \c true if a corresponding builtin header was found.
+ bool resolveAsBuiltinHeader(Module *M,
+ const Module::UnresolvedHeaderDirective &Header);
+
+ /// Looks up the modules that \p File corresponds to.
+ ///
+ /// If \p File represents a builtin header within Clang's builtin include
+ /// directory, this also loads all of the module maps to see if it will get
+ /// associated with a specific module (e.g. in /usr/include).
+ HeadersMap::iterator findKnownHeader(const FileEntry *File);
+
+ /// Searches for a module whose umbrella directory contains \p File.
+ ///
+ /// \param File The header to search for.
+ ///
+ /// \param IntermediateDirs On success, contains the set of directories
+ /// searched before finding \p File.
+ KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File,
+ SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs);
+
+ /// Given that \p File is not in the Headers map, look it up within
+ /// umbrella directories and find or create a module for it.
+ KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File);
+
+ /// A convenience method to determine if \p File is (possibly nested)
+ /// in an umbrella directory.
+ bool isHeaderInUmbrellaDirs(const FileEntry *File) {
+ SmallVector<const DirectoryEntry *, 2> IntermediateDirs;
+ return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs));
+ }
+
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ Attributes Attrs, Module *Parent);
+
+public:
+ /// Construct a new module map.
+ ///
+ /// \param SourceMgr The source manager used to find module files and headers.
+ /// This source manager should be shared with the header-search mechanism,
+ /// since they will refer to the same headers.
+ ///
+ /// \param Diags A diagnostic engine used for diagnostics.
+ ///
+ /// \param LangOpts Language options for this translation unit.
+ ///
+ /// \param Target The target for this translation unit.
+ ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
+ const LangOptions &LangOpts, const TargetInfo *Target,
+ HeaderSearch &HeaderInfo);
+
+ /// Destroy the module map.
+ ~ModuleMap();
+
+ /// Set the target information.
+ void setTarget(const TargetInfo &Target);
+
+ /// Set the directory that contains Clang-supplied include
+ /// files, such as our stdarg.h or tgmath.h.
+ void setBuiltinIncludeDir(const DirectoryEntry *Dir) {
+ BuiltinIncludeDir = Dir;
+ }
+
+ /// Get the directory that contains Clang-supplied include files.
+ const DirectoryEntry *getBuiltinDir() const {
+ return BuiltinIncludeDir;
+ }
+
+ /// Is this a compiler builtin header?
+ static bool isBuiltinHeader(StringRef FileName);
+ bool isBuiltinHeader(const FileEntry *File);
+
+ /// Add a module map callback.
+ void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) {
+ Callbacks.push_back(std::move(Callback));
+ }
+
+ /// Retrieve the module that owns the given header file, if any. Note that
+ /// this does not implicitly load module maps, except for builtin headers,
+ /// and does not consult the external source. (Those checks are the
+ /// responsibility of \ref HeaderSearch.)
+ ///
+ /// \param File The header file that is likely to be included.
+ ///
+ /// \param AllowTextual If \c true and \p File is a textual header, return
+ /// its owning module. Otherwise, no KnownHeader will be returned if the
+ /// file is only known as a textual header.
+ ///
+ /// \returns The module KnownHeader, which provides the module that owns the
+ /// given header file. The KnownHeader is default constructed to indicate
+ /// that no module owns this header file.
+ KnownHeader findModuleForHeader(const FileEntry *File,
+ bool AllowTextual = false,
+ bool AllowExcluded = false);
+
+ /// Retrieve all the modules that contain the given header file. Note that
+ /// this does not implicitly load module maps, except for builtin headers,
+ /// and does not consult the external source. (Those checks are the
+ /// responsibility of \ref HeaderSearch.)
+ ///
+ /// Typically, \ref findModuleForHeader should be used instead, as it picks
+ /// the preferred module for the header.
+ ArrayRef<KnownHeader> findAllModulesForHeader(const FileEntry *File);
+
+ /// Like \ref findAllModulesForHeader, but do not attempt to infer module
+ /// ownership from umbrella headers if we've not already done so.
+ ArrayRef<KnownHeader>
+ findResolvedModulesForHeader(const FileEntry *File) const;
+
+ /// Resolve all lazy header directives for the specified file.
+ ///
+ /// This ensures that the HeaderFileInfo on HeaderSearch is up to date. This
+ /// is effectively internal, but is exposed so HeaderSearch can call it.
+ void resolveHeaderDirectives(const FileEntry *File) const;
+
+ /// Resolve lazy header directives for the specified module. If File is
+ /// provided, only headers with same size and modtime are resolved. If File
+ /// is not set, all headers are resolved.
+ void resolveHeaderDirectives(Module *Mod,
+ std::optional<const FileEntry *> File) const;
+
+ /// Reports errors if a module must not include a specific file.
+ ///
+ /// \param RequestingModule The module including a file.
+ ///
+ /// \param RequestingModuleIsModuleInterface \c true if the inclusion is in
+ /// the interface of RequestingModule, \c false if it's in the
+ /// implementation of RequestingModule. Value is ignored and
+ /// meaningless if RequestingModule is nullptr.
+ ///
+ /// \param FilenameLoc The location of the inclusion's filename.
+ ///
+ /// \param Filename The included filename as written.
+ ///
+ /// \param File The included file.
+ void diagnoseHeaderInclusion(Module *RequestingModule,
+ bool RequestingModuleIsModuleInterface,
+ SourceLocation FilenameLoc, StringRef Filename,
+ FileEntryRef File);
+
+ /// Determine whether the given header is part of a module
+ /// marked 'unavailable'.
+ bool isHeaderInUnavailableModule(const FileEntry *Header) const;
+
+ /// Determine whether the given header is unavailable as part
+ /// of the specified module.
+ bool isHeaderUnavailableInModule(const FileEntry *Header,
+ const Module *RequestingModule) const;
+
+ /// Retrieve a module with the given name.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \returns The named module, if known; otherwise, returns null.
+ Module *findModule(StringRef Name) const;
+
+ /// Retrieve a module with the given name using lexical name lookup,
+ /// starting at the given context.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \param Context The module context, from which we will perform lexical
+ /// name lookup.
+ ///
+ /// \returns The named module, if known; otherwise, returns null.
+ Module *lookupModuleUnqualified(StringRef Name, Module *Context) const;
+
+ /// Retrieve a module with the given name within the given context,
+ /// using direct (qualified) name lookup.
+ ///
+ /// \param Name The name of the module to look up.
+ ///
+ /// \param Context The module for which we will look for a submodule. If
+ /// null, we will look for a top-level module.
+ ///
+ /// \returns The named submodule, if known; otherwose, returns null.
+ Module *lookupModuleQualified(StringRef Name, Module *Context) const;
+
+ /// Find a new module or submodule, or create it if it does not already
+ /// exist.
+ ///
+ /// \param Name The name of the module to find or create.
+ ///
+ /// \param Parent The module that will act as the parent of this submodule,
+ /// or nullptr to indicate that this is a top-level module.
+ ///
+ /// \param IsFramework Whether this is a framework module.
+ ///
+ /// \param IsExplicit Whether this is an explicit submodule.
+ ///
+ /// \returns The found or newly-created module, along with a boolean value
+ /// that will be true if the module is newly-created.
+ std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent,
+ bool IsFramework,
+ bool IsExplicit);
+
+ /// Create a global module fragment for a C++ module unit.
+ ///
+ /// We model the global module fragment as a submodule of the module
+ /// interface unit. Unfortunately, we can't create the module interface
+ /// unit's Module until later, because we don't know what it will be called
+ /// usually. See C++20 [module.unit]/7.2 for the case we could know its
+ /// parent.
+ Module *createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
+ Module *Parent = nullptr);
+
+ /// Create a global module fragment for a C++ module interface unit.
+ Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
+ SourceLocation Loc);
+
+ /// Create a new module for a C++ module interface unit.
+ /// The module must not already exist, and will be configured for the current
+ /// compilation.
+ ///
+ /// Note that this also sets the current module to the newly-created module.
+ ///
+ /// \returns The newly-created module.
+ Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
+
+ /// Create a C++20 header unit.
+ Module *createHeaderUnit(SourceLocation Loc, StringRef Name,
+ Module::Header H);
+
+ /// Infer the contents of a framework module map from the given
+ /// framework directory.
+ Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
+ bool IsSystem, Module *Parent);
+
+ /// Create a new top-level module that is shadowed by
+ /// \p ShadowingModule.
+ Module *createShadowedModule(StringRef Name, bool IsFramework,
+ Module *ShadowingModule);
+
+ /// Creates a new declaration scope for module names, allowing
+ /// previously defined modules to shadow definitions from the new scope.
+ ///
+ /// \note Module names from earlier scopes will shadow names from the new
+ /// scope, which is the opposite of how shadowing works for variables.
+ void finishModuleDeclarationScope() { CurrentModuleScopeID += 1; }
+
+ bool mayShadowNewModule(Module *ExistingModule) {
+ assert(!ExistingModule->Parent && "expected top-level module");
+ assert(ModuleScopeIDs.count(ExistingModule) && "unknown module");
+ return ModuleScopeIDs[ExistingModule] < CurrentModuleScopeID;
+ }
+
+ /// Check whether a framework module can be inferred in the given directory.
+ bool canInferFrameworkModule(const DirectoryEntry *Dir) const {
+ auto It = InferredDirectories.find(Dir);
+ return It != InferredDirectories.end() && It->getSecond().InferModules;
+ }
+
+ /// Retrieve the module map file containing the definition of the given
+ /// module.
+ ///
+ /// \param Module The module whose module map file will be returned, if known.
+ ///
+ /// \returns The file entry for the module map file containing the given
+ /// module, or nullptr if the module definition was inferred.
+ OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const;
+
+ /// Get the module map file that (along with the module name) uniquely
+ /// identifies this module.
+ ///
+ /// The particular module that \c Name refers to may depend on how the module
+ /// was found in header search. However, the combination of \c Name and
+ /// this module map will be globally unique for top-level modules. In the case
+ /// of inferred modules, returns the module map that allowed the inference
+ /// (e.g. contained 'module *'). Otherwise, returns
+ /// getContainingModuleMapFile().
+ OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const;
+
+ void setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap);
+
+ /// Canonicalize \p Path in a manner suitable for a module map file. In
+ /// particular, this canonicalizes the parent directory separately from the
+ /// filename so that it does not affect header resolution relative to the
+ /// modulemap.
+ ///
+ /// \returns an error code if any filesystem operations failed. In this case
+ /// \p Path is not modified.
+ std::error_code canonicalizeModuleMapPath(SmallVectorImpl<char> &Path);
+
+ /// Get any module map files other than getModuleMapFileForUniquing(M)
+ /// that define submodules of a top-level module \p M. This is cheaper than
+ /// getting the module map file for each submodule individually, since the
+ /// expected number of results is very small.
+ AdditionalModMapsSet *getAdditionalModuleMapFiles(const Module *M) {
+ auto I = AdditionalModMaps.find(M);
+ if (I == AdditionalModMaps.end())
+ return nullptr;
+ return &I->second;
+ }
+
+ void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap);
+
+ /// Resolve all of the unresolved exports in the given module.
+ ///
+ /// \param Mod The module whose exports should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving exports,
+ /// false otherwise.
+ bool resolveExports(Module *Mod, bool Complain);
+
+ /// Resolve all of the unresolved uses in the given module.
+ ///
+ /// \param Mod The module whose uses should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving uses,
+ /// false otherwise.
+ bool resolveUses(Module *Mod, bool Complain);
+
+ /// Resolve all of the unresolved conflicts in the given module.
+ ///
+ /// \param Mod The module whose conflicts should be resolved.
+ ///
+ /// \param Complain Whether to emit diagnostics for failures.
+ ///
+ /// \returns true if any errors were encountered while resolving conflicts,
+ /// false otherwise.
+ bool resolveConflicts(Module *Mod, bool Complain);
+
+ /// Sets the umbrella header of the given module to the given
+ /// header.
+ void setUmbrellaHeader(Module *Mod, FileEntryRef UmbrellaHeader,
+ const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory);
+
+ /// Sets the umbrella directory of the given module to the given
+ /// directory.
+ void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
+ const Twine &NameAsWritten,
+ const Twine &PathRelativeToRootModuleDirectory);
+
+ /// Adds this header to the given module.
+ /// \param Role The role of the header wrt the module.
+ void addHeader(Module *Mod, Module::Header Header,
+ ModuleHeaderRole Role, bool Imported = false);
+
+ /// Parse the given module map file, and record any modules we
+ /// encounter.
+ ///
+ /// \param File The file to be parsed.
+ ///
+ /// \param IsSystem Whether this module map file is in a system header
+ /// directory, and therefore should be considered a system module.
+ ///
+ /// \param HomeDir The directory in which relative paths within this module
+ /// map file will be resolved.
+ ///
+ /// \param ID The FileID of the file to process, if we've already entered it.
+ ///
+ /// \param Offset [inout] On input the offset at which to start parsing. On
+ /// output, the offset at which the module map terminated.
+ ///
+ /// \param ExternModuleLoc The location of the "extern module" declaration
+ /// that caused us to load this module map file, if any.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool parseModuleMapFile(const FileEntry *File, bool IsSystem,
+ const DirectoryEntry *HomeDir,
+ FileID ID = FileID(), unsigned *Offset = nullptr,
+ SourceLocation ExternModuleLoc = SourceLocation());
+
+ /// Dump the contents of the module map, for debugging purposes.
+ void dump();
+
+ using module_iterator = llvm::StringMap<Module *>::const_iterator;
+
+ module_iterator module_begin() const { return Modules.begin(); }
+ module_iterator module_end() const { return Modules.end(); }
+ llvm::iterator_range<module_iterator> modules() const {
+ return {module_begin(), module_end()};
+ }
+
+ /// Cache a module load. M might be nullptr.
+ void cacheModuleLoad(const IdentifierInfo &II, Module *M) {
+ CachedModuleLoads[&II] = M;
+ }
+
+ /// Return a cached module load.
+ std::optional<Module *> getCachedModuleLoad(const IdentifierInfo &II) {
+ auto I = CachedModuleLoads.find(&II);
+ if (I == CachedModuleLoads.end())
+ return std::nullopt;
+ return I->second;
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_MODULEMAP_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/MultipleIncludeOpt.h b/contrib/libs/clang16/include/clang/Lex/MultipleIncludeOpt.h
new file mode 100644
index 0000000000..78cf69fd74
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/MultipleIncludeOpt.h
@@ -0,0 +1,191 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- MultipleIncludeOpt.h - Header Multiple-Include Optzn ---*- 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
+/// Defines the MultipleIncludeOpt interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H
+#define LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+class IdentifierInfo;
+
+/// Implements the simple state machine that the Lexer class uses to
+/// detect files subject to the 'multiple-include' optimization.
+///
+/// The public methods in this class are triggered by various
+/// events that occur when a file is lexed, and after the entire file is lexed,
+/// information about which macro (if any) controls the header is returned.
+class MultipleIncludeOpt {
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final \#endif is parsed this is reset back
+ /// to false, that way any tokens before the first \#ifdef or after the last
+ /// \#endif can be easily detected.
+ bool ReadAnyTokens;
+
+ /// ImmediatelyAfterTopLevelIfndef - This is true when the only tokens
+ /// processed in the file so far is an #ifndef and an identifier. Used in
+ /// the detection of header guards in a file.
+ bool ImmediatelyAfterTopLevelIfndef;
+
+ /// ReadAnyTokens - This is set to false when a file is first opened and true
+ /// any time a token is returned to the client or a (non-multiple-include)
+ /// directive is parsed. When the final #endif is parsed this is reset back
+ /// to false, that way any tokens before the first #ifdef or after the last
+ /// #endif can be easily detected.
+ bool DidMacroExpansion;
+
+ /// TheMacro - The controlling macro for a file, if valid.
+ ///
+ const IdentifierInfo *TheMacro;
+
+ /// DefinedMacro - The macro defined right after TheMacro, if any.
+ const IdentifierInfo *DefinedMacro;
+
+ SourceLocation MacroLoc;
+ SourceLocation DefinedLoc;
+public:
+ MultipleIncludeOpt() {
+ ReadAnyTokens = false;
+ ImmediatelyAfterTopLevelIfndef = false;
+ DidMacroExpansion = false;
+ TheMacro = nullptr;
+ DefinedMacro = nullptr;
+ }
+
+ SourceLocation GetMacroLocation() const {
+ return MacroLoc;
+ }
+
+ SourceLocation GetDefinedLocation() const {
+ return DefinedLoc;
+ }
+
+ void resetImmediatelyAfterTopLevelIfndef() {
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ void SetDefinedMacro(IdentifierInfo *M, SourceLocation Loc) {
+ DefinedMacro = M;
+ DefinedLoc = Loc;
+ }
+
+ /// Invalidate - Permanently mark this file as not being suitable for the
+ /// include-file optimization.
+ void Invalidate() {
+ // If we have read tokens but have no controlling macro, the state-machine
+ // below can never "accept".
+ ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = false;
+ DefinedMacro = nullptr;
+ TheMacro = nullptr;
+ }
+
+ /// getHasReadAnyTokensVal - This is used for the \#ifndef handshake at the
+ /// top of the file when reading preprocessor directives. Otherwise, reading
+ /// the "ifndef x" would count as reading tokens.
+ bool getHasReadAnyTokensVal() const { return ReadAnyTokens; }
+
+ /// getImmediatelyAfterTopLevelIfndef - returns true if the last directive
+ /// was an #ifndef at the beginning of the file.
+ bool getImmediatelyAfterTopLevelIfndef() const {
+ return ImmediatelyAfterTopLevelIfndef;
+ }
+
+ // If a token is read, remember that we have seen a side-effect in this file.
+ void ReadToken() {
+ ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ /// ExpandedMacro - When a macro is expanded with this lexer as the current
+ /// buffer, this method is called to disable the MIOpt if needed.
+ void ExpandedMacro() { DidMacroExpansion = true; }
+
+ /// Called when entering a top-level \#ifndef directive (or the
+ /// "\#if !defined" equivalent) without any preceding tokens.
+ ///
+ /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller
+ /// ensures that this is only called if there are no tokens read before the
+ /// \#ifndef. The caller is required to do this, because reading the \#if
+ /// line obviously reads in tokens.
+ void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc) {
+ // If the macro is already set, this is after the top-level #endif.
+ if (TheMacro)
+ return Invalidate();
+
+ // If we have already expanded a macro by the end of the #ifndef line, then
+ // there is a macro expansion *in* the #ifndef line. This means that the
+ // condition could evaluate differently when subsequently #included. Reject
+ // this.
+ if (DidMacroExpansion)
+ return Invalidate();
+
+ // Remember that we're in the #if and that we have the macro.
+ ReadAnyTokens = true;
+ ImmediatelyAfterTopLevelIfndef = true;
+ TheMacro = M;
+ MacroLoc = Loc;
+ }
+
+ /// Invoked when a top level conditional (except \#ifndef) is found.
+ void EnterTopLevelConditional() {
+ // If a conditional directive (except #ifndef) is found at the top level,
+ // there is a chunk of the file not guarded by the controlling macro.
+ Invalidate();
+ }
+
+ /// Called when the lexer exits the top-level conditional.
+ void ExitTopLevelConditional() {
+ // If we have a macro, that means the top of the file was ok. Set our state
+ // back to "not having read any tokens" so we can detect anything after the
+ // #endif.
+ if (!TheMacro) return Invalidate();
+
+ // At this point, we haven't "read any tokens" but we do have a controlling
+ // macro.
+ ReadAnyTokens = false;
+ ImmediatelyAfterTopLevelIfndef = false;
+ }
+
+ /// Once the entire file has been lexed, if there is a controlling
+ /// macro, return it.
+ const IdentifierInfo *GetControllingMacroAtEndOfFile() const {
+ // If we haven't read any tokens after the #endif, return the controlling
+ // macro if it's valid (if it isn't, it will be null).
+ if (!ReadAnyTokens)
+ return TheMacro;
+ return nullptr;
+ }
+
+ /// If the ControllingMacro is followed by a macro definition, return
+ /// the macro that was defined.
+ const IdentifierInfo *GetDefinedMacro() const {
+ return DefinedMacro;
+ }
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/PPCallbacks.h b/contrib/libs/clang16/include/clang/Lex/PPCallbacks.h
new file mode 100644
index 0000000000..84e6b96985
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/PPCallbacks.h
@@ -0,0 +1,720 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- PPCallbacks.h - Callbacks for Preprocessor actions -----*- 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
+/// Defines the PPCallbacks interface.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PPCALLBACKS_H
+#define LLVM_CLANG_LEX_PPCALLBACKS_H
+
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/Pragma.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+ class Token;
+ class IdentifierInfo;
+ class MacroDefinition;
+ class MacroDirective;
+ class MacroArgs;
+
+/// This interface provides a way to observe the actions of the
+/// preprocessor as it does its thing.
+///
+/// Clients can define their hooks here to implement preprocessor level tools.
+class PPCallbacks {
+public:
+ virtual ~PPCallbacks();
+
+ enum FileChangeReason {
+ EnterFile, ExitFile, SystemHeaderPragma, RenameFile
+ };
+
+ /// Callback invoked whenever a source file is entered or exited.
+ ///
+ /// \param Loc Indicates the new location.
+ /// \param PrevFID the file that was exited if \p Reason is ExitFile or the
+ /// the file before the new one entered for \p Reason EnterFile.
+ virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID = FileID()) {
+ }
+
+ enum class LexedFileChangeReason { EnterFile, ExitFile };
+
+ /// Callback invoked whenever the \p Lexer moves to a different file for
+ /// lexing. Unlike \p FileChanged line number directives and other related
+ /// pragmas do not trigger callbacks to \p LexedFileChanged.
+ ///
+ /// \param FID The \p FileID that the \p Lexer moved to.
+ ///
+ /// \param Reason Whether the \p Lexer entered a new file or exited one.
+ ///
+ /// \param FileType The \p CharacteristicKind of the file the \p Lexer moved
+ /// to.
+ ///
+ /// \param PrevFID The \p FileID the \p Lexer was using before the change.
+ ///
+ /// \param Loc The location where the \p Lexer entered a new file from or the
+ /// location that the \p Lexer moved into after exiting a file.
+ virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID, SourceLocation Loc) {}
+
+ /// Callback invoked whenever a source file is skipped as the result
+ /// of header guard optimization.
+ ///
+ /// \param SkippedFile The file that is skipped instead of entering \#include
+ ///
+ /// \param FilenameTok The file name token in \#include "FileName" directive
+ /// or macro expanded file name token from \#include MACRO(PARAMS) directive.
+ /// Note that FilenameTok contains corresponding quotes/angles symbols.
+ virtual void FileSkipped(const FileEntryRef &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {}
+
+ /// Callback invoked whenever the preprocessor cannot find a file for an
+ /// inclusion directive.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \returns true to indicate that the preprocessor should skip this file
+ /// and not issue any diagnostic.
+ virtual bool FileNotFound(StringRef FileName) { return false; }
+
+ /// Callback invoked whenever an inclusion directive of
+ /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless
+ /// of whether the inclusion will actually result in an inclusion.
+ ///
+ /// \param HashLoc The location of the '#' that starts the inclusion
+ /// directive.
+ ///
+ /// \param IncludeTok The token that indicates the kind of inclusion
+ /// directive, e.g., 'include' or 'import'.
+ ///
+ /// \param FileName The name of the file being included, as written in the
+ /// source code.
+ ///
+ /// \param IsAngled Whether the file name was enclosed in angle brackets;
+ /// otherwise, it was enclosed in quotes.
+ ///
+ /// \param FilenameRange The character range of the quotes or angle brackets
+ /// for the written file name.
+ ///
+ /// \param File The actual file that may be included by this inclusion
+ /// directive.
+ ///
+ /// \param SearchPath Contains the search path which was used to find the file
+ /// in the file system. If the file was found via an absolute include path,
+ /// SearchPath will be empty. For framework includes, the SearchPath and
+ /// RelativePath will be split up. For example, if an include of "Some/Some.h"
+ /// is found via the framework path
+ /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be
+ /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be
+ /// "Some.h".
+ ///
+ /// \param RelativePath The path relative to SearchPath, at which the include
+ /// file was found. This is equal to FileName except for framework includes.
+ ///
+ /// \param Imported The module, whenever an inclusion directive was
+ /// automatically turned into a module import or null otherwise.
+ ///
+ /// \param FileType The characteristic kind, indicates whether a file or
+ /// directory holds normal user code, system code, or system code which is
+ /// implicitly 'extern "C"' in C++ mode.
+ ///
+ virtual void InclusionDirective(SourceLocation HashLoc,
+ const Token &IncludeTok, StringRef FileName,
+ bool IsAngled, CharSourceRange FilenameRange,
+ OptionalFileEntryRef File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {}
+
+ /// Callback invoked whenever a submodule was entered.
+ ///
+ /// \param M The submodule we have entered.
+ ///
+ /// \param ImportLoc The location of import directive token.
+ ///
+ /// \param ForPragma If entering from pragma directive.
+ ///
+ virtual void EnteredSubmodule(Module *M, SourceLocation ImportLoc,
+ bool ForPragma) { }
+
+ /// Callback invoked whenever a submodule was left.
+ ///
+ /// \param M The submodule we have left.
+ ///
+ /// \param ImportLoc The location of import directive token.
+ ///
+ /// \param ForPragma If entering from pragma directive.
+ ///
+ virtual void LeftSubmodule(Module *M, SourceLocation ImportLoc,
+ bool ForPragma) { }
+
+ /// Callback invoked whenever there was an explicit module-import
+ /// syntax.
+ ///
+ /// \param ImportLoc The location of import directive token.
+ ///
+ /// \param Path The identifiers (and their locations) of the module
+ /// "path", e.g., "std.vector" would be split into "std" and "vector".
+ ///
+ /// \param Imported The imported module; can be null if importing failed.
+ ///
+ virtual void moduleImport(SourceLocation ImportLoc,
+ ModuleIdPath Path,
+ const Module *Imported) {
+ }
+
+ /// Callback invoked when the end of the main file is reached.
+ ///
+ /// No subsequent callbacks will be made.
+ virtual void EndOfMainFile() {
+ }
+
+ /// Callback invoked when a \#ident or \#sccs directive is read.
+ /// \param Loc The location of the directive.
+ /// \param str The text of the directive.
+ ///
+ virtual void Ident(SourceLocation Loc, StringRef str) {
+ }
+
+ /// Callback invoked when start reading any pragma directive.
+ virtual void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) {
+ }
+
+ /// Callback invoked when a \#pragma comment directive is read.
+ virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ StringRef Str) {
+ }
+
+ /// Callback invoked when a \#pragma mark comment is read.
+ virtual void PragmaMark(SourceLocation Loc, StringRef Trivia) {
+ }
+
+ /// Callback invoked when a \#pragma detect_mismatch directive is
+ /// read.
+ virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value) {
+ }
+
+ /// Callback invoked when a \#pragma clang __debug directive is read.
+ /// \param Loc The location of the debug directive.
+ /// \param DebugType The identifier following __debug.
+ virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) {
+ }
+
+ /// Determines the kind of \#pragma invoking a call to PragmaMessage.
+ enum PragmaMessageKind {
+ /// \#pragma message has been invoked.
+ PMK_Message,
+
+ /// \#pragma GCC warning has been invoked.
+ PMK_Warning,
+
+ /// \#pragma GCC error has been invoked.
+ PMK_Error
+ };
+
+ /// Callback invoked when a \#pragma message directive is read.
+ /// \param Loc The location of the message directive.
+ /// \param Namespace The namespace of the message directive.
+ /// \param Kind The type of the message directive.
+ /// \param Str The text of the message directive.
+ virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str) {
+ }
+
+ /// Callback invoked when a \#pragma gcc diagnostic push directive
+ /// is read.
+ virtual void PragmaDiagnosticPush(SourceLocation Loc,
+ StringRef Namespace) {
+ }
+
+ /// Callback invoked when a \#pragma gcc diagnostic pop directive
+ /// is read.
+ virtual void PragmaDiagnosticPop(SourceLocation Loc,
+ StringRef Namespace) {
+ }
+
+ /// Callback invoked when a \#pragma gcc diagnostic directive is read.
+ virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
+ diag::Severity mapping, StringRef Str) {}
+
+ /// Called when an OpenCL extension is either disabled or
+ /// enabled with a pragma.
+ virtual void PragmaOpenCLExtension(SourceLocation NameLoc,
+ const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) {
+ }
+
+ /// Callback invoked when a \#pragma warning directive is read.
+ enum PragmaWarningSpecifier {
+ PWS_Default,
+ PWS_Disable,
+ PWS_Error,
+ PWS_Once,
+ PWS_Suppress,
+ PWS_Level1,
+ PWS_Level2,
+ PWS_Level3,
+ PWS_Level4,
+ };
+ virtual void PragmaWarning(SourceLocation Loc,
+ PragmaWarningSpecifier WarningSpec,
+ ArrayRef<int> Ids) {}
+
+ /// Callback invoked when a \#pragma warning(push) directive is read.
+ virtual void PragmaWarningPush(SourceLocation Loc, int Level) {
+ }
+
+ /// Callback invoked when a \#pragma warning(pop) directive is read.
+ virtual void PragmaWarningPop(SourceLocation Loc) {
+ }
+
+ /// Callback invoked when a \#pragma execution_character_set(push) directive
+ /// is read.
+ virtual void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) {}
+
+ /// Callback invoked when a \#pragma execution_character_set(pop) directive
+ /// is read.
+ virtual void PragmaExecCharsetPop(SourceLocation Loc) {}
+
+ /// Callback invoked when a \#pragma clang assume_nonnull begin directive
+ /// is read.
+ virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {}
+
+ /// Callback invoked when a \#pragma clang assume_nonnull end directive
+ /// is read.
+ virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {}
+
+ /// Called by Preprocessor::HandleMacroExpandedIdentifier when a
+ /// macro invocation is found.
+ virtual void MacroExpands(const Token &MacroNameTok,
+ const MacroDefinition &MD, SourceRange Range,
+ const MacroArgs *Args) {}
+
+ /// Hook called whenever a macro definition is seen.
+ virtual void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ }
+
+ /// Hook called whenever a macro \#undef is seen.
+ /// \param MacroNameTok The active Token
+ /// \param MD A MacroDefinition for the named macro.
+ /// \param Undef New MacroDirective if the macro was defined, null otherwise.
+ ///
+ /// MD is released immediately following this callback.
+ virtual void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD,
+ const MacroDirective *Undef) {
+ }
+
+ /// Hook called whenever the 'defined' operator is seen.
+ /// \param MD The MacroDirective if the name was a macro, null otherwise.
+ virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) {
+ }
+
+ /// Hook called when a '__has_include' or '__has_include_next' directive is
+ /// read.
+ virtual void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
+ OptionalFileEntryRef File,
+ SrcMgr::CharacteristicKind FileType);
+
+ /// Hook called when a source range is skipped.
+ /// \param Range The SourceRange that was skipped. The range begins at the
+ /// \#if/\#else directive and ends after the \#endif/\#else directive.
+ /// \param EndifLoc The end location of the 'endif' token, which may precede
+ /// the range skipped by the directive (e.g excluding comments after an
+ /// 'endif').
+ virtual void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) {
+ }
+
+ enum ConditionValueKind {
+ CVK_NotEvaluated, CVK_False, CVK_True
+ };
+
+ /// Hook called whenever an \#if is seen.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
+ ///
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) {
+ }
+
+ /// Hook called whenever an \#elif is seen.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param ConditionValue The evaluated value of the condition.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) {
+ }
+
+ /// Hook called whenever an \#ifdef is seen.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+ virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+
+ /// Hook called whenever an \#elifdef branch is taken.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+ virtual void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+ /// Hook called whenever an \#elifdef is skipped.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) {
+ }
+
+ /// Hook called whenever an \#ifndef is seen.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefiniton if the name was a macro, null otherwise.
+ virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+
+ /// Hook called whenever an \#elifndef branch is taken.
+ /// \param Loc the source location of the directive.
+ /// \param MacroNameTok Information on the token being tested.
+ /// \param MD The MacroDefinition if the name was a macro, null otherwise.
+ virtual void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) {
+ }
+ /// Hook called whenever an \#elifndef is skipped.
+ /// \param Loc the source location of the directive.
+ /// \param ConditionRange The SourceRange of the expression being tested.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ // FIXME: better to pass in a list (or tree!) of Tokens.
+ virtual void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) {
+ }
+
+ /// Hook called whenever an \#else is seen.
+ /// \param Loc the source location of the directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ virtual void Else(SourceLocation Loc, SourceLocation IfLoc) {
+ }
+
+ /// Hook called whenever an \#endif is seen.
+ /// \param Loc the source location of the directive.
+ /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive.
+ virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) {
+ }
+};
+
+/// Simple wrapper class for chaining callbacks.
+class PPChainedCallbacks : public PPCallbacks {
+ std::unique_ptr<PPCallbacks> First, Second;
+
+public:
+ PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First,
+ std::unique_ptr<PPCallbacks> _Second)
+ : First(std::move(_First)), Second(std::move(_Second)) {}
+
+ ~PPChainedCallbacks() override;
+
+ void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType,
+ FileID PrevFID) override {
+ First->FileChanged(Loc, Reason, FileType, PrevFID);
+ Second->FileChanged(Loc, Reason, FileType, PrevFID);
+ }
+
+ void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
+ SrcMgr::CharacteristicKind FileType, FileID PrevFID,
+ SourceLocation Loc) override {
+ First->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
+ Second->LexedFileChanged(FID, Reason, FileType, PrevFID, Loc);
+ }
+
+ void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) override {
+ First->FileSkipped(SkippedFile, FilenameTok, FileType);
+ Second->FileSkipped(SkippedFile, FilenameTok, FileType);
+ }
+
+ bool FileNotFound(StringRef FileName) override {
+ bool Skip = First->FileNotFound(FileName);
+ // Make sure to invoke the second callback, no matter if the first already
+ // returned true to skip the file.
+ Skip |= Second->FileNotFound(FileName);
+ return Skip;
+ }
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange,
+ OptionalFileEntryRef File, StringRef SearchPath,
+ StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override {
+ First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
+ FilenameRange, File, SearchPath, RelativePath,
+ Imported, FileType);
+ Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled,
+ FilenameRange, File, SearchPath, RelativePath,
+ Imported, FileType);
+ }
+
+ void EnteredSubmodule(Module *M, SourceLocation ImportLoc,
+ bool ForPragma) override {
+ First->EnteredSubmodule(M, ImportLoc, ForPragma);
+ Second->EnteredSubmodule(M, ImportLoc, ForPragma);
+ }
+
+ void LeftSubmodule(Module *M, SourceLocation ImportLoc,
+ bool ForPragma) override {
+ First->LeftSubmodule(M, ImportLoc, ForPragma);
+ Second->LeftSubmodule(M, ImportLoc, ForPragma);
+ }
+
+ void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path,
+ const Module *Imported) override {
+ First->moduleImport(ImportLoc, Path, Imported);
+ Second->moduleImport(ImportLoc, Path, Imported);
+ }
+
+ void EndOfMainFile() override {
+ First->EndOfMainFile();
+ Second->EndOfMainFile();
+ }
+
+ void Ident(SourceLocation Loc, StringRef str) override {
+ First->Ident(Loc, str);
+ Second->Ident(Loc, str);
+ }
+
+ void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) override {
+ First->PragmaDirective(Loc, Introducer);
+ Second->PragmaDirective(Loc, Introducer);
+ }
+
+ void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
+ StringRef Str) override {
+ First->PragmaComment(Loc, Kind, Str);
+ Second->PragmaComment(Loc, Kind, Str);
+ }
+
+ void PragmaMark(SourceLocation Loc, StringRef Trivia) override {
+ First->PragmaMark(Loc, Trivia);
+ Second->PragmaMark(Loc, Trivia);
+ }
+
+ void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value) override {
+ First->PragmaDetectMismatch(Loc, Name, Value);
+ Second->PragmaDetectMismatch(Loc, Name, Value);
+ }
+
+ void PragmaDebug(SourceLocation Loc, StringRef DebugType) override {
+ First->PragmaDebug(Loc, DebugType);
+ Second->PragmaDebug(Loc, DebugType);
+ }
+
+ void PragmaMessage(SourceLocation Loc, StringRef Namespace,
+ PragmaMessageKind Kind, StringRef Str) override {
+ First->PragmaMessage(Loc, Namespace, Kind, Str);
+ Second->PragmaMessage(Loc, Namespace, Kind, Str);
+ }
+
+ void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override {
+ First->PragmaDiagnosticPush(Loc, Namespace);
+ Second->PragmaDiagnosticPush(Loc, Namespace);
+ }
+
+ void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override {
+ First->PragmaDiagnosticPop(Loc, Namespace);
+ Second->PragmaDiagnosticPop(Loc, Namespace);
+ }
+
+ void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
+ diag::Severity mapping, StringRef Str) override {
+ First->PragmaDiagnostic(Loc, Namespace, mapping, Str);
+ Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
+ }
+
+ void HasInclude(SourceLocation Loc, StringRef FileName, bool IsAngled,
+ OptionalFileEntryRef File,
+ SrcMgr::CharacteristicKind FileType) override;
+
+ void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name,
+ SourceLocation StateLoc, unsigned State) override {
+ First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ Second->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);
+ }
+
+ void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier WarningSpec,
+ ArrayRef<int> Ids) override {
+ First->PragmaWarning(Loc, WarningSpec, Ids);
+ Second->PragmaWarning(Loc, WarningSpec, Ids);
+ }
+
+ void PragmaWarningPush(SourceLocation Loc, int Level) override {
+ First->PragmaWarningPush(Loc, Level);
+ Second->PragmaWarningPush(Loc, Level);
+ }
+
+ void PragmaWarningPop(SourceLocation Loc) override {
+ First->PragmaWarningPop(Loc);
+ Second->PragmaWarningPop(Loc);
+ }
+
+ void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override {
+ First->PragmaExecCharsetPush(Loc, Str);
+ Second->PragmaExecCharsetPush(Loc, Str);
+ }
+
+ void PragmaExecCharsetPop(SourceLocation Loc) override {
+ First->PragmaExecCharsetPop(Loc);
+ Second->PragmaExecCharsetPop(Loc);
+ }
+
+ void PragmaAssumeNonNullBegin(SourceLocation Loc) override {
+ First->PragmaAssumeNonNullBegin(Loc);
+ Second->PragmaAssumeNonNullBegin(Loc);
+ }
+
+ void PragmaAssumeNonNullEnd(SourceLocation Loc) override {
+ First->PragmaAssumeNonNullEnd(Loc);
+ Second->PragmaAssumeNonNullEnd(Loc);
+ }
+
+ void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override {
+ First->MacroExpands(MacroNameTok, MD, Range, Args);
+ Second->MacroExpands(MacroNameTok, MD, Range, Args);
+ }
+
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override {
+ First->MacroDefined(MacroNameTok, MD);
+ Second->MacroDefined(MacroNameTok, MD);
+ }
+
+ void MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD,
+ const MacroDirective *Undef) override {
+ First->MacroUndefined(MacroNameTok, MD, Undef);
+ Second->MacroUndefined(MacroNameTok, MD, Undef);
+ }
+
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override {
+ First->Defined(MacroNameTok, MD, Range);
+ Second->Defined(MacroNameTok, MD, Range);
+ }
+
+ void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override {
+ First->SourceRangeSkipped(Range, EndifLoc);
+ Second->SourceRangeSkipped(Range, EndifLoc);
+ }
+
+ /// Hook called whenever an \#if is seen.
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override {
+ First->If(Loc, ConditionRange, ConditionValue);
+ Second->If(Loc, ConditionRange, ConditionValue);
+ }
+
+ /// Hook called whenever an \#elif is seen.
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
+ First->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
+ Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc);
+ }
+
+ /// Hook called whenever an \#ifdef is seen.
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Ifdef(Loc, MacroNameTok, MD);
+ Second->Ifdef(Loc, MacroNameTok, MD);
+ }
+
+ /// Hook called whenever an \#elifdef is taken.
+ void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Elifdef(Loc, MacroNameTok, MD);
+ Second->Elifdef(Loc, MacroNameTok, MD);
+ }
+ /// Hook called whenever an \#elifdef is skipped.
+ void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) override {
+ First->Elifdef(Loc, ConditionRange, IfLoc);
+ Second->Elifdef(Loc, ConditionRange, IfLoc);
+ }
+
+ /// Hook called whenever an \#ifndef is seen.
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Ifndef(Loc, MacroNameTok, MD);
+ Second->Ifndef(Loc, MacroNameTok, MD);
+ }
+
+ /// Hook called whenever an \#elifndef is taken.
+ void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override {
+ First->Elifndef(Loc, MacroNameTok, MD);
+ Second->Elifndef(Loc, MacroNameTok, MD);
+ }
+ /// Hook called whenever an \#elifndef is skipped.
+ void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) override {
+ First->Elifndef(Loc, ConditionRange, IfLoc);
+ Second->Elifndef(Loc, ConditionRange, IfLoc);
+ }
+
+ /// Hook called whenever an \#else is seen.
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override {
+ First->Else(Loc, IfLoc);
+ Second->Else(Loc, IfLoc);
+ }
+
+ /// Hook called whenever an \#endif is seen.
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override {
+ First->Endif(Loc, IfLoc);
+ Second->Endif(Loc, IfLoc);
+ }
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/PPConditionalDirectiveRecord.h b/contrib/libs/clang16/include/clang/Lex/PPConditionalDirectiveRecord.h
new file mode 100644
index 0000000000..b5d06776e4
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/PPConditionalDirectiveRecord.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- PPConditionalDirectiveRecord.h - Preprocessing Directives-*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PPConditionalDirectiveRecord class, which maintains
+// a record of conditional directive regions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
+#define LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace clang {
+
+/// Records preprocessor conditional directive regions and allows
+/// querying in which region source locations belong to.
+class PPConditionalDirectiveRecord : public PPCallbacks {
+ SourceManager &SourceMgr;
+
+ SmallVector<SourceLocation, 6> CondDirectiveStack;
+
+ class CondDirectiveLoc {
+ SourceLocation Loc;
+ SourceLocation RegionLoc;
+
+ public:
+ CondDirectiveLoc(SourceLocation Loc, SourceLocation RegionLoc)
+ : Loc(Loc), RegionLoc(RegionLoc) {}
+
+ SourceLocation getLoc() const { return Loc; }
+ SourceLocation getRegionLoc() const { return RegionLoc; }
+
+ class Comp {
+ SourceManager &SM;
+ public:
+ explicit Comp(SourceManager &SM) : SM(SM) {}
+ bool operator()(const CondDirectiveLoc &LHS,
+ const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS.getLoc());
+ }
+ bool operator()(const CondDirectiveLoc &LHS, SourceLocation RHS) {
+ return SM.isBeforeInTranslationUnit(LHS.getLoc(), RHS);
+ }
+ bool operator()(SourceLocation LHS, const CondDirectiveLoc &RHS) {
+ return SM.isBeforeInTranslationUnit(LHS, RHS.getLoc());
+ }
+ };
+ };
+
+ typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy;
+ /// The locations of conditional directives in source order.
+ CondDirectiveLocsTy CondDirectiveLocs;
+
+ void addCondDirectiveLoc(CondDirectiveLoc DirLoc);
+
+public:
+ /// Construct a new preprocessing record.
+ explicit PPConditionalDirectiveRecord(SourceManager &SM);
+
+ size_t getTotalMemory() const;
+
+ SourceManager &getSourceManager() const { return SourceMgr; }
+
+ /// Returns true if the given range intersects with a conditional
+ /// directive. if a \#if/\#endif block is fully contained within the range,
+ /// this function will return false.
+ bool rangeIntersectsConditionalDirective(SourceRange Range) const;
+
+ /// Returns true if the given locations are in different regions,
+ /// separated by conditional directive blocks.
+ bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS,
+ SourceLocation RHS) const {
+ return findConditionalDirectiveRegionLoc(LHS) !=
+ findConditionalDirectiveRegionLoc(RHS);
+ }
+
+ SourceLocation findConditionalDirectiveRegionLoc(SourceLocation Loc) const;
+
+private:
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override;
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Elifdef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) override;
+ void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Elifndef(SourceLocation Loc, SourceRange ConditionRange,
+ SourceLocation IfLoc) override;
+ void Else(SourceLocation Loc, SourceLocation IfLoc) override;
+ void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_LEX_PPCONDITIONALDIRECTIVERECORD_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/Pragma.h b/contrib/libs/clang16/include/clang/Lex/Pragma.h
new file mode 100644
index 0000000000..2bbf3eb332
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/Pragma.h
@@ -0,0 +1,139 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Pragma.h - Pragma registration and handling --------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PragmaHandler and PragmaTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PRAGMA_H
+#define LLVM_CLANG_LEX_PRAGMA_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace clang {
+
+class PragmaNamespace;
+class Preprocessor;
+class Token;
+
+ /**
+ * Describes how the pragma was introduced, e.g., with \#pragma,
+ * _Pragma, or __pragma.
+ */
+ enum PragmaIntroducerKind {
+ /**
+ * The pragma was introduced via \#pragma.
+ */
+ PIK_HashPragma,
+
+ /**
+ * The pragma was introduced via the C99 _Pragma(string-literal).
+ */
+ PIK__Pragma,
+
+ /**
+ * The pragma was introduced via the Microsoft
+ * __pragma(token-string).
+ */
+ PIK___pragma
+ };
+
+ /// Describes how and where the pragma was introduced.
+ struct PragmaIntroducer {
+ PragmaIntroducerKind Kind;
+ SourceLocation Loc;
+ };
+
+/// PragmaHandler - Instances of this interface defined to handle the various
+/// pragmas that the language front-end uses. Each handler optionally has a
+/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
+/// that identifier is found. If a handler does not match any of the declared
+/// pragmas the handler with a null identifier is invoked, if it exists.
+///
+/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
+/// we treat "\#pragma STDC" and "\#pragma GCC" as namespaces that contain other
+/// pragmas.
+class PragmaHandler {
+ std::string Name;
+
+public:
+ PragmaHandler() = default;
+ explicit PragmaHandler(StringRef name) : Name(name) {}
+ virtual ~PragmaHandler();
+
+ StringRef getName() const { return Name; }
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) = 0;
+
+ /// getIfNamespace - If this is a namespace, return it. This is equivalent to
+ /// using a dynamic_cast, but doesn't require RTTI.
+ virtual PragmaNamespace *getIfNamespace() { return nullptr; }
+};
+
+/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
+/// used to ignore particular pragmas.
+class EmptyPragmaHandler : public PragmaHandler {
+public:
+ explicit EmptyPragmaHandler(StringRef Name = StringRef());
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &FirstToken) override;
+};
+
+/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
+/// allowing hierarchical pragmas to be defined. Common examples of namespaces
+/// are "\#pragma GCC", "\#pragma STDC", and "\#pragma omp", but any namespaces
+/// may be (potentially recursively) defined.
+class PragmaNamespace : public PragmaHandler {
+ /// Handlers - This is a map of the handlers in this namespace with their name
+ /// as key.
+ llvm::StringMap<std::unique_ptr<PragmaHandler>> Handlers;
+
+public:
+ explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {}
+
+ /// FindHandler - Check to see if there is already a handler for the
+ /// specified name. If not, return the handler for the null name if it
+ /// exists, otherwise return null. If IgnoreNull is true (the default) then
+ /// the null handler isn't returned on failure to match.
+ PragmaHandler *FindHandler(StringRef Name,
+ bool IgnoreNull = true) const;
+
+ /// AddPragma - Add a pragma to this namespace.
+ void AddPragma(PragmaHandler *Handler);
+
+ /// RemovePragmaHandler - Remove the given handler from the
+ /// namespace.
+ void RemovePragmaHandler(PragmaHandler *Handler);
+
+ bool IsEmpty() const { return Handlers.empty(); }
+
+ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
+ Token &Tok) override;
+
+ PragmaNamespace *getIfNamespace() override { return this; }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_PRAGMA_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/PreprocessingRecord.h b/contrib/libs/clang16/include/clang/Lex/PreprocessingRecord.h
new file mode 100644
index 0000000000..263057ad9c
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/PreprocessingRecord.h
@@ -0,0 +1,589 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- PreprocessingRecord.h - Record of Preprocessing ----------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PreprocessingRecord class, which maintains a record
+// of what occurred during preprocessing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <optional>
+#include <utility>
+#include <vector>
+
+namespace clang {
+
+class PreprocessingRecord;
+
+} // namespace clang
+
+/// Allocates memory within a Clang preprocessing record.
+void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment = 8) noexcept;
+
+/// Frees memory allocated in a Clang preprocessing record.
+void operator delete(void *ptr, clang::PreprocessingRecord &PR,
+ unsigned) noexcept;
+
+namespace clang {
+
+class IdentifierInfo;
+class MacroInfo;
+class SourceManager;
+class Token;
+
+ /// Base class that describes a preprocessed entity, which may be a
+ /// preprocessor directive or macro expansion.
+ class PreprocessedEntity {
+ public:
+ /// The kind of preprocessed entity an object describes.
+ enum EntityKind {
+ /// Indicates a problem trying to load the preprocessed entity.
+ InvalidKind,
+
+ /// A macro expansion.
+ MacroExpansionKind,
+
+ /// \defgroup Preprocessing directives
+ /// @{
+
+ /// A macro definition.
+ MacroDefinitionKind,
+
+ /// An inclusion directive, such as \c \#include, \c
+ /// \#import, or \c \#include_next.
+ InclusionDirectiveKind,
+
+ /// @}
+
+ FirstPreprocessingDirective = MacroDefinitionKind,
+ LastPreprocessingDirective = InclusionDirectiveKind
+ };
+
+ private:
+ /// The kind of preprocessed entity that this object describes.
+ EntityKind Kind;
+
+ /// The source range that covers this preprocessed entity.
+ SourceRange Range;
+
+ protected:
+ friend class PreprocessingRecord;
+
+ PreprocessedEntity(EntityKind Kind, SourceRange Range)
+ : Kind(Kind), Range(Range) {}
+
+ public:
+ /// Retrieve the kind of preprocessed entity stored in this object.
+ EntityKind getKind() const { return Kind; }
+
+ /// Retrieve the source range that covers this entire preprocessed
+ /// entity.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+
+ /// Returns true if there was a problem loading the preprocessed
+ /// entity.
+ bool isInvalid() const { return Kind == InvalidKind; }
+
+ // Only allow allocation of preprocessed entities using the allocator
+ // in PreprocessingRecord or by doing a placement new.
+ void *operator new(size_t bytes, PreprocessingRecord &PR,
+ unsigned alignment = 8) noexcept {
+ return ::operator new(bytes, PR, alignment);
+ }
+
+ void *operator new(size_t bytes, void *mem) noexcept { return mem; }
+
+ void operator delete(void *ptr, PreprocessingRecord &PR,
+ unsigned alignment) noexcept {
+ return ::operator delete(ptr, PR, alignment);
+ }
+
+ void operator delete(void *, std::size_t) noexcept {}
+ void operator delete(void *, void *) noexcept {}
+
+ private:
+ // Make vanilla 'new' and 'delete' illegal for preprocessed entities.
+ void *operator new(size_t bytes) noexcept;
+ void operator delete(void *data) noexcept;
+ };
+
+ /// Records the presence of a preprocessor directive.
+ class PreprocessingDirective : public PreprocessedEntity {
+ public:
+ PreprocessingDirective(EntityKind Kind, SourceRange Range)
+ : PreprocessedEntity(Kind, Range) {}
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PD) {
+ return PD->getKind() >= FirstPreprocessingDirective &&
+ PD->getKind() <= LastPreprocessingDirective;
+ }
+ };
+
+ /// Record the location of a macro definition.
+ class MacroDefinitionRecord : public PreprocessingDirective {
+ /// The name of the macro being defined.
+ const IdentifierInfo *Name;
+
+ public:
+ explicit MacroDefinitionRecord(const IdentifierInfo *Name,
+ SourceRange Range)
+ : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {}
+
+ /// Retrieve the name of the macro being defined.
+ const IdentifierInfo *getName() const { return Name; }
+
+ /// Retrieve the location of the macro name in the definition.
+ SourceLocation getLocation() const { return getSourceRange().getBegin(); }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroDefinitionKind;
+ }
+ };
+
+ /// Records the location of a macro expansion.
+ class MacroExpansion : public PreprocessedEntity {
+ /// The definition of this macro or the name of the macro if it is
+ /// a builtin macro.
+ llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef;
+
+ public:
+ MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range),
+ NameOrDef(BuiltinName) {}
+
+ MacroExpansion(MacroDefinitionRecord *Definition, SourceRange Range)
+ : PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) {
+ }
+
+ /// True if it is a builtin macro.
+ bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }
+
+ /// The name of the macro being expanded.
+ const IdentifierInfo *getName() const {
+ if (MacroDefinitionRecord *Def = getDefinition())
+ return Def->getName();
+ return NameOrDef.get<IdentifierInfo *>();
+ }
+
+ /// The definition of the macro being expanded. May return null if
+ /// this is a builtin macro.
+ MacroDefinitionRecord *getDefinition() const {
+ return NameOrDef.dyn_cast<MacroDefinitionRecord *>();
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == MacroExpansionKind;
+ }
+ };
+
+ /// Record the location of an inclusion directive, such as an
+ /// \c \#include or \c \#import statement.
+ class InclusionDirective : public PreprocessingDirective {
+ public:
+ /// The kind of inclusion directives known to the
+ /// preprocessor.
+ enum InclusionKind {
+ /// An \c \#include directive.
+ Include,
+
+ /// An Objective-C \c \#import directive.
+ Import,
+
+ /// A GNU \c \#include_next directive.
+ IncludeNext,
+
+ /// A Clang \c \#__include_macros directive.
+ IncludeMacros
+ };
+
+ private:
+ /// The name of the file that was included, as written in
+ /// the source.
+ StringRef FileName;
+
+ /// Whether the file name was in quotation marks; otherwise, it was
+ /// in angle brackets.
+ unsigned InQuotes : 1;
+
+ /// The kind of inclusion directive we have.
+ ///
+ /// This is a value of type InclusionKind.
+ unsigned Kind : 2;
+
+ /// Whether the inclusion directive was automatically turned into
+ /// a module import.
+ unsigned ImportedModule : 1;
+
+ /// The file that was included.
+ OptionalFileEntryRef File;
+
+ public:
+ InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind,
+ StringRef FileName, bool InQuotes, bool ImportedModule,
+ OptionalFileEntryRef File, SourceRange Range);
+
+ /// Determine what kind of inclusion directive this is.
+ InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }
+
+ /// Retrieve the included file name as it was written in the source.
+ StringRef getFileName() const { return FileName; }
+
+ /// Determine whether the included file name was written in quotes;
+ /// otherwise, it was written in angle brackets.
+ bool wasInQuotes() const { return InQuotes; }
+
+ /// Determine whether the inclusion directive was automatically
+ /// turned into a module import.
+ bool importedModule() const { return ImportedModule; }
+
+ /// Retrieve the file entry for the actual file that was included
+ /// by this directive.
+ OptionalFileEntryRef getFile() const { return File; }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const PreprocessedEntity *PE) {
+ return PE->getKind() == InclusionDirectiveKind;
+ }
+ };
+
+ /// An abstract class that should be subclassed by any external source
+ /// of preprocessing record entries.
+ class ExternalPreprocessingRecordSource {
+ public:
+ virtual ~ExternalPreprocessingRecordSource();
+
+ /// Read a preallocated preprocessed entity from the external source.
+ ///
+ /// \returns null if an error occurred that prevented the preprocessed
+ /// entity from being loaded.
+ virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;
+
+ /// Returns a pair of [Begin, End) indices of preallocated
+ /// preprocessed entities that \p Range encompasses.
+ virtual std::pair<unsigned, unsigned>
+ findPreprocessedEntitiesInRange(SourceRange Range) = 0;
+
+ /// Optionally returns true or false if the preallocated preprocessed
+ /// entity with index \p Index came from file \p FID.
+ virtual std::optional<bool> isPreprocessedEntityInFileID(unsigned Index,
+ FileID FID) {
+ return std::nullopt;
+ }
+
+ /// Read a preallocated skipped range from the external source.
+ virtual SourceRange ReadSkippedRange(unsigned Index) = 0;
+ };
+
+ /// A record of the steps taken while preprocessing a source file,
+ /// including the various preprocessing directives processed, macros
+ /// expanded, etc.
+ class PreprocessingRecord : public PPCallbacks {
+ SourceManager &SourceMgr;
+
+ /// Allocator used to store preprocessing objects.
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// The set of preprocessed entities in this record, in order they
+ /// were seen.
+ std::vector<PreprocessedEntity *> PreprocessedEntities;
+
+ /// The set of preprocessed entities in this record that have been
+ /// loaded from external sources.
+ ///
+ /// The entries in this vector are loaded lazily from the external source,
+ /// and are referenced by the iterator using negative indices.
+ std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
+
+ /// The set of ranges that were skipped by the preprocessor,
+ std::vector<SourceRange> SkippedRanges;
+
+ bool SkippedRangesAllLoaded = true;
+
+ /// Global (loaded or local) ID for a preprocessed entity.
+ /// Negative values are used to indicate preprocessed entities
+ /// loaded from the external source while non-negative values are used to
+ /// indicate preprocessed entities introduced by the current preprocessor.
+ /// Value -1 corresponds to element 0 in the loaded entities vector,
+ /// value -2 corresponds to element 1 in the loaded entities vector, etc.
+ /// Value 0 is an invalid value, the index to local entities is 1-based,
+ /// value 1 corresponds to element 0 in the local entities vector,
+ /// value 2 corresponds to element 1 in the local entities vector, etc.
+ class PPEntityID {
+ friend class PreprocessingRecord;
+
+ int ID = 0;
+
+ explicit PPEntityID(int ID) : ID(ID) {}
+
+ public:
+ PPEntityID() = default;
+ };
+
+ static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {
+ return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);
+ }
+
+ /// Mapping from MacroInfo structures to their definitions.
+ llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;
+
+ /// External source of preprocessed entities.
+ ExternalPreprocessingRecordSource *ExternalSource = nullptr;
+
+ /// Retrieve the preprocessed entity at the given ID.
+ PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);
+
+ /// Retrieve the loaded preprocessed entity at the given index.
+ PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);
+
+ /// Determine the number of preprocessed entities that were
+ /// loaded (or can be loaded) from an external source.
+ unsigned getNumLoadedPreprocessedEntities() const {
+ return LoadedPreprocessedEntities.size();
+ }
+
+ /// Returns a pair of [Begin, End) indices of local preprocessed
+ /// entities that \p Range encompasses.
+ std::pair<unsigned, unsigned>
+ findLocalPreprocessedEntitiesInRange(SourceRange Range) const;
+ unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;
+ unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;
+
+ /// Allocate space for a new set of loaded preprocessed entities.
+ ///
+ /// \returns The index into the set of loaded preprocessed entities, which
+ /// corresponds to the first newly-allocated entity.
+ unsigned allocateLoadedEntities(unsigned NumEntities);
+
+ /// Allocate space for a new set of loaded preprocessed skipped
+ /// ranges.
+ ///
+ /// \returns The index into the set of loaded preprocessed ranges, which
+ /// corresponds to the first newly-allocated range.
+ unsigned allocateSkippedRanges(unsigned NumRanges);
+
+ /// Ensures that all external skipped ranges have been loaded.
+ void ensureSkippedRangesLoaded();
+
+ /// Register a new macro definition.
+ void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);
+
+ public:
+ /// Construct a new preprocessing record.
+ explicit PreprocessingRecord(SourceManager &SM);
+
+ /// Allocate memory in the preprocessing record.
+ void *Allocate(unsigned Size, unsigned Align = 8) {
+ return BumpAlloc.Allocate(Size, Align);
+ }
+
+ /// Deallocate memory in the preprocessing record.
+ void Deallocate(void *Ptr) {}
+
+ size_t getTotalMemory() const;
+
+ SourceManager &getSourceManager() const { return SourceMgr; }
+
+ /// Iteration over the preprocessed entities.
+ ///
+ /// In a complete iteration, the iterator walks the range [-M, N),
+ /// where negative values are used to indicate preprocessed entities
+ /// loaded from the external source while non-negative values are used to
+ /// indicate preprocessed entities introduced by the current preprocessor.
+ /// However, to provide iteration in source order (for, e.g., chained
+ /// precompiled headers), dereferencing the iterator flips the negative
+ /// values (corresponding to loaded entities), so that position -M
+ /// corresponds to element 0 in the loaded entities vector, position -M+1
+ /// corresponds to element 1 in the loaded entities vector, etc. This
+ /// gives us a reasonably efficient, source-order walk.
+ ///
+ /// We define this as a wrapping iterator around an int. The
+ /// iterator_adaptor_base class forwards the iterator methods to basic
+ /// integer arithmetic.
+ class iterator : public llvm::iterator_adaptor_base<
+ iterator, int, std::random_access_iterator_tag,
+ PreprocessedEntity *, int, PreprocessedEntity *,
+ PreprocessedEntity *> {
+ friend class PreprocessingRecord;
+
+ PreprocessingRecord *Self;
+
+ iterator(PreprocessingRecord *Self, int Position)
+ : iterator::iterator_adaptor_base(Position), Self(Self) {}
+
+ public:
+ iterator() : iterator(nullptr, 0) {}
+
+ PreprocessedEntity *operator*() const {
+ bool isLoaded = this->I < 0;
+ unsigned Index = isLoaded ?
+ Self->LoadedPreprocessedEntities.size() + this->I : this->I;
+ PPEntityID ID = Self->getPPEntityID(Index, isLoaded);
+ return Self->getPreprocessedEntity(ID);
+ }
+ PreprocessedEntity *operator->() const { return **this; }
+ };
+
+ /// Begin iterator for all preprocessed entities.
+ iterator begin() {
+ return iterator(this, -(int)LoadedPreprocessedEntities.size());
+ }
+
+ /// End iterator for all preprocessed entities.
+ iterator end() {
+ return iterator(this, PreprocessedEntities.size());
+ }
+
+ /// Begin iterator for local, non-loaded, preprocessed entities.
+ iterator local_begin() {
+ return iterator(this, 0);
+ }
+
+ /// End iterator for local, non-loaded, preprocessed entities.
+ iterator local_end() {
+ return iterator(this, PreprocessedEntities.size());
+ }
+
+ /// iterator range for the given range of loaded
+ /// preprocessed entities.
+ llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start,
+ unsigned count) {
+ unsigned end = start + count;
+ assert(end <= LoadedPreprocessedEntities.size());
+ return llvm::make_range(
+ iterator(this, int(start) - LoadedPreprocessedEntities.size()),
+ iterator(this, int(end) - LoadedPreprocessedEntities.size()));
+ }
+
+ /// Returns a range of preprocessed entities that source range \p R
+ /// encompasses.
+ ///
+ /// \param R the range to look for preprocessed entities.
+ llvm::iterator_range<iterator>
+ getPreprocessedEntitiesInRange(SourceRange R);
+
+ /// Returns true if the preprocessed entity that \p PPEI iterator
+ /// points to is coming from the file \p FID.
+ ///
+ /// Can be used to avoid implicit deserializations of preallocated
+ /// preprocessed entities if we only care about entities of a specific file
+ /// and not from files \#included in the range given at
+ /// \see getPreprocessedEntitiesInRange.
+ bool isEntityInFileID(iterator PPEI, FileID FID);
+
+ /// Add a new preprocessed entity to this record.
+ PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);
+
+ /// Set the external source for preprocessed entities.
+ void SetExternalSource(ExternalPreprocessingRecordSource &Source);
+
+ /// Retrieve the external source for preprocessed entities.
+ ExternalPreprocessingRecordSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ /// Retrieve the macro definition that corresponds to the given
+ /// \c MacroInfo.
+ MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);
+
+ /// Retrieve all ranges that got skipped while preprocessing.
+ const std::vector<SourceRange> &getSkippedRanges() {
+ ensureSkippedRangesLoaded();
+ return SkippedRanges;
+ }
+
+ private:
+ friend class ASTReader;
+ friend class ASTWriter;
+
+ void MacroExpands(const Token &Id, const MacroDefinition &MD,
+ SourceRange Range, const MacroArgs *Args) override;
+ void MacroDefined(const Token &Id, const MacroDirective *MD) override;
+ void MacroUndefined(const Token &Id, const MacroDefinition &MD,
+ const MacroDirective *Undef) override;
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange,
+ OptionalFileEntryRef File, StringRef SearchPath,
+ StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
+ void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+
+ using PPCallbacks::Elifdef;
+ using PPCallbacks::Elifndef;
+ void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+ void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
+ const MacroDefinition &MD) override;
+
+ /// Hook called whenever the 'defined' operator is seen.
+ void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
+ SourceRange Range) override;
+
+ void SourceRangeSkipped(SourceRange Range,
+ SourceLocation EndifLoc) override;
+
+ void addMacroExpansion(const Token &Id, const MacroInfo *MI,
+ SourceRange Range);
+
+ /// Cached result of the last \see getPreprocessedEntitiesInRange
+ /// query.
+ struct {
+ SourceRange Range;
+ std::pair<int, int> Result;
+ } CachedRangeQuery;
+
+ std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);
+ };
+
+} // namespace clang
+
+inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
+ unsigned alignment) noexcept {
+ return PR.Allocate(bytes, alignment);
+}
+
+inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,
+ unsigned) noexcept {
+ PR.Deallocate(ptr);
+}
+
+#endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/Preprocessor.h b/contrib/libs/clang16/include/clang/Lex/Preprocessor.h
new file mode 100644
index 0000000000..83f4c1f476
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/Preprocessor.h
@@ -0,0 +1,2888 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Preprocessor.h - C Language Family Preprocessor ----------*- 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
+/// Defines the clang::Preprocessor interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOR_H
+#define LLVM_CLANG_LEX_PREPROCESSOR_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TokenKinds.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/ModuleMap.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Token.h"
+#include "clang/Lex/TokenLexer.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Registry.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+template<unsigned InternalLen> class SmallString;
+
+} // namespace llvm
+
+namespace clang {
+
+class CodeCompletionHandler;
+class CommentHandler;
+class DirectoryEntry;
+class EmptylineHandler;
+class ExternalPreprocessorSource;
+class FileEntry;
+class FileManager;
+class HeaderSearch;
+class MacroArgs;
+class PragmaHandler;
+class PragmaNamespace;
+class PreprocessingRecord;
+class PreprocessorLexer;
+class PreprocessorOptions;
+class ScratchBuffer;
+class TargetInfo;
+
+namespace Builtin {
+class Context;
+}
+
+/// Stores token information for comparing actual tokens with
+/// predefined values. Only handles simple tokens and identifiers.
+class TokenValue {
+ tok::TokenKind Kind;
+ IdentifierInfo *II;
+
+public:
+ TokenValue(tok::TokenKind Kind) : Kind(Kind), II(nullptr) {
+ assert(Kind != tok::raw_identifier && "Raw identifiers are not supported.");
+ assert(Kind != tok::identifier &&
+ "Identifiers should be created by TokenValue(IdentifierInfo *)");
+ assert(!tok::isLiteral(Kind) && "Literals are not supported.");
+ assert(!tok::isAnnotation(Kind) && "Annotations are not supported.");
+ }
+
+ TokenValue(IdentifierInfo *II) : Kind(tok::identifier), II(II) {}
+
+ bool operator==(const Token &Tok) const {
+ return Tok.getKind() == Kind &&
+ (!II || II == Tok.getIdentifierInfo());
+ }
+};
+
+/// Context in which macro name is used.
+enum MacroUse {
+ // other than #define or #undef
+ MU_Other = 0,
+
+ // macro name specified in #define
+ MU_Define = 1,
+
+ // macro name specified in #undef
+ MU_Undef = 2
+};
+
+/// Engages in a tight little dance with the lexer to efficiently
+/// preprocess tokens.
+///
+/// Lexers know only about tokens within a single source file, and don't
+/// know anything about preprocessor-level issues like the \#include stack,
+/// token expansion, etc.
+class Preprocessor {
+ friend class VAOptDefinitionContext;
+ friend class VariadicMacroScopeGuard;
+
+ llvm::unique_function<void(const clang::Token &)> OnToken;
+ std::shared_ptr<PreprocessorOptions> PPOpts;
+ DiagnosticsEngine *Diags;
+ LangOptions &LangOpts;
+ const TargetInfo *Target = nullptr;
+ const TargetInfo *AuxTarget = nullptr;
+ FileManager &FileMgr;
+ SourceManager &SourceMgr;
+ std::unique_ptr<ScratchBuffer> ScratchBuf;
+ HeaderSearch &HeaderInfo;
+ ModuleLoader &TheModuleLoader;
+
+ /// External source of macros.
+ ExternalPreprocessorSource *ExternalSource;
+
+ /// A BumpPtrAllocator object used to quickly allocate and release
+ /// objects internal to the Preprocessor.
+ llvm::BumpPtrAllocator BP;
+
+ /// Identifiers for builtin macros and other builtins.
+ IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__
+ IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
+ IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
+ IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
+ IdentifierInfo *Ident__FILE_NAME__; // __FILE_NAME__
+ IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
+ IdentifierInfo *Ident__COUNTER__; // __COUNTER__
+ IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
+ IdentifierInfo *Ident__identifier; // __identifier
+ IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
+ IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__
+ IdentifierInfo *Ident__has_feature; // __has_feature
+ IdentifierInfo *Ident__has_extension; // __has_extension
+ IdentifierInfo *Ident__has_builtin; // __has_builtin
+ IdentifierInfo *Ident__has_constexpr_builtin; // __has_constexpr_builtin
+ IdentifierInfo *Ident__has_attribute; // __has_attribute
+ IdentifierInfo *Ident__has_include; // __has_include
+ IdentifierInfo *Ident__has_include_next; // __has_include_next
+ IdentifierInfo *Ident__has_warning; // __has_warning
+ IdentifierInfo *Ident__is_identifier; // __is_identifier
+ IdentifierInfo *Ident__building_module; // __building_module
+ IdentifierInfo *Ident__MODULE__; // __MODULE__
+ IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute
+ IdentifierInfo *Ident__has_c_attribute; // __has_c_attribute
+ IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute
+ IdentifierInfo *Ident__is_target_arch; // __is_target_arch
+ IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor
+ IdentifierInfo *Ident__is_target_os; // __is_target_os
+ IdentifierInfo *Ident__is_target_environment; // __is_target_environment
+ IdentifierInfo *Ident__is_target_variant_os;
+ IdentifierInfo *Ident__is_target_variant_environment;
+ IdentifierInfo *Ident__FLT_EVAL_METHOD__; // __FLT_EVAL_METHOD
+
+ // Weak, only valid (and set) while InMacroArgs is true.
+ Token* ArgMacro;
+
+ SourceLocation DATELoc, TIMELoc;
+
+ // FEM_UnsetOnCommandLine means that an explicit evaluation method was
+ // not specified on the command line. The target is queried to set the
+ // default evaluation method.
+ LangOptions::FPEvalMethodKind CurrentFPEvalMethod =
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
+
+ // The most recent pragma location where the floating point evaluation
+ // method was modified. This is used to determine whether the
+ // 'pragma clang fp eval_method' was used whithin the current scope.
+ SourceLocation LastFPEvalPragmaLocation;
+
+ LangOptions::FPEvalMethodKind TUFPEvalMethod =
+ LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
+
+ // Next __COUNTER__ value, starts at 0.
+ unsigned CounterValue = 0;
+
+ enum {
+ /// Maximum depth of \#includes.
+ MaxAllowedIncludeStackDepth = 200
+ };
+
+ // State that is set before the preprocessor begins.
+ bool KeepComments : 1;
+ bool KeepMacroComments : 1;
+ bool SuppressIncludeNotFoundError : 1;
+
+ // State that changes while the preprocessor runs:
+ bool InMacroArgs : 1; // True if parsing fn macro invocation args.
+
+ /// Whether the preprocessor owns the header search object.
+ bool OwnsHeaderSearch : 1;
+
+ /// True if macro expansion is disabled.
+ bool DisableMacroExpansion : 1;
+
+ /// Temporarily disables DisableMacroExpansion (i.e. enables expansion)
+ /// when parsing preprocessor directives.
+ bool MacroExpansionInDirectivesOverride : 1;
+
+ class ResetMacroExpansionHelper;
+
+ /// Whether we have already loaded macros from the external source.
+ mutable bool ReadMacrosFromExternalSource : 1;
+
+ /// True if pragmas are enabled.
+ bool PragmasEnabled : 1;
+
+ /// True if the current build action is a preprocessing action.
+ bool PreprocessedOutput : 1;
+
+ /// True if we are currently preprocessing a #if or #elif directive
+ bool ParsingIfOrElifDirective;
+
+ /// True if we are pre-expanding macro arguments.
+ bool InMacroArgPreExpansion;
+
+ /// Mapping/lookup information for all identifiers in
+ /// the program, including program keywords.
+ mutable IdentifierTable Identifiers;
+
+ /// This table contains all the selectors in the program.
+ ///
+ /// Unlike IdentifierTable above, this table *isn't* populated by the
+ /// preprocessor. It is declared/expanded here because its role/lifetime is
+ /// conceptually similar to the IdentifierTable. In addition, the current
+ /// control flow (in clang::ParseAST()), make it convenient to put here.
+ ///
+ /// FIXME: Make sure the lifetime of Identifiers/Selectors *isn't* tied to
+ /// the lifetime of the preprocessor.
+ SelectorTable Selectors;
+
+ /// Information about builtins.
+ std::unique_ptr<Builtin::Context> BuiltinInfo;
+
+ /// Tracks all of the pragmas that the client registered
+ /// with this preprocessor.
+ std::unique_ptr<PragmaNamespace> PragmaHandlers;
+
+ /// Pragma handlers of the original source is stored here during the
+ /// parsing of a model file.
+ std::unique_ptr<PragmaNamespace> PragmaHandlersBackup;
+
+ /// Tracks all of the comment handlers that the client registered
+ /// with this preprocessor.
+ std::vector<CommentHandler *> CommentHandlers;
+
+ /// Empty line handler.
+ EmptylineHandler *Emptyline = nullptr;
+
+public:
+ /// The kind of translation unit we are processing.
+ const TranslationUnitKind TUKind;
+
+private:
+ /// The code-completion handler.
+ CodeCompletionHandler *CodeComplete = nullptr;
+
+ /// The file that we're performing code-completion for, if any.
+ const FileEntry *CodeCompletionFile = nullptr;
+
+ /// The offset in file for the code-completion point.
+ unsigned CodeCompletionOffset = 0;
+
+ /// The location for the code-completion point. This gets instantiated
+ /// when the CodeCompletionFile gets \#include'ed for preprocessing.
+ SourceLocation CodeCompletionLoc;
+
+ /// The start location for the file of the code-completion point.
+ ///
+ /// This gets instantiated when the CodeCompletionFile gets \#include'ed
+ /// for preprocessing.
+ SourceLocation CodeCompletionFileLoc;
+
+ /// The source location of the \c import contextual keyword we just
+ /// lexed, if any.
+ SourceLocation ModuleImportLoc;
+
+ /// The import path for named module that we're currently processing.
+ SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> NamedModuleImportPath;
+
+ /// Whether the import is an `@import` or a standard c++ modules import.
+ bool IsAtImport = false;
+
+ /// Whether the last token we lexed was an '@'.
+ bool LastTokenWasAt = false;
+
+ /// A position within a C++20 import-seq.
+ class StdCXXImportSeq {
+ public:
+ enum State : int {
+ // Positive values represent a number of unclosed brackets.
+ AtTopLevel = 0,
+ AfterTopLevelTokenSeq = -1,
+ AfterExport = -2,
+ AfterImportSeq = -3,
+ };
+
+ StdCXXImportSeq(State S) : S(S) {}
+
+ /// Saw any kind of open bracket.
+ void handleOpenBracket() {
+ S = static_cast<State>(std::max<int>(S, 0) + 1);
+ }
+ /// Saw any kind of close bracket other than '}'.
+ void handleCloseBracket() {
+ S = static_cast<State>(std::max<int>(S, 1) - 1);
+ }
+ /// Saw a close brace.
+ void handleCloseBrace() {
+ handleCloseBracket();
+ if (S == AtTopLevel && !AfterHeaderName)
+ S = AfterTopLevelTokenSeq;
+ }
+ /// Saw a semicolon.
+ void handleSemi() {
+ if (atTopLevel()) {
+ S = AfterTopLevelTokenSeq;
+ AfterHeaderName = false;
+ }
+ }
+
+ /// Saw an 'export' identifier.
+ void handleExport() {
+ if (S == AfterTopLevelTokenSeq)
+ S = AfterExport;
+ else if (S <= 0)
+ S = AtTopLevel;
+ }
+ /// Saw an 'import' identifier.
+ void handleImport() {
+ if (S == AfterTopLevelTokenSeq || S == AfterExport)
+ S = AfterImportSeq;
+ else if (S <= 0)
+ S = AtTopLevel;
+ }
+
+ /// Saw a 'header-name' token; do not recognize any more 'import' tokens
+ /// until we reach a top-level semicolon.
+ void handleHeaderName() {
+ if (S == AfterImportSeq)
+ AfterHeaderName = true;
+ handleMisc();
+ }
+
+ /// Saw any other token.
+ void handleMisc() {
+ if (S <= 0)
+ S = AtTopLevel;
+ }
+
+ bool atTopLevel() { return S <= 0; }
+ bool afterImportSeq() { return S == AfterImportSeq; }
+ bool afterTopLevelSeq() { return S == AfterTopLevelTokenSeq; }
+
+ private:
+ State S;
+ /// Whether we're in the pp-import-suffix following the header-name in a
+ /// pp-import. If so, a close-brace is not sufficient to end the
+ /// top-level-token-seq of an import-seq.
+ bool AfterHeaderName = false;
+ };
+
+ /// Our current position within a C++20 import-seq.
+ StdCXXImportSeq StdCXXImportSeqState = StdCXXImportSeq::AfterTopLevelTokenSeq;
+
+ /// Track whether we are in a Global Module Fragment
+ class TrackGMF {
+ public:
+ enum GMFState : int {
+ GMFActive = 1,
+ MaybeGMF = 0,
+ BeforeGMFIntroducer = -1,
+ GMFAbsentOrEnded = -2,
+ };
+
+ TrackGMF(GMFState S) : S(S) {}
+
+ /// Saw a semicolon.
+ void handleSemi() {
+ // If it is immediately after the first instance of the module keyword,
+ // then that introduces the GMF.
+ if (S == MaybeGMF)
+ S = GMFActive;
+ }
+
+ /// Saw an 'export' identifier.
+ void handleExport() {
+ // The presence of an 'export' keyword always ends or excludes a GMF.
+ S = GMFAbsentOrEnded;
+ }
+
+ /// Saw an 'import' identifier.
+ void handleImport(bool AfterTopLevelTokenSeq) {
+ // If we see this before any 'module' kw, then we have no GMF.
+ if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
+ S = GMFAbsentOrEnded;
+ }
+
+ /// Saw a 'module' identifier.
+ void handleModule(bool AfterTopLevelTokenSeq) {
+ // This was the first module identifier and not preceded by any token
+ // that would exclude a GMF. It could begin a GMF, but only if directly
+ // followed by a semicolon.
+ if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
+ S = MaybeGMF;
+ else
+ S = GMFAbsentOrEnded;
+ }
+
+ /// Saw any other token.
+ void handleMisc() {
+ // We saw something other than ; after the 'module' kw, so not a GMF.
+ if (S == MaybeGMF)
+ S = GMFAbsentOrEnded;
+ }
+
+ bool inGMF() { return S == GMFActive; }
+
+ private:
+ /// Track the transitions into and out of a Global Module Fragment,
+ /// if one is present.
+ GMFState S;
+ };
+
+ TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer;
+
+ /// Track the status of the c++20 module decl.
+ ///
+ /// module-declaration:
+ /// 'export'[opt] 'module' module-name module-partition[opt]
+ /// attribute-specifier-seq[opt] ';'
+ ///
+ /// module-name:
+ /// module-name-qualifier[opt] identifier
+ ///
+ /// module-partition:
+ /// ':' module-name-qualifier[opt] identifier
+ ///
+ /// module-name-qualifier:
+ /// identifier '.'
+ /// module-name-qualifier identifier '.'
+ ///
+ /// Transition state:
+ ///
+ /// NotAModuleDecl --- export ---> FoundExport
+ /// NotAModuleDecl --- module ---> ImplementationCandidate
+ /// FoundExport --- module ---> InterfaceCandidate
+ /// ImplementationCandidate --- Identifier ---> ImplementationCandidate
+ /// ImplementationCandidate --- period ---> ImplementationCandidate
+ /// ImplementationCandidate --- colon ---> ImplementationCandidate
+ /// InterfaceCandidate --- Identifier ---> InterfaceCandidate
+ /// InterfaceCandidate --- period ---> InterfaceCandidate
+ /// InterfaceCandidate --- colon ---> InterfaceCandidate
+ /// ImplementationCandidate --- Semi ---> NamedModuleImplementation
+ /// NamedModuleInterface --- Semi ---> NamedModuleInterface
+ /// NamedModuleImplementation --- Anything ---> NamedModuleImplementation
+ /// NamedModuleInterface --- Anything ---> NamedModuleInterface
+ ///
+ /// FIXME: We haven't handle attribute-specifier-seq here. It may not be bad
+ /// soon since we don't support any module attributes yet.
+ class ModuleDeclSeq {
+ enum ModuleDeclState : int {
+ NotAModuleDecl,
+ FoundExport,
+ InterfaceCandidate,
+ ImplementationCandidate,
+ NamedModuleInterface,
+ NamedModuleImplementation,
+ };
+
+ public:
+ ModuleDeclSeq() : State(NotAModuleDecl) {}
+
+ void handleExport() {
+ if (State == NotAModuleDecl)
+ State = FoundExport;
+ else if (!isNamedModule())
+ reset();
+ }
+
+ void handleModule() {
+ if (State == FoundExport)
+ State = InterfaceCandidate;
+ else if (State == NotAModuleDecl)
+ State = ImplementationCandidate;
+ else if (!isNamedModule())
+ reset();
+ }
+
+ void handleIdentifier(IdentifierInfo *Identifier) {
+ if (isModuleCandidate() && Identifier)
+ Name += Identifier->getName().str();
+ else if (!isNamedModule())
+ reset();
+ }
+
+ void handleColon() {
+ if (isModuleCandidate())
+ Name += ":";
+ else if (!isNamedModule())
+ reset();
+ }
+
+ void handlePeriod() {
+ if (isModuleCandidate())
+ Name += ".";
+ else if (!isNamedModule())
+ reset();
+ }
+
+ void handleSemi() {
+ if (!Name.empty() && isModuleCandidate()) {
+ if (State == InterfaceCandidate)
+ State = NamedModuleInterface;
+ else if (State == ImplementationCandidate)
+ State = NamedModuleImplementation;
+ else
+ llvm_unreachable("Unimaged ModuleDeclState.");
+ } else if (!isNamedModule())
+ reset();
+ }
+
+ void handleMisc() {
+ if (!isNamedModule())
+ reset();
+ }
+
+ bool isModuleCandidate() const {
+ return State == InterfaceCandidate || State == ImplementationCandidate;
+ }
+
+ bool isNamedModule() const {
+ return State == NamedModuleInterface ||
+ State == NamedModuleImplementation;
+ }
+
+ bool isNamedInterface() const { return State == NamedModuleInterface; }
+
+ bool isImplementationUnit() const {
+ return State == NamedModuleImplementation && !getName().contains(':');
+ }
+
+ StringRef getName() const {
+ assert(isNamedModule() && "Can't get name from a non named module");
+ return Name;
+ }
+
+ StringRef getPrimaryName() const {
+ assert(isNamedModule() && "Can't get name from a non named module");
+ return getName().split(':').first;
+ }
+
+ void reset() {
+ Name.clear();
+ State = NotAModuleDecl;
+ }
+
+ private:
+ ModuleDeclState State;
+ std::string Name;
+ };
+
+ ModuleDeclSeq ModuleDeclState;
+
+ /// Whether the module import expects an identifier next. Otherwise,
+ /// it expects a '.' or ';'.
+ bool ModuleImportExpectsIdentifier = false;
+
+ /// The identifier and source location of the currently-active
+ /// \#pragma clang arc_cf_code_audited begin.
+ std::pair<IdentifierInfo *, SourceLocation> PragmaARCCFCodeAuditedInfo;
+
+ /// The source location of the currently-active
+ /// \#pragma clang assume_nonnull begin.
+ SourceLocation PragmaAssumeNonNullLoc;
+
+ /// Set only for preambles which end with an active
+ /// \#pragma clang assume_nonnull begin.
+ ///
+ /// When the preamble is loaded into the main file,
+ /// `PragmaAssumeNonNullLoc` will be set to this to
+ /// replay the unterminated assume_nonnull.
+ SourceLocation PreambleRecordedPragmaAssumeNonNullLoc;
+
+ /// True if we hit the code-completion point.
+ bool CodeCompletionReached = false;
+
+ /// The code completion token containing the information
+ /// on the stem that is to be code completed.
+ IdentifierInfo *CodeCompletionII = nullptr;
+
+ /// Range for the code completion token.
+ SourceRange CodeCompletionTokenRange;
+
+ /// The directory that the main file should be considered to occupy,
+ /// if it does not correspond to a real file (as happens when building a
+ /// module).
+ const DirectoryEntry *MainFileDir = nullptr;
+
+ /// The number of bytes that we will initially skip when entering the
+ /// main file, along with a flag that indicates whether skipping this number
+ /// of bytes will place the lexer at the start of a line.
+ ///
+ /// This is used when loading a precompiled preamble.
+ std::pair<int, bool> SkipMainFilePreamble;
+
+ /// Whether we hit an error due to reaching max allowed include depth. Allows
+ /// to avoid hitting the same error over and over again.
+ bool HasReachedMaxIncludeDepth = false;
+
+ /// The number of currently-active calls to Lex.
+ ///
+ /// Lex is reentrant, and asking for an (end-of-phase-4) token can often
+ /// require asking for multiple additional tokens. This counter makes it
+ /// possible for Lex to detect whether it's producing a token for the end
+ /// of phase 4 of translation or for some other situation.
+ unsigned LexLevel = 0;
+
+ /// The number of (LexLevel 0) preprocessor tokens.
+ unsigned TokenCount = 0;
+
+ /// Preprocess every token regardless of LexLevel.
+ bool PreprocessToken = false;
+
+ /// The maximum number of (LexLevel 0) tokens before issuing a -Wmax-tokens
+ /// warning, or zero for unlimited.
+ unsigned MaxTokens = 0;
+ SourceLocation MaxTokensOverrideLoc;
+
+public:
+ struct PreambleSkipInfo {
+ SourceLocation HashTokenLoc;
+ SourceLocation IfTokenLoc;
+ bool FoundNonSkipPortion;
+ bool FoundElse;
+ SourceLocation ElseLoc;
+
+ PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse,
+ SourceLocation ElseLoc)
+ : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc),
+ FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse),
+ ElseLoc(ElseLoc) {}
+ };
+
+ using IncludedFilesSet = llvm::DenseSet<const FileEntry *>;
+
+private:
+ friend class ASTReader;
+ friend class MacroArgs;
+
+ class PreambleConditionalStackStore {
+ enum State {
+ Off = 0,
+ Recording = 1,
+ Replaying = 2,
+ };
+
+ public:
+ PreambleConditionalStackStore() = default;
+
+ void startRecording() { ConditionalStackState = Recording; }
+ void startReplaying() { ConditionalStackState = Replaying; }
+ bool isRecording() const { return ConditionalStackState == Recording; }
+ bool isReplaying() const { return ConditionalStackState == Replaying; }
+
+ ArrayRef<PPConditionalInfo> getStack() const {
+ return ConditionalStack;
+ }
+
+ void doneReplaying() {
+ ConditionalStack.clear();
+ ConditionalStackState = Off;
+ }
+
+ void setStack(ArrayRef<PPConditionalInfo> s) {
+ if (!isRecording() && !isReplaying())
+ return;
+ ConditionalStack.clear();
+ ConditionalStack.append(s.begin(), s.end());
+ }
+
+ bool hasRecordedPreamble() const { return !ConditionalStack.empty(); }
+
+ bool reachedEOFWhileSkipping() const { return SkipInfo.has_value(); }
+
+ void clearSkipInfo() { SkipInfo.reset(); }
+
+ std::optional<PreambleSkipInfo> SkipInfo;
+
+ private:
+ SmallVector<PPConditionalInfo, 4> ConditionalStack;
+ State ConditionalStackState = Off;
+ } PreambleConditionalStack;
+
+ /// The current top of the stack that we're lexing from if
+ /// not expanding a macro and we are lexing directly from source code.
+ ///
+ /// Only one of CurLexer, or CurTokenLexer will be non-null.
+ std::unique_ptr<Lexer> CurLexer;
+
+ /// The current top of the stack what we're lexing from
+ /// if not expanding a macro.
+ ///
+ /// This is an alias for CurLexer.
+ PreprocessorLexer *CurPPLexer = nullptr;
+
+ /// Used to find the current FileEntry, if CurLexer is non-null
+ /// and if applicable.
+ ///
+ /// This allows us to implement \#include_next and find directory-specific
+ /// properties.
+ ConstSearchDirIterator CurDirLookup = nullptr;
+
+ /// The current macro we are expanding, if we are expanding a macro.
+ ///
+ /// One of CurLexer and CurTokenLexer must be null.
+ std::unique_ptr<TokenLexer> CurTokenLexer;
+
+ /// The kind of lexer we're currently working with.
+ enum CurLexerKind {
+ CLK_Lexer,
+ CLK_TokenLexer,
+ CLK_CachingLexer,
+ CLK_DependencyDirectivesLexer,
+ CLK_LexAfterModuleImport
+ } CurLexerKind = CLK_Lexer;
+
+ /// If the current lexer is for a submodule that is being built, this
+ /// is that submodule.
+ Module *CurLexerSubmodule = nullptr;
+
+ /// Keeps track of the stack of files currently
+ /// \#included, and macros currently being expanded from, not counting
+ /// CurLexer/CurTokenLexer.
+ struct IncludeStackInfo {
+ enum CurLexerKind CurLexerKind;
+ Module *TheSubmodule;
+ std::unique_ptr<Lexer> TheLexer;
+ PreprocessorLexer *ThePPLexer;
+ std::unique_ptr<TokenLexer> TheTokenLexer;
+ ConstSearchDirIterator TheDirLookup;
+
+ // The following constructors are completely useless copies of the default
+ // versions, only needed to pacify MSVC.
+ IncludeStackInfo(enum CurLexerKind CurLexerKind, Module *TheSubmodule,
+ std::unique_ptr<Lexer> &&TheLexer,
+ PreprocessorLexer *ThePPLexer,
+ std::unique_ptr<TokenLexer> &&TheTokenLexer,
+ ConstSearchDirIterator TheDirLookup)
+ : CurLexerKind(std::move(CurLexerKind)),
+ TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
+ ThePPLexer(std::move(ThePPLexer)),
+ TheTokenLexer(std::move(TheTokenLexer)),
+ TheDirLookup(std::move(TheDirLookup)) {}
+ };
+ std::vector<IncludeStackInfo> IncludeMacroStack;
+
+ /// Actions invoked when some preprocessor activity is
+ /// encountered (e.g. a file is \#included, etc).
+ std::unique_ptr<PPCallbacks> Callbacks;
+
+ struct MacroExpandsInfo {
+ Token Tok;
+ MacroDefinition MD;
+ SourceRange Range;
+
+ MacroExpandsInfo(Token Tok, MacroDefinition MD, SourceRange Range)
+ : Tok(Tok), MD(MD), Range(Range) {}
+ };
+ SmallVector<MacroExpandsInfo, 2> DelayedMacroExpandsCallbacks;
+
+ /// Information about a name that has been used to define a module macro.
+ struct ModuleMacroInfo {
+ /// The most recent macro directive for this identifier.
+ MacroDirective *MD;
+
+ /// The active module macros for this identifier.
+ llvm::TinyPtrVector<ModuleMacro *> ActiveModuleMacros;
+
+ /// The generation number at which we last updated ActiveModuleMacros.
+ /// \see Preprocessor::VisibleModules.
+ unsigned ActiveModuleMacrosGeneration = 0;
+
+ /// Whether this macro name is ambiguous.
+ bool IsAmbiguous = false;
+
+ /// The module macros that are overridden by this macro.
+ llvm::TinyPtrVector<ModuleMacro *> OverriddenMacros;
+
+ ModuleMacroInfo(MacroDirective *MD) : MD(MD) {}
+ };
+
+ /// The state of a macro for an identifier.
+ class MacroState {
+ mutable llvm::PointerUnion<MacroDirective *, ModuleMacroInfo *> State;
+
+ ModuleMacroInfo *getModuleInfo(Preprocessor &PP,
+ const IdentifierInfo *II) const {
+ if (II->isOutOfDate())
+ PP.updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
+ // FIXME: Find a spare bit on IdentifierInfo and store a
+ // HasModuleMacros flag.
+ if (!II->hasMacroDefinition() ||
+ (!PP.getLangOpts().Modules &&
+ !PP.getLangOpts().ModulesLocalVisibility) ||
+ !PP.CurSubmoduleState->VisibleModules.getGeneration())
+ return nullptr;
+
+ auto *Info = State.dyn_cast<ModuleMacroInfo*>();
+ if (!Info) {
+ Info = new (PP.getPreprocessorAllocator())
+ ModuleMacroInfo(State.get<MacroDirective *>());
+ State = Info;
+ }
+
+ if (PP.CurSubmoduleState->VisibleModules.getGeneration() !=
+ Info->ActiveModuleMacrosGeneration)
+ PP.updateModuleMacroInfo(II, *Info);
+ return Info;
+ }
+
+ public:
+ MacroState() : MacroState(nullptr) {}
+ MacroState(MacroDirective *MD) : State(MD) {}
+
+ MacroState(MacroState &&O) noexcept : State(O.State) {
+ O.State = (MacroDirective *)nullptr;
+ }
+
+ MacroState &operator=(MacroState &&O) noexcept {
+ auto S = O.State;
+ O.State = (MacroDirective *)nullptr;
+ State = S;
+ return *this;
+ }
+
+ ~MacroState() {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ Info->~ModuleMacroInfo();
+ }
+
+ MacroDirective *getLatest() const {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ return Info->MD;
+ return State.get<MacroDirective*>();
+ }
+
+ void setLatest(MacroDirective *MD) {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ Info->MD = MD;
+ else
+ State = MD;
+ }
+
+ bool isAmbiguous(Preprocessor &PP, const IdentifierInfo *II) const {
+ auto *Info = getModuleInfo(PP, II);
+ return Info ? Info->IsAmbiguous : false;
+ }
+
+ ArrayRef<ModuleMacro *>
+ getActiveModuleMacros(Preprocessor &PP, const IdentifierInfo *II) const {
+ if (auto *Info = getModuleInfo(PP, II))
+ return Info->ActiveModuleMacros;
+ return std::nullopt;
+ }
+
+ MacroDirective::DefInfo findDirectiveAtLoc(SourceLocation Loc,
+ SourceManager &SourceMgr) const {
+ // FIXME: Incorporate module macros into the result of this.
+ if (auto *Latest = getLatest())
+ return Latest->findDirectiveAtLoc(Loc, SourceMgr);
+ return {};
+ }
+
+ void overrideActiveModuleMacros(Preprocessor &PP, IdentifierInfo *II) {
+ if (auto *Info = getModuleInfo(PP, II)) {
+ Info->OverriddenMacros.insert(Info->OverriddenMacros.end(),
+ Info->ActiveModuleMacros.begin(),
+ Info->ActiveModuleMacros.end());
+ Info->ActiveModuleMacros.clear();
+ Info->IsAmbiguous = false;
+ }
+ }
+
+ ArrayRef<ModuleMacro*> getOverriddenMacros() const {
+ if (auto *Info = State.dyn_cast<ModuleMacroInfo*>())
+ return Info->OverriddenMacros;
+ return std::nullopt;
+ }
+
+ void setOverriddenMacros(Preprocessor &PP,
+ ArrayRef<ModuleMacro *> Overrides) {
+ auto *Info = State.dyn_cast<ModuleMacroInfo*>();
+ if (!Info) {
+ if (Overrides.empty())
+ return;
+ Info = new (PP.getPreprocessorAllocator())
+ ModuleMacroInfo(State.get<MacroDirective *>());
+ State = Info;
+ }
+ Info->OverriddenMacros.clear();
+ Info->OverriddenMacros.insert(Info->OverriddenMacros.end(),
+ Overrides.begin(), Overrides.end());
+ Info->ActiveModuleMacrosGeneration = 0;
+ }
+ };
+
+ /// For each IdentifierInfo that was associated with a macro, we
+ /// keep a mapping to the history of all macro definitions and #undefs in
+ /// the reverse order (the latest one is in the head of the list).
+ ///
+ /// This mapping lives within the \p CurSubmoduleState.
+ using MacroMap = llvm::DenseMap<const IdentifierInfo *, MacroState>;
+
+ struct SubmoduleState;
+
+ /// Information about a submodule that we're currently building.
+ struct BuildingSubmoduleInfo {
+ /// The module that we are building.
+ Module *M;
+
+ /// The location at which the module was included.
+ SourceLocation ImportLoc;
+
+ /// Whether we entered this submodule via a pragma.
+ bool IsPragma;
+
+ /// The previous SubmoduleState.
+ SubmoduleState *OuterSubmoduleState;
+
+ /// The number of pending module macro names when we started building this.
+ unsigned OuterPendingModuleMacroNames;
+
+ BuildingSubmoduleInfo(Module *M, SourceLocation ImportLoc, bool IsPragma,
+ SubmoduleState *OuterSubmoduleState,
+ unsigned OuterPendingModuleMacroNames)
+ : M(M), ImportLoc(ImportLoc), IsPragma(IsPragma),
+ OuterSubmoduleState(OuterSubmoduleState),
+ OuterPendingModuleMacroNames(OuterPendingModuleMacroNames) {}
+ };
+ SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
+
+ /// Information about a submodule's preprocessor state.
+ struct SubmoduleState {
+ /// The macros for the submodule.
+ MacroMap Macros;
+
+ /// The set of modules that are visible within the submodule.
+ VisibleModuleSet VisibleModules;
+
+ // FIXME: CounterValue?
+ // FIXME: PragmaPushMacroInfo?
+ };
+ std::map<Module *, SubmoduleState> Submodules;
+
+ /// The preprocessor state for preprocessing outside of any submodule.
+ SubmoduleState NullSubmoduleState;
+
+ /// The current submodule state. Will be \p NullSubmoduleState if we're not
+ /// in a submodule.
+ SubmoduleState *CurSubmoduleState;
+
+ /// The files that have been included.
+ IncludedFilesSet IncludedFiles;
+
+ /// The set of top-level modules that affected preprocessing, but were not
+ /// imported.
+ llvm::SmallSetVector<Module *, 2> AffectingClangModules;
+
+ /// The set of known macros exported from modules.
+ llvm::FoldingSet<ModuleMacro> ModuleMacros;
+
+ /// The names of potential module macros that we've not yet processed.
+ llvm::SmallVector<const IdentifierInfo *, 32> PendingModuleMacroNames;
+
+ /// The list of module macros, for each identifier, that are not overridden by
+ /// any other module macro.
+ llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>>
+ LeafModuleMacros;
+
+ /// Macros that we want to warn because they are not used at the end
+ /// of the translation unit.
+ ///
+ /// We store just their SourceLocations instead of
+ /// something like MacroInfo*. The benefit of this is that when we are
+ /// deserializing from PCH, we don't need to deserialize identifier & macros
+ /// just so that we can report that they are unused, we just warn using
+ /// the SourceLocations of this set (that will be filled by the ASTReader).
+ using WarnUnusedMacroLocsTy = llvm::SmallDenseSet<SourceLocation, 32>;
+ WarnUnusedMacroLocsTy WarnUnusedMacroLocs;
+
+ /// This is a pair of an optional message and source location used for pragmas
+ /// that annotate macros like pragma clang restrict_expansion and pragma clang
+ /// deprecated. This pair stores the optional message and the location of the
+ /// annotation pragma for use producing diagnostics and notes.
+ using MsgLocationPair = std::pair<std::string, SourceLocation>;
+
+ struct MacroAnnotationInfo {
+ SourceLocation Location;
+ std::string Message;
+ };
+
+ struct MacroAnnotations {
+ std::optional<MacroAnnotationInfo> DeprecationInfo;
+ std::optional<MacroAnnotationInfo> RestrictExpansionInfo;
+ std::optional<SourceLocation> FinalAnnotationLoc;
+
+ static MacroAnnotations makeDeprecation(SourceLocation Loc,
+ std::string Msg) {
+ return MacroAnnotations{MacroAnnotationInfo{Loc, std::move(Msg)},
+ std::nullopt, std::nullopt};
+ }
+
+ static MacroAnnotations makeRestrictExpansion(SourceLocation Loc,
+ std::string Msg) {
+ return MacroAnnotations{
+ std::nullopt, MacroAnnotationInfo{Loc, std::move(Msg)}, std::nullopt};
+ }
+
+ static MacroAnnotations makeFinal(SourceLocation Loc) {
+ return MacroAnnotations{std::nullopt, std::nullopt, Loc};
+ }
+ };
+
+ /// Warning information for macro annotations.
+ llvm::DenseMap<const IdentifierInfo *, MacroAnnotations> AnnotationInfos;
+
+ /// A "freelist" of MacroArg objects that can be
+ /// reused for quick allocation.
+ MacroArgs *MacroArgCache = nullptr;
+
+ /// For each IdentifierInfo used in a \#pragma push_macro directive,
+ /// we keep a MacroInfo stack used to restore the previous macro value.
+ llvm::DenseMap<IdentifierInfo *, std::vector<MacroInfo *>>
+ PragmaPushMacroInfo;
+
+ // Various statistics we track for performance analysis.
+ unsigned NumDirectives = 0;
+ unsigned NumDefined = 0;
+ unsigned NumUndefined = 0;
+ unsigned NumPragma = 0;
+ unsigned NumIf = 0;
+ unsigned NumElse = 0;
+ unsigned NumEndif = 0;
+ unsigned NumEnteredSourceFiles = 0;
+ unsigned MaxIncludeStackDepth = 0;
+ unsigned NumMacroExpanded = 0;
+ unsigned NumFnMacroExpanded = 0;
+ unsigned NumBuiltinMacroExpanded = 0;
+ unsigned NumFastMacroExpanded = 0;
+ unsigned NumTokenPaste = 0;
+ unsigned NumFastTokenPaste = 0;
+ unsigned NumSkipped = 0;
+
+ /// The predefined macros that preprocessor should use from the
+ /// command line etc.
+ std::string Predefines;
+
+ /// The file ID for the preprocessor predefines.
+ FileID PredefinesFileID;
+
+ /// The file ID for the PCH through header.
+ FileID PCHThroughHeaderFileID;
+
+ /// Whether tokens are being skipped until a #pragma hdrstop is seen.
+ bool SkippingUntilPragmaHdrStop = false;
+
+ /// Whether tokens are being skipped until the through header is seen.
+ bool SkippingUntilPCHThroughHeader = false;
+
+ /// \{
+ /// Cache of macro expanders to reduce malloc traffic.
+ enum { TokenLexerCacheSize = 8 };
+ unsigned NumCachedTokenLexers;
+ std::unique_ptr<TokenLexer> TokenLexerCache[TokenLexerCacheSize];
+ /// \}
+
+ /// Keeps macro expanded tokens for TokenLexers.
+ //
+ /// Works like a stack; a TokenLexer adds the macro expanded tokens that is
+ /// going to lex in the cache and when it finishes the tokens are removed
+ /// from the end of the cache.
+ SmallVector<Token, 16> MacroExpandedTokens;
+ std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack;
+
+ /// A record of the macro definitions and expansions that
+ /// occurred during preprocessing.
+ ///
+ /// This is an optional side structure that can be enabled with
+ /// \c createPreprocessingRecord() prior to preprocessing.
+ PreprocessingRecord *Record = nullptr;
+
+ /// Cached tokens state.
+ using CachedTokensTy = SmallVector<Token, 1>;
+
+ /// Cached tokens are stored here when we do backtracking or
+ /// lookahead. They are "lexed" by the CachingLex() method.
+ CachedTokensTy CachedTokens;
+
+ /// The position of the cached token that CachingLex() should
+ /// "lex" next.
+ ///
+ /// If it points beyond the CachedTokens vector, it means that a normal
+ /// Lex() should be invoked.
+ CachedTokensTy::size_type CachedLexPos = 0;
+
+ /// Stack of backtrack positions, allowing nested backtracks.
+ ///
+ /// The EnableBacktrackAtThisPos() method pushes a position to
+ /// indicate where CachedLexPos should be set when the BackTrack() method is
+ /// invoked (at which point the last position is popped).
+ std::vector<CachedTokensTy::size_type> BacktrackPositions;
+
+ /// True if \p Preprocessor::SkipExcludedConditionalBlock() is running.
+ /// This is used to guard against calling this function recursively.
+ ///
+ /// See comments at the use-site for more context about why it is needed.
+ bool SkippingExcludedConditionalBlock = false;
+
+ /// Keeps track of skipped range mappings that were recorded while skipping
+ /// excluded conditional directives. It maps the source buffer pointer at
+ /// the beginning of a skipped block, to the number of bytes that should be
+ /// skipped.
+ llvm::DenseMap<const char *, unsigned> RecordedSkippedRanges;
+
+ void updateOutOfDateIdentifier(IdentifierInfo &II) const;
+
+public:
+ Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
+ DiagnosticsEngine &diags, LangOptions &opts, SourceManager &SM,
+ HeaderSearch &Headers, ModuleLoader &TheModuleLoader,
+ IdentifierInfoLookup *IILookup = nullptr,
+ bool OwnsHeaderSearch = false,
+ TranslationUnitKind TUKind = TU_Complete);
+
+ ~Preprocessor();
+
+ /// Initialize the preprocessor using information about the target.
+ ///
+ /// \param Target is owned by the caller and must remain valid for the
+ /// lifetime of the preprocessor.
+ /// \param AuxTarget is owned by the caller and must remain valid for
+ /// the lifetime of the preprocessor.
+ void Initialize(const TargetInfo &Target,
+ const TargetInfo *AuxTarget = nullptr);
+
+ /// Initialize the preprocessor to parse a model file
+ ///
+ /// To parse model files the preprocessor of the original source is reused to
+ /// preserver the identifier table. However to avoid some duplicate
+ /// information in the preprocessor some cleanup is needed before it is used
+ /// to parse model files. This method does that cleanup.
+ void InitializeForModelFile();
+
+ /// Cleanup after model file parsing
+ void FinalizeForModelFile();
+
+ /// Retrieve the preprocessor options used to initialize this
+ /// preprocessor.
+ PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; }
+
+ DiagnosticsEngine &getDiagnostics() const { return *Diags; }
+ void setDiagnostics(DiagnosticsEngine &D) { Diags = &D; }
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ const TargetInfo &getTargetInfo() const { return *Target; }
+ const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
+ FileManager &getFileManager() const { return FileMgr; }
+ SourceManager &getSourceManager() const { return SourceMgr; }
+ HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
+
+ IdentifierTable &getIdentifierTable() { return Identifiers; }
+ const IdentifierTable &getIdentifierTable() const { return Identifiers; }
+ SelectorTable &getSelectorTable() { return Selectors; }
+ Builtin::Context &getBuiltinInfo() { return *BuiltinInfo; }
+ llvm::BumpPtrAllocator &getPreprocessorAllocator() { return BP; }
+
+ void setExternalSource(ExternalPreprocessorSource *Source) {
+ ExternalSource = Source;
+ }
+
+ ExternalPreprocessorSource *getExternalSource() const {
+ return ExternalSource;
+ }
+
+ /// Retrieve the module loader associated with this preprocessor.
+ ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
+
+ bool hadModuleLoaderFatalFailure() const {
+ return TheModuleLoader.HadFatalFailure;
+ }
+
+ /// Retrieve the number of Directives that have been processed by the
+ /// Preprocessor.
+ unsigned getNumDirectives() const {
+ return NumDirectives;
+ }
+
+ /// True if we are currently preprocessing a #if or #elif directive
+ bool isParsingIfOrElifDirective() const {
+ return ParsingIfOrElifDirective;
+ }
+
+ /// Control whether the preprocessor retains comments in output.
+ void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) {
+ this->KeepComments = KeepComments | KeepMacroComments;
+ this->KeepMacroComments = KeepMacroComments;
+ }
+
+ bool getCommentRetentionState() const { return KeepComments; }
+
+ void setPragmasEnabled(bool Enabled) { PragmasEnabled = Enabled; }
+ bool getPragmasEnabled() const { return PragmasEnabled; }
+
+ void SetSuppressIncludeNotFoundError(bool Suppress) {
+ SuppressIncludeNotFoundError = Suppress;
+ }
+
+ bool GetSuppressIncludeNotFoundError() {
+ return SuppressIncludeNotFoundError;
+ }
+
+ /// Sets whether the preprocessor is responsible for producing output or if
+ /// it is producing tokens to be consumed by Parse and Sema.
+ void setPreprocessedOutput(bool IsPreprocessedOutput) {
+ PreprocessedOutput = IsPreprocessedOutput;
+ }
+
+ /// Returns true if the preprocessor is responsible for generating output,
+ /// false if it is producing tokens to be consumed by Parse and Sema.
+ bool isPreprocessedOutput() const { return PreprocessedOutput; }
+
+ /// Return true if we are lexing directly from the specified lexer.
+ bool isCurrentLexer(const PreprocessorLexer *L) const {
+ return CurPPLexer == L;
+ }
+
+ /// Return the current lexer being lexed from.
+ ///
+ /// Note that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; }
+
+ /// Return the current file lexer being lexed from.
+ ///
+ /// Note that this ignores any potentially active macro expansions and _Pragma
+ /// expansions going on at the time.
+ PreprocessorLexer *getCurrentFileLexer() const;
+
+ /// Return the submodule owning the file being lexed. This may not be
+ /// the current module if we have changed modules since entering the file.
+ Module *getCurrentLexerSubmodule() const { return CurLexerSubmodule; }
+
+ /// Returns the FileID for the preprocessor predefines.
+ FileID getPredefinesFileID() const { return PredefinesFileID; }
+
+ /// \{
+ /// Accessors for preprocessor callbacks.
+ ///
+ /// Note that this class takes ownership of any PPCallbacks object given to
+ /// it.
+ PPCallbacks *getPPCallbacks() const { return Callbacks.get(); }
+ void addPPCallbacks(std::unique_ptr<PPCallbacks> C) {
+ if (Callbacks)
+ C = std::make_unique<PPChainedCallbacks>(std::move(C),
+ std::move(Callbacks));
+ Callbacks = std::move(C);
+ }
+ /// \}
+
+ /// Get the number of tokens processed so far.
+ unsigned getTokenCount() const { return TokenCount; }
+
+ /// Get the max number of tokens before issuing a -Wmax-tokens warning.
+ unsigned getMaxTokens() const { return MaxTokens; }
+
+ void overrideMaxTokens(unsigned Value, SourceLocation Loc) {
+ MaxTokens = Value;
+ MaxTokensOverrideLoc = Loc;
+ };
+
+ SourceLocation getMaxTokensOverrideLoc() const { return MaxTokensOverrideLoc; }
+
+ /// Register a function that would be called on each token in the final
+ /// expanded token stream.
+ /// This also reports annotation tokens produced by the parser.
+ void setTokenWatcher(llvm::unique_function<void(const clang::Token &)> F) {
+ OnToken = std::move(F);
+ }
+
+ void setPreprocessToken(bool Preprocess) { PreprocessToken = Preprocess; }
+
+ bool isMacroDefined(StringRef Id) {
+ return isMacroDefined(&Identifiers.get(Id));
+ }
+ bool isMacroDefined(const IdentifierInfo *II) {
+ return II->hasMacroDefinition() &&
+ (!getLangOpts().Modules || (bool)getMacroDefinition(II));
+ }
+
+ /// Determine whether II is defined as a macro within the module M,
+ /// if that is a module that we've already preprocessed. Does not check for
+ /// macros imported into M.
+ bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) {
+ if (!II->hasMacroDefinition())
+ return false;
+ auto I = Submodules.find(M);
+ if (I == Submodules.end())
+ return false;
+ auto J = I->second.Macros.find(II);
+ if (J == I->second.Macros.end())
+ return false;
+ auto *MD = J->second.getLatest();
+ return MD && MD->isDefined();
+ }
+
+ MacroDefinition getMacroDefinition(const IdentifierInfo *II) {
+ if (!II->hasMacroDefinition())
+ return {};
+
+ MacroState &S = CurSubmoduleState->Macros[II];
+ auto *MD = S.getLatest();
+ while (MD && isa<VisibilityMacroDirective>(MD))
+ MD = MD->getPrevious();
+ return MacroDefinition(dyn_cast_or_null<DefMacroDirective>(MD),
+ S.getActiveModuleMacros(*this, II),
+ S.isAmbiguous(*this, II));
+ }
+
+ MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II,
+ SourceLocation Loc) {
+ if (!II->hadMacroDefinition())
+ return {};
+
+ MacroState &S = CurSubmoduleState->Macros[II];
+ MacroDirective::DefInfo DI;
+ if (auto *MD = S.getLatest())
+ DI = MD->findDirectiveAtLoc(Loc, getSourceManager());
+ // FIXME: Compute the set of active module macros at the specified location.
+ return MacroDefinition(DI.getDirective(),
+ S.getActiveModuleMacros(*this, II),
+ S.isAmbiguous(*this, II));
+ }
+
+ /// Given an identifier, return its latest non-imported MacroDirective
+ /// if it is \#define'd and not \#undef'd, or null if it isn't \#define'd.
+ MacroDirective *getLocalMacroDirective(const IdentifierInfo *II) const {
+ if (!II->hasMacroDefinition())
+ return nullptr;
+
+ auto *MD = getLocalMacroDirectiveHistory(II);
+ if (!MD || MD->getDefinition().isUndefined())
+ return nullptr;
+
+ return MD;
+ }
+
+ const MacroInfo *getMacroInfo(const IdentifierInfo *II) const {
+ return const_cast<Preprocessor*>(this)->getMacroInfo(II);
+ }
+
+ MacroInfo *getMacroInfo(const IdentifierInfo *II) {
+ if (!II->hasMacroDefinition())
+ return nullptr;
+ if (auto MD = getMacroDefinition(II))
+ return MD.getMacroInfo();
+ return nullptr;
+ }
+
+ /// Given an identifier, return the latest non-imported macro
+ /// directive for that identifier.
+ ///
+ /// One can iterate over all previous macro directives from the most recent
+ /// one.
+ MacroDirective *getLocalMacroDirectiveHistory(const IdentifierInfo *II) const;
+
+ /// Add a directive to the macro directive history for this identifier.
+ void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD);
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI,
+ SourceLocation Loc) {
+ DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc);
+ appendMacroDirective(II, MD);
+ return MD;
+ }
+ DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II,
+ MacroInfo *MI) {
+ return appendDefMacroDirective(II, MI, MI->getDefinitionLoc());
+ }
+
+ /// Set a MacroDirective that was loaded from a PCH file.
+ void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED,
+ MacroDirective *MD);
+
+ /// Register an exported macro for a module and identifier.
+ ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro,
+ ArrayRef<ModuleMacro *> Overrides, bool &IsNew);
+ ModuleMacro *getModuleMacro(Module *Mod, const IdentifierInfo *II);
+
+ /// Get the list of leaf (non-overridden) module macros for a name.
+ ArrayRef<ModuleMacro*> getLeafModuleMacros(const IdentifierInfo *II) const {
+ if (II->isOutOfDate())
+ updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II));
+ auto I = LeafModuleMacros.find(II);
+ if (I != LeafModuleMacros.end())
+ return I->second;
+ return std::nullopt;
+ }
+
+ /// Get the list of submodules that we're currently building.
+ ArrayRef<BuildingSubmoduleInfo> getBuildingSubmodules() const {
+ return BuildingSubmoduleStack;
+ }
+
+ /// \{
+ /// Iterators for the macro history table. Currently defined macros have
+ /// IdentifierInfo::hasMacroDefinition() set and an empty
+ /// MacroInfo::getUndefLoc() at the head of the list.
+ using macro_iterator = MacroMap::const_iterator;
+
+ macro_iterator macro_begin(bool IncludeExternalMacros = true) const;
+ macro_iterator macro_end(bool IncludeExternalMacros = true) const;
+
+ llvm::iterator_range<macro_iterator>
+ macros(bool IncludeExternalMacros = true) const {
+ macro_iterator begin = macro_begin(IncludeExternalMacros);
+ macro_iterator end = macro_end(IncludeExternalMacros);
+ return llvm::make_range(begin, end);
+ }
+
+ /// \}
+
+ /// Mark the given clang module as affecting the current clang module or translation unit.
+ void markClangModuleAsAffecting(Module *M) {
+ assert(M->isModuleMapModule());
+ if (!BuildingSubmoduleStack.empty()) {
+ if (M != BuildingSubmoduleStack.back().M)
+ BuildingSubmoduleStack.back().M->AffectingClangModules.insert(M);
+ } else {
+ AffectingClangModules.insert(M);
+ }
+ }
+
+ /// Get the set of top-level clang modules that affected preprocessing, but were not
+ /// imported.
+ const llvm::SmallSetVector<Module *, 2> &getAffectingClangModules() const {
+ return AffectingClangModules;
+ }
+
+ /// Mark the file as included.
+ /// Returns true if this is the first time the file was included.
+ bool markIncluded(const FileEntry *File) {
+ HeaderInfo.getFileInfo(File);
+ return IncludedFiles.insert(File).second;
+ }
+
+ /// Return true if this header has already been included.
+ bool alreadyIncluded(const FileEntry *File) const {
+ return IncludedFiles.count(File);
+ }
+
+ /// Get the set of included files.
+ IncludedFilesSet &getIncludedFiles() { return IncludedFiles; }
+ const IncludedFilesSet &getIncludedFiles() const { return IncludedFiles; }
+
+ /// Return the name of the macro defined before \p Loc that has
+ /// spelling \p Tokens. If there are multiple macros with same spelling,
+ /// return the last one defined.
+ StringRef getLastMacroWithSpelling(SourceLocation Loc,
+ ArrayRef<TokenValue> Tokens) const;
+
+ /// Get the predefines for this processor.
+ /// Used by some third-party tools to inspect and add predefines (see
+ /// https://github.com/llvm/llvm-project/issues/57483).
+ const std::string &getPredefines() const { return Predefines; }
+
+ /// Set the predefines for this Preprocessor.
+ ///
+ /// These predefines are automatically injected when parsing the main file.
+ void setPredefines(std::string P) { Predefines = std::move(P); }
+
+ /// Return information about the specified preprocessor
+ /// identifier token.
+ IdentifierInfo *getIdentifierInfo(StringRef Name) const {
+ return &Identifiers.get(Name);
+ }
+
+ /// Add the specified pragma handler to this preprocessor.
+ ///
+ /// If \p Namespace is non-null, then it is a token required to exist on the
+ /// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
+ void AddPragmaHandler(StringRef Namespace, PragmaHandler *Handler);
+ void AddPragmaHandler(PragmaHandler *Handler) {
+ AddPragmaHandler(StringRef(), Handler);
+ }
+
+ /// Remove the specific pragma handler from this preprocessor.
+ ///
+ /// If \p Namespace is non-null, then it should be the namespace that
+ /// \p Handler was added to. It is an error to remove a handler that
+ /// has not been registered.
+ void RemovePragmaHandler(StringRef Namespace, PragmaHandler *Handler);
+ void RemovePragmaHandler(PragmaHandler *Handler) {
+ RemovePragmaHandler(StringRef(), Handler);
+ }
+
+ /// Install empty handlers for all pragmas (making them ignored).
+ void IgnorePragmas();
+
+ /// Set empty line handler.
+ void setEmptylineHandler(EmptylineHandler *Handler) { Emptyline = Handler; }
+
+ EmptylineHandler *getEmptylineHandler() const { return Emptyline; }
+
+ /// Add the specified comment handler to the preprocessor.
+ void addCommentHandler(CommentHandler *Handler);
+
+ /// Remove the specified comment handler.
+ ///
+ /// It is an error to remove a handler that has not been registered.
+ void removeCommentHandler(CommentHandler *Handler);
+
+ /// Set the code completion handler to the given object.
+ void setCodeCompletionHandler(CodeCompletionHandler &Handler) {
+ CodeComplete = &Handler;
+ }
+
+ /// Retrieve the current code-completion handler.
+ CodeCompletionHandler *getCodeCompletionHandler() const {
+ return CodeComplete;
+ }
+
+ /// Clear out the code completion handler.
+ void clearCodeCompletionHandler() {
+ CodeComplete = nullptr;
+ }
+
+ /// Hook used by the lexer to invoke the "included file" code
+ /// completion point.
+ void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
+
+ /// Hook used by the lexer to invoke the "natural language" code
+ /// completion point.
+ void CodeCompleteNaturalLanguage();
+
+ /// Set the code completion token for filtering purposes.
+ void setCodeCompletionIdentifierInfo(IdentifierInfo *Filter) {
+ CodeCompletionII = Filter;
+ }
+
+ /// Set the code completion token range for detecting replacement range later
+ /// on.
+ void setCodeCompletionTokenRange(const SourceLocation Start,
+ const SourceLocation End) {
+ CodeCompletionTokenRange = {Start, End};
+ }
+ SourceRange getCodeCompletionTokenRange() const {
+ return CodeCompletionTokenRange;
+ }
+
+ /// Get the code completion token for filtering purposes.
+ StringRef getCodeCompletionFilter() {
+ if (CodeCompletionII)
+ return CodeCompletionII->getName();
+ return {};
+ }
+
+ /// Retrieve the preprocessing record, or NULL if there is no
+ /// preprocessing record.
+ PreprocessingRecord *getPreprocessingRecord() const { return Record; }
+
+ /// Create a new preprocessing record, which will keep track of
+ /// all macro expansions, macro definitions, etc.
+ void createPreprocessingRecord();
+
+ /// Returns true if the FileEntry is the PCH through header.
+ bool isPCHThroughHeader(const FileEntry *FE);
+
+ /// True if creating a PCH with a through header.
+ bool creatingPCHWithThroughHeader();
+
+ /// True if using a PCH with a through header.
+ bool usingPCHWithThroughHeader();
+
+ /// True if creating a PCH with a #pragma hdrstop.
+ bool creatingPCHWithPragmaHdrStop();
+
+ /// True if using a PCH with a #pragma hdrstop.
+ bool usingPCHWithPragmaHdrStop();
+
+ /// Skip tokens until after the #include of the through header or
+ /// until after a #pragma hdrstop.
+ void SkipTokensWhileUsingPCH();
+
+ /// Process directives while skipping until the through header or
+ /// #pragma hdrstop is found.
+ void HandleSkippedDirectiveWhileUsingPCH(Token &Result,
+ SourceLocation HashLoc);
+
+ /// Enter the specified FileID as the main source file,
+ /// which implicitly adds the builtin defines etc.
+ void EnterMainSourceFile();
+
+ /// Inform the preprocessor callbacks that processing is complete.
+ void EndSourceFile();
+
+ /// Add a source file to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ ///
+ /// Emits a diagnostic, doesn't enter the file, and returns true on error.
+ bool EnterSourceFile(FileID FID, ConstSearchDirIterator Dir,
+ SourceLocation Loc, bool IsFirstIncludeOfFile = true);
+
+ /// Add a Macro to the top of the include stack and start lexing
+ /// tokens from it instead of the current buffer.
+ ///
+ /// \param Args specifies the tokens input to a function-like macro.
+ /// \param ILEnd specifies the location of the ')' for a function-like macro
+ /// or the identifier for an object-like macro.
+ void EnterMacro(Token &Tok, SourceLocation ILEnd, MacroInfo *Macro,
+ MacroArgs *Args);
+
+private:
+ /// Add a "macro" context to the top of the include stack,
+ /// which will cause the lexer to start returning the specified tokens.
+ ///
+ /// If \p DisableMacroExpansion is true, tokens lexed from the token stream
+ /// will not be subject to further macro expansion. Otherwise, these tokens
+ /// will be re-macro-expanded when/if expansion is enabled.
+ ///
+ /// If \p OwnsTokens is false, this method assumes that the specified stream
+ /// of tokens has a permanent owner somewhere, so they do not need to be
+ /// copied. If it is true, it assumes the array of tokens is allocated with
+ /// \c new[] and the Preprocessor will delete[] it.
+ ///
+ /// If \p IsReinject the resulting tokens will have Token::IsReinjected flag
+ /// set, see the flag documentation for details.
+ void EnterTokenStream(const Token *Toks, unsigned NumToks,
+ bool DisableMacroExpansion, bool OwnsTokens,
+ bool IsReinject);
+
+public:
+ void EnterTokenStream(std::unique_ptr<Token[]> Toks, unsigned NumToks,
+ bool DisableMacroExpansion, bool IsReinject) {
+ EnterTokenStream(Toks.release(), NumToks, DisableMacroExpansion, true,
+ IsReinject);
+ }
+
+ void EnterTokenStream(ArrayRef<Token> Toks, bool DisableMacroExpansion,
+ bool IsReinject) {
+ EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false,
+ IsReinject);
+ }
+
+ /// Pop the current lexer/macro exp off the top of the lexer stack.
+ ///
+ /// This should only be used in situations where the current state of the
+ /// top-of-stack lexer is known.
+ void RemoveTopOfLexerStack();
+
+ /// From the point that this method is called, and until
+ /// CommitBacktrackedTokens() or Backtrack() is called, the Preprocessor
+ /// keeps track of the lexed tokens so that a subsequent Backtrack() call will
+ /// make the Preprocessor re-lex the same tokens.
+ ///
+ /// Nested backtracks are allowed, meaning that EnableBacktrackAtThisPos can
+ /// be called multiple times and CommitBacktrackedTokens/Backtrack calls will
+ /// be combined with the EnableBacktrackAtThisPos calls in reverse order.
+ ///
+ /// NOTE: *DO NOT* forget to call either CommitBacktrackedTokens or Backtrack
+ /// at some point after EnableBacktrackAtThisPos. If you don't, caching of
+ /// tokens will continue indefinitely.
+ ///
+ void EnableBacktrackAtThisPos();
+
+ /// Disable the last EnableBacktrackAtThisPos call.
+ void CommitBacktrackedTokens();
+
+ /// Make Preprocessor re-lex the tokens that were lexed since
+ /// EnableBacktrackAtThisPos() was previously called.
+ void Backtrack();
+
+ /// True if EnableBacktrackAtThisPos() was called and
+ /// caching of tokens is on.
+ bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); }
+
+ /// Lex the next token for this preprocessor.
+ void Lex(Token &Result);
+
+ /// Lex a token, forming a header-name token if possible.
+ bool LexHeaderName(Token &Result, bool AllowMacroExpansion = true);
+
+ bool LexAfterModuleImport(Token &Result);
+ void CollectPpImportSuffix(SmallVectorImpl<Token> &Toks);
+
+ void makeModuleVisible(Module *M, SourceLocation Loc);
+
+ SourceLocation getModuleImportLoc(Module *M) const {
+ return CurSubmoduleState->VisibleModules.getImportLoc(M);
+ }
+
+ /// Lex a string literal, which may be the concatenation of multiple
+ /// string literals and may even come from macro expansion.
+ /// \returns true on success, false if a error diagnostic has been generated.
+ bool LexStringLiteral(Token &Result, std::string &String,
+ const char *DiagnosticTag, bool AllowMacroExpansion) {
+ if (AllowMacroExpansion)
+ Lex(Result);
+ else
+ LexUnexpandedToken(Result);
+ return FinishLexStringLiteral(Result, String, DiagnosticTag,
+ AllowMacroExpansion);
+ }
+
+ /// Complete the lexing of a string literal where the first token has
+ /// already been lexed (see LexStringLiteral).
+ bool FinishLexStringLiteral(Token &Result, std::string &String,
+ const char *DiagnosticTag,
+ bool AllowMacroExpansion);
+
+ /// Lex a token. If it's a comment, keep lexing until we get
+ /// something not a comment.
+ ///
+ /// This is useful in -E -C mode where comments would foul up preprocessor
+ /// directive handling.
+ void LexNonComment(Token &Result) {
+ do
+ Lex(Result);
+ while (Result.getKind() == tok::comment);
+ }
+
+ /// Just like Lex, but disables macro expansion of identifier tokens.
+ void LexUnexpandedToken(Token &Result) {
+ // Disable macro expansion.
+ bool OldVal = DisableMacroExpansion;
+ DisableMacroExpansion = true;
+ // Lex the token.
+ Lex(Result);
+
+ // Reenable it.
+ DisableMacroExpansion = OldVal;
+ }
+
+ /// Like LexNonComment, but this disables macro expansion of
+ /// identifier tokens.
+ void LexUnexpandedNonComment(Token &Result) {
+ do
+ LexUnexpandedToken(Result);
+ while (Result.getKind() == tok::comment);
+ }
+
+ /// Parses a simple integer literal to get its numeric value. Floating
+ /// point literals and user defined literals are rejected. Used primarily to
+ /// handle pragmas that accept integer arguments.
+ bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value);
+
+ /// Disables macro expansion everywhere except for preprocessor directives.
+ void SetMacroExpansionOnlyInDirectives() {
+ DisableMacroExpansion = true;
+ MacroExpansionInDirectivesOverride = true;
+ }
+
+ /// Peeks ahead N tokens and returns that token without consuming any
+ /// tokens.
+ ///
+ /// LookAhead(0) returns the next token that would be returned by Lex(),
+ /// LookAhead(1) returns the token after it, etc. This returns normal
+ /// tokens after phase 5. As such, it is equivalent to using
+ /// 'Lex', not 'LexUnexpandedToken'.
+ const Token &LookAhead(unsigned N) {
+ assert(LexLevel == 0 && "cannot use lookahead while lexing");
+ if (CachedLexPos + N < CachedTokens.size())
+ return CachedTokens[CachedLexPos+N];
+ else
+ return PeekAhead(N+1);
+ }
+
+ /// When backtracking is enabled and tokens are cached,
+ /// this allows to revert a specific number of tokens.
+ ///
+ /// Note that the number of tokens being reverted should be up to the last
+ /// backtrack position, not more.
+ void RevertCachedTokens(unsigned N) {
+ assert(isBacktrackEnabled() &&
+ "Should only be called when tokens are cached for backtracking");
+ assert(signed(CachedLexPos) - signed(N) >= signed(BacktrackPositions.back())
+ && "Should revert tokens up to the last backtrack position, not more");
+ assert(signed(CachedLexPos) - signed(N) >= 0 &&
+ "Corrupted backtrack positions ?");
+ CachedLexPos -= N;
+ }
+
+ /// Enters a token in the token stream to be lexed next.
+ ///
+ /// If BackTrack() is called afterwards, the token will remain at the
+ /// insertion point.
+ /// If \p IsReinject is true, resulting token will have Token::IsReinjected
+ /// flag set. See the flag documentation for details.
+ void EnterToken(const Token &Tok, bool IsReinject) {
+ if (LexLevel) {
+ // It's not correct in general to enter caching lex mode while in the
+ // middle of a nested lexing action.
+ auto TokCopy = std::make_unique<Token[]>(1);
+ TokCopy[0] = Tok;
+ EnterTokenStream(std::move(TokCopy), 1, true, IsReinject);
+ } else {
+ EnterCachingLexMode();
+ assert(IsReinject && "new tokens in the middle of cached stream");
+ CachedTokens.insert(CachedTokens.begin()+CachedLexPos, Tok);
+ }
+ }
+
+ /// We notify the Preprocessor that if it is caching tokens (because
+ /// backtrack is enabled) it should replace the most recent cached tokens
+ /// with the given annotation token. This function has no effect if
+ /// backtracking is not enabled.
+ ///
+ /// Note that the use of this function is just for optimization, so that the
+ /// cached tokens doesn't get re-parsed and re-resolved after a backtrack is
+ /// invoked.
+ void AnnotateCachedTokens(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ AnnotatePreviousCachedTokens(Tok);
+ }
+
+ /// Get the location of the last cached token, suitable for setting the end
+ /// location of an annotation token.
+ SourceLocation getLastCachedTokenLocation() const {
+ assert(CachedLexPos != 0);
+ return CachedTokens[CachedLexPos-1].getLastLoc();
+ }
+
+ /// Whether \p Tok is the most recent token (`CachedLexPos - 1`) in
+ /// CachedTokens.
+ bool IsPreviousCachedToken(const Token &Tok) const;
+
+ /// Replace token in `CachedLexPos - 1` in CachedTokens by the tokens
+ /// in \p NewToks.
+ ///
+ /// Useful when a token needs to be split in smaller ones and CachedTokens
+ /// most recent token must to be updated to reflect that.
+ void ReplacePreviousCachedToken(ArrayRef<Token> NewToks);
+
+ /// Replace the last token with an annotation token.
+ ///
+ /// Like AnnotateCachedTokens(), this routine replaces an
+ /// already-parsed (and resolved) token with an annotation
+ /// token. However, this routine only replaces the last token with
+ /// the annotation token; it does not affect any other cached
+ /// tokens. This function has no effect if backtracking is not
+ /// enabled.
+ void ReplaceLastTokenWithAnnotation(const Token &Tok) {
+ assert(Tok.isAnnotation() && "Expected annotation token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ CachedTokens[CachedLexPos-1] = Tok;
+ }
+
+ /// Enter an annotation token into the token stream.
+ void EnterAnnotationToken(SourceRange Range, tok::TokenKind Kind,
+ void *AnnotationVal);
+
+ /// Determine whether it's possible for a future call to Lex to produce an
+ /// annotation token created by a previous call to EnterAnnotationToken.
+ bool mightHavePendingAnnotationTokens() {
+ return CurLexerKind != CLK_Lexer;
+ }
+
+ /// Update the current token to represent the provided
+ /// identifier, in order to cache an action performed by typo correction.
+ void TypoCorrectToken(const Token &Tok) {
+ assert(Tok.getIdentifierInfo() && "Expected identifier token");
+ if (CachedLexPos != 0 && isBacktrackEnabled())
+ CachedTokens[CachedLexPos-1] = Tok;
+ }
+
+ /// Recompute the current lexer kind based on the CurLexer/
+ /// CurTokenLexer pointers.
+ void recomputeCurLexerKind();
+
+ /// Returns true if incremental processing is enabled
+ bool isIncrementalProcessingEnabled() const {
+ return getLangOpts().IncrementalExtensions;
+ }
+
+ /// Enables the incremental processing
+ void enableIncrementalProcessing(bool value = true) {
+ // FIXME: Drop this interface.
+ const_cast<LangOptions &>(getLangOpts()).IncrementalExtensions = value;
+ }
+
+ /// Specify the point at which code-completion will be performed.
+ ///
+ /// \param File the file in which code completion should occur. If
+ /// this file is included multiple times, code-completion will
+ /// perform completion the first time it is included. If NULL, this
+ /// function clears out the code-completion point.
+ ///
+ /// \param Line the line at which code completion should occur
+ /// (1-based).
+ ///
+ /// \param Column the column at which code completion should occur
+ /// (1-based).
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SetCodeCompletionPoint(const FileEntry *File,
+ unsigned Line, unsigned Column);
+
+ /// Determine if we are performing code completion.
+ bool isCodeCompletionEnabled() const { return CodeCompletionFile != nullptr; }
+
+ /// Returns the location of the code-completion point.
+ ///
+ /// Returns an invalid location if code-completion is not enabled or the file
+ /// containing the code-completion point has not been lexed yet.
+ SourceLocation getCodeCompletionLoc() const { return CodeCompletionLoc; }
+
+ /// Returns the start location of the file of code-completion point.
+ ///
+ /// Returns an invalid location if code-completion is not enabled or the file
+ /// containing the code-completion point has not been lexed yet.
+ SourceLocation getCodeCompletionFileLoc() const {
+ return CodeCompletionFileLoc;
+ }
+
+ /// Returns true if code-completion is enabled and we have hit the
+ /// code-completion point.
+ bool isCodeCompletionReached() const { return CodeCompletionReached; }
+
+ /// Note that we hit the code-completion point.
+ void setCodeCompletionReached() {
+ assert(isCodeCompletionEnabled() && "Code-completion not enabled!");
+ CodeCompletionReached = true;
+ // Silence any diagnostics that occur after we hit the code-completion.
+ getDiagnostics().setSuppressAllDiagnostics(true);
+ }
+
+ /// The location of the currently-active \#pragma clang
+ /// arc_cf_code_audited begin.
+ ///
+ /// Returns an invalid location if there is no such pragma active.
+ std::pair<IdentifierInfo *, SourceLocation>
+ getPragmaARCCFCodeAuditedInfo() const {
+ return PragmaARCCFCodeAuditedInfo;
+ }
+
+ /// Set the location of the currently-active \#pragma clang
+ /// arc_cf_code_audited begin. An invalid location ends the pragma.
+ void setPragmaARCCFCodeAuditedInfo(IdentifierInfo *Ident,
+ SourceLocation Loc) {
+ PragmaARCCFCodeAuditedInfo = {Ident, Loc};
+ }
+
+ /// The location of the currently-active \#pragma clang
+ /// assume_nonnull begin.
+ ///
+ /// Returns an invalid location if there is no such pragma active.
+ SourceLocation getPragmaAssumeNonNullLoc() const {
+ return PragmaAssumeNonNullLoc;
+ }
+
+ /// Set the location of the currently-active \#pragma clang
+ /// assume_nonnull begin. An invalid location ends the pragma.
+ void setPragmaAssumeNonNullLoc(SourceLocation Loc) {
+ PragmaAssumeNonNullLoc = Loc;
+ }
+
+ /// Get the location of the recorded unterminated \#pragma clang
+ /// assume_nonnull begin in the preamble, if one exists.
+ ///
+ /// Returns an invalid location if the premable did not end with
+ /// such a pragma active or if there is no recorded preamble.
+ SourceLocation getPreambleRecordedPragmaAssumeNonNullLoc() const {
+ return PreambleRecordedPragmaAssumeNonNullLoc;
+ }
+
+ /// Record the location of the unterminated \#pragma clang
+ /// assume_nonnull begin in the preamble.
+ void setPreambleRecordedPragmaAssumeNonNullLoc(SourceLocation Loc) {
+ PreambleRecordedPragmaAssumeNonNullLoc = Loc;
+ }
+
+ /// Set the directory in which the main file should be considered
+ /// to have been found, if it is not a real file.
+ void setMainFileDir(const DirectoryEntry *Dir) {
+ MainFileDir = Dir;
+ }
+
+ /// Instruct the preprocessor to skip part of the main source file.
+ ///
+ /// \param Bytes The number of bytes in the preamble to skip.
+ ///
+ /// \param StartOfLine Whether skipping these bytes puts the lexer at the
+ /// start of a line.
+ void setSkipMainFilePreamble(unsigned Bytes, bool StartOfLine) {
+ SkipMainFilePreamble.first = Bytes;
+ SkipMainFilePreamble.second = StartOfLine;
+ }
+
+ /// Forwarding function for diagnostics. This emits a diagnostic at
+ /// the specified Token's location, translating the token's start
+ /// position in the current buffer into a SourcePosition object for rendering.
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const {
+ return Diags->Report(Loc, DiagID);
+ }
+
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) const {
+ return Diags->Report(Tok.getLocation(), DiagID);
+ }
+
+ /// Return the 'spelling' of the token at the given
+ /// location; does not go up to the spelling location or down to the
+ /// expansion location.
+ ///
+ /// \param buffer A buffer which will be used only if the token requires
+ /// "cleaning", e.g. if it contains trigraphs or escaped newlines
+ /// \param invalid If non-null, will be set \c true if an error occurs.
+ StringRef getSpelling(SourceLocation loc,
+ SmallVectorImpl<char> &buffer,
+ bool *invalid = nullptr) const {
+ return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid);
+ }
+
+ /// Return the 'spelling' of the Tok token.
+ ///
+ /// The spelling of a token is the characters used to represent the token in
+ /// the source file after trigraph expansion and escaped-newline folding. In
+ /// particular, this wants to get the true, uncanonicalized, spelling of
+ /// things like digraphs, UCNs, etc.
+ ///
+ /// \param Invalid If non-null, will be set \c true if an error occurs.
+ std::string getSpelling(const Token &Tok, bool *Invalid = nullptr) const {
+ return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid);
+ }
+
+ /// Get the spelling of a token into a preallocated buffer, instead
+ /// of as an std::string.
+ ///
+ /// The caller is required to allocate enough space for the token, which is
+ /// guaranteed to be at least Tok.getLength() bytes long. The length of the
+ /// actual result is returned.
+ ///
+ /// Note that this method may do two possible things: it may either fill in
+ /// the buffer specified with characters, or it may *change the input pointer*
+ /// to point to a constant buffer with the data already in it (avoiding a
+ /// copy). The caller is not allowed to modify the returned buffer pointer
+ /// if an internal buffer is returned.
+ unsigned getSpelling(const Token &Tok, const char *&Buffer,
+ bool *Invalid = nullptr) const {
+ return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid);
+ }
+
+ /// Get the spelling of a token into a SmallVector.
+ ///
+ /// Note that the returned StringRef may not point to the
+ /// supplied buffer if a copy can be avoided.
+ StringRef getSpelling(const Token &Tok,
+ SmallVectorImpl<char> &Buffer,
+ bool *Invalid = nullptr) const;
+
+ /// Relex the token at the specified location.
+ /// \returns true if there was a failure, false on success.
+ bool getRawToken(SourceLocation Loc, Token &Result,
+ bool IgnoreWhiteSpace = false) {
+ return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace);
+ }
+
+ /// Given a Token \p Tok that is a numeric constant with length 1,
+ /// return the character.
+ char
+ getSpellingOfSingleCharacterNumericConstant(const Token &Tok,
+ bool *Invalid = nullptr) const {
+ assert(Tok.is(tok::numeric_constant) &&
+ Tok.getLength() == 1 && "Called on unsupported token");
+ assert(!Tok.needsCleaning() && "Token can't need cleaning with length 1");
+
+ // If the token is carrying a literal data pointer, just use it.
+ if (const char *D = Tok.getLiteralData())
+ return *D;
+
+ // Otherwise, fall back on getCharacterData, which is slower, but always
+ // works.
+ return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid);
+ }
+
+ /// Retrieve the name of the immediate macro expansion.
+ ///
+ /// This routine starts from a source location, and finds the name of the
+ /// macro responsible for its immediate expansion. It looks through any
+ /// intervening macro argument expansions to compute this. It returns a
+ /// StringRef that refers to the SourceManager-owned buffer of the source
+ /// where that macro name is spelled. Thus, the result shouldn't out-live
+ /// the SourceManager.
+ StringRef getImmediateMacroName(SourceLocation Loc) {
+ return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts());
+ }
+
+ /// Plop the specified string into a scratch buffer and set the
+ /// specified token's location and length to it.
+ ///
+ /// If specified, the source location provides a location of the expansion
+ /// point of the token.
+ void CreateString(StringRef Str, Token &Tok,
+ SourceLocation ExpansionLocStart = SourceLocation(),
+ SourceLocation ExpansionLocEnd = SourceLocation());
+
+ /// Split the first Length characters out of the token starting at TokLoc
+ /// and return a location pointing to the split token. Re-lexing from the
+ /// split token will return the split token rather than the original.
+ SourceLocation SplitToken(SourceLocation TokLoc, unsigned Length);
+
+ /// Computes the source location just past the end of the
+ /// token at this source location.
+ ///
+ /// This routine can be used to produce a source location that
+ /// points just past the end of the token referenced by \p Loc, and
+ /// is generally used when a diagnostic needs to point just after a
+ /// token where it expected something different that it received. If
+ /// the returned source location would not be meaningful (e.g., if
+ /// it points into a macro), this routine returns an invalid
+ /// source location.
+ ///
+ /// \param Offset an offset from the end of the token, where the source
+ /// location should refer to. The default offset (0) produces a source
+ /// location pointing just past the end of the token; an offset of 1 produces
+ /// a source location pointing to the last character in the token, etc.
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0) {
+ return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
+ }
+
+ /// Returns true if the given MacroID location points at the first
+ /// token of the macro expansion.
+ ///
+ /// \param MacroBegin If non-null and function returns true, it is set to
+ /// begin location of the macro.
+ bool isAtStartOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroBegin = nullptr) const {
+ return Lexer::isAtStartOfMacroExpansion(loc, SourceMgr, LangOpts,
+ MacroBegin);
+ }
+
+ /// Returns true if the given MacroID location points at the last
+ /// token of the macro expansion.
+ ///
+ /// \param MacroEnd If non-null and function returns true, it is set to
+ /// end location of the macro.
+ bool isAtEndOfMacroExpansion(SourceLocation loc,
+ SourceLocation *MacroEnd = nullptr) const {
+ return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd);
+ }
+
+ /// Print the token to stderr, used for debugging.
+ void DumpToken(const Token &Tok, bool DumpFlags = false) const;
+ void DumpLocation(SourceLocation Loc) const;
+ void DumpMacro(const MacroInfo &MI) const;
+ void dumpMacroInfo(const IdentifierInfo *II);
+
+ /// Given a location that specifies the start of a
+ /// token, return a new location that specifies a character within the token.
+ SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart,
+ unsigned Char) const {
+ return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts);
+ }
+
+ /// Increment the counters for the number of token paste operations
+ /// performed.
+ ///
+ /// If fast was specified, this is a 'fast paste' case we handled.
+ void IncrementPasteCounter(bool isFast) {
+ if (isFast)
+ ++NumFastTokenPaste;
+ else
+ ++NumTokenPaste;
+ }
+
+ void PrintStats();
+
+ size_t getTotalMemory() const;
+
+ /// When the macro expander pastes together a comment (/##/) in Microsoft
+ /// mode, this method handles updating the current state, returning the
+ /// token on the next source line.
+ void HandleMicrosoftCommentPaste(Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ // Preprocessor callback methods. These are invoked by a lexer as various
+ // directives and events are found.
+
+ /// Given a tok::raw_identifier token, look up the
+ /// identifier information for the token and install it into the token,
+ /// updating the token kind accordingly.
+ IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const;
+
+private:
+ llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons;
+
+public:
+ /// Specifies the reason for poisoning an identifier.
+ ///
+ /// If that identifier is accessed while poisoned, then this reason will be
+ /// used instead of the default "poisoned" diagnostic.
+ void SetPoisonReason(IdentifierInfo *II, unsigned DiagID);
+
+ /// Display reason for poisoned identifier.
+ void HandlePoisonedIdentifier(Token & Identifier);
+
+ void MaybeHandlePoisonedIdentifier(Token & Identifier) {
+ if(IdentifierInfo * II = Identifier.getIdentifierInfo()) {
+ if(II->isPoisoned()) {
+ HandlePoisonedIdentifier(Identifier);
+ }
+ }
+ }
+
+private:
+ /// Identifiers used for SEH handling in Borland. These are only
+ /// allowed in particular circumstances
+ // __except block
+ IdentifierInfo *Ident__exception_code,
+ *Ident___exception_code,
+ *Ident_GetExceptionCode;
+ // __except filter expression
+ IdentifierInfo *Ident__exception_info,
+ *Ident___exception_info,
+ *Ident_GetExceptionInfo;
+ // __finally
+ IdentifierInfo *Ident__abnormal_termination,
+ *Ident___abnormal_termination,
+ *Ident_AbnormalTermination;
+
+ const char *getCurLexerEndPos();
+ void diagnoseMissingHeaderInUmbrellaDir(const Module &Mod);
+
+public:
+ void PoisonSEHIdentifiers(bool Poison = true); // Borland
+
+ /// Callback invoked when the lexer reads an identifier and has
+ /// filled in the tokens IdentifierInfo member.
+ ///
+ /// This callback potentially macro expands it or turns it into a named
+ /// token (like 'for').
+ ///
+ /// \returns true if we actually computed a token, false if we need to
+ /// lex again.
+ bool HandleIdentifier(Token &Identifier);
+
+ /// Callback invoked when the lexer hits the end of the current file.
+ ///
+ /// This either returns the EOF token and returns true, or
+ /// pops a level off the include stack and returns false, at which point the
+ /// client should call lex again.
+ bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false);
+
+ /// Callback invoked when the current TokenLexer hits the end of its
+ /// token stream.
+ bool HandleEndOfTokenLexer(Token &Result);
+
+ /// Callback invoked when the lexer sees a # token at the start of a
+ /// line.
+ ///
+ /// This consumes the directive, modifies the lexer/preprocessor state, and
+ /// advances the lexer(s) so that the next token read is the correct one.
+ void HandleDirective(Token &Result);
+
+ /// Ensure that the next token is a tok::eod token.
+ ///
+ /// If not, emit a diagnostic and consume up until the eod.
+ /// If \p EnableMacros is true, then we consider macros that expand to zero
+ /// tokens as being ok.
+ ///
+ /// \return The location of the end of the directive (the terminating
+ /// newline).
+ SourceLocation CheckEndOfDirective(const char *DirType,
+ bool EnableMacros = false);
+
+ /// Read and discard all tokens remaining on the current line until
+ /// the tok::eod token is found. Returns the range of the skipped tokens.
+ SourceRange DiscardUntilEndOfDirective();
+
+ /// Returns true if the preprocessor has seen a use of
+ /// __DATE__ or __TIME__ in the file so far.
+ bool SawDateOrTime() const {
+ return DATELoc != SourceLocation() || TIMELoc != SourceLocation();
+ }
+ unsigned getCounterValue() const { return CounterValue; }
+ void setCounterValue(unsigned V) { CounterValue = V; }
+
+ LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const {
+ assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine &&
+ "FPEvalMethod should be set either from command line or from the "
+ "target info");
+ return CurrentFPEvalMethod;
+ }
+
+ LangOptions::FPEvalMethodKind getTUFPEvalMethod() const {
+ return TUFPEvalMethod;
+ }
+
+ SourceLocation getLastFPEvalPragmaLocation() const {
+ return LastFPEvalPragmaLocation;
+ }
+
+ void setCurrentFPEvalMethod(SourceLocation PragmaLoc,
+ LangOptions::FPEvalMethodKind Val) {
+ assert(Val != LangOptions::FEM_UnsetOnCommandLine &&
+ "FPEvalMethod should never be set to FEM_UnsetOnCommandLine");
+ // This is the location of the '#pragma float_control" where the
+ // execution state is modifed.
+ LastFPEvalPragmaLocation = PragmaLoc;
+ CurrentFPEvalMethod = Val;
+ TUFPEvalMethod = Val;
+ }
+
+ void setTUFPEvalMethod(LangOptions::FPEvalMethodKind Val) {
+ assert(Val != LangOptions::FEM_UnsetOnCommandLine &&
+ "TUPEvalMethod should never be set to FEM_UnsetOnCommandLine");
+ TUFPEvalMethod = Val;
+ }
+
+ /// Retrieves the module that we're currently building, if any.
+ Module *getCurrentModule();
+
+ /// Retrieves the module whose implementation we're current compiling, if any.
+ Module *getCurrentModuleImplementation();
+
+ /// If we are preprocessing a named module.
+ bool isInNamedModule() const { return ModuleDeclState.isNamedModule(); }
+
+ /// If we are proprocessing a named interface unit.
+ /// Note that a module implementation partition is not considered as an
+ /// named interface unit here although it is importable
+ /// to ease the parsing.
+ bool isInNamedInterfaceUnit() const {
+ return ModuleDeclState.isNamedInterface();
+ }
+
+ /// Get the named module name we're preprocessing.
+ /// Requires we're preprocessing a named module.
+ StringRef getNamedModuleName() const { return ModuleDeclState.getName(); }
+
+ /// If we are implementing an implementation module unit.
+ /// Note that the module implementation partition is not considered as an
+ /// implementation unit.
+ bool isInImplementationUnit() const {
+ return ModuleDeclState.isImplementationUnit();
+ }
+
+ /// If we're importing a standard C++20 Named Modules.
+ bool isInImportingCXXNamedModules() const {
+ // NamedModuleImportPath will be non-empty only if we're importing
+ // Standard C++ named modules.
+ return !NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules &&
+ !IsAtImport;
+ }
+
+ /// Allocate a new MacroInfo object with the provided SourceLocation.
+ MacroInfo *AllocateMacroInfo(SourceLocation L);
+
+ /// Turn the specified lexer token into a fully checked and spelled
+ /// filename, e.g. as an operand of \#include.
+ ///
+ /// The caller is expected to provide a buffer that is large enough to hold
+ /// the spelling of the filename, but is also expected to handle the case
+ /// when this method decides to use a different buffer.
+ ///
+ /// \returns true if the input filename was in <>'s or false if it was
+ /// in ""'s.
+ bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Buffer);
+
+ /// Given a "foo" or \<foo> reference, look up the indicated file.
+ ///
+ /// Returns std::nullopt on failure. \p isAngled indicates whether the file
+ /// reference is for system \#include's or not (i.e. using <> instead of "").
+ OptionalFileEntryRef
+ LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled,
+ ConstSearchDirIterator FromDir, const FileEntry *FromFile,
+ ConstSearchDirIterator *CurDir, SmallVectorImpl<char> *SearchPath,
+ SmallVectorImpl<char> *RelativePath,
+ ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
+ bool *IsFrameworkFound, bool SkipCache = false,
+ bool OpenFile = true, bool CacheFailures = true);
+
+ /// Return true if we're in the top-level file, not in a \#include.
+ bool isInPrimaryFile() const;
+
+ /// Lex an on-off-switch (C99 6.10.6p2) and verify that it is
+ /// followed by EOD. Return true if the token is not a valid on-off-switch.
+ bool LexOnOffSwitch(tok::OnOffSwitch &Result);
+
+ bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef,
+ bool *ShadowFlag = nullptr);
+
+ void EnterSubmodule(Module *M, SourceLocation ImportLoc, bool ForPragma);
+ Module *LeaveSubmodule(bool ForPragma);
+
+private:
+ friend void TokenLexer::ExpandFunctionArguments();
+
+ void PushIncludeMacroStack() {
+ assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer");
+ IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule,
+ std::move(CurLexer), CurPPLexer,
+ std::move(CurTokenLexer), CurDirLookup);
+ CurPPLexer = nullptr;
+ }
+
+ void PopIncludeMacroStack() {
+ CurLexer = std::move(IncludeMacroStack.back().TheLexer);
+ CurPPLexer = IncludeMacroStack.back().ThePPLexer;
+ CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer);
+ CurDirLookup = IncludeMacroStack.back().TheDirLookup;
+ CurLexerSubmodule = IncludeMacroStack.back().TheSubmodule;
+ CurLexerKind = IncludeMacroStack.back().CurLexerKind;
+ IncludeMacroStack.pop_back();
+ }
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+
+ /// Determine whether we need to create module macros for #defines in the
+ /// current context.
+ bool needModuleMacros() const;
+
+ /// Update the set of active module macros and ambiguity flag for a module
+ /// macro name.
+ void updateModuleMacroInfo(const IdentifierInfo *II, ModuleMacroInfo &Info);
+
+ DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI,
+ SourceLocation Loc);
+ UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc);
+ VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc,
+ bool isPublic);
+
+ /// Lex and validate a macro name, which occurs after a
+ /// \#define or \#undef.
+ ///
+ /// \param MacroNameTok Token that represents the name defined or undefined.
+ /// \param IsDefineUndef Kind if preprocessor directive.
+ /// \param ShadowFlag Points to flag that is set if macro name shadows
+ /// a keyword.
+ ///
+ /// This emits a diagnostic, sets the token kind to eod,
+ /// and discards the rest of the macro line if the macro name is invalid.
+ void ReadMacroName(Token &MacroNameTok, MacroUse IsDefineUndef = MU_Other,
+ bool *ShadowFlag = nullptr);
+
+ /// ReadOptionalMacroParameterListAndBody - This consumes all (i.e. the
+ /// entire line) of the macro's tokens and adds them to MacroInfo, and while
+ /// doing so performs certain validity checks including (but not limited to):
+ /// - # (stringization) is followed by a macro parameter
+ /// \param MacroNameTok - Token that represents the macro name
+ /// \param ImmediatelyAfterHeaderGuard - Macro follows an #ifdef header guard
+ ///
+ /// Either returns a pointer to a MacroInfo object OR emits a diagnostic and
+ /// returns a nullptr if an invalid sequence of tokens is encountered.
+ MacroInfo *ReadOptionalMacroParameterListAndBody(
+ const Token &MacroNameTok, bool ImmediatelyAfterHeaderGuard);
+
+ /// The ( starting an argument list of a macro definition has just been read.
+ /// Lex the rest of the parameters and the closing ), updating \p MI with
+ /// what we learn and saving in \p LastTok the last token read.
+ /// Return true if an error occurs parsing the arg list.
+ bool ReadMacroParameterList(MacroInfo *MI, Token& LastTok);
+
+ /// Provide a suggestion for a typoed directive. If there is no typo, then
+ /// just skip suggesting.
+ ///
+ /// \param Tok - Token that represents the directive
+ /// \param Directive - String reference for the directive name
+ void SuggestTypoedDirective(const Token &Tok, StringRef Directive) const;
+
+ /// We just read a \#if or related directive and decided that the
+ /// subsequent tokens are in the \#if'd out portion of the
+ /// file. Lex the rest of the file, until we see an \#endif. If \p
+ /// FoundNonSkipPortion is true, then we have already emitted code for part of
+ /// this \#if directive, so \#else/\#elif blocks should never be entered. If
+ /// \p FoundElse is false, then \#else directives are ok, if not, then we have
+ /// already seen one so a \#else directive is a duplicate. When this returns,
+ /// the caller can lex the first valid token.
+ void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
+ SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse,
+ SourceLocation ElseLoc = SourceLocation());
+
+ /// Information about the result for evaluating an expression for a
+ /// preprocessor directive.
+ struct DirectiveEvalResult {
+ /// Whether the expression was evaluated as true or not.
+ bool Conditional;
+
+ /// True if the expression contained identifiers that were undefined.
+ bool IncludedUndefinedIds;
+
+ /// The source range for the expression.
+ SourceRange ExprRange;
+ };
+
+ /// Evaluate an integer constant expression that may occur after a
+ /// \#if or \#elif directive and return a \p DirectiveEvalResult object.
+ ///
+ /// If the expression is equivalent to "!defined(X)" return X in IfNDefMacro.
+ DirectiveEvalResult EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro);
+
+ /// Process a '__has_include("path")' expression.
+ ///
+ /// Returns true if successful.
+ bool EvaluateHasInclude(Token &Tok, IdentifierInfo *II);
+
+ /// Process '__has_include_next("path")' expression.
+ ///
+ /// Returns true if successful.
+ bool EvaluateHasIncludeNext(Token &Tok, IdentifierInfo *II);
+
+ /// Get the directory and file from which to start \#include_next lookup.
+ std::pair<ConstSearchDirIterator, const FileEntry *>
+ getIncludeNextStart(const Token &IncludeNextTok) const;
+
+ /// Install the standard preprocessor pragmas:
+ /// \#pragma GCC poison/system_header/dependency and \#pragma once.
+ void RegisterBuiltinPragmas();
+
+ /// Register builtin macros such as __LINE__ with the identifier table.
+ void RegisterBuiltinMacros();
+
+ /// If an identifier token is read that is to be expanded as a macro, handle
+ /// it and return the next token as 'Tok'. If we lexed a token, return true;
+ /// otherwise the caller should lex again.
+ bool HandleMacroExpandedIdentifier(Token &Identifier, const MacroDefinition &MD);
+
+ /// Cache macro expanded tokens for TokenLexers.
+ //
+ /// Works like a stack; a TokenLexer adds the macro expanded tokens that is
+ /// going to lex in the cache and when it finishes the tokens are removed
+ /// from the end of the cache.
+ Token *cacheMacroExpandedTokens(TokenLexer *tokLexer,
+ ArrayRef<Token> tokens);
+
+ void removeCachedMacroExpandedTokensOfLastLexer();
+
+ /// Determine whether the next preprocessor token to be
+ /// lexed is a '('. If so, consume the token and return true, if not, this
+ /// method should have no observable side-effect on the lexed tokens.
+ bool isNextPPTokenLParen();
+
+ /// After reading "MACRO(", this method is invoked to read all of the formal
+ /// arguments specified for the macro invocation. Returns null on error.
+ MacroArgs *ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI,
+ SourceLocation &MacroEnd);
+
+ /// If an identifier token is read that is to be expanded
+ /// as a builtin macro, handle it and return the next token as 'Tok'.
+ void ExpandBuiltinMacro(Token &Tok);
+
+ /// Read a \c _Pragma directive, slice it up, process it, then
+ /// return the first token after the directive.
+ /// This assumes that the \c _Pragma token has just been read into \p Tok.
+ void Handle_Pragma(Token &Tok);
+
+ /// Like Handle_Pragma except the pragma text is not enclosed within
+ /// a string literal.
+ void HandleMicrosoft__pragma(Token &Tok);
+
+ /// Add a lexer to the top of the include stack and
+ /// start lexing tokens from it instead of the current buffer.
+ void EnterSourceFileWithLexer(Lexer *TheLexer, ConstSearchDirIterator Dir);
+
+ /// Set the FileID for the preprocessor predefines.
+ void setPredefinesFileID(FileID FID) {
+ assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!");
+ PredefinesFileID = FID;
+ }
+
+ /// Set the FileID for the PCH through header.
+ void setPCHThroughHeaderFileID(FileID FID);
+
+ /// Returns true if we are lexing from a file and not a
+ /// pragma or a macro.
+ static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) {
+ return L ? !L->isPragmaLexer() : P != nullptr;
+ }
+
+ static bool IsFileLexer(const IncludeStackInfo& I) {
+ return IsFileLexer(I.TheLexer.get(), I.ThePPLexer);
+ }
+
+ bool IsFileLexer() const {
+ return IsFileLexer(CurLexer.get(), CurPPLexer);
+ }
+
+ //===--------------------------------------------------------------------===//
+ // Caching stuff.
+ void CachingLex(Token &Result);
+
+ bool InCachingLexMode() const {
+ // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means
+ // that we are past EOF, not that we are in CachingLex mode.
+ return !CurPPLexer && !CurTokenLexer && !IncludeMacroStack.empty();
+ }
+
+ void EnterCachingLexMode();
+ void EnterCachingLexModeUnchecked();
+
+ void ExitCachingLexMode() {
+ if (InCachingLexMode())
+ RemoveTopOfLexerStack();
+ }
+
+ const Token &PeekAhead(unsigned N);
+ void AnnotatePreviousCachedTokens(const Token &Tok);
+
+ //===--------------------------------------------------------------------===//
+ /// Handle*Directive - implement the various preprocessor directives. These
+ /// should side-effect the current preprocessor object so that the next call
+ /// to Lex() will return the appropriate token next.
+ void HandleLineDirective();
+ void HandleDigitDirective(Token &Tok);
+ void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
+ void HandleIdentSCCSDirective(Token &Tok);
+ void HandleMacroPublicDirective(Token &Tok);
+ void HandleMacroPrivateDirective();
+
+ /// An additional notification that can be produced by a header inclusion or
+ /// import to tell the parser what happened.
+ struct ImportAction {
+ enum ActionKind {
+ None,
+ ModuleBegin,
+ ModuleImport,
+ HeaderUnitImport,
+ SkippedModuleImport,
+ Failure,
+ } Kind;
+ Module *ModuleForHeader = nullptr;
+
+ ImportAction(ActionKind AK, Module *Mod = nullptr)
+ : Kind(AK), ModuleForHeader(Mod) {
+ assert((AK == None || Mod || AK == Failure) &&
+ "no module for module action");
+ }
+ };
+
+ OptionalFileEntryRef LookupHeaderIncludeOrImport(
+ ConstSearchDirIterator *CurDir, StringRef &Filename,
+ SourceLocation FilenameLoc, CharSourceRange FilenameRange,
+ const Token &FilenameTok, bool &IsFrameworkFound, bool IsImportDecl,
+ bool &IsMapped, ConstSearchDirIterator LookupFrom,
+ const FileEntry *LookupFromFile, StringRef &LookupFilename,
+ SmallVectorImpl<char> &RelativePath, SmallVectorImpl<char> &SearchPath,
+ ModuleMap::KnownHeader &SuggestedModule, bool isAngled);
+
+ // File inclusion.
+ void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok,
+ ConstSearchDirIterator LookupFrom = nullptr,
+ const FileEntry *LookupFromFile = nullptr);
+ ImportAction
+ HandleHeaderIncludeOrImport(SourceLocation HashLoc, Token &IncludeTok,
+ Token &FilenameTok, SourceLocation EndLoc,
+ ConstSearchDirIterator LookupFrom = nullptr,
+ const FileEntry *LookupFromFile = nullptr);
+ void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleImportDirective(SourceLocation HashLoc, Token &Tok);
+ void HandleMicrosoftImportDirective(Token &Tok);
+
+public:
+ /// Check that the given module is available, producing a diagnostic if not.
+ /// \return \c true if the check failed (because the module is not available).
+ /// \c false if the module appears to be usable.
+ static bool checkModuleIsAvailable(const LangOptions &LangOpts,
+ const TargetInfo &TargetInfo,
+ DiagnosticsEngine &Diags, Module *M);
+
+ // Module inclusion testing.
+ /// Find the module that owns the source or header file that
+ /// \p Loc points to. If the location is in a file that was included
+ /// into a module, or is outside any module, returns nullptr.
+ Module *getModuleForLocation(SourceLocation Loc, bool AllowTextual);
+
+ /// We want to produce a diagnostic at location IncLoc concerning an
+ /// unreachable effect at location MLoc (eg, where a desired entity was
+ /// declared or defined). Determine whether the right way to make MLoc
+ /// reachable is by #include, and if so, what header should be included.
+ ///
+ /// This is not necessarily fast, and might load unexpected module maps, so
+ /// should only be called by code that intends to produce an error.
+ ///
+ /// \param IncLoc The location at which the missing effect was detected.
+ /// \param MLoc A location within an unimported module at which the desired
+ /// effect occurred.
+ /// \return A file that can be #included to provide the desired effect. Null
+ /// if no such file could be determined or if a #include is not
+ /// appropriate (eg, if a module should be imported instead).
+ const FileEntry *getHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
+ SourceLocation MLoc);
+
+ bool isRecordingPreamble() const {
+ return PreambleConditionalStack.isRecording();
+ }
+
+ bool hasRecordedPreamble() const {
+ return PreambleConditionalStack.hasRecordedPreamble();
+ }
+
+ ArrayRef<PPConditionalInfo> getPreambleConditionalStack() const {
+ return PreambleConditionalStack.getStack();
+ }
+
+ void setRecordedPreambleConditionalStack(ArrayRef<PPConditionalInfo> s) {
+ PreambleConditionalStack.setStack(s);
+ }
+
+ void setReplayablePreambleConditionalStack(
+ ArrayRef<PPConditionalInfo> s, std::optional<PreambleSkipInfo> SkipInfo) {
+ PreambleConditionalStack.startReplaying();
+ PreambleConditionalStack.setStack(s);
+ PreambleConditionalStack.SkipInfo = SkipInfo;
+ }
+
+ std::optional<PreambleSkipInfo> getPreambleSkipInfo() const {
+ return PreambleConditionalStack.SkipInfo;
+ }
+
+private:
+ /// After processing predefined file, initialize the conditional stack from
+ /// the preamble.
+ void replayPreambleConditionalStack();
+
+ // Macro handling.
+ void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard);
+ void HandleUndefDirective();
+
+ // Conditional Inclusion.
+ void HandleIfdefDirective(Token &Result, const Token &HashToken,
+ bool isIfndef, bool ReadAnyTokensBeforeDirective);
+ void HandleIfDirective(Token &IfToken, const Token &HashToken,
+ bool ReadAnyTokensBeforeDirective);
+ void HandleEndifDirective(Token &EndifToken);
+ void HandleElseDirective(Token &Result, const Token &HashToken);
+ void HandleElifFamilyDirective(Token &ElifToken, const Token &HashToken,
+ tok::PPKeywordKind Kind);
+
+ // Pragmas.
+ void HandlePragmaDirective(PragmaIntroducer Introducer);
+
+public:
+ void HandlePragmaOnce(Token &OnceTok);
+ void HandlePragmaMark(Token &MarkTok);
+ void HandlePragmaPoison();
+ void HandlePragmaSystemHeader(Token &SysHeaderTok);
+ void HandlePragmaDependency(Token &DependencyTok);
+ void HandlePragmaPushMacro(Token &Tok);
+ void HandlePragmaPopMacro(Token &Tok);
+ void HandlePragmaIncludeAlias(Token &Tok);
+ void HandlePragmaModuleBuild(Token &Tok);
+ void HandlePragmaHdrstop(Token &Tok);
+ IdentifierInfo *ParsePragmaPushOrPopMacro(Token &Tok);
+
+ // Return true and store the first token only if any CommentHandler
+ // has inserted some tokens and getCommentRetentionState() is false.
+ bool HandleComment(Token &result, SourceRange Comment);
+
+ /// A macro is used, update information about macros that need unused
+ /// warnings.
+ void markMacroAsUsed(MacroInfo *MI);
+
+ void addMacroDeprecationMsg(const IdentifierInfo *II, std::string Msg,
+ SourceLocation AnnotationLoc) {
+ auto Annotations = AnnotationInfos.find(II);
+ if (Annotations == AnnotationInfos.end())
+ AnnotationInfos.insert(std::make_pair(
+ II,
+ MacroAnnotations::makeDeprecation(AnnotationLoc, std::move(Msg))));
+ else
+ Annotations->second.DeprecationInfo =
+ MacroAnnotationInfo{AnnotationLoc, std::move(Msg)};
+ }
+
+ void addRestrictExpansionMsg(const IdentifierInfo *II, std::string Msg,
+ SourceLocation AnnotationLoc) {
+ auto Annotations = AnnotationInfos.find(II);
+ if (Annotations == AnnotationInfos.end())
+ AnnotationInfos.insert(
+ std::make_pair(II, MacroAnnotations::makeRestrictExpansion(
+ AnnotationLoc, std::move(Msg))));
+ else
+ Annotations->second.RestrictExpansionInfo =
+ MacroAnnotationInfo{AnnotationLoc, std::move(Msg)};
+ }
+
+ void addFinalLoc(const IdentifierInfo *II, SourceLocation AnnotationLoc) {
+ auto Annotations = AnnotationInfos.find(II);
+ if (Annotations == AnnotationInfos.end())
+ AnnotationInfos.insert(
+ std::make_pair(II, MacroAnnotations::makeFinal(AnnotationLoc)));
+ else
+ Annotations->second.FinalAnnotationLoc = AnnotationLoc;
+ }
+
+ const MacroAnnotations &getMacroAnnotations(const IdentifierInfo *II) const {
+ return AnnotationInfos.find(II)->second;
+ }
+
+ void emitMacroExpansionWarnings(const Token &Identifier) const {
+ if (Identifier.getIdentifierInfo()->isDeprecatedMacro())
+ emitMacroDeprecationWarning(Identifier);
+
+ if (Identifier.getIdentifierInfo()->isRestrictExpansion() &&
+ !SourceMgr.isInMainFile(Identifier.getLocation()))
+ emitRestrictExpansionWarning(Identifier);
+ }
+
+ static void processPathForFileMacro(SmallVectorImpl<char> &Path,
+ const LangOptions &LangOpts,
+ const TargetInfo &TI);
+
+private:
+ void emitMacroDeprecationWarning(const Token &Identifier) const;
+ void emitRestrictExpansionWarning(const Token &Identifier) const;
+ void emitFinalMacroWarning(const Token &Identifier, bool IsUndef) const;
+};
+
+/// Abstract base class that describes a handler that will receive
+/// source ranges for each of the comments encountered in the source file.
+class CommentHandler {
+public:
+ virtual ~CommentHandler();
+
+ // The handler shall return true if it has pushed any tokens
+ // to be read using e.g. EnterToken or EnterTokenStream.
+ virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
+};
+
+/// Abstract base class that describes a handler that will receive
+/// source ranges for empty lines encountered in the source file.
+class EmptylineHandler {
+public:
+ virtual ~EmptylineHandler();
+
+ // The handler handles empty lines.
+ virtual void HandleEmptyline(SourceRange Range) = 0;
+};
+
+/// Registry of pragma handlers added by plugins
+using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_PREPROCESSOR_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/PreprocessorLexer.h b/contrib/libs/clang16/include/clang/Lex/PreprocessorLexer.h
new file mode 100644
index 0000000000..a97d0f0926
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/PreprocessorLexer.h
@@ -0,0 +1,194 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- PreprocessorLexer.h - C Language Family Lexer ------------*- 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
+/// Defines the PreprocessorLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H
+#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H
+
+#include "clang/Basic/FileEntry.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/MultipleIncludeOpt.h"
+#include "clang/Lex/Token.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+
+namespace clang {
+
+class FileEntry;
+class Preprocessor;
+
+class PreprocessorLexer {
+ virtual void anchor();
+
+protected:
+ friend class Preprocessor;
+
+ // Preprocessor object controlling lexing.
+ Preprocessor *PP = nullptr;
+
+ /// The SourceManager FileID corresponding to the file being lexed.
+ const FileID FID;
+
+ /// Number of SLocEntries before lexing the file.
+ unsigned InitialNumSLocEntries = 0;
+
+ //===--------------------------------------------------------------------===//
+ // Context-specific lexing flags set by the preprocessor.
+ //===--------------------------------------------------------------------===//
+
+ /// True when parsing \#XXX; turns '\\n' into a tok::eod token.
+ bool ParsingPreprocessorDirective = false;
+
+ /// True after \#include; turns \<xx> or "xxx" into a tok::header_name token.
+ bool ParsingFilename = false;
+
+ /// True if in raw mode.
+ ///
+ /// Raw mode disables interpretation of tokens and is a far faster mode to
+ /// lex in than non-raw-mode. This flag:
+ /// 1. If EOF of the current lexer is found, the include stack isn't popped.
+ /// 2. Identifier information is not looked up for identifier tokens. As an
+ /// effect of this, implicit macro expansion is naturally disabled.
+ /// 3. "#" tokens at the start of a line are treated as normal tokens, not
+ /// implicitly transformed by the lexer.
+ /// 4. All diagnostic messages are disabled.
+ /// 5. No callbacks are made into the preprocessor.
+ ///
+ /// Note that in raw mode that the PP pointer may be null.
+ bool LexingRawMode = false;
+
+ /// A state machine that detects the \#ifndef-wrapping a file
+ /// idiom for the multiple-include optimization.
+ MultipleIncludeOpt MIOpt;
+
+ /// Information about the set of \#if/\#ifdef/\#ifndef blocks
+ /// we are currently in.
+ SmallVector<PPConditionalInfo, 4> ConditionalStack;
+
+ PreprocessorLexer() : FID() {}
+ PreprocessorLexer(Preprocessor *pp, FileID fid);
+ virtual ~PreprocessorLexer() = default;
+
+ virtual void IndirectLex(Token& Result) = 0;
+
+ /// Return the source location for the next observable location.
+ virtual SourceLocation getSourceLocation() = 0;
+
+ //===--------------------------------------------------------------------===//
+ // #if directive handling.
+
+ /// pushConditionalLevel - When we enter a \#if directive, this keeps track of
+ /// what we are currently in for diagnostic emission (e.g. \#if with missing
+ /// \#endif).
+ void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
+ bool FoundNonSkip, bool FoundElse) {
+ PPConditionalInfo CI;
+ CI.IfLoc = DirectiveStart;
+ CI.WasSkipping = WasSkipping;
+ CI.FoundNonSkip = FoundNonSkip;
+ CI.FoundElse = FoundElse;
+ ConditionalStack.push_back(CI);
+ }
+ void pushConditionalLevel(const PPConditionalInfo &CI) {
+ ConditionalStack.push_back(CI);
+ }
+
+ /// popConditionalLevel - Remove an entry off the top of the conditional
+ /// stack, returning information about it. If the conditional stack is empty,
+ /// this returns true and does not fill in the arguments.
+ bool popConditionalLevel(PPConditionalInfo &CI) {
+ if (ConditionalStack.empty())
+ return true;
+ CI = ConditionalStack.pop_back_val();
+ return false;
+ }
+
+ /// Return the top of the conditional stack.
+ /// \pre This requires that there be a conditional active.
+ PPConditionalInfo &peekConditionalLevel() {
+ assert(!ConditionalStack.empty() && "No conditionals active!");
+ return ConditionalStack.back();
+ }
+
+ unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
+
+public:
+ PreprocessorLexer(const PreprocessorLexer &) = delete;
+ PreprocessorLexer &operator=(const PreprocessorLexer &) = delete;
+
+ //===--------------------------------------------------------------------===//
+ // Misc. lexing methods.
+
+ /// Lex a token, producing a header-name token if possible.
+ void LexIncludeFilename(Token &FilenameTok);
+
+ /// Inform the lexer whether or not we are currently lexing a
+ /// preprocessor directive.
+ void setParsingPreprocessorDirective(bool f) {
+ ParsingPreprocessorDirective = f;
+ }
+
+ /// Return true if this lexer is in raw mode or not.
+ bool isLexingRawMode() const { return LexingRawMode; }
+
+ /// Return the preprocessor object for this lexer.
+ Preprocessor *getPP() const { return PP; }
+
+ FileID getFileID() const {
+ assert(PP &&
+ "PreprocessorLexer::getFileID() should only be used with a Preprocessor");
+ return FID;
+ }
+
+ /// Number of SLocEntries before lexing the file.
+ unsigned getInitialNumSLocEntries() const {
+ return InitialNumSLocEntries;
+ }
+
+ /// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+ /// getFileID(), this only works for lexers with attached preprocessors.
+ OptionalFileEntryRefDegradesToFileEntryPtr getFileEntry() const;
+
+ /// Iterator that traverses the current stack of preprocessor
+ /// conditional directives (\#if/\#ifdef/\#ifndef).
+ using conditional_iterator =
+ SmallVectorImpl<PPConditionalInfo>::const_iterator;
+
+ conditional_iterator conditional_begin() const {
+ return ConditionalStack.begin();
+ }
+
+ conditional_iterator conditional_end() const {
+ return ConditionalStack.end();
+ }
+
+ void setConditionalLevels(ArrayRef<PPConditionalInfo> CL) {
+ ConditionalStack.clear();
+ ConditionalStack.append(CL.begin(), CL.end());
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_PREPROCESSORLEXER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/PreprocessorOptions.h b/contrib/libs/clang16/include/clang/Lex/PreprocessorOptions.h
new file mode 100644
index 0000000000..205d7762e8
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/PreprocessorOptions.h
@@ -0,0 +1,280 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- PreprocessorOptions.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
+#define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
+
+#include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/FileEntry.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/DependencyDirectivesScanner.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include <functional>
+#include <map>
+#include <memory>
+#include <optional>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class MemoryBuffer;
+
+} // namespace llvm
+
+namespace clang {
+
+/// Enumerate the kinds of standard library that
+enum ObjCXXARCStandardLibraryKind {
+ ARCXX_nolib,
+
+ /// libc++
+ ARCXX_libcxx,
+
+ /// libstdc++
+ ARCXX_libstdcxx
+};
+
+/// Whether to disable the normal validation performed on precompiled
+/// headers and module files when they are loaded.
+enum class DisableValidationForModuleKind {
+ /// Perform validation, don't disable it.
+ None = 0,
+
+ /// Disable validation for a precompiled header and the modules it depends on.
+ PCH = 0x1,
+
+ /// Disable validation for module files.
+ Module = 0x2,
+
+ /// Disable validation for all kinds.
+ All = PCH | Module,
+
+ LLVM_MARK_AS_BITMASK_ENUM(Module)
+};
+
+/// PreprocessorOptions - This class is used for passing the various options
+/// used in preprocessor initialization to InitializePreprocessor().
+class PreprocessorOptions {
+public:
+ std::vector<std::pair<std::string, bool/*isUndef*/>> Macros;
+ std::vector<std::string> Includes;
+ std::vector<std::string> MacroIncludes;
+
+ /// Initialize the preprocessor with the compiler and target specific
+ /// predefines.
+ bool UsePredefines = true;
+
+ /// Whether we should maintain a detailed record of all macro
+ /// definitions and expansions.
+ bool DetailedRecord = false;
+
+ /// When true, we are creating or using a PCH where a #pragma hdrstop is
+ /// expected to indicate the beginning or end of the PCH.
+ bool PCHWithHdrStop = false;
+
+ /// When true, we are creating a PCH or creating the PCH object while
+ /// expecting a #pragma hdrstop to separate the two. Allow for a
+ /// missing #pragma hdrstop, which generates a PCH for the whole file,
+ /// and creates an empty PCH object.
+ bool PCHWithHdrStopCreate = false;
+
+ /// If non-empty, the filename used in an #include directive in the primary
+ /// source file (or command-line preinclude) that is used to implement
+ /// MSVC-style precompiled headers. When creating a PCH, after the #include
+ /// of this header, the PCH generation stops. When using a PCH, tokens are
+ /// skipped until after an #include of this header is seen.
+ std::string PCHThroughHeader;
+
+ /// The implicit PCH included at the start of the translation unit, or empty.
+ std::string ImplicitPCHInclude;
+
+ /// Headers that will be converted to chained PCHs in memory.
+ std::vector<std::string> ChainedIncludes;
+
+ /// Whether to disable most of the normal validation performed on
+ /// precompiled headers and module files.
+ DisableValidationForModuleKind DisablePCHOrModuleValidation =
+ DisableValidationForModuleKind::None;
+
+ /// When true, a PCH with compiler errors will not be rejected.
+ bool AllowPCHWithCompilerErrors = false;
+
+ /// When true, a PCH with modules cache path different to the current
+ /// compilation will not be rejected.
+ bool AllowPCHWithDifferentModulesCachePath = false;
+
+ /// Dump declarations that are deserialized from PCH, for testing.
+ bool DumpDeserializedPCHDecls = false;
+
+ /// This is a set of names for decls that we do not want to be
+ /// deserialized, and we emit an error if they are; for testing purposes.
+ std::set<std::string> DeserializedPCHDeclsToErrorOn;
+
+ /// If non-zero, the implicit PCH include is actually a precompiled
+ /// preamble that covers this number of bytes in the main source file.
+ ///
+ /// The boolean indicates whether the preamble ends at the start of a new
+ /// line.
+ std::pair<unsigned, bool> PrecompiledPreambleBytes;
+
+ /// True indicates that a preamble is being generated.
+ ///
+ /// When the lexer is done, one of the things that need to be preserved is the
+ /// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when
+ /// processing the rest of the file. Similarly, we track an unterminated
+ /// #pragma assume_nonnull.
+ bool GeneratePreamble = false;
+
+ /// Whether to write comment locations into the PCH when building it.
+ /// Reading the comments from the PCH can be a performance hit even if the
+ /// clients don't use them.
+ bool WriteCommentListToPCH = true;
+
+ /// When enabled, preprocessor is in a mode for parsing a single file only.
+ ///
+ /// Disables #includes of other files and if there are unresolved identifiers
+ /// in preprocessor directive conditions it causes all blocks to be parsed so
+ /// that the client can get the maximum amount of information from the parser.
+ bool SingleFileParseMode = false;
+
+ /// When enabled, the preprocessor will construct editor placeholder tokens.
+ bool LexEditorPlaceholders = true;
+
+ /// True if the SourceManager should report the original file name for
+ /// contents of files that were remapped to other files. Defaults to true.
+ bool RemappedFilesKeepOriginalName = true;
+
+ /// The set of file remappings, which take existing files on
+ /// the system (the first part of each pair) and gives them the
+ /// contents of other files on the system (the second part of each
+ /// pair).
+ std::vector<std::pair<std::string, std::string>> RemappedFiles;
+
+ /// The set of file-to-buffer remappings, which take existing files
+ /// on the system (the first part of each pair) and gives them the contents
+ /// of the specified memory buffer (the second part of each pair).
+ std::vector<std::pair<std::string, llvm::MemoryBuffer *>> RemappedFileBuffers;
+
+ /// Whether the compiler instance should retain (i.e., not free)
+ /// the buffers associated with remapped files.
+ ///
+ /// This flag defaults to false; it can be set true only through direct
+ /// manipulation of the compiler invocation object, in cases where the
+ /// compiler invocation and its buffers will be reused.
+ bool RetainRemappedFileBuffers = false;
+
+ /// When enabled, excluded conditional blocks retain in the main file.
+ bool RetainExcludedConditionalBlocks = false;
+
+ /// The Objective-C++ ARC standard library that we should support,
+ /// by providing appropriate definitions to retrofit the standard library
+ /// with support for lifetime-qualified pointers.
+ ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib;
+
+ /// Records the set of modules
+ class FailedModulesSet {
+ llvm::StringSet<> Failed;
+
+ public:
+ bool hasAlreadyFailed(StringRef module) {
+ return Failed.count(module) > 0;
+ }
+
+ void addFailed(StringRef module) {
+ Failed.insert(module);
+ }
+ };
+
+ /// The set of modules that failed to build.
+ ///
+ /// This pointer will be shared among all of the compiler instances created
+ /// to (re)build modules, so that once a module fails to build anywhere,
+ /// other instances will see that the module has failed and won't try to
+ /// build it again.
+ std::shared_ptr<FailedModulesSet> FailedModules;
+
+ /// Function for getting the dependency preprocessor directives of a file.
+ ///
+ /// These are directives derived from a special form of lexing where the
+ /// source input is scanned for the preprocessor directives that might have an
+ /// effect on the dependencies for a compilation unit.
+ ///
+ /// Enables a client to cache the directives for a file and provide them
+ /// across multiple compiler invocations.
+ /// FIXME: Allow returning an error.
+ std::function<std::optional<ArrayRef<dependency_directives_scan::Directive>>(
+ FileEntryRef)>
+ DependencyDirectivesForFile;
+
+ /// Set up preprocessor for RunAnalysis action.
+ bool SetUpStaticAnalyzer = false;
+
+ /// Prevents intended crashes when using #pragma clang __debug. For testing.
+ bool DisablePragmaDebugCrash = false;
+
+ /// If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH.
+ std::optional<uint64_t> SourceDateEpoch;
+
+public:
+ PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
+
+ void addMacroDef(StringRef Name) {
+ Macros.emplace_back(std::string(Name), false);
+ }
+ void addMacroUndef(StringRef Name) {
+ Macros.emplace_back(std::string(Name), true);
+ }
+
+ void addRemappedFile(StringRef From, StringRef To) {
+ RemappedFiles.emplace_back(std::string(From), std::string(To));
+ }
+
+ void addRemappedFile(StringRef From, llvm::MemoryBuffer *To) {
+ RemappedFileBuffers.emplace_back(std::string(From), To);
+ }
+
+ void clearRemappedFiles() {
+ RemappedFiles.clear();
+ RemappedFileBuffers.clear();
+ }
+
+ /// Reset any options that are not considered when building a
+ /// module.
+ void resetNonModularOptions() {
+ Includes.clear();
+ MacroIncludes.clear();
+ ChainedIncludes.clear();
+ DumpDeserializedPCHDecls = false;
+ ImplicitPCHInclude.clear();
+ SingleFileParseMode = false;
+ LexEditorPlaceholders = true;
+ RetainRemappedFileBuffers = true;
+ PrecompiledPreambleBytes.first = 0;
+ PrecompiledPreambleBytes.second = false;
+ RetainExcludedConditionalBlocks = false;
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/ScratchBuffer.h b/contrib/libs/clang16/include/clang/Lex/ScratchBuffer.h
new file mode 100644
index 0000000000..6b6c792f21
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/ScratchBuffer.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- ScratchBuffer.h - Scratch space for forming tokens -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ScratchBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_SCRATCHBUFFER_H
+#define LLVM_CLANG_LEX_SCRATCHBUFFER_H
+
+#include "clang/Basic/SourceLocation.h"
+
+namespace clang {
+ class SourceManager;
+
+/// ScratchBuffer - This class exposes a simple interface for the dynamic
+/// construction of tokens. This is used for builtin macros (e.g. __LINE__) as
+/// well as token pasting, etc.
+class ScratchBuffer {
+ SourceManager &SourceMgr;
+ char *CurBuffer;
+ SourceLocation BufferStartLoc;
+ unsigned BytesUsed;
+public:
+ ScratchBuffer(SourceManager &SM);
+
+ /// getToken - Splat the specified text into a temporary MemoryBuffer and
+ /// return a SourceLocation that refers to the token. This is just like the
+ /// previous method, but returns a location that indicates the physloc of the
+ /// token.
+ SourceLocation getToken(const char *Buf, unsigned Len, const char *&DestPtr);
+
+private:
+ void AllocScratchBuffer(unsigned RequestLen);
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/Token.h b/contrib/libs/clang16/include/clang/Lex/Token.h
new file mode 100644
index 0000000000..72103d77c8
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/Token.h
@@ -0,0 +1,353 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- Token.h - Token interface ------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Token interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_TOKEN_H
+#define LLVM_CLANG_LEX_TOKEN_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include <cassert>
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// Token - This structure provides full information about a lexed token.
+/// It is not intended to be space efficient, it is intended to return as much
+/// information as possible about each returned token. This is expected to be
+/// compressed into a smaller form if memory footprint is important.
+///
+/// The parser can create a special "annotation token" representing a stream of
+/// tokens that were parsed and semantically resolved, e.g.: "foo::MyClass<int>"
+/// can be represented by a single typename annotation token that carries
+/// information about the SourceRange of the tokens and the type object.
+class Token {
+ /// The location of the token. This is actually a SourceLocation.
+ SourceLocation::UIntTy Loc;
+
+ // Conceptually these next two fields could be in a union. However, this
+ // causes gcc 4.2 to pessimize LexTokenInternal, a very performance critical
+ // routine. Keeping as separate members with casts until a more beautiful fix
+ // presents itself.
+
+ /// UintData - This holds either the length of the token text, when
+ /// a normal token, or the end of the SourceRange when an annotation
+ /// token.
+ SourceLocation::UIntTy UintData;
+
+ /// PtrData - This is a union of four different pointer types, which depends
+ /// on what type of token this is:
+ /// Identifiers, keywords, etc:
+ /// This is an IdentifierInfo*, which contains the uniqued identifier
+ /// spelling.
+ /// Literals: isLiteral() returns true.
+ /// This is a pointer to the start of the token in a text buffer, which
+ /// may be dirty (have trigraphs / escaped newlines).
+ /// Annotations (resolved type names, C++ scopes, etc): isAnnotation().
+ /// This is a pointer to sema-specific data for the annotation token.
+ /// Eof:
+ // This is a pointer to a Decl.
+ /// Other:
+ /// This is null.
+ void *PtrData;
+
+ /// Kind - The actual flavor of token this is.
+ tok::TokenKind Kind;
+
+ /// Flags - Bits we track about this token, members of the TokenFlags enum.
+ unsigned short Flags;
+
+public:
+ // Various flags set per token:
+ enum TokenFlags {
+ StartOfLine = 0x01, // At start of line or only after whitespace
+ // (considering the line after macro expansion).
+ LeadingSpace = 0x02, // Whitespace exists before this token (considering
+ // whitespace after macro expansion).
+ DisableExpand = 0x04, // This identifier may never be macro expanded.
+ NeedsCleaning = 0x08, // Contained an escaped newline or trigraph.
+ LeadingEmptyMacro = 0x10, // Empty macro exists before this token.
+ HasUDSuffix = 0x20, // This string or character literal has a ud-suffix.
+ HasUCN = 0x40, // This identifier contains a UCN.
+ IgnoredComma = 0x80, // This comma is not a macro argument separator (MS).
+ StringifiedInMacro = 0x100, // This string or character literal is formed by
+ // macro stringizing or charizing operator.
+ CommaAfterElided = 0x200, // The comma following this token was elided (MS).
+ IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
+ IsReinjected = 0x800, // A phase 4 token that was produced before and
+ // re-added, e.g. via EnterTokenStream. Annotation
+ // tokens are *not* reinjected.
+ };
+
+ tok::TokenKind getKind() const { return Kind; }
+ void setKind(tok::TokenKind K) { Kind = K; }
+
+ /// is/isNot - Predicates to check if this token is a specific kind, as in
+ /// "if (Tok.is(tok::l_brace)) {...}".
+ 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...);
+ }
+
+ /// Return true if this is a raw identifier (when lexing
+ /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode).
+ bool isAnyIdentifier() const {
+ return tok::isAnyIdentifier(getKind());
+ }
+
+ /// Return true if this is a "literal", like a numeric
+ /// constant, string, etc.
+ bool isLiteral() const {
+ return tok::isLiteral(getKind());
+ }
+
+ /// Return true if this is any of tok::annot_* kind tokens.
+ bool isAnnotation() const {
+ return tok::isAnnotation(getKind());
+ }
+
+ /// Return a source location identifier for the specified
+ /// offset in the current file.
+ SourceLocation getLocation() const {
+ return SourceLocation::getFromRawEncoding(Loc);
+ }
+ unsigned getLength() const {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ return UintData;
+ }
+
+ void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); }
+ void setLength(unsigned Len) {
+ assert(!isAnnotation() && "Annotation tokens have no length field");
+ UintData = Len;
+ }
+
+ SourceLocation getAnnotationEndLoc() const {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ return SourceLocation::getFromRawEncoding(UintData ? UintData : Loc);
+ }
+ void setAnnotationEndLoc(SourceLocation L) {
+ assert(isAnnotation() && "Used AnnotEndLocID on non-annotation token");
+ UintData = L.getRawEncoding();
+ }
+
+ SourceLocation getLastLoc() const {
+ return isAnnotation() ? getAnnotationEndLoc() : getLocation();
+ }
+
+ SourceLocation getEndLoc() const {
+ return isAnnotation() ? getAnnotationEndLoc()
+ : getLocation().getLocWithOffset(getLength());
+ }
+
+ /// SourceRange of the group of tokens that this annotation token
+ /// represents.
+ SourceRange getAnnotationRange() const {
+ return SourceRange(getLocation(), getAnnotationEndLoc());
+ }
+ void setAnnotationRange(SourceRange R) {
+ setLocation(R.getBegin());
+ setAnnotationEndLoc(R.getEnd());
+ }
+
+ const char *getName() const { return tok::getTokenName(Kind); }
+
+ /// Reset all flags to cleared.
+ void startToken() {
+ Kind = tok::unknown;
+ Flags = 0;
+ PtrData = nullptr;
+ UintData = 0;
+ Loc = SourceLocation().getRawEncoding();
+ }
+
+ bool hasPtrData() const { return PtrData != nullptr; }
+
+ IdentifierInfo *getIdentifierInfo() const {
+ assert(isNot(tok::raw_identifier) &&
+ "getIdentifierInfo() on a tok::raw_identifier token!");
+ assert(!isAnnotation() &&
+ "getIdentifierInfo() on an annotation token!");
+ if (isLiteral()) return nullptr;
+ if (is(tok::eof)) return nullptr;
+ return (IdentifierInfo*) PtrData;
+ }
+ void setIdentifierInfo(IdentifierInfo *II) {
+ PtrData = (void*) II;
+ }
+
+ const void *getEofData() const {
+ assert(is(tok::eof));
+ return reinterpret_cast<const void *>(PtrData);
+ }
+ void setEofData(const void *D) {
+ assert(is(tok::eof));
+ assert(!PtrData);
+ PtrData = const_cast<void *>(D);
+ }
+
+ /// getRawIdentifier - For a raw identifier token (i.e., an identifier
+ /// lexed in raw mode), returns a reference to the text substring in the
+ /// buffer if known.
+ StringRef getRawIdentifier() const {
+ assert(is(tok::raw_identifier));
+ return StringRef(reinterpret_cast<const char *>(PtrData), getLength());
+ }
+ void setRawIdentifierData(const char *Ptr) {
+ assert(is(tok::raw_identifier));
+ PtrData = const_cast<char*>(Ptr);
+ }
+
+ /// getLiteralData - For a literal token (numeric constant, string, etc), this
+ /// returns a pointer to the start of it in the text buffer if known, null
+ /// otherwise.
+ const char *getLiteralData() const {
+ assert(isLiteral() && "Cannot get literal data of non-literal");
+ return reinterpret_cast<const char*>(PtrData);
+ }
+ void setLiteralData(const char *Ptr) {
+ assert(isLiteral() && "Cannot set literal data of non-literal");
+ PtrData = const_cast<char*>(Ptr);
+ }
+
+ void *getAnnotationValue() const {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ return PtrData;
+ }
+ void setAnnotationValue(void *val) {
+ assert(isAnnotation() && "Used AnnotVal on non-annotation token");
+ PtrData = val;
+ }
+
+ /// Set the specified flag.
+ void setFlag(TokenFlags Flag) {
+ Flags |= Flag;
+ }
+
+ /// Get the specified flag.
+ bool getFlag(TokenFlags Flag) const {
+ return (Flags & Flag) != 0;
+ }
+
+ /// Unset the specified flag.
+ void clearFlag(TokenFlags Flag) {
+ Flags &= ~Flag;
+ }
+
+ /// Return the internal represtation of the flags.
+ ///
+ /// This is only intended for low-level operations such as writing tokens to
+ /// disk.
+ unsigned getFlags() const {
+ return Flags;
+ }
+
+ /// Set a flag to either true or false.
+ void setFlagValue(TokenFlags Flag, bool Val) {
+ if (Val)
+ setFlag(Flag);
+ else
+ clearFlag(Flag);
+ }
+
+ /// isAtStartOfLine - Return true if this token is at the start of a line.
+ ///
+ bool isAtStartOfLine() const { return getFlag(StartOfLine); }
+
+ /// Return true if this token has whitespace before it.
+ ///
+ bool hasLeadingSpace() const { return getFlag(LeadingSpace); }
+
+ /// Return true if this identifier token should never
+ /// be expanded in the future, due to C99 6.10.3.4p2.
+ bool isExpandDisabled() const { return getFlag(DisableExpand); }
+
+ /// Return true if we have an ObjC keyword identifier.
+ bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const;
+
+ /// Return the ObjC keyword kind.
+ tok::ObjCKeywordKind getObjCKeywordID() const;
+
+ /// Return true if this token has trigraphs or escaped newlines in it.
+ bool needsCleaning() const { return getFlag(NeedsCleaning); }
+
+ /// Return true if this token has an empty macro before it.
+ ///
+ bool hasLeadingEmptyMacro() const { return getFlag(LeadingEmptyMacro); }
+
+ /// Return true if this token is a string or character literal which
+ /// has a ud-suffix.
+ bool hasUDSuffix() const { return getFlag(HasUDSuffix); }
+
+ /// Returns true if this token contains a universal character name.
+ bool hasUCN() const { return getFlag(HasUCN); }
+
+ /// Returns true if this token is formed by macro by stringizing or charizing
+ /// operator.
+ bool stringifiedInMacro() const { return getFlag(StringifiedInMacro); }
+
+ /// Returns true if the comma after this token was elided.
+ bool commaAfterElided() const { return getFlag(CommaAfterElided); }
+
+ /// Returns true if this token is an editor placeholder.
+ ///
+ /// Editor placeholders are produced by the code-completion engine and are
+ /// represented as characters between '<#' and '#>' in the source code. The
+ /// lexer uses identifier tokens to represent placeholders.
+ bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
+};
+
+/// Information about the conditional stack (\#if directives)
+/// currently active.
+struct PPConditionalInfo {
+ /// Location where the conditional started.
+ SourceLocation IfLoc;
+
+ /// True if this was contained in a skipping directive, e.g.,
+ /// in a "\#if 0" block.
+ bool WasSkipping;
+
+ /// True if we have emitted tokens already, and now we're in
+ /// an \#else block or something. Only useful in Skipping blocks.
+ bool FoundNonSkip;
+
+ /// True if we've seen a \#else in this block. If so,
+ /// \#elif/\#else directives are not allowed.
+ bool FoundElse;
+};
+
+// Extra information needed for annonation tokens.
+struct PragmaLoopHintInfo {
+ Token PragmaName;
+ Token Option;
+ ArrayRef<Token> Toks;
+};
+} // end namespace clang
+
+#endif // LLVM_CLANG_LEX_TOKEN_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/TokenConcatenation.h b/contrib/libs/clang16/include/clang/Lex/TokenConcatenation.h
new file mode 100644
index 0000000000..7eb482fe6a
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/TokenConcatenation.h
@@ -0,0 +1,82 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- TokenConcatenation.h - Token Concatenation Avoidance ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenConcatenation class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_TOKENCONCATENATION_H
+#define LLVM_CLANG_LEX_TOKENCONCATENATION_H
+
+#include "clang/Basic/TokenKinds.h"
+
+namespace clang {
+ class Preprocessor;
+ class Token;
+
+ /// TokenConcatenation class, which answers the question of
+ /// "Is it safe to emit two tokens without a whitespace between them, or
+ /// would that cause implicit concatenation of the tokens?"
+ ///
+ /// For example, it emitting two identifiers "foo" and "bar" next to each
+ /// other would cause the lexer to produce one "foobar" token. Emitting "1"
+ /// and ")" next to each other is safe.
+ ///
+ class TokenConcatenation {
+ const Preprocessor &PP;
+
+ enum AvoidConcatInfo {
+ /// By default, a token never needs to avoid concatenation. Most tokens
+ /// (e.g. ',', ')', etc) don't cause a problem when concatenated.
+ aci_never_avoid_concat = 0,
+
+ /// aci_custom_firstchar - AvoidConcat contains custom code to handle this
+ /// token's requirements, and it needs to know the first character of the
+ /// token.
+ aci_custom_firstchar = 1,
+
+ /// aci_custom - AvoidConcat contains custom code to handle this token's
+ /// requirements, but it doesn't need to know the first character of the
+ /// token.
+ aci_custom = 2,
+
+ /// aci_avoid_equal - Many tokens cannot be safely followed by an '='
+ /// character. For example, "<<" turns into "<<=" when followed by an =.
+ aci_avoid_equal = 4
+ };
+
+ /// TokenInfo - This array contains information for each token on what
+ /// action to take when avoiding concatenation of tokens in the AvoidConcat
+ /// method.
+ char TokenInfo[tok::NUM_TOKENS];
+ public:
+ TokenConcatenation(const Preprocessor &PP);
+
+ bool AvoidConcat(const Token &PrevPrevTok,
+ const Token &PrevTok,
+ const Token &Tok) const;
+
+ private:
+ /// IsIdentifierStringPrefix - Return true if the spelling of the token
+ /// is literally 'L', 'u', 'U', or 'u8'.
+ bool IsIdentifierStringPrefix(const Token &Tok) const;
+ };
+ } // end clang namespace
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/TokenLexer.h b/contrib/libs/clang16/include/clang/Lex/TokenLexer.h
new file mode 100644
index 0000000000..70bf6839fa
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/TokenLexer.h
@@ -0,0 +1,256 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- TokenLexer.h - Lex from a token buffer -------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TokenLexer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_TOKENLEXER_H
+#define LLVM_CLANG_LEX_TOKENLEXER_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/ArrayRef.h"
+
+namespace clang {
+
+class MacroArgs;
+class MacroInfo;
+class Preprocessor;
+class Token;
+class VAOptExpansionContext;
+
+/// TokenLexer - This implements a lexer that returns tokens from a macro body
+/// or token stream instead of lexing from a character buffer. This is used for
+/// macro expansion and _Pragma handling, for example.
+class TokenLexer {
+ friend class Preprocessor;
+
+ /// The macro we are expanding from. This is null if expanding a token stream.
+ MacroInfo *Macro = nullptr;
+
+ /// The actual arguments specified for a function-like macro, or null. The
+ /// TokenLexer owns the pointed-to object.
+ MacroArgs *ActualArgs = nullptr;
+
+ /// The current preprocessor object we are expanding for.
+ Preprocessor &PP;
+
+ /// This is the pointer to an array of tokens that the macro is
+ /// defined to, with arguments expanded for function-like macros. If this is
+ /// a token stream, these are the tokens we are returning. This points into
+ /// the macro definition we are lexing from, a cache buffer that is owned by
+ /// the preprocessor, or some other buffer that we may or may not own
+ /// (depending on OwnsTokens).
+ /// Note that if it points into Preprocessor's cache buffer, the Preprocessor
+ /// may update the pointer as needed.
+ const Token *Tokens;
+
+ /// This is the length of the Tokens array.
+ unsigned NumTokens;
+
+ /// This is the index of the next token that Lex will return.
+ unsigned CurTokenIdx;
+
+ /// The source location range where this macro was expanded.
+ SourceLocation ExpandLocStart, ExpandLocEnd;
+
+ /// Source location pointing at the source location entry chunk that
+ /// was reserved for the current macro expansion.
+ SourceLocation MacroExpansionStart;
+
+ /// The offset of the macro expansion in the
+ /// "source location address space".
+ unsigned MacroStartSLocOffset;
+
+ /// Location of the macro definition.
+ SourceLocation MacroDefStart;
+
+ /// Length of the macro definition.
+ unsigned MacroDefLength;
+
+ /// Lexical information about the expansion point of the macro: the identifier
+ /// that the macro expanded from had these properties.
+ bool AtStartOfLine : 1;
+ bool HasLeadingSpace : 1;
+
+ // When this is true, the next token appended to the
+ // output list during function argument expansion will get a leading space,
+ // regardless of whether it had one to begin with or not. This is used for
+ // placemarker support. If still true after function argument expansion, the
+ // leading space will be applied to the first token following the macro
+ // expansion.
+ bool NextTokGetsSpace : 1;
+
+ /// This is true if this TokenLexer allocated the Tokens
+ /// array, and thus needs to free it when destroyed. For simple object-like
+ /// macros (for example) we just point into the token buffer of the macro
+ /// definition, we don't make a copy of it.
+ bool OwnsTokens : 1;
+
+ /// This is true when tokens lexed from the TokenLexer
+ /// should not be subject to further macro expansion.
+ bool DisableMacroExpansion : 1;
+
+ /// When true, the produced tokens have Token::IsReinjected flag set.
+ /// See the flag documentation for details.
+ bool IsReinject : 1;
+
+public:
+ /// Create a TokenLexer for the specified macro with the specified actual
+ /// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
+ /// ILEnd specifies the location of the ')' for a function-like macro or the
+ /// identifier for an object-like macro.
+ TokenLexer(Token &Tok, SourceLocation ILEnd, MacroInfo *MI,
+ MacroArgs *ActualArgs, Preprocessor &pp)
+ : PP(pp), OwnsTokens(false) {
+ Init(Tok, ILEnd, MI, ActualArgs);
+ }
+
+ /// Create a TokenLexer for the specified token stream. If 'OwnsTokens' is
+ /// specified, this takes ownership of the tokens and delete[]'s them when
+ /// the token lexer is empty.
+ TokenLexer(const Token *TokArray, unsigned NumToks, bool DisableExpansion,
+ bool ownsTokens, bool isReinject, Preprocessor &pp)
+ : PP(pp), OwnsTokens(false) {
+ Init(TokArray, NumToks, DisableExpansion, ownsTokens, isReinject);
+ }
+
+ TokenLexer(const TokenLexer &) = delete;
+ TokenLexer &operator=(const TokenLexer &) = delete;
+ ~TokenLexer() { destroy(); }
+
+ /// Initialize this TokenLexer to expand from the specified macro
+ /// with the specified argument information. Note that this ctor takes
+ /// ownership of the ActualArgs pointer. ILEnd specifies the location of the
+ /// ')' for a function-like macro or the identifier for an object-like macro.
+ void Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI,
+ MacroArgs *Actuals);
+
+ /// Initialize this TokenLexer with the specified token stream.
+ /// This does not take ownership of the specified token vector.
+ ///
+ /// DisableExpansion is true when macro expansion of tokens lexed from this
+ /// stream should be disabled.
+ void Init(const Token *TokArray, unsigned NumToks, bool DisableMacroExpansion,
+ bool OwnsTokens, bool IsReinject);
+
+ /// If the next token lexed will pop this macro off the
+ /// expansion stack, return 2. If the next unexpanded token is a '(', return
+ /// 1, otherwise return 0.
+ unsigned isNextTokenLParen() const;
+
+ /// Lex and return a token from this macro stream.
+ bool Lex(Token &Tok);
+
+ /// isParsingPreprocessorDirective - Return true if we are in the middle of a
+ /// preprocessor directive.
+ bool isParsingPreprocessorDirective() const;
+
+private:
+ void destroy();
+
+ /// Return true if the next lex call will pop this macro off the include
+ /// stack.
+ bool isAtEnd() const {
+ return CurTokenIdx == NumTokens;
+ }
+
+ /// Concatenates the next (sub-)sequence of \p Tokens separated by '##'
+ /// starting with LHSTok - stopping when we encounter a token that is neither
+ /// '##' nor preceded by '##'. Places the result back into \p LHSTok and sets
+ /// \p CurIdx to point to the token following the last one that was pasted.
+ ///
+ /// Also performs the MSVC extension wide-literal token pasting involved with:
+ /// \code L #macro-arg. \endcode
+ ///
+ /// \param[in,out] LHSTok - Contains the token to the left of '##' in \p
+ /// Tokens upon entry and will contain the resulting concatenated Token upon
+ /// exit.
+ ///
+ /// \param[in] TokenStream - The stream of Tokens we are lexing from.
+ ///
+ /// \param[in,out] CurIdx - Upon entry, \pTokens[\pCurIdx] must equal '##'
+ /// (with the exception of the MSVC extension mentioned above). Upon exit, it
+ /// is set to the index of the token following the last token that was
+ /// concatenated together.
+ ///
+ /// \returns If this returns true, the caller should immediately return the
+ /// token.
+ bool pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
+ unsigned int &CurIdx);
+
+ /// Calls pasteTokens above, passing in the '*this' object's Tokens and
+ /// CurTokenIdx data members.
+ bool pasteTokens(Token &Tok);
+
+
+ /// Takes the tail sequence of tokens within ReplacementToks that represent
+ /// the just expanded __VA_OPT__ tokens (possibly zero tokens) and transforms
+ /// them into a string. \p VCtx is used to determine which token represents
+ /// the first __VA_OPT__ replacement token.
+ ///
+ /// \param[in,out] ResultToks - Contains the current Replacement Tokens
+ /// (prior to rescanning and token pasting), the tail end of which represents
+ /// the tokens just expanded through __VA_OPT__ processing. These (sub)
+ /// sequence of tokens are folded into one stringified token.
+ ///
+ /// \param[in] VCtx - contains relevant contextual information about the
+ /// state of the tokens around and including the __VA_OPT__ token, necessary
+ /// for stringification.
+ void stringifyVAOPTContents(SmallVectorImpl<Token> &ResultToks,
+ const VAOptExpansionContext &VCtx,
+ SourceLocation VAOPTClosingParenLoc);
+
+ /// Expand the arguments of a function-like macro so that we can quickly
+ /// return preexpanded tokens from Tokens.
+ void ExpandFunctionArguments();
+
+ /// In microsoft compatibility mode, /##/ pastes
+ /// together to form a comment that comments out everything in the current
+ /// macro, other active macros, and anything left on the current physical
+ /// source line of the expanded buffer. Handle this by returning the
+ /// first token on the next line.
+ void HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc);
+
+ /// If \p loc is a FileID and points inside the current macro
+ /// definition, returns the appropriate source location pointing at the
+ /// macro expansion source location entry.
+ SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const;
+
+ /// Creates SLocEntries and updates the locations of macro argument
+ /// tokens to their new expanded locations.
+ ///
+ /// \param ArgIdSpellLoc the location of the macro argument id inside the
+ /// macro definition.
+ void updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
+ Token *begin_tokens, Token *end_tokens);
+
+ /// Remove comma ahead of __VA_ARGS__, if present, according to compiler
+ /// dialect settings. Returns true if the comma is removed.
+ bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
+ bool HasPasteOperator,
+ MacroInfo *Macro, unsigned MacroArgNo,
+ Preprocessor &PP);
+
+ void PropagateLineStartLeadingSpaceInfo(Token &Result);
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_LEX_TOKENLEXER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Lex/VariadicMacroSupport.h b/contrib/libs/clang16/include/clang/Lex/VariadicMacroSupport.h
new file mode 100644
index 0000000000..dcb0c5dd9d
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Lex/VariadicMacroSupport.h
@@ -0,0 +1,254 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- VariadicMacroSupport.h - state machines and scope guards -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines support types to help with preprocessing variadic macro
+// (i.e. macros that use: ellipses __VA_ARGS__ ) definitions and
+// expansions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H
+#define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H
+
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class Preprocessor;
+
+ /// An RAII class that tracks when the Preprocessor starts and stops lexing
+ /// the definition of a (ISO C/C++) variadic macro. As an example, this is
+ /// useful for unpoisoning and repoisoning certain identifiers (such as
+ /// __VA_ARGS__) that are only allowed in this context. Also, being a friend
+ /// of the Preprocessor class allows it to access PP's cached identifiers
+ /// directly (as opposed to performing a lookup each time).
+ class VariadicMacroScopeGuard {
+ const Preprocessor &PP;
+ IdentifierInfo *const Ident__VA_ARGS__;
+ IdentifierInfo *const Ident__VA_OPT__;
+
+ public:
+ VariadicMacroScopeGuard(const Preprocessor &P)
+ : PP(P), Ident__VA_ARGS__(PP.Ident__VA_ARGS__),
+ Ident__VA_OPT__(PP.Ident__VA_OPT__) {
+ assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned "
+ "outside an ISO C/C++ variadic "
+ "macro definition!");
+ assert(Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!");
+ }
+
+ /// Client code should call this function just before the Preprocessor is
+ /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro.
+ void enterScope() {
+ Ident__VA_ARGS__->setIsPoisoned(false);
+ Ident__VA_OPT__->setIsPoisoned(false);
+ }
+
+ /// Client code should call this function as soon as the Preprocessor has
+ /// either completed lexing the macro's definition tokens, or an error
+ /// occurred and the context is being exited. This function is idempotent
+ /// (might be explicitly called, and then reinvoked via the destructor).
+ void exitScope() {
+ Ident__VA_ARGS__->setIsPoisoned(true);
+ Ident__VA_OPT__->setIsPoisoned(true);
+ }
+
+ ~VariadicMacroScopeGuard() { exitScope(); }
+ };
+
+ /// A class for tracking whether we're inside a VA_OPT during a
+ /// traversal of the tokens of a variadic macro definition.
+ class VAOptDefinitionContext {
+ /// Contains all the locations of so far unmatched lparens.
+ SmallVector<SourceLocation, 8> UnmatchedOpeningParens;
+
+ const IdentifierInfo *const Ident__VA_OPT__;
+
+
+ public:
+ VAOptDefinitionContext(Preprocessor &PP)
+ : Ident__VA_OPT__(PP.Ident__VA_OPT__) {}
+
+ bool isVAOptToken(const Token &T) const {
+ return Ident__VA_OPT__ && T.getIdentifierInfo() == Ident__VA_OPT__;
+ }
+
+ /// Returns true if we have seen the __VA_OPT__ and '(' but before having
+ /// seen the matching ')'.
+ bool isInVAOpt() const { return UnmatchedOpeningParens.size(); }
+
+ /// Call this function as soon as you see __VA_OPT__ and '('.
+ void sawVAOptFollowedByOpeningParens(const SourceLocation LParenLoc) {
+ assert(!isInVAOpt() && "Must NOT be within VAOPT context to call this");
+ UnmatchedOpeningParens.push_back(LParenLoc);
+
+ }
+
+ SourceLocation getUnmatchedOpeningParenLoc() const {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ return UnmatchedOpeningParens.back();
+ }
+
+ /// Call this function each time an rparen is seen. It returns true only if
+ /// the rparen that was just seen was the eventual (non-nested) closing
+ /// paren for VAOPT, and ejects us out of the VAOPT context.
+ bool sawClosingParen() {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ UnmatchedOpeningParens.pop_back();
+ return !UnmatchedOpeningParens.size();
+ }
+
+ /// Call this function each time an lparen is seen.
+ void sawOpeningParen(SourceLocation LParenLoc) {
+ assert(isInVAOpt() && "Must be within VAOPT context to call this");
+ UnmatchedOpeningParens.push_back(LParenLoc);
+ }
+
+ /// Are we at the top level within the __VA_OPT__?
+ bool isAtTopLevel() const { return UnmatchedOpeningParens.size() == 1; }
+ };
+
+ /// A class for tracking whether we're inside a VA_OPT during a
+ /// traversal of the tokens of a macro during macro expansion.
+ class VAOptExpansionContext : VAOptDefinitionContext {
+
+ Token SyntheticEOFToken;
+
+ // The (spelling) location of the current __VA_OPT__ in the replacement list
+ // of the function-like macro being expanded.
+ SourceLocation VAOptLoc;
+
+ // NumOfTokensPriorToVAOpt : when != -1, contains the index *of* the first
+ // token of the current VAOPT contents (so we know where to start eager
+ // token-pasting and stringification) *within* the substituted tokens of
+ // the function-like macro's new replacement list.
+ int NumOfTokensPriorToVAOpt = -1;
+
+ unsigned LeadingSpaceForStringifiedToken : 1;
+
+ unsigned StringifyBefore : 1;
+ unsigned CharifyBefore : 1;
+ unsigned BeginsWithPlaceholder : 1;
+ unsigned EndsWithPlaceholder : 1;
+
+ bool hasStringifyBefore() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return StringifyBefore;
+ }
+
+ bool isReset() const {
+ return NumOfTokensPriorToVAOpt == -1 ||
+ VAOptLoc.isInvalid();
+ }
+
+ public:
+ VAOptExpansionContext(Preprocessor &PP)
+ : VAOptDefinitionContext(PP), LeadingSpaceForStringifiedToken(false),
+ StringifyBefore(false), CharifyBefore(false),
+ BeginsWithPlaceholder(false), EndsWithPlaceholder(false) {
+ SyntheticEOFToken.startToken();
+ SyntheticEOFToken.setKind(tok::eof);
+ }
+
+ void reset() {
+ VAOptLoc = SourceLocation();
+ NumOfTokensPriorToVAOpt = -1;
+ LeadingSpaceForStringifiedToken = false;
+ StringifyBefore = false;
+ CharifyBefore = false;
+ BeginsWithPlaceholder = false;
+ EndsWithPlaceholder = false;
+ }
+
+ const Token &getEOFTok() const { return SyntheticEOFToken; }
+
+ void sawHashOrHashAtBefore(const bool HasLeadingSpace,
+ const bool IsHashAt) {
+
+ StringifyBefore = !IsHashAt;
+ CharifyBefore = IsHashAt;
+ LeadingSpaceForStringifiedToken = HasLeadingSpace;
+ }
+
+ void hasPlaceholderAfterHashhashAtStart() { BeginsWithPlaceholder = true; }
+ void hasPlaceholderBeforeRParen() {
+ if (isAtTopLevel())
+ EndsWithPlaceholder = true;
+ }
+
+
+ bool beginsWithPlaceholder() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return BeginsWithPlaceholder;
+ }
+ bool endsWithPlaceholder() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return EndsWithPlaceholder;
+ }
+
+ bool hasCharifyBefore() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return CharifyBefore;
+ }
+ bool hasStringifyOrCharifyBefore() const {
+ return hasStringifyBefore() || hasCharifyBefore();
+ }
+
+ unsigned int getNumberOfTokensPriorToVAOpt() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ return NumOfTokensPriorToVAOpt;
+ }
+
+ bool getLeadingSpaceForStringifiedToken() const {
+ assert(hasStringifyBefore() &&
+ "Must only be called if this has been marked for stringification");
+ return LeadingSpaceForStringifiedToken;
+ }
+
+ void sawVAOptFollowedByOpeningParens(const SourceLocation VAOptLoc,
+ const unsigned int NumPriorTokens) {
+ assert(VAOptLoc.isFileID() && "Must not come from a macro expansion");
+ assert(isReset() && "Must only be called if the state has been reset");
+ VAOptDefinitionContext::sawVAOptFollowedByOpeningParens(SourceLocation());
+ this->VAOptLoc = VAOptLoc;
+ NumOfTokensPriorToVAOpt = NumPriorTokens;
+ assert(NumOfTokensPriorToVAOpt > -1 &&
+ "Too many prior tokens");
+ }
+
+ SourceLocation getVAOptLoc() const {
+ assert(!isReset() &&
+ "Must only be called if the state has not been reset");
+ assert(VAOptLoc.isValid() && "__VA_OPT__ location must be valid");
+ return VAOptLoc;
+ }
+ using VAOptDefinitionContext::isVAOptToken;
+ using VAOptDefinitionContext::isInVAOpt;
+ using VAOptDefinitionContext::sawClosingParen;
+ using VAOptDefinitionContext::sawOpeningParen;
+
+ };
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif