LLVM Backend ekleniyor
This commit is contained in:
parent
0c9ac1c876
commit
1af0592232
105
Parsing.cpp
105
Parsing.cpp
|
|
@ -1,90 +1,39 @@
|
|||
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;
|
||||
}
|
||||
#include "llvm/include/llvm-c/Core.h"
|
||||
#include "llvm/include/llvm-c/Analysis.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
init_jit("saqut");
|
||||
jit_state_t *_jit = jit_new_state();
|
||||
// 1. LLVM Context Oluştur (Bellek yönetimi ve izolasyon için şart)
|
||||
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ıtçısı sum olsun)
|
||||
jit_movi(JIT_V1, 1); // a = 1 (V1 kayıtçısı a olsun)
|
||||
// 3. Basit bir fonksiyon tipi oluştur: int32 f()
|
||||
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ıtçıdan kayıtçı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();
|
||||
// 5. Temel bir blok (Entry block) ekle
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context, main_func, "entry");
|
||||
|
||||
jit_word_t size;
|
||||
void* final_code = jit_emit();
|
||||
jit_get_code(&size);
|
||||
// 6. Bir Builder oluştur ve fonksiyonun içine "return 0" ekle
|
||||
LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
LLVMBuildRet(builder, LLVMConstInt(LLVMInt32TypeInContext(context), 0, 0));
|
||||
|
||||
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;
|
||||
}
|
||||
// 7. Oluşturulan IR kodunu terminale yazdır (Gözle kontrol için)
|
||||
printf("--- Oluşturulan LLVM IR Kodu ---\n");
|
||||
LLVMDumpModule(mod);
|
||||
printf("--------------------------------\n");
|
||||
printf("saQut: LLVM Modülü ve Fonksiyonu başarıyla oluşturuldu!\n");
|
||||
|
||||
// 8. Temizlik (Bellek sızıntısını önlemek için önemli)
|
||||
LLVMDisposeBuilder(builder);
|
||||
LLVMDisposeModule(mod);
|
||||
LLVMContextDispose(context);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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ıtçısı sum olsun)
|
||||
jit_movi(JIT_V1, 1); // a = 1 (V1 kayıtçısı a olsun)
|
||||
|
||||
jit_node_t *loop_start = jit_label();
|
||||
|
||||
// sum += a (Kayıtçıdan kayıtçı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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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, <br />).
|
||||
*/
|
||||
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 */
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue