Rev
This commit is contained in:
parent
1af0592232
commit
b08205c03f
|
|
@ -0,0 +1,11 @@
|
||||||
|
# saQut Compiler
|
||||||
|
saqut
|
||||||
|
*.o
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
.DS_Store
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "linux-gcc-x64",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**",
|
|
||||||
"${workspaceFolder}/lightning/include"
|
|
||||||
],
|
|
||||||
"compilerPath": "/usr/bin/gcc",
|
|
||||||
"cStandard": "${default}",
|
|
||||||
"cppStandard": "${default}",
|
|
||||||
"intelliSenseMode": "linux-gcc-x64",
|
|
||||||
"compilerArgs": [
|
|
||||||
""
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"comments": {
|
|
||||||
"lineComment": {
|
|
||||||
"comment": "//"
|
|
||||||
},
|
|
||||||
"blockComment": ["/*", "*/"]
|
|
||||||
},
|
|
||||||
"brackets": [
|
|
||||||
["{", "}"],
|
|
||||||
["[", "]"],
|
|
||||||
["(", ")"]
|
|
||||||
],
|
|
||||||
"autoClosingPairs": [
|
|
||||||
{ "open": "{", "close": "}" },
|
|
||||||
{ "open": "[", "close": "]" },
|
|
||||||
{ "open": "(", "close": ")" },
|
|
||||||
{ "open": "\"", "close": "\"" },
|
|
||||||
{ "open": "'", "close": "'" }
|
|
||||||
],
|
|
||||||
"surroundingPairs": [
|
|
||||||
["{", "}"],
|
|
||||||
["[", "]"],
|
|
||||||
["(", ")"],
|
|
||||||
["\"", "\""],
|
|
||||||
["'", "'"]
|
|
||||||
],
|
|
||||||
"indentationRules": {
|
|
||||||
"increaseIndentPattern": "^.*\\{\\s*$",
|
|
||||||
"decreaseIndentPattern": "^\\s*\\}.*$"
|
|
||||||
},
|
|
||||||
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)"
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"name": "saqut-support",
|
|
||||||
"displayName": "saQut Language Support",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"engines": { "vscode": "^1.60.0" },
|
|
||||||
"categories": ["Programming Languages"],
|
|
||||||
"contributes": {
|
|
||||||
"languages": [{
|
|
||||||
"id": "saqut",
|
|
||||||
"aliases": ["saQut", "saqut"],
|
|
||||||
"extensions": [".sqt"],
|
|
||||||
"configuration": "./language-configuration.json"
|
|
||||||
}],
|
|
||||||
"grammars": [{
|
|
||||||
"language": "saqut",
|
|
||||||
"scopeName": "source.sqt",
|
|
||||||
"path": "./syntaxes/saqut.tmLanguage.json"
|
|
||||||
}],
|
|
||||||
"snippets": [
|
|
||||||
{
|
|
||||||
"language": "saqut",
|
|
||||||
"path": "./snippets/saqut.code-snippets"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"If Statement": {
|
|
||||||
"prefix": "if",
|
|
||||||
"body": [
|
|
||||||
"if (${1:condition}) {",
|
|
||||||
"\t$0",
|
|
||||||
"}"
|
|
||||||
],
|
|
||||||
"description": "If Koşulu"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
{
|
|
||||||
"scopeName": "source.sqt",
|
|
||||||
"patterns": [
|
|
||||||
{ "include": "#comments" },
|
|
||||||
{ "include": "#keywords" },
|
|
||||||
{ "include": "#classes" },
|
|
||||||
{ "include": "#structs" },
|
|
||||||
{ "include": "#enums" },
|
|
||||||
{ "include": "#strings" },
|
|
||||||
{ "include": "#numbers" },
|
|
||||||
{ "include": "#functions" }
|
|
||||||
],
|
|
||||||
"repository": {
|
|
||||||
"keywords": {
|
|
||||||
"patterns": [{
|
|
||||||
"name": "keyword.control.saqut",
|
|
||||||
"match": "\\b(implements|protected|interface|continue|private|finally|extends|default|throws|switch|return|public|assert|false|while|throw|class|catch|break|null|true|enum|else|case|new|try|for|if|do)\\b"
|
|
||||||
}, {
|
|
||||||
"name": "storage.type.saqut",
|
|
||||||
"match": "\\b(int|float|double|string|bool|void|var|class|struct|enum|public|private|static|readonly|const)\\b"
|
|
||||||
}, {
|
|
||||||
"name": "variable.language.saqut",
|
|
||||||
"match": "\\b(this)\\b"
|
|
||||||
}, {
|
|
||||||
"name": "constant.language.saqut",
|
|
||||||
"match": "\\b(true|false|null)\\b"
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"functions": {
|
|
||||||
"patterns": [{
|
|
||||||
"name": "entity.name.function.saqut",
|
|
||||||
"match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)(?=\\s*\\()"
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"classes": {
|
|
||||||
"patterns": [{
|
|
||||||
"match": "\\b(class)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
|
|
||||||
"captures": {
|
|
||||||
"1": { "name": "storage.type.saqut" },
|
|
||||||
"2": { "name": "entity.name.class" }
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"structs": {
|
|
||||||
"patterns": [{
|
|
||||||
"match": "\\b(struct)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
|
|
||||||
"captures": {
|
|
||||||
"1": { "name": "storage.type.saqut" },
|
|
||||||
"2": { "name": "entity.name.struct" }
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"enums": {
|
|
||||||
"patterns": [{
|
|
||||||
"match": "\\b(enum)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
|
|
||||||
"captures": {
|
|
||||||
"1": { "name": "storage.type.saqut" },
|
|
||||||
"2": { "name": "entity.name.enum" }
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"strings": {
|
|
||||||
"name": "string.quoted.double.saqut",
|
|
||||||
"begin": "\"",
|
|
||||||
"end": "\"",
|
|
||||||
"patterns": [
|
|
||||||
{ "name": "constant.character.escape.saqut", "match": "\\\\." }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"numbers": {
|
|
||||||
"name": "constant.numeric.saqut",
|
|
||||||
"match": "\\b(0x[0-9a-fA-F]+|[0-9]+(\\.[0-9]+)?)\\b"
|
|
||||||
},
|
|
||||||
"comments": {
|
|
||||||
"patterns": [
|
|
||||||
{ "name": "comment.line.double-slash.saqut", "match": "//.*$" },
|
|
||||||
{ "name": "comment.block.saqut", "begin": "/\\*", "end": "\\*/" }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "C/C++ Runner: Debug Session",
|
|
||||||
"type": "cppdbg",
|
|
||||||
"request": "launch",
|
|
||||||
"args": [],
|
|
||||||
"preLaunchTask": "build saqut",
|
|
||||||
"stopAtEntry": true,
|
|
||||||
"externalConsole": false,
|
|
||||||
"cwd": "/home/saqut/Masaüstü/saqutcompiler",
|
|
||||||
"program": "/home/saqut/Masaüstü/saqutcompiler/saqut",
|
|
||||||
"MIMode": "gdb",
|
|
||||||
"miDebuggerPath": "gdb",
|
|
||||||
"setupCommands": [
|
|
||||||
{
|
|
||||||
"description": "Enable pretty-printing for gdb",
|
|
||||||
"text": "-enable-pretty-printing",
|
|
||||||
"ignoreFailures": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
{
|
|
||||||
"C_Cpp_Runner.cCompilerPath": "gcc",
|
|
||||||
"C_Cpp_Runner.cppCompilerPath": "g++",
|
|
||||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
|
||||||
"C_Cpp_Runner.cStandard": "",
|
|
||||||
"C_Cpp_Runner.cppStandard": "",
|
|
||||||
"C_Cpp_Runner.msvcBatchPath": "",
|
|
||||||
"C_Cpp_Runner.useMsvc": false,
|
|
||||||
"C_Cpp_Runner.warnings": [
|
|
||||||
"-Wall",
|
|
||||||
"-Wextra",
|
|
||||||
"-Wpedantic",
|
|
||||||
"-Wshadow",
|
|
||||||
"-Wformat=2",
|
|
||||||
"-Wcast-align",
|
|
||||||
"-Wconversion",
|
|
||||||
"-Wsign-conversion",
|
|
||||||
"-Wnull-dereference"
|
|
||||||
],
|
|
||||||
"C_Cpp_Runner.msvcWarnings": [
|
|
||||||
"/W4",
|
|
||||||
"/permissive-",
|
|
||||||
"/w14242",
|
|
||||||
"/w14287",
|
|
||||||
"/w14296",
|
|
||||||
"/w14311",
|
|
||||||
"/w14826",
|
|
||||||
"/w44062",
|
|
||||||
"/w44242",
|
|
||||||
"/w14905",
|
|
||||||
"/w14906",
|
|
||||||
"/w14263",
|
|
||||||
"/w44265",
|
|
||||||
"/w14928"
|
|
||||||
],
|
|
||||||
"C_Cpp_Runner.enableWarnings": true,
|
|
||||||
"C_Cpp_Runner.warningsAsError": false,
|
|
||||||
"C_Cpp_Runner.compilerArgs": [],
|
|
||||||
"C_Cpp_Runner.linkerArgs": [],
|
|
||||||
"C_Cpp_Runner.includePaths": [],
|
|
||||||
"C_Cpp_Runner.includeSearch": [
|
|
||||||
"*",
|
|
||||||
"**/*"
|
|
||||||
],
|
|
||||||
"C_Cpp_Runner.excludeSearch": [
|
|
||||||
"**/build",
|
|
||||||
"**/build/**",
|
|
||||||
"**/.*",
|
|
||||||
"**/.*/**",
|
|
||||||
"**/.vscode",
|
|
||||||
"**/.vscode/**"
|
|
||||||
],
|
|
||||||
"C_Cpp_Runner.useAddressSanitizer": false,
|
|
||||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
|
||||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
|
||||||
"C_Cpp_Runner.showCompilationTime": false,
|
|
||||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
|
||||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"type": "cppbuild",
|
|
||||||
"label": "build saqut",
|
|
||||||
"command": "/usr/bin/g++",
|
|
||||||
"args": [
|
|
||||||
"-g", // Debug sembolleri açık kalsın
|
|
||||||
"-O0", // Debug sırasında optimizasyonu kapat (kodun satırları karışmasın)
|
|
||||||
"./Parsing.cpp",
|
|
||||||
"${workspaceFolder}/lightning/lib/.libs/liblightning.a",
|
|
||||||
"-I${workspaceFolder}/lightning/include",
|
|
||||||
"-D_GNU_SOURCE",
|
|
||||||
"-ldl",
|
|
||||||
"-o",
|
|
||||||
"saqut" // Çıktı ismi sabit olsun (saqut)
|
|
||||||
],
|
|
||||||
"options": {
|
|
||||||
"cwd": "${workspaceFolder}"
|
|
||||||
},
|
|
||||||
"problemMatcher": [
|
|
||||||
"$gcc"
|
|
||||||
],
|
|
||||||
"group": {
|
|
||||||
"kind": "build",
|
|
||||||
"isDefault": true
|
|
||||||
},
|
|
||||||
"detail": "saQut için özel JIT derleme görevi"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
39
Parsing.cpp
39
Parsing.cpp
|
|
@ -1,39 +0,0 @@
|
||||||
#include "llvm/include/llvm-c/Core.h"
|
|
||||||
#include "llvm/include/llvm-c/Analysis.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
// 1. LLVM Context Oluştur (Bellek yönetimi ve izolasyon için şart)
|
|
||||||
LLVMContextRef context = LLVMContextCreate();
|
|
||||||
|
|
||||||
// 2. Modülü bu context içinde oluştur
|
|
||||||
LLVMModuleRef mod = LLVMModuleCreateWithNameInContext("saqut_module", context);
|
|
||||||
|
|
||||||
// 3. Basit bir fonksiyon tipi oluştur: int32 f()
|
|
||||||
LLVMTypeRef ret_type = LLVMInt32TypeInContext(context);
|
|
||||||
LLVMTypeRef func_type = LLVMFunctionType(ret_type, NULL, 0, 0);
|
|
||||||
|
|
||||||
// 4. Fonksiyonu modüle ekle
|
|
||||||
LLVMValueRef main_func = LLVMAddFunction(mod, "saqut_main", func_type);
|
|
||||||
|
|
||||||
// 5. Temel bir blok (Entry block) ekle
|
|
||||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context, main_func, "entry");
|
|
||||||
|
|
||||||
// 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));
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
34
Parsing1.cpp
34
Parsing1.cpp
|
|
@ -1,34 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "./core/Tokenizer.cpp"
|
|
||||||
#include "./core/Parser/Parser.cpp"
|
|
||||||
#include "./core/IR/IR.cpp"
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
std::ifstream dosyaOku("source.sqt", std::ios::in | std::ios::binary);
|
|
||||||
std::string icerik;
|
|
||||||
|
|
||||||
if (dosyaOku.is_open()) {
|
|
||||||
std::stringstream buffer;
|
|
||||||
buffer << dosyaOku.rdbuf(); // Dosya içeriğini buffer'a boşalt
|
|
||||||
icerik = buffer.str();
|
|
||||||
dosyaOku.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
Tokenizer tokenizer;
|
|
||||||
Parser parser;
|
|
||||||
CodeGenerator codeGenerator;
|
|
||||||
|
|
||||||
auto tokens = tokenizer.scan(icerik);
|
|
||||||
ASTNode * ast = parser.parse(tokens);
|
|
||||||
|
|
||||||
codeGenerator.parse(ast);
|
|
||||||
|
|
||||||
codeGenerator.IROpDatas;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
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,17 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# saQut Compiler — build script
|
||||||
|
# Derleme: g++ src/main.cpp -Isrc -o saqut
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== saQut Compiler Build ==="
|
||||||
|
|
||||||
|
g++ src/main.cpp \
|
||||||
|
-Isrc \
|
||||||
|
-std=c++17 \
|
||||||
|
-Wall -Wextra \
|
||||||
|
-O0 -g \
|
||||||
|
-o saqut
|
||||||
|
|
||||||
|
echo "Derleme başarılı: ./saqut"
|
||||||
|
echo "Çalıştırmak için: ./saqut"
|
||||||
133
core/IR/IR.cpp
133
core/IR/IR.cpp
|
|
@ -1,133 +0,0 @@
|
||||||
#include "../Parser/ASTNode.cpp"
|
|
||||||
#include "../Tokenizer.cpp"
|
|
||||||
#include <vector>
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#ifndef IR
|
|
||||||
#define IR
|
|
||||||
|
|
||||||
enum class OPCode {
|
|
||||||
// İşlem
|
|
||||||
mathadd,
|
|
||||||
mathsub,
|
|
||||||
mathdiv,
|
|
||||||
mathmul,
|
|
||||||
// Tanımalama
|
|
||||||
declare
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Param {
|
|
||||||
bool isRegister;
|
|
||||||
std::variant<int,float> value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IROpData {
|
|
||||||
OPCode op;
|
|
||||||
int targetReg;
|
|
||||||
Param arg1;
|
|
||||||
Param arg2;
|
|
||||||
Param arg3;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Identifier
|
|
||||||
{
|
|
||||||
int last = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class CodeGenerator
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void * processNumber(NumberToken * num, const std::string& rawStr) {
|
|
||||||
if (num->isFloat || num->hasEpsilon) {
|
|
||||||
return new float(std::strtof(rawStr.c_str(), nullptr));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return new int(std::strtol(rawStr.c_str(), nullptr, num->base));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
CodeGenerator()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
Identifier identifier;
|
|
||||||
std::vector<IROpData> IROpDatas;
|
|
||||||
int parse(ASTNode * ast)
|
|
||||||
{
|
|
||||||
switch (ast->kind)
|
|
||||||
{
|
|
||||||
case ASTKind::BinaryExpression:{
|
|
||||||
return this->parseBinaryExpression((BinaryExpressionNode *) ast);
|
|
||||||
}
|
|
||||||
case ASTKind::Literal:{
|
|
||||||
return this->parseLiteral((LiteralNode *) ast);
|
|
||||||
}
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
int parseBinaryExpression(BinaryExpressionNode * binaryAST)
|
|
||||||
{
|
|
||||||
OPCode op;
|
|
||||||
switch (binaryAST->Operator)
|
|
||||||
{
|
|
||||||
case TokenType::STAR:{
|
|
||||||
op = OPCode::mathmul;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TokenType::PLUS:{
|
|
||||||
op = OPCode::mathadd;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TokenType::MINUS:{
|
|
||||||
op = OPCode::mathsub;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TokenType::SLASH:{
|
|
||||||
op = OPCode::mathdiv;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int left = this->parse(binaryAST->Left);
|
|
||||||
int right = this->parse(binaryAST->Right);
|
|
||||||
|
|
||||||
IROpDatas.push_back({
|
|
||||||
op,
|
|
||||||
++identifier.last,
|
|
||||||
{true, left},
|
|
||||||
{true, right},
|
|
||||||
{false, 0}
|
|
||||||
});
|
|
||||||
return identifier.last;
|
|
||||||
}
|
|
||||||
int parseLiteral(LiteralNode * binaryAST)
|
|
||||||
{
|
|
||||||
LiteralNode literal = *binaryAST;
|
|
||||||
NumberToken * num = (NumberToken *) &literal.parserToken.token;
|
|
||||||
|
|
||||||
|
|
||||||
if(num->isFloat)
|
|
||||||
{
|
|
||||||
float * _value = (float *) this->processNumber(num, num->token);
|
|
||||||
IROpDatas.push_back({
|
|
||||||
OPCode::declare,
|
|
||||||
++identifier.last,
|
|
||||||
{false, *_value},
|
|
||||||
{false, 0},
|
|
||||||
{false, 0}
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
int * _value = (int *) this->processNumber(num, num->token);
|
|
||||||
IROpDatas.push_back({
|
|
||||||
OPCode::declare,
|
|
||||||
++identifier.last,
|
|
||||||
{false, *_value},
|
|
||||||
{false, 0},
|
|
||||||
{false, 0}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return identifier.last;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
425
core/Lexer.cpp
425
core/Lexer.cpp
|
|
@ -1,425 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef LEXER
|
|
||||||
#define LEXER
|
|
||||||
struct INumber {
|
|
||||||
int start = 0;
|
|
||||||
int end = 0;
|
|
||||||
std::string token;
|
|
||||||
bool isFloat = false;
|
|
||||||
bool hasEpsilon = false;
|
|
||||||
int base = 10;
|
|
||||||
bool positive = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Lexer {
|
|
||||||
public:
|
|
||||||
std::string input = "";
|
|
||||||
int size = 0;
|
|
||||||
int offset = 0;
|
|
||||||
std::vector<int> offsetMap;
|
|
||||||
void beginPosition();
|
|
||||||
int getLastPosition();
|
|
||||||
void acceptPosition();
|
|
||||||
void setLastPosition(int);
|
|
||||||
bool isEnd();
|
|
||||||
void rejectPosition();
|
|
||||||
int * positionRange();
|
|
||||||
std::string getPositionRange();
|
|
||||||
bool include(std::string,bool);
|
|
||||||
int getOffset();
|
|
||||||
int setOffset(int);
|
|
||||||
char getchar(int);
|
|
||||||
char getchar();
|
|
||||||
void nextChar();
|
|
||||||
void toChar(int);
|
|
||||||
void setText(std::string);
|
|
||||||
void skipWhiteSpace();
|
|
||||||
bool isNumeric();
|
|
||||||
INumber readNumeric();
|
|
||||||
};
|
|
||||||
|
|
||||||
void Lexer::beginPosition()
|
|
||||||
{
|
|
||||||
this->offsetMap.push_back(this->getLastPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int Lexer::getLastPosition()
|
|
||||||
{
|
|
||||||
if(this->offsetMap.size() == 0)
|
|
||||||
{
|
|
||||||
return this->offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return this->offsetMap[this->offsetMap.size() - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Lexer::acceptPosition()
|
|
||||||
{
|
|
||||||
int T = this->offsetMap[this->offsetMap.size() - 1];
|
|
||||||
this->setLastPosition(T);
|
|
||||||
}
|
|
||||||
void Lexer::setLastPosition(int n)
|
|
||||||
{
|
|
||||||
if(this->offsetMap.size() == 0)
|
|
||||||
{
|
|
||||||
this->offset = n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->offsetMap[this->offsetMap.size() - 1] = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool Lexer::isEnd()
|
|
||||||
{
|
|
||||||
bool result = this->size <= this->getOffset();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
void Lexer::rejectPosition()
|
|
||||||
{
|
|
||||||
this->offsetMap.pop_back();
|
|
||||||
}
|
|
||||||
int * Lexer::positionRange()
|
|
||||||
{
|
|
||||||
int len = this->offsetMap.size();
|
|
||||||
if(len == 0)
|
|
||||||
{
|
|
||||||
return new int[2]{0, this->offset};
|
|
||||||
}
|
|
||||||
else if(len == 1)
|
|
||||||
{
|
|
||||||
return new int[2]{
|
|
||||||
this->offset,
|
|
||||||
this->offsetMap[len - 1]
|
|
||||||
};
|
|
||||||
}else{
|
|
||||||
return new int[2]{
|
|
||||||
this->offsetMap[len - 2],
|
|
||||||
this->offsetMap[len - 1]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::string Lexer::getPositionRange()
|
|
||||||
{
|
|
||||||
int *A = this->positionRange();
|
|
||||||
std::string mem;
|
|
||||||
|
|
||||||
for (int i = A[0]; i < A[1];i++)
|
|
||||||
{
|
|
||||||
mem.push_back(this->input.at(i));
|
|
||||||
}
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Lexer::include(std::string word,bool accept = true)
|
|
||||||
{
|
|
||||||
this->beginPosition();
|
|
||||||
for (int i = 0; i < word.size(); i++)
|
|
||||||
{
|
|
||||||
if(this->isEnd())
|
|
||||||
{
|
|
||||||
if(word.size() == i)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
this->rejectPosition();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(word.at(i) != this->getchar())
|
|
||||||
{
|
|
||||||
this->rejectPosition();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this->nextChar();
|
|
||||||
}
|
|
||||||
if(accept)
|
|
||||||
{
|
|
||||||
this->acceptPosition();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->rejectPosition();
|
|
||||||
};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int Lexer::getOffset()
|
|
||||||
{
|
|
||||||
return this->getLastPosition();
|
|
||||||
}
|
|
||||||
int Lexer::setOffset(int n)
|
|
||||||
{
|
|
||||||
this->setLastPosition(n);
|
|
||||||
return this->getLastPosition();
|
|
||||||
}
|
|
||||||
char Lexer::getchar(int additionalOffset)
|
|
||||||
{
|
|
||||||
int target = this->getOffset() + additionalOffset;
|
|
||||||
if(this->size - 1 < target)
|
|
||||||
{
|
|
||||||
std::cerr << "Hata yanlış erişim\n";
|
|
||||||
return '\0';
|
|
||||||
}else{
|
|
||||||
return this->input.at(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char Lexer::getchar()
|
|
||||||
{
|
|
||||||
int target = this->getOffset();
|
|
||||||
if(this->size - 1 < target)
|
|
||||||
{
|
|
||||||
std::cerr << "Hata yanlış erişim\n";
|
|
||||||
return '\0';
|
|
||||||
}else{
|
|
||||||
return this->input.at(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Lexer::nextChar()
|
|
||||||
{
|
|
||||||
if(this->isEnd() == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
this->setOffset(this->getOffset() + 1);
|
|
||||||
}
|
|
||||||
void Lexer::toChar(int n)
|
|
||||||
{
|
|
||||||
if(this->isEnd() == true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
this->setOffset(this->getOffset() + n);
|
|
||||||
}
|
|
||||||
void Lexer::setText(std::string input) {
|
|
||||||
this->input = input;
|
|
||||||
this->size = input.length();
|
|
||||||
}
|
|
||||||
void Lexer::skipWhiteSpace()
|
|
||||||
{
|
|
||||||
while(this->isEnd() == false)
|
|
||||||
{
|
|
||||||
switch(this->getchar())
|
|
||||||
{
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case '\b':
|
|
||||||
case '\t':
|
|
||||||
case ' ':{
|
|
||||||
this->nextChar();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Lexer::isNumeric()
|
|
||||||
{
|
|
||||||
char c = this->getchar();
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INumber Lexer::readNumeric()
|
|
||||||
{
|
|
||||||
INumber numberToken;
|
|
||||||
numberToken.start = this->getLastPosition();
|
|
||||||
if(this->getchar() == '-')
|
|
||||||
{
|
|
||||||
this->nextChar();
|
|
||||||
numberToken.positive = false;
|
|
||||||
}else if(this->getchar() == '+'){
|
|
||||||
this->nextChar();
|
|
||||||
numberToken.positive = true;
|
|
||||||
}else{
|
|
||||||
numberToken.positive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nextDot = false;
|
|
||||||
if(this->getchar() == '0')
|
|
||||||
{
|
|
||||||
numberToken.token.push_back('0');
|
|
||||||
this->nextChar();
|
|
||||||
char c = this->getchar();
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case 'x':{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
numberToken.base = 16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'b':{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
numberToken.base = 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
if(c != '.')
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
numberToken.base = 8;
|
|
||||||
}else{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
numberToken.base = 10;
|
|
||||||
nextDot = true;
|
|
||||||
numberToken.isFloat = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->nextChar();
|
|
||||||
}else{
|
|
||||||
numberToken.base = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while(this->isEnd() == false)
|
|
||||||
{
|
|
||||||
char c = this->getchar();
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '0':
|
|
||||||
case '1':{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':{
|
|
||||||
if(numberToken.base >= 8)
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case '8':
|
|
||||||
case '9':{
|
|
||||||
if(numberToken.base >= 10)
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 'a': case 'A':
|
|
||||||
case 'b': case 'B':
|
|
||||||
case 'c': case 'C':
|
|
||||||
case 'd': case 'D':
|
|
||||||
case 'f': case 'F':{
|
|
||||||
if(numberToken.base >= 16)
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case '.':{
|
|
||||||
if(nextDot == false)
|
|
||||||
{
|
|
||||||
if(numberToken.token.size() == 0)
|
|
||||||
{
|
|
||||||
numberToken.token.push_back('0');
|
|
||||||
numberToken.token.push_back('.');
|
|
||||||
}else{
|
|
||||||
numberToken.token.push_back('.');
|
|
||||||
}
|
|
||||||
nextDot = true;
|
|
||||||
numberToken.isFloat = true;
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 'e':case 'E':{
|
|
||||||
if(numberToken.base == 16)
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(numberToken.base == 10)
|
|
||||||
{
|
|
||||||
numberToken.hasEpsilon = true;
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
this->nextChar();
|
|
||||||
c = this->getchar();
|
|
||||||
|
|
||||||
if(c == '+' || c == '-')
|
|
||||||
{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
this->nextChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
while(this->isEnd() == false)
|
|
||||||
{
|
|
||||||
char c = this->getchar();
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':{
|
|
||||||
numberToken.token.push_back(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->nextChar();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->nextChar();
|
|
||||||
}
|
|
||||||
numberToken.end = this->getLastPosition();
|
|
||||||
return numberToken;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
#include <unordered_map>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
#include "../Tokenizer.cpp"
|
|
||||||
#include "./ParserToken.cpp"
|
|
||||||
|
|
||||||
#ifndef AST
|
|
||||||
#define AST
|
|
||||||
|
|
||||||
|
|
||||||
enum class ASTKind
|
|
||||||
{
|
|
||||||
BinaryExpression,
|
|
||||||
Literal
|
|
||||||
};
|
|
||||||
|
|
||||||
class ASTNode
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::vector<ASTNode *> childrens;
|
|
||||||
public:
|
|
||||||
ASTKind kind;
|
|
||||||
ASTNode * parent;
|
|
||||||
virtual void log(int indent)
|
|
||||||
{
|
|
||||||
std::cout << "<Unknown>\n";
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
void addChild(ASTNode * children)
|
|
||||||
{
|
|
||||||
this->childrens.push_back(children);
|
|
||||||
}
|
|
||||||
void setParent(ASTNode * children)
|
|
||||||
{
|
|
||||||
this->parent = children;
|
|
||||||
}
|
|
||||||
virtual ~ASTNode() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class BinaryExpressionNode : public ASTNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BinaryExpressionNode(){
|
|
||||||
this->kind = ASTKind::BinaryExpression;
|
|
||||||
}
|
|
||||||
void log(int indent) override
|
|
||||||
{
|
|
||||||
auto korku = OPERATOR_MAP_STRREV.find(this->Operator);
|
|
||||||
std::cout
|
|
||||||
<< padRight(" ",indent)
|
|
||||||
<< "BinaryExpressionNode "
|
|
||||||
<< OPERATOR_MAP_STRREV.find(this->Operator)->second
|
|
||||||
<< "( "<< OPERATOR_MAP_REV.find(this->Operator)->second << " )"
|
|
||||||
<< "\n";
|
|
||||||
|
|
||||||
this->Right->log(indent + 4);
|
|
||||||
if(this->Left != nullptr) this->Left->log(indent + 4);
|
|
||||||
}
|
|
||||||
ASTNode* Right;
|
|
||||||
TokenType Operator;
|
|
||||||
ASTNode* Left;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class LiteralNode : public ASTNode
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
void log(int indent)
|
|
||||||
{
|
|
||||||
std::cout << padRight(" ",indent) << "LiteralNode {" << this->lexerToken->token << "}\n";
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
Token * lexerToken;
|
|
||||||
ParserToken parserToken;
|
|
||||||
LiteralNode(){
|
|
||||||
this->kind = ASTKind::Literal;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IdentifierNode : public ASTNode
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
ASTKind kind = ASTKind::Literal;
|
|
||||||
void log(int indent)
|
|
||||||
{
|
|
||||||
std::cout << padRight(" ",indent) << "IdentifierNode {" << this->lexerToken->token << "}\n";
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
Token * lexerToken;
|
|
||||||
ParserToken parserToken;
|
|
||||||
};
|
|
||||||
class PostfixNode : public ASTNode
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
ASTKind kind = ASTKind::Literal;
|
|
||||||
void log(int indent)
|
|
||||||
{
|
|
||||||
std::cout
|
|
||||||
<< padRight(" ",indent)
|
|
||||||
<< "Postfix "
|
|
||||||
<< OPERATOR_MAP_STRREV.find(this->Operator)->second
|
|
||||||
<< "( "<< OPERATOR_MAP_REV.find(this->Operator)->second << " )"
|
|
||||||
<< "\n";
|
|
||||||
this->operand->log(indent + 4);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
ASTNode * operand;
|
|
||||||
TokenType Operator;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,318 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <string_view>
|
|
||||||
#include "../Tokenizer.cpp"
|
|
||||||
#include "../Tools.cpp"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string_view>
|
|
||||||
#include "./ParserToken.cpp"
|
|
||||||
#include "./ASTNode.cpp"
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PARSER
|
|
||||||
#define PARSER
|
|
||||||
|
|
||||||
|
|
||||||
class Parser {
|
|
||||||
private:
|
|
||||||
ASTNode astroot;
|
|
||||||
public:
|
|
||||||
TokenList tokens;
|
|
||||||
ASTNode * parse(TokenList tokens);
|
|
||||||
int current = 0;
|
|
||||||
ParserToken currentToken();
|
|
||||||
void nextToken();
|
|
||||||
ParserToken lookehead(uint32_t);
|
|
||||||
ParserToken parseToken(Token *);
|
|
||||||
ParserToken getToken(int);
|
|
||||||
ASTNode * primaryExpression();
|
|
||||||
ASTNode * volumeExpression(uint16_t precedence);
|
|
||||||
ASTNode * volumeNullDominatorExpression();
|
|
||||||
ASTNode * volumeLeftDominatorExpression(ASTNode * left);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ParserToken Parser::parseToken(Token * token){
|
|
||||||
ParserToken pToken;
|
|
||||||
pToken.token = *token;
|
|
||||||
|
|
||||||
if(token->gettype() == "string")
|
|
||||||
{
|
|
||||||
pToken.type = TokenType::STRING;
|
|
||||||
}
|
|
||||||
else if(token->gettype() == "number")
|
|
||||||
{
|
|
||||||
pToken.type = TokenType::NUMBER;
|
|
||||||
}
|
|
||||||
else if(token->gettype() == "operator")
|
|
||||||
{
|
|
||||||
pToken.type = OPERATOR_MAP.find(token->token)->second;
|
|
||||||
}
|
|
||||||
else if(token->gettype() == "delimiter")
|
|
||||||
{
|
|
||||||
pToken.type = OPERATOR_MAP.find(token->token)->second;
|
|
||||||
}
|
|
||||||
else if(token->gettype() == "keyword")
|
|
||||||
{
|
|
||||||
pToken.type = KEYWORD_MAP.find(token->token)->second;
|
|
||||||
}
|
|
||||||
else if(token->gettype() == "identifier")
|
|
||||||
{
|
|
||||||
pToken.type = TokenType::IDENTIFIER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ParserToken Parser::getToken(int offset){
|
|
||||||
if(this->tokens.size() - 1 < this->current + offset)
|
|
||||||
{
|
|
||||||
ParserToken pToken;
|
|
||||||
pToken.type = TokenType::SVR_VOID;
|
|
||||||
return pToken;
|
|
||||||
}
|
|
||||||
return this->parseToken(this->tokens[this->current + offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::nextToken(){
|
|
||||||
if(this->tokens.size() >= this->current + 1)
|
|
||||||
{
|
|
||||||
this->current++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParserToken Parser::lookehead(uint32_t forward){
|
|
||||||
return this->getToken(forward);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParserToken Parser::currentToken(){
|
|
||||||
return this->getToken(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTNode * Parser::parse(TokenList tokens){
|
|
||||||
this->tokens = tokens;
|
|
||||||
return this->primaryExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTNode * Parser::primaryExpression()
|
|
||||||
{
|
|
||||||
auto currentToken = this->currentToken();
|
|
||||||
|
|
||||||
ASTNode * tree = nullptr;
|
|
||||||
if(
|
|
||||||
currentToken.is({
|
|
||||||
TokenType::NUMBER,
|
|
||||||
TokenType::PLUS_PLUS,
|
|
||||||
TokenType::MINUS_MINUS,
|
|
||||||
TokenType::PLUS,
|
|
||||||
TokenType::MINUS,
|
|
||||||
TokenType::BANG,
|
|
||||||
TokenType::TILDE,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
{
|
|
||||||
tree = this->volumeExpression(0);
|
|
||||||
}
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expresssionu tamamen okuyup bitiren kısım burası
|
|
||||||
// Bir expressionda kendi içerisindeki operatörleri işler
|
|
||||||
// Terimler ile ilgilenmez yanlızca ifadelerin önceliğini belirler
|
|
||||||
// Sayılar, fonksionlar, tanımlamalar gibi şeyler burda işlenmez
|
|
||||||
ASTNode * Parser::volumeExpression(uint16_t precedence)
|
|
||||||
{
|
|
||||||
if (this->currentToken().type == TokenType::SVR_VOID)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTNode* left = this->volumeNullDominatorExpression();
|
|
||||||
|
|
||||||
if (!left) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
auto nextToken = this->lookehead(+1);
|
|
||||||
if (nextToken.type == TokenType::RPAREN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nextToken = this->lookehead(+1);
|
|
||||||
if(precedence < nextToken.getPowerOperator())
|
|
||||||
{
|
|
||||||
this->nextToken();
|
|
||||||
left = this->volumeLeftDominatorExpression(left);
|
|
||||||
}else{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terimler burada işlenir tanımlamalar sayılar burada işlenir
|
|
||||||
// işlem önceliği işlenmez
|
|
||||||
// Tek yönlü operatörler !a b++ ++c burada işlenir
|
|
||||||
ASTNode * Parser::volumeNullDominatorExpression()
|
|
||||||
{
|
|
||||||
auto currentToken = this->currentToken();
|
|
||||||
|
|
||||||
if (currentToken.type == TokenType::SVR_VOID) {
|
|
||||||
// Hata: "Beklenmedik dosya sonu, bir değer bekleniyordu!"
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentToken.type == TokenType::RPAREN) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentToken.type == TokenType::LPAREN) {
|
|
||||||
this->nextToken();
|
|
||||||
ASTNode* expr = this->volumeExpression(0);
|
|
||||||
|
|
||||||
this->nextToken();
|
|
||||||
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(currentToken.is({
|
|
||||||
TokenType::PLUS_PLUS,
|
|
||||||
TokenType::MINUS_MINUS,
|
|
||||||
TokenType::PLUS,
|
|
||||||
TokenType::MINUS,
|
|
||||||
TokenType::BANG,
|
|
||||||
TokenType::TILDE,
|
|
||||||
})) {
|
|
||||||
this->nextToken();
|
|
||||||
ASTNode * right = this->volumeExpression(currentToken.getPowerOperator());
|
|
||||||
BinaryExpressionNode * binNode = new BinaryExpressionNode();
|
|
||||||
binNode->Right = right;
|
|
||||||
binNode->Left = nullptr;
|
|
||||||
binNode->Operator = currentToken.type;
|
|
||||||
return binNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
if(currentToken.is(TokenType::NUMBER)) {
|
|
||||||
LiteralNode * lNode = new LiteralNode();
|
|
||||||
lNode->lexerToken = ¤tToken.token;
|
|
||||||
lNode->parserToken = currentToken;
|
|
||||||
return lNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(currentToken.is(TokenType::IDENTIFIER)) {
|
|
||||||
IdentifierNode * iNode = new IdentifierNode();
|
|
||||||
iNode->lexerToken = ¤tToken.token;
|
|
||||||
iNode->parserToken = currentToken;
|
|
||||||
return iNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Çift yönlü matematiksel işlemler burada işlenir
|
|
||||||
// [volume]+[volume] veya [volume] * [volume] gibi terimleri birbirine bağlayarak geri döner
|
|
||||||
ASTNode * Parser::volumeLeftDominatorExpression(ASTNode * left)
|
|
||||||
{
|
|
||||||
auto currentToken = this->currentToken();
|
|
||||||
|
|
||||||
if (currentToken.is({
|
|
||||||
TokenType::PLUS_PLUS,
|
|
||||||
TokenType::MINUS_MINUS
|
|
||||||
})) {
|
|
||||||
this->nextToken();
|
|
||||||
PostfixNode* node = new PostfixNode();
|
|
||||||
node->operand = left;
|
|
||||||
node->Operator = currentToken.type;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t precedence = currentToken.getPowerOperator();
|
|
||||||
this->nextToken();
|
|
||||||
auto right = this->volumeExpression(precedence);
|
|
||||||
|
|
||||||
BinaryExpressionNode * binNode = new BinaryExpressionNode();
|
|
||||||
binNode->Right = right;
|
|
||||||
binNode->Left = left;
|
|
||||||
binNode->Operator = currentToken.type;
|
|
||||||
binNode->Right->parent = binNode;
|
|
||||||
binNode->Left->parent = binNode;
|
|
||||||
return binNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,548 +0,0 @@
|
||||||
#include "../Tokenizer.cpp"
|
|
||||||
#include "../Tools.cpp"
|
|
||||||
#include <cstdint>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <initializer_list>
|
|
||||||
|
|
||||||
#ifndef PARSER_TOKEN
|
|
||||||
#define PARSER_TOKEN
|
|
||||||
|
|
||||||
typedef std::vector<Token *> TokenList;
|
|
||||||
|
|
||||||
enum class TokenType : uint16_t
|
|
||||||
{
|
|
||||||
// --- Değerler ve Tanımlayıcılar ---
|
|
||||||
IDENTIFIER, // değişken/fonksiyon isimleri
|
|
||||||
NUMBER, // 42, 0xFF, 0b1010
|
|
||||||
STRING, // "merhaba"
|
|
||||||
SVR_VOID,
|
|
||||||
|
|
||||||
// --- KEYWORD'ler (Alfabetik) ---
|
|
||||||
KW_IF, // if
|
|
||||||
KW_ELSE, // else
|
|
||||||
KW_FOR, // for
|
|
||||||
KW_WHILE, // while
|
|
||||||
KW_DO, // do
|
|
||||||
KW_SWITCH, // switch
|
|
||||||
KW_CASE, // case
|
|
||||||
KW_DEFAULT, // default
|
|
||||||
KW_BREAK, // break
|
|
||||||
KW_CONTINUE, // continue
|
|
||||||
KW_RETURN, // return
|
|
||||||
KW_CLASS, // class
|
|
||||||
KW_INTERFACE, // interface
|
|
||||||
KW_ENUM, // enum
|
|
||||||
KW_EXTENDS, // extends
|
|
||||||
KW_IMPLEMENTS, // implements
|
|
||||||
KW_NEW, // new
|
|
||||||
KW_PUBLIC, // public
|
|
||||||
KW_PRIVATE, // private
|
|
||||||
KW_PROTECTED, // protected
|
|
||||||
KW_STATIC, // static
|
|
||||||
KW_FINAL, // final
|
|
||||||
KW_ABSTRACT, // abstract
|
|
||||||
KW_VOID, // void
|
|
||||||
KW_BOOL, // bool
|
|
||||||
KW_INT, // int
|
|
||||||
KW_FLOAT_TYPE, // float
|
|
||||||
KW_DOUBLE, // double
|
|
||||||
KW_CHAR, // char
|
|
||||||
KW_STRING_TYPE, // string
|
|
||||||
KW_TRUE, // true
|
|
||||||
KW_FALSE, // false
|
|
||||||
KW_NULL, // null
|
|
||||||
KW_TRY, // try
|
|
||||||
KW_CATCH, // catch
|
|
||||||
KW_FINALLY, // finally
|
|
||||||
KW_THROW, // throw
|
|
||||||
KW_THROWS, // throws
|
|
||||||
KW_ASSERT, // assert
|
|
||||||
KW_IMPORT, // import
|
|
||||||
KW_PACKAGE, // package
|
|
||||||
KW_NATIVE, // native
|
|
||||||
KW_SYNCHRONIZED,// synchronized
|
|
||||||
KW_VOLATILE, // volatile
|
|
||||||
KW_TRANSIENT, // transient
|
|
||||||
KW_CONST, // const (C++ style)
|
|
||||||
KW_EXTERN, // extern
|
|
||||||
KW_TYPEDEF, // typedef
|
|
||||||
KW_SIZEOF, // sizeof
|
|
||||||
KW_ALIGNOF, // alignof
|
|
||||||
KW_DECLTYPE, // decltype
|
|
||||||
KW_AUTO, // auto
|
|
||||||
KW_CONSTEXPR, // constexpr
|
|
||||||
KW_NOEXCEPT, // noexcept
|
|
||||||
|
|
||||||
// --- Operatörler (öncelik sırasına göre) ---
|
|
||||||
|
|
||||||
// Seviye 1: Üye erişimi ve çağrı
|
|
||||||
DOT, // .
|
|
||||||
ARROW, // ->
|
|
||||||
LBRACKET, // [
|
|
||||||
RBRACKET, // ]
|
|
||||||
LPAREN, // (
|
|
||||||
RPAREN, // )
|
|
||||||
|
|
||||||
// Seviye 2: Postfix
|
|
||||||
PLUS_PLUS, // ++ (postfix)
|
|
||||||
MINUS_MINUS, // -- (postfix)
|
|
||||||
|
|
||||||
// Seviye 3: Prefix/Unary
|
|
||||||
PLUS, // + (unary)
|
|
||||||
MINUS, // - (unary)
|
|
||||||
BANG, // ! (logical NOT)
|
|
||||||
TILDE, // ~ (bitwise NOT)
|
|
||||||
|
|
||||||
// Seviye 4: Üs alma
|
|
||||||
STAR_STAR, // ** (Python-style üs)
|
|
||||||
CARET, // ^ (bazı dillerde üs)
|
|
||||||
|
|
||||||
// Seviye 5: Çarpma/bölme
|
|
||||||
STAR, // *
|
|
||||||
SLASH, // /
|
|
||||||
PERCENT, // %
|
|
||||||
|
|
||||||
// Seviye 6: Toplama/çıkarma
|
|
||||||
// PLUS ve MINUS yukarıda var (unary olarak da kullanılır)
|
|
||||||
|
|
||||||
// Seviye 7: Bitsel kaydırma
|
|
||||||
LSHIFT, // <<
|
|
||||||
RSHIFT, // >>
|
|
||||||
|
|
||||||
// Seviye 8: İlişkisel
|
|
||||||
LESS, // <
|
|
||||||
LESS_EQUAL, // <=
|
|
||||||
GREATER, // >
|
|
||||||
GREATER_EQUAL, // >=
|
|
||||||
|
|
||||||
// Seviye 9: Eşitlik
|
|
||||||
EQUAL_EQUAL, // ==
|
|
||||||
BANG_EQUAL, // !=
|
|
||||||
|
|
||||||
// Seviye 10: Bitsel VE
|
|
||||||
AMPERSAND, // &
|
|
||||||
|
|
||||||
// Seviye 11: Bitsel XOR
|
|
||||||
// CARET yukarıda var
|
|
||||||
|
|
||||||
// Seviye 12: Bitsel VEYA
|
|
||||||
PIPE, // |
|
|
||||||
|
|
||||||
// Seviye 13: Mantıksal VE
|
|
||||||
AMPERSAND_AMPERSAND, // &&
|
|
||||||
|
|
||||||
// Seviye 14: Mantıksal VEYA
|
|
||||||
PIPE_PIPE, // ||
|
|
||||||
|
|
||||||
// Seviye 15: Ternary
|
|
||||||
TERNARY, // ?
|
|
||||||
COLON, // : (ternary için)
|
|
||||||
|
|
||||||
// Seviye 16: Atama
|
|
||||||
EQUAL, // =
|
|
||||||
PLUS_EQUAL, // +=
|
|
||||||
MINUS_EQUAL, // -=
|
|
||||||
STAR_EQUAL, // *=
|
|
||||||
SLASH_EQUAL, // /=
|
|
||||||
PERCENT_EQUAL, // %=
|
|
||||||
AMPERSAND_EQUAL,// &=
|
|
||||||
PIPE_EQUAL, // |=
|
|
||||||
CARET_EQUAL, // ^=
|
|
||||||
LSHIFT_EQUAL, // <<=
|
|
||||||
RSHIFT_EQUAL, // >>=
|
|
||||||
|
|
||||||
// --- Diğer Semboller ---
|
|
||||||
LBRACE, // {
|
|
||||||
RBRACE, // }
|
|
||||||
SEMICOLON, // ;
|
|
||||||
COMMA, // ,
|
|
||||||
COLON_COLON, // ::
|
|
||||||
|
|
||||||
// --- Özel ---
|
|
||||||
END_OF_FILE, // Dosya sonu
|
|
||||||
UNKNOWN, // Bilinmeyen karakter
|
|
||||||
COMMENT, // // veya /* */
|
|
||||||
PREPROCESSOR, // #include, #define
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// lexer.cpp - Keyword map ekleyelim
|
|
||||||
static const std::unordered_map<std::string_view, TokenType> KEYWORD_MAP = {
|
|
||||||
// --- Control flow ---
|
|
||||||
{"if", TokenType::KW_IF},
|
|
||||||
{"else", TokenType::KW_ELSE},
|
|
||||||
{"for", TokenType::KW_FOR},
|
|
||||||
{"while", TokenType::KW_WHILE},
|
|
||||||
{"do", TokenType::KW_DO},
|
|
||||||
{"switch", TokenType::KW_SWITCH},
|
|
||||||
{"case", TokenType::KW_CASE},
|
|
||||||
{"default", TokenType::KW_DEFAULT},
|
|
||||||
{"break", TokenType::KW_BREAK},
|
|
||||||
{"continue", TokenType::KW_CONTINUE},
|
|
||||||
{"return", TokenType::KW_RETURN},
|
|
||||||
|
|
||||||
// --- OOP ---
|
|
||||||
{"class", TokenType::KW_CLASS},
|
|
||||||
{"interface", TokenType::KW_INTERFACE},
|
|
||||||
{"enum", TokenType::KW_ENUM},
|
|
||||||
{"extends", TokenType::KW_EXTENDS},
|
|
||||||
{"implements", TokenType::KW_IMPLEMENTS},
|
|
||||||
{"new", TokenType::KW_NEW},
|
|
||||||
|
|
||||||
// --- Access modifiers ---
|
|
||||||
{"public", TokenType::KW_PUBLIC},
|
|
||||||
{"private", TokenType::KW_PRIVATE},
|
|
||||||
{"protected", TokenType::KW_PROTECTED},
|
|
||||||
{"static", TokenType::KW_STATIC},
|
|
||||||
{"final", TokenType::KW_FINAL},
|
|
||||||
{"abstract", TokenType::KW_ABSTRACT},
|
|
||||||
|
|
||||||
// --- Types ---
|
|
||||||
{"void", TokenType::KW_VOID},
|
|
||||||
{"bool", TokenType::KW_BOOL},
|
|
||||||
{"int", TokenType::KW_INT},
|
|
||||||
{"float", TokenType::KW_FLOAT_TYPE},
|
|
||||||
{"double", TokenType::KW_DOUBLE},
|
|
||||||
{"char", TokenType::KW_CHAR},
|
|
||||||
{"string", TokenType::KW_STRING_TYPE},
|
|
||||||
|
|
||||||
// --- Literals ---
|
|
||||||
{"true", TokenType::KW_TRUE},
|
|
||||||
{"false", TokenType::KW_FALSE},
|
|
||||||
{"null", TokenType::KW_NULL},
|
|
||||||
|
|
||||||
// --- Exception handling ---
|
|
||||||
{"try", TokenType::KW_TRY},
|
|
||||||
{"catch", TokenType::KW_CATCH},
|
|
||||||
{"finally", TokenType::KW_FINALLY},
|
|
||||||
{"throw", TokenType::KW_THROW},
|
|
||||||
{"throws", TokenType::KW_THROWS},
|
|
||||||
{"assert", TokenType::KW_ASSERT},
|
|
||||||
|
|
||||||
// --- Modules/packages ---
|
|
||||||
{"import", TokenType::KW_IMPORT},
|
|
||||||
{"package", TokenType::KW_PACKAGE},
|
|
||||||
|
|
||||||
// --- C/C++ specific ---
|
|
||||||
{"const", TokenType::KW_CONST},
|
|
||||||
{"extern", TokenType::KW_EXTERN},
|
|
||||||
{"typedef", TokenType::KW_TYPEDEF},
|
|
||||||
{"sizeof", TokenType::KW_SIZEOF},
|
|
||||||
{"auto", TokenType::KW_AUTO},
|
|
||||||
{"constexpr", TokenType::KW_CONSTEXPR},
|
|
||||||
{"noexcept", TokenType::KW_NOEXCEPT},
|
|
||||||
{"native", TokenType::KW_NATIVE},
|
|
||||||
{"synchronized", TokenType::KW_SYNCHRONIZED},
|
|
||||||
{"volatile", TokenType::KW_VOLATILE},
|
|
||||||
{"transient", TokenType::KW_TRANSIENT},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Operatör string'lerinden TokenType'e map
|
|
||||||
static const std::unordered_map<std::string_view, TokenType> OPERATOR_MAP = {
|
|
||||||
// --- 2 karakterli operatörler (uzun olanlar önce!) ---
|
|
||||||
{"->", TokenType::ARROW},
|
|
||||||
{"::", TokenType::COLON_COLON},
|
|
||||||
{"==", TokenType::EQUAL_EQUAL},
|
|
||||||
{"!=", TokenType::BANG_EQUAL},
|
|
||||||
{"<=", TokenType::LESS_EQUAL},
|
|
||||||
{">=", TokenType::GREATER_EQUAL},
|
|
||||||
{"&&", TokenType::AMPERSAND_AMPERSAND},
|
|
||||||
{"||", TokenType::PIPE_PIPE},
|
|
||||||
{"++", TokenType::PLUS_PLUS},
|
|
||||||
{"--", TokenType::MINUS_MINUS},
|
|
||||||
{"<<", TokenType::LSHIFT},
|
|
||||||
{">>", TokenType::RSHIFT},
|
|
||||||
{"**", TokenType::STAR_STAR},
|
|
||||||
|
|
||||||
// --- Atama operatörleri ---
|
|
||||||
{"+=", TokenType::PLUS_EQUAL},
|
|
||||||
{"-=", TokenType::MINUS_EQUAL},
|
|
||||||
{"*=", TokenType::STAR_EQUAL},
|
|
||||||
{"/=", TokenType::SLASH_EQUAL},
|
|
||||||
{"%=", TokenType::PERCENT_EQUAL},
|
|
||||||
{"&=", TokenType::AMPERSAND_EQUAL},
|
|
||||||
{"|=", TokenType::PIPE_EQUAL},
|
|
||||||
{"^=", TokenType::CARET_EQUAL},
|
|
||||||
{"<<=", TokenType::LSHIFT_EQUAL},
|
|
||||||
{">>=", TokenType::RSHIFT_EQUAL},
|
|
||||||
|
|
||||||
// --- 1 karakterli operatörler ---
|
|
||||||
{"+", TokenType::PLUS},
|
|
||||||
{"-", TokenType::MINUS},
|
|
||||||
{"*", TokenType::STAR},
|
|
||||||
{"/", TokenType::SLASH},
|
|
||||||
{"%", TokenType::PERCENT},
|
|
||||||
{"<", TokenType::LESS},
|
|
||||||
{">", TokenType::GREATER},
|
|
||||||
{"^", TokenType::CARET},
|
|
||||||
{"!", TokenType::BANG},
|
|
||||||
{"~", TokenType::TILDE},
|
|
||||||
{"&", TokenType::AMPERSAND},
|
|
||||||
{"|", TokenType::PIPE},
|
|
||||||
{"=", TokenType::EQUAL},
|
|
||||||
|
|
||||||
// --- Delimiter'lar ---
|
|
||||||
{"[", TokenType::LBRACKET},
|
|
||||||
{"]", TokenType::RBRACKET},
|
|
||||||
{"(", TokenType::LPAREN},
|
|
||||||
{")", TokenType::RPAREN},
|
|
||||||
{"{", TokenType::LBRACE},
|
|
||||||
{"}", TokenType::RBRACE},
|
|
||||||
{";", TokenType::SEMICOLON},
|
|
||||||
{",", TokenType::COMMA},
|
|
||||||
{":", TokenType::COLON},
|
|
||||||
{".", TokenType::DOT},
|
|
||||||
{"?", TokenType::TERNARY},
|
|
||||||
};
|
|
||||||
static const std::unordered_map<TokenType,std::string_view> OPERATOR_MAP_REV = {
|
|
||||||
{TokenType::ARROW,"->"},
|
|
||||||
{TokenType::COLON_COLON,"::"},
|
|
||||||
{TokenType::EQUAL_EQUAL,"=="},
|
|
||||||
{TokenType::BANG_EQUAL,"!="},
|
|
||||||
{TokenType::LESS_EQUAL,"<="},
|
|
||||||
{TokenType::GREATER_EQUAL,">="},
|
|
||||||
{TokenType::AMPERSAND_AMPERSAND,"&&"},
|
|
||||||
{TokenType::PIPE_PIPE,"||"},
|
|
||||||
{TokenType::PLUS_PLUS,"++"},
|
|
||||||
{TokenType::MINUS_MINUS,"--"},
|
|
||||||
{TokenType::LSHIFT,"<<"},
|
|
||||||
{TokenType::RSHIFT,">>"},
|
|
||||||
{TokenType::STAR_STAR,"**"},
|
|
||||||
{TokenType::PLUS_EQUAL,"+="},
|
|
||||||
{TokenType::MINUS_EQUAL,"-="},
|
|
||||||
{TokenType::STAR_EQUAL,"*="},
|
|
||||||
{TokenType::SLASH_EQUAL,"/="},
|
|
||||||
{TokenType::PERCENT_EQUAL,"%="},
|
|
||||||
{TokenType::AMPERSAND_EQUAL,"&="},
|
|
||||||
{TokenType::PIPE_EQUAL,"|="},
|
|
||||||
{TokenType::CARET_EQUAL,"^="},
|
|
||||||
{TokenType::LSHIFT_EQUAL,"<<="},
|
|
||||||
{TokenType::RSHIFT_EQUAL,">>="},
|
|
||||||
{TokenType::PLUS,"+"},
|
|
||||||
{TokenType::MINUS,"-"},
|
|
||||||
{TokenType::STAR,"*"},
|
|
||||||
{TokenType::SLASH,"/"},
|
|
||||||
{TokenType::PERCENT,"%"},
|
|
||||||
{TokenType::LESS,"<"},
|
|
||||||
{TokenType::GREATER,">"},
|
|
||||||
{TokenType::CARET,"^"},
|
|
||||||
{TokenType::BANG,"!"},
|
|
||||||
{TokenType::TILDE,"~"},
|
|
||||||
{TokenType::AMPERSAND,"&"},
|
|
||||||
{TokenType::PIPE,"|"},
|
|
||||||
{TokenType::EQUAL,"="},
|
|
||||||
{TokenType::LBRACKET,"["},
|
|
||||||
{TokenType::RBRACKET,"]"},
|
|
||||||
{TokenType::LPAREN,"("},
|
|
||||||
{TokenType::RPAREN,")"},
|
|
||||||
{TokenType::LBRACE,"{"},
|
|
||||||
{TokenType::RBRACE,"}"},
|
|
||||||
{TokenType::SEMICOLON,";"},
|
|
||||||
{TokenType::COMMA,","},
|
|
||||||
{TokenType::COLON,":"},
|
|
||||||
{TokenType::DOT,"."},
|
|
||||||
{TokenType::TERNARY,"?"},
|
|
||||||
};
|
|
||||||
static const std::unordered_map<TokenType,std::string_view> OPERATOR_MAP_STRREV = {
|
|
||||||
{TokenType::ARROW,"ARROW"},
|
|
||||||
{TokenType::COLON_COLON,"COLON_COLON"},
|
|
||||||
{TokenType::EQUAL_EQUAL,"EQUAL_EQUAL"},
|
|
||||||
{TokenType::BANG_EQUAL,"BANG_EQUAL"},
|
|
||||||
{TokenType::LESS_EQUAL,"LESS_EQUAL"},
|
|
||||||
{TokenType::GREATER_EQUAL,"GREATER_EQUAL"},
|
|
||||||
{TokenType::AMPERSAND_AMPERSAND,"AMPERSAND_AMPERSAND"},
|
|
||||||
{TokenType::PIPE_PIPE,"PIPE_PIPE"},
|
|
||||||
{TokenType::PLUS_PLUS,"PLUS_PLUS"},
|
|
||||||
{TokenType::MINUS_MINUS,"MINUS_MINUS"},
|
|
||||||
{TokenType::LSHIFT,"LSHIFT"},
|
|
||||||
{TokenType::RSHIFT,"RSHIFT"},
|
|
||||||
{TokenType::STAR_STAR,"STAR_STAR"},
|
|
||||||
{TokenType::PLUS_EQUAL,"PLUS_EQUAL"},
|
|
||||||
{TokenType::MINUS_EQUAL,"MINUS_EQUAL"},
|
|
||||||
{TokenType::STAR_EQUAL,"STAR_EQUAL"},
|
|
||||||
{TokenType::SLASH_EQUAL,"SLASH_EQUAL"},
|
|
||||||
{TokenType::PERCENT_EQUAL,"PERCENT_EQUAL"},
|
|
||||||
{TokenType::AMPERSAND_EQUAL,"AMPERSAND_EQUAL"},
|
|
||||||
{TokenType::PIPE_EQUAL,"PIPE_EQUAL"},
|
|
||||||
{TokenType::CARET_EQUAL,"CARET_EQUAL"},
|
|
||||||
{TokenType::LSHIFT_EQUAL,"LSHIFT_EQUAL"},
|
|
||||||
{TokenType::RSHIFT_EQUAL,"RSHIFT_EQUAL"},
|
|
||||||
{TokenType::PLUS,"PLUS"},
|
|
||||||
{TokenType::MINUS,"MINUS"},
|
|
||||||
{TokenType::STAR,"STAR"},
|
|
||||||
{TokenType::SLASH,"SLASH"},
|
|
||||||
{TokenType::PERCENT,"PERCENT"},
|
|
||||||
{TokenType::LESS,"LESS"},
|
|
||||||
{TokenType::GREATER,"GREATER"},
|
|
||||||
{TokenType::CARET,"CARET"},
|
|
||||||
{TokenType::BANG,"BANG"},
|
|
||||||
{TokenType::TILDE,"TILDE"},
|
|
||||||
{TokenType::AMPERSAND,"AMPERSAND"},
|
|
||||||
{TokenType::PIPE,"PIPE"},
|
|
||||||
{TokenType::EQUAL,"EQUAL"},
|
|
||||||
{TokenType::LBRACKET,"LBRACKET"},
|
|
||||||
{TokenType::RBRACKET,"RBRACKET"},
|
|
||||||
{TokenType::LPAREN,"LPAREN"},
|
|
||||||
{TokenType::RPAREN,"RPAREN"},
|
|
||||||
{TokenType::LBRACE,"LBRACE"},
|
|
||||||
{TokenType::RBRACE,"RBRACE"},
|
|
||||||
{TokenType::SEMICOLON,"SEMICOLON"},
|
|
||||||
{TokenType::COMMA,"COMMA"},
|
|
||||||
{TokenType::COLON,"COLON"},
|
|
||||||
{TokenType::DOT,"DOT"},
|
|
||||||
{TokenType::TERNARY,"TERNARY"},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t TokenPrecedence(TokenType type) {
|
|
||||||
switch (type) {
|
|
||||||
// Seviye 17: Gruplama/çağrı
|
|
||||||
case TokenType::DOT:
|
|
||||||
case TokenType::ARROW:
|
|
||||||
case TokenType::LBRACKET:
|
|
||||||
case TokenType::LPAREN:
|
|
||||||
return 18;
|
|
||||||
|
|
||||||
// Seviye 16: Postfix
|
|
||||||
case TokenType::PLUS_PLUS:
|
|
||||||
case TokenType::MINUS_MINUS:
|
|
||||||
return 17;
|
|
||||||
|
|
||||||
// Seviye 15: Unary/Prefix
|
|
||||||
case TokenType::BANG: // !
|
|
||||||
case TokenType::TILDE: // ~
|
|
||||||
return 16;
|
|
||||||
|
|
||||||
// Seviye 14: Üs alma
|
|
||||||
case TokenType::STAR_STAR: // **
|
|
||||||
case TokenType::CARET: // ^
|
|
||||||
return 15;
|
|
||||||
|
|
||||||
// Seviye 13: Çarpma/bölme
|
|
||||||
case TokenType::STAR: // *
|
|
||||||
case TokenType::SLASH: // /
|
|
||||||
case TokenType::PERCENT: // %
|
|
||||||
return 14;
|
|
||||||
|
|
||||||
case TokenType::PLUS: // +
|
|
||||||
case TokenType::MINUS: // -
|
|
||||||
return 13;
|
|
||||||
|
|
||||||
// Seviye 11: Bitsel kaydırma
|
|
||||||
case TokenType::LSHIFT: // <<
|
|
||||||
case TokenType::RSHIFT: // >>
|
|
||||||
return 12;
|
|
||||||
|
|
||||||
// Seviye 10: İlişkisel
|
|
||||||
case TokenType::LESS: // <
|
|
||||||
case TokenType::LESS_EQUAL:// <=
|
|
||||||
case TokenType::GREATER: // >
|
|
||||||
case TokenType::GREATER_EQUAL: // >=
|
|
||||||
return 11;
|
|
||||||
|
|
||||||
// Seviye 9: Eşitlik
|
|
||||||
case TokenType::EQUAL_EQUAL: // ==
|
|
||||||
case TokenType::BANG_EQUAL: // !=
|
|
||||||
return 10;
|
|
||||||
|
|
||||||
// Seviye 8: Bitsel VE
|
|
||||||
case TokenType::AMPERSAND: // &
|
|
||||||
return 9;
|
|
||||||
|
|
||||||
// Seviye 7: Bitsel XOR
|
|
||||||
// CARET burada binary XOR olarak
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
// Seviye 6: Bitsel VEYA
|
|
||||||
case TokenType::PIPE: // |
|
|
||||||
return 7;
|
|
||||||
|
|
||||||
// Seviye 5: Mantıksal VE
|
|
||||||
case TokenType::AMPERSAND_AMPERSAND: // &&
|
|
||||||
return 6;
|
|
||||||
|
|
||||||
// Seviye 4: Mantıksal VEYA
|
|
||||||
case TokenType::PIPE_PIPE: // ||
|
|
||||||
return 5;
|
|
||||||
|
|
||||||
// Seviye 3: Ternary (özel işlem)
|
|
||||||
case TokenType::TERNARY: // ?
|
|
||||||
return 4;
|
|
||||||
case TokenType::COLON: // : (ternary için)
|
|
||||||
return 3; // özel değer
|
|
||||||
|
|
||||||
// Seviye 2: Atama
|
|
||||||
case TokenType::EQUAL: // =
|
|
||||||
case TokenType::PLUS_EQUAL:// +=
|
|
||||||
case TokenType::MINUS_EQUAL:// -=
|
|
||||||
case TokenType::STAR_EQUAL:// *=
|
|
||||||
case TokenType::SLASH_EQUAL:// /=
|
|
||||||
case TokenType::PERCENT_EQUAL:// %=
|
|
||||||
case TokenType::AMPERSAND_EQUAL:// &=
|
|
||||||
case TokenType::PIPE_EQUAL:// |=
|
|
||||||
case TokenType::CARET_EQUAL:// ^=
|
|
||||||
case TokenType::LSHIFT_EQUAL:// <<=
|
|
||||||
case TokenType::RSHIFT_EQUAL:// >>=
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
// Seviye 1: Virgül
|
|
||||||
case TokenType::COMMA: // ,
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0; // Önceliksiz
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RightAssociative(TokenType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
// Sağdan sola işleyen operatörler:
|
|
||||||
case TokenType::STAR_STAR: // ** (üs - bazı dillerde)
|
|
||||||
case TokenType::CARET: // ^ (üs)
|
|
||||||
case TokenType::EQUAL: // =
|
|
||||||
case TokenType::PLUS_EQUAL: // +=
|
|
||||||
case TokenType::MINUS_EQUAL:// -=
|
|
||||||
case TokenType::STAR_EQUAL: // *=
|
|
||||||
case TokenType::SLASH_EQUAL:// /=
|
|
||||||
case TokenType::PERCENT_EQUAL:// %=
|
|
||||||
case TokenType::AMPERSAND_EQUAL:// &=
|
|
||||||
case TokenType::PIPE_EQUAL: // |=
|
|
||||||
case TokenType::CARET_EQUAL:// ^=
|
|
||||||
case TokenType::LSHIFT_EQUAL:// <<=
|
|
||||||
case TokenType::RSHIFT_EQUAL:// >>=
|
|
||||||
case TokenType::TERNARY: // ? (ternary)
|
|
||||||
return true;
|
|
||||||
// Soldan sağa işleyenler:
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ParserToken
|
|
||||||
{
|
|
||||||
Token token;
|
|
||||||
TokenType type;
|
|
||||||
bool is(TokenType type){
|
|
||||||
return this->type == type;
|
|
||||||
}
|
|
||||||
bool is(std::initializer_list<TokenType> types){
|
|
||||||
for (TokenType t : types) {
|
|
||||||
if (this->type == t) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint16_t getPowerOperator()
|
|
||||||
{
|
|
||||||
return TokenPrecedence(this->type);
|
|
||||||
}
|
|
||||||
bool isRightAssociative()
|
|
||||||
{
|
|
||||||
return RightAssociative(this->type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,384 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "./Lexer.cpp"
|
|
||||||
|
|
||||||
#ifndef TOKENIZER
|
|
||||||
#define TOKENIZER
|
|
||||||
|
|
||||||
class Token {
|
|
||||||
protected:
|
|
||||||
std::string type = "";
|
|
||||||
public:
|
|
||||||
int start = 0;
|
|
||||||
int end = 0;
|
|
||||||
std::string token;
|
|
||||||
std::string gettype(){
|
|
||||||
return this->type;
|
|
||||||
}
|
|
||||||
virtual ~Token() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StringToken : public Token {
|
|
||||||
public:
|
|
||||||
StringToken(){
|
|
||||||
this->type = "string";
|
|
||||||
};
|
|
||||||
std::string context;
|
|
||||||
int size = 0;
|
|
||||||
};
|
|
||||||
class NumberToken : public Token {
|
|
||||||
public:
|
|
||||||
NumberToken(){
|
|
||||||
this->type = "number";
|
|
||||||
}
|
|
||||||
bool isFloat = false;
|
|
||||||
bool hasEpsilon = false;
|
|
||||||
int base = 10;
|
|
||||||
};
|
|
||||||
class OperatorToken : public Token {
|
|
||||||
public:
|
|
||||||
OperatorToken(){
|
|
||||||
this->type = "operator";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class DelimiterToken : public Token {
|
|
||||||
public:
|
|
||||||
DelimiterToken(){
|
|
||||||
this->type = "delimiter";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class KeywordToken : public Token {
|
|
||||||
public:
|
|
||||||
KeywordToken(){
|
|
||||||
this->type = "keyword";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class IdentifierToken : public Token {
|
|
||||||
public:
|
|
||||||
IdentifierToken(){
|
|
||||||
this->type = "identifier";
|
|
||||||
}
|
|
||||||
std::string context;
|
|
||||||
int size = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const constexpr std::string_view operators[] = {
|
|
||||||
// --- Mantıksal Karşılaştırma ---
|
|
||||||
"==", "!=", "<=", ">=", "&&", "||",
|
|
||||||
|
|
||||||
// --- Aritmetik (Çift Karakterli) ---
|
|
||||||
"++", "--", "<<", ">>",
|
|
||||||
|
|
||||||
// --- Atama Operatörleri ---
|
|
||||||
"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
|
|
||||||
|
|
||||||
// --- Aritmetik (Tek Karakterli) ---
|
|
||||||
"+", "-", "*", "/", "%", "<", ">",
|
|
||||||
|
|
||||||
// --- Bitwise ve Mantıksal (Tek Karakterli) ---
|
|
||||||
"^", "!", "~", "&", "|",
|
|
||||||
|
|
||||||
// --- Temel Atama ---
|
|
||||||
"="
|
|
||||||
};
|
|
||||||
|
|
||||||
const constexpr std::string_view delimiters[] = {
|
|
||||||
// Bağlayıcılar
|
|
||||||
"->",
|
|
||||||
"::",
|
|
||||||
// Sınırlandırıcılar
|
|
||||||
"[",
|
|
||||||
"]",
|
|
||||||
"(",
|
|
||||||
")",
|
|
||||||
"{",
|
|
||||||
"}",
|
|
||||||
// Ayırıcılar
|
|
||||||
";",
|
|
||||||
",",
|
|
||||||
":",
|
|
||||||
// Bağlayıcılar
|
|
||||||
".",
|
|
||||||
};
|
|
||||||
|
|
||||||
const constexpr std::string_view keywords[] = {
|
|
||||||
"implements",
|
|
||||||
"protected",
|
|
||||||
"interface",
|
|
||||||
"continue",
|
|
||||||
"private",
|
|
||||||
"finally",
|
|
||||||
"extends",
|
|
||||||
"default",
|
|
||||||
"throws",
|
|
||||||
"switch",
|
|
||||||
"return",
|
|
||||||
"public",
|
|
||||||
"assert",
|
|
||||||
"false",
|
|
||||||
"while",
|
|
||||||
"throw",
|
|
||||||
"class",
|
|
||||||
"catch",
|
|
||||||
"break",
|
|
||||||
"null",
|
|
||||||
"true",
|
|
||||||
"enum",
|
|
||||||
"else",
|
|
||||||
"case",
|
|
||||||
"new",
|
|
||||||
"try",
|
|
||||||
"for",
|
|
||||||
"if",
|
|
||||||
"do"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Tokenizer {
|
|
||||||
public:
|
|
||||||
Lexer hmx;
|
|
||||||
std::vector<Token *> scan(std::string input);
|
|
||||||
Token * scope();
|
|
||||||
IdentifierToken * readIndetifier();
|
|
||||||
StringToken * readString();
|
|
||||||
void skipOneLineComment();
|
|
||||||
void skipMultiLineComment();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<Token *> Tokenizer::scan(std::string input)
|
|
||||||
{
|
|
||||||
std::vector<Token *> tokens;
|
|
||||||
this->hmx.setText(input);
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
Token * token = this->scope();
|
|
||||||
if(token->token == "EOL")
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tokens.push_back(token);
|
|
||||||
if(this->hmx.isEnd())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
Token * Tokenizer::scope()
|
|
||||||
{
|
|
||||||
this->hmx.skipWhiteSpace();
|
|
||||||
|
|
||||||
// Yorum satırları
|
|
||||||
if(this->hmx.include("//", true))
|
|
||||||
{
|
|
||||||
this->skipOneLineComment();
|
|
||||||
}
|
|
||||||
if(this->hmx.include("/*", true))
|
|
||||||
{
|
|
||||||
this->skipMultiLineComment();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->hmx.isEnd()){
|
|
||||||
Token * token = new Token();
|
|
||||||
token->token = "EOL";
|
|
||||||
return token;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Stringler
|
|
||||||
if(this->hmx.getchar() == '"')
|
|
||||||
{
|
|
||||||
return this->readString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sayılar
|
|
||||||
if(this->hmx.isNumeric())
|
|
||||||
{
|
|
||||||
INumber lem = this->hmx.readNumeric();
|
|
||||||
NumberToken * numberToken = new NumberToken();
|
|
||||||
numberToken->base = lem.base;
|
|
||||||
numberToken->start = lem.start;
|
|
||||||
numberToken->end = lem.end;
|
|
||||||
numberToken->hasEpsilon = lem.hasEpsilon;
|
|
||||||
numberToken->isFloat = lem.isFloat;
|
|
||||||
numberToken->token = lem.token;
|
|
||||||
return numberToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string_view& keys : keywords) {
|
|
||||||
if(this->hmx.include(std::string(keys),false))
|
|
||||||
{
|
|
||||||
KeywordToken * keytoken = new KeywordToken();
|
|
||||||
keytoken->start = this->hmx.getOffset();
|
|
||||||
this->hmx.toChar(+keys.size());
|
|
||||||
keytoken->end = this->hmx.getOffset();
|
|
||||||
keytoken->token = keys;
|
|
||||||
return keytoken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string_view& del : delimiters) {
|
|
||||||
if(this->hmx.include(std::string(del),false))
|
|
||||||
{
|
|
||||||
DelimiterToken * dtoken = new DelimiterToken();;
|
|
||||||
dtoken->start = this->hmx.getOffset();
|
|
||||||
this->hmx.toChar(+del.size());
|
|
||||||
dtoken->end = this->hmx.getOffset();
|
|
||||||
dtoken->token = del;
|
|
||||||
return dtoken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string_view& op : operators) {
|
|
||||||
if(this->hmx.include(std::string(op),false))
|
|
||||||
{
|
|
||||||
OperatorToken* optoken = new OperatorToken();
|
|
||||||
optoken->start = this->hmx.getOffset();
|
|
||||||
this->hmx.toChar(+op.size());
|
|
||||||
optoken->end = this->hmx.getOffset();
|
|
||||||
optoken->token = op;
|
|
||||||
return optoken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->readIndetifier();
|
|
||||||
}
|
|
||||||
IdentifierToken * Tokenizer::readIndetifier()
|
|
||||||
{
|
|
||||||
this->hmx.beginPosition();
|
|
||||||
IdentifierToken * idenditifierToken = new IdentifierToken();
|
|
||||||
idenditifierToken->start = this->hmx.getOffset();
|
|
||||||
|
|
||||||
while(this->hmx.isEnd() == false)
|
|
||||||
{
|
|
||||||
bool readed = false;
|
|
||||||
char c = this->hmx.getchar();
|
|
||||||
|
|
||||||
if(c >= 'a' && c <= 'z')
|
|
||||||
{
|
|
||||||
readed = true;
|
|
||||||
idenditifierToken->token.push_back(c);
|
|
||||||
this->hmx.nextChar();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c >= 'A' && c <= 'Z')
|
|
||||||
{
|
|
||||||
readed = true;
|
|
||||||
idenditifierToken->token.push_back(c);
|
|
||||||
this->hmx.nextChar();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(c >= '0' && c <= '9')
|
|
||||||
{
|
|
||||||
readed = true;
|
|
||||||
idenditifierToken->token.push_back(c);
|
|
||||||
this->hmx.nextChar();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '_':{
|
|
||||||
readed = true;
|
|
||||||
idenditifierToken->token.push_back(c);
|
|
||||||
this->hmx.nextChar();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '$':{
|
|
||||||
readed = true;
|
|
||||||
idenditifierToken->token.push_back(c);
|
|
||||||
this->hmx.nextChar();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(readed == false)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
idenditifierToken->end = this->hmx.getOffset();
|
|
||||||
idenditifierToken->size = idenditifierToken->context.size();
|
|
||||||
this->hmx.acceptPosition();
|
|
||||||
return idenditifierToken;
|
|
||||||
}
|
|
||||||
StringToken * Tokenizer::readString()
|
|
||||||
{
|
|
||||||
this->hmx.beginPosition();
|
|
||||||
StringToken * stringToken = new StringToken();
|
|
||||||
bool started = false;
|
|
||||||
bool isended = false;
|
|
||||||
stringToken->start = this->hmx.getOffset();
|
|
||||||
|
|
||||||
while(this->hmx.isEnd() == false)
|
|
||||||
{
|
|
||||||
char c = this->hmx.getchar();
|
|
||||||
stringToken->token.push_back(c);
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '"':{
|
|
||||||
if(started == false)
|
|
||||||
{
|
|
||||||
started = true;
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
isended = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case '\\':{
|
|
||||||
this->hmx.nextChar();
|
|
||||||
c = this->hmx.getchar();
|
|
||||||
stringToken->token.push_back(c);
|
|
||||||
stringToken->context.push_back(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:{
|
|
||||||
stringToken->context.push_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->hmx.nextChar();
|
|
||||||
if(isended)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stringToken->end = this->hmx.getOffset();
|
|
||||||
stringToken->size = stringToken->context.size();
|
|
||||||
this->hmx.acceptPosition();
|
|
||||||
return stringToken;
|
|
||||||
}
|
|
||||||
void Tokenizer::skipOneLineComment()
|
|
||||||
{
|
|
||||||
while(this->hmx.isEnd() == false)
|
|
||||||
{
|
|
||||||
if(this->hmx.getchar() == '\n')
|
|
||||||
{
|
|
||||||
this->hmx.nextChar();
|
|
||||||
this->hmx.skipWhiteSpace();
|
|
||||||
return;
|
|
||||||
}else{
|
|
||||||
this->hmx.nextChar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Tokenizer::skipMultiLineComment()
|
|
||||||
{
|
|
||||||
while(this->hmx.isEnd() == false)
|
|
||||||
{
|
|
||||||
if(this->hmx.include("*/",true))
|
|
||||||
{
|
|
||||||
this->hmx.skipWhiteSpace();
|
|
||||||
return;
|
|
||||||
}else{
|
|
||||||
this->hmx.nextChar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
/*==-- 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 */
|
|
||||||
|
|
||||||
|
|
@ -1,174 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
||||||
|
|
@ -1,379 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
@ -1,296 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
||||||
|
|
@ -1,619 +0,0 @@
|
||||||
/*==-- 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 */
|
|
||||||
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
/*===- 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
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
/*===-- 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
|
|
@ -1,53 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
/*===-- 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
|
|
||||||
|
|
@ -1,184 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,228 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
//===-- 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
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
//===-- 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
|
|
||||||
|
|
@ -1,935 +0,0 @@
|
||||||
//===-- 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
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,780 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,296 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
//===--- 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
|
|
@ -1,37 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,616 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,202 +0,0 @@
|
||||||
//===--- 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
|
|
@ -1,157 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,614 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,410 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,294 +0,0 @@
|
||||||
//==--- 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
|
|
@ -1,278 +0,0 @@
|
||||||
//==--- 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
|
|
@ -1,32 +0,0 @@
|
||||||
//==--- 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
|
|
||||||
|
|
@ -1,858 +0,0 @@
|
||||||
/*===- 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
//==--- 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
|
|
||||||
|
|
@ -1,737 +0,0 @@
|
||||||
/*===- 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,430 +0,0 @@
|
||||||
//===--- 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
|
|
@ -1,141 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,251 +0,0 @@
|
||||||
/*===- 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
|
|
@ -1,75 +0,0 @@
|
||||||
//===- 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
|
|
@ -1,129 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,344 +0,0 @@
|
||||||
//===-- 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
|
|
||||||
|
|
@ -1,390 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
//===-- 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
|
|
||||||
|
|
@ -1,689 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,260 +0,0 @@
|
||||||
//===--- 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
|
|
@ -1,54 +0,0 @@
|
||||||
//===--- 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
|
|
@ -1,211 +0,0 @@
|
||||||
/*===- 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)
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
||||||
|
|
@ -1,816 +0,0 @@
|
||||||
/*===- 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,264 +0,0 @@
|
||||||
/*===- 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
/*===- 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,366 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
||||||
/*===- 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
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,255 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,229 +0,0 @@
|
||||||
//===- 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
|
|
||||||
|
|
@ -1,213 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
//===--- 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
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue