LLVM Backend ekleniyor

This commit is contained in:
abdussamedulutas 2026-01-12 09:46:38 +03:00
parent 0c9ac1c876
commit 1af0592232
3233 changed files with 1467363 additions and 78 deletions

View File

@ -1,90 +1,39 @@
extern "C" { #include "llvm/include/llvm-c/Core.h"
#include "lightning.h" #include "llvm/include/llvm-c/Analysis.h"
} #include <stdio.h>
#include <iostream>
#include <fstream>
#include <sys/mman.h>
#include <unistd.h>
#include <chrono>
extern "C" int saqut_print(int value) {
return value + 1;
}
int main() { int main() {
init_jit("saqut"); // 1. LLVM Context Oluştur (Bellek yönetimi ve izolasyon için şart)
jit_state_t *_jit = jit_new_state(); LLVMContextRef context = LLVMContextCreate();
jit_prolog(); // 2. Modülü bu context içinde oluştur
LLVMModuleRef mod = LLVMModuleCreateWithNameInContext("saqut_module", context);
jit_movi(JIT_V0, 0); // sum = 0 (V0 kayıısı sum olsun) // 3. Basit bir fonksiyon tipi oluştur: int32 f()
jit_movi(JIT_V1, 1); // a = 1 (V1 kayıısı a olsun) LLVMTypeRef ret_type = LLVMInt32TypeInContext(context);
LLVMTypeRef func_type = LLVMFunctionType(ret_type, NULL, 0, 0);
jit_node_t *loop_start = jit_label(); // 4. Fonksiyonu modüle ekle
LLVMValueRef main_func = LLVMAddFunction(mod, "saqut_main", func_type);
// sum += a (Kayııdan kayııya toplama - Işık hızında) // 5. Temel bir blok (Entry block) ekle
jit_addr(JIT_V0, JIT_V0, JIT_V1); LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context, main_func, "entry");
// a++ // 6. Bir Builder oluştur ve fonksiyonun içine "return 0" ekle
jit_addi(JIT_V1, JIT_V1, 1); LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
// a++ LLVMPositionBuilderAtEnd(builder, entry);
jit_addi(JIT_V1, JIT_V1, 1); LLVMBuildRet(builder, LLVMConstInt(LLVMInt32TypeInContext(context), 0, 0));
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a < 15000 kontrolü // 7. Oluşturulan IR kodunu terminale yazdır (Gözle kontrol için)
jit_movi(JIT_R1, 15000); printf("--- Oluşturulan LLVM IR Kodu ---\n");
jit_node_t *if_node = jit_bltr(JIT_V1, JIT_R1); // a < 15000 ise loop_start'a zıpla LLVMDumpModule(mod);
jit_patch_at(if_node, loop_start); printf("--------------------------------\n");
printf("saQut: LLVM Modülü ve Fonksiyonu başarıyla oluşturuldu!\n");
jit_movr(JIT_R0, JIT_V0); // sonucu döndür // 8. Temizlik (Bellek sızıntısını önlemek için önemli)
jit_retr(JIT_R0); LLVMDisposeBuilder(builder);
jit_epilog(); LLVMDisposeModule(mod);
LLVMContextDispose(context);
// --- ÇALIŞTIRMA VE KAYDETME ---
jit_realize();
jit_word_t size;
void* final_code = jit_emit();
jit_get_code(&size);
void (*func)() = (void (*)())final_code;
std::cout << "--- saQut Programı Başlıyor ---" << std::endl;
if (final_code) {
auto start = std::chrono::high_resolution_clock::now();
func();
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> elapsed = end - start;
std::cout << "Süre: " << elapsed.count() << " mikrosaniye." << std::endl;
}
if (final_code) {
volatile int prevent_optimization = 0;
auto start = std::chrono::high_resolution_clock::now();
int sum = 0;
for(int a = 0; a < 15000; a++) {
sum += saqut_print(a);
}
prevent_optimization = sum;
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> elapsed = end - start;
std::cout << "Süre: " << elapsed.count() << " mikrosaniye." << prevent_optimization << std::endl;
}
std::cout << "--- saQut Programı Bitti ---" << std::endl;
std::cout << "Kod üretildi. Boyut: " << static_cast<signed long>(size) << " bayt." << std::endl;
std::ofstream outfile("calc.bin", std::ios::binary);
outfile.write(reinterpret_cast<const char*>(final_code), size);
outfile.close();
jit_destroy_state();
finish_jit();
return 0; return 0;
} }

90
ParsingLightning.cpp Normal file
View File

@ -0,0 +1,90 @@
extern "C" {
#include "lightning.h"
}
#include <iostream>
#include <fstream>
#include <sys/mman.h>
#include <unistd.h>
#include <chrono>
extern "C" int saqut_print(int value) {
return value + 1;
}
int main() {
init_jit("saqut");
jit_state_t *_jit = jit_new_state();
jit_prolog();
jit_movi(JIT_V0, 0); // sum = 0 (V0 kayıısı sum olsun)
jit_movi(JIT_V1, 1); // a = 1 (V1 kayıısı a olsun)
jit_node_t *loop_start = jit_label();
// sum += a (Kayııdan kayııya toplama - Işık hızında)
jit_addr(JIT_V0, JIT_V0, JIT_V1);
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a++
jit_addi(JIT_V1, JIT_V1, 1);
// a < 15000 kontrolü
jit_movi(JIT_R1, 15000);
jit_node_t *if_node = jit_bltr(JIT_V1, JIT_R1); // a < 15000 ise loop_start'a zıpla
jit_patch_at(if_node, loop_start);
jit_movr(JIT_R0, JIT_V0); // sonucu döndür
jit_retr(JIT_R0);
jit_epilog();
// --- ÇALIŞTIRMA VE KAYDETME ---
jit_realize();
jit_word_t size;
void* final_code = jit_emit();
jit_get_code(&size);
void (*func)() = (void (*)())final_code;
std::cout << "--- saQut Programı Başlıyor ---" << std::endl;
if (final_code) {
auto start = std::chrono::high_resolution_clock::now();
func();
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> elapsed = end - start;
std::cout << "Süre: " << elapsed.count() << " mikrosaniye." << std::endl;
}
if (final_code) {
volatile int prevent_optimization = 0;
auto start = std::chrono::high_resolution_clock::now();
int sum = 0;
for(int a = 0; a < 15000; a++) {
sum += saqut_print(a);
}
prevent_optimization = sum;
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> elapsed = end - start;
std::cout << "Süre: " << elapsed.count() << " mikrosaniye." << prevent_optimization << std::endl;
}
std::cout << "--- saQut Programı Bitti ---" << std::endl;
std::cout << "Kod üretildi. Boyut: " << static_cast<signed long>(size) << " bayt." << std::endl;
std::ofstream outfile("calc.bin", std::ios::binary);
outfile.write(reinterpret_cast<const char*>(final_code), size);
outfile.close();
jit_destroy_state();
finish_jit();
return 0;
}

View File

@ -0,0 +1,153 @@
/*==-- clang-c/BuildSystem.h - Utilities for use by build systems -*- 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 header provides various utilities for use by build systems. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_BUILDSYSTEM_H
#define LLVM_CLANG_C_BUILDSYSTEM_H
#include "clang-c/CXErrorCode.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup BUILD_SYSTEM Build system utilities
* @{
*/
/**
* Return the timestamp for use with Clang's
* \c -fbuild-session-timestamp= option.
*/
CINDEX_LINKAGE unsigned long long clang_getBuildSessionTimestamp(void);
/**
* Object encapsulating information about overlaying virtual
* file/directories over the real file system.
*/
typedef struct CXVirtualFileOverlayImpl *CXVirtualFileOverlay;
/**
* Create a \c CXVirtualFileOverlay object.
* Must be disposed with \c clang_VirtualFileOverlay_dispose().
*
* \param options is reserved, always pass 0.
*/
CINDEX_LINKAGE CXVirtualFileOverlay
clang_VirtualFileOverlay_create(unsigned options);
/**
* Map an absolute virtual file path to an absolute real one.
* The virtual path must be canonicalized (not contain "."/"..").
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_VirtualFileOverlay_addFileMapping(CXVirtualFileOverlay,
const char *virtualPath,
const char *realPath);
/**
* Set the case sensitivity for the \c CXVirtualFileOverlay object.
* The \c CXVirtualFileOverlay object is case-sensitive by default, this
* option can be used to override the default.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_VirtualFileOverlay_setCaseSensitivity(CXVirtualFileOverlay,
int caseSensitive);
/**
* Write out the \c CXVirtualFileOverlay object to a char buffer.
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
* disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_VirtualFileOverlay_writeToBuffer(CXVirtualFileOverlay, unsigned options,
char **out_buffer_ptr,
unsigned *out_buffer_size);
/**
* free memory allocated by libclang, such as the buffer returned by
* \c CXVirtualFileOverlay() or \c clang_ModuleMapDescriptor_writeToBuffer().
*
* \param buffer memory pointer to free.
*/
CINDEX_LINKAGE void clang_free(void *buffer);
/**
* Dispose a \c CXVirtualFileOverlay object.
*/
CINDEX_LINKAGE void clang_VirtualFileOverlay_dispose(CXVirtualFileOverlay);
/**
* Object encapsulating information about a module.modulemap file.
*/
typedef struct CXModuleMapDescriptorImpl *CXModuleMapDescriptor;
/**
* Create a \c CXModuleMapDescriptor object.
* Must be disposed with \c clang_ModuleMapDescriptor_dispose().
*
* \param options is reserved, always pass 0.
*/
CINDEX_LINKAGE CXModuleMapDescriptor
clang_ModuleMapDescriptor_create(unsigned options);
/**
* Sets the framework module name that the module.modulemap describes.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_ModuleMapDescriptor_setFrameworkModuleName(CXModuleMapDescriptor,
const char *name);
/**
* Sets the umbrella header name that the module.modulemap describes.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_ModuleMapDescriptor_setUmbrellaHeader(CXModuleMapDescriptor,
const char *name);
/**
* Write out the \c CXModuleMapDescriptor object to a char buffer.
*
* \param options is reserved, always pass 0.
* \param out_buffer_ptr pointer to receive the buffer pointer, which should be
* disposed using \c clang_free().
* \param out_buffer_size pointer to receive the buffer size.
* \returns 0 for success, non-zero to indicate an error.
*/
CINDEX_LINKAGE enum CXErrorCode
clang_ModuleMapDescriptor_writeToBuffer(CXModuleMapDescriptor, unsigned options,
char **out_buffer_ptr,
unsigned *out_buffer_size);
/**
* Dispose a \c CXModuleMapDescriptor object.
*/
CINDEX_LINKAGE void clang_ModuleMapDescriptor_dispose(CXModuleMapDescriptor);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif /* CLANG_C_BUILD_SYSTEM_H */

View File

@ -0,0 +1,174 @@
/*===-- clang-c/CXCompilationDatabase.h - Compilation database ---*- 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 header provides a public interface to use CompilationDatabase without *|
|* the full Clang C++ API. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/** \defgroup COMPILATIONDB CompilationDatabase functions
* \ingroup CINDEX
*
* @{
*/
/**
* A compilation database holds all information used to compile files in a
* project. For each file in the database, it can be queried for the working
* directory or the command line used for the compiler invocation.
*
* Must be freed by \c clang_CompilationDatabase_dispose
*/
typedef void * CXCompilationDatabase;
/**
* Contains the results of a search in the compilation database
*
* When searching for the compile command for a file, the compilation db can
* return several commands, as the file may have been compiled with
* different options in different places of the project. This choice of compile
* commands is wrapped in this opaque data structure. It must be freed by
* \c clang_CompileCommands_dispose.
*/
typedef void * CXCompileCommands;
/**
* Represents the command line invocation to compile a specific file.
*/
typedef void * CXCompileCommand;
/**
* Error codes for Compilation Database
*/
typedef enum {
/*
* No error occurred
*/
CXCompilationDatabase_NoError = 0,
/*
* Database can not be loaded
*/
CXCompilationDatabase_CanNotLoadDatabase = 1
} CXCompilationDatabase_Error;
/**
* Creates a compilation database from the database found in directory
* buildDir. For example, CMake can output a compile_commands.json which can
* be used to build the database.
*
* It must be freed by \c clang_CompilationDatabase_dispose.
*/
CINDEX_LINKAGE CXCompilationDatabase
clang_CompilationDatabase_fromDirectory(const char *BuildDir,
CXCompilationDatabase_Error *ErrorCode);
/**
* Free the given compilation database
*/
CINDEX_LINKAGE void
clang_CompilationDatabase_dispose(CXCompilationDatabase);
/**
* Find the compile commands used for a file. The compile commands
* must be freed by \c clang_CompileCommands_dispose.
*/
CINDEX_LINKAGE CXCompileCommands
clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase,
const char *CompleteFileName);
/**
* Get all the compile commands in the given compilation database.
*/
CINDEX_LINKAGE CXCompileCommands
clang_CompilationDatabase_getAllCompileCommands(CXCompilationDatabase);
/**
* Free the given CompileCommands
*/
CINDEX_LINKAGE void clang_CompileCommands_dispose(CXCompileCommands);
/**
* Get the number of CompileCommand we have for a file
*/
CINDEX_LINKAGE unsigned
clang_CompileCommands_getSize(CXCompileCommands);
/**
* Get the I'th CompileCommand for a file
*
* Note : 0 <= i < clang_CompileCommands_getSize(CXCompileCommands)
*/
CINDEX_LINKAGE CXCompileCommand
clang_CompileCommands_getCommand(CXCompileCommands, unsigned I);
/**
* Get the working directory where the CompileCommand was executed from
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getDirectory(CXCompileCommand);
/**
* Get the filename associated with the CompileCommand.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getFilename(CXCompileCommand);
/**
* Get the number of arguments in the compiler invocation.
*
*/
CINDEX_LINKAGE unsigned
clang_CompileCommand_getNumArgs(CXCompileCommand);
/**
* Get the I'th argument value in the compiler invocations
*
* Invariant :
* - argument 0 is the compiler executable
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getArg(CXCompileCommand, unsigned I);
/**
* Get the number of source mappings for the compiler invocation.
*/
CINDEX_LINKAGE unsigned
clang_CompileCommand_getNumMappedSources(CXCompileCommand);
/**
* Get the I'th mapped source path for the compiler invocation.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getMappedSourcePath(CXCompileCommand, unsigned I);
/**
* Get the I'th mapped source content for the compiler invocation.
*/
CINDEX_LINKAGE CXString
clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,379 @@
/*===-- clang-c/CXDiagnostic.h - C Index Diagnostics --------------*- 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 header provides the interface to C Index diagnostics. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXDIAGNOSTIC_H
#define LLVM_CLANG_C_CXDIAGNOSTIC_H
#include "clang-c/CXSourceLocation.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_DIAG Diagnostic reporting
*
* @{
*/
/**
* Describes the severity of a particular diagnostic.
*/
enum CXDiagnosticSeverity {
/**
* A diagnostic that has been suppressed, e.g., by a command-line
* option.
*/
CXDiagnostic_Ignored = 0,
/**
* This diagnostic is a note that should be attached to the
* previous (non-note) diagnostic.
*/
CXDiagnostic_Note = 1,
/**
* This diagnostic indicates suspicious code that may not be
* wrong.
*/
CXDiagnostic_Warning = 2,
/**
* This diagnostic indicates that the code is ill-formed.
*/
CXDiagnostic_Error = 3,
/**
* This diagnostic indicates that the code is ill-formed such
* that future parser recovery is unlikely to produce useful
* results.
*/
CXDiagnostic_Fatal = 4
};
/**
* A single diagnostic, containing the diagnostic's severity,
* location, text, source ranges, and fix-it hints.
*/
typedef void *CXDiagnostic;
/**
* A group of CXDiagnostics.
*/
typedef void *CXDiagnosticSet;
/**
* Determine the number of diagnostics in a CXDiagnosticSet.
*/
CINDEX_LINKAGE unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
/**
* Retrieve a diagnostic associated with the given CXDiagnosticSet.
*
* \param Diags the CXDiagnosticSet to query.
* \param Index the zero-based diagnostic number to retrieve.
*
* \returns the requested diagnostic. This diagnostic must be freed
* via a call to \c clang_disposeDiagnostic().
*/
CINDEX_LINKAGE CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags,
unsigned Index);
/**
* Describes the kind of error that occurred (if any) in a call to
* \c clang_loadDiagnostics.
*/
enum CXLoadDiag_Error {
/**
* Indicates that no error occurred.
*/
CXLoadDiag_None = 0,
/**
* Indicates that an unknown error occurred while attempting to
* deserialize diagnostics.
*/
CXLoadDiag_Unknown = 1,
/**
* Indicates that the file containing the serialized diagnostics
* could not be opened.
*/
CXLoadDiag_CannotLoad = 2,
/**
* Indicates that the serialized diagnostics file is invalid or
* corrupt.
*/
CXLoadDiag_InvalidFile = 3
};
/**
* Deserialize a set of diagnostics from a Clang diagnostics bitcode
* file.
*
* \param file The name of the file to deserialize.
* \param error A pointer to a enum value recording if there was a problem
* deserializing the diagnostics.
* \param errorString A pointer to a CXString for recording the error string
* if the file was not successfully loaded.
*
* \returns A loaded CXDiagnosticSet if successful, and NULL otherwise. These
* diagnostics should be released using clang_disposeDiagnosticSet().
*/
CINDEX_LINKAGE CXDiagnosticSet clang_loadDiagnostics(
const char *file, enum CXLoadDiag_Error *error, CXString *errorString);
/**
* Release a CXDiagnosticSet and all of its contained diagnostics.
*/
CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags);
/**
* Retrieve the child diagnostics of a CXDiagnostic.
*
* This CXDiagnosticSet does not need to be released by
* clang_disposeDiagnosticSet.
*/
CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
/**
* Destroy a diagnostic.
*/
CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic);
/**
* Options to control the display of diagnostics.
*
* The values in this enum are meant to be combined to customize the
* behavior of \c clang_formatDiagnostic().
*/
enum CXDiagnosticDisplayOptions {
/**
* Display the source-location information where the
* diagnostic was located.
*
* When set, diagnostics will be prefixed by the file, line, and
* (optionally) column to which the diagnostic refers. For example,
*
* \code
* test.c:28: warning: extra tokens at end of #endif directive
* \endcode
*
* This option corresponds to the clang flag \c -fshow-source-location.
*/
CXDiagnostic_DisplaySourceLocation = 0x01,
/**
* If displaying the source-location information of the
* diagnostic, also include the column number.
*
* This option corresponds to the clang flag \c -fshow-column.
*/
CXDiagnostic_DisplayColumn = 0x02,
/**
* If displaying the source-location information of the
* diagnostic, also include information about source ranges in a
* machine-parsable format.
*
* This option corresponds to the clang flag
* \c -fdiagnostics-print-source-range-info.
*/
CXDiagnostic_DisplaySourceRanges = 0x04,
/**
* Display the option name associated with this diagnostic, if any.
*
* The option name displayed (e.g., -Wconversion) will be placed in brackets
* after the diagnostic text. This option corresponds to the clang flag
* \c -fdiagnostics-show-option.
*/
CXDiagnostic_DisplayOption = 0x08,
/**
* Display the category number associated with this diagnostic, if any.
*
* The category number is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=id.
*/
CXDiagnostic_DisplayCategoryId = 0x10,
/**
* Display the category name associated with this diagnostic, if any.
*
* The category name is displayed within brackets after the diagnostic text.
* This option corresponds to the clang flag
* \c -fdiagnostics-show-category=name.
*/
CXDiagnostic_DisplayCategoryName = 0x20
};
/**
* Format the given diagnostic in a manner that is suitable for display.
*
* This routine will format the given diagnostic to a string, rendering
* the diagnostic according to the various options given. The
* \c clang_defaultDiagnosticDisplayOptions() function returns the set of
* options that most closely mimics the behavior of the clang compiler.
*
* \param Diagnostic The diagnostic to print.
*
* \param Options A set of options that control the diagnostic display,
* created by combining \c CXDiagnosticDisplayOptions values.
*
* \returns A new string containing for formatted diagnostic.
*/
CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic,
unsigned Options);
/**
* Retrieve the set of display options most similar to the
* default behavior of the clang compiler.
*
* \returns A set of display options suitable for use with \c
* clang_formatDiagnostic().
*/
CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void);
/**
* Determine the severity of the given diagnostic.
*/
CINDEX_LINKAGE enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic);
/**
* Retrieve the source location of the given diagnostic.
*
* This location is where Clang would print the caret ('^') when
* displaying the diagnostic on the command line.
*/
CINDEX_LINKAGE CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
/**
* Retrieve the text of the given diagnostic.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticSpelling(CXDiagnostic);
/**
* Retrieve the name of the command-line option that enabled this
* diagnostic.
*
* \param Diag The diagnostic to be queried.
*
* \param Disable If non-NULL, will be set to the option that disables this
* diagnostic (if any).
*
* \returns A string that contains the command-line option used to enable this
* warning, such as "-Wconversion" or "-pedantic".
*/
CINDEX_LINKAGE CXString clang_getDiagnosticOption(CXDiagnostic Diag,
CXString *Disable);
/**
* Retrieve the category number for this diagnostic.
*
* Diagnostics can be categorized into groups along with other, related
* diagnostics (e.g., diagnostics under the same warning flag). This routine
* retrieves the category number for the given diagnostic.
*
* \returns The number of the category that contains this diagnostic, or zero
* if this diagnostic is uncategorized.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticCategory(CXDiagnostic);
/**
* Retrieve the name of a particular diagnostic category. This
* is now deprecated. Use clang_getDiagnosticCategoryText()
* instead.
*
* \param Category A diagnostic category number, as returned by
* \c clang_getDiagnosticCategory().
*
* \returns The name of the given diagnostic category.
*/
CINDEX_DEPRECATED CINDEX_LINKAGE CXString
clang_getDiagnosticCategoryName(unsigned Category);
/**
* Retrieve the diagnostic category text for a given diagnostic.
*
* \returns The text of the given diagnostic category.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
/**
* Determine the number of source ranges associated with the given
* diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
/**
* Retrieve a source range associated with the diagnostic.
*
* A diagnostic's source ranges highlight important elements in the source
* code. On the command line, Clang displays source ranges by
* underlining them with '~' characters.
*
* \param Diagnostic the diagnostic whose range is being extracted.
*
* \param Range the zero-based index specifying which range to
*
* \returns the requested source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
unsigned Range);
/**
* Determine the number of fix-it hints associated with the
* given diagnostic.
*/
CINDEX_LINKAGE unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
/**
* Retrieve the replacement information for a given fix-it.
*
* Fix-its are described in terms of a source range whose contents
* should be replaced by a string. This approach generalizes over
* three kinds of operations: removal of source code (the range covers
* the code to be removed and the replacement string is empty),
* replacement of source code (the range covers the code to be
* replaced and the replacement string provides the new code), and
* insertion (both the start and end of the range point at the
* insertion location, and the replacement string provides the text to
* insert).
*
* \param Diagnostic The diagnostic whose fix-its are being queried.
*
* \param FixIt The zero-based index of the fix-it.
*
* \param ReplacementRange The source range whose contents will be
* replaced with the returned replacement string. Note that source
* ranges are half-open ranges [a, b), so the source code should be
* replaced from a and up to (but not including) b.
*
* \returns A string containing text that should be replace the source
* code indicated by the \c ReplacementRange.
*/
CINDEX_LINKAGE CXString clang_getDiagnosticFixIt(
CXDiagnostic Diagnostic, unsigned FixIt, CXSourceRange *ReplacementRange);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,62 @@
/*===-- clang-c/CXErrorCode.h - C Index Error Codes --------------*- 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 header provides the CXErrorCode enumerators. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXERRORCODE_H
#define LLVM_CLANG_C_CXERRORCODE_H
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* Error codes returned by libclang routines.
*
* Zero (\c CXError_Success) is the only error code indicating success. Other
* error codes, including not yet assigned non-zero values, indicate errors.
*/
enum CXErrorCode {
/**
* No error.
*/
CXError_Success = 0,
/**
* A generic error code, no further details are available.
*
* Errors of this kind can get their own specific error codes in future
* libclang versions.
*/
CXError_Failure = 1,
/**
* libclang crashed while performing the requested operation.
*/
CXError_Crashed = 2,
/**
* The function detected that the arguments violate the function
* contract.
*/
CXError_InvalidArguments = 3,
/**
* An AST deserialization error has occurred.
*/
CXError_ASTReadError = 4
};
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,83 @@
/*===-- clang-c/CXFile.h - C Index File ---------------------------*- 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 header provides the interface to C Index files. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXFILE_H
#define LLVM_CLANG_C_CXFILE_H
#include <time.h>
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_FILES File manipulation routines
*
* @{
*/
/**
* A particular source file that is part of a translation unit.
*/
typedef void *CXFile;
/**
* Retrieve the complete file and path name of the given file.
*/
CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
/**
* Retrieve the last modification time of the given file.
*/
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
/**
* Uniquely identifies a CXFile, that refers to the same underlying file,
* across an indexing session.
*/
typedef struct {
unsigned long long data[3];
} CXFileUniqueID;
/**
* Retrieve the unique ID for the given \c file.
*
* \param file the file to get the ID for.
* \param outID stores the returned CXFileUniqueID.
* \returns If there was a failure getting the unique ID, returns non-zero,
* otherwise returns 0.
*/
CINDEX_LINKAGE int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
/**
* Returns non-zero if the \c file1 and \c file2 point to the same file,
* or they are both NULL.
*/
CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
/**
* Returns the real path name of \c file.
*
* An empty string may be returned. Use \c clang_getFileName() in that case.
*/
CINDEX_LINKAGE CXString clang_File_tryGetRealPathName(CXFile file);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,296 @@
/*===-- clang-c/CXSourceLocation.h - C Index Source Location ------*- 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 header provides the interface to C Index source locations. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXSOURCE_LOCATION_H
#define LLVM_CLANG_C_CXSOURCE_LOCATION_H
#include "clang-c/CXFile.h"
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_LOCATIONS Physical source locations
*
* Clang represents physical source locations in its abstract syntax tree in
* great detail, with file, line, and column information for the majority of
* the tokens parsed in the source code. These data types and functions are
* used to represent source location information, either for a particular
* point in the program or for a range of points in the program, and extract
* specific location information from those data types.
*
* @{
*/
/**
* Identifies a specific source location within a translation
* unit.
*
* Use clang_getExpansionLocation() or clang_getSpellingLocation()
* to map a source location to a particular file, line, and column.
*/
typedef struct {
const void *ptr_data[2];
unsigned int_data;
} CXSourceLocation;
/**
* Identifies a half-open character range in the source code.
*
* Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
* starting and end locations from a source range, respectively.
*/
typedef struct {
const void *ptr_data[2];
unsigned begin_int_data;
unsigned end_int_data;
} CXSourceRange;
/**
* Retrieve a NULL (invalid) source location.
*/
CINDEX_LINKAGE CXSourceLocation clang_getNullLocation(void);
/**
* Determine whether two source locations, which must refer into
* the same translation unit, refer to exactly the same point in the source
* code.
*
* \returns non-zero if the source locations refer to the same location, zero
* if they refer to different locations.
*/
CINDEX_LINKAGE unsigned clang_equalLocations(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
* Determine for two source locations if the first comes
* strictly before the second one in the source code.
*
* \returns non-zero if the first source location comes
* strictly before the second one, zero otherwise.
*/
CINDEX_LINKAGE unsigned clang_isBeforeInTranslationUnit(CXSourceLocation loc1,
CXSourceLocation loc2);
/**
* Returns non-zero if the given source location is in a system header.
*/
CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location);
/**
* Returns non-zero if the given source location is in the main file of
* the corresponding translation unit.
*/
CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location);
/**
* Retrieve a NULL (invalid) source range.
*/
CINDEX_LINKAGE CXSourceRange clang_getNullRange(void);
/**
* Retrieve a source range given the beginning and ending source
* locations.
*/
CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin,
CXSourceLocation end);
/**
* Determine whether two ranges are equivalent.
*
* \returns non-zero if the ranges are the same, zero if they differ.
*/
CINDEX_LINKAGE unsigned clang_equalRanges(CXSourceRange range1,
CXSourceRange range2);
/**
* Returns non-zero if \p range is null.
*/
CINDEX_LINKAGE int clang_Range_isNull(CXSourceRange range);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, retrieves the
* location of the macro expansion.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getExpansionLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line and column represented by the given source
* location, as specified in a # line directive.
*
* Example: given the following source code in a file somefile.c
*
* \code
* #123 "dummy.c" 1
*
* static int func(void)
* {
* return 0;
* }
* \endcode
*
* the location information returned by this function would be
*
* File: dummy.c Line: 124 Column: 12
*
* whereas clang_getExpansionLocation would have returned
*
* File: somefile.c Line: 3 Column: 12
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param filename [out] if non-NULL, will be set to the filename of the
* source location. Note that filenames returned will be for "virtual" files,
* which don't necessarily exist on the machine running clang - e.g. when
* parsing preprocessed output obtained from a different environment. If
* a non-NULL value is passed in, remember to dispose of the returned value
* using \c clang_disposeString() once you've finished with it. For an invalid
* source location, an empty string is returned.
*
* \param line [out] if non-NULL, will be set to the line number of the
* source location. For an invalid source location, zero is returned.
*
* \param column [out] if non-NULL, will be set to the column number of the
* source location. For an invalid source location, zero is returned.
*/
CINDEX_LINKAGE void clang_getPresumedLocation(CXSourceLocation location,
CXString *filename,
unsigned *line, unsigned *column);
/**
* Legacy API to retrieve the file, line, column, and offset represented
* by the given source location.
*
* This interface has been replaced by the newer interface
* #clang_getExpansionLocation(). See that interface's documentation for
* details.
*/
CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro instantiation, return where the
* location was originally spelled in the source file.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column,
unsigned *offset);
/**
* Retrieve the file, line, column, and offset represented by
* the given source location.
*
* If the location refers into a macro expansion, return where the macro was
* expanded or where the macro argument was written, if the location points at
* a macro argument.
*
* \param location the location within a source file that will be decomposed
* into its parts.
*
* \param file [out] if non-NULL, will be set to the file to which the given
* source location points.
*
* \param line [out] if non-NULL, will be set to the line to which the given
* source location points.
*
* \param column [out] if non-NULL, will be set to the column to which the given
* source location points.
*
* \param offset [out] if non-NULL, will be set to the offset into the
* buffer to which the given source location points.
*/
CINDEX_LINKAGE void clang_getFileLocation(CXSourceLocation location,
CXFile *file, unsigned *line,
unsigned *column, unsigned *offset);
/**
* Retrieve a source location representing the first character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
/**
* Retrieve a source location representing the last character within a
* source range.
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/**
* Identifies an array of ranges.
*/
typedef struct {
/** The number of ranges in the \c ranges array. */
unsigned count;
/**
* An array of \c CXSourceRanges.
*/
CXSourceRange *ranges;
} CXSourceRangeList;
/**
* Destroy the given \c CXSourceRangeList.
*/
CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,73 @@
/*===-- clang-c/CXString.h - C Index strings --------------------*- 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 header provides the interface to C Index strings. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_CXSTRING_H
#define LLVM_CLANG_C_CXSTRING_H
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_STRING String manipulation routines
* \ingroup CINDEX
*
* @{
*/
/**
* A character string.
*
* The \c CXString type is used to return strings from the interface when
* the ownership of that string might differ from one call to the next.
* Use \c clang_getCString() to retrieve the string data and, once finished
* with the string data, call \c clang_disposeString() to free the string.
*/
typedef struct {
const void *data;
unsigned private_flags;
} CXString;
typedef struct {
CXString *Strings;
unsigned Count;
} CXStringSet;
/**
* Retrieve the character data associated with the given string.
*
* The returned data is a reference and not owned by the user. This data
* is only valid while the `CXString` is valid. This function is similar
* to `std::string::c_str()`.
*/
CINDEX_LINKAGE const char *clang_getCString(CXString string);
/**
* Free the given string.
*/
CINDEX_LINKAGE void clang_disposeString(CXString string);
/**
* Free the given string set.
*/
CINDEX_LINKAGE void clang_disposeStringSet(CXStringSet *set);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,619 @@
/*==-- clang-c/Documentation.h - Utilities for comment processing -*- 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 header provides a supplementary interface for inspecting *|
|* documentation comments. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_DOCUMENTATION_H
#define LLVM_CLANG_C_DOCUMENTATION_H
#include "clang-c/CXErrorCode.h"
#include "clang-c/ExternC.h"
#include "clang-c/Index.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* \defgroup CINDEX_COMMENT Comment introspection
*
* The routines in this group provide access to information in documentation
* comments. These facilities are distinct from the core and may be subject to
* their own schedule of stability and deprecation.
*
* @{
*/
/**
* A parsed comment.
*/
typedef struct {
const void *ASTNode;
CXTranslationUnit TranslationUnit;
} CXComment;
/**
* Given a cursor that represents a documentable entity (e.g.,
* declaration), return the associated parsed comment as a
* \c CXComment_FullComment AST node.
*/
CINDEX_LINKAGE CXComment clang_Cursor_getParsedComment(CXCursor C);
/**
* Describes the type of the comment AST node (\c CXComment). A comment
* node can be considered block content (e. g., paragraph), inline content
* (plain text) or neither (the root AST node).
*/
enum CXCommentKind {
/**
* Null comment. No AST node is constructed at the requested location
* because there is no text or a syntax error.
*/
CXComment_Null = 0,
/**
* Plain text. Inline content.
*/
CXComment_Text = 1,
/**
* A command with word-like arguments that is considered inline content.
*
* For example: \\c command.
*/
CXComment_InlineCommand = 2,
/**
* HTML start tag with attributes (name-value pairs). Considered
* inline content.
*
* For example:
* \verbatim
* <br> <br /> <a href="http://example.org/">
* \endverbatim
*/
CXComment_HTMLStartTag = 3,
/**
* HTML end tag. Considered inline content.
*
* For example:
* \verbatim
* </a>
* \endverbatim
*/
CXComment_HTMLEndTag = 4,
/**
* A paragraph, contains inline comment. The paragraph itself is
* block content.
*/
CXComment_Paragraph = 5,
/**
* A command that has zero or more word-like arguments (number of
* word-like arguments depends on command name) and a paragraph as an
* argument. Block command is block content.
*
* Paragraph argument is also a child of the block command.
*
* For example: \has 0 word-like arguments and a paragraph argument.
*
* AST nodes of special kinds that parser knows about (e. g., \\param
* command) have their own node kinds.
*/
CXComment_BlockCommand = 6,
/**
* A \\param or \\arg command that describes the function parameter
* (name, passing direction, description).
*
* For example: \\param [in] ParamName description.
*/
CXComment_ParamCommand = 7,
/**
* A \\tparam command that describes a template parameter (name and
* description).
*
* For example: \\tparam T description.
*/
CXComment_TParamCommand = 8,
/**
* A verbatim block command (e. g., preformatted code). Verbatim
* block has an opening and a closing command and contains multiple lines of
* text (\c CXComment_VerbatimBlockLine child nodes).
*
* For example:
* \\verbatim
* aaa
* \\endverbatim
*/
CXComment_VerbatimBlockCommand = 9,
/**
* A line of text that is contained within a
* CXComment_VerbatimBlockCommand node.
*/
CXComment_VerbatimBlockLine = 10,
/**
* A verbatim line command. Verbatim line has an opening command,
* a single line of text (up to the newline after the opening command) and
* has no closing command.
*/
CXComment_VerbatimLine = 11,
/**
* A full comment attached to a declaration, contains block content.
*/
CXComment_FullComment = 12
};
/**
* The most appropriate rendering mode for an inline command, chosen on
* command semantics in Doxygen.
*/
enum CXCommentInlineCommandRenderKind {
/**
* Command argument should be rendered in a normal font.
*/
CXCommentInlineCommandRenderKind_Normal,
/**
* Command argument should be rendered in a bold font.
*/
CXCommentInlineCommandRenderKind_Bold,
/**
* Command argument should be rendered in a monospaced font.
*/
CXCommentInlineCommandRenderKind_Monospaced,
/**
* Command argument should be rendered emphasized (typically italic
* font).
*/
CXCommentInlineCommandRenderKind_Emphasized,
/**
* Command argument should not be rendered (since it only defines an anchor).
*/
CXCommentInlineCommandRenderKind_Anchor
};
/**
* Describes parameter passing direction for \\param or \\arg command.
*/
enum CXCommentParamPassDirection {
/**
* The parameter is an input parameter.
*/
CXCommentParamPassDirection_In,
/**
* The parameter is an output parameter.
*/
CXCommentParamPassDirection_Out,
/**
* The parameter is an input and output parameter.
*/
CXCommentParamPassDirection_InOut
};
/**
* \param Comment AST node of any kind.
*
* \returns the type of the AST node.
*/
CINDEX_LINKAGE enum CXCommentKind clang_Comment_getKind(CXComment Comment);
/**
* \param Comment AST node of any kind.
*
* \returns number of children of the AST node.
*/
CINDEX_LINKAGE unsigned clang_Comment_getNumChildren(CXComment Comment);
/**
* \param Comment AST node of any kind.
*
* \param ChildIdx child index (zero-based).
*
* \returns the specified child of the AST node.
*/
CINDEX_LINKAGE
CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx);
/**
* A \c CXComment_Paragraph node is considered whitespace if it contains
* only \c CXComment_Text nodes that are empty or whitespace.
*
* Other AST nodes (except \c CXComment_Paragraph and \c CXComment_Text) are
* never considered whitespace.
*
* \returns non-zero if \c Comment is whitespace.
*/
CINDEX_LINKAGE unsigned clang_Comment_isWhitespace(CXComment Comment);
/**
* \returns non-zero if \c Comment is inline content and has a newline
* immediately following it in the comment text. Newlines between paragraphs
* do not count.
*/
CINDEX_LINKAGE
unsigned clang_InlineContentComment_hasTrailingNewline(CXComment Comment);
/**
* \param Comment a \c CXComment_Text AST node.
*
* \returns text contained in the AST node.
*/
CINDEX_LINKAGE CXString clang_TextComment_getText(CXComment Comment);
/**
* \param Comment a \c CXComment_InlineCommand AST node.
*
* \returns name of the inline command.
*/
CINDEX_LINKAGE
CXString clang_InlineCommandComment_getCommandName(CXComment Comment);
/**
* \param Comment a \c CXComment_InlineCommand AST node.
*
* \returns the most appropriate rendering mode, chosen on command
* semantics in Doxygen.
*/
CINDEX_LINKAGE enum CXCommentInlineCommandRenderKind
clang_InlineCommandComment_getRenderKind(CXComment Comment);
/**
* \param Comment a \c CXComment_InlineCommand AST node.
*
* \returns number of command arguments.
*/
CINDEX_LINKAGE
unsigned clang_InlineCommandComment_getNumArgs(CXComment Comment);
/**
* \param Comment a \c CXComment_InlineCommand AST node.
*
* \param ArgIdx argument index (zero-based).
*
* \returns text of the specified argument.
*/
CINDEX_LINKAGE
CXString clang_InlineCommandComment_getArgText(CXComment Comment,
unsigned ArgIdx);
/**
* \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
* node.
*
* \returns HTML tag name.
*/
CINDEX_LINKAGE CXString clang_HTMLTagComment_getTagName(CXComment Comment);
/**
* \param Comment a \c CXComment_HTMLStartTag AST node.
*
* \returns non-zero if tag is self-closing (for example, &lt;br /&gt;).
*/
CINDEX_LINKAGE
unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment Comment);
/**
* \param Comment a \c CXComment_HTMLStartTag AST node.
*
* \returns number of attributes (name-value pairs) attached to the start tag.
*/
CINDEX_LINKAGE unsigned clang_HTMLStartTag_getNumAttrs(CXComment Comment);
/**
* \param Comment a \c CXComment_HTMLStartTag AST node.
*
* \param AttrIdx attribute index (zero-based).
*
* \returns name of the specified attribute.
*/
CINDEX_LINKAGE
CXString clang_HTMLStartTag_getAttrName(CXComment Comment, unsigned AttrIdx);
/**
* \param Comment a \c CXComment_HTMLStartTag AST node.
*
* \param AttrIdx attribute index (zero-based).
*
* \returns value of the specified attribute.
*/
CINDEX_LINKAGE
CXString clang_HTMLStartTag_getAttrValue(CXComment Comment, unsigned AttrIdx);
/**
* \param Comment a \c CXComment_BlockCommand AST node.
*
* \returns name of the block command.
*/
CINDEX_LINKAGE
CXString clang_BlockCommandComment_getCommandName(CXComment Comment);
/**
* \param Comment a \c CXComment_BlockCommand AST node.
*
* \returns number of word-like arguments.
*/
CINDEX_LINKAGE
unsigned clang_BlockCommandComment_getNumArgs(CXComment Comment);
/**
* \param Comment a \c CXComment_BlockCommand AST node.
*
* \param ArgIdx argument index (zero-based).
*
* \returns text of the specified word-like argument.
*/
CINDEX_LINKAGE
CXString clang_BlockCommandComment_getArgText(CXComment Comment,
unsigned ArgIdx);
/**
* \param Comment a \c CXComment_BlockCommand or
* \c CXComment_VerbatimBlockCommand AST node.
*
* \returns paragraph argument of the block command.
*/
CINDEX_LINKAGE
CXComment clang_BlockCommandComment_getParagraph(CXComment Comment);
/**
* \param Comment a \c CXComment_ParamCommand AST node.
*
* \returns parameter name.
*/
CINDEX_LINKAGE
CXString clang_ParamCommandComment_getParamName(CXComment Comment);
/**
* \param Comment a \c CXComment_ParamCommand AST node.
*
* \returns non-zero if the parameter that this AST node represents was found
* in the function prototype and \c clang_ParamCommandComment_getParamIndex
* function will return a meaningful value.
*/
CINDEX_LINKAGE
unsigned clang_ParamCommandComment_isParamIndexValid(CXComment Comment);
/**
* \param Comment a \c CXComment_ParamCommand AST node.
*
* \returns zero-based parameter index in function prototype.
*/
CINDEX_LINKAGE
unsigned clang_ParamCommandComment_getParamIndex(CXComment Comment);
/**
* \param Comment a \c CXComment_ParamCommand AST node.
*
* \returns non-zero if parameter passing direction was specified explicitly in
* the comment.
*/
CINDEX_LINKAGE
unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment Comment);
/**
* \param Comment a \c CXComment_ParamCommand AST node.
*
* \returns parameter passing direction.
*/
CINDEX_LINKAGE
enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
CXComment Comment);
/**
* \param Comment a \c CXComment_TParamCommand AST node.
*
* \returns template parameter name.
*/
CINDEX_LINKAGE
CXString clang_TParamCommandComment_getParamName(CXComment Comment);
/**
* \param Comment a \c CXComment_TParamCommand AST node.
*
* \returns non-zero if the parameter that this AST node represents was found
* in the template parameter list and
* \c clang_TParamCommandComment_getDepth and
* \c clang_TParamCommandComment_getIndex functions will return a meaningful
* value.
*/
CINDEX_LINKAGE
unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment);
/**
* \param Comment a \c CXComment_TParamCommand AST node.
*
* \returns zero-based nesting depth of this parameter in the template parameter list.
*
* For example,
* \verbatim
* template<typename C, template<typename T> class TT>
* void test(TT<int> aaa);
* \endverbatim
* for C and TT nesting depth is 0,
* for T nesting depth is 1.
*/
CINDEX_LINKAGE
unsigned clang_TParamCommandComment_getDepth(CXComment Comment);
/**
* \param Comment a \c CXComment_TParamCommand AST node.
*
* \returns zero-based parameter index in the template parameter list at a
* given nesting depth.
*
* For example,
* \verbatim
* template<typename C, template<typename T> class TT>
* void test(TT<int> aaa);
* \endverbatim
* for C and TT nesting depth is 0, so we can ask for index at depth 0:
* at depth 0 C's index is 0, TT's index is 1.
*
* For T nesting depth is 1, so we can ask for index at depth 0 and 1:
* at depth 0 T's index is 1 (same as TT's),
* at depth 1 T's index is 0.
*/
CINDEX_LINKAGE
unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth);
/**
* \param Comment a \c CXComment_VerbatimBlockLine AST node.
*
* \returns text contained in the AST node.
*/
CINDEX_LINKAGE
CXString clang_VerbatimBlockLineComment_getText(CXComment Comment);
/**
* \param Comment a \c CXComment_VerbatimLine AST node.
*
* \returns text contained in the AST node.
*/
CINDEX_LINKAGE CXString clang_VerbatimLineComment_getText(CXComment Comment);
/**
* Convert an HTML tag AST node to string.
*
* \param Comment a \c CXComment_HTMLStartTag or \c CXComment_HTMLEndTag AST
* node.
*
* \returns string containing an HTML tag.
*/
CINDEX_LINKAGE CXString clang_HTMLTagComment_getAsString(CXComment Comment);
/**
* Convert a given full parsed comment to an HTML fragment.
*
* Specific details of HTML layout are subject to change. Don't try to parse
* this HTML back into an AST, use other APIs instead.
*
* Currently the following CSS classes are used:
* \li "para-brief" for \paragraph and equivalent commands;
* \li "para-returns" for \\returns paragraph and equivalent commands;
* \li "word-returns" for the "Returns" word in \\returns paragraph.
*
* Function argument documentation is rendered as a \<dl\> list with arguments
* sorted in function prototype order. CSS classes used:
* \li "param-name-index-NUMBER" for parameter name (\<dt\>);
* \li "param-descr-index-NUMBER" for parameter description (\<dd\>);
* \li "param-name-index-invalid" and "param-descr-index-invalid" are used if
* parameter index is invalid.
*
* Template parameter documentation is rendered as a \<dl\> list with
* parameters sorted in template parameter list order. CSS classes used:
* \li "tparam-name-index-NUMBER" for parameter name (\<dt\>);
* \li "tparam-descr-index-NUMBER" for parameter description (\<dd\>);
* \li "tparam-name-index-other" and "tparam-descr-index-other" are used for
* names inside template template parameters;
* \li "tparam-name-index-invalid" and "tparam-descr-index-invalid" are used if
* parameter position is invalid.
*
* \param Comment a \c CXComment_FullComment AST node.
*
* \returns string containing an HTML fragment.
*/
CINDEX_LINKAGE CXString clang_FullComment_getAsHTML(CXComment Comment);
/**
* Convert a given full parsed comment to an XML document.
*
* A Relax NG schema for the XML can be found in comment-xml-schema.rng file
* inside clang source tree.
*
* \param Comment a \c CXComment_FullComment AST node.
*
* \returns string containing an XML document.
*/
CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment);
/**
* CXAPISet is an opaque type that represents a data structure containing all
* the API information for a given translation unit. This can be used for a
* single symbol symbol graph for a given symbol.
*/
typedef struct CXAPISetImpl *CXAPISet;
/**
* Traverses the translation unit to create a \c CXAPISet.
*
* \param tu is the \c CXTranslationUnit to build the \c CXAPISet for.
*
* \param out_api is a pointer to the output of this function. It is needs to be
* disposed of by calling clang_disposeAPISet.
*
* \returns Error code indicating success or failure of the APISet creation.
*/
CINDEX_LINKAGE enum CXErrorCode clang_createAPISet(CXTranslationUnit tu,
CXAPISet *out_api);
/**
* Dispose of an APISet.
*
* The provided \c CXAPISet can not be used after this function is called.
*/
CINDEX_LINKAGE void clang_disposeAPISet(CXAPISet api);
/**
* Generate a single symbol symbol graph for the given USR. Returns a null
* string if the associated symbol can not be found in the provided \c CXAPISet.
*
* The output contains the symbol graph as well as some additional information
* about related symbols.
*
* \param usr is a string containing the USR of the symbol to generate the
* symbol graph for.
*
* \param api the \c CXAPISet to look for the symbol in.
*
* \returns a string containing the serialized symbol graph representation for
* the symbol being queried or a null string if it can not be found in the
* APISet.
*/
CINDEX_LINKAGE CXString clang_getSymbolGraphForUSR(const char *usr,
CXAPISet api);
/**
* Generate a single symbol symbol graph for the declaration at the given
* cursor. Returns a null string if the AST node for the cursor isn't a
* declaration.
*
* The output contains the symbol graph as well as some additional information
* about related symbols.
*
* \param cursor the declaration for which to generate the single symbol symbol
* graph.
*
* \returns a string containing the serialized symbol graph representation for
* the symbol being queried or a null string if it can not be found in the
* APISet.
*/
CINDEX_LINKAGE CXString clang_getSymbolGraphForCursor(CXCursor cursor);
/**
* @}
*/
LLVM_CLANG_C_EXTERN_C_END
#endif /* CLANG_C_DOCUMENTATION_H */

View File

@ -0,0 +1,39 @@
/*===- clang-c/ExternC.h - Wrapper for 'extern "C"' ---------------*- 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 an 'extern "C"' wrapper. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_EXTERN_C_H
#define LLVM_CLANG_C_EXTERN_C_H
#ifdef __clang__
#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic error \"-Wstrict-prototypes\"")
#define LLVM_CLANG_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop")
#else
#define LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
#define LLVM_CLANG_C_STRICT_PROTOTYPES_END
#endif
#ifdef __cplusplus
#define LLVM_CLANG_C_EXTERN_C_BEGIN \
extern "C" { \
LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
#define LLVM_CLANG_C_EXTERN_C_END \
LLVM_CLANG_C_STRICT_PROTOTYPES_END \
}
#else
#define LLVM_CLANG_C_EXTERN_C_BEGIN LLVM_CLANG_C_STRICT_PROTOTYPES_BEGIN
#define LLVM_CLANG_C_EXTERN_C_END LLVM_CLANG_C_STRICT_PROTOTYPES_END
#endif
#endif

View File

@ -0,0 +1,33 @@
/*===-- clang-c/FatalErrorHandler.h - Fatal Error 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 *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
#define LLVM_CLANG_C_FATAL_ERROR_HANDLER_H
#include "clang-c/ExternC.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/**
* Installs error handler that prints error message to stderr and calls abort().
* Replaces currently installed error handler (if any).
*/
CINDEX_LINKAGE void clang_install_aborting_llvm_fatal_error_handler(void);
/**
* Removes currently installed error handler (if any).
* If no error handler is intalled, the default strategy is to print error
* message to stderr and call exit(1).
*/
CINDEX_LINKAGE void clang_uninstall_llvm_fatal_error_handler(void);
LLVM_CLANG_C_EXTERN_C_END
#endif

6977
llvm/include/clang-c/Index.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
/*===-- clang-c/Platform.h - C Index platform decls -------------*- 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 header provides platform specific macros (dllimport, deprecated, ...) *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_CLANG_C_PLATFORM_H
#define LLVM_CLANG_C_PLATFORM_H
#include "clang-c/ExternC.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
/* Windows DLL import/export. */
#ifndef CINDEX_NO_EXPORTS
#define CINDEX_EXPORTS
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
#ifdef CINDEX_EXPORTS
#ifdef _CINDEX_LIB_
#define CINDEX_LINKAGE __declspec(dllexport)
#else
#define CINDEX_LINKAGE __declspec(dllimport)
#endif
#endif
#elif defined(CINDEX_EXPORTS) && defined(__GNUC__)
#define CINDEX_LINKAGE __attribute__((visibility("default")))
#endif
#ifndef CINDEX_LINKAGE
#define CINDEX_LINKAGE
#endif
#ifdef __GNUC__
#define CINDEX_DEPRECATED __attribute__((deprecated))
#else
#ifdef _MSC_VER
#define CINDEX_DEPRECATED __declspec(deprecated)
#else
#define CINDEX_DEPRECATED
#endif
#endif
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,63 @@
/*===-- clang-c/Rewrite.h - C CXRewriter --------------------------*- 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_C_REWRITE_H
#define LLVM_CLANG_C_REWRITE_H
#include "clang-c/CXString.h"
#include "clang-c/ExternC.h"
#include "clang-c/Index.h"
#include "clang-c/Platform.h"
LLVM_CLANG_C_EXTERN_C_BEGIN
typedef void *CXRewriter;
/**
* Create CXRewriter.
*/
CINDEX_LINKAGE CXRewriter clang_CXRewriter_create(CXTranslationUnit TU);
/**
* Insert the specified string at the specified location in the original buffer.
*/
CINDEX_LINKAGE void clang_CXRewriter_insertTextBefore(CXRewriter Rew, CXSourceLocation Loc,
const char *Insert);
/**
* Replace the specified range of characters in the input with the specified
* replacement.
*/
CINDEX_LINKAGE void clang_CXRewriter_replaceText(CXRewriter Rew, CXSourceRange ToBeReplaced,
const char *Replacement);
/**
* Remove the specified range.
*/
CINDEX_LINKAGE void clang_CXRewriter_removeText(CXRewriter Rew, CXSourceRange ToBeRemoved);
/**
* Save all changed files to disk.
* Returns 1 if any files were not saved successfully, returns 0 otherwise.
*/
CINDEX_LINKAGE int clang_CXRewriter_overwriteChangedFiles(CXRewriter Rew);
/**
* Write out rewritten version of the main file to stdout.
*/
CINDEX_LINKAGE void clang_CXRewriter_writeMainFileToStdOut(CXRewriter Rew);
/**
* Free the given CXRewriter.
*/
CINDEX_LINKAGE void clang_CXRewriter_dispose(CXRewriter Rew);
LLVM_CLANG_C_EXTERN_C_END
#endif

View File

@ -0,0 +1,184 @@
//===--- APINotesManager.h - Manage API Notes Files -------------*- 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_APINOTES_APINOTESMANAGER_H
#define LLVM_CLANG_APINOTES_APINOTESMANAGER_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/VersionTuple.h"
#include <memory>
#include <string>
namespace clang {
class DirectoryEntry;
class FileEntry;
class LangOptions;
class Module;
class SourceManager;
namespace api_notes {
class APINotesReader;
/// The API notes manager helps find API notes associated with declarations.
///
/// API notes are externally-provided annotations for declarations that can
/// introduce new attributes (covering availability, nullability of
/// parameters/results, and so on) for specific declarations without directly
/// modifying the headers that contain those declarations.
///
/// The API notes manager is responsible for finding and loading the
/// external API notes files that correspond to a given header. Its primary
/// operation is \c findAPINotes(), which finds the API notes reader that
/// provides information about the declarations at that location.
class APINotesManager {
using ReaderEntry = llvm::PointerUnion<DirectoryEntryRef, APINotesReader *>;
SourceManager &SM;
/// Whether to implicitly search for API notes files based on the
/// source file from which an entity was declared.
bool ImplicitAPINotes;
/// Whether to apply all APINotes as optionally-applied versioned
/// entities. This means that when building a Clang module,
/// we capture every note on a given decl wrapped in a SwiftVersionedAttr
/// (with an empty version field for unversioned notes), and have the
/// client apply the relevant version's notes.
bool VersionIndependentSwift;
/// The Swift version to use when interpreting versioned API notes.
llvm::VersionTuple SwiftVersion;
enum ReaderKind : unsigned { Public = 0, Private = 1 };
/// API notes readers for the current module.
///
/// There can be up to two of these, one for public headers and one
/// for private headers.
///
/// Not using std::unique_ptr to store these, since the reader pointers are
/// also stored in llvm::PointerUnion below.
APINotesReader *CurrentModuleReaders[2] = {nullptr, nullptr};
/// A mapping from header file directories to the API notes reader for
/// that directory, or a redirection to another directory entry that may
/// have more information, or NULL to indicate that there is no API notes
/// reader for this directory.
llvm::DenseMap<const DirectoryEntry *, ReaderEntry> Readers;
/// Load the API notes associated with the given file, whether it is
/// the binary or source form of API notes.
///
/// \returns the API notes reader for this file, or null if there is
/// a failure.
std::unique_ptr<APINotesReader> loadAPINotes(FileEntryRef APINotesFile);
/// Load the API notes associated with the given buffer, whether it is
/// the binary or source form of API notes.
///
/// \returns the API notes reader for this file, or null if there is
/// a failure.
std::unique_ptr<APINotesReader> loadAPINotes(StringRef Buffer);
/// Load the given API notes file for the given header directory.
///
/// \param HeaderDir The directory at which we
///
/// \returns true if an error occurred.
bool loadAPINotes(const DirectoryEntry *HeaderDir, FileEntryRef APINotesFile);
/// Look for API notes in the given directory.
///
/// This might find either a binary or source API notes.
OptionalFileEntryRef findAPINotesFile(DirectoryEntryRef Directory,
StringRef FileName,
bool WantPublic = true);
/// Attempt to load API notes for the given framework. A framework will have
/// the API notes file under either {FrameworkPath}/APINotes,
/// {FrameworkPath}/Headers or {FrameworkPath}/PrivateHeaders, while a
/// library will have the API notes simply in its directory.
///
/// \param FrameworkPath The path to the framework.
/// \param Public Whether to load the public API notes. Otherwise, attempt
/// to load the private API notes.
///
/// \returns the header directory entry (e.g., for Headers or PrivateHeaders)
/// for which the API notes were successfully loaded, or NULL if API notes
/// could not be loaded for any reason.
OptionalDirectoryEntryRef loadFrameworkAPINotes(llvm::StringRef FrameworkPath,
llvm::StringRef FrameworkName,
bool Public);
public:
APINotesManager(SourceManager &SM, const LangOptions &LangOpts);
~APINotesManager();
/// Set the Swift version to use when filtering API notes.
void setSwiftVersion(llvm::VersionTuple Version) {
this->SwiftVersion = Version;
}
/// Load the API notes for the current module.
///
/// \param M The current module.
/// \param LookInModule Whether to look inside the module itself.
/// \param SearchPaths The paths in which we should search for API notes
/// for the current module.
///
/// \returns true if API notes were successfully loaded, \c false otherwise.
bool loadCurrentModuleAPINotes(Module *M, bool LookInModule,
ArrayRef<std::string> SearchPaths);
/// Get FileEntry for the APINotes of the module that is currently being
/// compiled.
///
/// \param M The current module.
/// \param LookInModule Whether to look inside the directory of the current
/// module.
/// \param SearchPaths The paths in which we should search for API
/// notes for the current module.
///
/// \returns a vector of FileEntry where APINotes files are.
llvm::SmallVector<FileEntryRef, 2>
getCurrentModuleAPINotes(Module *M, bool LookInModule,
ArrayRef<std::string> SearchPaths);
/// Load Compiled API notes for current module.
///
/// \param Buffers Array of compiled API notes.
///
/// \returns true if API notes were successfully loaded, \c false otherwise.
bool loadCurrentModuleAPINotesFromBuffer(ArrayRef<StringRef> Buffers);
/// Retrieve the set of API notes readers for the current module.
ArrayRef<APINotesReader *> getCurrentModuleReaders() const {
bool HasPublic = CurrentModuleReaders[ReaderKind::Public];
bool HasPrivate = CurrentModuleReaders[ReaderKind::Private];
assert((!HasPrivate || HasPublic) && "private module requires public module");
if (!HasPrivate && !HasPublic)
return {};
return ArrayRef(CurrentModuleReaders).slice(0, HasPrivate ? 2 : 1);
}
/// Find the API notes readers that correspond to the given source location.
llvm::SmallVector<APINotesReader *, 2> findAPINotes(SourceLocation Loc);
bool captureVersionIndependentSwift() { return VersionIndependentSwift; }
};
} // end namespace api_notes
} // end namespace clang
#endif

View File

@ -0,0 +1,34 @@
//===--- APINotesOptions.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_APINOTES_APINOTESOPTIONS_H
#define LLVM_CLANG_APINOTES_APINOTESOPTIONS_H
#include "llvm/Support/VersionTuple.h"
#include <string>
#include <vector>
namespace clang {
/// Tracks various options which control how API notes are found and handled.
class APINotesOptions {
public:
/// The Swift version which should be used for API notes.
llvm::VersionTuple SwiftVersion;
/// The set of search paths where we API notes can be found for particular
/// modules.
///
/// The API notes in this directory are stored as <ModuleName>.apinotes, and
/// are only applied when building the module <ModuleName>.
std::vector<std::string> ModuleSearchPaths;
};
} // namespace clang
#endif // LLVM_CLANG_APINOTES_APINOTESOPTIONS_H

View File

@ -0,0 +1,228 @@
//===--- APINotesReader.h - API Notes Reader --------------------*- 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 \c APINotesReader class that reads source API notes
// data providing additional information about source code as a separate input,
// such as the non-nil/nilable annotations for method parameters.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_APINOTES_READER_H
#define LLVM_CLANG_APINOTES_READER_H
#include "clang/APINotes/Types.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/VersionTuple.h"
#include <memory>
namespace clang {
namespace api_notes {
/// A class that reads API notes data from a binary file that was written by
/// the \c APINotesWriter.
class APINotesReader {
class Implementation;
std::unique_ptr<Implementation> Implementation;
APINotesReader(llvm::MemoryBuffer *InputBuffer,
llvm::VersionTuple SwiftVersion, bool &Failed);
public:
/// Create a new API notes reader from the given member buffer, which
/// contains the contents of a binary API notes file.
///
/// \returns the new API notes reader, or null if an error occurred.
static std::unique_ptr<APINotesReader>
Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
llvm::VersionTuple SwiftVersion);
~APINotesReader();
APINotesReader(const APINotesReader &) = delete;
APINotesReader &operator=(const APINotesReader &) = delete;
/// Captures the completed versioned information for a particular part of
/// API notes, including both unversioned API notes and each versioned API
/// note for that particular entity.
template <typename T> class VersionedInfo {
/// The complete set of results.
llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> Results;
/// The index of the result that is the "selected" set based on the desired
/// Swift version, or null if nothing matched.
std::optional<unsigned> Selected;
public:
/// Form an empty set of versioned information.
VersionedInfo(std::nullopt_t) : Selected(std::nullopt) {}
/// Form a versioned info set given the desired version and a set of
/// results.
VersionedInfo(
llvm::VersionTuple Version,
llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> Results);
/// Retrieve the selected index in the result set.
std::optional<unsigned> getSelected() const { return Selected; }
/// Return the number of versioned results we know about.
unsigned size() const { return Results.size(); }
/// Access all versioned results.
const std::pair<llvm::VersionTuple, T> *begin() const {
assert(!Results.empty());
return Results.begin();
}
const std::pair<llvm::VersionTuple, T> *end() const {
return Results.end();
}
/// Access a specific versioned result.
const std::pair<llvm::VersionTuple, T> &operator[](unsigned index) const {
assert(index < Results.size());
return Results[index];
}
};
/// Look for the context ID of the given Objective-C class.
///
/// \param Name The name of the class we're looking for.
///
/// \returns The ID, if known.
std::optional<ContextID> lookupObjCClassID(llvm::StringRef Name);
/// Look for information regarding the given Objective-C class.
///
/// \param Name The name of the class we're looking for.
///
/// \returns The information about the class, if known.
VersionedInfo<ContextInfo> lookupObjCClassInfo(llvm::StringRef Name);
/// Look for the context ID of the given Objective-C protocol.
///
/// \param Name The name of the protocol we're looking for.
///
/// \returns The ID of the protocol, if known.
std::optional<ContextID> lookupObjCProtocolID(llvm::StringRef Name);
/// Look for information regarding the given Objective-C protocol.
///
/// \param Name The name of the protocol we're looking for.
///
/// \returns The information about the protocol, if known.
VersionedInfo<ContextInfo> lookupObjCProtocolInfo(llvm::StringRef Name);
/// Look for information regarding the given Objective-C property in
/// the given context.
///
/// \param CtxID The ID that references the context we are looking for.
/// \param Name The name of the property we're looking for.
/// \param IsInstance Whether we are looking for an instance property (vs.
/// a class property).
///
/// \returns Information about the property, if known.
VersionedInfo<ObjCPropertyInfo>
lookupObjCProperty(ContextID CtxID, llvm::StringRef Name, bool IsInstance);
/// Look for information regarding the given Objective-C method in
/// the given context.
///
/// \param CtxID The ID that references the context we are looking for.
/// \param Selector The selector naming the method we're looking for.
/// \param IsInstanceMethod Whether we are looking for an instance method.
///
/// \returns Information about the method, if known.
VersionedInfo<ObjCMethodInfo> lookupObjCMethod(ContextID CtxID,
ObjCSelectorRef Selector,
bool IsInstanceMethod);
/// Look for information regarding the given field of a C struct.
///
/// \param Name The name of the field.
///
/// \returns information about the field, if known.
VersionedInfo<FieldInfo> lookupField(ContextID CtxID, llvm::StringRef Name);
/// Look for information regarding the given C++ method in the given C++ tag
/// context.
///
/// \param CtxID The ID that references the parent context, i.e. a C++ tag.
/// \param Name The name of the C++ method we're looking for.
///
/// \returns Information about the method, if known.
VersionedInfo<CXXMethodInfo> lookupCXXMethod(ContextID CtxID,
llvm::StringRef Name);
/// Look for information regarding the given global variable.
///
/// \param Name The name of the global variable.
///
/// \returns information about the global variable, if known.
VersionedInfo<GlobalVariableInfo>
lookupGlobalVariable(llvm::StringRef Name,
std::optional<Context> Ctx = std::nullopt);
/// Look for information regarding the given global function.
///
/// \param Name The name of the global function.
///
/// \returns information about the global function, if known.
VersionedInfo<GlobalFunctionInfo>
lookupGlobalFunction(llvm::StringRef Name,
std::optional<Context> Ctx = std::nullopt);
/// Look for information regarding the given enumerator.
///
/// \param Name The name of the enumerator.
///
/// \returns information about the enumerator, if known.
VersionedInfo<EnumConstantInfo> lookupEnumConstant(llvm::StringRef Name);
/// Look for the context ID of the given C++ tag.
///
/// \param Name The name of the tag we're looking for.
/// \param ParentCtx The context in which this tag is declared, e.g. a C++
/// namespace.
///
/// \returns The ID, if known.
std::optional<ContextID>
lookupTagID(llvm::StringRef Name,
std::optional<Context> ParentCtx = std::nullopt);
/// Look for information regarding the given tag
/// (struct/union/enum/C++ class).
///
/// \param Name The name of the tag.
///
/// \returns information about the tag, if known.
VersionedInfo<TagInfo> lookupTag(llvm::StringRef Name,
std::optional<Context> Ctx = std::nullopt);
/// Look for information regarding the given typedef.
///
/// \param Name The name of the typedef.
///
/// \returns information about the typedef, if known.
VersionedInfo<TypedefInfo>
lookupTypedef(llvm::StringRef Name,
std::optional<Context> Ctx = std::nullopt);
/// Look for the context ID of the given C++ namespace.
///
/// \param Name The name of the class we're looking for.
///
/// \returns The ID, if known.
std::optional<ContextID>
lookupNamespaceID(llvm::StringRef Name,
std::optional<ContextID> ParentNamespaceID = std::nullopt);
};
} // end namespace api_notes
} // end namespace clang
#endif // LLVM_CLANG_APINOTES_READER_H

View File

@ -0,0 +1,137 @@
//===-- APINotesWriter.h - API Notes Writer ---------------------*- 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 \c APINotesWriter class that writes out source
// API notes data providing additional information about source code as
// a separate input, such as the non-nil/nilable annotations for
// method parameters.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_APINOTES_WRITER_H
#define LLVM_CLANG_APINOTES_WRITER_H
#include "clang/APINotes/Types.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
namespace clang {
class FileEntry;
namespace api_notes {
/// A class that writes API notes data to a binary representation that can be
/// read by the \c APINotesReader.
class APINotesWriter {
class Implementation;
std::unique_ptr<Implementation> Implementation;
public:
/// Create a new API notes writer with the given module name and
/// (optional) source file.
APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF);
~APINotesWriter();
APINotesWriter(const APINotesWriter &) = delete;
APINotesWriter &operator=(const APINotesWriter &) = delete;
void writeToStream(llvm::raw_ostream &OS);
/// Add information about a specific Objective-C class or protocol or a C++
/// namespace.
///
/// \param Name The name of this class/protocol/namespace.
/// \param Kind Whether this is a class, a protocol, or a namespace.
/// \param Info Information about this class/protocol/namespace.
///
/// \returns the ID of the class, protocol, or namespace, which can be used to
/// add properties and methods to the class/protocol/namespace.
ContextID addContext(std::optional<ContextID> ParentCtxID,
llvm::StringRef Name, ContextKind Kind,
const ContextInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a specific Objective-C property.
///
/// \param CtxID The context in which this property resides.
/// \param Name The name of this property.
/// \param Info Information about this property.
void addObjCProperty(ContextID CtxID, llvm::StringRef Name,
bool IsInstanceProperty, const ObjCPropertyInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a specific Objective-C method.
///
/// \param CtxID The context in which this method resides.
/// \param Selector The selector that names this method.
/// \param IsInstanceMethod Whether this method is an instance method
/// (vs. a class method).
/// \param Info Information about this method.
void addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
bool IsInstanceMethod, const ObjCMethodInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a specific C++ method.
///
/// \param CtxID The context in which this method resides, i.e. a C++ tag.
/// \param Name The name of the method.
/// \param Info Information about this method.
void addCXXMethod(ContextID CtxID, llvm::StringRef Name,
const CXXMethodInfo &Info, llvm::VersionTuple SwiftVersion);
/// Add information about a specific C record field.
///
/// \param CtxID The context in which this field resides, i.e. a C/C++ tag.
/// \param Name The name of the field.
/// \param Info Information about this field.
void addField(ContextID CtxID, llvm::StringRef Name, const FieldInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a global variable.
///
/// \param Name The name of this global variable.
/// \param Info Information about this global variable.
void addGlobalVariable(std::optional<Context> Ctx, llvm::StringRef Name,
const GlobalVariableInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a global function.
///
/// \param Name The name of this global function.
/// \param Info Information about this global function.
void addGlobalFunction(std::optional<Context> Ctx, llvm::StringRef Name,
const GlobalFunctionInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about an enumerator.
///
/// \param Name The name of this enumerator.
/// \param Info Information about this enumerator.
void addEnumConstant(llvm::StringRef Name, const EnumConstantInfo &Info,
llvm::VersionTuple SwiftVersion);
/// Add information about a tag (struct/union/enum/C++ class).
///
/// \param Name The name of this tag.
/// \param Info Information about this tag.
void addTag(std::optional<Context> Ctx, llvm::StringRef Name,
const TagInfo &Info, llvm::VersionTuple SwiftVersion);
/// Add information about a typedef.
///
/// \param Name The name of this typedef.
/// \param Info Information about this typedef.
void addTypedef(std::optional<Context> Ctx, llvm::StringRef Name,
const TypedefInfo &Info, llvm::VersionTuple SwiftVersion);
};
} // namespace api_notes
} // namespace clang
#endif // LLVM_CLANG_APINOTES_WRITER_H

View File

@ -0,0 +1,35 @@
//===-- APINotesYAMLCompiler.h - API Notes YAML Format Reader ---*- 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_APINOTES_APINOTESYAMLCOMPILER_H
#define LLVM_CLANG_APINOTES_APINOTESYAMLCOMPILER_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
class FileEntry;
} // namespace clang
namespace clang {
namespace api_notes {
/// Parses the APINotes YAML content and writes the representation back to the
/// specified stream. This provides a means of testing the YAML processing of
/// the APINotes format.
bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS);
/// Converts API notes from YAML format to binary format.
bool compileAPINotes(llvm::StringRef YAMLInput, const FileEntry *SourceFile,
llvm::raw_ostream &OS,
llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
void *DiagHandlerCtxt = nullptr);
} // namespace api_notes
} // namespace clang
#endif

View File

@ -0,0 +1,935 @@
//===-- Types.h - API Notes Data Types --------------------------*- 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_APINOTES_TYPES_H
#define LLVM_CLANG_APINOTES_TYPES_H
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <climits>
#include <optional>
#include <vector>
namespace llvm {
class raw_ostream;
} // namespace llvm
namespace clang {
namespace api_notes {
enum class RetainCountConventionKind {
None,
CFReturnsRetained,
CFReturnsNotRetained,
NSReturnsRetained,
NSReturnsNotRetained,
};
/// The payload for an enum_extensibility attribute. This is a tri-state rather
/// than just a boolean because the presence of the attribute indicates
/// auditing.
enum class EnumExtensibilityKind {
None,
Open,
Closed,
};
/// The kind of a swift_wrapper/swift_newtype.
enum class SwiftNewTypeKind {
None,
Struct,
Enum,
};
enum class SwiftSafetyKind { Unspecified, Safe, Unsafe, None };
/// Describes API notes data for any entity.
///
/// This is used as the base of all API notes.
class CommonEntityInfo {
public:
/// Message to use when this entity is unavailable.
std::string UnavailableMsg;
/// Whether this entity is marked unavailable.
LLVM_PREFERRED_TYPE(bool)
unsigned Unavailable : 1;
/// Whether this entity is marked unavailable in Swift.
LLVM_PREFERRED_TYPE(bool)
unsigned UnavailableInSwift : 1;
private:
/// Whether SwiftPrivate was specified.
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftPrivateSpecified : 1;
/// Whether this entity is considered "private" to a Swift overlay.
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftPrivate : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftSafetyAudited : 1;
LLVM_PREFERRED_TYPE(SwiftSafetyKind)
unsigned SwiftSafety : 2;
public:
/// Swift name of this entity.
std::string SwiftName;
CommonEntityInfo()
: Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0),
SwiftPrivate(0), SwiftSafetyAudited(0), SwiftSafety(0) {}
std::optional<bool> isSwiftPrivate() const {
return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate)
: std::nullopt;
}
void setSwiftPrivate(std::optional<bool> Private) {
SwiftPrivateSpecified = Private.has_value();
SwiftPrivate = Private.value_or(0);
}
std::optional<SwiftSafetyKind> getSwiftSafety() const {
return SwiftSafetyAudited ? std::optional<SwiftSafetyKind>(
static_cast<SwiftSafetyKind>(SwiftSafety))
: std::nullopt;
}
void setSwiftSafety(SwiftSafetyKind Safety) {
SwiftSafetyAudited = 1;
SwiftSafety = static_cast<unsigned>(Safety);
}
friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &);
CommonEntityInfo &operator|=(const CommonEntityInfo &RHS) {
// Merge unavailability.
if (RHS.Unavailable) {
Unavailable = true;
if (UnavailableMsg.empty())
UnavailableMsg = RHS.UnavailableMsg;
}
if (RHS.UnavailableInSwift) {
UnavailableInSwift = true;
if (UnavailableMsg.empty())
UnavailableMsg = RHS.UnavailableMsg;
}
if (!SwiftPrivateSpecified)
setSwiftPrivate(RHS.isSwiftPrivate());
if (!SwiftSafetyAudited && RHS.SwiftSafetyAudited)
setSwiftSafety(*RHS.getSwiftSafety());
if (SwiftName.empty())
SwiftName = RHS.SwiftName;
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const CommonEntityInfo &LHS,
const CommonEntityInfo &RHS) {
return LHS.UnavailableMsg == RHS.UnavailableMsg &&
LHS.Unavailable == RHS.Unavailable &&
LHS.UnavailableInSwift == RHS.UnavailableInSwift &&
LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified &&
LHS.SwiftPrivate == RHS.SwiftPrivate &&
LHS.SwiftSafetyAudited == RHS.SwiftSafetyAudited &&
LHS.SwiftSafety == RHS.SwiftSafety && LHS.SwiftName == RHS.SwiftName;
}
inline bool operator!=(const CommonEntityInfo &LHS,
const CommonEntityInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes for types.
class CommonTypeInfo : public CommonEntityInfo {
/// The Swift type to which a given type is bridged.
///
/// Reflects the swift_bridge attribute.
std::optional<std::string> SwiftBridge;
/// The NS error domain for this type.
std::optional<std::string> NSErrorDomain;
/// The Swift protocol that this type should be automatically conformed to.
std::optional<std::string> SwiftConformance;
public:
CommonTypeInfo() {}
const std::optional<std::string> &getSwiftBridge() const {
return SwiftBridge;
}
void setSwiftBridge(std::optional<std::string> SwiftType) {
SwiftBridge = SwiftType;
}
const std::optional<std::string> &getNSErrorDomain() const {
return NSErrorDomain;
}
void setNSErrorDomain(const std::optional<std::string> &Domain) {
NSErrorDomain = Domain;
}
void setNSErrorDomain(const std::optional<llvm::StringRef> &Domain) {
NSErrorDomain = Domain ? std::optional<std::string>(std::string(*Domain))
: std::nullopt;
}
std::optional<std::string> getSwiftConformance() const {
return SwiftConformance;
}
void setSwiftConformance(std::optional<std::string> conformance) {
SwiftConformance = conformance;
}
friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &);
CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) {
// Merge inherited info.
static_cast<CommonEntityInfo &>(*this) |= RHS;
if (!SwiftBridge)
setSwiftBridge(RHS.getSwiftBridge());
if (!NSErrorDomain)
setNSErrorDomain(RHS.getNSErrorDomain());
if (SwiftConformance)
setSwiftConformance(RHS.getSwiftConformance());
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
LHS.SwiftBridge == RHS.SwiftBridge &&
LHS.NSErrorDomain == RHS.NSErrorDomain &&
LHS.SwiftConformance == RHS.SwiftConformance;
}
inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for an Objective-C class or protocol or a C++
/// namespace.
class ContextInfo : public CommonTypeInfo {
/// Whether this class has a default nullability.
LLVM_PREFERRED_TYPE(bool)
unsigned HasDefaultNullability : 1;
/// The default nullability.
LLVM_PREFERRED_TYPE(NullabilityKind)
unsigned DefaultNullability : 2;
/// Whether this class has designated initializers recorded.
LLVM_PREFERRED_TYPE(bool)
unsigned HasDesignatedInits : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftImportAsNonGenericSpecified : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftImportAsNonGeneric : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftObjCMembersSpecified : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftObjCMembers : 1;
public:
ContextInfo()
: HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0),
SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false),
SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {}
/// Determine the default nullability for properties and methods of this
/// class.
///
/// Returns the default nullability, if implied, or std::nullopt if there is
/// none.
std::optional<NullabilityKind> getDefaultNullability() const {
return HasDefaultNullability
? std::optional<NullabilityKind>(
static_cast<NullabilityKind>(DefaultNullability))
: std::nullopt;
}
/// Set the default nullability for properties and methods of this class.
void setDefaultNullability(NullabilityKind Kind) {
HasDefaultNullability = true;
DefaultNullability = static_cast<unsigned>(Kind);
}
bool hasDesignatedInits() const { return HasDesignatedInits; }
void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; }
std::optional<bool> getSwiftImportAsNonGeneric() const {
return SwiftImportAsNonGenericSpecified
? std::optional<bool>(SwiftImportAsNonGeneric)
: std::nullopt;
}
void setSwiftImportAsNonGeneric(std::optional<bool> Value) {
SwiftImportAsNonGenericSpecified = Value.has_value();
SwiftImportAsNonGeneric = Value.value_or(false);
}
std::optional<bool> getSwiftObjCMembers() const {
return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers)
: std::nullopt;
}
void setSwiftObjCMembers(std::optional<bool> Value) {
SwiftObjCMembersSpecified = Value.has_value();
SwiftObjCMembers = Value.value_or(false);
}
friend bool operator==(const ContextInfo &, const ContextInfo &);
ContextInfo &operator|=(const ContextInfo &RHS) {
// Merge inherited info.
static_cast<CommonTypeInfo &>(*this) |= RHS;
// Merge nullability.
if (!getDefaultNullability())
if (auto Nullability = RHS.getDefaultNullability())
setDefaultNullability(*Nullability);
if (!SwiftImportAsNonGenericSpecified)
setSwiftImportAsNonGeneric(RHS.getSwiftImportAsNonGeneric());
if (!SwiftObjCMembersSpecified)
setSwiftObjCMembers(RHS.getSwiftObjCMembers());
HasDesignatedInits |= RHS.HasDesignatedInits;
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};
inline bool operator==(const ContextInfo &LHS, const ContextInfo &RHS) {
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
LHS.getDefaultNullability() == RHS.getDefaultNullability() &&
LHS.HasDesignatedInits == RHS.HasDesignatedInits &&
LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() &&
LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers();
}
inline bool operator!=(const ContextInfo &LHS, const ContextInfo &RHS) {
return !(LHS == RHS);
}
/// API notes for a variable/property.
class VariableInfo : public CommonEntityInfo {
/// Whether this property has been audited for nullability.
LLVM_PREFERRED_TYPE(bool)
unsigned NullabilityAudited : 1;
/// The kind of nullability for this property. Only valid if the nullability
/// has been audited.
LLVM_PREFERRED_TYPE(NullabilityKind)
unsigned Nullable : 2;
/// The C type of the variable, as a string.
std::string Type;
public:
VariableInfo() : NullabilityAudited(false), Nullable(0) {}
std::optional<NullabilityKind> getNullability() const {
return NullabilityAudited ? std::optional<NullabilityKind>(
static_cast<NullabilityKind>(Nullable))
: std::nullopt;
}
void setNullabilityAudited(NullabilityKind kind) {
NullabilityAudited = true;
Nullable = static_cast<unsigned>(kind);
}
const std::string &getType() const { return Type; }
void setType(const std::string &type) { Type = type; }
friend bool operator==(const VariableInfo &, const VariableInfo &);
VariableInfo &operator|=(const VariableInfo &RHS) {
static_cast<CommonEntityInfo &>(*this) |= RHS;
if (!NullabilityAudited && RHS.NullabilityAudited)
setNullabilityAudited(*RHS.getNullability());
if (Type.empty())
Type = RHS.Type;
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const VariableInfo &LHS, const VariableInfo &RHS) {
return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
LHS.NullabilityAudited == RHS.NullabilityAudited &&
LHS.Nullable == RHS.Nullable && LHS.Type == RHS.Type;
}
inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for an Objective-C property.
class ObjCPropertyInfo : public VariableInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftImportAsAccessorsSpecified : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftImportAsAccessors : 1;
public:
ObjCPropertyInfo()
: SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {}
std::optional<bool> getSwiftImportAsAccessors() const {
return SwiftImportAsAccessorsSpecified
? std::optional<bool>(SwiftImportAsAccessors)
: std::nullopt;
}
void setSwiftImportAsAccessors(std::optional<bool> Value) {
SwiftImportAsAccessorsSpecified = Value.has_value();
SwiftImportAsAccessors = Value.value_or(false);
}
friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &);
/// Merge class-wide information into the given property.
ObjCPropertyInfo &operator|=(const ContextInfo &RHS) {
static_cast<CommonEntityInfo &>(*this) |= RHS;
// Merge nullability.
if (!getNullability())
if (auto Nullable = RHS.getDefaultNullability())
setNullabilityAudited(*Nullable);
return *this;
}
ObjCPropertyInfo &operator|=(const ObjCPropertyInfo &RHS) {
static_cast<VariableInfo &>(*this) |= RHS;
if (!SwiftImportAsAccessorsSpecified)
setSwiftImportAsAccessors(RHS.getSwiftImportAsAccessors());
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const ObjCPropertyInfo &LHS,
const ObjCPropertyInfo &RHS) {
return static_cast<const VariableInfo &>(LHS) == RHS &&
LHS.getSwiftImportAsAccessors() == RHS.getSwiftImportAsAccessors();
}
inline bool operator!=(const ObjCPropertyInfo &LHS,
const ObjCPropertyInfo &RHS) {
return !(LHS == RHS);
}
/// Describes a function or method parameter.
class ParamInfo : public VariableInfo {
/// Whether noescape was specified.
LLVM_PREFERRED_TYPE(bool)
unsigned NoEscapeSpecified : 1;
/// Whether the this parameter has the 'noescape' attribute.
LLVM_PREFERRED_TYPE(bool)
unsigned NoEscape : 1;
/// Whether lifetimebound was specified.
LLVM_PREFERRED_TYPE(bool)
unsigned LifetimeboundSpecified : 1;
/// Whether the this parameter has the 'lifetimebound' attribute.
LLVM_PREFERRED_TYPE(bool)
unsigned Lifetimebound : 1;
/// A biased RetainCountConventionKind, where 0 means "unspecified".
///
/// Only relevant for out-parameters.
unsigned RawRetainCountConvention : 3;
public:
ParamInfo()
: NoEscapeSpecified(false), NoEscape(false),
LifetimeboundSpecified(false), Lifetimebound(false),
RawRetainCountConvention() {}
std::optional<bool> isNoEscape() const {
return NoEscapeSpecified ? std::optional<bool>(NoEscape) : std::nullopt;
}
void setNoEscape(std::optional<bool> Value) {
NoEscapeSpecified = Value.has_value();
NoEscape = Value.value_or(false);
}
std::optional<bool> isLifetimebound() const {
return LifetimeboundSpecified ? std::optional<bool>(Lifetimebound)
: std::nullopt;
}
void setLifetimebound(std::optional<bool> Value) {
LifetimeboundSpecified = Value.has_value();
Lifetimebound = Value.value_or(false);
}
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
if (!RawRetainCountConvention)
return std::nullopt;
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
}
void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
ParamInfo &operator|=(const ParamInfo &RHS) {
static_cast<VariableInfo &>(*this) |= RHS;
if (!NoEscapeSpecified && RHS.NoEscapeSpecified) {
NoEscapeSpecified = true;
NoEscape = RHS.NoEscape;
}
if (!LifetimeboundSpecified && RHS.LifetimeboundSpecified) {
LifetimeboundSpecified = true;
Lifetimebound = RHS.Lifetimebound;
}
if (!RawRetainCountConvention)
RawRetainCountConvention = RHS.RawRetainCountConvention;
return *this;
}
friend bool operator==(const ParamInfo &, const ParamInfo &);
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) {
return static_cast<const VariableInfo &>(LHS) == RHS &&
LHS.NoEscapeSpecified == RHS.NoEscapeSpecified &&
LHS.NoEscape == RHS.NoEscape &&
LHS.LifetimeboundSpecified == RHS.LifetimeboundSpecified &&
LHS.Lifetimebound == RHS.Lifetimebound &&
LHS.RawRetainCountConvention == RHS.RawRetainCountConvention;
}
inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) {
return !(LHS == RHS);
}
/// API notes for a function or method.
class FunctionInfo : public CommonEntityInfo {
private:
static constexpr const uint64_t NullabilityKindMask = 0x3;
static constexpr const unsigned NullabilityKindSize = 2;
static constexpr const unsigned ReturnInfoIndex = 0;
public:
// If yes, we consider all types to be non-nullable unless otherwise noted.
// If this flag is not set, the pointer types are considered to have
// unknown nullability.
/// Whether the signature has been audited with respect to nullability.
LLVM_PREFERRED_TYPE(bool)
unsigned NullabilityAudited : 1;
/// Number of types whose nullability is encoded with the NullabilityPayload.
unsigned NumAdjustedNullable : 8;
/// A biased RetainCountConventionKind, where 0 means "unspecified".
unsigned RawRetainCountConvention : 3;
// NullabilityKindSize bits are used to encode the nullability. The info
// about the return type is stored at position 0, followed by the nullability
// of the parameters.
/// Stores the nullability of the return type and the parameters.
uint64_t NullabilityPayload = 0;
/// The result type of this function, as a C type.
std::string ResultType;
/// Ownership convention for return value
std::string SwiftReturnOwnership;
/// The function parameters.
std::vector<ParamInfo> Params;
FunctionInfo()
: NullabilityAudited(false), NumAdjustedNullable(0),
RawRetainCountConvention() {}
static unsigned getMaxNullabilityIndex() {
return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize);
}
void addTypeInfo(unsigned index, NullabilityKind kind) {
assert(index <= getMaxNullabilityIndex());
assert(static_cast<unsigned>(kind) < NullabilityKindMask);
NullabilityAudited = true;
if (NumAdjustedNullable < index + 1)
NumAdjustedNullable = index + 1;
// Mask the bits.
NullabilityPayload &=
~(NullabilityKindMask << (index * NullabilityKindSize));
// Set the value.
unsigned kindValue = (static_cast<unsigned>(kind))
<< (index * NullabilityKindSize);
NullabilityPayload |= kindValue;
}
/// Adds the return type info.
void addReturnTypeInfo(NullabilityKind kind) {
addTypeInfo(ReturnInfoIndex, kind);
}
/// Adds the parameter type info.
void addParamTypeInfo(unsigned index, NullabilityKind kind) {
addTypeInfo(index + 1, kind);
}
NullabilityKind getParamTypeInfo(unsigned index) const {
return getTypeInfo(index + 1);
}
NullabilityKind getReturnTypeInfo() const { return getTypeInfo(0); }
std::optional<RetainCountConventionKind> getRetainCountConvention() const {
if (!RawRetainCountConvention)
return std::nullopt;
return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1);
}
void
setRetainCountConvention(std::optional<RetainCountConventionKind> Value) {
RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0;
assert(getRetainCountConvention() == Value && "bitfield too small");
}
friend bool operator==(const FunctionInfo &, const FunctionInfo &);
private:
NullabilityKind getTypeInfo(unsigned index) const {
assert(NullabilityAudited &&
"Checking the type adjustment on non-audited method.");
// If we don't have info about this parameter, return the default.
if (index > NumAdjustedNullable)
return NullabilityKind::NonNull;
auto nullability = NullabilityPayload >> (index * NullabilityKindSize);
return static_cast<NullabilityKind>(nullability & NullabilityKindMask);
}
public:
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
return static_cast<const CommonEntityInfo &>(LHS) == RHS &&
LHS.NullabilityAudited == RHS.NullabilityAudited &&
LHS.NumAdjustedNullable == RHS.NumAdjustedNullable &&
LHS.NullabilityPayload == RHS.NullabilityPayload &&
LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params &&
LHS.RawRetainCountConvention == RHS.RawRetainCountConvention &&
LHS.SwiftReturnOwnership == RHS.SwiftReturnOwnership;
}
inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for an Objective-C method.
class ObjCMethodInfo : public FunctionInfo {
public:
/// Whether this is a designated initializer of its class.
LLVM_PREFERRED_TYPE(bool)
unsigned DesignatedInit : 1;
/// Whether this is a required initializer.
LLVM_PREFERRED_TYPE(bool)
unsigned RequiredInit : 1;
std::optional<ParamInfo> Self;
ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {}
friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &);
ObjCMethodInfo &operator|=(const ContextInfo &RHS) {
// Merge Nullability.
if (!NullabilityAudited) {
if (auto Nullable = RHS.getDefaultNullability()) {
NullabilityAudited = true;
addTypeInfo(0, *Nullable);
}
}
return *this;
}
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};
inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
return static_cast<const FunctionInfo &>(LHS) == RHS &&
LHS.DesignatedInit == RHS.DesignatedInit &&
LHS.RequiredInit == RHS.RequiredInit && LHS.Self == RHS.Self;
}
inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for a global variable.
class GlobalVariableInfo : public VariableInfo {
public:
GlobalVariableInfo() {}
};
/// Describes API notes data for a global function.
class GlobalFunctionInfo : public FunctionInfo {
public:
GlobalFunctionInfo() {}
};
/// Describes API notes data for a C/C++ record field.
class FieldInfo : public VariableInfo {
public:
FieldInfo() {}
};
/// Describes API notes data for a C++ method.
class CXXMethodInfo : public FunctionInfo {
public:
CXXMethodInfo() {}
std::optional<ParamInfo> This;
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};
inline bool operator==(const CXXMethodInfo &LHS, const CXXMethodInfo &RHS) {
return static_cast<const FunctionInfo &>(LHS) == RHS && LHS.This == RHS.This;
}
inline bool operator!=(const CXXMethodInfo &LHS, const CXXMethodInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for an enumerator.
class EnumConstantInfo : public CommonEntityInfo {
public:
EnumConstantInfo() {}
};
/// Describes API notes data for a tag.
class TagInfo : public CommonTypeInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned HasFlagEnum : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned IsFlagEnum : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftCopyableSpecified : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftCopyable : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftEscapableSpecified : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned SwiftEscapable : 1;
public:
std::optional<std::string> SwiftImportAs;
std::optional<std::string> SwiftRetainOp;
std::optional<std::string> SwiftReleaseOp;
std::optional<std::string> SwiftDestroyOp;
std::optional<std::string> SwiftDefaultOwnership;
std::optional<EnumExtensibilityKind> EnumExtensibility;
TagInfo()
: HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
SwiftCopyable(false), SwiftEscapableSpecified(false),
SwiftEscapable(false) {}
std::optional<bool> isFlagEnum() const {
if (HasFlagEnum)
return IsFlagEnum;
return std::nullopt;
}
void setFlagEnum(std::optional<bool> Value) {
HasFlagEnum = Value.has_value();
IsFlagEnum = Value.value_or(false);
}
std::optional<bool> isSwiftCopyable() const {
return SwiftCopyableSpecified ? std::optional<bool>(SwiftCopyable)
: std::nullopt;
}
void setSwiftCopyable(std::optional<bool> Value) {
SwiftCopyableSpecified = Value.has_value();
SwiftCopyable = Value.value_or(false);
}
std::optional<bool> isSwiftEscapable() const {
return SwiftEscapableSpecified ? std::optional<bool>(SwiftEscapable)
: std::nullopt;
}
void setSwiftEscapable(std::optional<bool> Value) {
SwiftEscapableSpecified = Value.has_value();
SwiftEscapable = Value.value_or(false);
}
TagInfo &operator|=(const TagInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS;
if (!SwiftImportAs)
SwiftImportAs = RHS.SwiftImportAs;
if (!SwiftRetainOp)
SwiftRetainOp = RHS.SwiftRetainOp;
if (!SwiftReleaseOp)
SwiftReleaseOp = RHS.SwiftReleaseOp;
if (!SwiftDestroyOp)
SwiftDestroyOp = RHS.SwiftDestroyOp;
if (!SwiftDefaultOwnership)
SwiftDefaultOwnership = RHS.SwiftDefaultOwnership;
if (!HasFlagEnum)
setFlagEnum(RHS.isFlagEnum());
if (!EnumExtensibility)
EnumExtensibility = RHS.EnumExtensibility;
if (!SwiftCopyableSpecified)
setSwiftCopyable(RHS.isSwiftCopyable());
if (!SwiftEscapableSpecified)
setSwiftEscapable(RHS.isSwiftEscapable());
return *this;
}
friend bool operator==(const TagInfo &, const TagInfo &);
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS);
};
inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
LHS.SwiftImportAs == RHS.SwiftImportAs &&
LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
LHS.SwiftDestroyOp == RHS.SwiftDestroyOp &&
LHS.SwiftDefaultOwnership == RHS.SwiftDefaultOwnership &&
LHS.isFlagEnum() == RHS.isFlagEnum() &&
LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
LHS.isSwiftEscapable() == RHS.isSwiftEscapable() &&
LHS.EnumExtensibility == RHS.EnumExtensibility;
}
inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) {
return !(LHS == RHS);
}
/// Describes API notes data for a typedef.
class TypedefInfo : public CommonTypeInfo {
public:
std::optional<SwiftNewTypeKind> SwiftWrapper;
TypedefInfo() {}
TypedefInfo &operator|=(const TypedefInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS;
if (!SwiftWrapper)
SwiftWrapper = RHS.SwiftWrapper;
return *this;
}
friend bool operator==(const TypedefInfo &, const TypedefInfo &);
LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const;
};
inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) {
return static_cast<const CommonTypeInfo &>(LHS) == RHS &&
LHS.SwiftWrapper == RHS.SwiftWrapper;
}
inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) {
return !(LHS == RHS);
}
/// The file extension used for the source representation of API notes.
static const constexpr char SOURCE_APINOTES_EXTENSION[] = "apinotes";
/// Opaque context ID used to refer to an Objective-C class or protocol or a C++
/// namespace.
class ContextID {
public:
unsigned Value;
explicit ContextID(unsigned value) : Value(value) {}
};
enum class ContextKind : uint8_t {
ObjCClass = 0,
ObjCProtocol = 1,
Namespace = 2,
Tag = 3,
};
struct Context {
ContextID id;
ContextKind kind;
Context(ContextID id, ContextKind kind) : id(id), kind(kind) {}
};
/// A temporary reference to an Objective-C selector, suitable for
/// referencing selector data on the stack.
///
/// Instances of this struct do not store references to any of the
/// data they contain; it is up to the user to ensure that the data
/// referenced by the identifier list persists.
struct ObjCSelectorRef {
unsigned NumArgs;
llvm::ArrayRef<llvm::StringRef> Identifiers;
};
} // namespace api_notes
} // namespace clang
#endif

View File

@ -0,0 +1,71 @@
//===--- APNumericStorage.h - Store APInt/APFloat in ASTContext -*- 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_AST_APNUMERICSTORAGE_H
#define LLVM_CLANG_AST_APNUMERICSTORAGE_H
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
namespace clang {
class ASTContext;
/// Used by IntegerLiteral/FloatingLiteral/EnumConstantDecl to store the
/// numeric without leaking memory.
///
/// For large floats/integers, APFloat/APInt will allocate memory from the heap
/// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator
/// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with
/// the APFloat/APInt values will never get freed. APNumericStorage uses
/// ASTContext's allocator for memory allocation.
class APNumericStorage {
union {
uint64_t VAL; ///< Used to store the <= 64 bits integer value.
uint64_t *pVal; ///< Used to store the >64 bits integer value.
};
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
unsigned BitWidth;
APNumericStorage() : VAL(0), BitWidth(0) {}
llvm::APInt getIntValue() const {
unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
if (NumWords > 1)
return llvm::APInt(BitWidth, llvm::ArrayRef(pVal, NumWords));
return llvm::APInt(BitWidth, VAL);
}
void setIntValue(const ASTContext &C, const llvm::APInt &Val);
};
class APIntStorage : private APNumericStorage {
public:
llvm::APInt getValue() const { return getIntValue(); }
unsigned getBitWidth() const { return BitWidth; }
void setValue(const ASTContext &C, const llvm::APInt &Val) {
setIntValue(C, Val);
}
};
class APFloatStorage : private APNumericStorage {
public:
llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const {
return llvm::APFloat(Semantics, getIntValue());
}
void setValue(const ASTContext &C, const llvm::APFloat &Val) {
setIntValue(C, Val.bitcastToAPInt());
}
};
} // end namespace clang
#endif // LLVM_CLANG_AST_APNUMERICSTORAGE_H

View File

@ -0,0 +1,780 @@
//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APFixedPoint.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/AlignOf.h"
namespace clang {
namespace serialization {
template <typename T> class BasicReaderBase;
} // end namespace serialization
class AddrLabelExpr;
class ASTContext;
class CharUnits;
class CXXRecordDecl;
class Decl;
class DiagnosticBuilder;
class Expr;
class FieldDecl;
struct PrintingPolicy;
class Type;
class ValueDecl;
class QualType;
/// Symbolic representation of typeid(T) for some type T.
class TypeInfoLValue {
const Type *T;
public:
TypeInfoLValue() : T() {}
explicit TypeInfoLValue(const Type *T);
const Type *getType() const { return T; }
explicit operator bool() const { return T; }
const void *getOpaqueValue() const { return T; }
static TypeInfoLValue getFromOpaqueValue(const void *Value) {
TypeInfoLValue V;
V.T = reinterpret_cast<const Type*>(Value);
return V;
}
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const;
};
/// Symbolic representation of a dynamic allocation.
class DynamicAllocLValue {
unsigned Index;
public:
DynamicAllocLValue() : Index(0) {}
explicit DynamicAllocLValue(unsigned Index) : Index(Index + 1) {}
unsigned getIndex() { return Index - 1; }
explicit operator bool() const { return Index != 0; }
const void *getOpaqueValue() const {
return reinterpret_cast<const void *>(static_cast<uintptr_t>(Index)
<< NumLowBitsAvailable);
}
static DynamicAllocLValue getFromOpaqueValue(const void *Value) {
DynamicAllocLValue V;
V.Index = reinterpret_cast<uintptr_t>(Value) >> NumLowBitsAvailable;
return V;
}
static unsigned getMaxIndex() {
return (std::numeric_limits<unsigned>::max() >> NumLowBitsAvailable) - 1;
}
static constexpr int NumLowBitsAvailable = 3;
};
}
namespace llvm {
template<> struct PointerLikeTypeTraits<clang::TypeInfoLValue> {
static const void *getAsVoidPointer(clang::TypeInfoLValue V) {
return V.getOpaqueValue();
}
static clang::TypeInfoLValue getFromVoidPointer(const void *P) {
return clang::TypeInfoLValue::getFromOpaqueValue(P);
}
// Validated by static_assert in APValue.cpp; hardcoded to avoid needing
// to include Type.h.
static constexpr int NumLowBitsAvailable = 3;
};
template<> struct PointerLikeTypeTraits<clang::DynamicAllocLValue> {
static const void *getAsVoidPointer(clang::DynamicAllocLValue V) {
return V.getOpaqueValue();
}
static clang::DynamicAllocLValue getFromVoidPointer(const void *P) {
return clang::DynamicAllocLValue::getFromOpaqueValue(P);
}
static constexpr int NumLowBitsAvailable =
clang::DynamicAllocLValue::NumLowBitsAvailable;
};
}
namespace clang {
/// APValue - This class implements a discriminated union of [uninitialized]
/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
/// [Vector: N * APValue], [Array: N * APValue]
class APValue {
typedef llvm::APFixedPoint APFixedPoint;
typedef llvm::APSInt APSInt;
typedef llvm::APFloat APFloat;
public:
enum ValueKind {
/// There is no such object (it's outside its lifetime).
None,
/// This object has an indeterminate value (C++ [basic.indet]).
Indeterminate,
Int,
Float,
FixedPoint,
ComplexInt,
ComplexFloat,
LValue,
Vector,
Array,
Struct,
Union,
MemberPointer,
AddrLabelDiff
};
class alignas(uint64_t) LValueBase {
typedef llvm::PointerUnion<const ValueDecl *, const Expr *, TypeInfoLValue,
DynamicAllocLValue>
PtrTy;
public:
LValueBase() : Local{} {}
LValueBase(const ValueDecl *P, unsigned I = 0, unsigned V = 0);
LValueBase(const Expr *P, unsigned I = 0, unsigned V = 0);
static LValueBase getDynamicAlloc(DynamicAllocLValue LV, QualType Type);
static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo);
void Profile(llvm::FoldingSetNodeID &ID) const;
template <class T> bool is() const { return isa<T>(Ptr); }
template <class T> T get() const { return cast<T>(Ptr); }
template <class T> T dyn_cast() const {
return dyn_cast_if_present<T>(Ptr);
}
void *getOpaqueValue() const;
bool isNull() const;
explicit operator bool() const;
unsigned getCallIndex() const;
unsigned getVersion() const;
QualType getTypeInfoType() const;
QualType getDynamicAllocType() const;
QualType getType() const;
friend bool operator==(const LValueBase &LHS, const LValueBase &RHS);
friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) {
return !(LHS == RHS);
}
friend llvm::hash_code hash_value(const LValueBase &Base);
friend struct llvm::DenseMapInfo<LValueBase>;
private:
PtrTy Ptr;
struct LocalState {
unsigned CallIndex, Version;
};
union {
LocalState Local;
/// The type std::type_info, if this is a TypeInfoLValue.
void *TypeInfoType;
/// The QualType, if this is a DynamicAllocLValue.
void *DynamicAllocType;
};
};
/// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we
/// mean a virtual or non-virtual base class subobject.
typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
/// A non-discriminated union of a base, field, or array index.
class LValuePathEntry {
static_assert(sizeof(uintptr_t) <= sizeof(uint64_t),
"pointer doesn't fit in 64 bits?");
uint64_t Value;
public:
LValuePathEntry() : Value() {}
LValuePathEntry(BaseOrMemberType BaseOrMember);
static LValuePathEntry ArrayIndex(uint64_t Index) {
LValuePathEntry Result;
Result.Value = Index;
return Result;
}
BaseOrMemberType getAsBaseOrMember() const {
return BaseOrMemberType::getFromOpaqueValue(
reinterpret_cast<void *>(Value));
}
uint64_t getAsArrayIndex() const { return Value; }
void Profile(llvm::FoldingSetNodeID &ID) const;
friend bool operator==(LValuePathEntry A, LValuePathEntry B) {
return A.Value == B.Value;
}
friend bool operator!=(LValuePathEntry A, LValuePathEntry B) {
return A.Value != B.Value;
}
friend llvm::hash_code hash_value(LValuePathEntry A) {
return llvm::hash_value(A.Value);
}
};
class LValuePathSerializationHelper {
const void *Ty;
public:
ArrayRef<LValuePathEntry> Path;
LValuePathSerializationHelper(ArrayRef<LValuePathEntry>, QualType);
QualType getType();
};
struct NoLValuePath {};
struct UninitArray {};
struct UninitStruct {};
struct ConstexprUnknown {};
template <typename Impl> friend class clang::serialization::BasicReaderBase;
friend class ASTImporter;
friend class ASTNodeImporter;
private:
ValueKind Kind;
bool AllowConstexprUnknown : 1;
struct ComplexAPSInt {
APSInt Real, Imag;
ComplexAPSInt() : Real(1), Imag(1) {}
};
struct ComplexAPFloat {
APFloat Real, Imag;
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
struct LV;
struct Vec {
APValue *Elts = nullptr;
unsigned NumElts = 0;
Vec() = default;
Vec(const Vec &) = delete;
Vec &operator=(const Vec &) = delete;
~Vec() { delete[] Elts; }
};
struct Arr {
APValue *Elts;
unsigned NumElts, ArrSize;
Arr(unsigned NumElts, unsigned ArrSize);
Arr(const Arr &) = delete;
Arr &operator=(const Arr &) = delete;
~Arr();
};
struct StructData {
APValue *Elts;
unsigned NumBases;
unsigned NumFields;
StructData(unsigned NumBases, unsigned NumFields);
StructData(const StructData &) = delete;
StructData &operator=(const StructData &) = delete;
~StructData();
};
struct UnionData {
const FieldDecl *Field;
APValue *Value;
UnionData();
UnionData(const UnionData &) = delete;
UnionData &operator=(const UnionData &) = delete;
~UnionData();
};
struct AddrLabelDiffData {
const AddrLabelExpr* LHSExpr;
const AddrLabelExpr* RHSExpr;
};
struct MemberPointerData;
// We ensure elsewhere that Data is big enough for LV and MemberPointerData.
typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
ComplexAPFloat, Vec, Arr, StructData,
UnionData, AddrLabelDiffData> DataType;
static const size_t DataSize = sizeof(DataType);
DataType Data;
public:
bool allowConstexprUnknown() const { return AllowConstexprUnknown; }
void setConstexprUnknown(bool IsConstexprUnknown = true) {
AllowConstexprUnknown = IsConstexprUnknown;
}
/// Creates an empty APValue of type None.
APValue() : Kind(None), AllowConstexprUnknown(false) {}
/// Creates an integer APValue holding the given value.
explicit APValue(APSInt I) : Kind(None), AllowConstexprUnknown(false) {
MakeInt(); setInt(std::move(I));
}
/// Creates a float APValue holding the given value.
explicit APValue(APFloat F) : Kind(None), AllowConstexprUnknown(false) {
MakeFloat(); setFloat(std::move(F));
}
/// Creates a fixed-point APValue holding the given value.
explicit APValue(APFixedPoint FX) : Kind(None), AllowConstexprUnknown(false) {
MakeFixedPoint(std::move(FX));
}
/// Creates a vector APValue with \p N elements. The elements
/// are read from \p E.
explicit APValue(const APValue *E, unsigned N)
: Kind(None), AllowConstexprUnknown(false) {
MakeVector(); setVector(E, N);
}
/// Creates an integer complex APValue with the given real and imaginary
/// values.
APValue(APSInt R, APSInt I) : Kind(None), AllowConstexprUnknown(false) {
MakeComplexInt(); setComplexInt(std::move(R), std::move(I));
}
/// Creates a float complex APValue with the given real and imaginary values.
APValue(APFloat R, APFloat I) : Kind(None), AllowConstexprUnknown(false) {
MakeComplexFloat(); setComplexFloat(std::move(R), std::move(I));
}
APValue(const APValue &RHS);
APValue(APValue &&RHS);
/// Creates an lvalue APValue without an lvalue path.
/// \param Base The base of the lvalue.
/// \param Offset The offset of the lvalue.
/// \param IsNullPtr Whether this lvalue is a null pointer.
APValue(LValueBase Base, const CharUnits &Offset, NoLValuePath,
bool IsNullPtr = false)
: Kind(None), AllowConstexprUnknown(false) {
MakeLValue();
setLValue(Base, Offset, NoLValuePath{}, IsNullPtr);
}
/// Creates an lvalue APValue with an lvalue path.
/// \param Base The base of the lvalue.
/// \param Offset The offset of the lvalue.
/// \param Path The lvalue path.
/// \param OnePastTheEnd Whether this lvalue is one-past-the-end of the
/// subobject it points to.
/// \param IsNullPtr Whether this lvalue is a null pointer.
APValue(LValueBase Base, const CharUnits &Offset,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
bool IsNullPtr = false)
: Kind(None), AllowConstexprUnknown(false) {
MakeLValue();
setLValue(Base, Offset, Path, OnePastTheEnd, IsNullPtr);
}
/// Creates a constexpr unknown lvalue APValue.
/// \param Base The base of the lvalue.
/// \param Offset The offset of the lvalue.
/// \param IsNullPtr Whether this lvalue is a null pointer.
APValue(LValueBase Base, const CharUnits &Offset, ConstexprUnknown,
bool IsNullPtr = false)
: Kind(None), AllowConstexprUnknown(true) {
MakeLValue();
setLValue(Base, Offset, NoLValuePath{}, IsNullPtr);
}
/// Creates a new array APValue.
/// \param UninitArray Marker. Pass an empty UninitArray.
/// \param InitElts Number of elements you're going to initialize in the
/// array.
/// \param Size Full size of the array.
APValue(UninitArray, unsigned InitElts, unsigned Size)
: Kind(None), AllowConstexprUnknown(false) {
MakeArray(InitElts, Size);
}
/// Creates a new struct APValue.
/// \param UninitStruct Marker. Pass an empty UninitStruct.
/// \param NumBases Number of bases.
/// \param NumMembers Number of members.
APValue(UninitStruct, unsigned NumBases, unsigned NumMembers)
: Kind(None), AllowConstexprUnknown(false) {
MakeStruct(NumBases, NumMembers);
}
/// Creates a new union APValue.
/// \param ActiveDecl The FieldDecl of the active union member.
/// \param ActiveValue The value of the active union member.
explicit APValue(const FieldDecl *ActiveDecl,
const APValue &ActiveValue = APValue())
: Kind(None), AllowConstexprUnknown(false) {
MakeUnion();
setUnion(ActiveDecl, ActiveValue);
}
/// Creates a new member pointer APValue.
/// \param Member Declaration of the member
/// \param IsDerivedMember Whether member is a derived one.
/// \param Path The path of the member.
APValue(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl *> Path)
: Kind(None), AllowConstexprUnknown(false) {
MakeMemberPointer(Member, IsDerivedMember, Path);
}
/// Creates a new address label diff APValue.
/// \param LHSExpr The left-hand side of the difference.
/// \param RHSExpr The right-hand side of the difference.
APValue(const AddrLabelExpr *LHSExpr, const AddrLabelExpr *RHSExpr)
: Kind(None), AllowConstexprUnknown(false) {
MakeAddrLabelDiff(); setAddrLabelDiff(LHSExpr, RHSExpr);
}
static APValue IndeterminateValue() {
APValue Result;
Result.Kind = Indeterminate;
return Result;
}
APValue &operator=(const APValue &RHS);
APValue &operator=(APValue &&RHS);
~APValue() {
if (Kind != None && Kind != Indeterminate)
DestroyDataAndMakeUninit();
}
/// Returns whether the object performed allocations.
///
/// If APValues are constructed via placement new, \c needsCleanup()
/// indicates whether the destructor must be called in order to correctly
/// free all allocated memory.
bool needsCleanup() const;
/// Swaps the contents of this and the given APValue.
void swap(APValue &RHS);
/// profile this value. There is no guarantee that values of different
/// types will not produce the same profiled value, so the type should
/// typically also be profiled if it's not implied by the context.
void Profile(llvm::FoldingSetNodeID &ID) const;
ValueKind getKind() const { return Kind; }
bool isAbsent() const { return Kind == None; }
bool isIndeterminate() const { return Kind == Indeterminate; }
bool hasValue() const { return Kind != None && Kind != Indeterminate; }
bool isInt() const { return Kind == Int; }
bool isFloat() const { return Kind == Float; }
bool isFixedPoint() const { return Kind == FixedPoint; }
bool isComplexInt() const { return Kind == ComplexInt; }
bool isComplexFloat() const { return Kind == ComplexFloat; }
bool isLValue() const { return Kind == LValue; }
bool isVector() const { return Kind == Vector; }
bool isArray() const { return Kind == Array; }
bool isStruct() const { return Kind == Struct; }
bool isUnion() const { return Kind == Union; }
bool isMemberPointer() const { return Kind == MemberPointer; }
bool isAddrLabelDiff() const { return Kind == AddrLabelDiff; }
void dump() const;
void dump(raw_ostream &OS, const ASTContext &Context) const;
void printPretty(raw_ostream &OS, const ASTContext &Ctx, QualType Ty) const;
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy, QualType Ty,
const ASTContext *Ctx = nullptr) const;
std::string getAsString(const ASTContext &Ctx, QualType Ty) const;
APSInt &getInt() {
assert(isInt() && "Invalid accessor");
return *(APSInt *)(char *)&Data;
}
const APSInt &getInt() const {
return const_cast<APValue*>(this)->getInt();
}
/// Try to convert this value to an integral constant. This works if it's an
/// integer, null pointer, or offset from a null pointer. Returns true on
/// success.
bool toIntegralConstant(APSInt &Result, QualType SrcTy,
const ASTContext &Ctx) const;
APFloat &getFloat() {
assert(isFloat() && "Invalid accessor");
return *(APFloat *)(char *)&Data;
}
const APFloat &getFloat() const {
return const_cast<APValue*>(this)->getFloat();
}
APFixedPoint &getFixedPoint() {
assert(isFixedPoint() && "Invalid accessor");
return *(APFixedPoint *)(char *)&Data;
}
const APFixedPoint &getFixedPoint() const {
return const_cast<APValue *>(this)->getFixedPoint();
}
APSInt &getComplexIntReal() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt *)(char *)&Data)->Real;
}
const APSInt &getComplexIntReal() const {
return const_cast<APValue*>(this)->getComplexIntReal();
}
APSInt &getComplexIntImag() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt *)(char *)&Data)->Imag;
}
const APSInt &getComplexIntImag() const {
return const_cast<APValue*>(this)->getComplexIntImag();
}
APFloat &getComplexFloatReal() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat *)(char *)&Data)->Real;
}
const APFloat &getComplexFloatReal() const {
return const_cast<APValue*>(this)->getComplexFloatReal();
}
APFloat &getComplexFloatImag() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat *)(char *)&Data)->Imag;
}
const APFloat &getComplexFloatImag() const {
return const_cast<APValue*>(this)->getComplexFloatImag();
}
const LValueBase getLValueBase() const;
CharUnits &getLValueOffset();
const CharUnits &getLValueOffset() const {
return const_cast<APValue*>(this)->getLValueOffset();
}
bool isLValueOnePastTheEnd() const;
bool hasLValuePath() const;
ArrayRef<LValuePathEntry> getLValuePath() const;
unsigned getLValueCallIndex() const;
unsigned getLValueVersion() const;
bool isNullPointer() const;
APValue &getVectorElt(unsigned I) {
assert(isVector() && "Invalid accessor");
assert(I < getVectorLength() && "Index out of range");
return ((Vec *)(char *)&Data)->Elts[I];
}
const APValue &getVectorElt(unsigned I) const {
return const_cast<APValue*>(this)->getVectorElt(I);
}
unsigned getVectorLength() const {
assert(isVector() && "Invalid accessor");
return ((const Vec *)(const void *)&Data)->NumElts;
}
APValue &getArrayInitializedElt(unsigned I) {
assert(isArray() && "Invalid accessor");
assert(I < getArrayInitializedElts() && "Index out of range");
return ((Arr *)(char *)&Data)->Elts[I];
}
const APValue &getArrayInitializedElt(unsigned I) const {
return const_cast<APValue*>(this)->getArrayInitializedElt(I);
}
bool hasArrayFiller() const {
return getArrayInitializedElts() != getArraySize();
}
APValue &getArrayFiller() {
assert(isArray() && "Invalid accessor");
assert(hasArrayFiller() && "No array filler");
return ((Arr *)(char *)&Data)->Elts[getArrayInitializedElts()];
}
const APValue &getArrayFiller() const {
return const_cast<APValue*>(this)->getArrayFiller();
}
unsigned getArrayInitializedElts() const {
assert(isArray() && "Invalid accessor");
return ((const Arr *)(const void *)&Data)->NumElts;
}
unsigned getArraySize() const {
assert(isArray() && "Invalid accessor");
return ((const Arr *)(const void *)&Data)->ArrSize;
}
unsigned getStructNumBases() const {
assert(isStruct() && "Invalid accessor");
return ((const StructData *)(const char *)&Data)->NumBases;
}
unsigned getStructNumFields() const {
assert(isStruct() && "Invalid accessor");
return ((const StructData *)(const char *)&Data)->NumFields;
}
APValue &getStructBase(unsigned i) {
assert(isStruct() && "Invalid accessor");
assert(i < getStructNumBases() && "base class index OOB");
return ((StructData *)(char *)&Data)->Elts[i];
}
APValue &getStructField(unsigned i) {
assert(isStruct() && "Invalid accessor");
assert(i < getStructNumFields() && "field index OOB");
return ((StructData *)(char *)&Data)->Elts[getStructNumBases() + i];
}
const APValue &getStructBase(unsigned i) const {
return const_cast<APValue*>(this)->getStructBase(i);
}
const APValue &getStructField(unsigned i) const {
return const_cast<APValue*>(this)->getStructField(i);
}
const FieldDecl *getUnionField() const {
assert(isUnion() && "Invalid accessor");
return ((const UnionData *)(const char *)&Data)->Field;
}
APValue &getUnionValue() {
assert(isUnion() && "Invalid accessor");
return *((UnionData *)(char *)&Data)->Value;
}
const APValue &getUnionValue() const {
return const_cast<APValue*>(this)->getUnionValue();
}
const ValueDecl *getMemberPointerDecl() const;
bool isMemberPointerToDerivedMember() const;
ArrayRef<const CXXRecordDecl*> getMemberPointerPath() const;
const AddrLabelExpr* getAddrLabelDiffLHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
return ((const AddrLabelDiffData *)(const char *)&Data)->LHSExpr;
}
const AddrLabelExpr* getAddrLabelDiffRHS() const {
assert(isAddrLabelDiff() && "Invalid accessor");
return ((const AddrLabelDiffData *)(const char *)&Data)->RHSExpr;
}
void setInt(APSInt I) {
assert(isInt() && "Invalid accessor");
*(APSInt *)(char *)&Data = std::move(I);
}
void setFloat(APFloat F) {
assert(isFloat() && "Invalid accessor");
*(APFloat *)(char *)&Data = std::move(F);
}
void setFixedPoint(APFixedPoint FX) {
assert(isFixedPoint() && "Invalid accessor");
*(APFixedPoint *)(char *)&Data = std::move(FX);
}
void setVector(const APValue *E, unsigned N) {
MutableArrayRef<APValue> InternalElts = setVectorUninit(N);
for (unsigned i = 0; i != N; ++i)
InternalElts[i] = E[i];
}
void setComplexInt(APSInt R, APSInt I) {
assert(R.getBitWidth() == I.getBitWidth() &&
"Invalid complex int (type mismatch).");
assert(isComplexInt() && "Invalid accessor");
((ComplexAPSInt *)(char *)&Data)->Real = std::move(R);
((ComplexAPSInt *)(char *)&Data)->Imag = std::move(I);
}
void setComplexFloat(APFloat R, APFloat I) {
assert(&R.getSemantics() == &I.getSemantics() &&
"Invalid complex float (type mismatch).");
assert(isComplexFloat() && "Invalid accessor");
((ComplexAPFloat *)(char *)&Data)->Real = std::move(R);
((ComplexAPFloat *)(char *)&Data)->Imag = std::move(I);
}
void setLValue(LValueBase B, const CharUnits &O, NoLValuePath,
bool IsNullPtr);
void setLValue(LValueBase B, const CharUnits &O,
ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd,
bool IsNullPtr);
void setUnion(const FieldDecl *Field, const APValue &Value);
void setAddrLabelDiff(const AddrLabelExpr* LHSExpr,
const AddrLabelExpr* RHSExpr) {
((AddrLabelDiffData *)(char *)&Data)->LHSExpr = LHSExpr;
((AddrLabelDiffData *)(char *)&Data)->RHSExpr = RHSExpr;
}
private:
void DestroyDataAndMakeUninit();
void MakeInt() {
assert(isAbsent() && "Bad state change");
new ((void *)&Data) APSInt(1);
Kind = Int;
}
void MakeFloat() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) APFloat(0.0);
Kind = Float;
}
void MakeFixedPoint(APFixedPoint &&FX) {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) APFixedPoint(std::move(FX));
Kind = FixedPoint;
}
void MakeVector() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) Vec();
Kind = Vector;
}
void MakeComplexInt() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) ComplexAPSInt();
Kind = ComplexInt;
}
void MakeComplexFloat() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) ComplexAPFloat();
Kind = ComplexFloat;
}
void MakeLValue();
void MakeArray(unsigned InitElts, unsigned Size);
void MakeStruct(unsigned B, unsigned M) {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) StructData(B, M);
Kind = Struct;
}
void MakeUnion() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) UnionData();
Kind = Union;
}
void MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember,
ArrayRef<const CXXRecordDecl*> Path);
void MakeAddrLabelDiff() {
assert(isAbsent() && "Bad state change");
new ((void *)(char *)&Data) AddrLabelDiffData();
Kind = AddrLabelDiff;
}
private:
/// The following functions are used as part of initialization, during
/// deserialization and importing. Reserve the space so that it can be
/// filled in by those steps.
MutableArrayRef<APValue> setVectorUninit(unsigned N) {
assert(isVector() && "Invalid accessor");
Vec *V = ((Vec *)(char *)&Data);
V->Elts = new APValue[N];
V->NumElts = N;
return {V->Elts, V->NumElts};
}
MutableArrayRef<LValuePathEntry>
setLValueUninit(LValueBase B, const CharUnits &O, unsigned Size,
bool OnePastTheEnd, bool IsNullPtr);
MutableArrayRef<const CXXRecordDecl *>
setMemberPointerUninit(const ValueDecl *Member, bool IsDerivedMember,
unsigned Size);
};
} // end namespace clang.
namespace llvm {
template<> struct DenseMapInfo<clang::APValue::LValueBase> {
static clang::APValue::LValueBase getEmptyKey();
static clang::APValue::LValueBase getTombstoneKey();
static unsigned getHashValue(const clang::APValue::LValueBase &Base);
static bool isEqual(const clang::APValue::LValueBase &LHS,
const clang::APValue::LValueBase &RHS);
};
}
#endif

View File

@ -0,0 +1,27 @@
//===--- AST.h - "Umbrella" header for AST library --------------*- 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 interface to the AST classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AST_H
#define LLVM_CLANG_AST_AST_H
// This header exports all AST interfaces.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#endif

View File

@ -0,0 +1,296 @@
//===--- ASTConcept.h - Concepts Related AST Data Structures ----*- 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
/// \brief This file provides AST data structures related to concepts.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONCEPT_H
#define LLVM_CLANG_AST_ASTCONCEPT_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifierBase.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/UnsignedOrNone.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <utility>
namespace clang {
class ConceptDecl;
class TemplateDecl;
class ConceptReference;
class Expr;
class NamedDecl;
struct PrintingPolicy;
/// Unsatisfied constraint expressions if the template arguments could be
/// substituted into them, or a diagnostic if substitution resulted in
/// an invalid expression.
///
using ConstraintSubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
using UnsatisfiedConstraintRecord =
llvm::PointerUnion<const Expr *, const ConceptReference *,
const ConstraintSubstitutionDiagnostic *>;
/// The result of a constraint satisfaction check, containing the necessary
/// information to diagnose an unsatisfied constraint.
class ConstraintSatisfaction : public llvm::FoldingSetNode {
// The template-like entity that 'owns' the constraint checked here (can be a
// constrained entity or a concept).
const NamedDecl *ConstraintOwner = nullptr;
llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
public:
ConstraintSatisfaction() = default;
ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs)
: ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {}
bool IsSatisfied = false;
bool ContainsErrors = false;
/// \brief The substituted constraint expr, if the template arguments could be
/// substituted into them, or a diagnostic if substitution resulted in an
/// invalid expression.
llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details;
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
Profile(ID, C, ConstraintOwner, TemplateArgs);
}
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
const NamedDecl *ConstraintOwner,
ArrayRef<TemplateArgument> TemplateArgs);
bool HasSubstitutionFailure() {
for (const auto &Detail : Details)
if (Detail.dyn_cast<const ConstraintSubstitutionDiagnostic *>())
return true;
return false;
}
};
/// \brief The result of a constraint satisfaction check, containing the
/// necessary information to diagnose an unsatisfied constraint.
///
/// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
struct ASTConstraintSatisfaction final :
llvm::TrailingObjects<ASTConstraintSatisfaction,
UnsatisfiedConstraintRecord> {
std::size_t NumRecords;
bool IsSatisfied : 1;
bool ContainsErrors : 1;
const UnsatisfiedConstraintRecord *begin() const {
return getTrailingObjects();
}
const UnsatisfiedConstraintRecord *end() const {
return getTrailingObjects() + NumRecords;
}
ArrayRef<UnsatisfiedConstraintRecord> records() const {
return {begin(), end()};
}
ASTConstraintSatisfaction(const ASTContext &C,
const ConstraintSatisfaction &Satisfaction);
ASTConstraintSatisfaction(const ASTContext &C,
const ASTConstraintSatisfaction &Satisfaction);
static ASTConstraintSatisfaction *
Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
static ASTConstraintSatisfaction *
Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction);
};
/// A reference to a concept and its template args, as it appears in the code.
///
/// Examples:
/// template <int X> requires is_even<X> int half = X/2;
/// ~~~~~~~~~~ (in ConceptSpecializationExpr)
///
/// std::input_iterator auto I = Container.begin();
/// ~~~~~~~~~~~~~~~~~~~ (in AutoTypeLoc)
///
/// template <std::derives_from<Expr> T> void dump();
/// ~~~~~~~~~~~~~~~~~~~~~~~ (in TemplateTypeParmDecl)
class ConceptReference {
protected:
// \brief The optional nested name specifier used when naming the concept.
NestedNameSpecifierLoc NestedNameSpec;
/// \brief The location of the template keyword, if specified when naming the
/// concept.
SourceLocation TemplateKWLoc;
/// \brief The concept name used.
DeclarationNameInfo ConceptName;
/// \brief The declaration found by name lookup when the expression was
/// created.
/// Can differ from NamedConcept when, for example, the concept was found
/// through a UsingShadowDecl.
NamedDecl *FoundDecl;
/// \brief The concept named.
TemplateDecl *NamedConcept;
/// \brief The template argument list source info used to specialize the
/// concept.
const ASTTemplateArgumentListInfo *ArgsAsWritten;
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
public:
static ConceptReference *
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten);
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
return NestedNameSpec;
}
const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
SourceLocation getConceptNameLoc() const {
return getConceptNameInfo().getLoc();
}
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
SourceLocation getLocation() const { return getConceptNameLoc(); }
SourceLocation getBeginLoc() const LLVM_READONLY;
SourceLocation getEndLoc() const LLVM_READONLY {
return getTemplateArgsAsWritten() &&
getTemplateArgsAsWritten()->getRAngleLoc().isValid()
? getTemplateArgsAsWritten()->getRAngleLoc()
: getConceptNameInfo().getEndLoc();
}
SourceRange getSourceRange() const LLVM_READONLY {
return SourceRange(getBeginLoc(), getEndLoc());
}
NamedDecl *getFoundDecl() const {
return FoundDecl;
}
TemplateDecl *getNamedConcept() const { return NamedConcept; }
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
}
/// \brief Whether or not template arguments were explicitly specified in the
/// concept reference (they might not be in type constraints, for example)
bool hasExplicitTemplateArgs() const {
return ArgsAsWritten != nullptr;
}
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
void dump() const;
void dump(llvm::raw_ostream &) const;
};
/// Models the abbreviated syntax to constrain a template type parameter:
/// template <convertible_to<string> T> void print(T object);
/// ~~~~~~~~~~~~~~~~~~~~~~
/// Semantically, this adds an "immediately-declared constraint" with extra arg:
/// requires convertible_to<T, string>
///
/// In the C++ grammar, a type-constraint is also used for auto types:
/// convertible_to<string> auto X = ...;
/// We do *not* model these as TypeConstraints, but AutoType(Loc) directly.
class TypeConstraint {
/// \brief The immediately-declared constraint expression introduced by this
/// type-constraint.
Expr *ImmediatelyDeclaredConstraint = nullptr;
ConceptReference *ConceptRef;
UnsignedOrNone ArgPackSubstIndex;
public:
TypeConstraint(ConceptReference *ConceptRef,
Expr *ImmediatelyDeclaredConstraint,
UnsignedOrNone ArgPackSubstIndex)
: ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint),
ConceptRef(ConceptRef), ArgPackSubstIndex(ArgPackSubstIndex) {}
/// \brief Get the immediately-declared constraint expression introduced by
/// this type-constraint, that is - the constraint expression that is added to
/// the associated constraints of the enclosing declaration in practice.
Expr *getImmediatelyDeclaredConstraint() const {
return ImmediatelyDeclaredConstraint;
}
ConceptReference *getConceptReference() const { return ConceptRef; }
UnsignedOrNone getArgPackSubstIndex() const { return ArgPackSubstIndex; }
// FIXME: Instead of using these concept related functions the callers should
// directly work with the corresponding ConceptReference.
TemplateDecl *getNamedConcept() const {
return ConceptRef->getNamedConcept();
}
SourceLocation getConceptNameLoc() const {
return ConceptRef->getConceptNameLoc();
}
bool hasExplicitTemplateArgs() const {
return ConceptRef->hasExplicitTemplateArgs();
}
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ConceptRef->getTemplateArgsAsWritten();
}
SourceLocation getTemplateKWLoc() const {
return ConceptRef->getTemplateKWLoc();
}
NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); }
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
return ConceptRef->getNestedNameSpecifierLoc();
}
const DeclarationNameInfo &getConceptNameInfo() const {
return ConceptRef->getConceptNameInfo();
}
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const {
ConceptRef->print(OS, Policy);
}
};
/// Insertion operator for diagnostics. This allows sending ConceptReferences's
/// into a diagnostic with <<.
const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
const ConceptReference *C);
} // clang
#endif // LLVM_CLANG_AST_ASTCONCEPT_H

View File

@ -0,0 +1,157 @@
//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- 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 ASTConsumer class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
namespace clang {
class ASTContext;
class CXXMethodDecl;
class CXXRecordDecl;
class Decl;
class DeclGroupRef;
class ASTMutationListener;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class DeclaratorDecl;
class VarDecl;
class FunctionDecl;
class ImportDecl;
class OpenACCRoutineDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
/// clients that read ASTs. This abstraction layer allows the client to be
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
class ASTConsumer {
/// Whether this AST consumer also requires information about
/// semantic analysis.
bool SemaConsumer = false;
friend class SemaConsumer;
public:
ASTConsumer() = default;
virtual ~ASTConsumer() {}
/// Initialize - This is called to initialize the consumer, providing the
/// ASTContext.
virtual void Initialize(ASTContext &Context) {}
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by the parser to process every top-level Decl*.
///
/// \returns true to continue parsing, or false to abort parsing.
virtual bool HandleTopLevelDecl(DeclGroupRef D);
/// This callback is invoked each time an inline (method or friend)
/// function definition in a class is completed.
virtual void HandleInlineFunctionDefinition(FunctionDecl *D) {}
/// HandleInterestingDecl - Handle the specified interesting declaration. This
/// is called by the AST reader when deserializing things that might interest
/// the consumer. The default implementation forwards to HandleTopLevelDecl.
virtual void HandleInterestingDecl(DeclGroupRef D);
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// (e.g. struct, union, enum, class) is completed. This allows the client to
/// hack on the type, which can occur at any point in the file (because these
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
/// This callback is invoked the first time each TagDecl is required to
/// be complete.
virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {}
/// Invoked when a function is implicitly instantiated.
/// Note that at this point it does not have a body, its body is
/// instantiated at the end of the translation unit and passed to
/// HandleTopLevelDecl.
virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
/// Handle the specified top-level declaration that occurred inside
/// and ObjC container.
/// The default implementation ignored them.
virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
/// Handle an ImportDecl that was implicitly created due to an
/// inclusion directive.
/// The default implementation passes it to HandleTopLevelDecl.
virtual void HandleImplicitImportDecl(ImportDecl *D);
/// CompleteTentativeDefinition - Callback invoked at the end of a translation
/// unit to notify the consumer that the given tentative definition should be
/// completed.
///
/// The variable declaration itself will be a tentative
/// definition. If it had an incomplete array type, its type will
/// have already been changed to an array of size 1. However, the
/// declaration remains a tentative definition and has not been
/// modified by the introduction of an implicit zero initializer.
virtual void CompleteTentativeDefinition(VarDecl *D) {}
/// CompleteExternalDeclaration - Callback invoked at the end of a translation
/// unit to notify the consumer that the given external declaration should be
/// completed.
virtual void CompleteExternalDeclaration(DeclaratorDecl *D) {}
/// Callback invoked when an MSInheritanceAttr has been attached to a
/// CXXRecordDecl.
virtual void AssignInheritanceModel(CXXRecordDecl *RD) {}
/// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this
// variable has been instantiated.
virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {}
/// Callback to handle the end-of-translation unit attachment of OpenACC
/// routine declaration information.
virtual void HandleOpenACCRoutineReference(const FunctionDecl *FD,
const OpenACCRoutineDecl *RD) {}
/// Callback involved at the end of a translation unit to
/// notify the consumer that a vtable for the given C++ class is
/// required.
///
/// \param RD The class whose vtable was used.
virtual void HandleVTable(CXXRecordDecl *RD) {}
/// If the consumer is interested in entities getting modified after
/// their initial creation, it should return a pointer to
/// an ASTMutationListener here.
virtual ASTMutationListener *GetASTMutationListener() { return nullptr; }
/// If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
virtual ASTDeserializationListener *GetASTDeserializationListener() {
return nullptr;
}
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {}
/// This callback is called for each function if the Parser was
/// initialized with \c SkipFunctionBodies set to \c true.
///
/// \return \c true if the function's body should be skipped. The function
/// body may be parsed anyway if it is needed (for instance, if it contains
/// the code completion point or is constexpr).
virtual bool shouldSkipFunctionBody(Decl *D) { return true; }
};
} // end namespace clang.
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
//===- ASTContextAllocate.h - ASTContext allocate functions -----*- 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 declares ASTContext allocation functions separate from the main
// code in ASTContext.h.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H
#define LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H
#include <cstddef>
namespace clang {
class ASTContext;
} // namespace clang
// Defined in ASTContext.h
void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 8);
void *operator new[](size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 8);
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, const clang::ASTContext &C, size_t);
void operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
#endif // LLVM_CLANG_AST_ASTCONTEXTALLOCATE_H

View File

@ -0,0 +1,46 @@
//===--- ASTDiagnostic.h - Diagnostics for the AST library ------*- 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_AST_ASTDIAGNOSTIC_H
#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticAST.h"
namespace clang {
/// DiagnosticsEngine argument formatting function for diagnostics that
/// involve AST nodes.
///
/// This function formats diagnostic arguments for various AST nodes,
/// including types, declaration names, nested name specifiers, and
/// declaration contexts, into strings that can be printed as part of
/// diagnostics. It is meant to be used as the argument to
/// \c DiagnosticsEngine::SetArgToStringFn(), where the cookie is an \c
/// ASTContext pointer.
void FormatASTNodeDiagnosticArgument(
DiagnosticsEngine::ArgumentKind Kind,
intptr_t Val,
StringRef Modifier,
StringRef Argument,
ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
SmallVectorImpl<char> &Output,
void *Cookie,
ArrayRef<intptr_t> QualTypeVals);
/// Returns a desugared version of the QualType, and marks ShouldAKA as true
/// whenever we remove significant sugar from the type. Make sure ShouldAKA
/// is initialized before passing it in.
QualType desugarForDiagnostic(ASTContext &Context, QualType QT,
bool &ShouldAKA);
std::string FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T);
} // end namespace clang
#endif

View File

@ -0,0 +1,51 @@
//===--- ASTDumper.h - Dumping implementation for ASTs --------------------===//
//
// 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_AST_ASTDUMPER_H
#define LLVM_CLANG_AST_ASTDUMPER_H
#include "clang/AST/ASTNodeTraverser.h"
#include "clang/AST/TextNodeDumper.h"
#include "clang/Basic/SourceManager.h"
namespace clang {
class ASTDumper : public ASTNodeTraverser<ASTDumper, TextNodeDumper> {
TextNodeDumper NodeDumper;
raw_ostream &OS;
const bool ShowColors;
public:
ASTDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors)
: NodeDumper(OS, Context, ShowColors), OS(OS), ShowColors(ShowColors) {}
ASTDumper(raw_ostream &OS, bool ShowColors)
: NodeDumper(OS, ShowColors), OS(OS), ShowColors(ShowColors) {}
TextNodeDumper &doGetNodeDelegate() { return NodeDumper; }
void dumpInvalidDeclContext(const DeclContext *DC);
void dumpLookups(const DeclContext *DC, bool DumpDecls);
template <typename SpecializationDecl>
void dumpTemplateDeclSpecialization(const SpecializationDecl *D,
bool DumpExplicitInst, bool DumpRefOnly);
template <typename TemplateDecl>
void dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
void VisitClassTemplateDecl(const ClassTemplateDecl *D);
void VisitVarTemplateDecl(const VarTemplateDecl *D);
};
} // namespace clang
#endif

View File

@ -0,0 +1,104 @@
//===--- ASTDumperUtils.h - Printing of AST nodes -------------------------===//
//
// 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 implements AST utilities for traversal down the tree.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTDUMPERUTILS_H
#define LLVM_CLANG_AST_ASTDUMPERUTILS_H
#include "llvm/Support/raw_ostream.h"
namespace clang {
/// Used to specify the format for printing AST dump information.
enum ASTDumpOutputFormat {
ADOF_Default,
ADOF_JSON
};
// Colors used for various parts of the AST dump
// Do not use bold yellow for any text. It is hard to read on white screens.
struct TerminalColor {
llvm::raw_ostream::Colors Color;
bool Bold;
};
// Red - CastColor
// Green - TypeColor
// Bold Green - DeclKindNameColor, UndeserializedColor
// Yellow - AddressColor, LocationColor
// Blue - CommentColor, NullColor, IndentColor
// Bold Blue - AttrColor
// Bold Magenta - StmtColor
// Cyan - ValueKindColor, ObjectKindColor
// Bold Cyan - ValueColor, DeclNameColor
// Decl kind names (VarDecl, FunctionDecl, etc)
static const TerminalColor DeclKindNameColor = {llvm::raw_ostream::GREEN, true};
// Attr names (CleanupAttr, GuardedByAttr, etc)
static const TerminalColor AttrColor = {llvm::raw_ostream::BLUE, true};
// Statement names (DeclStmt, ImplicitCastExpr, etc)
static const TerminalColor StmtColor = {llvm::raw_ostream::MAGENTA, true};
// Comment names (FullComment, ParagraphComment, TextComment, etc)
static const TerminalColor CommentColor = {llvm::raw_ostream::BLUE, false};
// Type names (int, float, etc, plus user defined types)
static const TerminalColor TypeColor = {llvm::raw_ostream::GREEN, false};
// Pointer address
static const TerminalColor AddressColor = {llvm::raw_ostream::YELLOW, false};
// Source locations
static const TerminalColor LocationColor = {llvm::raw_ostream::YELLOW, false};
// lvalue/xvalue
static const TerminalColor ValueKindColor = {llvm::raw_ostream::CYAN, false};
// bitfield/objcproperty/objcsubscript/vectorcomponent
static const TerminalColor ObjectKindColor = {llvm::raw_ostream::CYAN, false};
// contains-errors
static const TerminalColor ErrorsColor = {llvm::raw_ostream::RED, true};
// Null statements
static const TerminalColor NullColor = {llvm::raw_ostream::BLUE, false};
// Undeserialized entities
static const TerminalColor UndeserializedColor = {llvm::raw_ostream::GREEN,
true};
// CastKind from CastExpr's
static const TerminalColor CastColor = {llvm::raw_ostream::RED, false};
// Value of the statement
static const TerminalColor ValueColor = {llvm::raw_ostream::CYAN, true};
// Decl names
static const TerminalColor DeclNameColor = {llvm::raw_ostream::CYAN, true};
// Indents ( `, -. | )
static const TerminalColor IndentColor = {llvm::raw_ostream::BLUE, false};
class ColorScope {
llvm::raw_ostream &OS;
const bool ShowColors;
public:
ColorScope(llvm::raw_ostream &OS, bool ShowColors, TerminalColor Color)
: OS(OS), ShowColors(ShowColors) {
if (ShowColors)
OS.changeColor(Color.Color, Color.Bold);
}
~ColorScope() {
if (ShowColors)
OS.resetColor();
}
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTDUMPERUTILS_H

View File

@ -0,0 +1,41 @@
//===--- ASTFwd.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
/// Forward declaration of all AST node types.
///
//===-------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTFWD_H
#define LLVM_CLANG_AST_ASTFWD_H
namespace clang {
class Decl;
#define DECL(DERIVED, BASE) class DERIVED##Decl;
#include "clang/AST/DeclNodes.inc"
class Stmt;
#define STMT(DERIVED, BASE) class DERIVED;
#include "clang/AST/StmtNodes.inc"
class Type;
#define TYPE(DERIVED, BASE) class DERIVED##Type;
#include "clang/AST/TypeNodes.inc"
class CXXCtorInitializer;
class OMPClause;
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) class Class;
#include "llvm/Frontend/OpenMP/OMP.inc"
class Attr;
#define ATTR(A) class A##Attr;
#include "clang/Basic/AttrList.inc"
class ObjCProtocolLoc;
class ConceptReference;
} // end namespace clang
#endif

View File

@ -0,0 +1,50 @@
//===- ASTImportError.h - Define errors while importing AST -----*- 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 ASTImportError class which basically defines the kind
// of error while importing AST .
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTERROR_H
#define LLVM_CLANG_AST_ASTIMPORTERROR_H
#include "llvm/Support/Error.h"
namespace clang {
class ASTImportError : public llvm::ErrorInfo<ASTImportError> {
public:
/// \brief Kind of error when importing an AST component.
enum ErrorKind {
NameConflict, /// Naming ambiguity (likely ODR violation).
UnsupportedConstruct, /// Not supported node or case.
Unknown /// Other error.
};
ErrorKind Error;
static char ID;
ASTImportError() : Error(Unknown) {}
ASTImportError(const ASTImportError &Other) : Error(Other.Error) {}
ASTImportError &operator=(const ASTImportError &Other) {
Error = Other.Error;
return *this;
}
ASTImportError(ErrorKind Error) : Error(Error) {}
std::string toString() const;
void log(llvm::raw_ostream &OS) const override;
std::error_code convertToErrorCode() const override;
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTERROR_H

View File

@ -0,0 +1,616 @@
//===- ASTImporter.h - Importing ASTs from other Contexts -------*- 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 ASTImporter class which imports AST nodes from one
// context into another context.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/ASTImportError.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include <optional>
#include <utility>
namespace clang {
class ASTContext;
class ASTImporterSharedState;
class Attr;
class CXXBaseSpecifier;
class CXXCtorInitializer;
class Decl;
class DeclContext;
class Expr;
class FileManager;
class NamedDecl;
class Stmt;
class TagDecl;
class TranslationUnitDecl;
class TypeSourceInfo;
// \brief Returns with a list of declarations started from the canonical decl
// then followed by subsequent decls in the translation unit.
// This gives a canonical list for each entry in the redecl chain.
// `Decl::redecls()` gives a list of decls which always start from the
// previous decl and the next item is actually the previous item in the order
// of source locations. Thus, `Decl::redecls()` gives different lists for
// the different entries in a given redecl chain.
llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D);
/// Imports selected nodes from one AST context into another context,
/// merging AST nodes where appropriate.
class ASTImporter {
friend class ASTNodeImporter;
public:
using NonEquivalentDeclSet =
llvm::DenseSet<std::tuple<Decl *, Decl *, int>>;
using ImportedCXXBaseSpecifierMap =
llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
enum class ODRHandlingType { Conservative, Liberal };
// An ImportPath is the list of the AST nodes which we visit during an
// Import call.
// If node `A` depends on node `B` then the path contains an `A`->`B` edge.
// From the call stack of the import functions we can read the very same
// path.
//
// Now imagine the following AST, where the `->` represents dependency in
// therms of the import.
// ```
// A->B->C->D
// `->E
// ```
// We would like to import A.
// The import behaves like a DFS, so we will visit the nodes in this order:
// ABCDE.
// During the visitation we will have the following ImportPaths:
// ```
// A
// AB
// ABC
// ABCD
// ABC
// AB
// ABE
// AB
// A
// ```
// If during the visit of E there is an error then we set an error for E,
// then as the call stack shrinks for B, then for A:
// ```
// A
// AB
// ABC
// ABCD
// ABC
// AB
// ABE // Error! Set an error to E
// AB // Set an error to B
// A // Set an error to A
// ```
// However, during the import we could import C and D without any error and
// they are independent from A,B and E.
// We must not set up an error for C and D.
// So, at the end of the import we have an entry in `ImportDeclErrors` for
// A,B,E but not for C,D.
//
// Now what happens if there is a cycle in the import path?
// Let's consider this AST:
// ```
// A->B->C->A
// `->E
// ```
// During the visitation we will have the below ImportPaths and if during
// the visit of E there is an error then we will set up an error for E,B,A.
// But what's up with C?
// ```
// A
// AB
// ABC
// ABCA
// ABC
// AB
// ABE // Error! Set an error to E
// AB // Set an error to B
// A // Set an error to A
// ```
// This time we know that both B and C are dependent on A.
// This means we must set up an error for C too.
// As the call stack reverses back we get to A and we must set up an error
// to all nodes which depend on A (this includes C).
// But C is no longer on the import path, it just had been previously.
// Such situation can happen only if during the visitation we had a cycle.
// If we didn't have any cycle, then the normal way of passing an Error
// object through the call stack could handle the situation.
// This is why we must track cycles during the import process for each
// visited declaration.
class ImportPathTy {
public:
using VecTy = llvm::SmallVector<Decl *, 32>;
void push(Decl *D) {
Nodes.push_back(D);
++Aux[D];
}
void pop() {
if (Nodes.empty())
return;
--Aux[Nodes.back()];
Nodes.pop_back();
}
/// Returns true if the last element can be found earlier in the path.
bool hasCycleAtBack() const {
auto Pos = Aux.find(Nodes.back());
return Pos != Aux.end() && Pos->second > 1;
}
using Cycle = llvm::iterator_range<VecTy::const_reverse_iterator>;
Cycle getCycleAtBack() const {
assert(Nodes.size() >= 2);
return Cycle(Nodes.rbegin(),
std::find(Nodes.rbegin() + 1, Nodes.rend(), Nodes.back()) +
1);
}
/// Returns the copy of the cycle.
VecTy copyCycleAtBack() const {
auto R = getCycleAtBack();
return VecTy(R.begin(), R.end());
}
private:
// All nodes of the path.
VecTy Nodes;
// Auxiliary container to be able to answer "Do we have a cycle ending
// at last element?" as fast as possible.
// We count each Decl's occurrence over the path.
llvm::SmallDenseMap<Decl *, int, 32> Aux;
};
class FunctionDeclImportCycleDetector {
public:
auto makeScopedCycleDetection(const FunctionDecl *D);
bool isCycle(const FunctionDecl *D) const;
private:
llvm::DenseSet<const FunctionDecl *> FunctionDeclsWithImportInProgress;
};
private:
std::shared_ptr<ASTImporterSharedState> SharedState = nullptr;
/// The path which we go through during the import of a given AST node.
ImportPathTy ImportPath;
/// Sometimes we have to save some part of an import path, so later we can
/// set up properties to the saved nodes.
/// We may have several of these import paths associated to one Decl.
using SavedImportPathsForOneDecl =
llvm::SmallVector<ImportPathTy::VecTy, 32>;
using SavedImportPathsTy =
llvm::SmallDenseMap<Decl *, SavedImportPathsForOneDecl, 32>;
SavedImportPathsTy SavedImportPaths;
/// The contexts we're importing to and from.
ASTContext &ToContext, &FromContext;
/// The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
/// Whether to perform a minimal import.
bool Minimal;
ODRHandlingType ODRHandling;
/// Whether the last diagnostic came from the "from" context.
bool LastDiagFromFrom = false;
/// Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
llvm::DenseMap<const Type *, const Type *> ImportedTypes;
/// Mapping from the already-imported declarations in the "from"
/// context to the corresponding declarations in the "to" context.
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
/// Mapping from the already-imported declarations in the "from"
/// context to the error status of the import of that declaration.
/// This map contains only the declarations that were not correctly
/// imported. The same declaration may or may not be included in
/// ImportedDecls. This map is updated continuously during imports and never
/// cleared (like ImportedDecls).
llvm::DenseMap<Decl *, ASTImportError> ImportDeclErrors;
/// Mapping from the already-imported declarations in the "to"
/// context to the corresponding declarations in the "from" context.
llvm::DenseMap<Decl *, Decl *> ImportedFromDecls;
/// Mapping from the already-imported statements in the "from"
/// context to the corresponding statements in the "to" context.
llvm::DenseMap<Stmt *, Stmt *> ImportedStmts;
/// Mapping from the already-imported FileIDs in the "from" source
/// manager to the corresponding FileIDs in the "to" source manager.
llvm::DenseMap<FileID, FileID> ImportedFileIDs;
/// Mapping from the already-imported CXXBasesSpecifier in
/// the "from" source manager to the corresponding CXXBasesSpecifier
/// in the "to" source manager.
ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers;
/// Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
NonEquivalentDeclSet NonEquivalentDecls;
/// A FunctionDecl can have properties that have a reference to the
/// function itself and are imported before the function is created. This
/// can come for example from auto return type or when template parameters
/// are used in the return type or parameters. This member is used to detect
/// cyclic import of FunctionDecl objects to avoid infinite recursion.
FunctionDeclImportCycleDetector FindFunctionDeclImportCycle;
using FoundDeclsTy = SmallVector<NamedDecl *, 2>;
FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name);
void AddToLookupTable(Decl *ToD);
protected:
/// Can be overwritten by subclasses to implement their own import logic.
/// The overwritten method should call this method if it didn't import the
/// decl on its own.
virtual Expected<Decl *> ImportImpl(Decl *From);
/// Used only in unittests to verify the behaviour of the error handling.
virtual bool returnWithErrorInTest() { return false; };
public:
/// \param ToContext The context we'll be importing into.
///
/// \param ToFileManager The file manager we'll be importing into.
///
/// \param FromContext The context we'll be importing from.
///
/// \param FromFileManager The file manager we'll be importing into.
///
/// \param MinimalImport If true, the importer will attempt to import
/// as little as it can, e.g., by importing declarations as forward
/// declarations that can be completed at a later point.
///
/// \param SharedState The importer specific lookup table which may be
/// shared amongst several ASTImporter objects.
/// If not set then the original C/C++ lookup is used.
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport,
std::shared_ptr<ASTImporterSharedState> SharedState = nullptr);
virtual ~ASTImporter();
/// Whether the importer will perform a minimal import, creating
/// to-be-completed forward declarations when possible.
bool isMinimalImport() const { return Minimal; }
void setODRHandling(ODRHandlingType T) { ODRHandling = T; }
/// \brief Import the given object, returns the result.
///
/// \param To Import the object into this variable.
/// \param From Object to import.
/// \return Error information (success or error).
template <typename ImportT>
[[nodiscard]] llvm::Error importInto(ImportT &To, const ImportT &From) {
auto ToOrErr = Import(From);
if (ToOrErr)
To = *ToOrErr;
return ToOrErr.takeError();
}
/// Import cleanup objects owned by ExprWithCleanup.
llvm::Expected<ExprWithCleanups::CleanupObject>
Import(ExprWithCleanups::CleanupObject From);
/// Import the given type from the "from" context into the "to"
/// context.
///
/// \returns The equivalent type in the "to" context, or the import error.
llvm::Expected<const Type *> Import(const Type *FromT);
/// Import the given qualified type from the "from" context into the "to"
/// context. A null type is imported as a null type (no error).
///
/// \returns The equivalent type in the "to" context, or the import error.
llvm::Expected<QualType> Import(QualType FromT);
/// Import the given type source information from the
/// "from" context into the "to" context.
///
/// \returns The equivalent type source information in the "to"
/// context, or the import error.
llvm::Expected<TypeSourceInfo *> Import(TypeSourceInfo *FromTSI);
/// Import the given attribute from the "from" context into the
/// "to" context.
///
/// \returns The equivalent attribute in the "to" context, or the import
/// error.
llvm::Expected<Attr *> Import(const Attr *FromAttr);
/// Import the given declaration from the "from" context into the
/// "to" context.
///
/// \returns The equivalent declaration in the "to" context, or the import
/// error.
llvm::Expected<Decl *> Import(Decl *FromD);
llvm::Expected<const Decl *> Import(const Decl *FromD) {
return Import(const_cast<Decl *>(FromD));
}
llvm::Expected<InheritedConstructor>
Import(const InheritedConstructor &From);
/// Return the copy of the given declaration in the "to" context if
/// it has already been imported from the "from" context. Otherwise return
/// nullptr.
Decl *GetAlreadyImportedOrNull(const Decl *FromD) const;
/// Return the translation unit from where the declaration was
/// imported. If it does not exist nullptr is returned.
TranslationUnitDecl *GetFromTU(Decl *ToD);
/// Return the declaration in the "from" context from which the declaration
/// in the "to" context was imported. If it was not imported or of the wrong
/// type a null value is returned.
template <typename DeclT>
std::optional<DeclT *> getImportedFromDecl(const DeclT *ToD) const {
auto FromI = ImportedFromDecls.find(ToD);
if (FromI == ImportedFromDecls.end())
return {};
auto *FromD = dyn_cast<DeclT>(FromI->second);
if (!FromD)
return {};
return FromD;
}
/// Import the given declaration context from the "from"
/// AST context into the "to" AST context.
///
/// \returns the equivalent declaration context in the "to"
/// context, or error value.
llvm::Expected<DeclContext *> ImportContext(DeclContext *FromDC);
/// Import the given expression from the "from" context into the
/// "to" context.
///
/// \returns The equivalent expression in the "to" context, or the import
/// error.
llvm::Expected<Expr *> Import(Expr *FromE);
/// Import the given statement from the "from" context into the
/// "to" context.
///
/// \returns The equivalent statement in the "to" context, or the import
/// error.
llvm::Expected<Stmt *> Import(Stmt *FromS);
/// Import the given nested-name-specifier from the "from"
/// context into the "to" context.
///
/// \returns The equivalent nested-name-specifier in the "to"
/// context, or the import error.
llvm::Expected<NestedNameSpecifier> Import(NestedNameSpecifier FromNNS);
/// Import the given nested-name-specifier-loc from the "from"
/// context into the "to" context.
///
/// \returns The equivalent nested-name-specifier-loc in the "to"
/// context, or the import error.
llvm::Expected<NestedNameSpecifierLoc>
Import(NestedNameSpecifierLoc FromNNS);
/// Import the given template name from the "from" context into the
/// "to" context, or the import error.
llvm::Expected<TemplateName> Import(TemplateName From);
/// Import the given source location from the "from" context into
/// the "to" context.
///
/// \returns The equivalent source location in the "to" context, or the
/// import error.
llvm::Expected<SourceLocation> Import(SourceLocation FromLoc);
/// Import the given source range from the "from" context into
/// the "to" context.
///
/// \returns The equivalent source range in the "to" context, or the import
/// error.
llvm::Expected<SourceRange> Import(SourceRange FromRange);
/// Import the given declaration name from the "from"
/// context into the "to" context.
///
/// \returns The equivalent declaration name in the "to" context, or the
/// import error.
llvm::Expected<DeclarationName> Import(DeclarationName FromName);
/// Import the given identifier from the "from" context
/// into the "to" context.
///
/// \returns The equivalent identifier in the "to" context. Note: It
/// returns nullptr only if the FromId was nullptr.
IdentifierInfo *Import(const IdentifierInfo *FromId);
/// Import the given identifier or overloaded operator from the "from"
/// context into the "to" context.
///
/// \returns The equivalent identifier or overloaded operator in the "to"
/// context.
IdentifierOrOverloadedOperator
Import(IdentifierOrOverloadedOperator FromIO);
/// Import the given Objective-C selector from the "from"
/// context into the "to" context.
///
/// \returns The equivalent selector in the "to" context, or the import
/// error.
llvm::Expected<Selector> Import(Selector FromSel);
/// Import the given file ID from the "from" context into the
/// "to" context.
///
/// \returns The equivalent file ID in the source manager of the "to"
/// context, or the import error.
llvm::Expected<FileID> Import(FileID, bool IsBuiltin = false);
/// Import the given C++ constructor initializer from the "from"
/// context into the "to" context.
///
/// \returns The equivalent initializer in the "to" context, or the import
/// error.
llvm::Expected<CXXCtorInitializer *> Import(CXXCtorInitializer *FromInit);
/// Import the given CXXBaseSpecifier from the "from" context into
/// the "to" context.
///
/// \returns The equivalent CXXBaseSpecifier in the source manager of the
/// "to" context, or the import error.
llvm::Expected<CXXBaseSpecifier *> Import(const CXXBaseSpecifier *FromSpec);
/// Import the given APValue from the "from" context into
/// the "to" context.
///
/// \return the equivalent APValue in the "to" context or the import
/// error.
llvm::Expected<APValue> Import(const APValue &FromValue);
/// Import the definition of the given declaration, including all of
/// the declarations it contains.
[[nodiscard]] llvm::Error ImportDefinition(Decl *From);
llvm::Error
ImportTemplateArguments(ArrayRef<TemplateArgument> FromArgs,
SmallVectorImpl<TemplateArgument> &ToArgs);
Expected<TemplateArgument> Import(const TemplateArgument &From);
/// Cope with a name conflict when importing a declaration into the
/// given context.
///
/// This routine is invoked whenever there is a name conflict while
/// importing a declaration. The returned name will become the name of the
/// imported declaration. By default, the returned name is the same as the
/// original name, leaving the conflict unresolve such that name lookup
/// for this name is likely to find an ambiguity later.
///
/// Subclasses may override this routine to resolve the conflict, e.g., by
/// renaming the declaration being imported.
///
/// \param Name the name of the declaration being imported, which conflicts
/// with other declarations.
///
/// \param DC the declaration context (in the "to" AST context) in which
/// the name is being imported.
///
/// \param IDNS the identifier namespace in which the name will be found.
///
/// \param Decls the set of declarations with the same name as the
/// declaration being imported.
///
/// \param NumDecls the number of conflicting declarations in \p Decls.
///
/// \returns the name that the newly-imported declaration should have. Or
/// an error if we can't handle the name conflict.
virtual Expected<DeclarationName>
HandleNameConflict(DeclarationName Name, DeclContext *DC, unsigned IDNS,
NamedDecl **Decls, unsigned NumDecls);
/// Retrieve the context that AST nodes are being imported into.
ASTContext &getToContext() const { return ToContext; }
/// Retrieve the context that AST nodes are being imported from.
ASTContext &getFromContext() const { return FromContext; }
/// Retrieve the file manager that AST nodes are being imported into.
FileManager &getToFileManager() const { return ToFileManager; }
/// Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
/// Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);
/// Report a diagnostic in the "from" context.
DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID);
/// Return the set of declarations that we know are not equivalent.
NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; }
/// Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl.
/// Mark the Decl as complete, filling it in as much as possible.
///
/// \param D A declaration in the "to" context.
virtual void CompleteDecl(Decl* D);
/// Subclasses can override this function to observe all of the \c From ->
/// \c To declaration mappings as they are imported.
virtual void Imported(Decl *From, Decl *To) {}
void RegisterImportedDecl(Decl *FromD, Decl *ToD);
/// Store and assign the imported declaration to its counterpart.
/// It may happen that several decls from the 'from' context are mapped to
/// the same decl in the 'to' context.
Decl *MapImported(Decl *From, Decl *To);
/// Called by StructuralEquivalenceContext. If a RecordDecl is
/// being compared to another RecordDecl as part of import, completing the
/// other RecordDecl may trigger importation of the first RecordDecl. This
/// happens especially for anonymous structs. If the original of the second
/// RecordDecl can be found, we can complete it without the need for
/// importation, eliminating this loop.
virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; }
/// Return if import of the given declaration has failed and if yes
/// the kind of the problem. This gives the first error encountered with
/// the node.
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *FromD) const;
/// Mark (newly) imported declaration with error.
void setImportDeclError(Decl *From, ASTImportError Error);
/// Determine whether the given types are structurally
/// equivalent.
bool IsStructurallyEquivalent(QualType From, QualType To,
bool Complain = true);
/// Determine the index of a field in its parent record.
/// F should be a field (or indirect field) declaration.
/// \returns The index of the field in its parent context (starting from 0).
/// On error `std::nullopt` is returned (parent context is non-record).
static UnsignedOrNone getFieldIndex(Decl *F);
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTER_H

View File

@ -0,0 +1,93 @@
//===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- 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 ASTImporterLookupTable class which implements a
// lookup procedure for the import mechanism.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
#define LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
#include "clang/AST/DeclBase.h" // lookup_result
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
namespace clang {
class NamedDecl;
class DeclContext;
// There are certain cases when normal C/C++ lookup (localUncachedLookup)
// does not find AST nodes. E.g.:
// Example 1:
// template <class T>
// struct X {
// friend void foo(); // this is never found in the DC of the TU.
// };
// Example 2:
// // The fwd decl to Foo is not found in the lookupPtr of the DC of the
// // translation unit decl.
// // Here we could find the node by doing a traverse through the list of
// // the Decls in the DC, but that would not scale.
// struct A { struct Foo *p; };
// This is a severe problem because the importer decides if it has to create a
// new Decl or not based on the lookup results.
// To overcome these cases we need an importer specific lookup table which
// holds every node and we are not interested in any C/C++ specific visibility
// considerations. Simply, we must know if there is an existing Decl in a
// given DC. Once we found it then we can handle any visibility related tasks.
class ASTImporterLookupTable {
// We store a list of declarations for each name.
// And we collect these lists for each DeclContext.
// We could have a flat map with (DeclContext, Name) tuple as key, but a two
// level map seems easier to handle.
using DeclList = llvm::SmallSetVector<NamedDecl *, 2>;
using NameMap = llvm::SmallDenseMap<DeclarationName, DeclList, 4>;
using DCMap = llvm::DenseMap<DeclContext *, NameMap>;
void add(DeclContext *DC, NamedDecl *ND);
void remove(DeclContext *DC, NamedDecl *ND);
DCMap LookupTable;
public:
ASTImporterLookupTable(TranslationUnitDecl &TU);
void add(NamedDecl *ND);
void remove(NamedDecl *ND);
// Sometimes a declaration is created first with a temporarily value of decl
// context (often the translation unit) and later moved to the final context.
// This happens for declarations that are created before the final declaration
// context. In such cases the lookup table needs to be updated.
// (The declaration is in these cases not added to the temporary decl context,
// only its parent is set.)
// FIXME: It would be better to not add the declaration to the temporary
// context at all in the lookup table, but this requires big change in
// ASTImporter.
// The function should be called when the old context is definitely different
// from the new.
void update(NamedDecl *ND, DeclContext *OldDC);
// Same as 'update' but allow if 'ND' is not in the table or the old context
// is the same as the new.
// FIXME: The old redeclaration context is not handled.
void updateForced(NamedDecl *ND, DeclContext *OldDC);
using LookupResult = DeclList;
LookupResult lookup(DeclContext *DC, DeclarationName Name) const;
// Check if the `ND` is within the lookup table (with its current name) in
// context `DC`. This is intended for debug purposes when the DeclContext of a
// NamedDecl is changed.
bool contains(DeclContext *DC, NamedDecl *ND) const;
void dump(DeclContext *DC) const;
void dump() const;
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H

View File

@ -0,0 +1,87 @@
//===- ASTImporterSharedState.h - ASTImporter specific state --*- 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 ASTImporter specific state, which may be shared
// amongst several ASTImporter objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H
#define LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H
#include "clang/AST/ASTImportError.h"
#include "clang/AST/ASTImporterLookupTable.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/DenseMap.h"
#include <optional>
namespace clang {
class TranslationUnitDecl;
/// Importer specific state, which may be shared amongst several ASTImporter
/// objects.
class ASTImporterSharedState {
/// Pointer to the import specific lookup table.
std::unique_ptr<ASTImporterLookupTable> LookupTable;
/// Mapping from the already-imported declarations in the "to"
/// context to the error status of the import of that declaration.
/// This map contains only the declarations that were not correctly
/// imported. The same declaration may or may not be included in
/// ImportedFromDecls. This map is updated continuously during imports and
/// never cleared (like ImportedFromDecls).
llvm::DenseMap<Decl *, ASTImportError> ImportErrors;
/// Set of the newly created declarations.
llvm::DenseSet<Decl *> NewDecls;
// FIXME put ImportedFromDecls here!
// And from that point we can better encapsulate the lookup table.
public:
ASTImporterSharedState() = default;
ASTImporterSharedState(TranslationUnitDecl &ToTU) {
LookupTable = std::make_unique<ASTImporterLookupTable>(ToTU);
}
ASTImporterLookupTable *getLookupTable() { return LookupTable.get(); }
void addDeclToLookup(Decl *D) {
if (LookupTable)
if (auto *ND = dyn_cast<NamedDecl>(D))
LookupTable->add(ND);
}
void removeDeclFromLookup(Decl *D) {
if (LookupTable)
if (auto *ND = dyn_cast<NamedDecl>(D))
LookupTable->remove(ND);
}
std::optional<ASTImportError> getImportDeclErrorIfAny(Decl *ToD) const {
auto Pos = ImportErrors.find(ToD);
if (Pos != ImportErrors.end())
return Pos->second;
else
return std::nullopt;
}
void setImportDeclError(Decl *To, ASTImportError Error) {
ImportErrors[To] = Error;
}
bool isNewDecl(const Decl *ToD) const { return NewDecls.count(ToD); }
void markAsNewDecl(Decl *ToD) { NewDecls.insert(ToD); }
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTIMPORTERSHAREDSTATE_H

View File

@ -0,0 +1,111 @@
//===--- ASTLambda.h - Lambda Helper Functions --------------*- 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 file provides some common utility functions for processing
/// Lambda related AST Constructs.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTLAMBDA_H
#define LLVM_CLANG_AST_ASTLAMBDA_H
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/Casting.h"
namespace clang {
inline StringRef getLambdaStaticInvokerName() {
return "__invoke";
}
// This function returns true if M is a specialization, a template,
// or a non-generic lambda call operator.
inline bool isLambdaCallOperator(const CXXMethodDecl *MD) {
const CXXRecordDecl *LambdaClass = MD->getParent();
if (!LambdaClass || !LambdaClass->isLambda()) return false;
return MD->getOverloadedOperator() == OO_Call;
}
inline bool isLambdaCallOperator(const DeclContext *DC) {
if (!DC || !isa<CXXMethodDecl>(DC)) return false;
return isLambdaCallOperator(cast<CXXMethodDecl>(DC));
}
inline bool isLambdaMethod(const DeclContext *DC) {
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(DC))
return MD->getParent()->isLambda();
return false;
}
inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) {
return isLambdaCallOperator(DC) &&
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction();
}
inline bool isLambdaCallWithImplicitObjectParameter(const DeclContext *DC) {
return isLambdaCallOperator(DC) &&
// FIXME: Checking for a null type is not great
// but lambdas with invalid captures or whose closure parameter list
// have not fully been parsed may have a call operator whose type is
// null.
!cast<CXXMethodDecl>(DC)->getType().isNull() &&
!cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction();
}
inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) {
if (!MD) return false;
const CXXRecordDecl *LambdaClass = MD->getParent();
if (LambdaClass && LambdaClass->isGenericLambda())
return isLambdaCallOperator(MD) &&
MD->isFunctionTemplateSpecialization();
return false;
}
inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
return C ? C->getParent()->isLambda() : false;
}
inline bool isLambdaConversionOperator(Decl *D) {
if (!D) return false;
if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D))
return isLambdaConversionOperator(Conv);
if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D))
if (CXXConversionDecl *Conv =
dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl()))
return isLambdaConversionOperator(Conv);
return false;
}
inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
return isGenericLambdaCallOperatorSpecialization(
dyn_cast<CXXMethodDecl>(DC));
}
inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization(
const DeclContext *DC) {
const auto *MD = dyn_cast<CXXMethodDecl>(DC);
if (!MD) return false;
const CXXRecordDecl *LambdaClass = MD->getParent();
if (LambdaClass && LambdaClass->isGenericLambda())
return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) &&
MD->isFunctionTemplateSpecialization();
return false;
}
// This returns the parent DeclContext ensuring that the correct
// parent DeclContext is returned for Lambdas
inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
if (isLambdaCallOperator(DC))
return DC->getParent()->getParent();
else
return DC->getParent();
}
} // clang
#endif

View File

@ -0,0 +1,202 @@
//===--- ASTMutationListener.h - AST Mutation 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 ASTMutationListener interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
namespace clang {
class Attr;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
class ConstructorUsingShadowDecl;
class CXXDestructorDecl;
class CXXRecordDecl;
class Decl;
class DeclContext;
class Expr;
class FieldDecl;
class FunctionDecl;
class FunctionTemplateDecl;
class Module;
class NamedDecl;
class NamespaceDecl;
class ObjCCategoryDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCPropertyDecl;
class ParmVarDecl;
class QualType;
class RecordDecl;
class TagDecl;
class TranslationUnitDecl;
class ValueDecl;
class VarDecl;
class VarTemplateDecl;
class VarTemplateSpecializationDecl;
/// An abstract interface that should be implemented by listeners
/// that want to be notified when an AST entity gets modified after its
/// initial creation.
class ASTMutationListener {
public:
virtual ~ASTMutationListener();
/// A new TagDecl definition was completed.
virtual void CompletedTagDefinition(const TagDecl *D) { }
/// A new declaration with name has been added to a DeclContext.
virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {}
/// An implicit member was added after the definition was completed.
virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {}
/// A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
const ClassTemplateSpecializationDecl *D) {}
/// A template specialization (or partial one) was added to the
/// template declaration.
virtual void
AddedCXXTemplateSpecialization(const VarTemplateDecl *TD,
const VarTemplateSpecializationDecl *D) {}
/// A template specialization (or partial one) was added to the
/// template declaration.
virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {}
/// A function's exception specification has been evaluated or
/// instantiated.
virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {}
/// A function's return type has been deduced.
virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
/// A virtual destructor's operator delete has been resolved.
virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
const FunctionDecl *Delete,
Expr *ThisArg) {}
/// A virtual destructor's operator global delete has been resolved.
virtual void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
const FunctionDecl *GlobDelete) {}
/// A virtual destructor's operator array delete has been resolved.
virtual void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
const FunctionDecl *ArrayDelete) {}
/// A virtual destructor's operator global array delete has been resolved.
virtual void
ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
const FunctionDecl *GlobArrayDelete) {}
/// An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
/// The instantiation of a templated function or variable was
/// requested. In particular, the point of instantiation and template
/// specialization kind of \p D may have changed.
virtual void InstantiationRequested(const ValueDecl *D) {}
/// A templated variable's definition was implicitly instantiated.
virtual void VariableDefinitionInstantiated(const VarDecl *D) {}
/// A function template's definition was instantiated.
virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
/// A default argument was instantiated.
virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {}
/// A default member initializer was instantiated.
virtual void DefaultMemberInitializerInstantiated(const FieldDecl *D) {}
/// A new objc category class was added for an interface.
virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
const ObjCInterfaceDecl *IFD) {}
/// A declaration is marked used which was not previously marked used.
///
/// \param D the declaration marked used
virtual void DeclarationMarkedUsed(const Decl *D) {}
/// A declaration is marked as OpenMP threadprivate which was not
/// previously marked as threadprivate.
///
/// \param D the declaration marked OpenMP threadprivate.
virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
/// A declaration is marked as OpenMP groupprivate which was not
/// previously marked as groupprivate.
///
/// \param D the declaration marked OpenMP groupprivate.
virtual void DeclarationMarkedOpenMPGroupPrivate(const Decl *D) {}
/// A declaration is marked as OpenMP declaretarget which was not
/// previously marked as declaretarget.
///
/// \param D the declaration marked OpenMP declaretarget.
/// \param Attr the added attribute.
virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) {}
/// A declaration is marked as a variable with OpenMP allocator.
///
/// \param D the declaration marked as a variable with OpenMP allocator.
virtual void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {}
/// A definition has been made visible by being redefined locally.
///
/// \param D The definition that was previously not visible.
/// \param M The containing module in which the definition was made visible,
/// if any.
virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {}
/// An attribute was added to a RecordDecl
///
/// \param Attr The attribute that was added to the Record
///
/// \param Record The RecordDecl that got a new attribute
virtual void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) {}
/// The parser find the named module declaration.
virtual void EnteringModulePurview() {}
/// An mangling number was added to a Decl
///
/// \param D The decl that got a mangling number
///
/// \param Number The mangling number that was added to the Decl
virtual void AddedManglingNumber(const Decl *D, unsigned Number) {}
/// An static local number was added to a Decl
///
/// \param D The decl that got a static local number
///
/// \param Number The static local number that was added to the Decl
virtual void AddedStaticLocalNumbers(const Decl *D, unsigned Number) {}
/// An anonymous namespace was added the translation unit decl
///
/// \param TU The translation unit decl that got a new anonymous namespace
///
/// \param AnonNamespace The anonymous namespace that was added
virtual void AddedAnonymousNamespace(const TranslationUnitDecl *TU,
NamespaceDecl *AnonNamespace) {}
// NOTE: If new methods are added they should also be added to
// MultiplexASTMutationListener.
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
//===- ASTStructuralEquivalence.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 StructuralEquivalenceContext class which checks for
// structural equivalence between types.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include <optional>
#include <queue>
#include <utility>
namespace clang {
class ASTContext;
class Decl;
class DiagnosticBuilder;
class QualType;
class RecordDecl;
class SourceLocation;
/// \brief Whether to perform a normal or minimal equivalence check.
/// In case of `Minimal`, we do not perform a recursive check of decls with
/// external storage.
enum class StructuralEquivalenceKind {
Default,
Minimal,
};
struct StructuralEquivalenceContext {
/// Store declaration pairs already found to be non-equivalent.
/// key: (from, to, IgnoreTemplateParmDepth)
using NonEquivalentDeclSet = llvm::DenseSet<std::tuple<Decl *, Decl *, int>>;
/// The language options to use for making a structural equivalence check.
const LangOptions &LangOpts;
/// AST contexts for which we are checking structural equivalence.
ASTContext &FromCtx, &ToCtx;
// Queue of from-to Decl pairs that are to be checked to determine the final
// result of equivalence of a starting Decl pair.
std::queue<std::pair<Decl *, Decl *>> DeclsToCheck;
// Set of from-to Decl pairs that are already visited during the check
// (are in or were once in \c DeclsToCheck) of a starting Decl pair.
llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls;
/// Declaration (from, to) pairs that are known not to be equivalent
/// (which we have already complained about).
NonEquivalentDeclSet &NonEquivalentDecls;
StructuralEquivalenceKind EqKind;
/// Whether we're being strict about the spelling of types when
/// unifying two types.
bool StrictTypeSpelling;
/// Whether warn or error on tag type mismatches.
bool ErrorOnTagTypeMismatch;
/// Whether to complain about failures.
bool Complain;
/// \c true if the last diagnostic came from ToCtx.
bool LastDiagFromC2 = false;
/// Whether to ignore comparing the depth of template param(TemplateTypeParm)
bool IgnoreTemplateParmDepth;
StructuralEquivalenceContext(const LangOptions &LangOpts, ASTContext &FromCtx,
ASTContext &ToCtx,
NonEquivalentDeclSet &NonEquivalentDecls,
StructuralEquivalenceKind EqKind,
bool StrictTypeSpelling = false,
bool Complain = true,
bool ErrorOnTagTypeMismatch = false,
bool IgnoreTemplateParmDepth = false)
: LangOpts(LangOpts), FromCtx(FromCtx), ToCtx(ToCtx),
NonEquivalentDecls(NonEquivalentDecls), EqKind(EqKind),
StrictTypeSpelling(StrictTypeSpelling),
ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain),
IgnoreTemplateParmDepth(IgnoreTemplateParmDepth) {}
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID);
/// Determine whether the two declarations are structurally
/// equivalent.
/// Implementation functions (all static functions in
/// ASTStructuralEquivalence.cpp) must never call this function because that
/// will wreak havoc the internal state (\c DeclsToCheck and
/// \c VisitedDecls members) and can cause faulty equivalent results.
bool IsEquivalent(Decl *D1, Decl *D2);
/// Determine whether the two types are structurally equivalent.
/// Implementation functions (all static functions in
/// ASTStructuralEquivalence.cpp) must never call this function because that
/// will wreak havoc the internal state (\c DeclsToCheck and
/// \c VisitedDecls members) and can cause faulty equivalent results.
bool IsEquivalent(QualType T1, QualType T2);
/// Determine whether the two statements are structurally equivalent.
/// Implementation functions (all static functions in
/// ASTStructuralEquivalence.cpp) must never call this function because that
/// will wreak havoc the internal state (\c DeclsToCheck and
/// \c VisitedDecls members) and can cause faulty equivalent results.
bool IsEquivalent(Stmt *S1, Stmt *S2);
/// Find the index of the given anonymous struct/union within its
/// context.
///
/// \returns Returns the index of this anonymous struct/union in its context,
/// including the next assigned index (if none of them match). Returns an
/// empty option if the context is not a record, i.e.. if the anonymous
/// struct/union is at namespace or block scope.
///
/// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
/// probably makes more sense in some other common place then here.
static UnsignedOrNone findUntaggedStructOrUnionIndex(RecordDecl *Anon);
// If ErrorOnTagTypeMismatch is set, return the error, otherwise get the
// relevant warning for the input error diagnostic.
unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic);
private:
/// Finish checking all of the structural equivalences.
///
/// \returns true if the equivalence check failed (non-equivalence detected),
/// false if equivalence was detected.
bool Finish();
/// Check for common properties at Finish.
/// \returns true if D1 and D2 may be equivalent,
/// false if they are for sure not.
bool CheckCommonEquivalence(Decl *D1, Decl *D2);
/// Check for class dependent properties at Finish.
/// \returns true if D1 and D2 may be equivalent,
/// false if they are for sure not.
bool CheckKindSpecificEquivalence(Decl *D1, Decl *D2);
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H

View File

@ -0,0 +1,614 @@
//===--- ASTTypeTraits.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
//
//===----------------------------------------------------------------------===//
//
// Provides a dynamic type identifier and a dynamically typed node container
// that can be used to store an AST base node at runtime in the same storage in
// a type safe way.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
#define LLVM_CLANG_AST_ASTTYPETRAITS_H
#include "clang/AST/ASTFwd.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/AlignOf.h"
namespace llvm {
class raw_ostream;
} // namespace llvm
namespace clang {
struct PrintingPolicy;
/// Defines how we descend a level in the AST when we pass
/// through expressions.
enum TraversalKind {
/// Will traverse all child nodes.
TK_AsIs,
/// Ignore AST nodes not written in the source
TK_IgnoreUnlessSpelledInSource
};
/// Kind identifier.
///
/// It can be constructed from any node kind and allows for runtime type
/// hierarchy checks.
/// Use getFromNodeKind<T>() to construct them.
class ASTNodeKind {
public:
/// Empty identifier. It matches nothing.
constexpr ASTNodeKind() : KindId(NKI_None) {}
/// Construct an identifier for T.
template <class T> static constexpr ASTNodeKind getFromNodeKind() {
return ASTNodeKind(KindToKindId<T>::Id);
}
/// \{
/// Construct an identifier for the dynamic type of the node
static ASTNodeKind getFromNode(const Decl &D);
static ASTNodeKind getFromNode(const Stmt &S);
static ASTNodeKind getFromNode(const Type &T);
static ASTNodeKind getFromNode(const TypeLoc &T);
static ASTNodeKind getFromNode(const LambdaCapture &L);
static ASTNodeKind getFromNode(const OMPClause &C);
static ASTNodeKind getFromNode(const Attr &A);
/// \}
/// Returns \c true if \c this and \c Other represent the same kind.
constexpr bool isSame(ASTNodeKind Other) const {
return KindId != NKI_None && KindId == Other.KindId;
}
/// Returns \c true only for the default \c ASTNodeKind()
constexpr bool isNone() const { return KindId == NKI_None; }
/// Returns \c true if \c this is a base kind of (or same as) \c Other.
bool isBaseOf(ASTNodeKind Other) const;
/// Returns \c true if \c this is a base kind of (or same as) \c Other.
/// \param Distance If non-null, used to return the distance between \c this
/// and \c Other in the class hierarchy.
bool isBaseOf(ASTNodeKind Other, unsigned *Distance) const;
/// String representation of the kind.
StringRef asStringRef() const;
/// Strict weak ordering for ASTNodeKind.
constexpr bool operator<(const ASTNodeKind &Other) const {
return KindId < Other.KindId;
}
/// Return the most derived type between \p Kind1 and \p Kind2.
///
/// Return ASTNodeKind() if they are not related.
static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
/// Return the most derived common ancestor between Kind1 and Kind2.
///
/// Return ASTNodeKind() if they are not related.
static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
ASTNodeKind Kind2);
ASTNodeKind getCladeKind() const;
/// Hooks for using ASTNodeKind as a key in a DenseMap.
struct DenseMapInfo {
// ASTNodeKind() is a good empty key because it is represented as a 0.
static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
// NKI_NumberOfKinds is not a valid value, so it is good for a
// tombstone key.
static inline ASTNodeKind getTombstoneKey() {
return ASTNodeKind(NKI_NumberOfKinds);
}
static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
return LHS.KindId == RHS.KindId;
}
};
/// Check if the given ASTNodeKind identifies a type that offers pointer
/// identity. This is useful for the fast path in DynTypedNode.
constexpr bool hasPointerIdentity() const {
return KindId > NKI_LastKindWithoutPointerIdentity;
}
private:
/// Kind ids.
///
/// Includes all possible base and derived kinds.
enum NodeKindId {
NKI_None,
NKI_TemplateArgument,
NKI_TemplateArgumentLoc,
NKI_LambdaCapture,
NKI_TemplateName,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
#include "clang/AST/TypeLocNodes.def"
NKI_TypeLoc,
NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
NKI_CXXBaseSpecifier,
NKI_CXXCtorInitializer,
NKI_NestedNameSpecifier,
NKI_Decl,
#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
#include "clang/AST/DeclNodes.inc"
NKI_Stmt,
#define STMT(DERIVED, BASE) NKI_##DERIVED,
#include "clang/AST/StmtNodes.inc"
NKI_Type,
#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
#include "clang/AST/TypeNodes.inc"
NKI_OMPClause,
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) NKI_##Class,
#include "llvm/Frontend/OpenMP/OMP.inc"
NKI_Attr,
#define ATTR(A) NKI_##A##Attr,
#include "clang/Basic/AttrList.inc"
NKI_ObjCProtocolLoc,
NKI_ConceptReference,
NKI_NumberOfKinds
};
/// Use getFromNodeKind<T>() to construct the kind.
constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
/// Returns \c true if \c Base is a base kind of (or same as) \c
/// Derived.
static bool isBaseOf(NodeKindId Base, NodeKindId Derived);
/// Returns \c true if \c Base is a base kind of (or same as) \c
/// Derived.
/// \param Distance If non-null, used to return the distance between \c Base
/// and \c Derived in the class hierarchy.
static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
/// Helper meta-function to convert a kind T to its enum value.
///
/// This struct is specialized below for all known kinds.
template <class T> struct KindToKindId {
static const NodeKindId Id = NKI_None;
};
template <class T>
struct KindToKindId<const T> : KindToKindId<T> {};
/// Per kind info.
struct KindInfo {
/// The id of the parent kind, or None if it has no parent.
NodeKindId ParentId;
/// Name of the kind.
const char *Name;
};
static const KindInfo AllKindInfo[NKI_NumberOfKinds];
NodeKindId KindId;
};
#define KIND_TO_KIND_ID(Class) \
template <> struct ASTNodeKind::KindToKindId<Class> { \
static const NodeKindId Id = NKI_##Class; \
};
KIND_TO_KIND_ID(CXXCtorInitializer)
KIND_TO_KIND_ID(TemplateArgument)
KIND_TO_KIND_ID(TemplateArgumentLoc)
KIND_TO_KIND_ID(LambdaCapture)
KIND_TO_KIND_ID(TemplateName)
KIND_TO_KIND_ID(NestedNameSpecifier)
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
KIND_TO_KIND_ID(QualType)
#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
#include "clang/AST/TypeLocNodes.def"
KIND_TO_KIND_ID(TypeLoc)
KIND_TO_KIND_ID(Decl)
KIND_TO_KIND_ID(Stmt)
KIND_TO_KIND_ID(Type)
KIND_TO_KIND_ID(OMPClause)
KIND_TO_KIND_ID(Attr)
KIND_TO_KIND_ID(ObjCProtocolLoc)
KIND_TO_KIND_ID(CXXBaseSpecifier)
KIND_TO_KIND_ID(ConceptReference)
#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
#include "clang/AST/DeclNodes.inc"
#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
#include "clang/AST/StmtNodes.inc"
#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
#include "clang/AST/TypeNodes.inc"
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class)
#include "llvm/Frontend/OpenMP/OMP.inc"
#define ATTR(A) KIND_TO_KIND_ID(A##Attr)
#include "clang/Basic/AttrList.inc"
#undef KIND_TO_KIND_ID
inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
OS << K.asStringRef();
return OS;
}
/// A dynamically typed AST node container.
///
/// Stores an AST node in a type safe way. This allows writing code that
/// works with different kinds of AST nodes, despite the fact that they don't
/// have a common base class.
///
/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
/// and \c get<T>() to retrieve the node as type T if the types match.
///
/// See \c ASTNodeKind for which node base types are currently supported;
/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
/// the supported base types.
class DynTypedNode {
public:
/// Creates a \c DynTypedNode from \c Node.
template <typename T>
static DynTypedNode create(const T &Node) {
return BaseConverter<T>::create(Node);
}
/// Retrieve the stored node as type \c T.
///
/// Returns NULL if the stored node does not have a type that is
/// convertible to \c T.
///
/// For types that have identity via their pointer in the AST
/// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
/// pointer points to the referenced AST node.
/// For other types (like \c QualType) the value is stored directly
/// in the \c DynTypedNode, and the returned pointer points at
/// the storage inside DynTypedNode. For those nodes, do not
/// use the pointer outside the scope of the DynTypedNode.
template <typename T> const T *get() const {
return BaseConverter<T>::get(NodeKind, &Storage);
}
/// Retrieve the stored node as type \c T.
///
/// Similar to \c get(), but asserts that the type is what we are expecting.
template <typename T>
const T &getUnchecked() const {
return BaseConverter<T>::getUnchecked(NodeKind, &Storage);
}
ASTNodeKind getNodeKind() const { return NodeKind; }
/// Returns a pointer that identifies the stored AST node.
///
/// Note that this is not supported by all AST nodes. For AST nodes
/// that don't have a pointer-defined identity inside the AST, this
/// method returns NULL.
const void *getMemoizationData() const {
return NodeKind.hasPointerIdentity()
? *reinterpret_cast<void *const *>(&Storage)
: nullptr;
}
/// Prints the node to the given output stream.
void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
/// Dumps the node to the given output stream.
void dump(llvm::raw_ostream &OS, const ASTContext &Context) const;
/// For nodes which represent textual entities in the source code,
/// return their SourceRange. For all other nodes, return SourceRange().
SourceRange getSourceRange(bool IncludeQualifier = false) const;
/// @{
/// Imposes an order on \c DynTypedNode.
///
/// Supports comparison of nodes that support memoization.
/// FIXME: Implement comparison for other node types (currently
/// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
bool operator<(const DynTypedNode &Other) const {
if (!NodeKind.isSame(Other.NodeKind))
return NodeKind < Other.NodeKind;
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>().getAsOpaquePtr() <
Other.getUnchecked<QualType>().getAsOpaquePtr();
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) {
auto TLA = getUnchecked<TypeLoc>();
auto TLB = Other.getUnchecked<TypeLoc>();
return std::make_pair(TLA.getType().getAsOpaquePtr(),
TLA.getOpaqueData()) <
std::make_pair(TLB.getType().getAsOpaquePtr(),
TLB.getOpaqueData());
}
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
NodeKind)) {
auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
return std::make_pair(NNSLA.getNestedNameSpecifier().getAsVoidPointer(),
NNSLA.getOpaqueData()) <
std::make_pair(NNSLB.getNestedNameSpecifier().getAsVoidPointer(),
NNSLB.getOpaqueData());
}
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() < Other.getMemoizationData();
}
bool operator==(const DynTypedNode &Other) const {
// DynTypedNode::create() stores the exact kind of the node in NodeKind.
// If they contain the same node, their NodeKind must be the same.
if (!NodeKind.isSame(Other.NodeKind))
return false;
// FIXME: Implement for other types.
if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind))
return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
return getUnchecked<NestedNameSpecifierLoc>() ==
Other.getUnchecked<NestedNameSpecifierLoc>();
assert(getMemoizationData() && Other.getMemoizationData());
return getMemoizationData() == Other.getMemoizationData();
}
bool operator!=(const DynTypedNode &Other) const {
return !operator==(Other);
}
/// @}
/// Hooks for using DynTypedNode as a key in a DenseMap.
struct DenseMapInfo {
static inline DynTypedNode getEmptyKey() {
DynTypedNode Node;
Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
return Node;
}
static inline DynTypedNode getTombstoneKey() {
DynTypedNode Node;
Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
return Node;
}
static unsigned getHashValue(const DynTypedNode &Val) {
// FIXME: Add hashing support for the remaining types.
if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(Val.NodeKind)) {
auto TL = Val.getUnchecked<TypeLoc>();
return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
TL.getOpaqueData());
}
if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
Val.NodeKind)) {
auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
return llvm::hash_combine(
NNSL.getNestedNameSpecifier().getAsVoidPointer(),
NNSL.getOpaqueData());
}
assert(Val.getMemoizationData());
return llvm::hash_value(Val.getMemoizationData());
}
static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
(ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
LHS == RHS;
}
};
private:
/// Takes care of converting from and to \c T.
template <typename T, typename EnablerT = void> struct BaseConverter;
/// Converter that uses dyn_cast<T> from a stored BaseT*.
template <typename T, typename BaseT> struct DynCastPtrConverter {
static const T *get(ASTNodeKind NodeKind, const void *Storage) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
return *cast<T>(static_cast<const BaseT *>(
*reinterpret_cast<const void *const *>(Storage)));
}
static DynTypedNode create(const BaseT &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
new (&Result.Storage) const void *(&Node);
return Result;
}
};
/// Converter that stores T* (by pointer).
template <typename T> struct PtrConverter {
static const T *get(ASTNodeKind NodeKind, const void *Storage) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
return *static_cast<const T *>(
*reinterpret_cast<const void *const *>(Storage));
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
new (&Result.Storage) const void *(&Node);
return Result;
}
};
/// Converter that stores T (by value).
template <typename T> struct ValueConverter {
static const T *get(ASTNodeKind NodeKind, const void *Storage) {
if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
return reinterpret_cast<const T *>(Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
return *reinterpret_cast<const T *>(Storage);
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
new (&Result.Storage) T(Node);
return Result;
}
};
/// Converter that stores nodes by value. It must be possible to dynamically
/// cast the stored node within a type hierarchy without breaking (especially
/// through slicing).
template <typename T, typename BaseT,
typename = std::enable_if_t<(sizeof(T) == sizeof(BaseT))>>
struct DynCastValueConverter {
static const T *get(ASTNodeKind NodeKind, const void *Storage) {
if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
return &getUnchecked(NodeKind, Storage);
return nullptr;
}
static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
return *static_cast<const T *>(reinterpret_cast<const BaseT *>(Storage));
}
static DynTypedNode create(const T &Node) {
DynTypedNode Result;
Result.NodeKind = ASTNodeKind::getFromNode(Node);
new (&Result.Storage) T(Node);
return Result;
}
};
ASTNodeKind NodeKind;
/// Stores the data of the node.
///
/// Note that we can store \c Decls, \c Stmts, \c Types,
/// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
/// guaranteed to be unique pointers pointing to dedicated storage in the AST.
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
/// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
/// have storage or unique pointers and thus need to be stored by value.
llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
TemplateArgumentLoc, NestedNameSpecifierLoc,
QualType, TypeLoc, ObjCProtocolLoc>
Storage;
};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<Decl, T>::value>>
: public DynCastPtrConverter<T, Decl> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<Stmt, T>::value>>
: public DynCastPtrConverter<T, Stmt> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<Type, T>::value>>
: public DynCastPtrConverter<T, Type> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>>
: public DynCastPtrConverter<T, OMPClause> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<Attr, T>::value>>
: public DynCastPtrConverter<T, Attr> {};
template <>
struct DynTypedNode::BaseConverter<NestedNameSpecifier, void>
: public ValueConverter<NestedNameSpecifier> {};
template <>
struct DynTypedNode::BaseConverter<
CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
template <>
struct DynTypedNode::BaseConverter<
TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
template <>
struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
: public ValueConverter<TemplateArgumentLoc> {};
template <>
struct DynTypedNode::BaseConverter<LambdaCapture, void>
: public ValueConverter<LambdaCapture> {};
template <>
struct DynTypedNode::BaseConverter<
TemplateName, void> : public ValueConverter<TemplateName> {};
template <>
struct DynTypedNode::BaseConverter<
NestedNameSpecifierLoc,
void> : public ValueConverter<NestedNameSpecifierLoc> {};
template <>
struct DynTypedNode::BaseConverter<QualType,
void> : public ValueConverter<QualType> {};
template <typename T>
struct DynTypedNode::BaseConverter<
T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>>
: public DynCastValueConverter<T, TypeLoc> {};
template <>
struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
: public PtrConverter<CXXBaseSpecifier> {};
template <>
struct DynTypedNode::BaseConverter<ObjCProtocolLoc, void>
: public ValueConverter<ObjCProtocolLoc> {};
template <>
struct DynTypedNode::BaseConverter<ConceptReference, void>
: public PtrConverter<ConceptReference> {};
// The only operation we allow on unsupported types is \c get.
// This allows to conveniently use \c DynTypedNode when having an arbitrary
// AST node that is not supported, but prevents misuse - a user cannot create
// a DynTypedNode from arbitrary types.
template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
return NULL;
}
};
} // end namespace clang
namespace llvm {
template <>
struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {};
template <>
struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {};
} // end namespace llvm
#endif

View File

@ -0,0 +1,126 @@
//===- ASTUnresolvedSet.h - Unresolved sets of declarations -----*- 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 provides an UnresolvedSet-like class, whose contents are
// allocated using the allocator associated with an ASTContext.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
#define LLVM_CLANG_AST_ASTUNRESOLVEDSET_H
#include "clang/AST/ASTVector.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclID.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/Specifiers.h"
#include <cassert>
#include <cstdint>
namespace clang {
class NamedDecl;
/// An UnresolvedSet-like class which uses the ASTContext's allocator.
class ASTUnresolvedSet {
friend class LazyASTUnresolvedSet;
struct DeclsTy : ASTVector<DeclAccessPair> {
DeclsTy() = default;
DeclsTy(ASTContext &C, unsigned N) : ASTVector<DeclAccessPair>(C, N) {}
bool isLazy() const { return getTag(); }
void setLazy(bool Lazy) { setTag(Lazy); }
};
DeclsTy Decls;
public:
ASTUnresolvedSet() = default;
ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {}
using iterator = UnresolvedSetIterator;
using const_iterator = UnresolvedSetIterator;
iterator begin() { return iterator(Decls.begin()); }
iterator end() { return iterator(Decls.end()); }
const_iterator begin() const { return const_iterator(Decls.begin()); }
const_iterator end() const { return const_iterator(Decls.end()); }
void addDecl(ASTContext &C, NamedDecl *D, AccessSpecifier AS) {
Decls.push_back(DeclAccessPair::make(D, AS), C);
}
void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
Decls.push_back(DeclAccessPair::makeLazy(ID.getRawValue(), AS), C);
}
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) {
for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
if (I->getDecl() == Old) {
I->set(New, AS);
return true;
}
}
return false;
}
void erase(unsigned I) {
if (I == Decls.size() - 1)
Decls.pop_back();
else
Decls[I] = Decls.pop_back_val();
}
void clear() { Decls.clear(); }
bool empty() const { return Decls.empty(); }
unsigned size() const { return Decls.size(); }
void reserve(ASTContext &C, unsigned N) {
Decls.reserve(C, N);
}
void append(ASTContext &C, iterator I, iterator E) {
Decls.append(C, I.I, E.I);
}
DeclAccessPair &operator[](unsigned I) { return Decls[I]; }
const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; }
};
/// An UnresolvedSet-like class that might not have been loaded from the
/// external AST source yet.
class LazyASTUnresolvedSet {
mutable ASTUnresolvedSet Impl;
void getFromExternalSource(ASTContext &C) const;
public:
ASTUnresolvedSet &get(ASTContext &C) const {
if (Impl.Decls.isLazy())
getFromExternalSource(C);
return Impl;
}
void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }
void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
assert(Impl.empty() || Impl.Decls.isLazy());
Impl.Decls.setLazy(true);
Impl.addLazyDecl(C, ID, AS);
}
};
} // namespace clang
#endif // LLVM_CLANG_AST_ASTUNRESOLVEDSET_H

View File

@ -0,0 +1,410 @@
//===- ASTVector.h - Vector that uses ASTContext for allocation ---*- 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 provides ASTVector, a vector ADT whose contents are
// allocated using the allocator associated with an ASTContext..
//
//===----------------------------------------------------------------------===//
// FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
// We can refactor this core logic into something common.
#ifndef LLVM_CLANG_AST_ASTVECTOR_H
#define LLVM_CLANG_AST_ASTVECTOR_H
#include "clang/AST/ASTContextAllocate.h"
#include "llvm/ADT/PointerIntPair.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
namespace clang {
class ASTContext;
template<typename T>
class ASTVector {
private:
T *Begin = nullptr;
T *End = nullptr;
llvm::PointerIntPair<T *, 1, bool> Capacity;
void setEnd(T *P) { this->End = P; }
protected:
// Make a tag bit available to users of this class.
// FIXME: This is a horrible hack.
bool getTag() const { return Capacity.getInt(); }
void setTag(bool B) { Capacity.setInt(B); }
public:
// Default ctor - Initialize to empty.
ASTVector() : Capacity(nullptr, false) {}
ASTVector(ASTVector &&O) : Begin(O.Begin), End(O.End), Capacity(O.Capacity) {
O.Begin = O.End = nullptr;
O.Capacity.setPointer(nullptr);
O.Capacity.setInt(false);
}
ASTVector(const ASTContext &C, unsigned N) : Capacity(nullptr, false) {
reserve(C, N);
}
ASTVector &operator=(ASTVector &&RHS) {
ASTVector O(std::move(RHS));
using std::swap;
swap(Begin, O.Begin);
swap(End, O.End);
swap(Capacity, O.Capacity);
return *this;
}
~ASTVector() {
if (std::is_class<T>::value) {
// Destroy the constructed elements in the vector.
destroy_range(Begin, End);
}
}
using size_type = size_t;
using difference_type = ptrdiff_t;
using value_type = T;
using iterator = T *;
using const_iterator = const T *;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = std::reverse_iterator<iterator>;
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
// forward iterator creation methods.
iterator begin() { return Begin; }
const_iterator begin() const { return Begin; }
iterator end() { return End; }
const_iterator end() const { return End; }
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
bool empty() const { return Begin == End; }
size_type size() const { return End-Begin; }
reference operator[](unsigned idx) {
assert(Begin + idx < End);
return Begin[idx];
}
const_reference operator[](unsigned idx) const {
assert(Begin + idx < End);
return Begin[idx];
}
reference front() {
return begin()[0];
}
const_reference front() const {
return begin()[0];
}
reference back() {
return end()[-1];
}
const_reference back() const {
return end()[-1];
}
void pop_back() {
--End;
End->~T();
}
T pop_back_val() {
T Result = back();
pop_back();
return Result;
}
void clear() {
if (std::is_class<T>::value) {
destroy_range(Begin, End);
}
End = Begin;
}
/// data - Return a pointer to the vector's buffer, even if empty().
pointer data() {
return pointer(Begin);
}
/// data - Return a pointer to the vector's buffer, even if empty().
const_pointer data() const {
return const_pointer(Begin);
}
void push_back(const_reference Elt, const ASTContext &C) {
if (End < this->capacity_ptr()) {
Retry:
new (End) T(Elt);
++End;
return;
}
grow(C);
goto Retry;
}
void reserve(const ASTContext &C, unsigned N) {
if (unsigned(this->capacity_ptr()-Begin) < N)
grow(C, N);
}
/// capacity - Return the total number of elements in the currently allocated
/// buffer.
size_t capacity() const { return this->capacity_ptr() - Begin; }
/// append - Add the specified range to the end of the SmallVector.
template<typename in_iter>
void append(const ASTContext &C, in_iter in_start, in_iter in_end) {
size_type NumInputs = std::distance(in_start, in_end);
if (NumInputs == 0)
return;
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
this->grow(C, this->size()+NumInputs);
// Copy the new elements over.
// TODO: NEED To compile time dispatch on whether in_iter is a random access
// iterator to use the fast uninitialized_copy.
std::uninitialized_copy(in_start, in_end, this->end());
this->setEnd(this->end() + NumInputs);
}
/// append - Add the specified range to the end of the SmallVector.
void append(const ASTContext &C, size_type NumInputs, const T &Elt) {
// Grow allocated space if needed.
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
this->grow(C, this->size()+NumInputs);
// Copy the new elements over.
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
this->setEnd(this->end() + NumInputs);
}
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
/// starting with "Dest", constructing elements into it as needed.
template<typename It1, typename It2>
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
std::uninitialized_copy(I, E, Dest);
}
iterator insert(const ASTContext &C, iterator I, const T &Elt) {
if (I == this->end()) { // Important special case for empty vector.
push_back(Elt, C);
return this->end()-1;
}
if (this->End < this->capacity_ptr()) {
Retry:
new (this->end()) T(this->back());
this->setEnd(this->end()+1);
// Push everything else over.
std::copy_backward(I, this->end()-1, this->end());
*I = Elt;
return I;
}
size_t EltNo = I-this->begin();
this->grow(C);
I = this->begin()+EltNo;
goto Retry;
}
iterator insert(const ASTContext &C, iterator I, size_type NumToInsert,
const T &Elt) {
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
if (I == this->end()) { // Important special case for empty vector.
append(C, NumToInsert, Elt);
return this->begin() + InsertElt;
}
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
// If there are more elements between the insertion point and the end of the
// range than there are being inserted, we can use a simple approach to
// insertion. Since we already reserved space, we know that this won't
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(C, this->end()-NumToInsert, this->end());
// Copy the existing elements that get replaced.
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
std::fill_n(I, NumToInsert, Elt);
return I;
}
// Otherwise, we're inserting more elements than exist already, and we're
// not inserting at the end.
// Copy over the elements that we're about to overwrite.
T *OldEnd = this->end();
this->setEnd(this->end() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
// Replace the overwritten part.
std::fill_n(I, NumOverwritten, Elt);
// Insert the non-overwritten middle part.
std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
return I;
}
template<typename ItTy>
iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) {
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
size_t InsertElt = I - this->begin();
if (I == this->end()) { // Important special case for empty vector.
append(C, From, To);
return this->begin() + InsertElt;
}
size_t NumToInsert = std::distance(From, To);
// Ensure there is enough space.
reserve(C, static_cast<unsigned>(this->size() + NumToInsert));
// Uninvalidate the iterator.
I = this->begin()+InsertElt;
// If there are more elements between the insertion point and the end of the
// range than there are being inserted, we can use a simple approach to
// insertion. Since we already reserved space, we know that this won't
// reallocate the vector.
if (size_t(this->end()-I) >= NumToInsert) {
T *OldEnd = this->end();
append(C, this->end()-NumToInsert, this->end());
// Copy the existing elements that get replaced.
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
std::copy(From, To, I);
return I;
}
// Otherwise, we're inserting more elements than exist already, and we're
// not inserting at the end.
// Copy over the elements that we're about to overwrite.
T *OldEnd = this->end();
this->setEnd(this->end() + NumToInsert);
size_t NumOverwritten = OldEnd-I;
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
// Replace the overwritten part.
for (; NumOverwritten > 0; --NumOverwritten) {
*I = *From;
++I; ++From;
}
// Insert the non-overwritten middle part.
this->uninitialized_copy(From, To, OldEnd);
return I;
}
void resize(const ASTContext &C, unsigned N, const T &NV) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->setEnd(this->begin()+N);
} else if (N > this->size()) {
if (this->capacity() < N)
this->grow(C, N);
construct_range(this->end(), this->begin()+N, NV);
this->setEnd(this->begin()+N);
}
}
private:
/// grow - double the size of the allocated memory, guaranteeing space for at
/// least one more element or MinSize if specified.
void grow(const ASTContext &C, size_type MinSize = 1);
void construct_range(T *S, T *E, const T &Elt) {
for (; S != E; ++S)
new (S) T(Elt);
}
void destroy_range(T *S, T *E) {
while (S != E) {
--E;
E->~T();
}
}
protected:
const_iterator capacity_ptr() const {
return (iterator) Capacity.getPointer();
}
iterator capacity_ptr() { return (iterator)Capacity.getPointer(); }
};
// Define this out-of-line to dissuade the C++ compiler from inlining it.
template <typename T>
void ASTVector<T>::grow(const ASTContext &C, size_t MinSize) {
size_t CurCapacity = this->capacity();
size_t CurSize = size();
size_t NewCapacity = 2*CurCapacity;
if (NewCapacity < MinSize)
NewCapacity = MinSize;
// Allocate the memory from the ASTContext.
T *NewElts = new (C, alignof(T)) T[NewCapacity];
// Copy the elements over.
if (Begin != End) {
if (std::is_class<T>::value) {
std::uninitialized_copy(Begin, End, NewElts);
// Destroy the original elements.
destroy_range(Begin, End);
} else {
// Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
memcpy(NewElts, Begin, CurSize * sizeof(T));
}
}
// ASTContext never frees any memory.
Begin = NewElts;
End = NewElts+CurSize;
Capacity.setPointer(Begin+NewCapacity);
}
} // namespace clang
#endif // LLVM_CLANG_AST_ASTVECTOR_H

View File

@ -0,0 +1,294 @@
//==--- AbstractBasicReader.h - Abstract basic value deserialization -----===//
//
// 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_AST_ABSTRACTBASICREADER_H
#define LLVM_CLANG_AST_ABSTRACTBASICREADER_H
#include "clang/AST/DeclTemplate.h"
#include <optional>
namespace clang {
namespace serialization {
template <class T>
inline T makeNullableFromOptional(const std::optional<T> &value) {
return (value ? *value : T());
}
template <class T> inline T *makePointerFromOptional(std::optional<T *> value) {
return value.value_or(nullptr);
}
// PropertyReader is a class concept that requires the following method:
// BasicReader find(llvm::StringRef propertyName);
// where BasicReader is some class conforming to the BasicReader concept.
// An abstract AST-node reader is created with a PropertyReader and
// performs a sequence of calls like so:
// propertyReader.find(propertyName).read##TypeName()
// to read the properties of the node it is deserializing.
// BasicReader is a class concept that requires methods like:
// ValueType read##TypeName();
// where TypeName is the name of a PropertyType node from PropertiesBase.td
// and ValueType is the corresponding C++ type name. The read method may
// require one or more buffer arguments.
//
// In addition to the concrete type names, BasicReader is expected to
// implement these methods:
//
// template <class EnumType>
// void writeEnum(T value);
//
// Reads an enum value from the current property. EnumType will always
// be an enum type. Only necessary if the BasicReader doesn't provide
// type-specific readers for all the enum types.
//
// template <class ValueType>
// std::optional<ValueType> writeOptional();
//
// Reads an optional value from the current property.
//
// template <class ValueType>
// ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer);
//
// Reads an array of values from the current property.
//
// PropertyReader readObject();
//
// Reads an object from the current property; the returned property
// reader will be subjected to a sequence of property reads and then
// discarded before any other properties are reader from the "outer"
// property reader (which need not be the same type). The sub-reader
// will be used as if with the following code:
//
// {
// auto &&widget = W.find("widget").readObject();
// auto kind = widget.find("kind").readWidgetKind();
// auto declaration = widget.find("declaration").readDeclRef();
// return Widget(kind, declaration);
// }
// ReadDispatcher does type-based forwarding to one of the read methods
// on the BasicReader passed in:
//
// template <class ValueType>
// struct ReadDispatcher {
// template <class BasicReader, class... BufferTypes>
// static ValueType read(BasicReader &R, BufferTypes &&...);
// };
// BasicReaderBase provides convenience implementations of the read methods
// for EnumPropertyType and SubclassPropertyType types that just defer to
// the "underlying" implementations (for UInt32 and the base class,
// respectively).
//
// template <class Impl>
// class BasicReaderBase {
// protected:
// BasicReaderBase(ASTContext &ctx);
// Impl &asImpl();
// public:
// ASTContext &getASTContext();
// ...
// };
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
#include "clang/AST/AbstractBasicReader.inc"
/// DataStreamBasicReader provides convenience implementations for many
/// BasicReader methods based on the assumption that the
/// ultimate reader implementation is based on a variable-length stream
/// of unstructured data (like Clang's module files). It is designed
/// to pair with DataStreamBasicWriter.
///
/// This class can also act as a PropertyReader, implementing find("...")
/// by simply forwarding to itself.
///
/// Unimplemented methods:
/// readBool
/// readUInt32
/// readUInt64
/// readIdentifier
/// readSelector
/// readSourceLocation
/// readQualType
/// readStmtRef
/// readDeclRef
template <class Impl>
class DataStreamBasicReader : public BasicReaderBase<Impl> {
protected:
using BasicReaderBase<Impl>::asImpl;
DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}
public:
using BasicReaderBase<Impl>::getASTContext;
/// Implement property-find by ignoring it. We rely on properties being
/// serialized and deserialized in a reliable order instead.
Impl &find(const char *propertyName) {
return asImpl();
}
template <class T>
T readEnum() {
return T(asImpl().readUInt32());
}
// Implement object reading by forwarding to this, collapsing the
// structure into a single data stream.
Impl &readObject() { return asImpl(); }
template <class T> ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
assert(buffer.empty());
uint32_t size = asImpl().readUInt32();
buffer.reserve(size);
for (uint32_t i = 0; i != size; ++i) {
buffer.push_back(ReadDispatcher<T>::read(asImpl()));
}
return buffer;
}
template <class T, class... Args>
std::optional<T> readOptional(Args &&...args) {
return UnpackOptionalValue<T>::unpack(
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
}
llvm::APSInt readAPSInt() {
bool isUnsigned = asImpl().readBool();
llvm::APInt value = asImpl().readAPInt();
return llvm::APSInt(std::move(value), isUnsigned);
}
llvm::APInt readAPInt() {
unsigned bitWidth = asImpl().readUInt32();
unsigned numWords = llvm::APInt::getNumWords(bitWidth);
llvm::SmallVector<uint64_t, 4> data;
for (uint32_t i = 0; i != numWords; ++i)
data.push_back(asImpl().readUInt64());
return llvm::APInt(bitWidth, data);
}
llvm::FixedPointSemantics readFixedPointSemantics() {
unsigned width = asImpl().readUInt32();
unsigned scale = asImpl().readUInt32();
unsigned tmp = asImpl().readUInt32();
bool isSigned = tmp & 0x1;
bool isSaturated = tmp & 0x2;
bool hasUnsignedPadding = tmp & 0x4;
return llvm::FixedPointSemantics(width, scale, isSigned, isSaturated,
hasUnsignedPadding);
}
APValue::LValuePathSerializationHelper readLValuePathSerializationHelper(
SmallVectorImpl<APValue::LValuePathEntry> &path) {
auto origTy = asImpl().readQualType();
auto elemTy = origTy;
unsigned pathLength = asImpl().readUInt32();
for (unsigned i = 0; i < pathLength; ++i) {
if (elemTy->isRecordType()) {
unsigned int_ = asImpl().readUInt32();
Decl *decl = asImpl().template readDeclAs<Decl>();
if (auto *recordDecl = dyn_cast<CXXRecordDecl>(decl))
elemTy = getASTContext().getCanonicalTagType(recordDecl);
else
elemTy = cast<ValueDecl>(decl)->getType();
path.push_back(
APValue::LValuePathEntry(APValue::BaseOrMemberType(decl, int_)));
} else {
elemTy = getASTContext().getAsArrayType(elemTy)->getElementType();
path.push_back(
APValue::LValuePathEntry::ArrayIndex(asImpl().readUInt32()));
}
}
return APValue::LValuePathSerializationHelper(path, origTy);
}
Qualifiers readQualifiers() {
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes");
uint64_t value = asImpl().readUInt64();
return Qualifiers::fromOpaqueValue(value);
}
FunctionProtoType::ExceptionSpecInfo
readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
FunctionProtoType::ExceptionSpecInfo esi;
esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
if (esi.Type == EST_Dynamic) {
esi.Exceptions = asImpl().template readArray<QualType>(buffer);
} else if (isComputedNoexcept(esi.Type)) {
esi.NoexceptExpr = asImpl().readExprRef();
} else if (esi.Type == EST_Uninstantiated) {
esi.SourceDecl = asImpl().readFunctionDeclRef();
esi.SourceTemplate = asImpl().readFunctionDeclRef();
} else if (esi.Type == EST_Unevaluated) {
esi.SourceDecl = asImpl().readFunctionDeclRef();
}
return esi;
}
FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
<= sizeof(uint32_t),
"opaque value doesn't fit into uint32_t");
uint32_t value = asImpl().readUInt32();
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
}
FunctionEffect readFunctionEffect() {
uint32_t value = asImpl().readUInt32();
return FunctionEffect::fromOpaqueInt32(value);
}
EffectConditionExpr readEffectConditionExpr() {
return EffectConditionExpr{asImpl().readExprRef()};
}
NestedNameSpecifier readNestedNameSpecifier() {
auto &ctx = getASTContext();
// We build this up iteratively.
NestedNameSpecifier cur = std::nullopt;
uint32_t depth = asImpl().readUInt32();
for (uint32_t i = 0; i != depth; ++i) {
auto kind = asImpl().readNestedNameSpecifierKind();
switch (kind) {
case NestedNameSpecifier::Kind::Namespace:
cur =
NestedNameSpecifier(ctx, asImpl().readNamespaceBaseDeclRef(), cur);
continue;
case NestedNameSpecifier::Kind::Type:
assert(!cur);
cur = NestedNameSpecifier(asImpl().readQualType().getTypePtr());
continue;
case NestedNameSpecifier::Kind::Global:
assert(!cur);
cur = NestedNameSpecifier::getGlobal();
continue;
case NestedNameSpecifier::Kind::MicrosoftSuper:
assert(!cur);
cur = NestedNameSpecifier(asImpl().readCXXRecordDeclRef());
continue;
case NestedNameSpecifier::Kind::Null:
llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("bad nested name specifier kind");
}
return cur;
}
};
} // end namespace serialization
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,278 @@
//==--- AbstractBasicWriter.h - Abstract basic value serialization --------===//
//
// 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_AST_ABSTRACTBASICWRITER_H
#define LLVM_CLANG_AST_ABSTRACTBASICWRITER_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include <optional>
namespace clang {
namespace serialization {
template <class T>
inline std::optional<T> makeOptionalFromNullable(const T &value) {
return (value.isNull() ? std::optional<T>() : std::optional<T>(value));
}
template <class T> inline std::optional<T *> makeOptionalFromPointer(T *value) {
return (value ? std::optional<T *>(value) : std::optional<T *>());
}
// PropertyWriter is a class concept that requires the following method:
// BasicWriter find(llvm::StringRef propertyName);
// where BasicWriter is some class conforming to the BasicWriter concept.
// An abstract AST-node writer is created with a PropertyWriter and
// performs a sequence of calls like so:
// propertyWriter.find(propertyName).write##TypeName(value)
// to write the properties of the node it is serializing.
// BasicWriter is a class concept that requires methods like:
// void write##TypeName(ValueType value);
// where TypeName is the name of a PropertyType node from PropertiesBase.td
// and ValueType is the corresponding C++ type name.
//
// In addition to the concrete property types, BasicWriter is expected
// to implement these methods:
//
// template <class EnumType>
// void writeEnum(T value);
//
// Writes an enum value as the current property. EnumType will always
// be an enum type. Only necessary if the BasicWriter doesn't provide
// type-specific writers for all the enum types.
//
// template <class ValueType>
// void writeOptional(std::optional<ValueType> value);
//
// Writes an optional value as the current property.
//
// template <class ValueType>
// void writeArray(ArrayRef<ValueType> value);
//
// Writes an array of values as the current property.
//
// PropertyWriter writeObject();
//
// Writes an object as the current property; the returned property
// writer will be subjected to a sequence of property writes and then
// discarded before any other properties are written to the "outer"
// property writer (which need not be the same type). The sub-writer
// will be used as if with the following code:
//
// {
// auto &&widget = W.find("widget").writeObject();
// widget.find("kind").writeWidgetKind(...);
// widget.find("declaration").writeDeclRef(...);
// }
// WriteDispatcher is a template which does type-based forwarding to one
// of the write methods of the BasicWriter passed in:
//
// template <class ValueType>
// struct WriteDispatcher {
// template <class BasicWriter>
// static void write(BasicWriter &W, ValueType value);
// };
// BasicWriterBase provides convenience implementations of the write
// methods for EnumPropertyType and SubclassPropertyType types that just
// defer to the "underlying" implementations (for UInt32 and the base class,
// respectively).
//
// template <class Impl>
// class BasicWriterBase {
// protected:
// Impl &asImpl();
// public:
// ...
// };
// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
#include "clang/AST/AbstractBasicWriter.inc"
/// DataStreamBasicWriter provides convenience implementations for many
/// BasicWriter methods based on the assumption that the
/// ultimate writer implementation is based on a variable-length stream
/// of unstructured data (like Clang's module files). It is designed
/// to pair with DataStreamBasicReader.
///
/// This class can also act as a PropertyWriter, implementing find("...")
/// by simply forwarding to itself.
///
/// Unimplemented methods:
/// writeBool
/// writeUInt32
/// writeUInt64
/// writeIdentifier
/// writeSelector
/// writeSourceLocation
/// writeQualType
/// writeStmtRef
/// writeDeclRef
template <class Impl>
class DataStreamBasicWriter : public BasicWriterBase<Impl> {
protected:
using BasicWriterBase<Impl>::asImpl;
DataStreamBasicWriter(ASTContext &ctx) : BasicWriterBase<Impl>(ctx) {}
public:
/// Implement property-find by ignoring it. We rely on properties being
/// serialized and deserialized in a reliable order instead.
Impl &find(const char *propertyName) {
return asImpl();
}
// Implement object writing by forwarding to this, collapsing the
// structure into a single data stream.
Impl &writeObject() { return asImpl(); }
template <class T>
void writeEnum(T value) {
asImpl().writeUInt32(uint32_t(value));
}
template <class T> void writeArray(ArrayRef<T> array) {
asImpl().writeUInt32(array.size());
for (const T &elt : array) {
WriteDispatcher<T>::write(asImpl(), elt);
}
}
template <class T> void writeOptional(std::optional<T> value) {
WriteDispatcher<T>::write(asImpl(), PackOptionalValue<T>::pack(value));
}
void writeAPSInt(const llvm::APSInt &value) {
asImpl().writeBool(value.isUnsigned());
asImpl().writeAPInt(value);
}
void writeAPInt(const llvm::APInt &value) {
asImpl().writeUInt32(value.getBitWidth());
const uint64_t *words = value.getRawData();
for (size_t i = 0, e = value.getNumWords(); i != e; ++i)
asImpl().writeUInt64(words[i]);
}
void writeFixedPointSemantics(const llvm::FixedPointSemantics &sema) {
asImpl().writeUInt32(sema.getWidth());
asImpl().writeUInt32(sema.getScale());
asImpl().writeUInt32(sema.isSigned() | sema.isSaturated() << 1 |
sema.hasUnsignedPadding() << 2);
}
void writeLValuePathSerializationHelper(
APValue::LValuePathSerializationHelper lvaluePath) {
ArrayRef<APValue::LValuePathEntry> path = lvaluePath.Path;
QualType elemTy = lvaluePath.getType();
asImpl().writeQualType(elemTy);
asImpl().writeUInt32(path.size());
auto &ctx = ((BasicWriterBase<Impl> *)this)->getASTContext();
for (auto elem : path) {
if (elemTy->isRecordType()) {
asImpl().writeUInt32(elem.getAsBaseOrMember().getInt());
const Decl *baseOrMember = elem.getAsBaseOrMember().getPointer();
if (const auto *recordDecl = dyn_cast<CXXRecordDecl>(baseOrMember)) {
asImpl().writeDeclRef(recordDecl);
elemTy = ctx.getCanonicalTagType(recordDecl);
} else {
const auto *valueDecl = cast<ValueDecl>(baseOrMember);
asImpl().writeDeclRef(valueDecl);
elemTy = valueDecl->getType();
}
} else {
asImpl().writeUInt32(elem.getAsArrayIndex());
elemTy = ctx.getAsArrayType(elemTy)->getElementType();
}
}
}
void writeQualifiers(Qualifiers value) {
static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes");
asImpl().writeUInt64(value.getAsOpaqueValue());
}
void writeExceptionSpecInfo(
const FunctionProtoType::ExceptionSpecInfo &esi) {
asImpl().writeUInt32(uint32_t(esi.Type));
if (esi.Type == EST_Dynamic) {
asImpl().writeArray(esi.Exceptions);
} else if (isComputedNoexcept(esi.Type)) {
asImpl().writeExprRef(esi.NoexceptExpr);
} else if (esi.Type == EST_Uninstantiated) {
asImpl().writeDeclRef(esi.SourceDecl);
asImpl().writeDeclRef(esi.SourceTemplate);
} else if (esi.Type == EST_Unevaluated) {
asImpl().writeDeclRef(esi.SourceDecl);
}
}
void writeExtParameterInfo(FunctionProtoType::ExtParameterInfo epi) {
static_assert(sizeof(epi.getOpaqueValue()) <= sizeof(uint32_t),
"opaque value doesn't fit into uint32_t");
asImpl().writeUInt32(epi.getOpaqueValue());
}
void writeFunctionEffect(FunctionEffect E) {
asImpl().writeUInt32(E.toOpaqueInt32());
}
void writeEffectConditionExpr(EffectConditionExpr CE) {
asImpl().writeExprRef(CE.getCondition());
}
void writeNestedNameSpecifier(NestedNameSpecifier NNS) {
// Nested name specifiers usually aren't too long. I think that 8 would
// typically accommodate the vast majority.
SmallVector<NestedNameSpecifier, 8> nestedNames;
// Push each of the NNS's onto a stack for serialization in reverse order.
while (NNS) {
nestedNames.push_back(NNS);
NNS = NNS.getKind() == NestedNameSpecifier::Kind::Namespace
? NNS.getAsNamespaceAndPrefix().Prefix
: std::nullopt;
}
asImpl().writeUInt32(nestedNames.size());
while (!nestedNames.empty()) {
NNS = nestedNames.pop_back_val();
NestedNameSpecifier::Kind kind = NNS.getKind();
asImpl().writeNestedNameSpecifierKind(kind);
switch (kind) {
case NestedNameSpecifier::Kind::Namespace:
asImpl().writeNamespaceBaseDeclRef(
NNS.getAsNamespaceAndPrefix().Namespace);
continue;
case NestedNameSpecifier::Kind::Type:
asImpl().writeQualType(QualType(NNS.getAsType(), 0));
continue;
case NestedNameSpecifier::Kind::Global:
// Don't need to write an associated value.
continue;
case NestedNameSpecifier::Kind::MicrosoftSuper:
asImpl().writeDeclRef(NNS.getAsMicrosoftSuper());
continue;
case NestedNameSpecifier::Kind::Null:
llvm_unreachable("unexpected null nested name specifier");
}
llvm_unreachable("bad nested name specifier kind");
}
}
};
} // end namespace serialization
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
//==--- AbstractTypeReader.h - Abstract deserialization for types ---------===//
//
// 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_AST_ABSTRACTTYPEREADER_H
#define LLVM_CLANG_AST_ABSTRACTTYPEREADER_H
#include "clang/AST/AbstractBasicReader.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Type.h"
namespace clang {
namespace serialization {
// template <class PropertyReader>
// class AbstractTypeReader {
// public:
// AbstractTypeReader(PropertyReader &W);
// QualType read(Type::TypeClass kind);
// };
//
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
#include "clang/AST/AbstractTypeReader.inc"
} // end namespace serialization
} // end namespace clang
#endif

View File

@ -0,0 +1,858 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* A CRTP reader for Clang Type nodes *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: TypeProperties.td *|
|* *|
\*===----------------------------------------------------------------------===*/
template <class PropertyReader>
class AbstractTypeReader {
public:
PropertyReader &R;
AbstractTypeReader(PropertyReader &R) : R(R) {}
QualType read(Type::TypeClass kind) {
switch (kind) {
case Type::Adjusted:
return readAdjustedType();
case Type::Decayed:
return readDecayedType();
case Type::ConstantArray:
return readConstantArrayType();
case Type::ArrayParameter:
return readArrayParameterType();
case Type::DependentSizedArray:
return readDependentSizedArrayType();
case Type::IncompleteArray:
return readIncompleteArrayType();
case Type::VariableArray:
return readVariableArrayType();
case Type::Atomic:
return readAtomicType();
case Type::Attributed:
return readAttributedType();
case Type::BTFTagAttributed:
return readBTFTagAttributedType();
case Type::BitInt:
return readBitIntType();
case Type::BlockPointer:
return readBlockPointerType();
case Type::CountAttributed:
return readCountAttributedType();
case Type::Builtin:
return readBuiltinType();
case Type::Complex:
return readComplexType();
case Type::Decltype:
return readDecltypeType();
case Type::Auto:
return readAutoType();
case Type::DeducedTemplateSpecialization:
return readDeducedTemplateSpecializationType();
case Type::DependentAddressSpace:
return readDependentAddressSpaceType();
case Type::DependentBitInt:
return readDependentBitIntType();
case Type::DependentName:
return readDependentNameType();
case Type::DependentSizedExtVector:
return readDependentSizedExtVectorType();
case Type::DependentVector:
return readDependentVectorType();
case Type::FunctionNoProto:
return readFunctionNoProtoType();
case Type::FunctionProto:
return readFunctionProtoType();
case Type::HLSLAttributedResource:
return readHLSLAttributedResourceType();
case Type::HLSLInlineSpirv:
return readHLSLInlineSpirvType();
case Type::MacroQualified:
return readMacroQualifiedType();
case Type::ConstantMatrix:
return readConstantMatrixType();
case Type::DependentSizedMatrix:
return readDependentSizedMatrixType();
case Type::MemberPointer:
return readMemberPointerType();
case Type::ObjCObjectPointer:
return readObjCObjectPointerType();
case Type::ObjCObject:
return readObjCObjectType();
case Type::ObjCInterface:
return readObjCInterfaceType();
case Type::ObjCTypeParam:
return readObjCTypeParamType();
case Type::PackExpansion:
return readPackExpansionType();
case Type::PackIndexing:
return readPackIndexingType();
case Type::Paren:
return readParenType();
case Type::Pipe:
return readPipeType();
case Type::Pointer:
return readPointerType();
case Type::PredefinedSugar:
return readPredefinedSugarType();
case Type::LValueReference:
return readLValueReferenceType();
case Type::RValueReference:
return readRValueReferenceType();
case Type::SubstBuiltinTemplatePack:
return readSubstBuiltinTemplatePackType();
case Type::SubstTemplateTypeParmPack:
return readSubstTemplateTypeParmPackType();
case Type::SubstTemplateTypeParm:
return readSubstTemplateTypeParmType();
case Type::Enum:
return readEnumType();
case Type::InjectedClassName:
return readInjectedClassNameType();
case Type::Record:
return readRecordType();
case Type::TemplateSpecialization:
return readTemplateSpecializationType();
case Type::TemplateTypeParm:
return readTemplateTypeParmType();
case Type::TypeOfExpr:
return readTypeOfExprType();
case Type::TypeOf:
return readTypeOfType();
case Type::Typedef:
return readTypedefType();
case Type::UnaryTransform:
return readUnaryTransformType();
case Type::UnresolvedUsing:
return readUnresolvedUsingType();
case Type::Using:
return readUsingType();
case Type::Vector:
return readVectorType();
case Type::ExtVector:
return readExtVectorType();
}
llvm_unreachable("bad kind");
}
QualType readAdjustedType() {
auto &ctx = R.getASTContext();
QualType originalType = R.find("originalType").readQualType();
QualType adjustedType = R.find("adjustedType").readQualType();
return ctx.getAdjustedType(originalType, adjustedType);
}
QualType readDecayedType() {
auto &ctx = R.getASTContext();
QualType originalType = R.find("originalType").readQualType();
return ctx.getAdjustedParameterType(originalType);
}
QualType readConstantArrayType() {
auto &ctx = R.getASTContext();
llvm::APInt sizeValue = R.find("sizeValue").readAPInt();
Expr* size = R.find("size").readExprRef();
QualType elementType = R.find("elementType").readQualType();
ArraySizeModifier sizeModifier = R.find("sizeModifier").readArraySizeModifier();
Qualifiers indexQualifiers = R.find("indexQualifiers").readQualifiers();
return ctx.getConstantArrayType(elementType, sizeValue, size,
sizeModifier,
indexQualifiers.getCVRQualifiers());
}
QualType readArrayParameterType() {
auto &ctx = R.getASTContext();
llvm::APInt sizeValue = R.find("sizeValue").readAPInt();
Expr* size = R.find("size").readExprRef();
QualType elementType = R.find("elementType").readQualType();
ArraySizeModifier sizeModifier = R.find("sizeModifier").readArraySizeModifier();
Qualifiers indexQualifiers = R.find("indexQualifiers").readQualifiers();
return ctx.getAdjustedParameterType(
ctx.getConstantArrayType(elementType,sizeValue,
size,sizeModifier,
indexQualifiers.getCVRQualifiers()));
}
QualType readDependentSizedArrayType() {
auto &ctx = R.getASTContext();
Expr* size = R.find("size").readExprRef();
QualType elementType = R.find("elementType").readQualType();
ArraySizeModifier sizeModifier = R.find("sizeModifier").readArraySizeModifier();
Qualifiers indexQualifiers = R.find("indexQualifiers").readQualifiers();
return ctx.getDependentSizedArrayType(elementType, size, sizeModifier,
indexQualifiers.getCVRQualifiers());
}
QualType readIncompleteArrayType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
ArraySizeModifier sizeModifier = R.find("sizeModifier").readArraySizeModifier();
Qualifiers indexQualifiers = R.find("indexQualifiers").readQualifiers();
return ctx.getIncompleteArrayType(elementType, sizeModifier,
indexQualifiers.getCVRQualifiers());
}
QualType readVariableArrayType() {
auto &ctx = R.getASTContext();
Expr* size = R.find("size").readExprRef();
QualType elementType = R.find("elementType").readQualType();
ArraySizeModifier sizeModifier = R.find("sizeModifier").readArraySizeModifier();
Qualifiers indexQualifiers = R.find("indexQualifiers").readQualifiers();
return ctx.getVariableArrayType(elementType, size, sizeModifier,
indexQualifiers.getCVRQualifiers());
}
QualType readAtomicType() {
auto &ctx = R.getASTContext();
QualType valueType = R.find("valueType").readQualType();
return ctx.getAtomicType(valueType);
}
QualType readAttributedType() {
auto &ctx = R.getASTContext();
QualType modifiedType = R.find("modifiedType").readQualType();
QualType equivalentType = R.find("equivalentType").readQualType();
attr::Kind attrKind = R.find("attrKind").readAttrKind();
const Attr * attribute = R.find("attribute").readAttr();
return ctx.getAttributedType(attrKind, modifiedType,
equivalentType, attribute);
}
QualType readBTFTagAttributedType() {
auto &ctx = R.getASTContext();
const BTFTypeTagAttr * attr = R.find("attr").readBTFTypeTagAttr();
QualType wrappedType = R.find("wrappedType").readQualType();
return ctx.getBTFTagAttributedType(attr, wrappedType);
}
QualType readBitIntType() {
auto &ctx = R.getASTContext();
bool isUnsigned = R.find("isUnsigned").readBool();
uint32_t numBits = R.find("numBits").readUInt32();
return ctx.getBitIntType(isUnsigned, numBits);
}
QualType readBlockPointerType() {
auto &ctx = R.getASTContext();
QualType pointeeType = R.find("pointeeType").readQualType();
return ctx.getBlockPointerType(pointeeType);
}
QualType readCountAttributedType() {
auto &ctx = R.getASTContext();
QualType WrappedTy = R.find("WrappedTy").readQualType();
Expr* CountExpr = R.find("CountExpr").readExprRef();
bool CountInBytes = R.find("CountInBytes").readBool();
bool OrNull = R.find("OrNull").readBool();
llvm::SmallVector<TypeCoupledDeclRefInfo, 8> CoupledDecls_buffer_0;
llvm::ArrayRef<TypeCoupledDeclRefInfo> CoupledDecls = R.find("CoupledDecls").template readArray<TypeCoupledDeclRefInfo>(CoupledDecls_buffer_0);
return ctx.getCountAttributedType(WrappedTy, CountExpr, CountInBytes, OrNull, CoupledDecls);
}
QualType readBuiltinType() {
auto &ctx = R.getASTContext();
BuiltinType::Kind kind = R.find("kind").readBuiltinTypeKind();
switch (kind) {
#define IMAGE_TYPE(IMGTYPE, ID, SINGLETON_ID, ACCESS, SUFFIX) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(EXTTYPE, ID, EXT) \
case BuiltinType::ID: return ctx.ID##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
#define SVE_TYPE(NAME, ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/AArch64ACLETypes.def"
#define PPC_VECTOR_TYPE(NAME, ID, SIZE) \
case BuiltinType::ID: return ctx.ID##Ty;
#include "clang/Basic/PPCTypes.def"
#define RVV_TYPE(NAME, ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/RISCVVTypes.def"
#define WASM_TYPE(NAME, ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/WebAssemblyReferenceTypes.def"
#define AMDGPU_TYPE(NAME, ID, SINGLETON_ID, WIDTH, ALIGN) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/AMDGPUTypes.def"
#define HLSL_INTANGIBLE_TYPE(NAME, ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/Basic/HLSLIntangibleTypes.def"
#define BUILTIN_TYPE(ID, SINGLETON_ID) \
case BuiltinType::ID: return ctx.SINGLETON_ID;
#include "clang/AST/BuiltinTypes.def"
}
llvm_unreachable("unreachable builtin case");
}
QualType readComplexType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
return ctx.getComplexType(elementType);
}
QualType readDecltypeType() {
auto &ctx = R.getASTContext();
QualType underlyingType = R.find("underlyingType").readQualType();
Expr* expression = R.find("expression").readExprRef();
return ctx.getDecltypeType(expression, underlyingType);
}
QualType readAutoType() {
auto &ctx = R.getASTContext();
std::optional<QualType> deducedType = R.find("deducedType").template readOptional<QualType>();
AutoTypeKeyword keyword = R.find("keyword").readAutoTypeKeyword();
std::optional<TemplateDecl*> typeConstraintConcept = R.find("typeConstraintConcept").template readOptional<TemplateDecl*>();
llvm::SmallVector<TemplateArgument, 8> typeConstraintArguments_buffer_0;
llvm::ArrayRef<TemplateArgument> typeConstraintArguments = R.find("typeConstraintArguments").template readArray<TemplateArgument>(typeConstraintArguments_buffer_0);
uint32_t dependence = R.find("dependence").readUInt32();
return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
/*isDependentWithoutDeducedType*/ dependence > 0,
/*isPackWithoutDeducedType*/ dependence > 1,
makePointerFromOptional(typeConstraintConcept),
typeConstraintArguments);
}
QualType readDeducedTemplateSpecializationType() {
auto &ctx = R.getASTContext();
ElaboratedTypeKeyword keyword = R.find("keyword").readElaboratedTypeKeyword();
std::optional<TemplateName> templateName = R.find("templateName").template readOptional<TemplateName>();
QualType deducedType = R.find("deducedType").readQualType();
bool dependent = R.find("dependent").readBool();
return ctx.getDeducedTemplateSpecializationType(keyword,
makeNullableFromOptional(templateName),
deducedType, dependent);
}
QualType readDependentAddressSpaceType() {
auto &ctx = R.getASTContext();
QualType pointeeType = R.find("pointeeType").readQualType();
Expr* addressSpace = R.find("addressSpace").readExprRef();
SourceLocation attributeLoc = R.find("attributeLoc").readSourceLocation();
return ctx.getDependentAddressSpaceType(pointeeType, addressSpace,
attributeLoc);
}
QualType readDependentBitIntType() {
auto &ctx = R.getASTContext();
bool isUnsigned = R.find("isUnsigned").readBool();
Expr* numBitsExpr = R.find("numBitsExpr").readExprRef();
return ctx.getDependentBitIntType(isUnsigned, numBitsExpr);
}
QualType readDependentNameType() {
auto &ctx = R.getASTContext();
ElaboratedTypeKeyword keyword = R.find("keyword").readElaboratedTypeKeyword();
NestedNameSpecifier qualifier = R.find("qualifier").readNestedNameSpecifier();
IdentifierInfo* name = R.find("name").readIdentifier();
return ctx.getDependentNameType(keyword, qualifier, name);
}
QualType readDependentSizedExtVectorType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
Expr* size = R.find("size").readExprRef();
SourceLocation attributeLoc = R.find("attributeLoc").readSourceLocation();
return ctx.getDependentSizedExtVectorType(elementType, size, attributeLoc);
}
QualType readDependentVectorType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
Expr* size = R.find("size").readExprRef();
SourceLocation attributeLoc = R.find("attributeLoc").readSourceLocation();
VectorKind vectorKind = R.find("vectorKind").readVectorKind();
return ctx.getDependentVectorType(elementType, size, attributeLoc,
vectorKind);
}
QualType readFunctionNoProtoType() {
auto &ctx = R.getASTContext();
QualType returnType = R.find("returnType").readQualType();
bool noReturn = R.find("noReturn").readBool();
bool hasRegParm = R.find("hasRegParm").readBool();
uint32_t regParm = R.find("regParm").readUInt32();
CallingConv callingConvention = R.find("callingConvention").readCallingConv();
bool producesResult = R.find("producesResult").readBool();
bool noCallerSavedRegs = R.find("noCallerSavedRegs").readBool();
bool noCfCheck = R.find("noCfCheck").readBool();
bool cmseNSCall = R.find("cmseNSCall").readBool();
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
callingConvention, producesResult,
noCallerSavedRegs, noCfCheck,
cmseNSCall);
return ctx.getFunctionNoProtoType(returnType, extInfo);
}
QualType readFunctionProtoType() {
auto &ctx = R.getASTContext();
bool variadic = R.find("variadic").readBool();
bool trailingReturn = R.find("trailingReturn").readBool();
bool cfiUncheckedCallee = R.find("cfiUncheckedCallee").readBool();
Qualifiers methodQualifiers = R.find("methodQualifiers").readQualifiers();
RefQualifierKind refQualifier = R.find("refQualifier").readRefQualifierKind();
llvm::SmallVector<QualType, 8> exceptionSpecifier_buffer_0;
FunctionProtoType::ExceptionSpecInfo exceptionSpecifier = R.find("exceptionSpecifier").readExceptionSpecInfo(exceptionSpecifier_buffer_0);
llvm::SmallVector<QualType, 8> parameters_buffer_0;
llvm::ArrayRef<QualType> parameters = R.find("parameters").template readArray<QualType>(parameters_buffer_0);
llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 8> extParameterInfo_buffer_0;
llvm::ArrayRef<FunctionProtoType::ExtParameterInfo> extParameterInfo = R.find("extParameterInfo").template readArray<FunctionProtoType::ExtParameterInfo>(extParameterInfo_buffer_0);
uint32_t AArch64SMEAttributes = R.find("AArch64SMEAttributes").readUInt32();
llvm::SmallVector<FunctionEffect, 8> functionEffects_buffer_0;
llvm::ArrayRef<FunctionEffect> functionEffects = R.find("functionEffects").template readArray<FunctionEffect>(functionEffects_buffer_0);
llvm::SmallVector<EffectConditionExpr, 8> functionEffectConds_buffer_0;
llvm::ArrayRef<EffectConditionExpr> functionEffectConds = R.find("functionEffectConds").template readArray<EffectConditionExpr>(functionEffectConds_buffer_0);
QualType returnType = R.find("returnType").readQualType();
bool noReturn = R.find("noReturn").readBool();
bool hasRegParm = R.find("hasRegParm").readBool();
uint32_t regParm = R.find("regParm").readUInt32();
CallingConv callingConvention = R.find("callingConvention").readCallingConv();
bool producesResult = R.find("producesResult").readBool();
bool noCallerSavedRegs = R.find("noCallerSavedRegs").readBool();
bool noCfCheck = R.find("noCfCheck").readBool();
bool cmseNSCall = R.find("cmseNSCall").readBool();
auto extInfo = FunctionType::ExtInfo(noReturn, hasRegParm, regParm,
callingConvention, producesResult,
noCallerSavedRegs, noCfCheck,
cmseNSCall);
FunctionProtoType::ExtProtoInfo epi;
epi.ExtInfo = extInfo;
epi.Variadic = variadic;
epi.HasTrailingReturn = trailingReturn;
epi.CFIUncheckedCallee = cfiUncheckedCallee;
epi.TypeQuals = methodQualifiers;
epi.RefQualifier = refQualifier;
epi.ExceptionSpec = exceptionSpecifier;
epi.ExtParameterInfos =
extParameterInfo.empty() ? nullptr : extParameterInfo.data();
epi.AArch64SMEAttributes = AArch64SMEAttributes;
epi.FunctionEffects = FunctionEffectsRef::create(functionEffects, functionEffectConds);
return ctx.getFunctionType(returnType, parameters, epi);
}
QualType readHLSLAttributedResourceType() {
auto &ctx = R.getASTContext();
uint32_t resClass = R.find("resClass").readUInt32();
bool isROV = R.find("isROV").readBool();
bool rawBuffer = R.find("rawBuffer").readBool();
bool isCounter = R.find("isCounter").readBool();
QualType wrappedTy = R.find("wrappedTy").readQualType();
QualType containedTy = R.find("containedTy").readQualType();
HLSLAttributedResourceType::Attributes attrs(static_cast<llvm::dxil::ResourceClass>(resClass), isROV, rawBuffer, isCounter);
return ctx.getHLSLAttributedResourceType(wrappedTy, containedTy, attrs);
}
QualType readHLSLInlineSpirvType() {
auto &ctx = R.getASTContext();
uint32_t opcode = R.find("opcode").readUInt32();
uint32_t size = R.find("size").readUInt32();
uint32_t alignment = R.find("alignment").readUInt32();
llvm::SmallVector<SpirvOperand, 8> operands_buffer_0;
llvm::ArrayRef<SpirvOperand> operands = R.find("operands").template readArray<SpirvOperand>(operands_buffer_0);
return ctx.getHLSLInlineSpirvType(opcode, size, alignment, operands);
}
QualType readMacroQualifiedType() {
auto &ctx = R.getASTContext();
QualType underlyingType = R.find("underlyingType").readQualType();
IdentifierInfo* macroIdentifier = R.find("macroIdentifier").readIdentifier();
return ctx.getMacroQualifiedType(underlyingType, macroIdentifier);
}
QualType readConstantMatrixType() {
auto &ctx = R.getASTContext();
uint32_t numRows = R.find("numRows").readUInt32();
uint32_t numColumns = R.find("numColumns").readUInt32();
QualType elementType = R.find("elementType").readQualType();
return ctx.getConstantMatrixType(elementType, numRows, numColumns);
}
QualType readDependentSizedMatrixType() {
auto &ctx = R.getASTContext();
Expr* rows = R.find("rows").readExprRef();
Expr* columns = R.find("columns").readExprRef();
SourceLocation attributeLoc = R.find("attributeLoc").readSourceLocation();
QualType elementType = R.find("elementType").readQualType();
return ctx.getDependentSizedMatrixType(elementType, rows, columns, attributeLoc);
}
QualType readMemberPointerType() {
auto &ctx = R.getASTContext();
QualType pointeeType = R.find("pointeeType").readQualType();
NestedNameSpecifier Qualifier = R.find("Qualifier").readNestedNameSpecifier();
Decl* Cls = R.find("Cls").readDeclRef();
return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
}
QualType readObjCObjectPointerType() {
auto &ctx = R.getASTContext();
QualType pointeeType = R.find("pointeeType").readQualType();
return ctx.getObjCObjectPointerType(pointeeType);
}
QualType readObjCObjectType() {
auto &ctx = R.getASTContext();
QualType baseType = R.find("baseType").readQualType();
llvm::SmallVector<QualType, 8> typeArgsAsWritten_buffer_0;
llvm::ArrayRef<QualType> typeArgsAsWritten = R.find("typeArgsAsWritten").template readArray<QualType>(typeArgsAsWritten_buffer_0);
llvm::SmallVector<ObjCProtocolDecl*, 8> qualifiers_buffer_0;
llvm::ArrayRef<ObjCProtocolDecl*> qualifiers = R.find("qualifiers").template readArray<ObjCProtocolDecl*>(qualifiers_buffer_0);
bool isKindOfTypeAsWritten = R.find("isKindOfTypeAsWritten").readBool();
return ctx.getObjCObjectType(baseType, typeArgsAsWritten, qualifiers,
isKindOfTypeAsWritten);
}
QualType readObjCInterfaceType() {
auto &ctx = R.getASTContext();
Decl* declaration = R.find("declaration").readDeclRef();
return ctx.getObjCInterfaceType(
cast<ObjCInterfaceDecl>(declaration->getCanonicalDecl()));
}
QualType readObjCTypeParamType() {
auto &ctx = R.getASTContext();
ObjCTypeParamDecl* declaration = R.find("declaration").readObjCTypeParamDeclRef();
llvm::SmallVector<ObjCProtocolDecl*, 8> qualifiers_buffer_0;
llvm::ArrayRef<ObjCProtocolDecl*> qualifiers = R.find("qualifiers").template readArray<ObjCProtocolDecl*>(qualifiers_buffer_0);
return ctx.getObjCTypeParamType(declaration, qualifiers);
}
QualType readPackExpansionType() {
auto &ctx = R.getASTContext();
QualType pattern = R.find("pattern").readQualType();
UnsignedOrNone numExpansions = R.find("numExpansions").readUnsignedOrNone();
return ctx.getPackExpansionType(pattern, numExpansions,
/*ExpectPackInType*/false);
}
QualType readPackIndexingType() {
auto &ctx = R.getASTContext();
QualType pattern = R.find("pattern").readQualType();
Expr* indexExpression = R.find("indexExpression").readExprRef();
bool isFullySubstituted = R.find("isFullySubstituted").readBool();
llvm::SmallVector<QualType, 8> expansions_buffer_0;
llvm::ArrayRef<QualType> expansions = R.find("expansions").template readArray<QualType>(expansions_buffer_0);
return ctx.getPackIndexingType(pattern, indexExpression, isFullySubstituted, expansions);
}
QualType readParenType() {
auto &ctx = R.getASTContext();
QualType innerType = R.find("innerType").readQualType();
return ctx.getParenType(innerType);
}
QualType readPipeType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
bool isReadOnly = R.find("isReadOnly").readBool();
return ctx.getPipeType(elementType, isReadOnly);
}
QualType readPointerType() {
auto &ctx = R.getASTContext();
QualType pointeeType = R.find("pointeeType").readQualType();
return ctx.getPointerType(pointeeType);
}
QualType readPredefinedSugarType() {
auto &ctx = R.getASTContext();
uint32_t kind = R.find("kind").readUInt32();
return ctx.getPredefinedSugarType(static_cast<PredefinedSugarType::Kind>(kind));
}
QualType readLValueReferenceType() {
auto &ctx = R.getASTContext();
bool isSpelledAsLValue = R.find("isSpelledAsLValue").readBool();
QualType pointeeTypeAsWritten = R.find("pointeeTypeAsWritten").readQualType();
return ctx.getLValueReferenceType(pointeeTypeAsWritten,
isSpelledAsLValue);
}
QualType readRValueReferenceType() {
auto &ctx = R.getASTContext();
QualType pointeeTypeAsWritten = R.find("pointeeTypeAsWritten").readQualType();
return ctx.getRValueReferenceType(pointeeTypeAsWritten);
}
QualType readSubstBuiltinTemplatePackType() {
auto &ctx = R.getASTContext();
TemplateArgument replacementPack = R.find("replacementPack").readTemplateArgument();
return ctx.getSubstBuiltinTemplatePack(replacementPack);
}
QualType readSubstTemplateTypeParmPackType() {
auto &ctx = R.getASTContext();
Decl* associatedDecl = R.find("associatedDecl").readDeclRef();
uint32_t Index = R.find("Index").readUInt32();
bool Final = R.find("Final").readBool();
TemplateArgument replacementPack = R.find("replacementPack").readTemplateArgument();
return ctx.getSubstTemplateTypeParmPackType(
associatedDecl, Index, Final, replacementPack);
}
QualType readSubstTemplateTypeParmType() {
auto &ctx = R.getASTContext();
QualType replacementType = R.find("replacementType").readQualType();
Decl* associatedDecl = R.find("associatedDecl").readDeclRef();
uint32_t Index = R.find("Index").readUInt32();
UnsignedOrNone PackIndex = R.find("PackIndex").readUnsignedOrNone();
bool Final = R.find("Final").readBool();
return ctx.getSubstTemplateTypeParmType(
replacementType, associatedDecl, Index, PackIndex, Final);
}
QualType readEnumType() {
auto &ctx = R.getASTContext();
bool OwnsTag = R.find("OwnsTag").readBool();
bool IsCanonical = R.find("IsCanonical").readBool();
std::optional<ElaboratedTypeKeyword> Keyword;
if ( !IsCanonical ) {
Keyword.emplace(R.find("Keyword").readElaboratedTypeKeyword());
}
std::optional<NestedNameSpecifier> Qualifier;
if ( !IsCanonical ) {
Qualifier.emplace(R.find("Qualifier").readNestedNameSpecifier());
}
TagDecl* TD = R.find("TD").readTagDeclRef();
return IsCanonical ? ctx.getCanonicalTagType(TD) : ctx.getTagType(*Keyword, *Qualifier, TD, OwnsTag);
}
QualType readInjectedClassNameType() {
auto &ctx = R.getASTContext();
bool IsCanonical = R.find("IsCanonical").readBool();
std::optional<ElaboratedTypeKeyword> Keyword;
if ( !IsCanonical ) {
Keyword.emplace(R.find("Keyword").readElaboratedTypeKeyword());
}
std::optional<NestedNameSpecifier> Qualifier;
if ( !IsCanonical ) {
Qualifier.emplace(R.find("Qualifier").readNestedNameSpecifier());
}
TagDecl* TD = R.find("TD").readTagDeclRef();
return IsCanonical ? ctx.getCanonicalTagType(TD) : ctx.getTagType(*Keyword, *Qualifier, TD, /*OwnsTag=*/false);
}
QualType readRecordType() {
auto &ctx = R.getASTContext();
bool OwnsTag = R.find("OwnsTag").readBool();
bool IsCanonical = R.find("IsCanonical").readBool();
std::optional<ElaboratedTypeKeyword> Keyword;
if ( !IsCanonical ) {
Keyword.emplace(R.find("Keyword").readElaboratedTypeKeyword());
}
std::optional<NestedNameSpecifier> Qualifier;
if ( !IsCanonical ) {
Qualifier.emplace(R.find("Qualifier").readNestedNameSpecifier());
}
TagDecl* TD = R.find("TD").readTagDeclRef();
return IsCanonical ? ctx.getCanonicalTagType(TD) : ctx.getTagType(*Keyword, *Qualifier, TD, OwnsTag);
}
QualType readTemplateSpecializationType() {
auto &ctx = R.getASTContext();
ElaboratedTypeKeyword keyword = R.find("keyword").readElaboratedTypeKeyword();
TemplateName templateName = R.find("templateName").readTemplateName();
llvm::SmallVector<TemplateArgument, 8> args_buffer_0;
llvm::ArrayRef<TemplateArgument> args = R.find("args").template readArray<TemplateArgument>(args_buffer_0);
QualType UnderlyingType = R.find("UnderlyingType").readQualType();
return ctx.getTemplateSpecializationType(keyword, templateName, args, {}, UnderlyingType);
}
QualType readTemplateTypeParmType() {
auto &ctx = R.getASTContext();
uint32_t depth = R.find("depth").readUInt32();
uint32_t index = R.find("index").readUInt32();
bool isParameterPack = R.find("isParameterPack").readBool();
std::optional<TemplateTypeParmDecl*> declaration = R.find("declaration").template readOptional<TemplateTypeParmDecl*>();
return ctx.getTemplateTypeParmType(depth, index, isParameterPack,
makePointerFromOptional(declaration));
}
QualType readTypeOfExprType() {
auto &ctx = R.getASTContext();
Expr* expression = R.find("expression").readExprRef();
TypeOfKind kind = R.find("kind").readTypeOfKind();
return ctx.getTypeOfExprType(expression, kind);
}
QualType readTypeOfType() {
auto &ctx = R.getASTContext();
QualType unmodifiedType = R.find("unmodifiedType").readQualType();
TypeOfKind kind = R.find("kind").readTypeOfKind();
return ctx.getTypeOfType(unmodifiedType, kind);
}
QualType readTypedefType() {
auto &ctx = R.getASTContext();
ElaboratedTypeKeyword Keyword = R.find("Keyword").readElaboratedTypeKeyword();
NestedNameSpecifier Qualifier = R.find("Qualifier").readNestedNameSpecifier();
Decl* declaration = R.find("declaration").readDeclRef();
QualType UnderlyingType = R.find("UnderlyingType").readQualType();
bool TypeMatchesDecl = R.find("TypeMatchesDecl").readBool();
return ctx.getTypedefType(Keyword, Qualifier, cast<TypedefNameDecl>(declaration), UnderlyingType, TypeMatchesDecl);
}
QualType readUnaryTransformType() {
auto &ctx = R.getASTContext();
QualType baseType = R.find("baseType").readQualType();
QualType underlyingType = R.find("underlyingType").readQualType();
UnaryTransformType::UTTKind transform = R.find("transform").readUnaryTypeTransformKind();
return ctx.getUnaryTransformType(baseType, underlyingType, transform);
}
QualType readUnresolvedUsingType() {
auto &ctx = R.getASTContext();
bool IsCanonical = R.find("IsCanonical").readBool();
std::optional<ElaboratedTypeKeyword> Keyword;
if ( !IsCanonical ) {
Keyword.emplace(R.find("Keyword").readElaboratedTypeKeyword());
}
std::optional<NestedNameSpecifier> Qualifier;
if ( !IsCanonical ) {
Qualifier.emplace(R.find("Qualifier").readNestedNameSpecifier());
}
Decl* D = R.find("D").readDeclRef();
auto *UD = cast<UnresolvedUsingTypenameDecl>(D);
return IsCanonical ? ctx.getCanonicalUnresolvedUsingType(UD) : ctx.getUnresolvedUsingType(*Keyword, *Qualifier, UD);
}
QualType readUsingType() {
auto &ctx = R.getASTContext();
ElaboratedTypeKeyword Keyword = R.find("Keyword").readElaboratedTypeKeyword();
NestedNameSpecifier Qualifier = R.find("Qualifier").readNestedNameSpecifier();
UsingShadowDecl* D = R.find("D").readUsingShadowDeclRef();
QualType UnderlyingType = R.find("UnderlyingType").readQualType();
return ctx.getUsingType(Keyword, Qualifier, D, UnderlyingType);
}
QualType readVectorType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
uint32_t numElements = R.find("numElements").readUInt32();
VectorKind vectorKind = R.find("vectorKind").readVectorKind();
return ctx.getVectorType(elementType, numElements, vectorKind);
}
QualType readExtVectorType() {
auto &ctx = R.getASTContext();
QualType elementType = R.find("elementType").readQualType();
uint32_t numElements = R.find("numElements").readUInt32();
return ctx.getExtVectorType(elementType, numElements);
}
};

View File

@ -0,0 +1,32 @@
//==--- AbstractTypeWriter.h - Abstract serialization for types -----------===//
//
// 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_AST_ABSTRACTTYPEWRITER_H
#define LLVM_CLANG_AST_ABSTRACTTYPEWRITER_H
#include "clang/AST/Type.h"
#include "clang/AST/AbstractBasicWriter.h"
#include "clang/AST/DeclObjC.h"
namespace clang {
namespace serialization {
// template <class PropertyWriter>
// class AbstractTypeWriter {
// public:
// AbstractTypeWriter(PropertyWriter &W);
// void write(QualType type);
// };
//
// The actual class is auto-generated; see ClangASTPropertiesEmitter.cpp.
#include "clang/AST/AbstractTypeWriter.inc"
} // end namespace serialization
} // end namespace clang
#endif

View File

@ -0,0 +1,737 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* A CRTP writer for Clang Type nodes *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: TypeProperties.td *|
|* *|
\*===----------------------------------------------------------------------===*/
template <class PropertyWriter>
class AbstractTypeWriter {
public:
PropertyWriter &W;
AbstractTypeWriter(PropertyWriter &W) : W(W) {}
void write(const Type *node) {
switch (node->getTypeClass()) {
case Type::Adjusted:
return writeAdjustedType(static_cast<const AdjustedType *>(node));
case Type::Decayed:
return writeDecayedType(static_cast<const DecayedType *>(node));
case Type::ConstantArray:
return writeConstantArrayType(static_cast<const ConstantArrayType *>(node));
case Type::ArrayParameter:
return writeArrayParameterType(static_cast<const ArrayParameterType *>(node));
case Type::DependentSizedArray:
return writeDependentSizedArrayType(static_cast<const DependentSizedArrayType *>(node));
case Type::IncompleteArray:
return writeIncompleteArrayType(static_cast<const IncompleteArrayType *>(node));
case Type::VariableArray:
return writeVariableArrayType(static_cast<const VariableArrayType *>(node));
case Type::Atomic:
return writeAtomicType(static_cast<const AtomicType *>(node));
case Type::Attributed:
return writeAttributedType(static_cast<const AttributedType *>(node));
case Type::BTFTagAttributed:
return writeBTFTagAttributedType(static_cast<const BTFTagAttributedType *>(node));
case Type::BitInt:
return writeBitIntType(static_cast<const BitIntType *>(node));
case Type::BlockPointer:
return writeBlockPointerType(static_cast<const BlockPointerType *>(node));
case Type::CountAttributed:
return writeCountAttributedType(static_cast<const CountAttributedType *>(node));
case Type::Builtin:
return writeBuiltinType(static_cast<const BuiltinType *>(node));
case Type::Complex:
return writeComplexType(static_cast<const ComplexType *>(node));
case Type::Decltype:
return writeDecltypeType(static_cast<const DecltypeType *>(node));
case Type::Auto:
return writeAutoType(static_cast<const AutoType *>(node));
case Type::DeducedTemplateSpecialization:
return writeDeducedTemplateSpecializationType(static_cast<const DeducedTemplateSpecializationType *>(node));
case Type::DependentAddressSpace:
return writeDependentAddressSpaceType(static_cast<const DependentAddressSpaceType *>(node));
case Type::DependentBitInt:
return writeDependentBitIntType(static_cast<const DependentBitIntType *>(node));
case Type::DependentName:
return writeDependentNameType(static_cast<const DependentNameType *>(node));
case Type::DependentSizedExtVector:
return writeDependentSizedExtVectorType(static_cast<const DependentSizedExtVectorType *>(node));
case Type::DependentVector:
return writeDependentVectorType(static_cast<const DependentVectorType *>(node));
case Type::FunctionNoProto:
return writeFunctionNoProtoType(static_cast<const FunctionNoProtoType *>(node));
case Type::FunctionProto:
return writeFunctionProtoType(static_cast<const FunctionProtoType *>(node));
case Type::HLSLAttributedResource:
return writeHLSLAttributedResourceType(static_cast<const HLSLAttributedResourceType *>(node));
case Type::HLSLInlineSpirv:
return writeHLSLInlineSpirvType(static_cast<const HLSLInlineSpirvType *>(node));
case Type::MacroQualified:
return writeMacroQualifiedType(static_cast<const MacroQualifiedType *>(node));
case Type::ConstantMatrix:
return writeConstantMatrixType(static_cast<const ConstantMatrixType *>(node));
case Type::DependentSizedMatrix:
return writeDependentSizedMatrixType(static_cast<const DependentSizedMatrixType *>(node));
case Type::MemberPointer:
return writeMemberPointerType(static_cast<const MemberPointerType *>(node));
case Type::ObjCObjectPointer:
return writeObjCObjectPointerType(static_cast<const ObjCObjectPointerType *>(node));
case Type::ObjCObject:
return writeObjCObjectType(static_cast<const ObjCObjectType *>(node));
case Type::ObjCInterface:
return writeObjCInterfaceType(static_cast<const ObjCInterfaceType *>(node));
case Type::ObjCTypeParam:
return writeObjCTypeParamType(static_cast<const ObjCTypeParamType *>(node));
case Type::PackExpansion:
return writePackExpansionType(static_cast<const PackExpansionType *>(node));
case Type::PackIndexing:
return writePackIndexingType(static_cast<const PackIndexingType *>(node));
case Type::Paren:
return writeParenType(static_cast<const ParenType *>(node));
case Type::Pipe:
return writePipeType(static_cast<const PipeType *>(node));
case Type::Pointer:
return writePointerType(static_cast<const PointerType *>(node));
case Type::PredefinedSugar:
return writePredefinedSugarType(static_cast<const PredefinedSugarType *>(node));
case Type::LValueReference:
return writeLValueReferenceType(static_cast<const LValueReferenceType *>(node));
case Type::RValueReference:
return writeRValueReferenceType(static_cast<const RValueReferenceType *>(node));
case Type::SubstBuiltinTemplatePack:
return writeSubstBuiltinTemplatePackType(static_cast<const SubstBuiltinTemplatePackType *>(node));
case Type::SubstTemplateTypeParmPack:
return writeSubstTemplateTypeParmPackType(static_cast<const SubstTemplateTypeParmPackType *>(node));
case Type::SubstTemplateTypeParm:
return writeSubstTemplateTypeParmType(static_cast<const SubstTemplateTypeParmType *>(node));
case Type::Enum:
return writeEnumType(static_cast<const EnumType *>(node));
case Type::InjectedClassName:
return writeInjectedClassNameType(static_cast<const InjectedClassNameType *>(node));
case Type::Record:
return writeRecordType(static_cast<const RecordType *>(node));
case Type::TemplateSpecialization:
return writeTemplateSpecializationType(static_cast<const TemplateSpecializationType *>(node));
case Type::TemplateTypeParm:
return writeTemplateTypeParmType(static_cast<const TemplateTypeParmType *>(node));
case Type::TypeOfExpr:
return writeTypeOfExprType(static_cast<const TypeOfExprType *>(node));
case Type::TypeOf:
return writeTypeOfType(static_cast<const TypeOfType *>(node));
case Type::Typedef:
return writeTypedefType(static_cast<const TypedefType *>(node));
case Type::UnaryTransform:
return writeUnaryTransformType(static_cast<const UnaryTransformType *>(node));
case Type::UnresolvedUsing:
return writeUnresolvedUsingType(static_cast<const UnresolvedUsingType *>(node));
case Type::Using:
return writeUsingType(static_cast<const UsingType *>(node));
case Type::Vector:
return writeVectorType(static_cast<const VectorType *>(node));
case Type::ExtVector:
return writeExtVectorType(static_cast<const ExtVectorType *>(node));
}
llvm_unreachable("bad kind");
}
void writeAdjustedType(const AdjustedType *node) {
QualType originalType = ( node->getOriginalType() );
W.find("originalType").writeQualType(originalType);
QualType adjustedType = ( node->getAdjustedType() );
W.find("adjustedType").writeQualType(adjustedType);
}
void writeDecayedType(const DecayedType *node) {
QualType originalType = ( node->getOriginalType() );
W.find("originalType").writeQualType(originalType);
}
void writeConstantArrayType(const ConstantArrayType *node) {
llvm::APInt sizeValue = ( node->getSize() );
W.find("sizeValue").writeAPInt(sizeValue);
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
ArraySizeModifier sizeModifier = ( node->getSizeModifier() );
W.find("sizeModifier").writeArraySizeModifier(sizeModifier);
Qualifiers indexQualifiers = ( Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) );
W.find("indexQualifiers").writeQualifiers(indexQualifiers);
}
void writeArrayParameterType(const ArrayParameterType *node) {
llvm::APInt sizeValue = ( node->getSize() );
W.find("sizeValue").writeAPInt(sizeValue);
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
ArraySizeModifier sizeModifier = ( node->getSizeModifier() );
W.find("sizeModifier").writeArraySizeModifier(sizeModifier);
Qualifiers indexQualifiers = ( Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) );
W.find("indexQualifiers").writeQualifiers(indexQualifiers);
}
void writeDependentSizedArrayType(const DependentSizedArrayType *node) {
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
ArraySizeModifier sizeModifier = ( node->getSizeModifier() );
W.find("sizeModifier").writeArraySizeModifier(sizeModifier);
Qualifiers indexQualifiers = ( Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) );
W.find("indexQualifiers").writeQualifiers(indexQualifiers);
}
void writeIncompleteArrayType(const IncompleteArrayType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
ArraySizeModifier sizeModifier = ( node->getSizeModifier() );
W.find("sizeModifier").writeArraySizeModifier(sizeModifier);
Qualifiers indexQualifiers = ( Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) );
W.find("indexQualifiers").writeQualifiers(indexQualifiers);
}
void writeVariableArrayType(const VariableArrayType *node) {
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
ArraySizeModifier sizeModifier = ( node->getSizeModifier() );
W.find("sizeModifier").writeArraySizeModifier(sizeModifier);
Qualifiers indexQualifiers = ( Qualifiers::fromCVRMask(node->getIndexTypeCVRQualifiers()) );
W.find("indexQualifiers").writeQualifiers(indexQualifiers);
}
void writeAtomicType(const AtomicType *node) {
QualType valueType = ( node->getValueType() );
W.find("valueType").writeQualType(valueType);
}
void writeAttributedType(const AttributedType *node) {
QualType modifiedType = ( node->getModifiedType() );
W.find("modifiedType").writeQualType(modifiedType);
QualType equivalentType = ( node->getEquivalentType() );
W.find("equivalentType").writeQualType(equivalentType);
attr::Kind attrKind = ( node->getAttrKind() );
W.find("attrKind").writeAttrKind(attrKind);
const Attr * attribute = ( node->getAttr() );
W.find("attribute").writeAttr(attribute);
}
void writeBTFTagAttributedType(const BTFTagAttributedType *node) {
const BTFTypeTagAttr * attr = ( node->getAttr() );
W.find("attr").writeBTFTypeTagAttr(attr);
QualType wrappedType = ( node->getWrappedType() );
W.find("wrappedType").writeQualType(wrappedType);
}
void writeBitIntType(const BitIntType *node) {
bool isUnsigned = ( node->isUnsigned() );
W.find("isUnsigned").writeBool(isUnsigned);
uint32_t numBits = ( node->getNumBits() );
W.find("numBits").writeUInt32(numBits);
}
void writeBlockPointerType(const BlockPointerType *node) {
QualType pointeeType = ( node->getPointeeType() );
W.find("pointeeType").writeQualType(pointeeType);
}
void writeCountAttributedType(const CountAttributedType *node) {
QualType WrappedTy = ( node->desugar() );
W.find("WrappedTy").writeQualType(WrappedTy);
const Expr* CountExpr = ( node->getCountExpr() );
W.find("CountExpr").writeExprRef(CountExpr);
bool CountInBytes = ( node->isCountInBytes() );
W.find("CountInBytes").writeBool(CountInBytes);
bool OrNull = ( node->isOrNull() );
W.find("OrNull").writeBool(OrNull);
llvm::ArrayRef<TypeCoupledDeclRefInfo> CoupledDecls = ( node->getCoupledDecls() );
W.find("CoupledDecls").writeArray(CoupledDecls);
}
void writeBuiltinType(const BuiltinType *node) {
BuiltinType::Kind kind = ( node->getKind() );
W.find("kind").writeBuiltinTypeKind(kind);
}
void writeComplexType(const ComplexType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
}
void writeDecltypeType(const DecltypeType *node) {
QualType underlyingType = ( node->getUnderlyingType() );
W.find("underlyingType").writeQualType(underlyingType);
const Expr* expression = ( node->getUnderlyingExpr() );
W.find("expression").writeExprRef(expression);
}
void writeAutoType(const AutoType *node) {
std::optional<QualType> deducedType = ( makeOptionalFromNullable(node->getDeducedType()) );
W.find("deducedType").writeOptional(deducedType);
AutoTypeKeyword keyword = ( node->getKeyword() );
W.find("keyword").writeAutoTypeKeyword(keyword);
std::optional<const TemplateDecl*> typeConstraintConcept = ( makeOptionalFromPointer(
node->getTypeConstraintConcept()) );
W.find("typeConstraintConcept").writeOptional(typeConstraintConcept);
llvm::ArrayRef<TemplateArgument> typeConstraintArguments = ( node->getTypeConstraintArguments() );
W.find("typeConstraintArguments").writeArray(typeConstraintArguments);
uint32_t dependence = ( !node->getDeducedType().isNull() ? 0 :
node->containsUnexpandedParameterPack() ? 2 :
node->isDependentType() ? 1 : 0 );
W.find("dependence").writeUInt32(dependence);
}
void writeDeducedTemplateSpecializationType(const DeducedTemplateSpecializationType *node) {
ElaboratedTypeKeyword keyword = ( node->getKeyword() );
W.find("keyword").writeElaboratedTypeKeyword(keyword);
std::optional<TemplateName> templateName = ( makeOptionalFromNullable(node->getTemplateName()) );
W.find("templateName").writeOptional(templateName);
QualType deducedType = ( node->getDeducedType() );
W.find("deducedType").writeQualType(deducedType);
bool dependent = ( !node->getDeducedType().isNull()
? false : node->isDependentType() );
W.find("dependent").writeBool(dependent);
}
void writeDependentAddressSpaceType(const DependentAddressSpaceType *node) {
QualType pointeeType = ( node->getPointeeType() );
W.find("pointeeType").writeQualType(pointeeType);
const Expr* addressSpace = ( node->getAddrSpaceExpr() );
W.find("addressSpace").writeExprRef(addressSpace);
SourceLocation attributeLoc = ( node->getAttributeLoc() );
W.find("attributeLoc").writeSourceLocation(attributeLoc);
}
void writeDependentBitIntType(const DependentBitIntType *node) {
bool isUnsigned = ( node->isUnsigned() );
W.find("isUnsigned").writeBool(isUnsigned);
const Expr* numBitsExpr = ( node->getNumBitsExpr() );
W.find("numBitsExpr").writeExprRef(numBitsExpr);
}
void writeDependentNameType(const DependentNameType *node) {
ElaboratedTypeKeyword keyword = ( node->getKeyword() );
W.find("keyword").writeElaboratedTypeKeyword(keyword);
NestedNameSpecifier qualifier = ( node->getQualifier() );
W.find("qualifier").writeNestedNameSpecifier(qualifier);
const IdentifierInfo* name = ( node->getIdentifier() );
W.find("name").writeIdentifier(name);
}
void writeDependentSizedExtVectorType(const DependentSizedExtVectorType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
SourceLocation attributeLoc = ( node->getAttributeLoc() );
W.find("attributeLoc").writeSourceLocation(attributeLoc);
}
void writeDependentVectorType(const DependentVectorType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
const Expr* size = ( node->getSizeExpr() );
W.find("size").writeExprRef(size);
SourceLocation attributeLoc = ( node->getAttributeLoc() );
W.find("attributeLoc").writeSourceLocation(attributeLoc);
VectorKind vectorKind = ( node->getVectorKind() );
W.find("vectorKind").writeVectorKind(vectorKind);
}
void writeFunctionNoProtoType(const FunctionNoProtoType *node) {
QualType returnType = ( node->getReturnType() );
W.find("returnType").writeQualType(returnType);
bool noReturn = ( node->getExtInfo().getNoReturn() );
W.find("noReturn").writeBool(noReturn);
bool hasRegParm = ( node->getExtInfo().getHasRegParm() );
W.find("hasRegParm").writeBool(hasRegParm);
uint32_t regParm = ( node->getExtInfo().getRegParm() );
W.find("regParm").writeUInt32(regParm);
CallingConv callingConvention = ( node->getExtInfo().getCC() );
W.find("callingConvention").writeCallingConv(callingConvention);
bool producesResult = ( node->getExtInfo().getProducesResult() );
W.find("producesResult").writeBool(producesResult);
bool noCallerSavedRegs = ( node->getExtInfo().getNoCallerSavedRegs() );
W.find("noCallerSavedRegs").writeBool(noCallerSavedRegs);
bool noCfCheck = ( node->getExtInfo().getNoCfCheck() );
W.find("noCfCheck").writeBool(noCfCheck);
bool cmseNSCall = ( node->getExtInfo().getCmseNSCall() );
W.find("cmseNSCall").writeBool(cmseNSCall);
}
void writeFunctionProtoType(const FunctionProtoType *node) {
bool variadic = ( node->isVariadic() );
W.find("variadic").writeBool(variadic);
bool trailingReturn = ( node->hasTrailingReturn() );
W.find("trailingReturn").writeBool(trailingReturn);
bool cfiUncheckedCallee = ( node->hasCFIUncheckedCallee() );
W.find("cfiUncheckedCallee").writeBool(cfiUncheckedCallee);
Qualifiers methodQualifiers = ( node->getMethodQuals() );
W.find("methodQualifiers").writeQualifiers(methodQualifiers);
RefQualifierKind refQualifier = ( node->getRefQualifier() );
W.find("refQualifier").writeRefQualifierKind(refQualifier);
FunctionProtoType::ExceptionSpecInfo exceptionSpecifier = ( node->getExceptionSpecInfo() );
W.find("exceptionSpecifier").writeExceptionSpecInfo(exceptionSpecifier);
llvm::ArrayRef<QualType> parameters = ( node->getParamTypes() );
W.find("parameters").writeArray(parameters);
llvm::ArrayRef<FunctionProtoType::ExtParameterInfo> extParameterInfo = ( node->hasExtParameterInfos()
? node->getExtParameterInfos()
: ArrayRef<FunctionProtoType::ExtParameterInfo>() );
W.find("extParameterInfo").writeArray(extParameterInfo);
uint32_t AArch64SMEAttributes = ( node->getAArch64SMEAttributes() );
W.find("AArch64SMEAttributes").writeUInt32(AArch64SMEAttributes);
llvm::ArrayRef<FunctionEffect> functionEffects = ( node->getFunctionEffectsWithoutConditions() );
W.find("functionEffects").writeArray(functionEffects);
llvm::ArrayRef<EffectConditionExpr> functionEffectConds = ( node->getFunctionEffectConditions() );
W.find("functionEffectConds").writeArray(functionEffectConds);
QualType returnType = ( node->getReturnType() );
W.find("returnType").writeQualType(returnType);
bool noReturn = ( node->getExtInfo().getNoReturn() );
W.find("noReturn").writeBool(noReturn);
bool hasRegParm = ( node->getExtInfo().getHasRegParm() );
W.find("hasRegParm").writeBool(hasRegParm);
uint32_t regParm = ( node->getExtInfo().getRegParm() );
W.find("regParm").writeUInt32(regParm);
CallingConv callingConvention = ( node->getExtInfo().getCC() );
W.find("callingConvention").writeCallingConv(callingConvention);
bool producesResult = ( node->getExtInfo().getProducesResult() );
W.find("producesResult").writeBool(producesResult);
bool noCallerSavedRegs = ( node->getExtInfo().getNoCallerSavedRegs() );
W.find("noCallerSavedRegs").writeBool(noCallerSavedRegs);
bool noCfCheck = ( node->getExtInfo().getNoCfCheck() );
W.find("noCfCheck").writeBool(noCfCheck);
bool cmseNSCall = ( node->getExtInfo().getCmseNSCall() );
W.find("cmseNSCall").writeBool(cmseNSCall);
}
void writeHLSLAttributedResourceType(const HLSLAttributedResourceType *node) {
uint32_t resClass = ( static_cast<uint32_t>(node->getAttrs().ResourceClass) );
W.find("resClass").writeUInt32(resClass);
bool isROV = ( node->getAttrs().IsROV );
W.find("isROV").writeBool(isROV);
bool rawBuffer = ( node->getAttrs().RawBuffer );
W.find("rawBuffer").writeBool(rawBuffer);
bool isCounter = ( node->getAttrs().IsCounter );
W.find("isCounter").writeBool(isCounter);
QualType wrappedTy = ( node->getWrappedType() );
W.find("wrappedTy").writeQualType(wrappedTy);
QualType containedTy = ( node->getContainedType() );
W.find("containedTy").writeQualType(containedTy);
}
void writeHLSLInlineSpirvType(const HLSLInlineSpirvType *node) {
uint32_t opcode = ( node->getOpcode() );
W.find("opcode").writeUInt32(opcode);
uint32_t size = ( node->getSize() );
W.find("size").writeUInt32(size);
uint32_t alignment = ( node->getAlignment() );
W.find("alignment").writeUInt32(alignment);
llvm::ArrayRef<SpirvOperand> operands = ( node->getOperands() );
W.find("operands").writeArray(operands);
}
void writeMacroQualifiedType(const MacroQualifiedType *node) {
QualType underlyingType = ( node->getUnderlyingType() );
W.find("underlyingType").writeQualType(underlyingType);
const IdentifierInfo* macroIdentifier = ( node->getMacroIdentifier() );
W.find("macroIdentifier").writeIdentifier(macroIdentifier);
}
void writeConstantMatrixType(const ConstantMatrixType *node) {
uint32_t numRows = ( node->getNumRows() );
W.find("numRows").writeUInt32(numRows);
uint32_t numColumns = ( node->getNumColumns() );
W.find("numColumns").writeUInt32(numColumns);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
}
void writeDependentSizedMatrixType(const DependentSizedMatrixType *node) {
const Expr* rows = ( node->getRowExpr() );
W.find("rows").writeExprRef(rows);
const Expr* columns = ( node->getColumnExpr() );
W.find("columns").writeExprRef(columns);
SourceLocation attributeLoc = ( node->getAttributeLoc() );
W.find("attributeLoc").writeSourceLocation(attributeLoc);
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
}
void writeMemberPointerType(const MemberPointerType *node) {
QualType pointeeType = ( node->getPointeeType() );
W.find("pointeeType").writeQualType(pointeeType);
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
const Decl* Cls = ( node->getMostRecentCXXRecordDecl() );
W.find("Cls").writeDeclRef(Cls);
}
void writeObjCObjectPointerType(const ObjCObjectPointerType *node) {
QualType pointeeType = ( node->getPointeeType() );
W.find("pointeeType").writeQualType(pointeeType);
}
void writeObjCObjectType(const ObjCObjectType *node) {
QualType baseType = ( node->getBaseType() );
W.find("baseType").writeQualType(baseType);
llvm::ArrayRef<QualType> typeArgsAsWritten = ( node->getTypeArgsAsWritten() );
W.find("typeArgsAsWritten").writeArray(typeArgsAsWritten);
llvm::ArrayRef<const ObjCProtocolDecl*> qualifiers = ( node->getProtocols() );
W.find("qualifiers").writeArray(qualifiers);
bool isKindOfTypeAsWritten = ( node->isKindOfTypeAsWritten() );
W.find("isKindOfTypeAsWritten").writeBool(isKindOfTypeAsWritten);
}
void writeObjCInterfaceType(const ObjCInterfaceType *node) {
const Decl* declaration = ( node->getDecl()->getCanonicalDecl() );
W.find("declaration").writeDeclRef(declaration);
}
void writeObjCTypeParamType(const ObjCTypeParamType *node) {
const ObjCTypeParamDecl* declaration = ( node->getDecl() );
W.find("declaration").writeObjCTypeParamDeclRef(declaration);
llvm::ArrayRef<const ObjCProtocolDecl*> qualifiers = ( node->getProtocols() );
W.find("qualifiers").writeArray(qualifiers);
}
void writePackExpansionType(const PackExpansionType *node) {
QualType pattern = ( node->getPattern() );
W.find("pattern").writeQualType(pattern);
UnsignedOrNone numExpansions = ( node->getNumExpansions() );
W.find("numExpansions").writeUnsignedOrNone(numExpansions);
}
void writePackIndexingType(const PackIndexingType *node) {
QualType pattern = ( node->getPattern() );
W.find("pattern").writeQualType(pattern);
const Expr* indexExpression = ( node->getIndexExpr() );
W.find("indexExpression").writeExprRef(indexExpression);
bool isFullySubstituted = ( node->isFullySubstituted() );
W.find("isFullySubstituted").writeBool(isFullySubstituted);
llvm::ArrayRef<QualType> expansions = ( node->getExpansions() );
W.find("expansions").writeArray(expansions);
}
void writeParenType(const ParenType *node) {
QualType innerType = ( node->getInnerType() );
W.find("innerType").writeQualType(innerType);
}
void writePipeType(const PipeType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
bool isReadOnly = ( node->isReadOnly() );
W.find("isReadOnly").writeBool(isReadOnly);
}
void writePointerType(const PointerType *node) {
QualType pointeeType = ( node->getPointeeType() );
W.find("pointeeType").writeQualType(pointeeType);
}
void writePredefinedSugarType(const PredefinedSugarType *node) {
uint32_t kind = ( static_cast<uint32_t>(node->getKind()) );
W.find("kind").writeUInt32(kind);
}
void writeLValueReferenceType(const LValueReferenceType *node) {
bool isSpelledAsLValue = ( node->isSpelledAsLValue() );
W.find("isSpelledAsLValue").writeBool(isSpelledAsLValue);
QualType pointeeTypeAsWritten = ( node->getPointeeTypeAsWritten() );
W.find("pointeeTypeAsWritten").writeQualType(pointeeTypeAsWritten);
}
void writeRValueReferenceType(const RValueReferenceType *node) {
QualType pointeeTypeAsWritten = ( node->getPointeeTypeAsWritten() );
W.find("pointeeTypeAsWritten").writeQualType(pointeeTypeAsWritten);
}
void writeSubstBuiltinTemplatePackType(const SubstBuiltinTemplatePackType *node) {
TemplateArgument replacementPack = ( node->getArgumentPack() );
W.find("replacementPack").writeTemplateArgument(replacementPack);
}
void writeSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *node) {
const Decl* associatedDecl = ( node->getAssociatedDecl() );
W.find("associatedDecl").writeDeclRef(associatedDecl);
uint32_t Index = ( node->getIndex() );
W.find("Index").writeUInt32(Index);
bool Final = ( node->getFinal() );
W.find("Final").writeBool(Final);
TemplateArgument replacementPack = ( node->getArgumentPack() );
W.find("replacementPack").writeTemplateArgument(replacementPack);
}
void writeSubstTemplateTypeParmType(const SubstTemplateTypeParmType *node) {
QualType replacementType = ( node->getReplacementType() );
W.find("replacementType").writeQualType(replacementType);
const Decl* associatedDecl = ( node->getAssociatedDecl() );
W.find("associatedDecl").writeDeclRef(associatedDecl);
uint32_t Index = ( node->getIndex() );
W.find("Index").writeUInt32(Index);
UnsignedOrNone PackIndex = ( node->getPackIndex() );
W.find("PackIndex").writeUnsignedOrNone(PackIndex);
bool Final = ( node->getFinal() );
W.find("Final").writeBool(Final);
}
void writeEnumType(const EnumType *node) {
bool OwnsTag = ( node->isTagOwned() );
W.find("OwnsTag").writeBool(OwnsTag);
bool IsCanonical = ( node->isCanonicalUnqualified() );
W.find("IsCanonical").writeBool(IsCanonical);
if ( !IsCanonical ) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
}
if ( !IsCanonical ) {
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
}
const TagDecl* TD = ( node->getDecl() );
W.find("TD").writeTagDeclRef(TD);
}
void writeInjectedClassNameType(const InjectedClassNameType *node) {
bool IsCanonical = ( node->isCanonicalUnqualified() );
W.find("IsCanonical").writeBool(IsCanonical);
if ( !IsCanonical ) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
}
if ( !IsCanonical ) {
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
}
const TagDecl* TD = ( node->getDecl() );
W.find("TD").writeTagDeclRef(TD);
}
void writeRecordType(const RecordType *node) {
bool OwnsTag = ( node->isTagOwned() );
W.find("OwnsTag").writeBool(OwnsTag);
bool IsCanonical = ( node->isCanonicalUnqualified() );
W.find("IsCanonical").writeBool(IsCanonical);
if ( !IsCanonical ) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
}
if ( !IsCanonical ) {
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
}
const TagDecl* TD = ( node->getDecl() );
W.find("TD").writeTagDeclRef(TD);
}
void writeTemplateSpecializationType(const TemplateSpecializationType *node) {
ElaboratedTypeKeyword keyword = ( node->getKeyword() );
W.find("keyword").writeElaboratedTypeKeyword(keyword);
TemplateName templateName = ( node->getTemplateName() );
W.find("templateName").writeTemplateName(templateName);
llvm::ArrayRef<TemplateArgument> args = ( node->template_arguments() );
W.find("args").writeArray(args);
QualType UnderlyingType = ( node->isCanonicalUnqualified() ? QualType() :
node->desugar() );
W.find("UnderlyingType").writeQualType(UnderlyingType);
}
void writeTemplateTypeParmType(const TemplateTypeParmType *node) {
uint32_t depth = ( node->getDepth() );
W.find("depth").writeUInt32(depth);
uint32_t index = ( node->getIndex() );
W.find("index").writeUInt32(index);
bool isParameterPack = ( node->isParameterPack() );
W.find("isParameterPack").writeBool(isParameterPack);
std::optional<const TemplateTypeParmDecl*> declaration = ( makeOptionalFromPointer(
const_cast<const TemplateTypeParmDecl*>(node->getDecl())) );
W.find("declaration").writeOptional(declaration);
}
void writeTypeOfExprType(const TypeOfExprType *node) {
const Expr* expression = ( node->getUnderlyingExpr() );
W.find("expression").writeExprRef(expression);
TypeOfKind kind = ( node->getKind() );
W.find("kind").writeTypeOfKind(kind);
}
void writeTypeOfType(const TypeOfType *node) {
QualType unmodifiedType = ( node->getUnmodifiedType() );
W.find("unmodifiedType").writeQualType(unmodifiedType);
TypeOfKind kind = ( node->getKind() );
W.find("kind").writeTypeOfKind(kind);
}
void writeTypedefType(const TypedefType *node) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
const Decl* declaration = ( node->getDecl() );
W.find("declaration").writeDeclRef(declaration);
QualType UnderlyingType = ( node->desugar() );
W.find("UnderlyingType").writeQualType(UnderlyingType);
bool TypeMatchesDecl = ( node->typeMatchesDecl() );
W.find("TypeMatchesDecl").writeBool(TypeMatchesDecl);
}
void writeUnaryTransformType(const UnaryTransformType *node) {
QualType baseType = ( node->getBaseType() );
W.find("baseType").writeQualType(baseType);
QualType underlyingType = ( node->getUnderlyingType() );
W.find("underlyingType").writeQualType(underlyingType);
UnaryTransformType::UTTKind transform = ( node->getUTTKind() );
W.find("transform").writeUnaryTypeTransformKind(transform);
}
void writeUnresolvedUsingType(const UnresolvedUsingType *node) {
bool IsCanonical = ( node->isCanonicalUnqualified() );
W.find("IsCanonical").writeBool(IsCanonical);
if ( !IsCanonical ) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
}
if ( !IsCanonical ) {
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
}
const Decl* D = ( node->getDecl() );
W.find("D").writeDeclRef(D);
}
void writeUsingType(const UsingType *node) {
ElaboratedTypeKeyword Keyword = ( node->getKeyword() );
W.find("Keyword").writeElaboratedTypeKeyword(Keyword);
NestedNameSpecifier Qualifier = ( node->getQualifier() );
W.find("Qualifier").writeNestedNameSpecifier(Qualifier);
const UsingShadowDecl* D = ( node->getDecl() );
W.find("D").writeUsingShadowDeclRef(D);
QualType UnderlyingType = ( node->desugar() );
W.find("UnderlyingType").writeQualType(UnderlyingType);
}
void writeVectorType(const VectorType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
uint32_t numElements = ( node->getNumElements() );
W.find("numElements").writeUInt32(numElements);
VectorKind vectorKind = ( node->getVectorKind() );
W.find("vectorKind").writeVectorKind(vectorKind);
}
void writeExtVectorType(const ExtVectorType *node) {
QualType elementType = ( node->getElementType() );
W.find("elementType").writeQualType(elementType);
uint32_t numElements = ( node->getNumElements() );
W.find("numElements").writeUInt32(numElements);
}
};

View File

@ -0,0 +1,430 @@
//===--- Attr.h - Classes for representing attributes ----------*- 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 Attr interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "clang/AST/ASTFwd.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/AttributeCommonInfo.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Support/Compiler.h"
#include "llvm/Frontend/HLSL/HLSLResource.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
namespace clang {
class ASTContext;
class AttributeCommonInfo;
class FunctionDecl;
class OMPTraitInfo;
class OpenACCClause;
/// Attr - This represents one attribute.
class Attr : public AttributeCommonInfo {
private:
LLVM_PREFERRED_TYPE(attr::Kind)
unsigned AttrKind : 16;
protected:
/// An index into the spelling list of an
/// attribute defined in Attr.td file.
LLVM_PREFERRED_TYPE(bool)
unsigned Inherited : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned IsPackExpansion : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned Implicit : 1;
// FIXME: These are properties of the attribute kind, not state for this
// instance of the attribute.
LLVM_PREFERRED_TYPE(bool)
unsigned IsLateParsed : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned InheritEvenIfAlreadyPresent : 1;
void *operator new(size_t bytes) noexcept {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
}
void operator delete(void *data) noexcept {
llvm_unreachable("Attrs cannot be released with regular 'delete'.");
}
public:
// Forward so that the regular new and delete do not hide global ones.
void *operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 8) noexcept {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
return ::operator delete(Ptr, C, Alignment);
}
protected:
Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed)
: AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
InheritEvenIfAlreadyPresent(false) {}
public:
attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
unsigned getSpellingListIndex() const {
return getAttributeSpellingListIndex();
}
const char *getSpelling() const;
SourceLocation getLocation() const { return getRange().getBegin(); }
bool isInherited() const { return Inherited; }
/// Returns true if the attribute has been implicitly created instead
/// of explicitly written by the user.
bool isImplicit() const { return Implicit; }
void setImplicit(bool I) { Implicit = I; }
void setPackExpansion(bool PE) { IsPackExpansion = PE; }
bool isPackExpansion() const { return IsPackExpansion; }
// Clone this attribute.
Attr *clone(ASTContext &C) const;
bool isLateParsed() const { return IsLateParsed; }
// Pretty print this attribute.
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
static StringRef getDocumentation(attr::Kind);
};
class TypeAttr : public Attr {
protected:
TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed)
: Attr(Context, CommonInfo, AK, IsLateParsed) {}
public:
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstTypeAttr &&
A->getKind() <= attr::LastTypeAttr;
}
};
class StmtAttr : public Attr {
protected:
StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed)
: Attr(Context, CommonInfo, AK, IsLateParsed) {}
public:
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstStmtAttr &&
A->getKind() <= attr::LastStmtAttr;
}
};
class InheritableAttr : public Attr {
protected:
InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: Attr(Context, CommonInfo, AK, IsLateParsed) {
this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
}
public:
void setInherited(bool I) { Inherited = I; }
/// Should this attribute be inherited from a prior declaration even if it's
/// explicitly provided in the current declaration?
bool shouldInheritEvenIfAlreadyPresent() const {
return InheritEvenIfAlreadyPresent;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstInheritableAttr &&
A->getKind() <= attr::LastInheritableAttr;
}
};
class DeclOrStmtAttr : public InheritableAttr {
protected:
DeclOrStmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstDeclOrStmtAttr &&
A->getKind() <= attr::LastDeclOrStmtAttr;
}
};
class InheritableParamAttr : public InheritableAttr {
protected:
InheritableParamAttr(ASTContext &Context,
const AttributeCommonInfo &CommonInfo, attr::Kind AK,
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
: InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstInheritableParamAttr &&
A->getKind() <= attr::LastInheritableParamAttr;
}
};
class InheritableParamOrStmtAttr : public InheritableParamAttr {
protected:
InheritableParamOrStmtAttr(ASTContext &Context,
const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstInheritableParamOrStmtAttr &&
A->getKind() <= attr::LastInheritableParamOrStmtAttr;
}
};
class HLSLAnnotationAttr : public InheritableAttr {
protected:
HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstHLSLAnnotationAttr &&
A->getKind() <= attr::LastHLSLAnnotationAttr;
}
};
class HLSLSemanticBaseAttr : public HLSLAnnotationAttr {
protected:
HLSLSemanticBaseAttr(ASTContext &Context,
const AttributeCommonInfo &CommonInfo, attr::Kind AK,
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
: HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstHLSLSemanticBaseAttr &&
A->getKind() <= attr::LastHLSLSemanticBaseAttr;
}
};
/// A parameter attribute which changes the argument-passing ABI rule
/// for the parameter.
class ParameterABIAttr : public InheritableParamAttr {
protected:
ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
attr::Kind AK, bool IsLateParsed,
bool InheritEvenIfAlreadyPresent)
: InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
InheritEvenIfAlreadyPresent) {}
public:
ParameterABI getABI() const;
static bool classof(const Attr *A) {
return A->getKind() >= attr::FirstParameterABIAttr &&
A->getKind() <= attr::LastParameterABIAttr;
}
};
/// A single parameter index whose accessors require each use to make explicit
/// the parameter index encoding needed.
class ParamIdx {
// Idx is exposed only via accessors that specify specific encodings.
unsigned Idx : 30;
LLVM_PREFERRED_TYPE(bool)
unsigned HasThis : 1;
LLVM_PREFERRED_TYPE(bool)
unsigned IsValid : 1;
void assertComparable(const ParamIdx &I) const {
assert(isValid() && I.isValid() &&
"ParamIdx must be valid to be compared");
// It's possible to compare indices from separate functions, but so far
// it's not proven useful. Moreover, it might be confusing because a
// comparison on the results of getASTIndex might be inconsistent with a
// comparison on the ParamIdx objects themselves.
assert(HasThis == I.HasThis &&
"ParamIdx must be for the same function to be compared");
}
public:
/// Construct an invalid parameter index (\c isValid returns false and
/// accessors fail an assert).
ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}
/// \param Idx is the parameter index as it is normally specified in
/// attributes in the source: one-origin including any C++ implicit this
/// parameter.
///
/// \param D is the declaration containing the parameters. It is used to
/// determine if there is a C++ implicit this parameter.
ParamIdx(unsigned Idx, const Decl *D)
: Idx(Idx), HasThis(false), IsValid(true) {
assert(Idx >= 1 && "Idx must be one-origin");
if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(D))
HasThis = MethodDecl->isImplicitObjectMemberFunction();
}
/// A type into which \c ParamIdx can be serialized.
///
/// A static assertion that it's of the correct size follows the \c ParamIdx
/// class definition.
typedef uint32_t SerialType;
/// Produce a representation that can later be passed to \c deserialize to
/// construct an equivalent \c ParamIdx.
SerialType serialize() const {
return *reinterpret_cast<const SerialType *>(this);
}
/// Construct from a result from \c serialize.
static ParamIdx deserialize(SerialType S) {
// Using this two-step static_cast via void * instead of reinterpret_cast
// silences a -Wstrict-aliasing false positive from GCC7 and earlier.
void *ParamIdxPtr = static_cast<void *>(&S);
ParamIdx P(*static_cast<ParamIdx *>(ParamIdxPtr));
assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin");
return P;
}
/// Is this parameter index valid?
bool isValid() const { return IsValid; }
/// Get the parameter index as it would normally be encoded for attributes at
/// the source level of representation: one-origin including any C++ implicit
/// this parameter.
///
/// This encoding thus makes sense for diagnostics, pretty printing, and
/// constructing new attributes from a source-like specification.
unsigned getSourceIndex() const {
assert(isValid() && "ParamIdx must be valid");
return Idx;
}
/// Get the parameter index as it would normally be encoded at the AST level
/// of representation: zero-origin not including any C++ implicit this
/// parameter.
///
/// This is the encoding primarily used in Sema. However, in diagnostics,
/// Sema uses \c getSourceIndex instead.
unsigned getASTIndex() const {
assert(isValid() && "ParamIdx must be valid");
assert(Idx >= 1 + HasThis &&
"stored index must be base-1 and not specify C++ implicit this");
return Idx - 1 - HasThis;
}
/// Get the parameter index as it would normally be encoded at the LLVM level
/// of representation: zero-origin including any C++ implicit this parameter.
///
/// This is the encoding primarily used in CodeGen.
unsigned getLLVMIndex() const {
assert(isValid() && "ParamIdx must be valid");
assert(Idx >= 1 && "stored index must be base-1");
return Idx - 1;
}
bool operator==(const ParamIdx &I) const {
assertComparable(I);
return Idx == I.Idx;
}
bool operator!=(const ParamIdx &I) const {
assertComparable(I);
return Idx != I.Idx;
}
bool operator<(const ParamIdx &I) const {
assertComparable(I);
return Idx < I.Idx;
}
bool operator>(const ParamIdx &I) const {
assertComparable(I);
return Idx > I.Idx;
}
bool operator<=(const ParamIdx &I) const {
assertComparable(I);
return Idx <= I.Idx;
}
bool operator>=(const ParamIdx &I) const {
assertComparable(I);
return Idx >= I.Idx;
}
};
static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
"ParamIdx does not fit its serialization type");
#include "clang/AST/Attrs.inc" // IWYU pragma: export
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
const Attr *At) {
DB.AddTaggedVal(reinterpret_cast<uint64_t>(At), DiagnosticsEngine::ak_attr);
return DB;
}
inline ParameterABI ParameterABIAttr::getABI() const {
switch (getKind()) {
case attr::SwiftContext:
return ParameterABI::SwiftContext;
case attr::SwiftAsyncContext:
return ParameterABI::SwiftAsyncContext;
case attr::SwiftErrorResult:
return ParameterABI::SwiftErrorResult;
case attr::SwiftIndirectResult:
return ParameterABI::SwiftIndirectResult;
case attr::HLSLParamModifier: {
const auto *A = cast<HLSLParamModifierAttr>(this);
if (A->isOut())
return ParameterABI::HLSLOut;
if (A->isInOut())
return ParameterABI::HLSLInOut;
return ParameterABI::Ordinary;
}
default:
llvm_unreachable("bad parameter ABI attribute kind");
}
}
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,141 @@
//===- AttrIterator.h - Classes for attribute iteration ---------*- 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 Attr vector and specific_attr_iterator interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTRITERATOR_H
#define LLVM_CLANG_AST_ATTRITERATOR_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ADL.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace clang {
class Attr;
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
using AttrVec = SmallVector<Attr *, 4>;
/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specific type.
template <typename SpecificAttr, typename Container = AttrVec>
class specific_attr_iterator {
using Iterator = typename Container::const_iterator;
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
/// specifically requested, we don't necessarily advance this all the
/// way. Instead, we advance it when an operation is requested; if the
/// operation is acting on what should be a past-the-end iterator,
/// then we offer no guarantees, but this way we do not dereference a
/// past-the-end iterator when we move to a past-the-end position.
mutable Iterator Current;
void AdvanceToNext() const {
while (!isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(Iterator I) const {
while (Current != I && !isa<SpecificAttr>(*Current))
++Current;
}
public:
using value_type = SpecificAttr *;
using reference = SpecificAttr *;
using pointer = SpecificAttr *;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
specific_attr_iterator() = default;
explicit specific_attr_iterator(Iterator i) : Current(i) {}
reference operator*() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
pointer operator->() const {
AdvanceToNext();
return cast<SpecificAttr>(*Current);
}
specific_attr_iterator& operator++() {
++Current;
return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
}
friend bool operator==(specific_attr_iterator Left,
specific_attr_iterator Right) {
assert((Left.Current == nullptr) == (Right.Current == nullptr));
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
else
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
}
friend bool operator!=(specific_attr_iterator Left,
specific_attr_iterator Right) {
return !(Left == Right);
}
};
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_begin(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.begin());
}
template <typename SpecificAttr, typename Container>
inline specific_attr_iterator<SpecificAttr, Container>
specific_attr_end(const Container& container) {
return specific_attr_iterator<SpecificAttr, Container>(container.end());
}
template <typename SpecificAttr, typename Container>
inline bool hasSpecificAttr(const Container& container) {
return specific_attr_begin<SpecificAttr>(container) !=
specific_attr_end<SpecificAttr>(container);
}
template <typename SpecificAttr, typename Container>
inline auto *getSpecificAttr(const Container &container) {
using ValueTy = llvm::detail::ValueOfRange<Container>;
using ValuePointeeTy = std::remove_pointer_t<ValueTy>;
using IterTy = std::conditional_t<std::is_const_v<ValuePointeeTy>,
const SpecificAttr, SpecificAttr>;
auto It = specific_attr_begin<IterTy>(container);
return It != specific_attr_end<IterTy>(container) ? *It : nullptr;
}
template <typename SpecificAttr, typename Container>
inline auto getSpecificAttrs(const Container &container) {
using ValueTy = llvm::detail::ValueOfRange<Container>;
using ValuePointeeTy = std::remove_pointer_t<ValueTy>;
using IterTy = std::conditional_t<std::is_const_v<ValuePointeeTy>,
const SpecificAttr, SpecificAttr>;
auto Begin = specific_attr_begin<IterTy>(container);
auto End = specific_attr_end<IterTy>(container);
return llvm::make_range(Begin, End);
}
} // namespace clang
#endif // LLVM_CLANG_AST_ATTRITERATOR_H

View File

@ -0,0 +1,251 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* Attribute text node traverser *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: Attr.td *|
|* *|
\*===----------------------------------------------------------------------===*/
void VisitAMDGPUFlatWorkGroupSizeAttr(const AMDGPUFlatWorkGroupSizeAttr *A) {
const auto *SA = cast<AMDGPUFlatWorkGroupSizeAttr>(A); (void)SA;
Visit(SA->getMin());
Visit(SA->getMax());
}
void VisitAMDGPUMaxNumWorkGroupsAttr(const AMDGPUMaxNumWorkGroupsAttr *A) {
const auto *SA = cast<AMDGPUMaxNumWorkGroupsAttr>(A); (void)SA;
Visit(SA->getMaxNumWorkGroupsX());
Visit(SA->getMaxNumWorkGroupsY());
Visit(SA->getMaxNumWorkGroupsZ());
}
void VisitAMDGPUWavesPerEUAttr(const AMDGPUWavesPerEUAttr *A) {
const auto *SA = cast<AMDGPUWavesPerEUAttr>(A); (void)SA;
Visit(SA->getMin());
Visit(SA->getMax());
}
void VisitAcquireCapabilityAttr(const AcquireCapabilityAttr *A) {
const auto *SA = cast<AcquireCapabilityAttr>(A); (void)SA;
for (AcquireCapabilityAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AcquireCapabilityAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAcquiredAfterAttr(const AcquiredAfterAttr *A) {
const auto *SA = cast<AcquiredAfterAttr>(A); (void)SA;
for (AcquiredAfterAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AcquiredAfterAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAcquiredBeforeAttr(const AcquiredBeforeAttr *A) {
const auto *SA = cast<AcquiredBeforeAttr>(A); (void)SA;
for (AcquiredBeforeAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AcquiredBeforeAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAlignValueAttr(const AlignValueAttr *A) {
const auto *SA = cast<AlignValueAttr>(A); (void)SA;
Visit(SA->getAlignment());
}
void VisitAlignedAttr(const AlignedAttr *A) {
const auto *SA = cast<AlignedAttr>(A); (void)SA;
if (SA->isAlignmentExpr())
Visit(SA->getAlignmentExpr());
}
void VisitAnnotateAttr(const AnnotateAttr *A) {
const auto *SA = cast<AnnotateAttr>(A); (void)SA;
for (AnnotateAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AnnotateAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAnnotateTypeAttr(const AnnotateTypeAttr *A) {
const auto *SA = cast<AnnotateTypeAttr>(A); (void)SA;
for (AnnotateTypeAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AnnotateTypeAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAssertCapabilityAttr(const AssertCapabilityAttr *A) {
const auto *SA = cast<AssertCapabilityAttr>(A); (void)SA;
for (AssertCapabilityAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (AssertCapabilityAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitAssumeAlignedAttr(const AssumeAlignedAttr *A) {
const auto *SA = cast<AssumeAlignedAttr>(A); (void)SA;
Visit(SA->getAlignment());
Visit(SA->getOffset());
}
void VisitCUDAClusterDimsAttr(const CUDAClusterDimsAttr *A) {
const auto *SA = cast<CUDAClusterDimsAttr>(A); (void)SA;
Visit(SA->getX());
Visit(SA->getY());
Visit(SA->getZ());
}
void VisitCUDALaunchBoundsAttr(const CUDALaunchBoundsAttr *A) {
const auto *SA = cast<CUDALaunchBoundsAttr>(A); (void)SA;
Visit(SA->getMaxThreads());
Visit(SA->getMinBlocks());
Visit(SA->getMaxBlocks());
}
void VisitCXXAssumeAttr(const CXXAssumeAttr *A) {
const auto *SA = cast<CXXAssumeAttr>(A); (void)SA;
Visit(SA->getAssumption());
}
void VisitCodeAlignAttr(const CodeAlignAttr *A) {
const auto *SA = cast<CodeAlignAttr>(A); (void)SA;
Visit(SA->getAlignment());
}
void VisitConstructorAttr(const ConstructorAttr *A) {
const auto *SA = cast<ConstructorAttr>(A); (void)SA;
Visit(SA->getPriority());
}
void VisitCountedByAttr(const CountedByAttr *A) {
const auto *SA = cast<CountedByAttr>(A); (void)SA;
Visit(SA->getCount());
}
void VisitCountedByOrNullAttr(const CountedByOrNullAttr *A) {
const auto *SA = cast<CountedByOrNullAttr>(A); (void)SA;
Visit(SA->getCount());
}
void VisitDestructorAttr(const DestructorAttr *A) {
const auto *SA = cast<DestructorAttr>(A); (void)SA;
Visit(SA->getPriority());
}
void VisitDiagnoseIfAttr(const DiagnoseIfAttr *A) {
const auto *SA = cast<DiagnoseIfAttr>(A); (void)SA;
Visit(SA->getCond());
}
void VisitEnableIfAttr(const EnableIfAttr *A) {
const auto *SA = cast<EnableIfAttr>(A); (void)SA;
Visit(SA->getCond());
}
void VisitExtVectorTypeAttr(const ExtVectorTypeAttr *A) {
const auto *SA = cast<ExtVectorTypeAttr>(A); (void)SA;
Visit(SA->getNumElements());
}
void VisitFormatMatchesAttr(const FormatMatchesAttr *A) {
const auto *SA = cast<FormatMatchesAttr>(A); (void)SA;
Visit(SA->getExpectedFormat());
}
void VisitGuardedByAttr(const GuardedByAttr *A) {
const auto *SA = cast<GuardedByAttr>(A); (void)SA;
Visit(SA->getArg());
}
void VisitLockReturnedAttr(const LockReturnedAttr *A) {
const auto *SA = cast<LockReturnedAttr>(A); (void)SA;
Visit(SA->getArg());
}
void VisitLocksExcludedAttr(const LocksExcludedAttr *A) {
const auto *SA = cast<LocksExcludedAttr>(A); (void)SA;
for (LocksExcludedAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (LocksExcludedAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitLoopHintAttr(const LoopHintAttr *A) {
const auto *SA = cast<LoopHintAttr>(A); (void)SA;
Visit(SA->getValue());
}
void VisitNonAllocatingAttr(const NonAllocatingAttr *A) {
const auto *SA = cast<NonAllocatingAttr>(A); (void)SA;
Visit(SA->getCond());
}
void VisitNonBlockingAttr(const NonBlockingAttr *A) {
const auto *SA = cast<NonBlockingAttr>(A); (void)SA;
Visit(SA->getCond());
}
void VisitOMPAllocateDeclAttr(const OMPAllocateDeclAttr *A) {
const auto *SA = cast<OMPAllocateDeclAttr>(A); (void)SA;
Visit(SA->getAllocator());
Visit(SA->getAlignment());
}
void VisitOMPDeclareSimdDeclAttr(const OMPDeclareSimdDeclAttr *A) {
const auto *SA = cast<OMPDeclareSimdDeclAttr>(A); (void)SA;
Visit(SA->getSimdlen());
for (OMPDeclareSimdDeclAttr::uniforms_iterator I = SA->uniforms_begin(), E = SA->uniforms_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareSimdDeclAttr::aligneds_iterator I = SA->aligneds_begin(), E = SA->aligneds_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareSimdDeclAttr::alignments_iterator I = SA->alignments_begin(), E = SA->alignments_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareSimdDeclAttr::linears_iterator I = SA->linears_begin(), E = SA->linears_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareSimdDeclAttr::steps_iterator I = SA->steps_begin(), E = SA->steps_end(); I != E; ++I)
Visit(*I);
}
void VisitOMPDeclareTargetDeclAttr(const OMPDeclareTargetDeclAttr *A) {
const auto *SA = cast<OMPDeclareTargetDeclAttr>(A); (void)SA;
Visit(SA->getIndirectExpr());
}
void VisitOMPDeclareVariantAttr(const OMPDeclareVariantAttr *A) {
const auto *SA = cast<OMPDeclareVariantAttr>(A); (void)SA;
Visit(SA->getVariantFuncRef());
for (OMPDeclareVariantAttr::adjustArgsNothing_iterator I = SA->adjustArgsNothing_begin(), E = SA->adjustArgsNothing_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareVariantAttr::adjustArgsNeedDevicePtr_iterator I = SA->adjustArgsNeedDevicePtr_begin(), E = SA->adjustArgsNeedDevicePtr_end(); I != E; ++I)
Visit(*I);
for (OMPDeclareVariantAttr::adjustArgsNeedDeviceAddr_iterator I = SA->adjustArgsNeedDeviceAddr_begin(), E = SA->adjustArgsNeedDeviceAddr_end(); I != E; ++I)
Visit(*I);
}
void VisitOMPReferencedVarAttr(const OMPReferencedVarAttr *A) {
const auto *SA = cast<OMPReferencedVarAttr>(A); (void)SA;
Visit(SA->getRef());
}
void VisitPtGuardedByAttr(const PtGuardedByAttr *A) {
const auto *SA = cast<PtGuardedByAttr>(A); (void)SA;
Visit(SA->getArg());
}
void VisitReleaseCapabilityAttr(const ReleaseCapabilityAttr *A) {
const auto *SA = cast<ReleaseCapabilityAttr>(A); (void)SA;
for (ReleaseCapabilityAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (ReleaseCapabilityAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitReqdWorkGroupSizeAttr(const ReqdWorkGroupSizeAttr *A) {
const auto *SA = cast<ReqdWorkGroupSizeAttr>(A); (void)SA;
Visit(SA->getXDim());
Visit(SA->getYDim());
Visit(SA->getZDim());
}
void VisitRequiresCapabilityAttr(const RequiresCapabilityAttr *A) {
const auto *SA = cast<RequiresCapabilityAttr>(A); (void)SA;
for (RequiresCapabilityAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (RequiresCapabilityAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitRestrictAttr(const RestrictAttr *A) {
const auto *SA = cast<RestrictAttr>(A); (void)SA;
Visit(SA->getDeallocator());
}
void VisitSizedByAttr(const SizedByAttr *A) {
const auto *SA = cast<SizedByAttr>(A); (void)SA;
Visit(SA->getSize());
}
void VisitSizedByOrNullAttr(const SizedByOrNullAttr *A) {
const auto *SA = cast<SizedByOrNullAttr>(A); (void)SA;
Visit(SA->getSize());
}
void VisitSwiftVersionedAdditionAttr(const SwiftVersionedAdditionAttr *A) {
const auto *SA = cast<SwiftVersionedAdditionAttr>(A); (void)SA;
Visit(SA->getAdditionalAttr());
}
void VisitTryAcquireCapabilityAttr(const TryAcquireCapabilityAttr *A) {
const auto *SA = cast<TryAcquireCapabilityAttr>(A); (void)SA;
Visit(SA->getSuccessValue());
for (TryAcquireCapabilityAttr::args_iterator I = SA->args_begin(), E = SA->args_end(); I != E; ++I)
Visit(*I);
for (TryAcquireCapabilityAttr::delayedArgs_iterator I = SA->delayedArgs_begin(), E = SA->delayedArgs_end(); I != E; ++I)
Visit(*I);
}
void VisitWorkGroupSizeHintAttr(const WorkGroupSizeHintAttr *A) {
const auto *SA = cast<WorkGroupSizeHintAttr>(A); (void)SA;
Visit(SA->getXDim());
Visit(SA->getYDim());
Visit(SA->getZDim());
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
//===- AttrVisitor.h - Visitor for Attr subclasses --------------*- 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 AttrVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTRVISITOR_H
#define LLVM_CLANG_AST_ATTRVISITOR_H
#include "clang/AST/Attr.h"
namespace clang {
namespace attrvisitor {
/// A simple visitor class that helps create attribute visitors.
template <template <typename> class Ptr, typename ImplClass,
typename RetTy = void, class... ParamTys>
class Base {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME) \
return static_cast<ImplClass *>(this)->Visit##NAME(static_cast<PTR(NAME)>(A))
RetTy Visit(PTR(Attr) A) {
switch (A->getKind()) {
#define ATTR(NAME) \
case attr::NAME: \
DISPATCH(NAME##Attr);
#include "clang/Basic/AttrList.inc"
}
llvm_unreachable("Attr that isn't part of AttrList.inc!");
}
// If the implementation chooses not to implement a certain visit
// method, fall back to the parent.
#define ATTR(NAME) \
RetTy Visit##NAME##Attr(PTR(NAME##Attr) A) { DISPATCH(Attr); }
#include "clang/Basic/AttrList.inc"
RetTy VisitAttr(PTR(Attr)) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
} // namespace attrvisitor
/// A simple visitor class that helps create attribute visitors.
///
/// This class does not preserve constness of Attr pointers (see
/// also ConstAttrVisitor).
template <typename ImplClass, typename RetTy = void, typename... ParamTys>
class AttrVisitor : public attrvisitor::Base<std::add_pointer, ImplClass, RetTy,
ParamTys...> {};
/// A simple visitor class that helps create attribute visitors.
///
/// This class preserves constness of Attr pointers (see also
/// AttrVisitor).
template <typename ImplClass, typename RetTy = void, typename... ParamTys>
class ConstAttrVisitor
: public attrvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy,
ParamTys...> {};
} // namespace clang
#endif // LLVM_CLANG_AST_ATTRVISITOR_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,129 @@
//===--- Availability.h - Classes for availability --------------*- 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 files defines some classes that implement availability checking.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AVAILABILITY_H
#define LLVM_CLANG_AST_AVAILABILITY_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/VersionTuple.h"
namespace clang {
/// One specifier in an @available expression.
///
/// \code
/// @available(macos 10.10, *)
/// \endcode
///
/// Here, 'macos 10.10' and '*' both map to an instance of this type.
///
class AvailabilitySpec {
/// Represents the version that this specifier requires. If the host OS
/// version is greater than or equal to Version, the @available will evaluate
/// to true.
VersionTuple Version;
/// Name of the platform that Version corresponds to.
StringRef Platform;
SourceLocation BeginLoc, EndLoc;
public:
AvailabilitySpec(VersionTuple Version, StringRef Platform,
SourceLocation BeginLoc, SourceLocation EndLoc)
: Version(Version), Platform(Platform), BeginLoc(BeginLoc),
EndLoc(EndLoc) {}
/// This constructor is used when representing the '*' case.
AvailabilitySpec(SourceLocation StarLoc)
: BeginLoc(StarLoc), EndLoc(StarLoc) {}
VersionTuple getVersion() const { return Version; }
StringRef getPlatform() const { return Platform; }
SourceLocation getBeginLoc() const { return BeginLoc; }
SourceLocation getEndLoc() const { return EndLoc; }
/// Returns true when this represents the '*' case.
bool isOtherPlatformSpec() const { return Version.empty(); }
};
class Decl;
/// Storage of availability attributes for a declaration.
struct AvailabilityInfo {
/// The domain is the platform for which this availability info applies to.
llvm::SmallString<32> Domain;
VersionTuple Introduced;
VersionTuple Deprecated;
VersionTuple Obsoleted;
bool Unavailable = false;
bool UnconditionallyDeprecated = false;
bool UnconditionallyUnavailable = false;
AvailabilityInfo() = default;
/// Determine if this AvailabilityInfo represents the default availability.
bool isDefault() const { return *this == AvailabilityInfo(); }
/// Check if the symbol has been obsoleted.
bool isObsoleted() const { return !Obsoleted.empty(); }
/// Check if the symbol is unavailable unconditionally or
/// on the active platform and os version.
bool isUnavailable() const {
return Unavailable || isUnconditionallyUnavailable();
}
/// Check if the symbol is unconditionally deprecated.
///
/// i.e. \code __attribute__((deprecated)) \endcode
bool isUnconditionallyDeprecated() const { return UnconditionallyDeprecated; }
/// Check if the symbol is unconditionally unavailable.
///
/// i.e. \code __attribute__((unavailable)) \endcode
bool isUnconditionallyUnavailable() const {
return UnconditionallyUnavailable;
}
/// Augments the existing information with additional constraints provided by
/// \c Other.
void mergeWith(AvailabilityInfo Other);
AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D,
VersionTuple O, bool U, bool UD, bool UU)
: Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O),
Unavailable(U), UnconditionallyDeprecated(UD),
UnconditionallyUnavailable(UU) {}
friend bool operator==(const AvailabilityInfo &Lhs,
const AvailabilityInfo &Rhs);
public:
static AvailabilityInfo createFromDecl(const Decl *Decl);
};
inline bool operator==(const AvailabilityInfo &Lhs,
const AvailabilityInfo &Rhs) {
return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted,
Lhs.Unavailable, Lhs.UnconditionallyDeprecated,
Lhs.UnconditionallyUnavailable) ==
std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted,
Rhs.Unavailable, Rhs.UnconditionallyDeprecated,
Rhs.UnconditionallyUnavailable);
}
} // end namespace clang
#endif

View File

@ -0,0 +1,85 @@
//===- BaseSubobject.h - BaseSubobject class --------------------*- 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 provides a definition of the BaseSubobject class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BASESUBOBJECT_H
#define LLVM_CLANG_AST_BASESUBOBJECT_H
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/type_traits.h"
#include <cstdint>
#include <utility>
namespace clang {
class CXXRecordDecl;
// BaseSubobject - Uniquely identifies a direct or indirect base class.
// Stores both the base class decl and the offset from the most derived class to
// the base class. Used for vtable and VTT generation.
class BaseSubobject {
/// Base - The base class declaration.
const CXXRecordDecl *Base;
/// BaseOffset - The offset from the most derived class to the base class.
CharUnits BaseOffset;
public:
BaseSubobject() = default;
BaseSubobject(const CXXRecordDecl *Base, CharUnits BaseOffset)
: Base(Base), BaseOffset(BaseOffset) {}
/// getBase - Returns the base class declaration.
const CXXRecordDecl *getBase() const { return Base; }
/// getBaseOffset - Returns the base class offset.
CharUnits getBaseOffset() const { return BaseOffset; }
friend bool operator==(const BaseSubobject &LHS, const BaseSubobject &RHS) {
return LHS.Base == RHS.Base && LHS.BaseOffset == RHS.BaseOffset;
}
};
} // namespace clang
namespace llvm {
template<> struct DenseMapInfo<clang::BaseSubobject> {
static clang::BaseSubobject getEmptyKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getEmptyKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getEmptyKey()));
}
static clang::BaseSubobject getTombstoneKey() {
return clang::BaseSubobject(
DenseMapInfo<const clang::CXXRecordDecl *>::getTombstoneKey(),
clang::CharUnits::fromQuantity(DenseMapInfo<int64_t>::getTombstoneKey()));
}
static unsigned getHashValue(const clang::BaseSubobject &Base) {
using PairTy = std::pair<const clang::CXXRecordDecl *, clang::CharUnits>;
return DenseMapInfo<PairTy>::getHashValue(PairTy(Base.getBase(),
Base.getBaseOffset()));
}
static bool isEqual(const clang::BaseSubobject &LHS,
const clang::BaseSubobject &RHS) {
return LHS == RHS;
}
};
} // namespace llvm
#endif // LLVM_CLANG_AST_BASESUBOBJECT_H

View File

@ -0,0 +1,344 @@
//===-- BuiltinTypes.def - Metadata about BuiltinTypes ----------*- 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 database about various builtin singleton types.
//
// BuiltinType::Id is the enumerator defining the type.
//
// Context.SingletonId is the global singleton of this type. Some global
// singletons are shared by multiple types.
//
// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been
// covered by any other #define. Defining this macro covers all
// the builtins.
//
// SIGNED_TYPE(Id, SingletonId) - A signed integral type.
//
// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type.
//
// FLOATING_TYPE(Id, SingletonId) - A floating-point type.
//
// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder
// types are used to perform context-sensitive checking of specific
// forms of expression.
//
// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds
// to a builtin which uses a shared singleton type.
//
//===----------------------------------------------------------------------===//
#ifndef SIGNED_TYPE
#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef UNSIGNED_TYPE
#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef FLOATING_TYPE
#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef PLACEHOLDER_TYPE
#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId)
#endif
#ifndef SHARED_SINGLETON_TYPE
#define SHARED_SINGLETON_TYPE(Expansion) Expansion
#endif
//===- Builtin Types ------------------------------------------------------===//
// void
BUILTIN_TYPE(Void, VoidTy)
//===- Unsigned Types -----------------------------------------------------===//
// 'bool' in C++, '_Bool' in C99
UNSIGNED_TYPE(Bool, BoolTy)
// 'char' for targets where it's unsigned
SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy))
// 'unsigned char', explicitly qualified
UNSIGNED_TYPE(UChar, UnsignedCharTy)
// 'wchar_t' for targets where it's unsigned
SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy))
// 'char8_t' in C++20 (proposed)
UNSIGNED_TYPE(Char8, Char8Ty)
// 'char16_t' in C++
UNSIGNED_TYPE(Char16, Char16Ty)
// 'char32_t' in C++
UNSIGNED_TYPE(Char32, Char32Ty)
// 'unsigned short'
UNSIGNED_TYPE(UShort, UnsignedShortTy)
// 'unsigned int'
UNSIGNED_TYPE(UInt, UnsignedIntTy)
// 'unsigned long'
UNSIGNED_TYPE(ULong, UnsignedLongTy)
// 'unsigned long long'
UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy)
// '__uint128_t'
UNSIGNED_TYPE(UInt128, UnsignedInt128Ty)
//===- Signed Types -------------------------------------------------------===//
// 'char' for targets where it's signed
SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy))
// 'signed char', explicitly qualified
SIGNED_TYPE(SChar, SignedCharTy)
// 'wchar_t' for targets where it's signed
SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy))
// 'short' or 'signed short'
SIGNED_TYPE(Short, ShortTy)
// 'int' or 'signed int'
SIGNED_TYPE(Int, IntTy)
// 'long' or 'signed long'
SIGNED_TYPE(Long, LongTy)
// 'long long' or 'signed long long'
SIGNED_TYPE(LongLong, LongLongTy)
// '__int128_t'
SIGNED_TYPE(Int128, Int128Ty)
//===- Fixed point types --------------------------------------------------===//
// 'short _Accum'
SIGNED_TYPE(ShortAccum, ShortAccumTy)
// '_Accum'
SIGNED_TYPE(Accum, AccumTy)
// 'long _Accum'
SIGNED_TYPE(LongAccum, LongAccumTy)
// 'unsigned short _Accum'
UNSIGNED_TYPE(UShortAccum, UnsignedShortAccumTy)
// 'unsigned _Accum'
UNSIGNED_TYPE(UAccum, UnsignedAccumTy)
// 'unsigned long _Accum'
UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy)
// 'short _Fract'
SIGNED_TYPE(ShortFract, ShortFractTy)
// '_Fract'
SIGNED_TYPE(Fract, FractTy)
// 'long _Fract'
SIGNED_TYPE(LongFract, LongFractTy)
// 'unsigned short _Fract'
UNSIGNED_TYPE(UShortFract, UnsignedShortFractTy)
// 'unsigned _Fract'
UNSIGNED_TYPE(UFract, UnsignedFractTy)
// 'unsigned long _Fract'
UNSIGNED_TYPE(ULongFract, UnsignedLongFractTy)
// '_Sat short _Accum'
SIGNED_TYPE(SatShortAccum, SatShortAccumTy)
// '_Sat _Accum'
SIGNED_TYPE(SatAccum, SatAccumTy)
// '_Sat long _Accum'
SIGNED_TYPE(SatLongAccum, SatLongAccumTy)
// '_Sat unsigned short _Accum'
UNSIGNED_TYPE(SatUShortAccum, SatUnsignedShortAccumTy)
// '_Sat unsigned _Accum'
UNSIGNED_TYPE(SatUAccum, SatUnsignedAccumTy)
// '_Sat unsigned long _Accum'
UNSIGNED_TYPE(SatULongAccum, SatUnsignedLongAccumTy)
// '_Sat short _Fract'
SIGNED_TYPE(SatShortFract, SatShortFractTy)
// '_Sat _Fract'
SIGNED_TYPE(SatFract, SatFractTy)
// '_Sat long _Fract'
SIGNED_TYPE(SatLongFract, SatLongFractTy)
// '_Sat unsigned short _Fract'
UNSIGNED_TYPE(SatUShortFract, SatUnsignedShortFractTy)
// '_Sat unsigned _Fract'
UNSIGNED_TYPE(SatUFract, SatUnsignedFractTy)
// '_Sat unsigned long _Fract'
UNSIGNED_TYPE(SatULongFract, SatUnsignedLongFractTy)
//===- Floating point types -----------------------------------------------===//
// 'half' in OpenCL, '__fp16' in ARM NEON.
FLOATING_TYPE(Half, HalfTy)
// 'float'
FLOATING_TYPE(Float, FloatTy)
// 'double'
FLOATING_TYPE(Double, DoubleTy)
// 'long double'
FLOATING_TYPE(LongDouble, LongDoubleTy)
// '_Float16'
FLOATING_TYPE(Float16, HalfTy)
// '__bf16'
FLOATING_TYPE(BFloat16, BFloat16Ty)
// '__float128'
FLOATING_TYPE(Float128, Float128Ty)
// '__ibm128'
FLOATING_TYPE(Ibm128, Ibm128Ty)
//===- Language-specific types --------------------------------------------===//
// This is the type of C++0x 'nullptr'.
BUILTIN_TYPE(NullPtr, NullPtrTy)
// The primitive Objective C 'id' type. The user-visible 'id'
// type is a typedef of an ObjCObjectPointerType to an
// ObjCObjectType with this as its base. In fact, this only ever
// shows up in an AST as the base type of an ObjCObjectType.
BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy)
// The primitive Objective C 'Class' type. The user-visible
// 'Class' type is a typedef of an ObjCObjectPointerType to an
// ObjCObjectType with this as its base. In fact, this only ever
// shows up in an AST as the base type of an ObjCObjectType.
BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy)
// The primitive Objective C 'SEL' type. The user-visible 'SEL'
// type is a typedef of a PointerType to this.
BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy)
// OpenCL sampler_t.
BUILTIN_TYPE(OCLSampler, OCLSamplerTy)
// OpenCL event_t.
BUILTIN_TYPE(OCLEvent, OCLEventTy)
// OpenCL clk_event_t.
BUILTIN_TYPE(OCLClkEvent, OCLClkEventTy)
// OpenCL queue_t.
BUILTIN_TYPE(OCLQueue, OCLQueueTy)
// OpenCL reserve_id_t.
BUILTIN_TYPE(OCLReserveID, OCLReserveIDTy)
// This represents the type of an expression whose type is
// totally unknown, e.g. 'T::foo'. It is permitted for this to
// appear in situations where the structure of the type is
// theoretically deducible.
BUILTIN_TYPE(Dependent, DependentTy)
// The type of an unresolved overload set. A placeholder type.
// Expressions with this type have one of the following basic
// forms, with parentheses generally permitted:
// foo # possibly qualified, not if an implicit access
// foo # possibly qualified, not if an implicit access
// &foo # possibly qualified, not if an implicit access
// x->foo # only if might be a static member function
// &x->foo # only if might be a static member function
// &Class::foo # when a pointer-to-member; sub-expr also has this type
// OverloadExpr::find can be used to analyze the expression.
//
// Overload should be the first placeholder type, or else change
// BuiltinType::isNonOverloadPlaceholderType()
PLACEHOLDER_TYPE(Overload, OverloadTy)
// The type of a bound C++ non-static member function.
// A placeholder type. Expressions with this type have one of the
// following basic forms:
// foo # if an implicit access
// x->foo # if only contains non-static members
PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
// The type of an unresolved template. Used in UnresolvedLookupExpr.
PLACEHOLDER_TYPE(UnresolvedTemplate, UnresolvedTemplateTy)
// The type of an expression which refers to a pseudo-object,
// such as those introduced by Objective C's @property or
// VS.NET's __property declarations. A placeholder type. The
// pseudo-object is actually accessed by emitting a call to
// some sort of function or method; typically there is a pair
// of a setter and a getter, with the setter used if the
// pseudo-object reference is used syntactically as the
// left-hand-side of an assignment operator.
//
// A pseudo-object reference naming an Objective-C @property is
// always a dot access with a base of object-pointer type,
// e.g. 'x.foo'.
//
// In VS.NET, a __property declaration creates an implicit
// member with an associated name, which can then be named
// in any of the normal ways an ordinary member could be.
PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
// __builtin_any_type. A placeholder type. Useful for clients
// like debuggers that don't know what type to give something.
// Only a small number of operations are valid on expressions of
// unknown type, most notably explicit casts.
PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy)
PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
// The type of a cast which, in ARC, would normally require a
// __bridge, but which might be okay depending on the immediate
// context.
PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
// A placeholder type for incomplete matrix index expressions.
PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy)
// A placeholder type for OpenMP array sections.
PLACEHOLDER_TYPE(ArraySection, ArraySectionTy)
// A placeholder type for OpenMP array shaping operation.
PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
// A placeholder type for OpenMP iterators.
PLACEHOLDER_TYPE(OMPIterator, OMPIteratorTy)
#ifdef LAST_BUILTIN_TYPE
LAST_BUILTIN_TYPE(OMPIterator)
#undef LAST_BUILTIN_TYPE
#endif
#undef SHARED_SINGLETON_TYPE
#undef PLACEHOLDER_TYPE
#undef FLOATING_TYPE
#undef SIGNED_TYPE
#undef UNSIGNED_TYPE
#undef BUILTIN_TYPE

View File

@ -0,0 +1,390 @@
//===- CXXInheritance.h - C++ Inheritance -----------------------*- 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 provides routines that help analyzing C++ inheritance hierarchies.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CXXINHERITANCE_H
#define LLVM_CLANG_AST_CXXINHERITANCE_H
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include <list>
#include <memory>
#include <utility>
namespace clang {
class ASTContext;
class NamedDecl;
/// Represents an element in a path from a derived class to a
/// base class.
///
/// Each step in the path references the link from a
/// derived class to one of its direct base classes, along with a
/// base "number" that identifies which base subobject of the
/// original derived class we are referencing.
struct CXXBasePathElement {
/// The base specifier that states the link from a derived
/// class to a base class, which will be followed by this base
/// path element.
const CXXBaseSpecifier *Base;
/// The record decl of the class that the base is a base of.
const CXXRecordDecl *Class;
/// Identifies which base class subobject (of type
/// \c Base->getType()) this base path element refers to.
///
/// This value is only valid if \c !Base->isVirtual(), because there
/// is no base numbering for the zero or one virtual bases of a
/// given type.
int SubobjectNumber;
};
/// Represents a path from a specific derived class
/// (which is not represented as part of the path) to a particular
/// (direct or indirect) base class subobject.
///
/// Individual elements in the path are described by the \c CXXBasePathElement
/// structure, which captures both the link from a derived class to one of its
/// direct bases and identification describing which base class
/// subobject is being used.
class CXXBasePath : public SmallVector<CXXBasePathElement, 4> {
public:
/// The access along this inheritance path. This is only
/// calculated when recording paths. AS_none is a special value
/// used to indicate a path which permits no legal access.
AccessSpecifier Access = AS_public;
CXXBasePath() = default;
/// The declarations found inside this base class subobject.
DeclContext::lookup_iterator Decls;
void clear() {
SmallVectorImpl<CXXBasePathElement>::clear();
Access = AS_public;
}
};
/// BasePaths - Represents the set of paths from a derived class to
/// one of its (direct or indirect) bases. For example, given the
/// following class hierarchy:
///
/// @code
/// class A { };
/// class B : public A { };
/// class C : public A { };
/// class D : public B, public C{ };
/// @endcode
///
/// There are two potential BasePaths to represent paths from D to a
/// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0)
/// and another is (D,0)->(C,0)->(A,1). These two paths actually
/// refer to two different base class subobjects of the same type,
/// so the BasePaths object refers to an ambiguous path. On the
/// other hand, consider the following class hierarchy:
///
/// @code
/// class A { };
/// class B : public virtual A { };
/// class C : public virtual A { };
/// class D : public B, public C{ };
/// @endcode
///
/// Here, there are two potential BasePaths again, (D, 0) -> (B, 0)
/// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them
/// refer to the same base class subobject of type A (the virtual
/// one), there is no ambiguity.
class CXXBasePaths {
friend class CXXRecordDecl;
/// The type from which this search originated.
const CXXRecordDecl *Origin = nullptr;
/// Paths - The actual set of paths that can be taken from the
/// derived class to the same base class.
std::list<CXXBasePath> Paths;
/// ClassSubobjects - Records the class subobjects for each class
/// type that we've seen. The first element IsVirtBase says
/// whether we found a path to a virtual base for that class type,
/// while NumberOfNonVirtBases contains the number of non-virtual base
/// class subobjects for that class type. The key of the map is
/// the cv-unqualified canonical type of the base class subobject.
struct IsVirtBaseAndNumberNonVirtBases {
LLVM_PREFERRED_TYPE(bool)
unsigned IsVirtBase : 1;
unsigned NumberOfNonVirtBases : 31;
};
llvm::SmallDenseMap<QualType, IsVirtBaseAndNumberNonVirtBases, 8>
ClassSubobjects;
/// VisitedDependentRecords - Records the dependent records that have been
/// already visited.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
/// DetectedVirtual - The base class that is virtual.
const RecordType *DetectedVirtual = nullptr;
/// ScratchPath - A BasePath that is used by Sema::lookupInBases
/// to help build the set of paths.
CXXBasePath ScratchPath;
/// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
/// ambiguous paths while it is looking for a path from a derived
/// type to a base type.
bool FindAmbiguities;
/// RecordPaths - Whether Sema::IsDerivedFrom should record paths
/// while it is determining whether there are paths from a derived
/// type to a base type.
bool RecordPaths;
/// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search
/// if it finds a path that goes across a virtual base. The virtual class
/// is also recorded.
bool DetectVirtual;
bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
CXXRecordDecl::BaseMatchesCallback BaseMatches,
bool LookupInDependent = false);
public:
using paths_iterator = std::list<CXXBasePath>::iterator;
using const_paths_iterator = std::list<CXXBasePath>::const_iterator;
using decl_iterator = NamedDecl **;
/// BasePaths - Construct a new BasePaths structure to record the
/// paths for a derived-to-base search.
explicit CXXBasePaths(bool FindAmbiguities = true, bool RecordPaths = true,
bool DetectVirtual = true)
: FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths),
DetectVirtual(DetectVirtual) {}
paths_iterator begin() { return Paths.begin(); }
paths_iterator end() { return Paths.end(); }
const_paths_iterator begin() const { return Paths.begin(); }
const_paths_iterator end() const { return Paths.end(); }
CXXBasePath& front() { return Paths.front(); }
const CXXBasePath& front() const { return Paths.front(); }
using decl_range = llvm::iterator_range<decl_iterator>;
/// Determine whether the path from the most-derived type to the
/// given base type is ambiguous (i.e., it refers to multiple subobjects of
/// the same base type).
bool isAmbiguous(CanQualType BaseType) const;
/// Whether we are finding multiple paths to detect ambiguities.
bool isFindingAmbiguities() const { return FindAmbiguities; }
/// Whether we are recording paths.
bool isRecordingPaths() const { return RecordPaths; }
/// Specify whether we should be recording paths or not.
void setRecordingPaths(bool RP) { RecordPaths = RP; }
/// Whether we are detecting virtual bases.
bool isDetectingVirtual() const { return DetectVirtual; }
/// The virtual base discovered on the path (if we are merely
/// detecting virtuals).
const RecordType* getDetectedVirtual() const {
return DetectedVirtual;
}
/// Retrieve the type from which this base-paths search
/// began
const CXXRecordDecl *getOrigin() const { return Origin; }
void setOrigin(const CXXRecordDecl *Rec) { Origin = Rec; }
/// Clear the base-paths results.
void clear();
/// Swap this data structure's contents with another CXXBasePaths
/// object.
void swap(CXXBasePaths &Other);
};
/// Uniquely identifies a virtual method within a class
/// hierarchy by the method itself and a class subobject number.
struct UniqueVirtualMethod {
/// The overriding virtual method.
CXXMethodDecl *Method = nullptr;
/// The subobject in which the overriding virtual method
/// resides.
unsigned Subobject = 0;
/// The virtual base class subobject of which this overridden
/// virtual method is a part. Note that this records the closest
/// derived virtual base class subobject.
const CXXRecordDecl *InVirtualSubobject = nullptr;
UniqueVirtualMethod() = default;
UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject,
const CXXRecordDecl *InVirtualSubobject)
: Method(Method), Subobject(Subobject),
InVirtualSubobject(InVirtualSubobject) {}
friend bool operator==(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return X.Method == Y.Method && X.Subobject == Y.Subobject &&
X.InVirtualSubobject == Y.InVirtualSubobject;
}
friend bool operator!=(const UniqueVirtualMethod &X,
const UniqueVirtualMethod &Y) {
return !(X == Y);
}
};
/// The set of methods that override a given virtual method in
/// each subobject where it occurs.
///
/// The first part of the pair is the subobject in which the
/// overridden virtual function occurs, while the second part of the
/// pair is the virtual method that overrides it (including the
/// subobject in which that virtual function occurs).
class OverridingMethods {
using ValuesT = SmallVector<UniqueVirtualMethod, 4>;
using MapType = llvm::MapVector<unsigned, ValuesT>;
MapType Overrides;
public:
// Iterate over the set of subobjects that have overriding methods.
using iterator = MapType::iterator;
using const_iterator = MapType::const_iterator;
iterator begin() { return Overrides.begin(); }
const_iterator begin() const { return Overrides.begin(); }
iterator end() { return Overrides.end(); }
const_iterator end() const { return Overrides.end(); }
unsigned size() const { return Overrides.size(); }
// Iterate over the set of overriding virtual methods in a given
// subobject.
using overriding_iterator =
SmallVectorImpl<UniqueVirtualMethod>::iterator;
using overriding_const_iterator =
SmallVectorImpl<UniqueVirtualMethod>::const_iterator;
// Add a new overriding method for a particular subobject.
void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding);
// Add all of the overriding methods from "other" into overrides for
// this method. Used when merging the overrides from multiple base
// class subobjects.
void add(const OverridingMethods &Other);
// Replace all overriding virtual methods in all subobjects with the
// given virtual method.
void replaceAll(UniqueVirtualMethod Overriding);
};
/// A mapping from each virtual member function to its set of
/// final overriders.
///
/// Within a class hierarchy for a given derived class, each virtual
/// member function in that hierarchy has one or more "final
/// overriders" (C++ [class.virtual]p2). A final overrider for a
/// virtual function "f" is the virtual function that will actually be
/// invoked when dispatching a call to "f" through the
/// vtable. Well-formed classes have a single final overrider for each
/// virtual function; in abstract classes, the final overrider for at
/// least one virtual function is a pure virtual function. Due to
/// multiple, virtual inheritance, it is possible for a class to have
/// more than one final overrider. Although this is an error (per C++
/// [class.virtual]p2), it is not considered an error here: the final
/// overrider map can represent multiple final overriders for a
/// method, and it is up to the client to determine whether they are
/// problem. For example, the following class \c D has two final
/// overriders for the virtual function \c A::f(), one in \c C and one
/// in \c D:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : virtual A { virtual void f(); };
/// struct C : virtual A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// This data structure contains a mapping from every virtual
/// function *that does not override an existing virtual function* and
/// in every subobject where that virtual function occurs to the set
/// of virtual functions that override it. Thus, the same virtual
/// function \c A::f can actually occur in multiple subobjects of type
/// \c A due to multiple inheritance, and may be overridden by
/// different virtual functions in each, as in the following example:
///
/// \code
/// struct A { virtual void f(); };
/// struct B : A { virtual void f(); };
/// struct C : A { virtual void f(); };
/// struct D : B, C { };
/// \endcode
///
/// Unlike in the previous example, where the virtual functions \c
/// B::f and \c C::f both overrode \c A::f in the same subobject of
/// type \c A, in this example the two virtual functions both override
/// \c A::f but in *different* subobjects of type A. This is
/// represented by numbering the subobjects in which the overridden
/// and the overriding virtual member functions are located. Subobject
/// 0 represents the virtual base class subobject of that type, while
/// subobject numbers greater than 0 refer to non-virtual base class
/// subobjects of that type.
class CXXFinalOverriderMap
: public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> {};
/// A set of all the primary bases for a class.
class CXXIndirectPrimaryBaseSet
: public llvm::SmallPtrSet<const CXXRecordDecl *, 32> {};
inline bool
inheritanceModelHasVBPtrOffsetField(MSInheritanceModel Inheritance) {
return Inheritance == MSInheritanceModel::Unspecified;
}
// Only member pointers to functions need a this adjustment, since it can be
// combined with the field offset for data pointers.
inline bool inheritanceModelHasNVOffsetField(bool IsMemberFunction,
MSInheritanceModel Inheritance) {
return IsMemberFunction && Inheritance >= MSInheritanceModel::Multiple;
}
inline bool
inheritanceModelHasVBTableOffsetField(MSInheritanceModel Inheritance) {
return Inheritance >= MSInheritanceModel::Virtual;
}
inline bool inheritanceModelHasOnlyOneField(bool IsMemberFunction,
MSInheritanceModel Inheritance) {
if (IsMemberFunction)
return Inheritance <= MSInheritanceModel::Single;
return Inheritance <= MSInheritanceModel::Multiple;
}
} // namespace clang
#endif // LLVM_CLANG_AST_CXXINHERITANCE_H

View File

@ -0,0 +1,256 @@
//===-- CXXRecordDeclDefinitionBits.def - Class definition bits -*- 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 enumerates the various bitfields that we want to store on C++ class
// definitions.
//
//===----------------------------------------------------------------------===//
//
/// @file CXXRecordDeclDefinitionBits.def
///
/// In this file, each of the bitfields representing data about a C++ class
/// results in an expansion of the FIELD macro, which should be defined before
/// including this file.
///
/// The macro have three operands:
///
/// Name: The name of the field, as a member of CXXRecordDecl::DefinitionData.
///
/// BitWidth: The width of the field in bits.
///
/// MergePolicy: How to behave when the value of the field is different in
/// multiple translation units, one of:
/// NO_MERGE: It is an ODR violation if the fields do not match.
/// MERGE_OR: Merge the fields by ORing them together.
#ifndef FIELD
#error define FIELD before including this file
#endif
/// True if this class has any user-declared constructors.
FIELD(UserDeclaredConstructor, 1, NO_MERGE)
/// The user-declared special members which this class has.
FIELD(UserDeclaredSpecialMembers, 6, NO_MERGE)
/// True when this class is an aggregate.
FIELD(Aggregate, 1, NO_MERGE)
/// True when this class is a POD-type.
FIELD(PlainOldData, 1, NO_MERGE)
/// True when this class is empty for traits purposes, that is:
/// * has no data members other than 0-width bit-fields and empty fields
/// marked [[no_unique_address]]
/// * has no virtual function/base, and
/// * doesn't inherit from a non-empty class.
/// Doesn't take union-ness into account.
FIELD(Empty, 1, NO_MERGE)
/// True when this class is polymorphic, i.e., has at
/// least one virtual member or derives from a polymorphic class.
FIELD(Polymorphic, 1, NO_MERGE)
/// True when this class is abstract, i.e., has at least
/// one pure virtual function, (that can come from a base class).
FIELD(Abstract, 1, NO_MERGE)
/// True when this class is standard-layout, per the applicable
/// language rules (including DRs).
FIELD(IsStandardLayout, 1, NO_MERGE)
/// True when this class was standard-layout under the C++11
/// definition.
///
/// C++11 [class]p7. A standard-layout class is a class that:
/// * has no non-static data members of type non-standard-layout class (or
/// array of such types) or reference,
/// * has no virtual functions (10.3) and no virtual base classes (10.1),
/// * has the same access control (Clause 11) for all non-static data
/// members
/// * has no non-standard-layout base classes,
/// * either has no non-static data members in the most derived class and at
/// most one base class with non-static data members, or has no base
/// classes with non-static data members, and
/// * has no base classes of the same type as the first non-static data
/// member.
FIELD(IsCXX11StandardLayout, 1, NO_MERGE)
/// True when any base class has any declared non-static data
/// members or bit-fields.
/// This is a helper bit of state used to implement IsStandardLayout more
/// efficiently.
FIELD(HasBasesWithFields, 1, NO_MERGE)
/// True when any base class has any declared non-static data
/// members.
/// This is a helper bit of state used to implement IsCXX11StandardLayout
/// more efficiently.
FIELD(HasBasesWithNonStaticDataMembers, 1, NO_MERGE)
/// True when there are private non-static data members.
FIELD(HasPrivateFields, 1, NO_MERGE)
/// True when there are protected non-static data members.
FIELD(HasProtectedFields, 1, NO_MERGE)
/// True when there are private non-static data members.
FIELD(HasPublicFields, 1, NO_MERGE)
/// True if this class (or any subobject) has mutable fields.
FIELD(HasMutableFields, 1, NO_MERGE)
/// True if this class (or any nested anonymous struct or union)
/// has variant members.
FIELD(HasVariantMembers, 1, NO_MERGE)
/// True if there no non-field members declared by the user.
FIELD(HasOnlyCMembers, 1, NO_MERGE)
/// True if there is an '__init' method defined by the user.
FIELD(HasInitMethod, 1, NO_MERGE)
/// True if any field has an in-class initializer, including those
/// within anonymous unions or structs.
FIELD(HasInClassInitializer, 1, NO_MERGE)
/// True if any field is of reference type, and does not have an
/// in-class initializer.
///
/// In this case, value-initialization of this class is illegal in C++98
/// even if the class has a trivial default constructor.
FIELD(HasUninitializedReferenceMember, 1, NO_MERGE)
/// True if any non-mutable field whose type doesn't have a user-
/// provided default ctor also doesn't have an in-class initializer.
FIELD(HasUninitializedFields, 1, NO_MERGE)
/// True if there are any member using-declarations that inherit
/// constructors from a base class.
FIELD(HasInheritedConstructor, 1, NO_MERGE)
/// True if there are any member using-declarations that inherit
/// default constructors from a base class.
FIELD(HasInheritedDefaultConstructor, 1, NO_MERGE)
/// True if there are any member using-declarations named
/// 'operator='.
FIELD(HasInheritedAssignment, 1, NO_MERGE)
/// These flags are \c true if a defaulted corresponding special
/// member can't be fully analyzed without performing overload resolution.
/// @{
FIELD(NeedOverloadResolutionForCopyConstructor, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForMoveConstructor, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForCopyAssignment, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForMoveAssignment, 1, NO_MERGE)
FIELD(NeedOverloadResolutionForDestructor, 1, NO_MERGE)
/// @}
/// These flags are \c true if an implicit defaulted corresponding
/// special member would be defined as deleted.
/// @{
FIELD(DefaultedCopyConstructorIsDeleted, 1, NO_MERGE)
FIELD(DefaultedMoveConstructorIsDeleted, 1, NO_MERGE)
FIELD(DefaultedCopyAssignmentIsDeleted, 1, NO_MERGE)
FIELD(DefaultedMoveAssignmentIsDeleted, 1, NO_MERGE)
FIELD(DefaultedDestructorIsDeleted, 1, NO_MERGE)
/// @}
/// The trivial special members which this class has, per
/// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25,
/// C++11 [class.dtor]p5, or would have if the member were not suppressed.
///
/// This excludes any user-declared but not user-provided special members
/// which have been declared but not yet defined.
FIELD(HasTrivialSpecialMembers, 6, MERGE_OR)
/// These bits keep track of the triviality of special functions for the
/// purpose of calls. Only the bits corresponding to SMF_CopyConstructor,
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
FIELD(HasTrivialSpecialMembersForCall, 6, MERGE_OR)
/// The declared special members of this class which are known to be
/// non-trivial.
///
/// This excludes any user-declared but not user-provided special members
/// which have been declared but not yet defined, and any implicit special
/// members which have not yet been declared.
FIELD(DeclaredNonTrivialSpecialMembers, 6, MERGE_OR)
/// These bits keep track of the declared special members that are
/// non-trivial for the purpose of calls.
/// Only the bits corresponding to SMF_CopyConstructor,
/// SMF_MoveConstructor, and SMF_Destructor are meaningful here.
FIELD(DeclaredNonTrivialSpecialMembersForCall, 6, MERGE_OR)
/// True when this class has a destructor with no semantic effect.
FIELD(HasIrrelevantDestructor, 1, NO_MERGE)
/// True when this class has at least one user-declared constexpr
/// constructor which is neither the copy nor move constructor.
FIELD(HasConstexprNonCopyMoveConstructor, 1, MERGE_OR)
/// True if this class has a (possibly implicit) defaulted default
/// constructor.
FIELD(HasDefaultedDefaultConstructor, 1, MERGE_OR)
/// True if a defaulted default constructor for this class would
/// be constexpr.
FIELD(DefaultedDefaultConstructorIsConstexpr, 1, NO_MERGE)
/// True if this class has a constexpr default constructor.
///
/// This is true for either a user-declared constexpr default constructor
/// or an implicitly declared constexpr default constructor.
FIELD(HasConstexprDefaultConstructor, 1, MERGE_OR)
/// True if a defaulted destructor for this class would be constexpr.
FIELD(DefaultedDestructorIsConstexpr, 1, NO_MERGE)
/// True when this class contains at least one non-static data
/// member or base class of non-literal or volatile type.
FIELD(HasNonLiteralTypeFieldsOrBases, 1, NO_MERGE)
/// True if this class is a structural type, assuming it is a literal type.
FIELD(StructuralIfLiteral, 1, NO_MERGE)
/// Whether we have a C++11 user-provided default constructor (not
/// explicitly deleted or defaulted).
FIELD(UserProvidedDefaultConstructor, 1, NO_MERGE)
/// The special members which have been declared for this class,
/// either by the user or implicitly.
FIELD(DeclaredSpecialMembers, 6, MERGE_OR)
/// Whether an implicit copy constructor could have a const-qualified
/// parameter, for initializing virtual bases and for other subobjects.
FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase, 1, NO_MERGE)
FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase, 1, NO_MERGE)
/// Whether an implicit copy assignment operator would have a
/// const-qualified parameter.
FIELD(ImplicitCopyAssignmentHasConstParam, 1, NO_MERGE)
/// Whether any declared copy constructor has a const-qualified
/// parameter.
FIELD(HasDeclaredCopyConstructorWithConstParam, 1, MERGE_OR)
/// Whether any declared copy assignment operator has either a
/// const-qualified reference parameter or a non-reference parameter.
FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR)
/// Whether the destructor is no-return. Either explicitly, or if any
/// base classes or fields have a no-return destructor
FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
/// Whether the record type is intangible (if any base classes or fields have
/// type that is intangible). HLSL only.
FIELD(IsHLSLIntangible, 1, NO_MERGE)
#undef FIELD

View File

@ -0,0 +1,689 @@
//===- CanonicalType.h - C Language Family Type Representation --*- 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 CanQual class template, which provides access to
// canonical types.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CANONICALTYPE_H
#define LLVM_CLANG_AST_CANONICALTYPE_H
#include "clang/AST/Type.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <iterator>
#include <type_traits>
namespace clang {
template<typename T> class CanProxy;
template<typename T> struct CanProxyAdaptor;
class ASTContext;
class CXXRecordDecl;
class EnumDecl;
class Expr;
class IdentifierInfo;
class ObjCInterfaceDecl;
class RecordDecl;
class TagDecl;
class TemplateTypeParmDecl;
//----------------------------------------------------------------------------//
// Canonical, qualified type template
//----------------------------------------------------------------------------//
/// Represents a canonical, potentially-qualified type.
///
/// The CanQual template is a lightweight smart pointer that provides access
/// to the canonical representation of a type, where all typedefs and other
/// syntactic sugar has been eliminated. A CanQualType may also have various
/// qualifiers (const, volatile, restrict) attached to it.
///
/// The template type parameter @p T is one of the Type classes (PointerType,
/// BuiltinType, etc.). The type stored within @c CanQual<T> will be of that
/// type (or some subclass of that type). The typedef @c CanQualType is just
/// a shorthand for @c CanQual<Type>.
///
/// An instance of @c CanQual<T> can be implicitly converted to a
/// @c CanQual<U> when T is derived from U, which essentially provides an
/// implicit upcast. For example, @c CanQual<LValueReferenceType> can be
/// converted to @c CanQual<ReferenceType>. Note that any @c CanQual type can
/// be implicitly converted to a QualType, but the reverse operation requires
/// a call to ASTContext::getCanonicalType().
template<typename T = Type>
class CanQual {
/// The actual, canonical type.
QualType Stored;
public:
/// Constructs a NULL canonical type.
CanQual() = default;
/// Converting constructor that permits implicit upcasting of
/// canonical type pointers.
template <typename U>
CanQual(const CanQual<U> &Other,
std::enable_if_t<std::is_base_of<T, U>::value, int> = 0);
/// Retrieve the underlying type pointer, which refers to a
/// canonical type.
///
/// The underlying pointer must not be nullptr.
const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
/// Retrieve the underlying type pointer, which refers to a
/// canonical type, or nullptr.
const T *getTypePtrOrNull() const {
return cast_or_null<T>(Stored.getTypePtrOrNull());
}
/// Implicit conversion to a qualified type.
operator QualType() const { return Stored; }
/// Implicit conversion to bool.
explicit operator bool() const { return !isNull(); }
bool isNull() const {
return Stored.isNull();
}
SplitQualType split() const { return Stored.split(); }
/// Retrieve a canonical type pointer with a different static type,
/// upcasting or downcasting as needed.
///
/// The getAs() function is typically used to try to downcast to a
/// more specific (canonical) type in the type system. For example:
///
/// @code
/// void f(CanQual<Type> T) {
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) {
/// // look at Ptr's pointee type
/// }
/// }
/// @endcode
///
/// \returns A proxy pointer to the same type, but with the specified
/// static type (@p U). If the dynamic type is not the specified static type
/// or a derived class thereof, a NULL canonical type.
template<typename U> CanProxy<U> getAs() const;
template<typename U> CanProxy<U> castAs() const;
/// Overloaded arrow operator that produces a canonical type
/// proxy.
CanProxy<T> operator->() const;
/// Retrieve all qualifiers.
Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); }
/// Retrieve the const/volatile/restrict qualifiers.
unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); }
/// Determines whether this type has any qualifiers
bool hasQualifiers() const { return Stored.hasLocalQualifiers(); }
bool isConstQualified() const {
return Stored.isLocalConstQualified();
}
bool isVolatileQualified() const {
return Stored.isLocalVolatileQualified();
}
bool isRestrictQualified() const {
return Stored.isLocalRestrictQualified();
}
/// Determines if this canonical type is furthermore
/// canonical as a parameter. The parameter-canonicalization
/// process decays arrays to pointers and drops top-level qualifiers.
bool isCanonicalAsParam() const {
return Stored.isCanonicalAsParam();
}
/// Retrieve the unqualified form of this type.
CanQual<T> getUnqualifiedType() const;
/// Retrieves a version of this type with const applied.
/// Note that this does not always yield a canonical type.
QualType withConst() const {
return Stored.withConst();
}
/// Determines whether this canonical type is more qualified than
/// the @p Other canonical type.
bool isMoreQualifiedThan(CanQual<T> Other, const ASTContext &Ctx) const {
return Stored.isMoreQualifiedThan(Other.Stored, Ctx);
}
/// Determines whether this canonical type is at least as qualified as
/// the @p Other canonical type.
bool isAtLeastAsQualifiedAs(CanQual<T> Other, const ASTContext &Ctx) const {
return Stored.isAtLeastAsQualifiedAs(Other.Stored, Ctx);
}
/// If the canonical type is a reference type, returns the type that
/// it refers to; otherwise, returns the type itself.
CanQual<Type> getNonReferenceType() const;
/// Retrieve the internal representation of this canonical type.
void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); }
/// Construct a canonical type from its internal representation.
static CanQual<T> getFromOpaquePtr(void *Ptr);
/// Builds a canonical type from a QualType.
///
/// This routine is inherently unsafe, because it requires the user to
/// ensure that the given type is a canonical type with the correct
// (dynamic) type.
static CanQual<T> CreateUnsafe(QualType Other);
void dump() const { Stored.dump(); }
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(getAsOpaquePtr());
}
};
template<typename T, typename U>
inline bool operator==(CanQual<T> x, CanQual<U> y) {
return x.getAsOpaquePtr() == y.getAsOpaquePtr();
}
template<typename T, typename U>
inline bool operator!=(CanQual<T> x, CanQual<U> y) {
return x.getAsOpaquePtr() != y.getAsOpaquePtr();
}
/// Represents a canonical, potentially-qualified type.
using CanQualType = CanQual<Type>;
inline CanQualType Type::getCanonicalTypeUnqualified() const {
return CanQualType::CreateUnsafe(
getCanonicalTypeInternal().getUnqualifiedType());
}
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
CanQualType T) {
DB << static_cast<QualType>(T);
return DB;
}
//----------------------------------------------------------------------------//
// Internal proxy classes used by canonical types
//----------------------------------------------------------------------------//
#define LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(Accessor) \
CanQualType Accessor() const { \
return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \
}
#define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \
Type Accessor() const { return this->getTypePtr()->Accessor(); }
/// Base class of all canonical proxy types, which is responsible for
/// storing the underlying canonical type and providing basic conversions.
template<typename T>
class CanProxyBase {
protected:
CanQual<T> Stored;
public:
/// Retrieve the pointer to the underlying Type
const T *getTypePtr() const { return Stored.getTypePtr(); }
/// Implicit conversion to the underlying pointer.
///
/// Also provides the ability to use canonical type proxies in a Boolean
// context,e.g.,
/// @code
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
/// @endcode
operator const T*() const { return this->Stored.getTypePtrOrNull(); }
/// Try to convert the given canonical type to a specific structural
/// type.
template<typename U> CanProxy<U> getAs() const {
return this->Stored.template getAs<U>();
}
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type::TypeClass, getTypeClass)
// Type predicates
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessBuiltinType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isBooleanType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFloatingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArithmeticType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDerivedType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isScalarType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAggregateType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVoidPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isFunctionPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isMemberFunctionPointerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isInterfaceType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isStructureOrClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnionType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
/// Retrieve the proxy-adaptor type.
///
/// This arrow operator is used when CanProxyAdaptor has been specialized
/// for the given type T. In that case, we reference members of the
/// CanProxyAdaptor specialization. Otherwise, this operator will be hidden
/// by the arrow operator in the primary CanProxyAdaptor template.
const CanProxyAdaptor<T> *operator->() const {
return static_cast<const CanProxyAdaptor<T> *>(this);
}
};
/// Replaceable canonical proxy adaptor class that provides the link
/// between a canonical type and the accessors of the type.
///
/// The CanProxyAdaptor is a replaceable class template that is instantiated
/// as part of each canonical proxy type. The primary template merely provides
/// redirection to the underlying type (T), e.g., @c PointerType. One can
/// provide specializations of this class template for each underlying type
/// that provide accessors returning canonical types (@c CanQualType) rather
/// than the more typical @c QualType, to propagate the notion of "canonical"
/// through the system.
template<typename T>
struct CanProxyAdaptor : CanProxyBase<T> {};
/// Canonical proxy type returned when retrieving the members of a
/// canonical type or as the result of the @c CanQual<T>::getAs member
/// function.
///
/// The CanProxy type mainly exists as a proxy through which operator-> will
/// look to either map down to a raw T* (e.g., PointerType*) or to a proxy
/// type that provides canonical-type access to the fields of the type.
template<typename T>
class CanProxy : public CanProxyAdaptor<T> {
public:
/// Build a NULL proxy.
CanProxy() = default;
/// Build a proxy to the given canonical type.
CanProxy(CanQual<T> Stored) { this->Stored = Stored; }
/// Implicit conversion to the stored canonical type.
operator CanQual<T>() const { return this->Stored; }
};
} // namespace clang
namespace llvm {
/// Implement simplify_type for CanQual<T>, so that we can dyn_cast from
/// CanQual<T> to a specific Type class. We're prefer isa/dyn_cast/cast/etc.
/// to return smart pointer (proxies?).
template<typename T>
struct simplify_type< ::clang::CanQual<T>> {
using SimpleType = const T *;
static SimpleType getSimplifiedValue(::clang::CanQual<T> Val) {
return Val.getTypePtr();
}
};
// Teach SmallPtrSet that CanQual<T> is "basically a pointer".
template<typename T>
struct PointerLikeTypeTraits<clang::CanQual<T>> {
static void *getAsVoidPointer(clang::CanQual<T> P) {
return P.getAsOpaquePtr();
}
static clang::CanQual<T> getFromVoidPointer(void *P) {
return clang::CanQual<T>::getFromOpaquePtr(P);
}
// qualifier information is encoded in the low bits.
static constexpr int NumLowBitsAvailable = 0;
};
} // namespace llvm
namespace clang {
//----------------------------------------------------------------------------//
// Canonical proxy adaptors for canonical type nodes.
//----------------------------------------------------------------------------//
/// Iterator adaptor that turns an iterator over canonical QualTypes
/// into an iterator over CanQualTypes.
template <typename InputIterator>
struct CanTypeIterator
: llvm::iterator_adaptor_base<
CanTypeIterator<InputIterator>, InputIterator,
typename std::iterator_traits<InputIterator>::iterator_category,
CanQualType,
typename std::iterator_traits<InputIterator>::difference_type,
CanProxy<Type>, CanQualType> {
CanTypeIterator() = default;
explicit CanTypeIterator(InputIterator Iter)
: CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); }
CanProxy<Type> operator->() const;
};
template<>
struct CanProxyAdaptor<ComplexType> : public CanProxyBase<ComplexType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
};
template<>
struct CanProxyAdaptor<PointerType> : public CanProxyBase<PointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<BlockPointerType>
: public CanProxyBase<BlockPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<ReferenceType> : public CanProxyBase<ReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<LValueReferenceType>
: public CanProxyBase<LValueReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<RValueReferenceType>
: public CanProxyBase<RValueReferenceType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
};
template<>
struct CanProxyAdaptor<MemberPointerType>
: public CanProxyBase<MemberPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier, getQualifier)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
getMostRecentCXXRecordDecl)
};
// CanProxyAdaptors for arrays are intentionally unimplemented because
// they are not safe.
template<> struct CanProxyAdaptor<ArrayType>;
template<> struct CanProxyAdaptor<ConstantArrayType>;
template<> struct CanProxyAdaptor<IncompleteArrayType>;
template<> struct CanProxyAdaptor<VariableArrayType>;
template<> struct CanProxyAdaptor<DependentSizedArrayType>;
template<>
struct CanProxyAdaptor<DependentSizedExtVectorType>
: public CanProxyBase<DependentSizedExtVectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Expr *, getSizeExpr)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getAttributeLoc)
};
template<>
struct CanProxyAdaptor<VectorType> : public CanProxyBase<VectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
};
template<>
struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumElements)
};
template<>
struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionNoProtoType>
: public CanProxyBase<FunctionNoProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
};
template<>
struct CanProxyAdaptor<FunctionProtoType>
: public CanProxyBase<FunctionProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(
ArrayRef<FunctionProtoType::ExtParameterInfo>, getExtParameterInfos)
CanQualType getParamType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i));
}
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariadic)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getMethodQuals)
using param_type_iterator =
CanTypeIterator<FunctionProtoType::param_type_iterator>;
param_type_iterator param_type_begin() const {
return param_type_iterator(this->getTypePtr()->param_type_begin());
}
param_type_iterator param_type_end() const {
return param_type_iterator(this->getTypePtr()->param_type_end());
}
// Note: canonical function types never have exception specifications
};
template<>
struct CanProxyAdaptor<TypeOfType> : public CanProxyBase<TypeOfType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnmodifiedType)
};
template<>
struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getUnderlyingExpr)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
};
template <>
struct CanProxyAdaptor<UnaryTransformType>
: public CanProxyBase<UnaryTransformType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
};
template<>
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
};
template<>
struct CanProxyAdaptor<RecordType> : public CanProxyBase<RecordType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(RecordDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasConstFields)
};
template<>
struct CanProxyAdaptor<EnumType> : public CanProxyBase<EnumType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(EnumDecl *, getDecl)
};
template<>
struct CanProxyAdaptor<TemplateTypeParmType>
: public CanProxyBase<TemplateTypeParmType> {
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier)
};
template<>
struct CanProxyAdaptor<ObjCObjectType>
: public CanProxyBase<ObjCObjectType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceDecl *,
getInterface)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedId)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCUnqualifiedClass)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedId)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClass)
using qual_iterator = ObjCObjectPointerType::qual_iterator;
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
};
template<>
struct CanProxyAdaptor<ObjCObjectPointerType>
: public CanProxyBase<ObjCObjectPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const ObjCInterfaceType *,
getInterfaceType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCIdType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCClassType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedIdType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjCQualifiedClassType)
using qual_iterator = ObjCObjectPointerType::qual_iterator;
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_begin)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(qual_iterator, qual_end)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, qual_empty)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumProtocols)
};
//----------------------------------------------------------------------------//
// Method and function definitions
//----------------------------------------------------------------------------//
template<typename T>
inline CanQual<T> CanQual<T>::getUnqualifiedType() const {
return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType());
}
template<typename T>
inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
if (CanQual<ReferenceType> RefType = getAs<ReferenceType>())
return RefType->getPointeeType();
else
return *this;
}
template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
CanQual<T> Result;
Result.Stored = QualType::getFromOpaquePtr(Ptr);
assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
Result.Stored.isCanonical()) && "Type is not canonical!");
return Result;
}
template<typename T>
CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) {
assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");
assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&
"Dynamic type does not meet the static type's requires");
CanQual<T> Result;
Result.Stored = Other;
return Result;
}
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::getAs() const {
static_assert(!TypeIsArrayType<T>::value,
"ArrayType cannot be used with getAs!");
if (Stored.isNull())
return CanProxy<U>();
if (isa<U>(Stored.getTypePtr()))
return CanQual<U>::CreateUnsafe(Stored);
return CanProxy<U>();
}
template<typename T>
template<typename U>
CanProxy<U> CanQual<T>::castAs() const {
static_assert(!TypeIsArrayType<U>::value,
"ArrayType cannot be used with castAs!");
assert(!Stored.isNull() && isa<U>(Stored.getTypePtr()));
return CanQual<U>::CreateUnsafe(Stored);
}
template<typename T>
CanProxy<T> CanQual<T>::operator->() const {
return CanProxy<T>(*this);
}
template <typename InputIterator>
CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {
return CanProxy<Type>(*this);
}
} // namespace clang
#endif // LLVM_CLANG_AST_CANONICALTYPE_H

View File

@ -0,0 +1,260 @@
//===--- CharUnits.h - Character units for sizes and offsets ----*- 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 CharUnits class
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
namespace clang {
/// CharUnits - This is an opaque type for sizes expressed in character units.
/// Instances of this type represent a quantity as a multiple of the size
/// of the standard C type, char, on the target architecture. As an opaque
/// type, CharUnits protects you from accidentally combining operations on
/// quantities in bit units and character units.
///
/// In both C and C++, an object of type 'char', 'signed char', or 'unsigned
/// char' occupies exactly one byte, so 'character unit' and 'byte' refer to
/// the same quantity of storage. However, we use the term 'character unit'
/// rather than 'byte' to avoid an implication that a character unit is
/// exactly 8 bits.
///
/// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values wherever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
public:
typedef int64_t QuantityType;
private:
QuantityType Quantity = 0;
explicit CharUnits(QuantityType C) : Quantity(C) {}
public:
/// CharUnits - A default constructor.
CharUnits() = default;
/// Zero - Construct a CharUnits quantity of zero.
static CharUnits Zero() {
return CharUnits(0);
}
/// One - Construct a CharUnits quantity of one.
static CharUnits One() {
return CharUnits(1);
}
/// fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits fromQuantity(QuantityType Quantity) {
return CharUnits(Quantity);
}
/// fromQuantity - Construct a CharUnits quantity from an llvm::Align
/// quantity.
static CharUnits fromQuantity(llvm::Align Quantity) {
return CharUnits(Quantity.value());
}
// Compound assignment.
CharUnits& operator+= (const CharUnits &Other) {
Quantity += Other.Quantity;
return *this;
}
CharUnits& operator++ () {
++Quantity;
return *this;
}
CharUnits operator++ (int) {
return CharUnits(Quantity++);
}
CharUnits& operator-= (const CharUnits &Other) {
Quantity -= Other.Quantity;
return *this;
}
CharUnits& operator-- () {
--Quantity;
return *this;
}
CharUnits operator-- (int) {
return CharUnits(Quantity--);
}
// Comparison operators.
bool operator== (const CharUnits &Other) const {
return Quantity == Other.Quantity;
}
bool operator!= (const CharUnits &Other) const {
return Quantity != Other.Quantity;
}
// Relational operators.
bool operator< (const CharUnits &Other) const {
return Quantity < Other.Quantity;
}
bool operator<= (const CharUnits &Other) const {
return Quantity <= Other.Quantity;
}
bool operator> (const CharUnits &Other) const {
return Quantity > Other.Quantity;
}
bool operator>= (const CharUnits &Other) const {
return Quantity >= Other.Quantity;
}
// Other predicates.
/// isZero - Test whether the quantity equals zero.
bool isZero() const { return Quantity == 0; }
/// isOne - Test whether the quantity equals one.
bool isOne() const { return Quantity == 1; }
/// isPositive - Test whether the quantity is greater than zero.
bool isPositive() const { return Quantity > 0; }
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
/// isPowerOfTwo - Test whether the quantity is a power of two.
/// Zero is not a power of two.
bool isPowerOfTwo() const {
return (Quantity & -Quantity) == Quantity;
}
/// Test whether this is a multiple of the other value.
///
/// Among other things, this promises that
/// self.alignTo(N) will just return self.
bool isMultipleOf(CharUnits N) const {
return (*this % N) == CharUnits::Zero();
}
// Arithmetic operators.
CharUnits operator* (QuantityType N) const {
return CharUnits(Quantity * N);
}
CharUnits &operator*= (QuantityType N) {
Quantity *= N;
return *this;
}
CharUnits operator/ (QuantityType N) const {
return CharUnits(Quantity / N);
}
CharUnits &operator/= (QuantityType N) {
Quantity /= N;
return *this;
}
QuantityType operator/ (const CharUnits &Other) const {
return Quantity / Other.Quantity;
}
CharUnits operator% (QuantityType N) const {
return CharUnits(Quantity % N);
}
CharUnits operator%(const CharUnits &Other) const {
return CharUnits(Quantity % Other.Quantity);
}
CharUnits operator+ (const CharUnits &Other) const {
return CharUnits(Quantity + Other.Quantity);
}
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
CharUnits operator- () const {
return CharUnits(-Quantity);
}
// Conversions.
/// getQuantity - Get the raw integer representation of this quantity.
QuantityType getQuantity() const { return Quantity; }
/// getAsAlign - Returns Quantity as a valid llvm::Align,
/// Beware llvm::Align assumes power of two 8-bit bytes.
llvm::Align getAsAlign() const { return llvm::Align(Quantity); }
/// getAsMaybeAlign - Returns Quantity as a valid llvm::Align or
/// std::nullopt, Beware llvm::MaybeAlign assumes power of two 8-bit
/// bytes.
llvm::MaybeAlign getAsMaybeAlign() const {
return llvm::MaybeAlign(Quantity);
}
/// alignTo - Returns the next integer (mod 2**64) that is
/// greater than or equal to this quantity and is a multiple of \p Align.
/// Align must be non-zero.
CharUnits alignTo(const CharUnits &Align) const {
return CharUnits(llvm::alignTo(Quantity, Align.Quantity));
}
/// Given that this is a non-zero alignment value, what is the
/// alignment at the given offset?
CharUnits alignmentAtOffset(CharUnits offset) const {
assert(Quantity != 0 && "offsetting from unknown alignment?");
return CharUnits(llvm::MinAlign(Quantity, offset.Quantity));
}
/// Given that this is the alignment of the first element of an
/// array, return the minimum alignment of any element in the array.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const {
// Since we don't track offsetted alignments, the alignment of
// the second element (or any odd element) will be minimally
// aligned.
return alignmentAtOffset(elementSize);
}
}; // class CharUnit
} // namespace clang
inline clang::CharUnits operator* (clang::CharUnits::QuantityType Scale,
const clang::CharUnits &CU) {
return CU * Scale;
}
namespace llvm {
template<> struct DenseMapInfo<clang::CharUnits> {
static clang::CharUnits getEmptyKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getEmptyKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static clang::CharUnits getTombstoneKey() {
clang::CharUnits::QuantityType Quantity =
DenseMapInfo<clang::CharUnits::QuantityType>::getTombstoneKey();
return clang::CharUnits::fromQuantity(Quantity);
}
static unsigned getHashValue(const clang::CharUnits &CU) {
clang::CharUnits::QuantityType Quantity = CU.getQuantity();
return DenseMapInfo<clang::CharUnits::QuantityType>::getHashValue(Quantity);
}
static bool isEqual(const clang::CharUnits &LHS,
const clang::CharUnits &RHS) {
return LHS == RHS;
}
};
} // end namespace llvm
#endif // LLVM_CLANG_AST_CHARUNITS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
//===--- CommentBriefParser.h - Dumb comment parser -------------*- 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 a very simple Doxygen comment parser.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
#include "clang/AST/CommentLexer.h"
namespace clang {
namespace comments {
/// A very simple comment parser that extracts "a brief description".
///
/// Due to a variety of comment styles, it considers the following as "a brief
/// description", in order of priority:
/// \li a \or \\short command,
/// \li the first paragraph,
/// \li a \\result or \\return or \\returns paragraph.
class BriefParser {
Lexer &L;
const CommandTraits &Traits;
/// Current lookahead token.
Token Tok;
SourceLocation ConsumeToken() {
SourceLocation Loc = Tok.getLocation();
L.lex(Tok);
return Loc;
}
public:
BriefParser(Lexer &L, const CommandTraits &Traits);
/// Return the best "brief description" we can find.
std::string Parse();
};
} // end namespace comments
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* A list of commands useable in documentation comments *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: CommentCommands.td *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef COMMENT_COMMAND
# define COMMENT_COMMAND(NAME)
#endif
COMMENT_COMMAND(a)
COMMENT_COMMAND(abstract)
COMMENT_COMMAND(addindex)
COMMENT_COMMAND(addtogroup)
COMMENT_COMMAND(anchor)
COMMENT_COMMAND(arg)
COMMENT_COMMAND(attention)
COMMENT_COMMAND(author)
COMMENT_COMMAND(authors)
COMMENT_COMMAND(b)
COMMENT_COMMAND(brief)
COMMENT_COMMAND(bug)
COMMENT_COMMAND(c)
COMMENT_COMMAND(callgraph)
COMMENT_COMMAND(callback)
COMMENT_COMMAND(callergraph)
COMMENT_COMMAND(category)
COMMENT_COMMAND(cite)
COMMENT_COMMAND(class)
COMMENT_COMMAND(classdesign)
COMMENT_COMMAND(coclass)
COMMENT_COMMAND(code)
COMMENT_COMMAND(endcode)
COMMENT_COMMAND(concept)
COMMENT_COMMAND(cond)
COMMENT_COMMAND(const)
COMMENT_COMMAND(constant)
COMMENT_COMMAND(copybrief)
COMMENT_COMMAND(copydetails)
COMMENT_COMMAND(copydoc)
COMMENT_COMMAND(copyright)
COMMENT_COMMAND(date)
COMMENT_COMMAND(def)
COMMENT_COMMAND(defgroup)
COMMENT_COMMAND(dependency)
COMMENT_COMMAND(deprecated)
COMMENT_COMMAND(details)
COMMENT_COMMAND(diafile)
COMMENT_COMMAND(dir)
COMMENT_COMMAND(discussion)
COMMENT_COMMAND(docbookinclude)
COMMENT_COMMAND(docbookonly)
COMMENT_COMMAND(enddocbookonly)
COMMENT_COMMAND(dontinclude)
COMMENT_COMMAND(dot)
COMMENT_COMMAND(enddot)
COMMENT_COMMAND(dotfile)
COMMENT_COMMAND(e)
COMMENT_COMMAND(else)
COMMENT_COMMAND(elseif)
COMMENT_COMMAND(em)
COMMENT_COMMAND(emoji)
COMMENT_COMMAND(endcond)
COMMENT_COMMAND(endif)
COMMENT_COMMAND(enum)
COMMENT_COMMAND(example)
COMMENT_COMMAND(exception)
COMMENT_COMMAND(extends)
COMMENT_COMMAND(flbrace)
COMMENT_COMMAND(frbrace)
COMMENT_COMMAND(flsquare)
COMMENT_COMMAND(frsquare)
COMMENT_COMMAND(fdollar)
COMMENT_COMMAND(flparen)
COMMENT_COMMAND(frparen)
COMMENT_COMMAND(file)
COMMENT_COMMAND(fn)
COMMENT_COMMAND(function)
COMMENT_COMMAND(functiongroup)
COMMENT_COMMAND(headerfile)
COMMENT_COMMAND(helper)
COMMENT_COMMAND(helperclass)
COMMENT_COMMAND(helps)
COMMENT_COMMAND(hidecallgraph)
COMMENT_COMMAND(hidecallergraph)
COMMENT_COMMAND(hideinitializer)
COMMENT_COMMAND(hiderefby)
COMMENT_COMMAND(hiderefs)
COMMENT_COMMAND(htmlinclude)
COMMENT_COMMAND(htmlonly)
COMMENT_COMMAND(endhtmlonly)
COMMENT_COMMAND(idlexcept)
COMMENT_COMMAND(if)
COMMENT_COMMAND(ifnot)
COMMENT_COMMAND(image)
COMMENT_COMMAND(implements)
COMMENT_COMMAND(include)
COMMENT_COMMAND(ingroup)
COMMENT_COMMAND(instancesize)
COMMENT_COMMAND(interface)
COMMENT_COMMAND(internal)
COMMENT_COMMAND(endinternal)
COMMENT_COMMAND(invariant)
COMMENT_COMMAND(latexinclude)
COMMENT_COMMAND(latexonly)
COMMENT_COMMAND(endlatexonly)
COMMENT_COMMAND(li)
COMMENT_COMMAND(line)
COMMENT_COMMAND(link)
COMMENT_COMMAND(slashlink)
COMMENT_COMMAND(mainpage)
COMMENT_COMMAND(maninclude)
COMMENT_COMMAND(manonly)
COMMENT_COMMAND(endmanonly)
COMMENT_COMMAND(memberof)
COMMENT_COMMAND(method)
COMMENT_COMMAND(methodgroup)
COMMENT_COMMAND(msc)
COMMENT_COMMAND(endmsc)
COMMENT_COMMAND(mscfile)
COMMENT_COMMAND(n)
COMMENT_COMMAND(name)
COMMENT_COMMAND(namespace)
COMMENT_COMMAND(noop)
COMMENT_COMMAND(nosubgrouping)
COMMENT_COMMAND(note)
COMMENT_COMMAND(overload)
COMMENT_COMMAND(ownership)
COMMENT_COMMAND(p)
COMMENT_COMMAND(page)
COMMENT_COMMAND(par)
COMMENT_COMMAND(parblock)
COMMENT_COMMAND(endparblock)
COMMENT_COMMAND(paragraph)
COMMENT_COMMAND(param)
COMMENT_COMMAND(performance)
COMMENT_COMMAND(post)
COMMENT_COMMAND(pre)
COMMENT_COMMAND(private)
COMMENT_COMMAND(privatesection)
COMMENT_COMMAND(property)
COMMENT_COMMAND(protected)
COMMENT_COMMAND(protectedsection)
COMMENT_COMMAND(protocol)
COMMENT_COMMAND(public)
COMMENT_COMMAND(publicsection)
COMMENT_COMMAND(pure)
COMMENT_COMMAND(ref)
COMMENT_COMMAND(refitem)
COMMENT_COMMAND(related)
COMMENT_COMMAND(relatedalso)
COMMENT_COMMAND(relates)
COMMENT_COMMAND(relatesalso)
COMMENT_COMMAND(remark)
COMMENT_COMMAND(remarks)
COMMENT_COMMAND(result)
COMMENT_COMMAND(return)
COMMENT_COMMAND(returns)
COMMENT_COMMAND(retval)
COMMENT_COMMAND(rtfinclude)
COMMENT_COMMAND(rtfonly)
COMMENT_COMMAND(endrtfonly)
COMMENT_COMMAND(sa)
COMMENT_COMMAND(secreflist)
COMMENT_COMMAND(endsecreflist)
COMMENT_COMMAND(section)
COMMENT_COMMAND(security)
COMMENT_COMMAND(see)
COMMENT_COMMAND(seealso)
COMMENT_COMMAND(short)
COMMENT_COMMAND(showinitializer)
COMMENT_COMMAND(showrefby)
COMMENT_COMMAND(showrefs)
COMMENT_COMMAND(since)
COMMENT_COMMAND(skip)
COMMENT_COMMAND(skipline)
COMMENT_COMMAND(snippet)
COMMENT_COMMAND(static)
COMMENT_COMMAND(struct)
COMMENT_COMMAND(subpage)
COMMENT_COMMAND(subsection)
COMMENT_COMMAND(subsubsection)
COMMENT_COMMAND(superclass)
COMMENT_COMMAND(tableofcontents)
COMMENT_COMMAND(template)
COMMENT_COMMAND(templatefield)
COMMENT_COMMAND(test)
COMMENT_COMMAND(textblock)
COMMENT_COMMAND(slashtextblock)
COMMENT_COMMAND(throw)
COMMENT_COMMAND(throws)
COMMENT_COMMAND(todo)
COMMENT_COMMAND(tparam)
COMMENT_COMMAND(typedef)
COMMENT_COMMAND(startuml)
COMMENT_COMMAND(enduml)
COMMENT_COMMAND(union)
COMMENT_COMMAND(until)
COMMENT_COMMAND(var)
COMMENT_COMMAND(verbinclude)
COMMENT_COMMAND(verbatim)
COMMENT_COMMAND(endverbatim)
COMMENT_COMMAND(version)
COMMENT_COMMAND(warning)
COMMENT_COMMAND(weakgroup)
COMMENT_COMMAND(xrefitem)
COMMENT_COMMAND(xmlinclude)
COMMENT_COMMAND(xmlonly)
COMMENT_COMMAND(endxmlonly)

View File

@ -0,0 +1,210 @@
//===--- CommentCommandTraits.h - Comment command properties ----*- 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 class that provides information about comment
// commands.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
/// Information about a single command.
///
/// When reordering, adding or removing members please update the corresponding
/// TableGen backend.
struct CommandInfo {
unsigned getID() const {
return ID;
}
const char *Name;
/// Name of the command that ends the verbatim block.
const char *EndCommandName;
/// DRY definition of the number of bits used for a command ID.
enum { NumCommandIDBits = 20 };
/// The ID of the command.
unsigned ID : NumCommandIDBits;
/// Number of word-like arguments for a given block command, except for
/// \\param and \\tparam commands -- these have special argument parsers.
unsigned NumArgs : 4;
/// True if this command is a inline command (of any kind).
LLVM_PREFERRED_TYPE(bool)
unsigned IsInlineCommand : 1;
/// True if this command is a block command (of any kind).
LLVM_PREFERRED_TYPE(bool)
unsigned IsBlockCommand : 1;
/// True if this command is introducing a brief documentation
/// paragraph (\or an alias).
LLVM_PREFERRED_TYPE(bool)
unsigned IsBriefCommand : 1;
/// True if this command is \\returns or an alias.
LLVM_PREFERRED_TYPE(bool)
unsigned IsReturnsCommand : 1;
/// True if this command is introducing documentation for a function
/// parameter (\\param or an alias).
LLVM_PREFERRED_TYPE(bool)
unsigned IsParamCommand : 1;
/// True if this command is introducing documentation for
/// a template parameter (\\tparam or an alias).
LLVM_PREFERRED_TYPE(bool)
unsigned IsTParamCommand : 1;
/// True if this command is \\throws or an alias.
LLVM_PREFERRED_TYPE(bool)
unsigned IsThrowsCommand : 1;
/// True if this command is \\deprecated or an alias.
LLVM_PREFERRED_TYPE(bool)
unsigned IsDeprecatedCommand : 1;
/// True if this is a \\headerfile-like command.
LLVM_PREFERRED_TYPE(bool)
unsigned IsHeaderfileCommand : 1;
/// True if this is a \\par command.
LLVM_PREFERRED_TYPE(bool)
unsigned IsParCommand : 1;
/// True if we don't want to warn about this command being passed an empty
/// paragraph. Meaningful only for block commands.
LLVM_PREFERRED_TYPE(bool)
unsigned IsEmptyParagraphAllowed : 1;
/// True if this command is a verbatim-like block command.
///
/// A verbatim-like block command eats every character (except line starting
/// decorations) until matching end command is seen or comment end is hit.
LLVM_PREFERRED_TYPE(bool)
unsigned IsVerbatimBlockCommand : 1;
/// True if this command is an end command for a verbatim-like block.
LLVM_PREFERRED_TYPE(bool)
unsigned IsVerbatimBlockEndCommand : 1;
/// True if this command is a verbatim line command.
///
/// A verbatim-like line command eats everything until a newline is seen or
/// comment end is hit.
LLVM_PREFERRED_TYPE(bool)
unsigned IsVerbatimLineCommand : 1;
/// True if this command contains a declaration for the entity being
/// documented.
///
/// For example:
/// \code
/// \fn void f(int a);
/// \endcode
LLVM_PREFERRED_TYPE(bool)
unsigned IsDeclarationCommand : 1;
/// True if verbatim-like line command is a function declaration.
LLVM_PREFERRED_TYPE(bool)
unsigned IsFunctionDeclarationCommand : 1;
/// True if block command is further describing a container API; such
/// as \@coclass, \@classdesign, etc.
LLVM_PREFERRED_TYPE(bool)
unsigned IsRecordLikeDetailCommand : 1;
/// True if block command is a container API; such as \@interface.
LLVM_PREFERRED_TYPE(bool)
unsigned IsRecordLikeDeclarationCommand : 1;
/// True if this command is unknown. This \c CommandInfo object was
/// created during parsing.
LLVM_PREFERRED_TYPE(bool)
unsigned IsUnknownCommand : 1;
};
/// This class provides information about commands that can be used
/// in comments.
class CommandTraits {
public:
enum KnownCommandIDs {
#define COMMENT_COMMAND(NAME) KCI_##NAME,
#include "clang/AST/CommentCommandList.inc"
#undef COMMENT_COMMAND
KCI_Last
};
CommandTraits(llvm::BumpPtrAllocator &Allocator,
const CommentOptions &CommentOptions);
void registerCommentOptions(const CommentOptions &CommentOptions);
/// \returns a CommandInfo object for a given command name or
/// NULL if no CommandInfo object exists for this command.
const CommandInfo *getCommandInfoOrNULL(StringRef Name) const;
const CommandInfo *getCommandInfo(StringRef Name) const {
if (const CommandInfo *Info = getCommandInfoOrNULL(Name))
return Info;
llvm_unreachable("the command should be known");
}
const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const;
const CommandInfo *getCommandInfo(unsigned CommandID) const;
const CommandInfo *registerUnknownCommand(StringRef CommandName);
const CommandInfo *registerBlockCommand(StringRef CommandName);
/// \returns a CommandInfo object for a given command name or
/// NULL if \c Name is not a builtin command.
static const CommandInfo *getBuiltinCommandInfo(StringRef Name);
/// \returns a CommandInfo object for a given command ID or
/// NULL if \c CommandID is not a builtin command.
static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID);
private:
CommandTraits(const CommandTraits &) = delete;
void operator=(const CommandTraits &) = delete;
const CommandInfo *getRegisteredCommandInfo(StringRef Name) const;
const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const;
CommandInfo *createCommandInfoWithName(StringRef CommandName);
unsigned NextID;
/// Allocator for CommandInfo objects.
llvm::BumpPtrAllocator &Allocator;
SmallVector<CommandInfo *, 4> RegisteredCommands;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@ -0,0 +1,15 @@
//===--- CommentDiagnostic.h - Diagnostics for the AST library --*- 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_AST_COMMENTDIAGNOSTIC_H
#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
#include "clang/Basic/DiagnosticComment.h"
#endif

View File

@ -0,0 +1,816 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* HTML named character reference to UTF-8 translation *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: CommentHTMLNamedCharacterReferences.td *|
|* *|
\*===----------------------------------------------------------------------===*/
StringRef translateHTMLNamedCharacterReferenceToUTF8(
StringRef Name) {
switch (Name.size()) {
default: break;
case 2: // 15 strings to match.
switch (Name[0]) {
default: break;
case 'G': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'T': // 1 string to match.
return "\x3e"; // "GT"
case 't': // 1 string to match.
return "\x3e"; // "Gt"
}
break;
case 'L': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'T': // 1 string to match.
return "\x3c"; // "LT"
case 't': // 1 string to match.
return "\x3c"; // "Lt"
}
break;
case 'P': // 1 string to match.
if (Name[1] != 'i')
break;
return "\xce\xa0"; // "Pi"
case 'X': // 1 string to match.
if (Name[1] != 'i')
break;
return "\xce\x9e"; // "Xi"
case 'g': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 1 string to match.
return "\xe2\x89\xa5"; // "ge"
case 't': // 1 string to match.
return "\x3e"; // "gt"
}
break;
case 'l': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 1 string to match.
return "\xe2\x89\xa4"; // "le"
case 't': // 1 string to match.
return "\x3c"; // "lt"
}
break;
case 'm': // 1 string to match.
if (Name[1] != 'u')
break;
return "\xce\xbc"; // "mu"
case 'n': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 1 string to match.
return "\xe2\x89\xa0"; // "ne"
case 'u': // 1 string to match.
return "\xce\xbd"; // "nu"
}
break;
case 'p': // 1 string to match.
if (Name[1] != 'i')
break;
return "\xcf\x80"; // "pi"
case 'x': // 1 string to match.
if (Name[1] != 'i')
break;
return "\xce\xbe"; // "xi"
}
break;
case 3: // 16 strings to match.
switch (Name[0]) {
default: break;
case 'A': // 1 string to match.
if (memcmp(Name.data()+1, "MP", 2) != 0)
break;
return "\x26"; // "AMP"
case 'P': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'h': // 1 string to match.
if (Name[2] != 'i')
break;
return "\xce\xa6"; // "Phi"
case 's': // 1 string to match.
if (Name[2] != 'i')
break;
return "\xce\xa8"; // "Psi"
}
break;
case 'R': // 1 string to match.
if (memcmp(Name.data()+1, "EG", 2) != 0)
break;
return "\xc2\xae"; // "REG"
case 'a': // 1 string to match.
if (memcmp(Name.data()+1, "mp", 2) != 0)
break;
return "\x26"; // "amp"
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "hi", 2) != 0)
break;
return "\xcf\x87"; // "chi"
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "eg", 2) != 0)
break;
return "\xc2\xb0"; // "deg"
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "ta", 2) != 0)
break;
return "\xce\xb7"; // "eta"
case 'i': // 1 string to match.
if (memcmp(Name.data()+1, "nt", 2) != 0)
break;
return "\xe2\x88\xab"; // "int"
case 'p': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'h': // 1 string to match.
if (Name[2] != 'i')
break;
return "\xcf\x86"; // "phi"
case 's': // 1 string to match.
if (Name[2] != 'i')
break;
return "\xcf\x88"; // "psi"
}
break;
case 'r': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 1 string to match.
if (Name[2] != 'g')
break;
return "\xc2\xae"; // "reg"
case 'h': // 1 string to match.
if (Name[2] != 'o')
break;
return "\xcf\x81"; // "rho"
}
break;
case 's': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'i': // 1 string to match.
if (Name[2] != 'm')
break;
return "\xe2\x88\xbc"; // "sim"
case 'u': // 1 string to match.
if (Name[2] != 'm')
break;
return "\xe2\x88\x91"; // "sum"
}
break;
case 't': // 1 string to match.
if (memcmp(Name.data()+1, "au", 2) != 0)
break;
return "\xcf\x84"; // "tau"
}
break;
case 4: // 30 strings to match.
switch (Name[0]) {
default: break;
case 'A': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\x84"; // "Auml"
case 'C': // 1 string to match.
if (memcmp(Name.data()+1, "OPY", 3) != 0)
break;
return "\xc2\xa9"; // "COPY"
case 'E': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\x8b"; // "Euml"
case 'I': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\x8f"; // "Iuml"
case 'O': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\x96"; // "Ouml"
case 'Q': // 1 string to match.
if (memcmp(Name.data()+1, "UOT", 3) != 0)
break;
return "\x22"; // "QUOT"
case 'U': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\x9c"; // "Uuml"
case 'Y': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc5\xb8"; // "Yuml"
case 'a': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+2, "os", 2) != 0)
break;
return "\x27"; // "apos"
case 'u': // 1 string to match.
if (memcmp(Name.data()+2, "ml", 2) != 0)
break;
return "\xc3\xa4"; // "auml"
}
break;
case 'b': // 1 string to match.
if (memcmp(Name.data()+1, "eta", 3) != 0)
break;
return "\xce\xb2"; // "beta"
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "opy", 3) != 0)
break;
return "\xc2\xa9"; // "copy"
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\xab"; // "euml"
case 'i': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'o': // 1 string to match.
if (memcmp(Name.data()+2, "ta", 2) != 0)
break;
return "\xce\xb9"; // "iota"
case 's': // 1 string to match.
if (memcmp(Name.data()+2, "in", 2) != 0)
break;
return "\xe2\x88\x88"; // "isin"
case 'u': // 1 string to match.
if (memcmp(Name.data()+2, "ml", 2) != 0)
break;
return "\xc3\xaf"; // "iuml"
}
break;
case 'l': // 1 string to match.
if (memcmp(Name.data()+1, "arr", 3) != 0)
break;
return "\xe2\x86\x90"; // "larr"
case 'n': // 1 string to match.
if (memcmp(Name.data()+1, "bsp", 3) != 0)
break;
return "\xc2\xa0"; // "nbsp"
case 'o': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\xb6"; // "ouml"
case 'p': // 4 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "rt", 2) != 0)
break;
return "\xe2\x88\x82"; // "part"
case 'e': // 1 string to match.
if (memcmp(Name.data()+2, "rp", 2) != 0)
break;
return "\xe2\x8a\xa5"; // "perp"
case 'r': // 2 strings to match.
if (Name[2] != 'o')
break;
switch (Name[3]) {
default: break;
case 'd': // 1 string to match.
return "\xe2\x88\x8f"; // "prod"
case 'p': // 1 string to match.
return "\xe2\x88\x9d"; // "prop"
}
break;
}
break;
case 'q': // 1 string to match.
if (memcmp(Name.data()+1, "uot", 3) != 0)
break;
return "\x22"; // "quot"
case 'r': // 1 string to match.
if (memcmp(Name.data()+1, "arr", 3) != 0)
break;
return "\xe2\x86\x92"; // "rarr"
case 's': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
if (memcmp(Name.data()+2, "ot", 2) != 0)
break;
return "\xe2\x8b\x85"; // "sdot"
case 'e': // 1 string to match.
if (memcmp(Name.data()+2, "ct", 2) != 0)
break;
return "\xc2\xa7"; // "sect"
}
break;
case 'u': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\xbc"; // "uuml"
case 'y': // 1 string to match.
if (memcmp(Name.data()+1, "uml", 3) != 0)
break;
return "\xc3\xbf"; // "yuml"
case 'z': // 1 string to match.
if (memcmp(Name.data()+1, "eta", 3) != 0)
break;
return "\xce\xb6"; // "zeta"
}
break;
case 5: // 48 strings to match.
switch (Name[0]) {
default: break;
case 'A': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\x82"; // "Acirc"
case 'r': // 1 string to match.
if (memcmp(Name.data()+2, "ing", 3) != 0)
break;
return "\xc3\x85"; // "Aring"
}
break;
case 'D': // 1 string to match.
if (memcmp(Name.data()+1, "elta", 4) != 0)
break;
return "\xce\x94"; // "Delta"
case 'E': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc3\x8a"; // "Ecirc"
case 'G': // 1 string to match.
if (memcmp(Name.data()+1, "amma", 4) != 0)
break;
return "\xce\x93"; // "Gamma"
case 'I': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc3\x8e"; // "Icirc"
case 'O': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\x94"; // "Ocirc"
case 'm': // 1 string to match.
if (memcmp(Name.data()+2, "ega", 3) != 0)
break;
return "\xce\xa9"; // "Omega"
}
break;
case 'P': // 1 string to match.
if (memcmp(Name.data()+1, "rime", 4) != 0)
break;
return "\xe2\x80\xb3"; // "Prime"
case 'S': // 1 string to match.
if (memcmp(Name.data()+1, "igma", 4) != 0)
break;
return "\xce\xa3"; // "Sigma"
case 'T': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'R': // 1 string to match.
if (memcmp(Name.data()+2, "ADE", 3) != 0)
break;
return "\xe2\x84\xa2"; // "TRADE"
case 'h': // 1 string to match.
if (memcmp(Name.data()+2, "eta", 3) != 0)
break;
return "\xce\x98"; // "Theta"
}
break;
case 'U': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc3\x9b"; // "Ucirc"
case 'Y': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc5\xb6"; // "Ycirc"
case 'a': // 4 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\xa2"; // "acirc"
case 'l': // 1 string to match.
if (memcmp(Name.data()+2, "pha", 3) != 0)
break;
return "\xce\xb1"; // "alpha"
case 'r': // 1 string to match.
if (memcmp(Name.data()+2, "ing", 3) != 0)
break;
return "\xc3\xa5"; // "aring"
case 's': // 1 string to match.
if (memcmp(Name.data()+2, "ymp", 3) != 0)
break;
return "\xe2\x89\x88"; // "asymp"
}
break;
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "elta", 4) != 0)
break;
return "\xce\xb4"; // "delta"
case 'e': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\xaa"; // "ecirc"
case 'm': // 1 string to match.
if (memcmp(Name.data()+2, "pty", 3) != 0)
break;
return "\xe2\x88\x85"; // "empty"
case 'q': // 1 string to match.
if (memcmp(Name.data()+2, "uiv", 3) != 0)
break;
return "\xe2\x89\xa1"; // "equiv"
}
break;
case 'g': // 1 string to match.
if (memcmp(Name.data()+1, "amma", 4) != 0)
break;
return "\xce\xb3"; // "gamma"
case 'i': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\xae"; // "icirc"
case 'n': // 1 string to match.
if (memcmp(Name.data()+2, "fin", 3) != 0)
break;
return "\xe2\x88\x9e"; // "infin"
}
break;
case 'k': // 1 string to match.
if (memcmp(Name.data()+1, "appa", 4) != 0)
break;
return "\xce\xba"; // "kappa"
case 'l': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "eil", 3) != 0)
break;
return "\xe2\x8c\x88"; // "lceil"
case 'd': // 1 string to match.
if (memcmp(Name.data()+2, "quo", 3) != 0)
break;
return "\xe2\x80\x9c"; // "ldquo"
case 's': // 1 string to match.
if (memcmp(Name.data()+2, "quo", 3) != 0)
break;
return "\xe2\x80\x98"; // "lsquo"
}
break;
case 'm': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
if (memcmp(Name.data()+2, "ash", 3) != 0)
break;
return "\xe2\x80\x94"; // "mdash"
case 'i': // 1 string to match.
if (memcmp(Name.data()+2, "nus", 3) != 0)
break;
return "\xe2\x88\x92"; // "minus"
}
break;
case 'n': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "bla", 3) != 0)
break;
return "\xe2\x88\x87"; // "nabla"
case 'd': // 1 string to match.
if (memcmp(Name.data()+2, "ash", 3) != 0)
break;
return "\xe2\x80\x93"; // "ndash"
case 'o': // 1 string to match.
if (memcmp(Name.data()+2, "tin", 3) != 0)
break;
return "\xe2\x88\x89"; // "notin"
}
break;
case 'o': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "irc", 3) != 0)
break;
return "\xc3\xb4"; // "ocirc"
case 'm': // 1 string to match.
if (memcmp(Name.data()+2, "ega", 3) != 0)
break;
return "\xcf\x89"; // "omega"
}
break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "rime", 4) != 0)
break;
return "\xe2\x80\xb2"; // "prime"
case 'r': // 4 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "dic", 3) != 0)
break;
return "\xe2\x88\x9a"; // "radic"
case 'c': // 1 string to match.
if (memcmp(Name.data()+2, "eil", 3) != 0)
break;
return "\xe2\x8c\x89"; // "rceil"
case 'd': // 1 string to match.
if (memcmp(Name.data()+2, "quo", 3) != 0)
break;
return "\xe2\x80\x9d"; // "rdquo"
case 's': // 1 string to match.
if (memcmp(Name.data()+2, "quo", 3) != 0)
break;
return "\xe2\x80\x99"; // "rsquo"
}
break;
case 's': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'i': // 1 string to match.
if (memcmp(Name.data()+2, "gma", 3) != 0)
break;
return "\xcf\x83"; // "sigma"
case 'z': // 1 string to match.
if (memcmp(Name.data()+2, "lig", 3) != 0)
break;
return "\xc3\x9f"; // "szlig"
}
break;
case 't': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'h': // 1 string to match.
if (memcmp(Name.data()+2, "eta", 3) != 0)
break;
return "\xce\xb8"; // "theta"
case 'i': // 1 string to match.
if (memcmp(Name.data()+2, "mes", 3) != 0)
break;
return "\xc3\x97"; // "times"
case 'r': // 1 string to match.
if (memcmp(Name.data()+2, "ade", 3) != 0)
break;
return "\xe2\x84\xa2"; // "trade"
}
break;
case 'u': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc3\xbb"; // "ucirc"
case 'y': // 1 string to match.
if (memcmp(Name.data()+1, "circ", 4) != 0)
break;
return "\xc5\xb7"; // "ycirc"
}
break;
case 6: // 37 strings to match.
switch (Name[0]) {
default: break;
case 'A': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\x81"; // "Aacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\x80"; // "Agrave"
case 't': // 1 string to match.
if (memcmp(Name.data()+2, "ilde", 4) != 0)
break;
return "\xc3\x83"; // "Atilde"
}
break;
case 'C': // 1 string to match.
if (memcmp(Name.data()+1, "cedil", 5) != 0)
break;
return "\xc3\x87"; // "Ccedil"
case 'E': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\x89"; // "Eacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\x88"; // "Egrave"
}
break;
case 'I': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\x8d"; // "Iacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\x8c"; // "Igrave"
}
break;
case 'L': // 1 string to match.
if (memcmp(Name.data()+1, "ambda", 5) != 0)
break;
return "\xce\x9b"; // "Lambda"
case 'N': // 1 string to match.
if (memcmp(Name.data()+1, "tilde", 5) != 0)
break;
return "\xc3\x91"; // "Ntilde"
case 'O': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\x93"; // "Oacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\x92"; // "Ograve"
case 't': // 1 string to match.
if (memcmp(Name.data()+2, "ilde", 4) != 0)
break;
return "\xc3\x95"; // "Otilde"
}
break;
case 'U': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\x9a"; // "Uacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\x99"; // "Ugrave"
}
break;
case 'Y': // 1 string to match.
if (memcmp(Name.data()+1, "acute", 5) != 0)
break;
return "\xc3\x9d"; // "Yacute"
case 'a': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xa1"; // "aacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\xa0"; // "agrave"
case 't': // 1 string to match.
if (memcmp(Name.data()+2, "ilde", 4) != 0)
break;
return "\xc3\xa3"; // "atilde"
}
break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "cedil", 5) != 0)
break;
return "\xc3\xa7"; // "ccedil"
case 'e': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xa9"; // "eacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\xa8"; // "egrave"
}
break;
case 'i': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xad"; // "iacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\xac"; // "igrave"
}
break;
case 'l': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "mbda", 4) != 0)
break;
return "\xce\xbb"; // "lambda"
case 'f': // 1 string to match.
if (memcmp(Name.data()+2, "loor", 4) != 0)
break;
return "\xe2\x8c\x8a"; // "lfloor"
}
break;
case 'n': // 1 string to match.
if (memcmp(Name.data()+1, "tilde", 5) != 0)
break;
return "\xc3\xb1"; // "ntilde"
case 'o': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xb3"; // "oacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\xb2"; // "ograve"
case 't': // 1 string to match.
if (memcmp(Name.data()+2, "ilde", 4) != 0)
break;
return "\xc3\xb5"; // "otilde"
}
break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "lusmn", 5) != 0)
break;
return "\xc2\xb1"; // "plusmn"
case 'r': // 1 string to match.
if (memcmp(Name.data()+1, "floor", 5) != 0)
break;
return "\xe2\x8c\x8b"; // "rfloor"
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "igmaf", 5) != 0)
break;
return "\xcf\x82"; // "sigmaf"
case 'u': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xba"; // "uacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xc3\xb9"; // "ugrave"
}
break;
case 'y': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "cute", 4) != 0)
break;
return "\xc3\xbd"; // "yacute"
case 'g': // 1 string to match.
if (memcmp(Name.data()+2, "rave", 4) != 0)
break;
return "\xe1\xbb\xb3"; // "ygrave"
}
break;
}
break;
case 7: // 3 strings to match.
switch (Name[0]) {
default: break;
case 'U': // 1 string to match.
if (memcmp(Name.data()+1, "psilon", 6) != 0)
break;
return "\xce\xa5"; // "Upsilon"
case 'e': // 1 string to match.
if (memcmp(Name.data()+1, "psilon", 6) != 0)
break;
return "\xce\xb5"; // "epsilon"
case 'u': // 1 string to match.
if (memcmp(Name.data()+1, "psilon", 6) != 0)
break;
return "\xcf\x85"; // "upsilon"
}
break;
}
return StringRef();
}

View File

@ -0,0 +1,264 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* HTML tag name matcher *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: CommentHTMLTags.td *|
|* *|
\*===----------------------------------------------------------------------===*/
bool isHTMLTagName(StringRef Name) {
switch (Name.size()) {
default: break;
case 1: // 6 strings to match.
switch (Name[0]) {
default: break;
case 'a': // 1 string to match.
return true; // "a"
case 'b': // 1 string to match.
return true; // "b"
case 'i': // 1 string to match.
return true; // "i"
case 'p': // 1 string to match.
return true; // "p"
case 's': // 1 string to match.
return true; // "s"
case 'u': // 1 string to match.
return true; // "u"
}
break;
case 2: // 19 strings to match.
switch (Name[0]) {
default: break;
case 'b': // 1 string to match.
if (Name[1] != 'r')
break;
return true; // "br"
case 'd': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
return true; // "dd"
case 'l': // 1 string to match.
return true; // "dl"
case 't': // 1 string to match.
return true; // "dt"
}
break;
case 'e': // 1 string to match.
if (Name[1] != 'm')
break;
return true; // "em"
case 'h': // 7 strings to match.
switch (Name[1]) {
default: break;
case '1': // 1 string to match.
return true; // "h1"
case '2': // 1 string to match.
return true; // "h2"
case '3': // 1 string to match.
return true; // "h3"
case '4': // 1 string to match.
return true; // "h4"
case '5': // 1 string to match.
return true; // "h5"
case '6': // 1 string to match.
return true; // "h6"
case 'r': // 1 string to match.
return true; // "hr"
}
break;
case 'l': // 1 string to match.
if (Name[1] != 'i')
break;
return true; // "li"
case 'o': // 1 string to match.
if (Name[1] != 'l')
break;
return true; // "ol"
case 't': // 4 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
return true; // "td"
case 'h': // 1 string to match.
return true; // "th"
case 'r': // 1 string to match.
return true; // "tr"
case 't': // 1 string to match.
return true; // "tt"
}
break;
case 'u': // 1 string to match.
if (Name[1] != 'l')
break;
return true; // "ul"
}
break;
case 3: // 9 strings to match.
switch (Name[0]) {
default: break;
case 'b': // 1 string to match.
if (memcmp(Name.data()+1, "ig", 2) != 0)
break;
return true; // "big"
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "ol", 2) != 0)
break;
return true; // "col"
case 'd': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'e': // 1 string to match.
if (Name[2] != 'l')
break;
return true; // "del"
case 'i': // 1 string to match.
if (Name[2] != 'v')
break;
return true; // "div"
}
break;
case 'i': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'm': // 1 string to match.
if (Name[2] != 'g')
break;
return true; // "img"
case 'n': // 1 string to match.
if (Name[2] != 's')
break;
return true; // "ins"
}
break;
case 'p': // 1 string to match.
if (memcmp(Name.data()+1, "re", 2) != 0)
break;
return true; // "pre"
case 's': // 2 strings to match.
if (Name[1] != 'u')
break;
switch (Name[2]) {
default: break;
case 'b': // 1 string to match.
return true; // "sub"
case 'p': // 1 string to match.
return true; // "sup"
}
break;
}
break;
case 4: // 4 strings to match.
switch (Name[0]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "ode", 3) != 0)
break;
return true; // "code"
case 'f': // 1 string to match.
if (memcmp(Name.data()+1, "ont", 3) != 0)
break;
return true; // "font"
case 'm': // 1 string to match.
if (memcmp(Name.data()+1, "ark", 3) != 0)
break;
return true; // "mark"
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "pan", 3) != 0)
break;
return true; // "span"
}
break;
case 5: // 5 strings to match.
switch (Name[0]) {
default: break;
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "mall", 4) != 0)
break;
return true; // "small"
case 't': // 4 strings to match.
switch (Name[1]) {
default: break;
case 'a': // 1 string to match.
if (memcmp(Name.data()+2, "ble", 3) != 0)
break;
return true; // "table"
case 'b': // 1 string to match.
if (memcmp(Name.data()+2, "ody", 3) != 0)
break;
return true; // "tbody"
case 'f': // 1 string to match.
if (memcmp(Name.data()+2, "oot", 3) != 0)
break;
return true; // "tfoot"
case 'h': // 1 string to match.
if (memcmp(Name.data()+2, "ead", 3) != 0)
break;
return true; // "thead"
}
break;
}
break;
case 6: // 3 strings to match.
switch (Name[0]) {
default: break;
case 'f': // 1 string to match.
if (memcmp(Name.data()+1, "igure", 5) != 0)
break;
return true; // "figure"
case 's': // 2 strings to match.
if (memcmp(Name.data()+1, "tr", 2) != 0)
break;
switch (Name[3]) {
default: break;
case 'i': // 1 string to match.
if (memcmp(Name.data()+4, "ke", 2) != 0)
break;
return true; // "strike"
case 'o': // 1 string to match.
if (memcmp(Name.data()+4, "ng", 2) != 0)
break;
return true; // "strong"
}
break;
}
break;
case 7: // 3 strings to match.
switch (Name[0]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "aption", 6) != 0)
break;
return true; // "caption"
case 'd': // 1 string to match.
if (memcmp(Name.data()+1, "etails", 6) != 0)
break;
return true; // "details"
case 's': // 1 string to match.
if (memcmp(Name.data()+1, "ummary", 6) != 0)
break;
return true; // "summary"
}
break;
case 8: // 1 string to match.
if (memcmp(Name.data()+0, "colgroup", 8) != 0)
break;
return true; // "colgroup"
case 10: // 2 strings to match.
switch (Name[0]) {
default: break;
case 'b': // 1 string to match.
if (memcmp(Name.data()+1, "lockquote", 9) != 0)
break;
return true; // "blockquote"
case 'f': // 1 string to match.
if (memcmp(Name.data()+1, "igcaption", 9) != 0)
break;
return true; // "figcaption"
}
break;
}
return false;
}

View File

@ -0,0 +1,105 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* HTML tag properties *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: CommentHTMLTags.td *|
|* *|
\*===----------------------------------------------------------------------===*/
bool isHTMLEndTagOptional(StringRef Name) {
switch (Name.size()) {
default: break;
case 1: // 1 string to match.
if (Name[0] != 'p')
break;
return true; // "p"
case 2: // 6 strings to match.
switch (Name[0]) {
default: break;
case 'd': // 2 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
return true; // "dd"
case 't': // 1 string to match.
return true; // "dt"
}
break;
case 'l': // 1 string to match.
if (Name[1] != 'i')
break;
return true; // "li"
case 't': // 3 strings to match.
switch (Name[1]) {
default: break;
case 'd': // 1 string to match.
return true; // "td"
case 'h': // 1 string to match.
return true; // "th"
case 'r': // 1 string to match.
return true; // "tr"
}
break;
}
break;
case 5: // 3 strings to match.
if (Name[0] != 't')
break;
switch (Name[1]) {
default: break;
case 'b': // 1 string to match.
if (memcmp(Name.data()+2, "ody", 3) != 0)
break;
return true; // "tbody"
case 'f': // 1 string to match.
if (memcmp(Name.data()+2, "oot", 3) != 0)
break;
return true; // "tfoot"
case 'h': // 1 string to match.
if (memcmp(Name.data()+2, "ead", 3) != 0)
break;
return true; // "thead"
}
break;
case 8: // 1 string to match.
if (memcmp(Name.data()+0, "colgroup", 8) != 0)
break;
return true; // "colgroup"
}
return false;
}
bool isHTMLEndTagForbidden(StringRef Name) {
switch (Name.size()) {
default: break;
case 2: // 2 strings to match.
switch (Name[0]) {
default: break;
case 'b': // 1 string to match.
if (Name[1] != 'r')
break;
return true; // "br"
case 'h': // 1 string to match.
if (Name[1] != 'r')
break;
return true; // "hr"
}
break;
case 3: // 2 strings to match.
switch (Name[0]) {
default: break;
case 'c': // 1 string to match.
if (memcmp(Name.data()+1, "ol", 2) != 0)
break;
return true; // "col"
case 'i': // 1 string to match.
if (memcmp(Name.data()+1, "mg", 2) != 0)
break;
return true; // "img"
}
break;
}
return false;
}

View File

@ -0,0 +1,366 @@
//===--- CommentLexer.h - Lexer for structured comments ---------*- 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 lexer for structured comments and supporting token class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTLEXER_H
#define LLVM_CLANG_AST_COMMENTLEXER_H
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
namespace comments {
class Lexer;
class TextTokenRetokenizer;
struct CommandInfo;
class CommandTraits;
namespace tok {
enum TokenKind {
eof,
newline,
text,
unknown_command, // Command that does not have an ID.
backslash_command, // Command with an ID, that used backslash marker.
at_command, // Command with an ID, that used 'at' marker.
verbatim_block_begin,
verbatim_block_line,
verbatim_block_end,
verbatim_line_name,
verbatim_line_text,
html_start_tag, // <tag
html_ident, // attr
html_equals, // =
html_quoted_string, // "blah\"blah" or 'blah\'blah'
html_greater, // >
html_slash_greater, // />
html_end_tag // </tag
};
} // end namespace tok
/// Comment token.
class Token {
friend class Lexer;
friend class TextTokenRetokenizer;
/// The location of the token.
SourceLocation Loc;
/// The actual kind of the token.
tok::TokenKind Kind;
/// Integer value associated with a token.
///
/// If the token is a known command, contains command ID and TextPtr is
/// unused (command spelling can be found with CommandTraits). Otherwise,
/// contains the length of the string that starts at TextPtr.
unsigned IntVal;
/// Length of the token spelling in comment. Can be 0 for synthenized
/// tokens.
unsigned Length;
/// Contains text value associated with a token.
const char *TextPtr;
public:
SourceLocation getLocation() const LLVM_READONLY { return Loc; }
void setLocation(SourceLocation SL) { Loc = SL; }
SourceLocation getEndLocation() const LLVM_READONLY {
if (Length == 0 || Length == 1)
return Loc;
return Loc.getLocWithOffset(Length - 1);
}
tok::TokenKind getKind() const LLVM_READONLY { return Kind; }
void setKind(tok::TokenKind K) { Kind = K; }
bool is(tok::TokenKind K) const LLVM_READONLY { return Kind == K; }
bool isNot(tok::TokenKind K) const LLVM_READONLY { return Kind != K; }
unsigned getLength() const LLVM_READONLY { return Length; }
void setLength(unsigned L) { Length = L; }
StringRef getText() const LLVM_READONLY {
assert(is(tok::text));
return StringRef(TextPtr, IntVal);
}
void setText(StringRef Text) {
assert(is(tok::text));
TextPtr = Text.data();
IntVal = Text.size();
}
StringRef getUnknownCommandName() const LLVM_READONLY {
assert(is(tok::unknown_command));
return StringRef(TextPtr, IntVal);
}
void setUnknownCommandName(StringRef Name) {
assert(is(tok::unknown_command));
TextPtr = Name.data();
IntVal = Name.size();
}
unsigned getCommandID() const LLVM_READONLY {
assert(is(tok::backslash_command) || is(tok::at_command));
return IntVal;
}
void setCommandID(unsigned ID) {
assert(is(tok::backslash_command) || is(tok::at_command));
IntVal = ID;
}
unsigned getVerbatimBlockID() const LLVM_READONLY {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
return IntVal;
}
void setVerbatimBlockID(unsigned ID) {
assert(is(tok::verbatim_block_begin) || is(tok::verbatim_block_end));
IntVal = ID;
}
StringRef getVerbatimBlockText() const LLVM_READONLY {
assert(is(tok::verbatim_block_line));
return StringRef(TextPtr, IntVal);
}
void setVerbatimBlockText(StringRef Text) {
assert(is(tok::verbatim_block_line));
TextPtr = Text.data();
IntVal = Text.size();
}
unsigned getVerbatimLineID() const LLVM_READONLY {
assert(is(tok::verbatim_line_name));
return IntVal;
}
void setVerbatimLineID(unsigned ID) {
assert(is(tok::verbatim_line_name));
IntVal = ID;
}
StringRef getVerbatimLineText() const LLVM_READONLY {
assert(is(tok::verbatim_line_text));
return StringRef(TextPtr, IntVal);
}
void setVerbatimLineText(StringRef Text) {
assert(is(tok::verbatim_line_text));
TextPtr = Text.data();
IntVal = Text.size();
}
StringRef getHTMLTagStartName() const LLVM_READONLY {
assert(is(tok::html_start_tag));
return StringRef(TextPtr, IntVal);
}
void setHTMLTagStartName(StringRef Name) {
assert(is(tok::html_start_tag));
TextPtr = Name.data();
IntVal = Name.size();
}
StringRef getHTMLIdent() const LLVM_READONLY {
assert(is(tok::html_ident));
return StringRef(TextPtr, IntVal);
}
void setHTMLIdent(StringRef Name) {
assert(is(tok::html_ident));
TextPtr = Name.data();
IntVal = Name.size();
}
StringRef getHTMLQuotedString() const LLVM_READONLY {
assert(is(tok::html_quoted_string));
return StringRef(TextPtr, IntVal);
}
void setHTMLQuotedString(StringRef Str) {
assert(is(tok::html_quoted_string));
TextPtr = Str.data();
IntVal = Str.size();
}
StringRef getHTMLTagEndName() const LLVM_READONLY {
assert(is(tok::html_end_tag));
return StringRef(TextPtr, IntVal);
}
void setHTMLTagEndName(StringRef Name) {
assert(is(tok::html_end_tag));
TextPtr = Name.data();
IntVal = Name.size();
}
void dump(const Lexer &L, const SourceManager &SM) const;
};
/// Comment lexer.
class Lexer {
private:
Lexer(const Lexer &) = delete;
void operator=(const Lexer &) = delete;
/// Allocator for strings that are semantic values of tokens and have to be
/// computed (for example, resolved decimal character references).
llvm::BumpPtrAllocator &Allocator;
DiagnosticsEngine &Diags;
const CommandTraits &Traits;
const char *const BufferStart;
const char *const BufferEnd;
const char *BufferPtr;
/// One past end pointer for the current comment. For BCPL comments points
/// to newline or BufferEnd, for C comments points to star in '*/'.
const char *CommentEnd;
SourceLocation FileLoc;
/// If true, the commands, html tags, etc will be parsed and reported as
/// separate tokens inside the comment body. If false, the comment text will
/// be parsed into text and newline tokens.
bool ParseCommands;
enum LexerCommentState : uint8_t {
LCS_BeforeComment,
LCS_InsideBCPLComment,
LCS_InsideCComment,
LCS_BetweenComments
};
/// Low-level lexer state, track if we are inside or outside of comment.
LexerCommentState CommentState;
enum LexerState : uint8_t {
/// Lexing normal comment text
LS_Normal,
/// Finished lexing verbatim block beginning command, will lex first body
/// line.
LS_VerbatimBlockFirstLine,
/// Lexing verbatim block body line-by-line, skipping line-starting
/// decorations.
LS_VerbatimBlockBody,
/// Finished lexing verbatim line beginning command, will lex text (one
/// line).
LS_VerbatimLineText,
/// Finished lexing \verbatim <TAG \endverbatim part, lexing tag attributes.
LS_HTMLStartTag,
/// Finished lexing \verbatim </TAG \endverbatim part, lexing '>'.
LS_HTMLEndTag
};
/// Current lexing mode.
LexerState State;
/// If State is LS_VerbatimBlock, contains the name of verbatim end
/// command, including command marker.
SmallString<16> VerbatimBlockEndCommandName;
/// Given a character reference name (e.g., "lt"), return the character that
/// it stands for (e.g., "<").
StringRef resolveHTMLNamedCharacterReference(StringRef Name) const;
/// Given a Unicode codepoint as base-10 integer, return the character.
StringRef resolveHTMLDecimalCharacterReference(StringRef Name) const;
/// Given a Unicode codepoint as base-16 integer, return the character.
StringRef resolveHTMLHexCharacterReference(StringRef Name) const;
void formTokenWithChars(Token &Result, const char *TokEnd,
tok::TokenKind Kind);
void formTextToken(Token &Result, const char *TokEnd) {
StringRef Text(BufferPtr, TokEnd - BufferPtr);
formTokenWithChars(Result, TokEnd, tok::text);
Result.setText(Text);
}
SourceLocation getSourceLocation(const char *Loc) const {
assert(Loc >= BufferStart && Loc <= BufferEnd &&
"Location out of range for this buffer!");
const unsigned CharNo = Loc - BufferStart;
return FileLoc.getLocWithOffset(CharNo);
}
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
/// Eat string matching regexp \code \s*\* \endcode.
void skipLineStartingDecorations();
/// Skip over pure text.
const char *skipTextToken();
/// Lex comment text, including commands if ParseCommands is set to true.
void lexCommentText(Token &T);
void setupAndLexVerbatimBlock(Token &T, const char *TextBegin, char Marker,
const CommandInfo *Info);
void lexVerbatimBlockFirstLine(Token &T);
void lexVerbatimBlockBody(Token &T);
void setupAndLexVerbatimLine(Token &T, const char *TextBegin,
const CommandInfo *Info);
void lexVerbatimLineText(Token &T);
void lexHTMLCharacterReference(Token &T);
void setupAndLexHTMLStartTag(Token &T);
void lexHTMLStartTag(Token &T);
void setupAndLexHTMLEndTag(Token &T);
void lexHTMLEndTag(Token &T);
public:
Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags,
const CommandTraits &Traits, SourceLocation FileLoc,
const char *BufferStart, const char *BufferEnd,
bool ParseCommands = true);
void lex(Token &T);
StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr) const;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@ -0,0 +1,124 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* List of AST nodes of a particular kind *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: CommentNodes.td *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef ABSTRACT_COMMENT
# define ABSTRACT_COMMENT(Type) Type
#endif
#ifndef COMMENT_RANGE
# define COMMENT_RANGE(Base, First, Last)
#endif
#ifndef LAST_COMMENT_RANGE
# define LAST_COMMENT_RANGE(Base, First, Last) COMMENT_RANGE(Base, First, Last)
#endif
#ifndef VERBATIMBLOCKLINECOMMENT
# define VERBATIMBLOCKLINECOMMENT(Type, Base) COMMENT(Type, Base)
#endif
VERBATIMBLOCKLINECOMMENT(VerbatimBlockLineComment, Comment)
#undef VERBATIMBLOCKLINECOMMENT
#ifndef INLINECONTENTCOMMENT
# define INLINECONTENTCOMMENT(Type, Base) COMMENT(Type, Base)
#endif
ABSTRACT_COMMENT(INLINECONTENTCOMMENT(InlineContentComment, Comment))
#ifndef TEXTCOMMENT
# define TEXTCOMMENT(Type, Base) INLINECONTENTCOMMENT(Type, Base)
#endif
TEXTCOMMENT(TextComment, InlineContentComment)
#undef TEXTCOMMENT
#ifndef INLINECOMMANDCOMMENT
# define INLINECOMMANDCOMMENT(Type, Base) INLINECONTENTCOMMENT(Type, Base)
#endif
INLINECOMMANDCOMMENT(InlineCommandComment, InlineContentComment)
#undef INLINECOMMANDCOMMENT
#ifndef HTMLTAGCOMMENT
# define HTMLTAGCOMMENT(Type, Base) INLINECONTENTCOMMENT(Type, Base)
#endif
ABSTRACT_COMMENT(HTMLTAGCOMMENT(HTMLTagComment, InlineContentComment))
#ifndef HTMLSTARTTAGCOMMENT
# define HTMLSTARTTAGCOMMENT(Type, Base) HTMLTAGCOMMENT(Type, Base)
#endif
HTMLSTARTTAGCOMMENT(HTMLStartTagComment, HTMLTagComment)
#undef HTMLSTARTTAGCOMMENT
#ifndef HTMLENDTAGCOMMENT
# define HTMLENDTAGCOMMENT(Type, Base) HTMLTAGCOMMENT(Type, Base)
#endif
HTMLENDTAGCOMMENT(HTMLEndTagComment, HTMLTagComment)
#undef HTMLENDTAGCOMMENT
COMMENT_RANGE(HTMLTagComment, HTMLStartTagComment, HTMLEndTagComment)
#undef HTMLTAGCOMMENT
COMMENT_RANGE(InlineContentComment, TextComment, HTMLEndTagComment)
#undef INLINECONTENTCOMMENT
#ifndef FULLCOMMENT
# define FULLCOMMENT(Type, Base) COMMENT(Type, Base)
#endif
FULLCOMMENT(FullComment, Comment)
#undef FULLCOMMENT
#ifndef BLOCKCONTENTCOMMENT
# define BLOCKCONTENTCOMMENT(Type, Base) COMMENT(Type, Base)
#endif
ABSTRACT_COMMENT(BLOCKCONTENTCOMMENT(BlockContentComment, Comment))
#ifndef PARAGRAPHCOMMENT
# define PARAGRAPHCOMMENT(Type, Base) BLOCKCONTENTCOMMENT(Type, Base)
#endif
PARAGRAPHCOMMENT(ParagraphComment, BlockContentComment)
#undef PARAGRAPHCOMMENT
#ifndef BLOCKCOMMANDCOMMENT
# define BLOCKCOMMANDCOMMENT(Type, Base) BLOCKCONTENTCOMMENT(Type, Base)
#endif
BLOCKCOMMANDCOMMENT(BlockCommandComment, BlockContentComment)
#ifndef VERBATIMLINECOMMENT
# define VERBATIMLINECOMMENT(Type, Base) BLOCKCOMMANDCOMMENT(Type, Base)
#endif
VERBATIMLINECOMMENT(VerbatimLineComment, BlockCommandComment)
#undef VERBATIMLINECOMMENT
#ifndef VERBATIMBLOCKCOMMENT
# define VERBATIMBLOCKCOMMENT(Type, Base) BLOCKCOMMANDCOMMENT(Type, Base)
#endif
VERBATIMBLOCKCOMMENT(VerbatimBlockComment, BlockCommandComment)
#undef VERBATIMBLOCKCOMMENT
#ifndef TPARAMCOMMANDCOMMENT
# define TPARAMCOMMANDCOMMENT(Type, Base) BLOCKCOMMANDCOMMENT(Type, Base)
#endif
TPARAMCOMMANDCOMMENT(TParamCommandComment, BlockCommandComment)
#undef TPARAMCOMMANDCOMMENT
#ifndef PARAMCOMMANDCOMMENT
# define PARAMCOMMANDCOMMENT(Type, Base) BLOCKCOMMANDCOMMENT(Type, Base)
#endif
PARAMCOMMANDCOMMENT(ParamCommandComment, BlockCommandComment)
#undef PARAMCOMMANDCOMMENT
COMMENT_RANGE(BlockCommandComment, BlockCommandComment, ParamCommandComment)
#undef BLOCKCOMMANDCOMMENT
COMMENT_RANGE(BlockContentComment, ParagraphComment, ParamCommandComment)
#undef BLOCKCONTENTCOMMENT
LAST_COMMENT_RANGE(Comment, VerbatimBlockLineComment, ParamCommandComment)
#undef COMMENT
#undef COMMENT_RANGE
#undef LAST_COMMENT_RANGE
#undef ABSTRACT_COMMENT

View File

@ -0,0 +1,128 @@
//===--- CommentParser.h - Doxygen comment parser ---------------*- 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 Doxygen comment parser.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTPARSER_H
#define LLVM_CLANG_AST_COMMENTPARSER_H
#include "clang/AST/Comment.h"
#include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentSema.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class SourceManager;
namespace comments {
class CommandTraits;
/// Doxygen comment parser.
class Parser {
Parser(const Parser &) = delete;
void operator=(const Parser &) = delete;
friend class TextTokenRetokenizer;
Lexer &L;
Sema &S;
/// Allocator for anything that goes into AST nodes.
llvm::BumpPtrAllocator &Allocator;
/// Source manager for the comment being parsed.
const SourceManager &SourceMgr;
DiagnosticsEngine &Diags;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
const CommandTraits &Traits;
/// Current lookahead token. We can safely assume that all tokens are from
/// a single source file.
Token Tok;
/// A stack of additional lookahead tokens.
SmallVector<Token, 8> MoreLATokens;
void consumeToken() {
if (MoreLATokens.empty())
L.lex(Tok);
else
Tok = MoreLATokens.pop_back_val();
}
void putBack(const Token &OldTok) {
MoreLATokens.push_back(Tok);
Tok = OldTok;
}
void putBack(ArrayRef<Token> Toks) {
if (Toks.empty())
return;
MoreLATokens.push_back(Tok);
MoreLATokens.append(Toks.rbegin(), std::prev(Toks.rend()));
Tok = Toks[0];
}
bool isTokBlockCommand() {
return (Tok.is(tok::backslash_command) || Tok.is(tok::at_command)) &&
Traits.getCommandInfo(Tok.getCommandID())->IsBlockCommand;
}
public:
Parser(Lexer &L, Sema &S, llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const CommandTraits &Traits);
/// Parse arguments for \\param command.
void parseParamCommandArgs(ParamCommandComment *PC,
TextTokenRetokenizer &Retokenizer);
/// Parse arguments for \\tparam command.
void parseTParamCommandArgs(TParamCommandComment *TPC,
TextTokenRetokenizer &Retokenizer);
ArrayRef<Comment::Argument>
parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
/// Parse arguments for \throws command supported args are in form of class
/// or template.
ArrayRef<Comment::Argument>
parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
ArrayRef<Comment::Argument>
parseParCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);
BlockCommandComment *parseBlockCommand();
InlineCommandComment *parseInlineCommand();
HTMLStartTagComment *parseHTMLStartTag();
HTMLEndTagComment *parseHTMLEndTag();
BlockContentComment *parseParagraphOrBlockCommand();
VerbatimBlockComment *parseVerbatimBlock();
VerbatimLineComment *parseVerbatimLine();
BlockContentComment *parseBlockContent();
FullComment *parseFullComment();
};
} // end namespace comments
} // end namespace clang
#endif

View File

@ -0,0 +1,255 @@
//===--- CommentSema.h - Doxygen comment semantic analysis ------*- 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 semantic analysis class for Doxygen comments.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMMENTSEMA_H
#define LLVM_CLANG_AST_COMMENTSEMA_H
#include "clang/AST/Comment.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class Decl;
class SourceMgr;
class Preprocessor;
namespace comments {
class CommandTraits;
class Sema {
Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;
/// Allocator for AST nodes.
llvm::BumpPtrAllocator &Allocator;
/// Source manager for the comment being parsed.
const SourceManager &SourceMgr;
DiagnosticsEngine &Diags;
CommandTraits &Traits;
const Preprocessor *PP;
/// Information about the declaration this comment is attached to.
DeclInfo *ThisDeclInfo;
/// Comment AST nodes that correspond to parameter names in
/// \c TemplateParameters.
///
/// Contains a valid value if \c DeclInfo->IsFilled is true.
llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
/// AST node for the \command and its aliases.
const BlockCommandComment *BriefCommand;
/// AST node for the \\headerfile command.
const BlockCommandComment *HeaderfileCommand;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
/// A stack of HTML tags that are currently open (not matched with closing
/// tags).
SmallVector<HTMLStartTagComment *, 8> HTMLOpenTags;
public:
Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags, CommandTraits &Traits,
const Preprocessor *PP);
void setDecl(const Decl *D);
/// Returns a copy of array, owned by Sema's allocator.
template<typename T>
ArrayRef<T> copyArray(ArrayRef<T> Source) {
if (!Source.empty())
return Source.copy(Allocator);
return {};
}
ParagraphComment *actOnParagraphComment(
ArrayRef<InlineContentComment *> Content);
BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnBlockCommandArgs(BlockCommandComment *Command,
ArrayRef<BlockCommandComment::Argument> Args);
void actOnBlockCommandFinish(BlockCommandComment *Command,
ParagraphComment *Paragraph);
ParamCommandComment *actOnParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnParamCommandDirectionArg(ParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnParamCommandParamNameArg(ParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnParamCommandFinish(ParamCommandComment *Command,
ParagraphComment *Paragraph);
TParamCommandComment *actOnTParamCommandStart(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker);
void actOnTParamCommandParamNameArg(TParamCommandComment *Command,
SourceLocation ArgLocBegin,
SourceLocation ArgLocEnd,
StringRef Arg);
void actOnTParamCommandFinish(TParamCommandComment *Command,
ParagraphComment *Paragraph);
InlineCommandComment *actOnInlineCommand(SourceLocation CommandLocBegin,
SourceLocation CommandLocEnd,
unsigned CommandID,
CommandMarkerKind CommandMarker,
ArrayRef<Comment::Argument> Args);
InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef CommandName);
InlineContentComment *actOnUnknownCommand(SourceLocation LocBegin,
SourceLocation LocEnd,
unsigned CommandID);
TextComment *actOnText(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef Text);
VerbatimBlockComment *actOnVerbatimBlockStart(SourceLocation Loc,
unsigned CommandID);
VerbatimBlockLineComment *actOnVerbatimBlockLine(SourceLocation Loc,
StringRef Text);
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block,
SourceLocation CloseNameLocBegin,
StringRef CloseName,
ArrayRef<VerbatimBlockLineComment *> Lines);
VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
unsigned CommandID,
SourceLocation TextBegin,
StringRef Text);
HTMLStartTagComment *actOnHTMLStartTagStart(SourceLocation LocBegin,
StringRef TagName);
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag,
ArrayRef<HTMLStartTagComment::Attribute> Attrs,
SourceLocation GreaterLoc,
bool IsSelfClosing);
HTMLEndTagComment *actOnHTMLEndTag(SourceLocation LocBegin,
SourceLocation LocEnd,
StringRef TagName);
FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks);
private:
void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
void checkReturnsCommand(const BlockCommandComment *Command);
/// Emit diagnostics about duplicate block commands that should be
/// used only once per comment, e.g., \and \\returns.
void checkBlockCommandDuplicate(const BlockCommandComment *Command);
void checkDeprecatedCommand(const BlockCommandComment *Comment);
void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment);
void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment);
void checkContainerDecl(const BlockCommandComment *Comment);
/// Resolve parameter names to parameter indexes in function declaration.
/// Emit diagnostics about unknown parameters.
void resolveParamCommandIndexes(const FullComment *FC);
/// \returns \c true if the declaration that this comment is attached to
/// is a pointer to function/method/block type or has such a type.
bool involvesFunctionType();
bool isFunctionDecl();
bool isAnyFunctionDecl();
/// \returns \c true if declaration that this comment is attached to declares
/// a function pointer.
bool isFunctionPointerVarDecl();
bool isFunctionOrMethodVariadic();
bool isObjCMethodDecl();
bool isObjCPropertyDecl();
bool isTemplateOrSpecialization();
bool isRecordLikeDecl();
bool isClassOrStructDecl();
/// \return \c true if the declaration that this comment is attached to
/// declares either struct, class or tag typedef.
bool isClassOrStructOrTagTypedefDecl();
bool isUnionDecl();
bool isObjCInterfaceDecl();
bool isObjCProtocolDecl();
bool isClassTemplateDecl();
bool isFunctionTemplateDecl();
ArrayRef<const ParmVarDecl *> getParamVars();
/// Extract all important semantic information from
/// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
void inspectThisDecl();
/// Returns index of a function parameter with a given name.
unsigned resolveParmVarReference(StringRef Name,
ArrayRef<const ParmVarDecl *> ParamVars);
/// Returns index of a function parameter with the name closest to a given
/// typo.
unsigned correctTypoInParmVarReference(StringRef Typo,
ArrayRef<const ParmVarDecl *> ParamVars);
bool resolveTParamReference(StringRef Name,
const TemplateParameterList *TemplateParameters,
SmallVectorImpl<unsigned> *Position);
StringRef correctTypoInTParamReference(
StringRef Typo,
const TemplateParameterList *TemplateParameters);
InlineCommandRenderKind getInlineCommandRenderKind(StringRef Name) const;
};
} // end namespace comments
} // end namespace clang
#endif

View File

@ -0,0 +1,70 @@
//===- CommentVisitor.h - Visitor for Comment subclasses --------*- 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_AST_COMMENTVISITOR_H
#define LLVM_CLANG_AST_COMMENTVISITOR_H
#include "clang/AST/Comment.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace comments {
template <template <typename> class Ptr, typename ImplClass,
typename RetTy = void, class... ParamTys>
class CommentVisitorBase {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass *>(this)->visit##NAME( \
static_cast<PTR(CLASS)>(C), std::forward<ParamTys>(P)...)
RetTy visit(PTR(Comment) C, ParamTys... P) {
if (!C)
return RetTy();
switch (C->getCommentKind()) {
default: llvm_unreachable("Unknown comment kind!");
#define ABSTRACT_COMMENT(COMMENT)
#define COMMENT(CLASS, PARENT) \
case CommentKind::CLASS: \
DISPATCH(CLASS, CLASS);
#include "clang/AST/CommentNodes.inc"
#undef ABSTRACT_COMMENT
#undef COMMENT
}
}
// If the derived class does not implement a certain Visit* method, fall back
// on Visit* method for the superclass.
#define ABSTRACT_COMMENT(COMMENT) COMMENT
#define COMMENT(CLASS, PARENT) \
RetTy visit##CLASS(PTR(CLASS) C, ParamTys... P) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/CommentNodes.inc"
#undef ABSTRACT_COMMENT
#undef COMMENT
RetTy visitComment(PTR(Comment) C, ParamTys... P) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
template <typename ImplClass, typename RetTy = void, class... ParamTys>
class CommentVisitor : public CommentVisitorBase<std::add_pointer, ImplClass,
RetTy, ParamTys...> {};
template <typename ImplClass, typename RetTy = void, class... ParamTys>
class ConstCommentVisitor
: public CommentVisitorBase<llvm::make_const_ptr, ImplClass, RetTy,
ParamTys...> {};
} // namespace comments
} // namespace clang
#endif // LLVM_CLANG_AST_COMMENTVISITOR_H

View File

@ -0,0 +1,229 @@
//===- ComparisonCategories.h - Three Way Comparison Data -------*- 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 Comparison Category enum and data types, which
// store the types and expressions needed to support operator<=>
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H
#define LLVM_CLANG_AST_COMPARISONCATEGORIES_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseMap.h"
#include <array>
#include <cassert>
#include <optional>
#include <vector>
namespace llvm {
class StringRef;
class APSInt;
}
namespace clang {
class ASTContext;
class VarDecl;
class CXXRecordDecl;
class Sema;
class QualType;
class NamespaceDecl;
/// An enumeration representing the different comparison categories
/// types.
///
/// C++20 [cmp.categories.pre] The types partial_ordering, weak_ordering, and
/// strong_ordering are collectively termed the comparison category types.
enum class ComparisonCategoryType : unsigned char {
PartialOrdering,
WeakOrdering,
StrongOrdering,
First = PartialOrdering,
Last = StrongOrdering
};
/// Determine the common comparison type, as defined in C++2a
/// [class.spaceship]p4.
inline ComparisonCategoryType commonComparisonType(ComparisonCategoryType A,
ComparisonCategoryType B) {
return A < B ? A : B;
}
/// Get the comparison category that should be used when comparing values of
/// type \c T.
std::optional<ComparisonCategoryType>
getComparisonCategoryForBuiltinCmp(QualType T);
/// An enumeration representing the possible results of a three-way
/// comparison. These values map onto instances of comparison category types
/// defined in the standard library. e.g. 'std::strong_ordering::less'.
enum class ComparisonCategoryResult : unsigned char {
Equal,
Equivalent,
Less,
Greater,
Unordered,
Last = Unordered
};
class ComparisonCategoryInfo {
friend class ComparisonCategories;
friend class Sema;
public:
ComparisonCategoryInfo(const ASTContext &Ctx, const CXXRecordDecl *RD,
ComparisonCategoryType Kind)
: Ctx(Ctx), Record(RD), Kind(Kind) {}
struct ValueInfo {
ComparisonCategoryResult Kind;
VarDecl *VD;
ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD)
: Kind(Kind), VD(VD) {}
/// True iff we've successfully evaluated the variable as a constant
/// expression and extracted its integer value.
bool hasValidIntValue() const;
/// Get the constant integer value used by this variable to represent
/// the comparison category result type.
llvm::APSInt getIntValue() const;
};
private:
const ASTContext &Ctx;
/// A map containing the comparison category result decls from the
/// standard library. The key is a value of ComparisonCategoryResult.
mutable llvm::SmallVector<
ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1>
Objects;
/// Lookup the ValueInfo struct for the specified ValueKind. If the
/// VarDecl for the value cannot be found, nullptr is returned.
///
/// If the ValueInfo does not have a valid integer value the variable
/// is evaluated as a constant expression to determine that value.
ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const;
public:
/// The declaration for the comparison category type from the
/// standard library.
const CXXRecordDecl *Record = nullptr;
/// The Kind of the comparison category type
ComparisonCategoryType Kind;
public:
QualType getType() const;
const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const {
ValueInfo *Info = lookupValueInfo(ValueKind);
assert(Info &&
"comparison category does not contain the specified result kind");
assert(Info->hasValidIntValue() &&
"couldn't determine the integer constant for this value");
return Info;
}
/// True iff the comparison is "strong". i.e. it checks equality and
/// not equivalence.
bool isStrong() const {
using CCK = ComparisonCategoryType;
return Kind == CCK::StrongOrdering;
}
/// True iff the comparison is not totally ordered.
bool isPartial() const {
using CCK = ComparisonCategoryType;
return Kind == CCK::PartialOrdering;
}
/// Converts the specified result kind into the correct result kind
/// for this category. Specifically it lowers strong equality results to
/// weak equivalence if needed.
ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const {
using CCR = ComparisonCategoryResult;
if (!isStrong() && Res == CCR::Equal)
return CCR::Equivalent;
return Res;
}
const ValueInfo *getEqualOrEquiv() const {
return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal));
}
const ValueInfo *getLess() const {
return getValueInfo(ComparisonCategoryResult::Less);
}
const ValueInfo *getGreater() const {
return getValueInfo(ComparisonCategoryResult::Greater);
}
const ValueInfo *getUnordered() const {
assert(isPartial());
return getValueInfo(ComparisonCategoryResult::Unordered);
}
};
class ComparisonCategories {
public:
static StringRef getCategoryString(ComparisonCategoryType Kind);
static StringRef getResultString(ComparisonCategoryResult Kind);
/// Return the list of results which are valid for the specified
/// comparison category type.
static std::vector<ComparisonCategoryResult>
getPossibleResultsForType(ComparisonCategoryType Type);
/// Return the comparison category information for the category
/// specified by 'Kind'.
const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const {
const ComparisonCategoryInfo *Result = lookupInfo(Kind);
assert(Result != nullptr &&
"information for specified comparison category has not been built");
return *Result;
}
/// Return the comparison category information as specified by
/// `getCategoryForType(Ty)`. If the information is not already cached,
/// the declaration is looked up and a cache entry is created.
/// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is
/// possible.
const ComparisonCategoryInfo &getInfoForType(QualType Ty) const;
public:
/// Return the cached comparison category information for the
/// specified 'Kind'. If no cache entry is present the comparison category
/// type is looked up. If lookup fails nullptr is returned. Otherwise, a
/// new cache entry is created and returned
const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const;
ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) {
const auto &This = *this;
return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind));
}
const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const;
private:
friend class ASTContext;
explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {}
const ASTContext &Ctx;
/// A map from the ComparisonCategoryType (represented as 'char') to the
/// cached information for the specified category.
mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data;
mutable NamespaceDecl *StdNS = nullptr;
};
} // namespace clang
#endif

View File

@ -0,0 +1,213 @@
//===--- ComputeDependence.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
//
//===----------------------------------------------------------------------===//
//
// Calculate various template dependency flags for the AST.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_COMPUTEDEPENDENCE_H
#define LLVM_CLANG_AST_COMPUTEDEPENDENCE_H
#include "clang/AST/DependenceFlags.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h"
namespace clang {
class ASTContext;
class Expr;
class FullExpr;
class OpaqueValueExpr;
class ParenExpr;
class UnaryOperator;
class UnaryExprOrTypeTraitExpr;
class ArraySubscriptExpr;
class MatrixSingleSubscriptExpr;
class MatrixSubscriptExpr;
class CompoundLiteralExpr;
class ImplicitCastExpr;
class ExplicitCastExpr;
class BinaryOperator;
class ConditionalOperator;
class BinaryConditionalOperator;
class StmtExpr;
class ConvertVectorExpr;
class VAArgExpr;
class ChooseExpr;
class NoInitExpr;
class ArrayInitLoopExpr;
class ImplicitValueInitExpr;
class InitListExpr;
class ExtVectorElementExpr;
class BlockExpr;
class AsTypeExpr;
class DeclRefExpr;
class RecoveryExpr;
class CXXRewrittenBinaryOperator;
class CXXStdInitializerListExpr;
class CXXTypeidExpr;
class MSPropertyRefExpr;
class MSPropertySubscriptExpr;
class CXXUuidofExpr;
class CXXThisExpr;
class CXXThrowExpr;
class CXXBindTemporaryExpr;
class CXXScalarValueInitExpr;
class CXXDeleteExpr;
class ArrayTypeTraitExpr;
class ExpressionTraitExpr;
class CXXNoexceptExpr;
class PackExpansionExpr;
class PackIndexingExpr;
class SubstNonTypeTemplateParmExpr;
class CoroutineSuspendExpr;
class DependentCoawaitExpr;
class CXXNewExpr;
class CXXPseudoDestructorExpr;
class OverloadExpr;
class DependentScopeDeclRefExpr;
class CXXConstructExpr;
class CXXTemporaryObjectExpr;
class CXXDefaultInitExpr;
class CXXDefaultArgExpr;
class LambdaExpr;
class CXXUnresolvedConstructExpr;
class CXXDependentScopeMemberExpr;
class MaterializeTemporaryExpr;
class CXXFoldExpr;
class CXXParenListInitExpr;
class TypeTraitExpr;
class ConceptSpecializationExpr;
class SYCLUniqueStableNameExpr;
class PredefinedExpr;
class CallExpr;
class OffsetOfExpr;
class MemberExpr;
class ShuffleVectorExpr;
class GenericSelectionExpr;
class DesignatedInitExpr;
class ParenListExpr;
class PseudoObjectExpr;
class AtomicExpr;
class ArraySectionExpr;
class OMPArrayShapingExpr;
class OMPIteratorExpr;
class ObjCArrayLiteral;
class ObjCDictionaryLiteral;
class ObjCBoxedExpr;
class ObjCEncodeExpr;
class ObjCIvarRefExpr;
class ObjCPropertyRefExpr;
class ObjCSubscriptRefExpr;
class ObjCIsaExpr;
class ObjCIndirectCopyRestoreExpr;
class ObjCMessageExpr;
class OpenACCAsteriskSizeExpr;
// The following functions are called from constructors of `Expr`, so they
// should not access anything beyond basic
ExprDependence computeDependence(FullExpr *E);
ExprDependence computeDependence(OpaqueValueExpr *E);
ExprDependence computeDependence(ParenExpr *E);
ExprDependence computeDependence(UnaryOperator *E, const ASTContext &Ctx);
ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E);
ExprDependence computeDependence(ArraySubscriptExpr *E);
ExprDependence computeDependence(MatrixSingleSubscriptExpr *E);
ExprDependence computeDependence(MatrixSubscriptExpr *E);
ExprDependence computeDependence(CompoundLiteralExpr *E);
ExprDependence computeDependence(ImplicitCastExpr *E);
ExprDependence computeDependence(ExplicitCastExpr *E);
ExprDependence computeDependence(BinaryOperator *E);
ExprDependence computeDependence(ConditionalOperator *E);
ExprDependence computeDependence(BinaryConditionalOperator *E);
ExprDependence computeDependence(StmtExpr *E, unsigned TemplateDepth);
ExprDependence computeDependence(ConvertVectorExpr *E);
ExprDependence computeDependence(VAArgExpr *E);
ExprDependence computeDependence(ChooseExpr *E);
ExprDependence computeDependence(NoInitExpr *E);
ExprDependence computeDependence(ArrayInitLoopExpr *E);
ExprDependence computeDependence(ImplicitValueInitExpr *E);
ExprDependence computeDependence(InitListExpr *E);
ExprDependence computeDependence(ExtVectorElementExpr *E);
ExprDependence computeDependence(BlockExpr *E,
bool ContainsUnexpandedParameterPack);
ExprDependence computeDependence(AsTypeExpr *E);
ExprDependence computeDependence(DeclRefExpr *E, const ASTContext &Ctx);
ExprDependence computeDependence(RecoveryExpr *E);
ExprDependence computeDependence(CXXRewrittenBinaryOperator *E);
ExprDependence computeDependence(CXXStdInitializerListExpr *E);
ExprDependence computeDependence(CXXTypeidExpr *E);
ExprDependence computeDependence(MSPropertyRefExpr *E);
ExprDependence computeDependence(MSPropertySubscriptExpr *E);
ExprDependence computeDependence(CXXUuidofExpr *E);
ExprDependence computeDependence(CXXThisExpr *E);
ExprDependence computeDependence(CXXThrowExpr *E);
ExprDependence computeDependence(CXXBindTemporaryExpr *E);
ExprDependence computeDependence(CXXScalarValueInitExpr *E);
ExprDependence computeDependence(CXXDeleteExpr *E);
ExprDependence computeDependence(ArrayTypeTraitExpr *E);
ExprDependence computeDependence(ExpressionTraitExpr *E);
ExprDependence computeDependence(CXXNoexceptExpr *E, CanThrowResult CT);
ExprDependence computeDependence(PackExpansionExpr *E);
ExprDependence computeDependence(PackIndexingExpr *E);
ExprDependence computeDependence(SubstNonTypeTemplateParmExpr *E);
ExprDependence computeDependence(CoroutineSuspendExpr *E);
ExprDependence computeDependence(DependentCoawaitExpr *E);
ExprDependence computeDependence(CXXNewExpr *E);
ExprDependence computeDependence(CXXPseudoDestructorExpr *E);
ExprDependence computeDependence(OverloadExpr *E, bool KnownDependent,
bool KnownInstantiationDependent,
bool KnownContainsUnexpandedParameterPack);
ExprDependence computeDependence(DependentScopeDeclRefExpr *E);
ExprDependence computeDependence(CXXConstructExpr *E);
ExprDependence computeDependence(CXXTemporaryObjectExpr *E);
ExprDependence computeDependence(CXXDefaultInitExpr *E);
ExprDependence computeDependence(CXXDefaultArgExpr *E);
ExprDependence computeDependence(LambdaExpr *E,
bool ContainsUnexpandedParameterPack);
ExprDependence computeDependence(CXXUnresolvedConstructExpr *E);
ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
ExprDependence computeDependence(CXXFoldExpr *E);
ExprDependence computeDependence(CXXParenListInitExpr *E);
ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);
ExprDependence computeDependence(SYCLUniqueStableNameExpr *E);
ExprDependence computeDependence(PredefinedExpr *E);
ExprDependence computeDependence(CallExpr *E, ArrayRef<Expr *> PreArgs);
ExprDependence computeDependence(OffsetOfExpr *E);
ExprDependence computeDependence(MemberExpr *E);
ExprDependence computeDependence(ShuffleVectorExpr *E);
ExprDependence computeDependence(GenericSelectionExpr *E,
bool ContainsUnexpandedPack);
ExprDependence computeDependence(DesignatedInitExpr *E);
ExprDependence computeDependence(ParenListExpr *E);
ExprDependence computeDependence(PseudoObjectExpr *E);
ExprDependence computeDependence(AtomicExpr *E);
ExprDependence computeDependence(ArraySectionExpr *E);
ExprDependence computeDependence(OMPArrayShapingExpr *E);
ExprDependence computeDependence(OMPIteratorExpr *E);
ExprDependence computeDependence(ObjCArrayLiteral *E);
ExprDependence computeDependence(ObjCDictionaryLiteral *E);
ExprDependence computeDependence(ObjCBoxedExpr *E);
ExprDependence computeDependence(ObjCEncodeExpr *E);
ExprDependence computeDependence(ObjCIvarRefExpr *E);
ExprDependence computeDependence(ObjCPropertyRefExpr *E);
ExprDependence computeDependence(ObjCSubscriptRefExpr *E);
ExprDependence computeDependence(ObjCIsaExpr *E);
ExprDependence computeDependence(ObjCIndirectCopyRestoreExpr *E);
ExprDependence computeDependence(ObjCMessageExpr *E);
ExprDependence computeDependence(OpenACCAsteriskSizeExpr *E);
} // namespace clang
#endif

View File

@ -0,0 +1,74 @@
//===--- CurrentSourceLocExprScope.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 types used to track the current context needed to evaluate
// a SourceLocExpr.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H
#define LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H
#include <cassert>
namespace clang {
class Expr;
/// Represents the current source location and context used to determine the
/// value of the source location builtins (ex. __builtin_LINE), including the
/// context of default argument and default initializer expressions.
class CurrentSourceLocExprScope {
/// The CXXDefaultArgExpr or CXXDefaultInitExpr we're currently evaluating.
const Expr *DefaultExpr = nullptr;
public:
/// A RAII style scope guard used for tracking the current source
/// location and context as used by the source location builtins
/// (ex. __builtin_LINE).
class SourceLocExprScopeGuard;
const Expr *getDefaultExpr() const { return DefaultExpr; }
explicit CurrentSourceLocExprScope() = default;
private:
explicit CurrentSourceLocExprScope(const Expr *DefaultExpr)
: DefaultExpr(DefaultExpr) {}
CurrentSourceLocExprScope(CurrentSourceLocExprScope const &) = default;
CurrentSourceLocExprScope &
operator=(CurrentSourceLocExprScope const &) = default;
};
class CurrentSourceLocExprScope::SourceLocExprScopeGuard {
public:
SourceLocExprScopeGuard(const Expr *DefaultExpr,
CurrentSourceLocExprScope &Current)
: Current(Current), OldVal(Current), Enable(false) {
assert(DefaultExpr && "the new scope should not be empty");
if ((Enable = (Current.getDefaultExpr() == nullptr)))
Current = CurrentSourceLocExprScope(DefaultExpr);
}
~SourceLocExprScopeGuard() {
if (Enable)
Current = OldVal;
}
private:
SourceLocExprScopeGuard(SourceLocExprScopeGuard const &) = delete;
SourceLocExprScopeGuard &operator=(SourceLocExprScopeGuard const &) = delete;
CurrentSourceLocExprScope &Current;
CurrentSourceLocExprScope OldVal;
bool Enable;
};
} // end namespace clang
#endif // LLVM_CLANG_AST_CURRENTSOURCELOCEXPRSCOPE_H

View File

@ -0,0 +1,63 @@
//===--- DatatCollection.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 file declares helper methods for collecting data from AST nodes.
///
/// To collect data from Stmt nodes, subclass ConstStmtVisitor and include
/// StmtDataCollectors.inc after defining the macros that you need. This
/// provides data collection implementations for most Stmt kinds. Note
/// that the code requires some conditions to be met:
///
/// - There must be a method addData(const T &Data) that accepts strings,
/// integral types as well as QualType. All data is forwarded using
/// to this method.
/// - The ASTContext of the Stmt must be accessible by the name Context.
///
/// It is also possible to override individual visit methods. Have a look at
/// the DataCollector in lib/Analysis/CloneDetection.cpp for a usage example.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DATACOLLECTION_H
#define LLVM_CLANG_AST_DATACOLLECTION_H
#include "clang/AST/ASTContext.h"
namespace clang {
namespace data_collection {
/// Returns a string that represents all macro expansions that expanded into the
/// given SourceLocation.
///
/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
/// A and B are expanded from the same macros in the same order.
std::string getMacroStack(SourceLocation Loc, ASTContext &Context);
/// Utility functions for implementing addData() for a consumer that has a
/// method update(StringRef)
template <class T>
void addDataToConsumer(T &DataConsumer, llvm::StringRef Str) {
DataConsumer.update(Str);
}
template <class T> void addDataToConsumer(T &DataConsumer, const QualType &QT) {
addDataToConsumer(DataConsumer, QT.getAsString());
}
template <class T, class Type>
std::enable_if_t<std::is_integral<Type>::value || std::is_enum<Type>::value ||
std::is_convertible<Type, size_t>::value // for llvm::hash_code
>
addDataToConsumer(T &DataConsumer, Type Data) {
DataConsumer.update(StringRef(reinterpret_cast<char *>(&Data), sizeof(Data)));
}
} // end namespace data_collection
} // end namespace clang
#endif // LLVM_CLANG_AST_DATACOLLECTION_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
//===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 DeclAccessPair class, which provides an
// efficient representation of a pair of a NamedDecl* and an
// AccessSpecifier. Generally the access specifier gives the
// natural access of a declaration when named in a class, as
// defined in C++ [class.access.base]p1.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H
#define LLVM_CLANG_AST_DECLACCESSPAIR_H
#include "clang/Basic/Specifiers.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Endian.h"
namespace clang {
class NamedDecl;
/// A POD class for pairing a NamedDecl* with an access specifier.
/// Can be put into unions.
class DeclAccessPair {
/// Use the lower 2 bit to store AccessSpecifier. Use the higher
/// 61 bit to store the pointer to a NamedDecl or the DeclID to
/// a NamedDecl. If the 3rd bit is set, storing the DeclID, otherwise
/// storing the pointer.
llvm::support::detail::packed_endian_specific_integral<
uint64_t, llvm::endianness::native, alignof(void *)>
Ptr;
enum { ASMask = 0x3, Mask = 0x7 };
bool isDeclID() const { return (Ptr >> 2) & 0x1; }
public:
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
DeclAccessPair p;
p.set(D, AS);
return p;
}
static DeclAccessPair makeLazy(uint64_t ID, AccessSpecifier AS) {
DeclAccessPair p;
p.Ptr = (ID << 3) | (0x1 << 2) | uint64_t(AS);
return p;
}
uint64_t getDeclID() const {
assert(isDeclID());
return (~Mask & Ptr) >> 3;
}
NamedDecl *getDecl() const {
assert(!isDeclID());
return reinterpret_cast<NamedDecl*>(~Mask & Ptr);
}
AccessSpecifier getAccess() const { return AccessSpecifier(ASMask & Ptr); }
void setDecl(NamedDecl *D) {
set(D, getAccess());
}
void setAccess(AccessSpecifier AS) {
set(getDecl(), AS);
}
void set(NamedDecl *D, AccessSpecifier AS) {
Ptr = uint64_t(AS) | reinterpret_cast<uint64_t>(D);
}
operator NamedDecl*() const { return getDecl(); }
NamedDecl *operator->() const { return getDecl(); }
};
// Make sure DeclAccessPair is pointer-aligned types.
static_assert(alignof(DeclAccessPair) == alignof(void *));
// Make sure DeclAccessPair is still POD.
static_assert(std::is_standard_layout_v<DeclAccessPair> &&
std::is_trivial_v<DeclAccessPair>);
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,323 @@
//===- DeclContextInternals.h - DeclContext Representation ------*- 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 data structures used in the implementation
// of DeclContext.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclarationName.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include <cassert>
namespace clang {
class DependentDiagnostic;
/// An array of decls optimized for the common case of only containing
/// one entry.
class StoredDeclsList {
using Decls = DeclListNode::Decls;
/// A collection of declarations, with a flag to indicate if we have
/// further external declarations.
using DeclsAndHasExternalTy = llvm::PointerIntPair<Decls, 1, bool>;
/// The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a list with a flag to indicate if there are further
/// external declarations.
DeclsAndHasExternalTy Data;
template <typename Fn> DeclListNode::Decls *erase_if(Fn ShouldErase) {
Decls List = Data.getPointer();
if (!List)
return nullptr;
ASTContext &C = getASTContext();
DeclListNode::Decls NewHead = nullptr;
DeclListNode::Decls *NewLast = nullptr;
DeclListNode::Decls *NewTail = &NewHead;
while (true) {
if (!ShouldErase(*DeclListNode::iterator(List))) {
NewLast = NewTail;
*NewTail = List;
if (auto *Node = List.dyn_cast<DeclListNode*>()) {
NewTail = &Node->Rest;
List = Node->Rest;
} else {
break;
}
} else if (DeclListNode *N = List.dyn_cast<DeclListNode*>()) {
List = N->Rest;
C.DeallocateDeclListNode(N);
} else {
// We're discarding the last declaration in the list. The last node we
// want to keep (if any) will be of the form DeclListNode(D, <rest>);
// replace it with just D.
if (NewLast) {
DeclListNode *Node = cast<DeclListNode *>(*NewLast);
*NewLast = Node->D;
C.DeallocateDeclListNode(Node);
}
break;
}
}
Data.setPointer(NewHead);
assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
if (!Data.getPointer())
// All declarations are erased.
return nullptr;
else if (isa<NamedDecl *>(NewHead))
// The list only contains a declaration, the header itself.
return (DeclListNode::Decls *)&Data;
else {
assert(NewLast && isa<NamedDecl *>(*NewLast) && "Not the tail?");
return NewLast;
}
}
void erase(NamedDecl *ND) {
erase_if([ND](NamedDecl *D) { return D == ND; });
}
public:
StoredDeclsList() = default;
StoredDeclsList(StoredDeclsList &&RHS) : Data(RHS.Data) {
RHS.Data.setPointer(nullptr);
RHS.Data.setInt(false);
}
void MaybeDeallocList() {
if (isNull())
return;
// If this is a list-form, free the list.
ASTContext &C = getASTContext();
Decls List = Data.getPointer();
while (DeclListNode *ToDealloc = List.dyn_cast<DeclListNode *>()) {
List = ToDealloc->Rest;
C.DeallocateDeclListNode(ToDealloc);
}
}
~StoredDeclsList() {
MaybeDeallocList();
}
StoredDeclsList &operator=(StoredDeclsList &&RHS) {
MaybeDeallocList();
Data = RHS.Data;
RHS.Data.setPointer(nullptr);
RHS.Data.setInt(false);
return *this;
}
bool isNull() const { return Data.getPointer().isNull(); }
ASTContext &getASTContext() {
assert(!isNull() && "No ASTContext.");
if (NamedDecl *ND = getAsDecl())
return ND->getASTContext();
return getAsList()->D->getASTContext();
}
DeclsAndHasExternalTy getAsListAndHasExternal() const { return Data; }
NamedDecl *getAsDecl() const {
return getAsListAndHasExternal().getPointer().dyn_cast<NamedDecl *>();
}
DeclListNode *getAsList() const {
return getAsListAndHasExternal().getPointer().dyn_cast<DeclListNode*>();
}
bool hasExternalDecls() const {
return getAsListAndHasExternal().getInt();
}
void setHasExternalDecls() {
Data.setInt(true);
}
void remove(NamedDecl *D) {
assert(!isNull() && "removing from empty list");
erase(D);
}
/// Remove any declarations which were imported from an external AST source.
void removeExternalDecls() {
erase_if([](NamedDecl *ND) { return ND->isFromASTFile(); });
// Don't have any pending external decls any more.
Data.setInt(false);
}
void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
// Remove all declarations that are either external or are replaced with
// external declarations with higher visibilities.
DeclListNode::Decls *Tail = erase_if([Decls](NamedDecl *ND) {
if (ND->isFromASTFile())
return true;
// FIXME: Can we get rid of this loop completely?
return llvm::any_of(Decls, [ND](NamedDecl *D) {
// Only replace the local declaration if the external declaration has
// higher visiblities.
return D->getModuleOwnershipKind() <= ND->getModuleOwnershipKind() &&
D->declarationReplaces(ND, /*IsKnownNewer=*/false);
});
});
// Don't have any pending external decls any more.
Data.setInt(false);
if (Decls.empty())
return;
// Convert Decls into a list, in order.
ASTContext &C = Decls.front()->getASTContext();
DeclListNode::Decls DeclsAsList = Decls.back();
for (size_t I = Decls.size() - 1; I != 0; --I) {
DeclListNode *Node = C.AllocateDeclListNode(Decls[I - 1]);
Node->Rest = DeclsAsList;
DeclsAsList = Node;
}
if (!Data.getPointer()) {
Data.setPointer(DeclsAsList);
return;
}
// Append the Decls.
DeclListNode *Node = C.AllocateDeclListNode(cast<NamedDecl *>(*Tail));
Node->Rest = DeclsAsList;
*Tail = Node;
}
/// Return the list of all the decls.
DeclContext::lookup_result getLookupResult() const {
return DeclContext::lookup_result(Data.getPointer());
}
/// If this is a redeclaration of an existing decl, replace the old one with
/// D. Otherwise, append D.
void addOrReplaceDecl(NamedDecl *D) {
const bool IsKnownNewer = true;
if (isNull()) {
Data.setPointer(D);
return;
}
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (D->declarationReplaces(OldD, IsKnownNewer)) {
Data.setPointer(D);
return;
}
// Add D after OldD.
ASTContext &C = D->getASTContext();
DeclListNode *Node = C.AllocateDeclListNode(OldD);
Node->Rest = D;
Data.setPointer(Node);
return;
}
// FIXME: Move the assert before the single decl case when we fix the
// duplication coming from the ASTReader reading builtin types.
assert(!llvm::is_contained(getLookupResult(), D) && "Already exists!");
// Determine if this declaration is actually a redeclaration.
for (DeclListNode *N = getAsList(); /*return in loop*/;
N = N->Rest.dyn_cast<DeclListNode *>()) {
if (D->declarationReplaces(N->D, IsKnownNewer)) {
N->D = D;
return;
}
if (auto *ND = N->Rest.dyn_cast<NamedDecl *>()) {
if (D->declarationReplaces(ND, IsKnownNewer)) {
N->Rest = D;
return;
}
// Add D after ND.
ASTContext &C = D->getASTContext();
DeclListNode *Node = C.AllocateDeclListNode(ND);
N->Rest = Node;
Node->Rest = D;
return;
}
}
}
/// Add a declaration to the list without checking if it replaces anything.
void prependDeclNoReplace(NamedDecl *D) {
if (isNull()) {
Data.setPointer(D);
return;
}
ASTContext &C = D->getASTContext();
DeclListNode *Node = C.AllocateDeclListNode(D);
Node->Rest = Data.getPointer();
Data.setPointer(Node);
}
LLVM_DUMP_METHOD void dump() const {
Decls D = Data.getPointer();
if (!D) {
llvm::errs() << "<null>\n";
return;
}
while (true) {
if (auto *Node = D.dyn_cast<DeclListNode*>()) {
llvm::errs() << '[' << Node->D << "] -> ";
D = Node->Rest;
} else {
llvm::errs() << '[' << cast<NamedDecl *>(D) << "]\n";
return;
}
}
}
};
class StoredDeclsMap
: public llvm::SmallDenseMap<DeclarationName, StoredDeclsList, 4> {
friend class ASTContext; // walks the chain deleting these
friend class DeclContext;
llvm::PointerIntPair<StoredDeclsMap*, 1> Previous;
public:
static void DestroyAll(StoredDeclsMap *Map, bool Dependent);
};
class DependentStoredDeclsMap : public StoredDeclsMap {
friend class DeclContext; // iterates over diagnostics
friend class DependentDiagnostic;
DependentDiagnostic *FirstDiagnostic = nullptr;
public:
DependentStoredDeclsMap() = default;
};
} // namespace clang
#endif // LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H

View File

@ -0,0 +1,270 @@
//===- DeclFriend.h - Classes for C++ friend declarations -------*- 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 section of the AST representing C++ friend
// declarations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLFRIEND_H
#define LLVM_CLANG_AST_DECLFRIEND_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <iterator>
namespace clang {
class ASTContext;
/// FriendDecl - Represents the declaration of a friend entity,
/// which can be a function, a type, or a templated function or type.
/// For example:
///
/// @code
/// template <typename T> class A {
/// friend int foo(T);
/// friend class B;
/// friend T; // only in C++0x
/// template <typename U> friend class C;
/// template <typename U> friend A& operator+=(A&, const U&) { ... }
/// };
/// @endcode
///
/// The semantic context of a friend decl is its declaring class.
class FriendDecl final
: public Decl,
private llvm::TrailingObjects<FriendDecl, TemplateParameterList *> {
LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
public:
using FriendUnion = llvm::PointerUnion<NamedDecl *, TypeSourceInfo *>;
private:
friend class CXXRecordDecl;
friend class CXXRecordDecl::friend_iterator;
// The declaration that's a friend of this class.
FriendUnion Friend;
// A pointer to the next friend in the sequence.
LazyDeclPtr NextFriend;
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
// Location of the '...', if present.
SourceLocation EllipsisLoc;
/// True if this 'friend' declaration is unsupported. Eventually we
/// will support every possible friend declaration, but for now we
/// silently ignore some and set this flag to authorize all access.
LLVM_PREFERRED_TYPE(bool)
unsigned UnsupportedFriend : 1;
// The number of "outer" template parameter lists in non-templatic
// (currently unsupported) friend type declarations, such as
// template <class T> friend class A<T>::B;
unsigned NumTPLists : 31;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL, SourceLocation EllipsisLoc,
ArrayRef<TemplateParameterList *> FriendTypeTPLists)
: Decl(Decl::Friend, DC, L), Friend(Friend), FriendLoc(FriendL),
EllipsisLoc(EllipsisLoc), UnsupportedFriend(false),
NumTPLists(FriendTypeTPLists.size()) {
llvm::copy(FriendTypeTPLists, getTrailingObjects());
}
FriendDecl(EmptyShell Empty, unsigned NumFriendTypeTPLists)
: Decl(Decl::Friend, Empty), UnsupportedFriend(false),
NumTPLists(NumFriendTypeTPLists) {}
FriendDecl *getNextFriend() {
if (!NextFriend.isOffset())
return cast_or_null<FriendDecl>(NextFriend.get(nullptr));
return getNextFriendSlowCase();
}
FriendDecl *getNextFriendSlowCase();
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend class ASTNodeImporter;
friend TrailingObjects;
static FriendDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL, SourceLocation EllipsisLoc = {},
ArrayRef<TemplateParameterList *> FriendTypeTPLists = {});
static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned FriendTypeNumTPLists);
/// If this friend declaration names an (untemplated but possibly
/// dependent) type, return the type; otherwise return null. This
/// is used for elaborated-type-specifiers and, in C++0x, for
/// arbitrary friend type declarations.
TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>();
}
unsigned getFriendTypeNumTemplateParameterLists() const {
return NumTPLists;
}
TemplateParameterList *getFriendTypeTemplateParameterList(unsigned N) const {
return getTrailingObjects(NumTPLists)[N];
}
/// If this friend declaration doesn't name a type, return the inner
/// declaration.
NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl *>();
}
/// Retrieves the location of the 'friend' keyword.
SourceLocation getFriendLoc() const {
return FriendLoc;
}
/// Retrieves the location of the '...', if present.
SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
/// Retrieves the source range for the friend declaration.
SourceRange getSourceRange() const override LLVM_READONLY {
if (TypeSourceInfo *TInfo = getFriendType()) {
SourceLocation StartL = (NumTPLists == 0)
? getFriendLoc()
: getTrailingObjects()[0]->getTemplateLoc();
SourceLocation EndL = isPackExpansion() ? getEllipsisLoc()
: TInfo->getTypeLoc().getEndLoc();
return SourceRange(StartL, EndL);
}
if (isPackExpansion())
return SourceRange(getFriendLoc(), getEllipsisLoc());
if (NamedDecl *ND = getFriendDecl()) {
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
return FD->getSourceRange();
if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
return FTD->getSourceRange();
if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
return CTD->getSourceRange();
if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) {
if (DD->getOuterLocStart() != DD->getInnerLocStart())
return DD->getSourceRange();
}
return SourceRange(getFriendLoc(), ND->getEndLoc());
}
return SourceRange(getFriendLoc(), getLocation());
}
/// Determines if this friend kind is unsupported.
bool isUnsupportedFriend() const {
return UnsupportedFriend;
}
void setUnsupportedFriend(bool Unsupported) {
UnsupportedFriend = Unsupported;
}
bool isPackExpansion() const { return EllipsisLoc.isValid(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::Friend; }
};
/// An iterator over the friend declarations of a class.
class CXXRecordDecl::friend_iterator {
friend class CXXRecordDecl;
FriendDecl *Ptr;
explicit friend_iterator(FriendDecl *Ptr) : Ptr(Ptr) {}
public:
friend_iterator() = default;
using value_type = FriendDecl *;
using reference = FriendDecl *;
using pointer = FriendDecl *;
using difference_type = int;
using iterator_category = std::forward_iterator_tag;
reference operator*() const { return Ptr; }
friend_iterator &operator++() {
assert(Ptr && "attempt to increment past end of friend list");
Ptr = Ptr->getNextFriend();
return *this;
}
friend_iterator operator++(int) {
friend_iterator tmp = *this;
++*this;
return tmp;
}
bool operator==(const friend_iterator &Other) const {
return Ptr == Other.Ptr;
}
bool operator!=(const friend_iterator &Other) const {
return Ptr != Other.Ptr;
}
friend_iterator &operator+=(difference_type N) {
assert(N >= 0 && "cannot rewind a CXXRecordDecl::friend_iterator");
while (N--)
++*this;
return *this;
}
friend_iterator operator+(difference_type N) const {
friend_iterator tmp = *this;
tmp += N;
return tmp;
}
};
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const {
return friend_iterator(getFirstFriend());
}
inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const {
return friend_iterator(nullptr);
}
inline CXXRecordDecl::friend_range CXXRecordDecl::friends() const {
return friend_range(friend_begin(), friend_end());
}
inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) {
assert(!FD->NextFriend && "friend already has next friend?");
FD->NextFriend = data().FirstFriend;
data().FirstFriend = FD;
}
} // namespace clang
#endif // LLVM_CLANG_AST_DECLFRIEND_H

View File

@ -0,0 +1,151 @@
//===- DeclGroup.h - Classes for representing groups of Decls ---*- 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 DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstdint>
namespace clang {
class ASTContext;
class Decl;
class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
// FIXME: Include a TypeSpecifier object.
unsigned NumDecls = 0;
private:
DeclGroup() = default;
DeclGroup(unsigned numdecls, Decl** decls);
public:
friend TrailingObjects;
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
unsigned size() const { return NumDecls; }
Decl *&operator[](unsigned i) { return getTrailingObjects(NumDecls)[i]; }
Decl* const& operator[](unsigned i) const {
return getTrailingObjects(NumDecls)[i];
}
};
class DeclGroupRef {
// Note this is not a PointerIntPair because we need the address of the
// non-group case to be valid as a Decl** for iteration.
enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
Decl* D = nullptr;
Kind getKind() const {
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
}
public:
DeclGroupRef() = default;
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
if (NumDecls == 0)
return DeclGroupRef();
if (NumDecls == 1)
return DeclGroupRef(Decls[0]);
return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
}
using iterator = Decl **;
using const_iterator = Decl * const *;
bool isNull() const { return D == nullptr; }
bool isSingleDecl() const { return getKind() == SingleDeclKind; }
bool isDeclGroup() const { return getKind() == DeclGroupKind; }
Decl *getSingleDecl() {
assert(isSingleDecl() && "Isn't a single decl");
return D;
}
const Decl *getSingleDecl() const {
return const_cast<DeclGroupRef*>(this)->getSingleDecl();
}
DeclGroup &getDeclGroup() {
assert(isDeclGroup() && "Isn't a declgroup");
return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
}
const DeclGroup &getDeclGroup() const {
return const_cast<DeclGroupRef*>(this)->getDeclGroup();
}
iterator begin() {
if (isSingleDecl())
return D ? &D : nullptr;
return &getDeclGroup()[0];
}
iterator end() {
if (isSingleDecl())
return D ? &D+1 : nullptr;
DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
const_iterator begin() const {
if (isSingleDecl())
return D ? &D : nullptr;
return &getDeclGroup()[0];
}
const_iterator end() const {
if (isSingleDecl())
return D ? &D+1 : nullptr;
const DeclGroup &G = getDeclGroup();
return &G[0] + G.size();
}
void *getAsOpaquePtr() const { return D; }
static DeclGroupRef getFromOpaquePtr(void *Ptr) {
DeclGroupRef X;
X.D = static_cast<Decl*>(Ptr);
return X;
}
};
} // namespace clang
namespace llvm {
// DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
template <typename T>
struct PointerLikeTypeTraits;
template <>
struct PointerLikeTypeTraits<clang::DeclGroupRef> {
static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
return P.getAsOpaquePtr();
}
static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
return clang::DeclGroupRef::getFromOpaquePtr(P);
}
static constexpr int NumLowBitsAvailable = 0;
};
} // namespace llvm
#endif // LLVM_CLANG_AST_DECLGROUP_H

View File

@ -0,0 +1,291 @@
//===--- DeclID.h - ID number for deserialized declarations ----*- 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 DeclID class family to describe the deserialized
// declarations. The DeclID is widely used in AST via LazyDeclPtr, or calls to
// `ExternalASTSource::getExternalDecl`. It will be helpful for type safety to
// require the use of `DeclID` to explicit.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLID_H
#define LLVM_CLANG_AST_DECLID_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/iterator.h"
namespace clang {
/// Predefined declaration IDs.
///
/// These declaration IDs correspond to predefined declarations in the AST
/// context, such as the NULL declaration ID. Such declarations are never
/// actually serialized, since they will be built by the AST context when
/// it is created.
enum PredefinedDeclIDs {
/// The NULL declaration.
PREDEF_DECL_NULL_ID,
/// The translation unit.
PREDEF_DECL_TRANSLATION_UNIT_ID,
/// The Objective-C 'id' type.
PREDEF_DECL_OBJC_ID_ID,
/// The Objective-C 'SEL' type.
PREDEF_DECL_OBJC_SEL_ID,
/// The Objective-C 'Class' type.
PREDEF_DECL_OBJC_CLASS_ID,
/// The Objective-C 'Protocol' type.
PREDEF_DECL_OBJC_PROTOCOL_ID,
/// The signed 128-bit integer type.
PREDEF_DECL_INT_128_ID,
/// The unsigned 128-bit integer type.
PREDEF_DECL_UNSIGNED_INT_128_ID,
/// The internal 'instancetype' typedef.
PREDEF_DECL_OBJC_INSTANCETYPE_ID,
/// The internal '__builtin_va_list' typedef.
PREDEF_DECL_BUILTIN_VA_LIST_ID,
/// The internal '__va_list_tag' struct, if any.
PREDEF_DECL_VA_LIST_TAG,
/// The internal '__builtin_ms_va_list' typedef.
PREDEF_DECL_BUILTIN_MS_VA_LIST_ID,
/// The predeclared '_GUID' struct.
PREDEF_DECL_BUILTIN_MS_GUID_ID,
/// The extern "C" context.
PREDEF_DECL_EXTERN_C_CONTEXT_ID,
/// The internal '__NSConstantString' typedef.
PREDEF_DECL_CF_CONSTANT_STRING_ID,
/// The internal '__NSConstantString' tag type.
PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID,
/// The predeclared 'type_info' struct.
PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID,
#define BuiltinTemplate(BTName) PREDEF_DECL##BTName##_ID,
#include "clang/Basic/BuiltinTemplates.inc"
/// The number of declaration IDs that are predefined.
NUM_PREDEF_DECL_IDS
};
/// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means
/// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the
/// LocalDeclID to the ModuleFile been writting is equal to the GlobalDeclID.
/// Outside the serializer, all the DeclID been used should be GlobalDeclID.
/// We can translate a LocalDeclID to the GlobalDeclID by
/// `ASTReader::getGlobalDeclID()`.
class DeclIDBase {
public:
/// An ID number that refers to a declaration in an AST file.
///
/// The ID numbers of declarations are consecutive (in order of
/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
/// At the start of a chain of precompiled headers, declaration ID 1 is
/// used for the translation unit declaration.
///
/// DeclID should only be used directly in serialization. All other users
/// should use LocalDeclID or GlobalDeclID.
using DeclID = uint64_t;
protected:
DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
explicit DeclIDBase(DeclID ID) : ID(ID) {}
public:
DeclID getRawValue() const { return ID; }
explicit operator DeclID() const { return ID; }
explicit operator PredefinedDeclIDs() const { return (PredefinedDeclIDs)ID; }
bool isValid() const { return ID != PREDEF_DECL_NULL_ID; }
bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }
unsigned getModuleFileIndex() const { return ID >> 32; }
unsigned getLocalDeclIndex() const;
// The DeclID may be compared with predefined decl ID.
friend bool operator==(const DeclIDBase &LHS, const DeclID &RHS) {
return LHS.ID == RHS;
}
friend bool operator!=(const DeclIDBase &LHS, const DeclID &RHS) {
return !operator==(LHS, RHS);
}
friend bool operator<(const DeclIDBase &LHS, const DeclID &RHS) {
return LHS.ID < RHS;
}
friend bool operator<=(const DeclIDBase &LHS, const DeclID &RHS) {
return LHS.ID <= RHS;
}
friend bool operator>(const DeclIDBase &LHS, const DeclID &RHS) {
return LHS.ID > RHS;
}
friend bool operator>=(const DeclIDBase &LHS, const DeclID &RHS) {
return LHS.ID >= RHS;
}
friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID == RHS.ID;
}
friend bool operator!=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID != RHS.ID;
}
// We may sort the decl ID.
friend bool operator<(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID < RHS.ID;
}
friend bool operator>(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID > RHS.ID;
}
friend bool operator<=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID <= RHS.ID;
}
friend bool operator>=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID >= RHS.ID;
}
protected:
DeclID ID;
};
class ASTWriter;
class ASTReader;
namespace serialization {
class ModuleFile;
} // namespace serialization
class LocalDeclID : public DeclIDBase {
using Base = DeclIDBase;
LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
explicit LocalDeclID(DeclID ID) : Base(ID) {}
// Every Decl ID is a local decl ID to the module being writing in ASTWriter.
friend class ASTWriter;
friend class GlobalDeclID;
friend struct llvm::DenseMapInfo<clang::LocalDeclID>;
public:
LocalDeclID() : Base() {}
static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
DeclID ID);
static LocalDeclID get(ASTReader &Reader, serialization::ModuleFile &MF,
unsigned ModuleFileIndex, unsigned LocalDeclID);
LocalDeclID &operator++() {
++ID;
return *this;
}
LocalDeclID operator++(int) {
LocalDeclID Ret = *this;
++(*this);
return Ret;
}
};
class GlobalDeclID : public DeclIDBase {
using Base = DeclIDBase;
public:
GlobalDeclID() : Base() {}
explicit GlobalDeclID(DeclID ID) : Base(ID) {}
explicit GlobalDeclID(unsigned ModuleFileIndex, unsigned LocalID)
: Base((DeclID)ModuleFileIndex << 32 | (DeclID)LocalID) {}
// For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
// to a LocalDeclID.
explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
};
/// A helper iterator adaptor to convert the iterators to
/// `SmallVector<SomeDeclID>` to the iterators to `SmallVector<OtherDeclID>`.
template <class FromTy, class ToTy>
class DeclIDIterator
: public llvm::iterator_adaptor_base<DeclIDIterator<FromTy, ToTy>,
const FromTy *,
std::forward_iterator_tag, ToTy> {
public:
DeclIDIterator() : DeclIDIterator::iterator_adaptor_base(nullptr) {}
DeclIDIterator(const FromTy *ID)
: DeclIDIterator::iterator_adaptor_base(ID) {}
ToTy operator*() const { return ToTy(*this->I); }
bool operator==(const DeclIDIterator &RHS) const { return this->I == RHS.I; }
};
} // namespace clang
namespace llvm {
template <> struct DenseMapInfo<clang::GlobalDeclID> {
using GlobalDeclID = clang::GlobalDeclID;
using DeclID = GlobalDeclID::DeclID;
static GlobalDeclID getEmptyKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
}
static GlobalDeclID getTombstoneKey() {
return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
}
static unsigned getHashValue(const GlobalDeclID &Key) {
return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
}
static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
return L == R;
}
};
template <> struct DenseMapInfo<clang::LocalDeclID> {
using LocalDeclID = clang::LocalDeclID;
using DeclID = LocalDeclID::DeclID;
static LocalDeclID getEmptyKey() {
return LocalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
}
static LocalDeclID getTombstoneKey() {
return LocalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
}
static unsigned getHashValue(const LocalDeclID &Key) {
return DenseMapInfo<DeclID>::getHashValue(Key.getRawValue());
}
static bool isEqual(const LocalDeclID &L, const LocalDeclID &R) {
return L == R;
}
};
} // namespace llvm
#endif

View File

@ -0,0 +1,104 @@
//===- DeclLookups.h - Low-level interface to all names in a DC -*- 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 DeclContext::all_lookups_iterator.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLLOOKUPS_H
#define LLVM_CLANG_AST_DECLLOOKUPS_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include <cstddef>
#include <iterator>
namespace clang {
/// all_lookups_iterator - An iterator that provides a view over the results
/// of looking up every possible name.
class DeclContext::all_lookups_iterator {
StoredDeclsMap::iterator It, End;
public:
using value_type = lookup_result;
using reference = lookup_result;
using pointer = lookup_result;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
all_lookups_iterator() = default;
all_lookups_iterator(StoredDeclsMap::iterator It,
StoredDeclsMap::iterator End)
: It(It), End(End) {}
DeclarationName getLookupName() const { return It->first; }
reference operator*() const { return It->second.getLookupResult(); }
pointer operator->() const { return It->second.getLookupResult(); }
all_lookups_iterator& operator++() {
// Filter out using directives. They don't belong as results from name
// lookup anyways, except as an implementation detail. Users of the API
// should not expect to get them (or worse, rely on it).
do {
++It;
} while (It != End &&
It->first == DeclarationName::getUsingDirectiveName());
return *this;
}
all_lookups_iterator operator++(int) {
all_lookups_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(all_lookups_iterator x, all_lookups_iterator y) {
return x.It == y.It;
}
friend bool operator!=(all_lookups_iterator x, all_lookups_iterator y) {
return x.It != y.It;
}
};
inline DeclContext::lookups_range DeclContext::lookups() const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (Primary->hasExternalVisibleStorage())
getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary);
if (StoredDeclsMap *Map = Primary->buildLookup())
return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
all_lookups_iterator(Map->end(), Map->end()));
// Synthesize an empty range. This requires that two default constructed
// versions of these iterators form a valid empty range.
return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
inline DeclContext::lookups_range
DeclContext::noload_lookups(bool PreserveInternalState) const {
DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext();
if (!PreserveInternalState)
Primary->loadLazyLocalLexicalLookups();
if (StoredDeclsMap *Map = Primary->getLookupPtr())
return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
all_lookups_iterator(Map->end(), Map->end()));
// Synthesize an empty range. This requires that two default constructed
// versions of these iterators form a valid empty range.
return lookups_range(all_lookups_iterator(), all_lookups_iterator());
}
} // namespace clang
#endif // LLVM_CLANG_AST_DECLLOOKUPS_H

View File

@ -0,0 +1,729 @@
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* List of AST nodes of a particular kind *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: DeclNodes.td *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef ABSTRACT_DECL
# define ABSTRACT_DECL(Type) Type
#endif
#ifndef DECL_RANGE
# define DECL_RANGE(Base, First, Last)
#endif
#ifndef LAST_DECL_RANGE
# define LAST_DECL_RANGE(Base, First, Last) DECL_RANGE(Base, First, Last)
#endif
#ifndef TRANSLATIONUNIT
# define TRANSLATIONUNIT(Type, Base) DECL(Type, Base)
#endif
TRANSLATIONUNIT(TranslationUnit, Decl)
#undef TRANSLATIONUNIT
#ifndef TOPLEVELSTMT
# define TOPLEVELSTMT(Type, Base) DECL(Type, Base)
#endif
TOPLEVELSTMT(TopLevelStmt, Decl)
#undef TOPLEVELSTMT
#ifndef REQUIRESEXPRBODY
# define REQUIRESEXPRBODY(Type, Base) DECL(Type, Base)
#endif
REQUIRESEXPRBODY(RequiresExprBody, Decl)
#undef REQUIRESEXPRBODY
#ifndef OUTLINEDFUNCTION
# define OUTLINEDFUNCTION(Type, Base) DECL(Type, Base)
#endif
OUTLINEDFUNCTION(OutlinedFunction, Decl)
#undef OUTLINEDFUNCTION
#ifndef LINKAGESPEC
# define LINKAGESPEC(Type, Base) DECL(Type, Base)
#endif
LINKAGESPEC(LinkageSpec, Decl)
#undef LINKAGESPEC
#ifndef EXTERNCCONTEXT
# define EXTERNCCONTEXT(Type, Base) DECL(Type, Base)
#endif
EXTERNCCONTEXT(ExternCContext, Decl)
#undef EXTERNCCONTEXT
#ifndef EXPORT
# define EXPORT(Type, Base) DECL(Type, Base)
#endif
EXPORT(Export, Decl)
#undef EXPORT
#ifndef CAPTURED
# define CAPTURED(Type, Base) DECL(Type, Base)
#endif
CAPTURED(Captured, Decl)
#undef CAPTURED
#ifndef BLOCK
# define BLOCK(Type, Base) DECL(Type, Base)
#endif
BLOCK(Block, Decl)
#undef BLOCK
#ifndef STATICASSERT
# define STATICASSERT(Type, Base) DECL(Type, Base)
#endif
STATICASSERT(StaticAssert, Decl)
#undef STATICASSERT
#ifndef PRAGMADETECTMISMATCH
# define PRAGMADETECTMISMATCH(Type, Base) DECL(Type, Base)
#endif
PRAGMADETECTMISMATCH(PragmaDetectMismatch, Decl)
#undef PRAGMADETECTMISMATCH
#ifndef PRAGMACOMMENT
# define PRAGMACOMMENT(Type, Base) DECL(Type, Base)
#endif
PRAGMACOMMENT(PragmaComment, Decl)
#undef PRAGMACOMMENT
#ifndef OPENACCROUTINE
# define OPENACCROUTINE(Type, Base) DECL(Type, Base)
#endif
OPENACCROUTINE(OpenACCRoutine, Decl)
#undef OPENACCROUTINE
#ifndef OPENACCDECLARE
# define OPENACCDECLARE(Type, Base) DECL(Type, Base)
#endif
OPENACCDECLARE(OpenACCDeclare, Decl)
#undef OPENACCDECLARE
#ifndef OBJCPROPERTYIMPL
# define OBJCPROPERTYIMPL(Type, Base) DECL(Type, Base)
#endif
OBJCPROPERTYIMPL(ObjCPropertyImpl, Decl)
#undef OBJCPROPERTYIMPL
#ifndef OMPTHREADPRIVATE
# define OMPTHREADPRIVATE(Type, Base) DECL(Type, Base)
#endif
OMPTHREADPRIVATE(OMPThreadPrivate, Decl)
#undef OMPTHREADPRIVATE
#ifndef OMPREQUIRES
# define OMPREQUIRES(Type, Base) DECL(Type, Base)
#endif
OMPREQUIRES(OMPRequires, Decl)
#undef OMPREQUIRES
#ifndef OMPGROUPPRIVATE
# define OMPGROUPPRIVATE(Type, Base) DECL(Type, Base)
#endif
OMPGROUPPRIVATE(OMPGroupPrivate, Decl)
#undef OMPGROUPPRIVATE
#ifndef OMPALLOCATE
# define OMPALLOCATE(Type, Base) DECL(Type, Base)
#endif
OMPALLOCATE(OMPAllocate, Decl)
#undef OMPALLOCATE
#ifndef NAMED
# define NAMED(Type, Base) DECL(Type, Base)
#endif
ABSTRACT_DECL(NAMED(Named, Decl))
#ifndef OBJCMETHOD
# define OBJCMETHOD(Type, Base) NAMED(Type, Base)
#endif
OBJCMETHOD(ObjCMethod, NamedDecl)
#undef OBJCMETHOD
#ifndef OBJCCONTAINER
# define OBJCCONTAINER(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(OBJCCONTAINER(ObjCContainer, NamedDecl))
#ifndef OBJCPROTOCOL
# define OBJCPROTOCOL(Type, Base) OBJCCONTAINER(Type, Base)
#endif
OBJCPROTOCOL(ObjCProtocol, ObjCContainerDecl)
#undef OBJCPROTOCOL
#ifndef OBJCINTERFACE
# define OBJCINTERFACE(Type, Base) OBJCCONTAINER(Type, Base)
#endif
OBJCINTERFACE(ObjCInterface, ObjCContainerDecl)
#undef OBJCINTERFACE
#ifndef OBJCIMPL
# define OBJCIMPL(Type, Base) OBJCCONTAINER(Type, Base)
#endif
ABSTRACT_DECL(OBJCIMPL(ObjCImpl, ObjCContainerDecl))
#ifndef OBJCIMPLEMENTATION
# define OBJCIMPLEMENTATION(Type, Base) OBJCIMPL(Type, Base)
#endif
OBJCIMPLEMENTATION(ObjCImplementation, ObjCImplDecl)
#undef OBJCIMPLEMENTATION
#ifndef OBJCCATEGORYIMPL
# define OBJCCATEGORYIMPL(Type, Base) OBJCIMPL(Type, Base)
#endif
OBJCCATEGORYIMPL(ObjCCategoryImpl, ObjCImplDecl)
#undef OBJCCATEGORYIMPL
DECL_RANGE(ObjCImpl, ObjCImplementation, ObjCCategoryImpl)
#undef OBJCIMPL
#ifndef OBJCCATEGORY
# define OBJCCATEGORY(Type, Base) OBJCCONTAINER(Type, Base)
#endif
OBJCCATEGORY(ObjCCategory, ObjCContainerDecl)
#undef OBJCCATEGORY
DECL_RANGE(ObjCContainer, ObjCProtocol, ObjCCategory)
#undef OBJCCONTAINER
#ifndef HLSLBUFFER
# define HLSLBUFFER(Type, Base) NAMED(Type, Base)
#endif
HLSLBUFFER(HLSLBuffer, NamedDecl)
#undef HLSLBUFFER
#ifndef VALUE
# define VALUE(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(VALUE(Value, NamedDecl))
#ifndef OMPDECLAREREDUCTION
# define OMPDECLAREREDUCTION(Type, Base) VALUE(Type, Base)
#endif
OMPDECLAREREDUCTION(OMPDeclareReduction, ValueDecl)
#undef OMPDECLAREREDUCTION
#ifndef OMPDECLAREMAPPER
# define OMPDECLAREMAPPER(Type, Base) VALUE(Type, Base)
#endif
OMPDECLAREMAPPER(OMPDeclareMapper, ValueDecl)
#undef OMPDECLAREMAPPER
#ifndef UNRESOLVEDUSINGVALUE
# define UNRESOLVEDUSINGVALUE(Type, Base) VALUE(Type, Base)
#endif
UNRESOLVEDUSINGVALUE(UnresolvedUsingValue, ValueDecl)
#undef UNRESOLVEDUSINGVALUE
#ifndef UNNAMEDGLOBALCONSTANT
# define UNNAMEDGLOBALCONSTANT(Type, Base) VALUE(Type, Base)
#endif
UNNAMEDGLOBALCONSTANT(UnnamedGlobalConstant, ValueDecl)
#undef UNNAMEDGLOBALCONSTANT
#ifndef TEMPLATEPARAMOBJECT
# define TEMPLATEPARAMOBJECT(Type, Base) VALUE(Type, Base)
#endif
TEMPLATEPARAMOBJECT(TemplateParamObject, ValueDecl)
#undef TEMPLATEPARAMOBJECT
#ifndef MSGUID
# define MSGUID(Type, Base) VALUE(Type, Base)
#endif
MSGUID(MSGuid, ValueDecl)
#undef MSGUID
#ifndef INDIRECTFIELD
# define INDIRECTFIELD(Type, Base) VALUE(Type, Base)
#endif
INDIRECTFIELD(IndirectField, ValueDecl)
#undef INDIRECTFIELD
#ifndef ENUMCONSTANT
# define ENUMCONSTANT(Type, Base) VALUE(Type, Base)
#endif
ENUMCONSTANT(EnumConstant, ValueDecl)
#undef ENUMCONSTANT
#ifndef DECLARATOR
# define DECLARATOR(Type, Base) VALUE(Type, Base)
#endif
ABSTRACT_DECL(DECLARATOR(Declarator, ValueDecl))
#ifndef FUNCTION
# define FUNCTION(Type, Base) DECLARATOR(Type, Base)
#endif
FUNCTION(Function, DeclaratorDecl)
#ifndef CXXMETHOD
# define CXXMETHOD(Type, Base) FUNCTION(Type, Base)
#endif
CXXMETHOD(CXXMethod, FunctionDecl)
#ifndef CXXDESTRUCTOR
# define CXXDESTRUCTOR(Type, Base) CXXMETHOD(Type, Base)
#endif
CXXDESTRUCTOR(CXXDestructor, CXXMethodDecl)
#undef CXXDESTRUCTOR
#ifndef CXXCONVERSION
# define CXXCONVERSION(Type, Base) CXXMETHOD(Type, Base)
#endif
CXXCONVERSION(CXXConversion, CXXMethodDecl)
#undef CXXCONVERSION
#ifndef CXXCONSTRUCTOR
# define CXXCONSTRUCTOR(Type, Base) CXXMETHOD(Type, Base)
#endif
CXXCONSTRUCTOR(CXXConstructor, CXXMethodDecl)
#undef CXXCONSTRUCTOR
DECL_RANGE(CXXMethod, CXXMethod, CXXConstructor)
#undef CXXMETHOD
#ifndef CXXDEDUCTIONGUIDE
# define CXXDEDUCTIONGUIDE(Type, Base) FUNCTION(Type, Base)
#endif
CXXDEDUCTIONGUIDE(CXXDeductionGuide, FunctionDecl)
#undef CXXDEDUCTIONGUIDE
DECL_RANGE(Function, Function, CXXDeductionGuide)
#undef FUNCTION
#ifndef VAR
# define VAR(Type, Base) DECLARATOR(Type, Base)
#endif
VAR(Var, DeclaratorDecl)
#ifndef VARTEMPLATESPECIALIZATION
# define VARTEMPLATESPECIALIZATION(Type, Base) VAR(Type, Base)
#endif
VARTEMPLATESPECIALIZATION(VarTemplateSpecialization, VarDecl)
#ifndef VARTEMPLATEPARTIALSPECIALIZATION
# define VARTEMPLATEPARTIALSPECIALIZATION(Type, Base) VARTEMPLATESPECIALIZATION(Type, Base)
#endif
VARTEMPLATEPARTIALSPECIALIZATION(VarTemplatePartialSpecialization, VarTemplateSpecializationDecl)
#undef VARTEMPLATEPARTIALSPECIALIZATION
DECL_RANGE(VarTemplateSpecialization, VarTemplateSpecialization, VarTemplatePartialSpecialization)
#undef VARTEMPLATESPECIALIZATION
#ifndef PARMVAR
# define PARMVAR(Type, Base) VAR(Type, Base)
#endif
PARMVAR(ParmVar, VarDecl)
#undef PARMVAR
#ifndef OMPCAPTUREDEXPR
# define OMPCAPTUREDEXPR(Type, Base) VAR(Type, Base)
#endif
OMPCAPTUREDEXPR(OMPCapturedExpr, VarDecl)
#undef OMPCAPTUREDEXPR
#ifndef IMPLICITPARAM
# define IMPLICITPARAM(Type, Base) VAR(Type, Base)
#endif
IMPLICITPARAM(ImplicitParam, VarDecl)
#undef IMPLICITPARAM
#ifndef DECOMPOSITION
# define DECOMPOSITION(Type, Base) VAR(Type, Base)
#endif
DECOMPOSITION(Decomposition, VarDecl)
#undef DECOMPOSITION
DECL_RANGE(Var, Var, Decomposition)
#undef VAR
#ifndef NONTYPETEMPLATEPARM
# define NONTYPETEMPLATEPARM(Type, Base) DECLARATOR(Type, Base)
#endif
NONTYPETEMPLATEPARM(NonTypeTemplateParm, DeclaratorDecl)
#undef NONTYPETEMPLATEPARM
#ifndef MSPROPERTY
# define MSPROPERTY(Type, Base) DECLARATOR(Type, Base)
#endif
MSPROPERTY(MSProperty, DeclaratorDecl)
#undef MSPROPERTY
#ifndef FIELD
# define FIELD(Type, Base) DECLARATOR(Type, Base)
#endif
FIELD(Field, DeclaratorDecl)
#ifndef OBJCIVAR
# define OBJCIVAR(Type, Base) FIELD(Type, Base)
#endif
OBJCIVAR(ObjCIvar, FieldDecl)
#undef OBJCIVAR
#ifndef OBJCATDEFSFIELD
# define OBJCATDEFSFIELD(Type, Base) FIELD(Type, Base)
#endif
OBJCATDEFSFIELD(ObjCAtDefsField, FieldDecl)
#undef OBJCATDEFSFIELD
DECL_RANGE(Field, Field, ObjCAtDefsField)
#undef FIELD
DECL_RANGE(Declarator, Function, ObjCAtDefsField)
#undef DECLARATOR
#ifndef BINDING
# define BINDING(Type, Base) VALUE(Type, Base)
#endif
BINDING(Binding, ValueDecl)
#undef BINDING
DECL_RANGE(Value, OMPDeclareReduction, Binding)
#undef VALUE
#ifndef USINGSHADOW
# define USINGSHADOW(Type, Base) NAMED(Type, Base)
#endif
USINGSHADOW(UsingShadow, NamedDecl)
#ifndef CONSTRUCTORUSINGSHADOW
# define CONSTRUCTORUSINGSHADOW(Type, Base) USINGSHADOW(Type, Base)
#endif
CONSTRUCTORUSINGSHADOW(ConstructorUsingShadow, UsingShadowDecl)
#undef CONSTRUCTORUSINGSHADOW
DECL_RANGE(UsingShadow, UsingShadow, ConstructorUsingShadow)
#undef USINGSHADOW
#ifndef USINGPACK
# define USINGPACK(Type, Base) NAMED(Type, Base)
#endif
USINGPACK(UsingPack, NamedDecl)
#undef USINGPACK
#ifndef USINGDIRECTIVE
# define USINGDIRECTIVE(Type, Base) NAMED(Type, Base)
#endif
USINGDIRECTIVE(UsingDirective, NamedDecl)
#undef USINGDIRECTIVE
#ifndef UNRESOLVEDUSINGIFEXISTS
# define UNRESOLVEDUSINGIFEXISTS(Type, Base) NAMED(Type, Base)
#endif
UNRESOLVEDUSINGIFEXISTS(UnresolvedUsingIfExists, NamedDecl)
#undef UNRESOLVEDUSINGIFEXISTS
#ifndef TYPE
# define TYPE(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(TYPE(Type, NamedDecl))
#ifndef TAG
# define TAG(Type, Base) TYPE(Type, Base)
#endif
ABSTRACT_DECL(TAG(Tag, TypeDecl))
#ifndef RECORD
# define RECORD(Type, Base) TAG(Type, Base)
#endif
RECORD(Record, TagDecl)
#ifndef CXXRECORD
# define CXXRECORD(Type, Base) RECORD(Type, Base)
#endif
CXXRECORD(CXXRecord, RecordDecl)
#ifndef CLASSTEMPLATESPECIALIZATION
# define CLASSTEMPLATESPECIALIZATION(Type, Base) CXXRECORD(Type, Base)
#endif
CLASSTEMPLATESPECIALIZATION(ClassTemplateSpecialization, CXXRecordDecl)
#ifndef CLASSTEMPLATEPARTIALSPECIALIZATION
# define CLASSTEMPLATEPARTIALSPECIALIZATION(Type, Base) CLASSTEMPLATESPECIALIZATION(Type, Base)
#endif
CLASSTEMPLATEPARTIALSPECIALIZATION(ClassTemplatePartialSpecialization, ClassTemplateSpecializationDecl)
#undef CLASSTEMPLATEPARTIALSPECIALIZATION
DECL_RANGE(ClassTemplateSpecialization, ClassTemplateSpecialization, ClassTemplatePartialSpecialization)
#undef CLASSTEMPLATESPECIALIZATION
DECL_RANGE(CXXRecord, CXXRecord, ClassTemplatePartialSpecialization)
#undef CXXRECORD
DECL_RANGE(Record, Record, ClassTemplatePartialSpecialization)
#undef RECORD
#ifndef ENUM
# define ENUM(Type, Base) TAG(Type, Base)
#endif
ENUM(Enum, TagDecl)
#undef ENUM
DECL_RANGE(Tag, Record, Enum)
#undef TAG
#ifndef UNRESOLVEDUSINGTYPENAME
# define UNRESOLVEDUSINGTYPENAME(Type, Base) TYPE(Type, Base)
#endif
UNRESOLVEDUSINGTYPENAME(UnresolvedUsingTypename, TypeDecl)
#undef UNRESOLVEDUSINGTYPENAME
#ifndef TYPEDEFNAME
# define TYPEDEFNAME(Type, Base) TYPE(Type, Base)
#endif
ABSTRACT_DECL(TYPEDEFNAME(TypedefName, TypeDecl))
#ifndef TYPEDEF
# define TYPEDEF(Type, Base) TYPEDEFNAME(Type, Base)
#endif
TYPEDEF(Typedef, TypedefNameDecl)
#undef TYPEDEF
#ifndef TYPEALIAS
# define TYPEALIAS(Type, Base) TYPEDEFNAME(Type, Base)
#endif
TYPEALIAS(TypeAlias, TypedefNameDecl)
#undef TYPEALIAS
#ifndef OBJCTYPEPARAM
# define OBJCTYPEPARAM(Type, Base) TYPEDEFNAME(Type, Base)
#endif
OBJCTYPEPARAM(ObjCTypeParam, TypedefNameDecl)
#undef OBJCTYPEPARAM
DECL_RANGE(TypedefName, Typedef, ObjCTypeParam)
#undef TYPEDEFNAME
#ifndef TEMPLATETYPEPARM
# define TEMPLATETYPEPARM(Type, Base) TYPE(Type, Base)
#endif
TEMPLATETYPEPARM(TemplateTypeParm, TypeDecl)
#undef TEMPLATETYPEPARM
DECL_RANGE(Type, Record, TemplateTypeParm)
#undef TYPE
#ifndef TEMPLATE
# define TEMPLATE(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(TEMPLATE(Template, NamedDecl))
#ifndef TEMPLATETEMPLATEPARM
# define TEMPLATETEMPLATEPARM(Type, Base) TEMPLATE(Type, Base)
#endif
TEMPLATETEMPLATEPARM(TemplateTemplateParm, TemplateDecl)
#undef TEMPLATETEMPLATEPARM
#ifndef REDECLARABLETEMPLATE
# define REDECLARABLETEMPLATE(Type, Base) TEMPLATE(Type, Base)
#endif
ABSTRACT_DECL(REDECLARABLETEMPLATE(RedeclarableTemplate, TemplateDecl))
#ifndef VARTEMPLATE
# define VARTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
#endif
VARTEMPLATE(VarTemplate, RedeclarableTemplateDecl)
#undef VARTEMPLATE
#ifndef TYPEALIASTEMPLATE
# define TYPEALIASTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
#endif
TYPEALIASTEMPLATE(TypeAliasTemplate, RedeclarableTemplateDecl)
#undef TYPEALIASTEMPLATE
#ifndef FUNCTIONTEMPLATE
# define FUNCTIONTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
#endif
FUNCTIONTEMPLATE(FunctionTemplate, RedeclarableTemplateDecl)
#undef FUNCTIONTEMPLATE
#ifndef CLASSTEMPLATE
# define CLASSTEMPLATE(Type, Base) REDECLARABLETEMPLATE(Type, Base)
#endif
CLASSTEMPLATE(ClassTemplate, RedeclarableTemplateDecl)
#undef CLASSTEMPLATE
DECL_RANGE(RedeclarableTemplate, VarTemplate, ClassTemplate)
#undef REDECLARABLETEMPLATE
#ifndef CONCEPT
# define CONCEPT(Type, Base) TEMPLATE(Type, Base)
#endif
CONCEPT(Concept, TemplateDecl)
#undef CONCEPT
#ifndef BUILTINTEMPLATE
# define BUILTINTEMPLATE(Type, Base) TEMPLATE(Type, Base)
#endif
BUILTINTEMPLATE(BuiltinTemplate, TemplateDecl)
#undef BUILTINTEMPLATE
DECL_RANGE(Template, TemplateTemplateParm, BuiltinTemplate)
#undef TEMPLATE
#ifndef OBJCPROPERTY
# define OBJCPROPERTY(Type, Base) NAMED(Type, Base)
#endif
OBJCPROPERTY(ObjCProperty, NamedDecl)
#undef OBJCPROPERTY
#ifndef OBJCCOMPATIBLEALIAS
# define OBJCCOMPATIBLEALIAS(Type, Base) NAMED(Type, Base)
#endif
OBJCCOMPATIBLEALIAS(ObjCCompatibleAlias, NamedDecl)
#undef OBJCCOMPATIBLEALIAS
#ifndef NAMESPACEBASE
# define NAMESPACEBASE(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(NAMESPACEBASE(NamespaceBase, NamedDecl))
#ifndef NAMESPACE
# define NAMESPACE(Type, Base) NAMESPACEBASE(Type, Base)
#endif
NAMESPACE(Namespace, NamespaceBaseDecl)
#undef NAMESPACE
#ifndef NAMESPACEALIAS
# define NAMESPACEALIAS(Type, Base) NAMESPACEBASE(Type, Base)
#endif
NAMESPACEALIAS(NamespaceAlias, NamespaceBaseDecl)
#undef NAMESPACEALIAS
DECL_RANGE(NamespaceBase, Namespace, NamespaceAlias)
#undef NAMESPACEBASE
#ifndef LABEL
# define LABEL(Type, Base) NAMED(Type, Base)
#endif
LABEL(Label, NamedDecl)
#undef LABEL
#ifndef HLSLROOTSIGNATURE
# define HLSLROOTSIGNATURE(Type, Base) NAMED(Type, Base)
#endif
HLSLROOTSIGNATURE(HLSLRootSignature, NamedDecl)
#undef HLSLROOTSIGNATURE
#ifndef BASEUSING
# define BASEUSING(Type, Base) NAMED(Type, Base)
#endif
ABSTRACT_DECL(BASEUSING(BaseUsing, NamedDecl))
#ifndef USINGENUM
# define USINGENUM(Type, Base) BASEUSING(Type, Base)
#endif
USINGENUM(UsingEnum, BaseUsingDecl)
#undef USINGENUM
#ifndef USING
# define USING(Type, Base) BASEUSING(Type, Base)
#endif
USING(Using, BaseUsingDecl)
#undef USING
DECL_RANGE(BaseUsing, UsingEnum, Using)
#undef BASEUSING
DECL_RANGE(Named, ObjCMethod, Using)
#undef NAMED
#ifndef LIFETIMEEXTENDEDTEMPORARY
# define LIFETIMEEXTENDEDTEMPORARY(Type, Base) DECL(Type, Base)
#endif
LIFETIMEEXTENDEDTEMPORARY(LifetimeExtendedTemporary, Decl)
#undef LIFETIMEEXTENDEDTEMPORARY
#ifndef IMPORT
# define IMPORT(Type, Base) DECL(Type, Base)
#endif
IMPORT(Import, Decl)
#undef IMPORT
#ifndef IMPLICITCONCEPTSPECIALIZATION
# define IMPLICITCONCEPTSPECIALIZATION(Type, Base) DECL(Type, Base)
#endif
IMPLICITCONCEPTSPECIALIZATION(ImplicitConceptSpecialization, Decl)
#undef IMPLICITCONCEPTSPECIALIZATION
#ifndef FRIENDTEMPLATE
# define FRIENDTEMPLATE(Type, Base) DECL(Type, Base)
#endif
FRIENDTEMPLATE(FriendTemplate, Decl)
#undef FRIENDTEMPLATE
#ifndef FRIEND
# define FRIEND(Type, Base) DECL(Type, Base)
#endif
FRIEND(Friend, Decl)
#undef FRIEND
#ifndef FILESCOPEASM
# define FILESCOPEASM(Type, Base) DECL(Type, Base)
#endif
FILESCOPEASM(FileScopeAsm, Decl)
#undef FILESCOPEASM
#ifndef EMPTY
# define EMPTY(Type, Base) DECL(Type, Base)
#endif
EMPTY(Empty, Decl)
#undef EMPTY
#ifndef ACCESSSPEC
# define ACCESSSPEC(Type, Base) DECL(Type, Base)
#endif
ACCESSSPEC(AccessSpec, Decl)
#undef ACCESSSPEC
LAST_DECL_RANGE(Decl, TranslationUnit, AccessSpec)
#undef DECL
#undef DECL_RANGE
#undef LAST_DECL_RANGE
#undef ABSTRACT_DECL
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|* *|
|* List of AST Decl nodes *|
|* *|
|* Automatically generated file, do not edit! *|
|* From: DeclNodes.td *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef DECL_CONTEXT
# define DECL_CONTEXT(DECL)
#endif
DECL_CONTEXT(Block)
DECL_CONTEXT(Captured)
DECL_CONTEXT(Export)
DECL_CONTEXT(ExternCContext)
DECL_CONTEXT(Function)
DECL_CONTEXT(CXXDeductionGuide)
DECL_CONTEXT(CXXMethod)
DECL_CONTEXT(CXXConstructor)
DECL_CONTEXT(CXXConversion)
DECL_CONTEXT(CXXDestructor)
DECL_CONTEXT(HLSLBuffer)
DECL_CONTEXT(LinkageSpec)
DECL_CONTEXT(Namespace)
DECL_CONTEXT(OMPDeclareMapper)
DECL_CONTEXT(OMPDeclareReduction)
DECL_CONTEXT(ObjCCategory)
DECL_CONTEXT(ObjCCategoryImpl)
DECL_CONTEXT(ObjCImplementation)
DECL_CONTEXT(ObjCInterface)
DECL_CONTEXT(ObjCProtocol)
DECL_CONTEXT(ObjCMethod)
DECL_CONTEXT(OutlinedFunction)
DECL_CONTEXT(RequiresExprBody)
DECL_CONTEXT(Enum)
DECL_CONTEXT(Record)
DECL_CONTEXT(CXXRecord)
DECL_CONTEXT(ClassTemplateSpecialization)
DECL_CONTEXT(ClassTemplatePartialSpecialization)
DECL_CONTEXT(TopLevelStmt)
DECL_CONTEXT(TranslationUnit)
#undef DECL_CONTEXT

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
//===- DeclObjCCommon.h - Classes for representing declarations -*- 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 contains common ObjC enums and classes used in AST and
// Sema.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLOBJCCOMMON_H
#define LLVM_CLANG_AST_DECLOBJCCOMMON_H
namespace clang {
/// ObjCPropertyAttribute::Kind - list of property attributes.
/// Keep this list in sync with LLVM's Dwarf.h ApplePropertyAttributes.s
namespace ObjCPropertyAttribute {
enum Kind {
kind_noattr = 0x00,
kind_readonly = 0x01,
kind_getter = 0x02,
kind_assign = 0x04,
kind_readwrite = 0x08,
kind_retain = 0x10,
kind_copy = 0x20,
kind_nonatomic = 0x40,
kind_setter = 0x80,
kind_atomic = 0x100,
kind_weak = 0x200,
kind_strong = 0x400,
kind_unsafe_unretained = 0x800,
/// Indicates that the nullability of the type was spelled with a
/// property attribute rather than a type qualifier.
kind_nullability = 0x1000,
kind_null_resettable = 0x2000,
kind_class = 0x4000,
kind_direct = 0x8000,
// Adding a property should change NumObjCPropertyAttrsBits
// Also, don't forget to update the Clang C API at CXObjCPropertyAttrKind and
// clang_Cursor_getObjCPropertyAttributes.
};
} // namespace ObjCPropertyAttribute::Kind
enum {
/// Number of bits fitting all the property attributes.
NumObjCPropertyAttrsBits = 16
};
} // namespace clang
#endif // LLVM_CLANG_AST_DECLOBJCCOMMON_H

View File

@ -0,0 +1,155 @@
//=- DeclOpenACC.h - Classes for representing OpenACC 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines OpenACC nodes for declarative directives.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLOPENACC_H
#define LLVM_CLANG_AST_DECLOPENACC_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/OpenACCClause.h"
#include "clang/Basic/OpenACCKinds.h"
#include "llvm/ADT/STLExtras.h"
namespace clang {
// A base class for the declaration constructs, which manages the clauses and
// basic source location information. Currently not part of the Decl inheritence
// tree, as we should never have a reason to store one of these.
class OpenACCConstructDecl : public Decl {
friend class ASTDeclReader;
friend class ASTDeclWriter;
// The directive kind, each implementation of this interface is expected to
// handle a specific kind.
OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid;
SourceLocation DirectiveLoc;
SourceLocation EndLoc;
/// The list of clauses. This is stored here as an ArrayRef, as this is the
/// most convienient place to access the list, however the list itself should
/// be stored in leaf nodes, likely in trailing-storage.
MutableArrayRef<const OpenACCClause *> Clauses;
protected:
OpenACCConstructDecl(Kind DeclKind, DeclContext *DC, OpenACCDirectiveKind K,
SourceLocation StartLoc, SourceLocation DirLoc,
SourceLocation EndLoc)
: Decl(DeclKind, DC, StartLoc), DirKind(K), DirectiveLoc(DirLoc),
EndLoc(EndLoc) {}
OpenACCConstructDecl(Kind DeclKind) : Decl(DeclKind, EmptyShell{}) {}
void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
assert(Clauses.empty() && "Cannot change clause list");
Clauses = NewClauses;
}
public:
OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
SourceLocation getDirectiveLoc() const { return DirectiveLoc; }
virtual SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocation(), EndLoc);
}
ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K);
};
class OpenACCDeclareDecl final
: public OpenACCConstructDecl,
private llvm::TrailingObjects<OpenACCDeclareDecl, const OpenACCClause *> {
friend TrailingObjects;
friend class ASTDeclReader;
friend class ASTDeclWriter;
OpenACCDeclareDecl(unsigned NumClauses)
: OpenACCConstructDecl(OpenACCDeclare) {
std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
setClauseList(getTrailingObjects(NumClauses));
}
OpenACCDeclareDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation DirLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses)
: OpenACCConstructDecl(OpenACCDeclare, DC, OpenACCDirectiveKind::Declare,
StartLoc, DirLoc, EndLoc) {
// Initialize the trailing storage.
llvm::uninitialized_copy(Clauses, getTrailingObjects());
setClauseList(getTrailingObjects(Clauses.size()));
}
public:
static OpenACCDeclareDecl *Create(ASTContext &Ctx, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation DirLoc,
SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses);
static OpenACCDeclareDecl *
CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID, unsigned NumClauses);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OpenACCDeclare; }
};
// Reprents a 'routine' directive with a name. When this has no name, it is
// represented as an attribute.
class OpenACCRoutineDecl final
: public OpenACCConstructDecl,
private llvm::TrailingObjects<OpenACCRoutineDecl, const OpenACCClause *> {
friend TrailingObjects;
friend class ASTDeclReader;
friend class ASTDeclWriter;
Expr *FuncRef = nullptr;
SourceRange ParensLoc;
OpenACCRoutineDecl(unsigned NumClauses)
: OpenACCConstructDecl(OpenACCRoutine) {
std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
setClauseList(getTrailingObjects(NumClauses));
}
OpenACCRoutineDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation DirLoc, SourceLocation LParenLoc,
Expr *FuncRef, SourceLocation RParenLoc,
SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses)
: OpenACCConstructDecl(OpenACCRoutine, DC, OpenACCDirectiveKind::Routine,
StartLoc, DirLoc, EndLoc),
FuncRef(FuncRef), ParensLoc(LParenLoc, RParenLoc) {
assert(LParenLoc.isValid() &&
"Cannot represent implicit name with this declaration");
// Initialize the trailing storage.
llvm::uninitialized_copy(Clauses, getTrailingObjects());
setClauseList(getTrailingObjects(Clauses.size()));
}
public:
static OpenACCRoutineDecl *
Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc,
SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef,
SourceLocation RParenLoc, SourceLocation EndLoc,
ArrayRef<const OpenACCClause *> Clauses);
static OpenACCRoutineDecl *
CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID, unsigned NumClauses);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OpenACCRoutine; }
const Expr *getFunctionReference() const { return FuncRef; }
Expr *getFunctionReference() { return FuncRef; }
SourceLocation getLParenLoc() const { return ParensLoc.getBegin(); }
SourceLocation getRParenLoc() const { return ParensLoc.getEnd(); }
};
} // namespace clang
#endif

View File

@ -0,0 +1,610 @@
//===- DeclOpenMP.h - Classes for representing OpenMP 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines OpenMP nodes for declarative directives.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLOPENMP_H
#define LLVM_CLANG_AST_DECLOPENMP_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/TrailingObjects.h"
namespace clang {
/// This is a basic class for representing single OpenMP declarative directive.
///
template <typename U> class OMPDeclarativeDirective : public U {
friend class ASTDeclReader;
friend class ASTDeclWriter;
/// Get the clauses storage.
MutableArrayRef<OMPClause *> getClauses() {
if (!Data)
return {};
return Data->getClauses();
}
protected:
/// Data, associated with the directive.
OMPChildren *Data = nullptr;
/// Build instance of directive.
template <typename... Params>
OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {}
template <typename T, typename... Params>
static T *createDirective(const ASTContext &C, DeclContext *DC,
ArrayRef<OMPClause *> Clauses, unsigned NumChildren,
Params &&... P) {
auto *Inst = new (C, DC, size(Clauses.size(), NumChildren))
T(DC, std::forward<Params>(P)...);
Inst->Data = OMPChildren::Create(Inst + 1, Clauses,
/*AssociatedStmt=*/nullptr, NumChildren);
Inst->Data->setClauses(Clauses);
return Inst;
}
template <typename T, typename... Params>
static T *createEmptyDirective(const ASTContext &C, GlobalDeclID ID,
unsigned NumClauses, unsigned NumChildren,
Params &&... P) {
auto *Inst = new (C, ID, size(NumClauses, NumChildren))
T(nullptr, std::forward<Params>(P)...);
Inst->Data = OMPChildren::CreateEmpty(
Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren);
return Inst;
}
static size_t size(unsigned NumClauses, unsigned NumChildren) {
return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false,
NumChildren);
}
public:
/// Get number of clauses.
unsigned getNumClauses() const {
if (!Data)
return 0;
return Data->getNumClauses();
}
/// Returns specified clause.
///
/// \param I Number of clause.
///
OMPClause *getClause(unsigned I) const { return clauses()[I]; }
ArrayRef<OMPClause *> clauses() const {
if (!Data)
return {};
return Data->getClauses();
}
};
/// This represents '#pragma omp threadprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are threadprivate:
///
/// \code
/// int a;
/// #pragma omp threadprivate(a)
/// struct A {
/// static int b;
/// #pragma omp threadprivate(b)
/// };
/// \endcode
///
class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
friend class OMPDeclarativeDirective<Decl>;
LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
OMPThreadPrivateDecl(DeclContext *DC = nullptr,
SourceLocation L = SourceLocation())
: OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {}
ArrayRef<const Expr *> getVars() const {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
MutableArrayRef<Expr *> getVars() {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
void setVars(ArrayRef<Expr *> VL);
public:
static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ArrayRef<Expr *> VL);
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID, unsigned N);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
typedef llvm::iterator_range<varlist_iterator> varlist_range;
typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
unsigned varlist_size() const { return Data->getNumChildren(); }
bool varlist_empty() const { return Data->getChildren().empty(); }
varlist_range varlist() {
return varlist_range(varlist_begin(), varlist_end());
}
varlist_const_range varlist() const {
return varlist_const_range(varlist_begin(), varlist_end());
}
varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_iterator varlist_end() { return getVars().end(); }
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
};
/// This represents '#pragma omp groupprivate ...' directive.
/// For example, in the following, both 'a' and 'A::b' are groupprivate:
///
/// \code
/// int a;
/// #pragma omp groupprivate(a)
/// struct A {
/// static int b;
/// #pragma omp groupprivate(b)
/// };
/// \endcode
///
class OMPGroupPrivateDecl final : public OMPDeclarativeDirective<Decl> {
friend class OMPDeclarativeDirective<Decl>;
LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
OMPGroupPrivateDecl(DeclContext *DC = nullptr,
SourceLocation L = SourceLocation())
: OMPDeclarativeDirective<Decl>(OMPGroupPrivate, DC, L) {}
ArrayRef<const Expr *> getVars() const {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
MutableArrayRef<Expr *> getVars() {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
void setVars(ArrayRef<Expr *> VL);
public:
static OMPGroupPrivateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<Expr *> VL);
static OMPGroupPrivateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned N);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
typedef llvm::iterator_range<varlist_iterator> varlist_range;
typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
unsigned varlist_size() const { return Data->getNumChildren(); }
bool varlist_empty() const { return Data->getChildren().empty(); }
varlist_range varlist() {
return varlist_range(varlist_begin(), varlist_end());
}
varlist_const_range varlist() const {
return varlist_const_range(varlist_begin(), varlist_end());
}
varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_iterator varlist_end() { return getVars().end(); }
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPGroupPrivate; }
};
enum class OMPDeclareReductionInitKind {
Call, // Initialized by function call.
Direct, // omp_priv(<expr>)
Copy // omp_priv = <expr>
};
/// This represents '#pragma omp declare reduction ...' directive.
/// For example, in the following, declared reduction 'foo' for types 'int' and
/// 'float':
///
/// \code
/// #pragma omp declare reduction (foo : int,float : omp_out += omp_in)
/// initializer (omp_priv = 0)
/// \endcode
///
/// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
// This class stores some data in DeclContext::OMPDeclareReductionDeclBits
// to save some space. Use the provided accessors to access it.
friend class ASTDeclReader;
/// Combiner for declare reduction construct.
Expr *Combiner = nullptr;
/// Initializer for declare reduction construct.
Expr *Initializer = nullptr;
/// In parameter of the combiner.
Expr *In = nullptr;
/// Out parameter of the combiner.
Expr *Out = nullptr;
/// Priv parameter of the initializer.
Expr *Priv = nullptr;
/// Orig parameter of the initializer.
Expr *Orig = nullptr;
/// Reference to the previous declare reduction construct in the same
/// scope with the same name. Required for proper templates instantiation if
/// the declare reduction construct is declared inside compound statement.
LazyDeclPtr PrevDeclInScope;
void anchor() override;
OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, QualType Ty,
OMPDeclareReductionDecl *PrevDeclInScope);
void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
PrevDeclInScope = Prev;
}
public:
/// Create declare reduction node.
static OMPDeclareReductionDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
/// Create deserialized declare reduction node.
static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
/// Get combiner expression of the declare reduction construct.
Expr *getCombiner() { return Combiner; }
const Expr *getCombiner() const { return Combiner; }
/// Get In variable of the combiner.
Expr *getCombinerIn() { return In; }
const Expr *getCombinerIn() const { return In; }
/// Get Out variable of the combiner.
Expr *getCombinerOut() { return Out; }
const Expr *getCombinerOut() const { return Out; }
/// Set combiner expression for the declare reduction construct.
void setCombiner(Expr *E) { Combiner = E; }
/// Set combiner In and Out vars.
void setCombinerData(Expr *InE, Expr *OutE) {
In = InE;
Out = OutE;
}
/// Get initializer expression (if specified) of the declare reduction
/// construct.
Expr *getInitializer() { return Initializer; }
const Expr *getInitializer() const { return Initializer; }
/// Get initializer kind.
OMPDeclareReductionInitKind getInitializerKind() const {
return static_cast<OMPDeclareReductionInitKind>(
OMPDeclareReductionDeclBits.InitializerKind);
}
/// Get Orig variable of the initializer.
Expr *getInitOrig() { return Orig; }
const Expr *getInitOrig() const { return Orig; }
/// Get Priv variable of the initializer.
Expr *getInitPriv() { return Priv; }
const Expr *getInitPriv() const { return Priv; }
/// Set initializer expression for the declare reduction construct.
void setInitializer(Expr *E, OMPDeclareReductionInitKind IK) {
Initializer = E;
OMPDeclareReductionDeclBits.InitializerKind = llvm::to_underlying(IK);
}
/// Set initializer Orig and Priv vars.
void setInitializerData(Expr *OrigE, Expr *PrivE) {
Orig = OrigE;
Priv = PrivE;
}
/// Get reference to previous declare reduction construct in the same
/// scope with the same name.
OMPDeclareReductionDecl *getPrevDeclInScope();
const OMPDeclareReductionDecl *getPrevDeclInScope() const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPDeclareReduction; }
static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) {
return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D));
}
static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<OMPDeclareReductionDecl *>(
const_cast<DeclContext *>(DC));
}
};
/// This represents '#pragma omp declare mapper ...' directive. Map clauses are
/// allowed to use with this directive. The following example declares a user
/// defined mapper for the type 'struct vec'. This example instructs the fields
/// 'len' and 'data' should be mapped when mapping instances of 'struct vec'.
///
/// \code
/// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N])
/// \endcode
class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>,
public DeclContext {
friend class OMPDeclarativeDirective<ValueDecl>;
friend class ASTDeclReader;
friend class ASTDeclWriter;
/// Mapper variable, which is 'v' in the example above
Expr *MapperVarRef = nullptr;
/// Name of the mapper variable
DeclarationName VarName;
LazyDeclPtr PrevDeclInScope;
void anchor() override;
OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
QualType Ty, DeclarationName VarName,
OMPDeclareMapperDecl *PrevDeclInScope)
: OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty),
DeclContext(OMPDeclareMapper), VarName(VarName),
PrevDeclInScope(PrevDeclInScope) {}
void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) {
PrevDeclInScope = Prev;
}
public:
/// Creates declare mapper node.
static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, DeclarationName Name,
QualType T, DeclarationName VarName,
ArrayRef<OMPClause *> Clauses,
OMPDeclareMapperDecl *PrevDeclInScope);
/// Creates deserialized declare mapper node.
static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID, unsigned N);
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
using clauselist_range = llvm::iterator_range<clauselist_iterator>;
using clauselist_const_range =
llvm::iterator_range<clauselist_const_iterator>;
unsigned clauselist_size() const { return Data->getNumClauses(); }
bool clauselist_empty() const { return Data->getClauses().empty(); }
clauselist_range clauselists() {
return clauselist_range(clauselist_begin(), clauselist_end());
}
clauselist_const_range clauselists() const {
return clauselist_const_range(clauselist_begin(), clauselist_end());
}
clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_const_iterator clauselist_begin() const {
return Data->getClauses().begin();
}
clauselist_const_iterator clauselist_end() const {
return Data->getClauses().end();
}
/// Get the variable declared in the mapper
Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
const Expr *getMapperVarRef() const {
return cast_or_null<Expr>(Data->getChildren()[0]);
}
/// Set the variable declared in the mapper
void setMapperVarRef(Expr *MapperVarRefE) {
Data->getChildren()[0] = MapperVarRefE;
}
/// Get the name of the variable declared in the mapper
DeclarationName getVarName() { return VarName; }
/// Get reference to previous declare mapper construct in the same
/// scope with the same name.
OMPDeclareMapperDecl *getPrevDeclInScope();
const OMPDeclareMapperDecl *getPrevDeclInScope() const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPDeclareMapper; }
static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) {
return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D));
}
static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC));
}
};
/// Pseudo declaration for capturing expressions. Also is used for capturing of
/// non-static data members in non-static member functions.
///
/// Clang supports capturing of variables only, but OpenMP 4.5 allows to
/// privatize non-static members of current class in non-static member
/// functions. This pseudo-declaration allows properly handle this kind of
/// capture by wrapping captured expression into a variable-like declaration.
class OMPCapturedExprDecl final : public VarDecl {
friend class ASTDeclReader;
void anchor() override;
OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
QualType Type, TypeSourceInfo *TInfo,
SourceLocation StartLoc)
: VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo,
SC_None) {
setImplicit();
}
public:
static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id, QualType T,
SourceLocation StartLoc);
static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C,
GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
};
/// This represents '#pragma omp requires...' directive.
/// For example
///
/// \code
/// #pragma omp requires unified_address
/// \endcode
///
class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> {
friend class OMPDeclarativeDirective<Decl>;
friend class ASTDeclReader;
LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
OMPRequiresDecl(DeclContext *DC, SourceLocation L)
: OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {}
public:
/// Create requires node.
static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<OMPClause *> CL);
/// Create deserialized requires node.
static OMPRequiresDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned N);
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
using clauselist_range = llvm::iterator_range<clauselist_iterator>;
using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
unsigned clauselist_size() const { return Data->getNumClauses(); }
bool clauselist_empty() const { return Data->getClauses().empty(); }
clauselist_range clauselists() {
return clauselist_range(clauselist_begin(), clauselist_end());
}
clauselist_const_range clauselists() const {
return clauselist_const_range(clauselist_begin(), clauselist_end());
}
clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_const_iterator clauselist_begin() const {
return Data->getClauses().begin();
}
clauselist_const_iterator clauselist_end() const {
return Data->getClauses().end();
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPRequires; }
};
/// This represents '#pragma omp allocate ...' directive.
/// For example, in the following, the default allocator is used for both 'a'
/// and 'A::b':
///
/// \code
/// int a;
/// #pragma omp allocate(a)
/// struct A {
/// static int b;
/// #pragma omp allocate(b)
/// };
/// \endcode
///
class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
friend class OMPDeclarativeDirective<Decl>;
friend class ASTDeclReader;
LLVM_DECLARE_VIRTUAL_ANCHOR_FUNCTION();
OMPAllocateDecl(DeclContext *DC, SourceLocation L)
: OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {}
ArrayRef<const Expr *> getVars() const {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
MutableArrayRef<Expr *> getVars() {
auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
return {Storage, Data->getNumChildren()};
}
void setVars(ArrayRef<Expr *> VL);
public:
static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<Expr *> VL,
ArrayRef<OMPClause *> CL);
static OMPAllocateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NVars, unsigned NClauses);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
typedef llvm::iterator_range<varlist_iterator> varlist_range;
typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
using clauselist_range = llvm::iterator_range<clauselist_iterator>;
using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
unsigned varlist_size() const { return Data->getNumChildren(); }
bool varlist_empty() const { return Data->getChildren().empty(); }
unsigned clauselist_size() const { return Data->getNumClauses(); }
bool clauselist_empty() const { return Data->getClauses().empty(); }
varlist_range varlist() {
return varlist_range(varlist_begin(), varlist_end());
}
varlist_const_range varlist() const {
return varlist_const_range(varlist_begin(), varlist_end());
}
varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_iterator varlist_end() { return getVars().end(); }
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
clauselist_range clauselists() {
return clauselist_range(clauselist_begin(), clauselist_end());
}
clauselist_const_range clauselists() const {
return clauselist_const_range(clauselist_begin(), clauselist_end());
}
clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
clauselist_const_iterator clauselist_begin() const {
return Data->getClauses().begin();
}
clauselist_const_iterator clauselist_end() const {
return Data->getClauses().end();
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPAllocate; }
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
//===- DeclVisitor.h - Visitor for Decl subclasses --------------*- 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 DeclVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLVISITOR_H
#define LLVM_CLANG_AST_DECLVISITOR_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenACC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
namespace clang {
namespace declvisitor {
/// A simple visitor class that helps create declaration visitors.
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
class Base {
public:
#define PTR(CLASS) typename Ptr<CLASS>::type
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit##NAME(static_cast<PTR(CLASS)>(D))
RetTy Visit(PTR(Decl) D) {
switch (D->getKind()) {
#define DECL(DERIVED, BASE) \
case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
}
llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
}
// If the implementation chooses not to implement a certain visit
// method, fall back to the parent.
#define DECL(DERIVED, BASE) \
RetTy Visit##DERIVED##Decl(PTR(DERIVED##Decl) D) { DISPATCH(BASE, BASE); }
#include "clang/AST/DeclNodes.inc"
RetTy VisitDecl(PTR(Decl) D) { return RetTy(); }
#undef PTR
#undef DISPATCH
};
} // namespace declvisitor
/// A simple visitor class that helps create declaration visitors.
///
/// This class does not preserve constness of Decl pointers (see also
/// ConstDeclVisitor).
template <typename ImplClass, typename RetTy = void>
class DeclVisitor
: public declvisitor::Base<std::add_pointer, ImplClass, RetTy> {};
/// A simple visitor class that helps create declaration visitors.
///
/// This class preserves constness of Decl pointers (see also DeclVisitor).
template <typename ImplClass, typename RetTy = void>
class ConstDeclVisitor
: public declvisitor::Base<llvm::make_const_ptr, ImplClass, RetTy> {};
} // namespace clang
#endif // LLVM_CLANG_AST_DECLVISITOR_H

Some files were not shown because too many files have changed in this diff Show More