From bb5aae1cf55c89623cde4d6b73f62c874fe0a67a Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Thu, 20 Feb 2025 16:31:42 +0100 Subject: [PATCH 1/3] Node Visitor WIP --- src/Core/Diagnostics.cs | 4 +- src/CppParser/AST.cpp | 2254 ++++++++++++------------ src/CppParser/ASTNodeVisitor.cpp | 2352 ++++++++++++++++++++++++++ src/CppParser/ASTNodeVisitor.h | 545 ++++++ src/CppParser/Decl.h | 54 +- src/CppParser/Parser.cpp | 35 +- src/CppParser/Parser.h | 12 +- src/CppParser/ParserGen/ParserGen.cs | 2 + src/CppParser/Types.h | 618 +++---- src/Generator.Tests/GeneratorTest.cs | 1 + 10 files changed, 4392 insertions(+), 1485 deletions(-) create mode 100644 src/CppParser/ASTNodeVisitor.cpp create mode 100644 src/CppParser/ASTNodeVisitor.h diff --git a/src/Core/Diagnostics.cs b/src/Core/Diagnostics.cs index a7f40ac6c2..a5bf538e4e 100644 --- a/src/Core/Diagnostics.cs +++ b/src/Core/Diagnostics.cs @@ -128,7 +128,9 @@ public void Emit(DiagnosticInfo info) { Console.WriteLine(message); } - Debug.WriteLine(message); + + // Super slow, don't use this for now + // Debug.WriteLine(message); } public void PushIndent(int level) diff --git a/src/CppParser/AST.cpp b/src/CppParser/AST.cpp index e5823a23b2..27e1c27800 100644 --- a/src/CppParser/AST.cpp +++ b/src/CppParser/AST.cpp @@ -11,58 +11,61 @@ #include #include -// copy from widenPath ('llvm/lib/Support/Windows/Path.inc') -static std::string normalizePath(const std::string& File) -{ - llvm::SmallString<2 * 128> Result; - - for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(File), - E = llvm::sys::path::end(File); - I != E; ++I) +namespace CppSharp::CppParser::AST { +namespace { + // Adapted from widenPath ('llvm/lib/Support/Windows/Path.inc') + std::string normalizePath(const std::string_view& file) { - if (I->size() == 1 && *I == ".") - continue; - if (I->size() == 2 && *I == "..") - llvm::sys::path::remove_filename(Result); - else - llvm::sys::path::append(Result, *I); - } + llvm::SmallString<2 * 128> Result; + + for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(file), + E = llvm::sys::path::end(file); + I != E; ++I) + { + if (I->size() == 1 && *I == ".") + continue; + + if (I->size() == 2 && *I == "..") + llvm::sys::path::remove_filename(Result); + else + llvm::sys::path::append(Result, *I); + } #ifdef _WIN32 - // Clean up the file path. - std::replace(Result.begin(), Result.end(), '/', '\\'); + // Clean up the file path. + std::replace(Result.begin(), Result.end(), '/', '\\'); #endif - return Result.c_str(); -} + return Result.c_str(); + } -template -static std::vector split(const T& str, const T& delimiters) -{ - std::vector v; - if (str.length() == 0) + std::vector split(const std::string_view& str, const std::string_view& delimiters) { - v.push_back(str); + std::vector v; + if (str.empty()) + { + v.emplace_back(str); + return v; + } + + std::string_view::size_type start = 0; + auto pos = str.find_first_of(delimiters, start); + while (pos != std::string_view::npos) + { + if (pos != start) // ignore empty tokens + v.emplace_back(str.substr(start, pos - start)); + + start = pos + 1; + pos = str.find_first_of(delimiters, start); + } + + if (start < str.length()) // Ignore trailing delimiter + v.emplace_back(str.substr(start, str.length() - start)); // Add what's left of the string + return v; } - typename T::size_type start = 0; - auto pos = str.find_first_of(delimiters, start); - while (pos != T::npos) - { - if (pos != start) // ignore empty tokens - v.emplace_back(str, start, pos - start); - start = pos + 1; - pos = str.find_first_of(delimiters, start); - } - if (start < str.length()) // ignore trailing delimiter - // add what's left of the string - v.emplace_back(str, start, str.length() - start); - return v; -} - -namespace CppSharp { namespace CppParser { namespace AST { - static void deleteExpression(ExpressionObsolete* expression) + void deleteExpression(ExpressionObsolete* expression) { if (expression) { @@ -84,1373 +87,1364 @@ namespace CppSharp { namespace CppParser { namespace AST { } } } +} // namespace - Type::Type(TypeKind kind) - : kind(kind) - { - } - Type::Type(const Type& rhs) - : kind(rhs.kind) - , isDependent(rhs.isDependent) - { - } +Type::Type(TypeKind kind) + : kind(kind) +{ +} +Type::Type(const Type& rhs) + : kind(rhs.kind) + , isDependent(rhs.isDependent) +{ +} - QualifiedType::QualifiedType() - : type(0) - { - } +QualifiedType::QualifiedType() {} - TagType::TagType() - : Type(TypeKind::Tag) - { - } +TagType::TagType() + : Type(TypeKind::Tag) +{ +} - ArrayType::ArrayType() - : Type(TypeKind::Array) - , size(0) - , elementSize(0) - { - } +ArrayType::ArrayType() + : Type(TypeKind::Array) + , size(0) + , elementSize(0) +{ +} - FunctionType::FunctionType() - : Type(TypeKind::Function) - , callingConvention(CallingConvention::Default) - , exceptionSpecType(ExceptionSpecType::None) - { - } +FunctionType::FunctionType() + : Type(TypeKind::Function) + , callingConvention(CallingConvention::Default) + , exceptionSpecType(ExceptionSpecType::None) +{ +} - FunctionType::~FunctionType() {} +FunctionType::~FunctionType() {} - DEF_VECTOR(FunctionType, Parameter*, Parameters) +DEF_VECTOR(FunctionType, Parameter*, Parameters) - PointerType::PointerType() - : Type(TypeKind::Pointer) - { - } +PointerType::PointerType() + : Type(TypeKind::Pointer) +{ +} - MemberPointerType::MemberPointerType() - : Type(TypeKind::MemberPointer) - { - } +MemberPointerType::MemberPointerType() + : Type(TypeKind::MemberPointer) +{ +} - TypedefType::TypedefType() - : Type(TypeKind::Typedef) - , declaration(0) - { - } +TypedefType::TypedefType() + : Type(TypeKind::Typedef) + , declaration(nullptr) +{ +} - AttributedType::AttributedType() - : Type(TypeKind::Attributed) - { - } +AttributedType::AttributedType() + : Type(TypeKind::Attributed) +{ +} - DecayedType::DecayedType() - : Type(TypeKind::Decayed) - { - } +DecayedType::DecayedType() + : Type(TypeKind::Decayed) +{ +} - // Template - TemplateParameter::TemplateParameter(DeclarationKind kind) - : Declaration(kind) - , depth(0) - , index(0) - , isParameterPack(false) - { - } +// Template +TemplateParameter::TemplateParameter(DeclarationKind kind) + : Declaration(kind) + , depth(0) + , index(0) + , isParameterPack(false) +{ +} - TemplateParameter::~TemplateParameter() - { - } +TemplateParameter::~TemplateParameter() +{ +} - TemplateTemplateParameter::TemplateTemplateParameter() - : Template(DeclarationKind::TemplateTemplateParm) - , isParameterPack(false) - , isPackExpansion(false) - , isExpandedParameterPack(false) - { - } +TemplateTemplateParameter::TemplateTemplateParameter() + : Template(DeclarationKind::TemplateTemplateParm) + , isParameterPack(false) + , isPackExpansion(false) + , isExpandedParameterPack(false) +{ +} - TemplateTemplateParameter::~TemplateTemplateParameter() - { - } +TemplateTemplateParameter::~TemplateTemplateParameter() +{ +} - // TemplateParameter - TypeTemplateParameter::TypeTemplateParameter() - : TemplateParameter(DeclarationKind::TemplateTypeParm) - { - } +// TemplateParameter +TypeTemplateParameter::TypeTemplateParameter() + : TemplateParameter(DeclarationKind::TemplateTypeParm) +{ +} - TypeTemplateParameter::TypeTemplateParameter(const TypeTemplateParameter& rhs) - : TemplateParameter(rhs.kind) - , defaultArgument(rhs.defaultArgument) - { - } +TypeTemplateParameter::TypeTemplateParameter(const TypeTemplateParameter& rhs) + : TemplateParameter(rhs.kind) + , defaultArgument(rhs.defaultArgument) +{ +} - TypeTemplateParameter::~TypeTemplateParameter() {} +TypeTemplateParameter::~TypeTemplateParameter() {} - NonTypeTemplateParameter::NonTypeTemplateParameter() - : TemplateParameter(DeclarationKind::NonTypeTemplateParm) - , defaultArgument(0) - , position(0) - , isPackExpansion(false) - , isExpandedParameterPack(false) - { - } +NonTypeTemplateParameter::NonTypeTemplateParameter() + : TemplateParameter(DeclarationKind::NonTypeTemplateParm) + , defaultArgument(nullptr) + , position(0) + , isPackExpansion(false) + , isExpandedParameterPack(false) +{ +} - NonTypeTemplateParameter::NonTypeTemplateParameter(const NonTypeTemplateParameter& rhs) - : TemplateParameter(rhs.kind) - , defaultArgument(rhs.defaultArgument) - , position(rhs.position) - , isPackExpansion(rhs.isPackExpansion) - , isExpandedParameterPack(rhs.isExpandedParameterPack) - , type(rhs.type) - { - } +NonTypeTemplateParameter::NonTypeTemplateParameter(const NonTypeTemplateParameter& rhs) + : TemplateParameter(rhs.kind) + , defaultArgument(rhs.defaultArgument) + , position(rhs.position) + , isPackExpansion(rhs.isPackExpansion) + , isExpandedParameterPack(rhs.isExpandedParameterPack) + , type(rhs.type) +{ +} - NonTypeTemplateParameter::~NonTypeTemplateParameter() - { - deleteExpression(defaultArgument); - } +NonTypeTemplateParameter::~NonTypeTemplateParameter() +{ + deleteExpression(defaultArgument); +} - TemplateArgument::TemplateArgument() - : declaration(0) - , integral(0) - { - } +TemplateArgument::TemplateArgument() + : declaration(nullptr) + , integral(0) +{ +} - TemplateSpecializationType::TemplateSpecializationType() - : Type(TypeKind::TemplateSpecialization) - , _template(0) - { - } +TemplateSpecializationType::TemplateSpecializationType() + : Type(TypeKind::TemplateSpecialization) + , _template(nullptr) +{ +} - TemplateSpecializationType::TemplateSpecializationType( - const TemplateSpecializationType& rhs) - : Type(rhs) - , Arguments(rhs.Arguments) - , _template(rhs._template) - , desugared(rhs.desugared) - { - } +TemplateSpecializationType::TemplateSpecializationType( + const TemplateSpecializationType& rhs) + : Type(rhs) + , Arguments(rhs.Arguments) + , _template(rhs._template) + , desugared(rhs.desugared) +{ +} - TemplateSpecializationType::~TemplateSpecializationType() {} +TemplateSpecializationType::~TemplateSpecializationType() {} - DEF_VECTOR(TemplateSpecializationType, TemplateArgument, Arguments) +DEF_VECTOR(TemplateSpecializationType, TemplateArgument, Arguments) - DependentTemplateSpecializationType::DependentTemplateSpecializationType() - : Type(TypeKind::DependentTemplateSpecialization) - { - } +DependentTemplateSpecializationType::DependentTemplateSpecializationType() + : Type(TypeKind::DependentTemplateSpecialization) +{ +} - DependentTemplateSpecializationType::DependentTemplateSpecializationType( - const DependentTemplateSpecializationType& rhs) - : Type(rhs) - , Arguments(rhs.Arguments) - , desugared(rhs.desugared) - { - } +DependentTemplateSpecializationType::DependentTemplateSpecializationType( + const DependentTemplateSpecializationType& rhs) + : Type(rhs) + , Arguments(rhs.Arguments) + , desugared(rhs.desugared) +{ +} - DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} +DependentTemplateSpecializationType::~DependentTemplateSpecializationType() {} - DEF_VECTOR(DependentTemplateSpecializationType, TemplateArgument, Arguments) +DEF_VECTOR(DependentTemplateSpecializationType, TemplateArgument, Arguments) - TemplateParameterType::TemplateParameterType() - : Type(TypeKind::TemplateParameter) - , parameter(0) - { - } +TemplateParameterType::TemplateParameterType() + : Type(TypeKind::TemplateParameter) + , parameter(nullptr) +{ +} - TemplateParameterType::~TemplateParameterType() {} +TemplateParameterType::~TemplateParameterType() {} - TemplateParameterSubstitutionType::TemplateParameterSubstitutionType() - : Type(TypeKind::TemplateParameterSubstitution) - , replacedParameter(0) - { - } +TemplateParameterSubstitutionType::TemplateParameterSubstitutionType() + : Type(TypeKind::TemplateParameterSubstitution) + , replacedParameter(nullptr) +{ +} - InjectedClassNameType::InjectedClassNameType() - : Type(TypeKind::InjectedClassName) - , _class(0) - { - } +InjectedClassNameType::InjectedClassNameType() + : Type(TypeKind::InjectedClassName) + , _class(nullptr) +{ +} - DependentNameType::DependentNameType() - : Type(TypeKind::DependentName) - { - } +DependentNameType::DependentNameType() + : Type(TypeKind::DependentName) +{ +} - DependentNameType::~DependentNameType() {} +DependentNameType::~DependentNameType() {} - PackExpansionType::PackExpansionType() - : Type(TypeKind::PackExpansion) - { - } +PackExpansionType::PackExpansionType() + : Type(TypeKind::PackExpansion) +{ +} - UnaryTransformType::UnaryTransformType() - : Type(TypeKind::UnaryTransform) - { - } +UnaryTransformType::UnaryTransformType() + : Type(TypeKind::UnaryTransform) +{ +} - UnresolvedUsingType::UnresolvedUsingType() - : Type(TypeKind::UnresolvedUsing) - { - } +UnresolvedUsingType::UnresolvedUsingType() + : Type(TypeKind::UnresolvedUsing) +{ +} - VectorType::VectorType() - : Type(TypeKind::Vector) - , numElements(0) - { - } +VectorType::VectorType() + : Type(TypeKind::Vector) + , numElements(0) +{ +} - BuiltinType::BuiltinType() - : CppSharp::CppParser::AST::Type(TypeKind::Builtin) - { - } +BuiltinType::BuiltinType() + : Type(TypeKind::Builtin) +{ +} - VTableComponent::VTableComponent() - : offset(0) - , declaration(0) - { - } +VTableComponent::VTableComponent() + : offset(0) + , declaration(nullptr) +{ +} - // VTableLayout - VTableLayout::VTableLayout() {} - VTableLayout::VTableLayout(const VTableLayout& rhs) - : Components(rhs.Components) - { - } - VTableLayout::~VTableLayout() {} +// VTableLayout +VTableLayout::VTableLayout() {} +VTableLayout::VTableLayout(const VTableLayout& rhs) + : Components(rhs.Components) +{ +} +VTableLayout::~VTableLayout() {} - DEF_VECTOR(VTableLayout, VTableComponent, Components) +DEF_VECTOR(VTableLayout, VTableComponent, Components) - VFTableInfo::VFTableInfo() - : VBTableIndex(0) - , VFPtrOffset(0) - , VFPtrFullOffset(0) - { - } - VFTableInfo::VFTableInfo(const VFTableInfo& rhs) - : VBTableIndex(rhs.VBTableIndex) - , VFPtrOffset(rhs.VFPtrOffset) - , VFPtrFullOffset(rhs.VFPtrFullOffset) - , layout(rhs.layout) - { - } +VFTableInfo::VFTableInfo() + : VBTableIndex(0) + , VFPtrOffset(0) + , VFPtrFullOffset(0) +{ +} +VFTableInfo::VFTableInfo(const VFTableInfo& rhs) + : VBTableIndex(rhs.VBTableIndex) + , VFPtrOffset(rhs.VFPtrOffset) + , VFPtrFullOffset(rhs.VFPtrFullOffset) + , layout(rhs.layout) +{ +} - LayoutField::LayoutField() - : offset(0) - , fieldPtr(0) - { - } +LayoutField::LayoutField() + : offset(0) + , fieldPtr(nullptr) +{ +} - LayoutField::LayoutField(const LayoutField& other) - : offset(other.offset) - , name(other.name) - , qualifiedType(other.qualifiedType) - , fieldPtr(other.fieldPtr) - { - } +LayoutField::LayoutField(const LayoutField& other) + : offset(other.offset) + , name(other.name) + , qualifiedType(other.qualifiedType) + , fieldPtr(other.fieldPtr) +{ +} - LayoutField::~LayoutField() {} +LayoutField::~LayoutField() {} - LayoutBase::LayoutBase() - : offset(0) - , _class(0) - { - } +LayoutBase::LayoutBase() + : offset(0) + , _class(nullptr) +{ +} - LayoutBase::LayoutBase(const LayoutBase& other) - : offset(other.offset) - , _class(other._class) - { - } +LayoutBase::LayoutBase(const LayoutBase& other) + : offset(other.offset) + , _class(other._class) +{ +} - LayoutBase::~LayoutBase() {} +LayoutBase::~LayoutBase() {} - ClassLayout::ClassLayout() - : ABI(CppAbi::Itanium) - , argABI(RecordArgABI::Default) - , hasOwnVFPtr(false) - , VBPtrOffset(0) - , alignment(0) - , size(0) - , dataSize(0) - { - } +ClassLayout::ClassLayout() + : ABI(CppAbi::Itanium) + , argABI(RecordArgABI::Default) + , hasOwnVFPtr(false) + , VBPtrOffset(0) + , alignment(0) + , size(0) + , dataSize(0) +{ +} - DEF_VECTOR(ClassLayout, VFTableInfo, VFTables) - - DEF_VECTOR(ClassLayout, LayoutField, Fields) - - DEF_VECTOR(ClassLayout, LayoutBase, Bases) - - Declaration::Declaration(DeclarationKind kind) - : kind(kind) - , access(AccessSpecifier::Public) - , _namespace(0) - , location(0) - , lineNumberStart(0) - , lineNumberEnd(0) - , comment(0) - , isIncomplete(false) - , isDependent(false) - , isImplicit(false) - , isInvalid(false) - , isDeprecated(false) - , completeDeclaration(0) - , definitionOrder(0) - , originalPtr(0) - , alignAs(0) - , maxFieldAlignment(0) - { - } +DEF_VECTOR(ClassLayout, VFTableInfo, VFTables) + +DEF_VECTOR(ClassLayout, LayoutField, Fields) + +DEF_VECTOR(ClassLayout, LayoutBase, Bases) + +Declaration::Declaration(DeclarationKind kind) + : kind(kind) + , access(AccessSpecifier::Public) + , _namespace(nullptr) + , location(0) + , lineNumberStart(0) + , lineNumberEnd(0) + , comment(nullptr) + , isIncomplete(false) + , isDependent(false) + , isImplicit(false) + , isInvalid(false) + , isDeprecated(false) + , completeDeclaration(nullptr) + , definitionOrder(0) + , originalPtr(nullptr) + , alignAs(0) + , maxFieldAlignment(0) +{ +} - Declaration::Declaration(const Declaration& rhs) - : kind(rhs.kind) - , access(rhs.access) - , _namespace(rhs._namespace) - , location(rhs.location.ID) - , lineNumberStart(rhs.lineNumberStart) - , lineNumberEnd(rhs.lineNumberEnd) - , name(rhs.name) - , comment(rhs.comment) - , debugText(rhs.debugText) - , isIncomplete(rhs.isIncomplete) - , isDependent(rhs.isDependent) - , isImplicit(rhs.isImplicit) - , isInvalid(rhs.isInvalid) - , isDeprecated(rhs.isDeprecated) - , completeDeclaration(rhs.completeDeclaration) - , definitionOrder(rhs.definitionOrder) - , PreprocessedEntities(rhs.PreprocessedEntities) - , originalPtr(rhs.originalPtr) - { - } +Declaration::Declaration(const Declaration& rhs) + : kind(rhs.kind) + , access(rhs.access) + , _namespace(rhs._namespace) + , location(rhs.location.ID) + , lineNumberStart(rhs.lineNumberStart) + , lineNumberEnd(rhs.lineNumberEnd) + , name(rhs.name) + , comment(rhs.comment) + , debugText(rhs.debugText) + , isIncomplete(rhs.isIncomplete) + , isDependent(rhs.isDependent) + , isImplicit(rhs.isImplicit) + , isInvalid(rhs.isInvalid) + , isDeprecated(rhs.isDeprecated) + , completeDeclaration(rhs.completeDeclaration) + , definitionOrder(rhs.definitionOrder) + , PreprocessedEntities(rhs.PreprocessedEntities) + , originalPtr(rhs.originalPtr) +{ +} - Declaration::~Declaration() - { - } +Declaration::~Declaration() +{ +} - DEF_VECTOR(Declaration, PreprocessedEntity*, PreprocessedEntities) - DEF_VECTOR(Declaration, Declaration*, Redeclarations) +DEF_VECTOR(Declaration, PreprocessedEntity*, PreprocessedEntities) +DEF_VECTOR(Declaration, Declaration*, Redeclarations) - DeclarationContext::DeclarationContext(DeclarationKind kind) - : Declaration(kind) - , isAnonymous(false) - { - } +DeclarationContext::DeclarationContext(DeclarationKind kind) + : Declaration(kind) + , isAnonymous(false) +{ +} - DEF_VECTOR(DeclarationContext, Namespace*, Namespaces) - DEF_VECTOR(DeclarationContext, Enumeration*, Enums) - DEF_VECTOR(DeclarationContext, Function*, Functions) - DEF_VECTOR(DeclarationContext, Class*, Classes) - DEF_VECTOR(DeclarationContext, Template*, Templates) - DEF_VECTOR(DeclarationContext, TypedefDecl*, Typedefs) - DEF_VECTOR(DeclarationContext, TypeAlias*, TypeAliases) - DEF_VECTOR(DeclarationContext, Variable*, Variables) - DEF_VECTOR(DeclarationContext, Friend*, Friends) - - Declaration* DeclarationContext::FindAnonymous(const std::string& key) - { - auto it = anonymous.find(key); - return (it != anonymous.end()) ? it->second : 0; - } +DEF_VECTOR(DeclarationContext, Namespace*, Namespaces) +DEF_VECTOR(DeclarationContext, Enumeration*, Enums) +DEF_VECTOR(DeclarationContext, Function*, Functions) +DEF_VECTOR(DeclarationContext, Class*, Classes) +DEF_VECTOR(DeclarationContext, Template*, Templates) +DEF_VECTOR(DeclarationContext, TypedefDecl*, Typedefs) +DEF_VECTOR(DeclarationContext, TypeAlias*, TypeAliases) +DEF_VECTOR(DeclarationContext, Variable*, Variables) +DEF_VECTOR(DeclarationContext, Friend*, Friends) + +Declaration* DeclarationContext::FindAnonymous(const std::string_view& key) +{ + auto it = anonymous.find(key); + return (it != anonymous.end()) ? it->second : nullptr; +} - Namespace* DeclarationContext::FindNamespace(const std::string& Name) - { - auto namespaces = split(Name, "::"); - return FindNamespace(namespaces); - } +Namespace* DeclarationContext::FindNamespace(const std::string_view& name) +{ + const auto namespaces = split(name, "::"); + return FindNamespace(namespaces); +} - Namespace* - DeclarationContext::FindNamespace(const std::vector& Namespaces) +Namespace* DeclarationContext::FindNamespace(const std::vector& namespaces) +{ + auto currentNamespace = this; + for (auto& _namespace : namespaces) { - auto currentNamespace = this; - for (auto I = Namespaces.begin(), E = Namespaces.end(); I != E; ++I) - { - auto& _namespace = *I; - - auto childNamespace = std::find_if(currentNamespace->Namespaces.begin(), - currentNamespace->Namespaces.end(), - [&](CppSharp::CppParser::AST::Namespace* ns) - { - return ns->name == _namespace; - }); - - if (childNamespace == currentNamespace->Namespaces.end()) - return nullptr; + auto childNamespace = std::find_if(currentNamespace->Namespaces.begin(), + currentNamespace->Namespaces.end(), + [&](const Namespace* ns) + { + return ns->name == _namespace; + }); - currentNamespace = *childNamespace; - } + if (childNamespace == currentNamespace->Namespaces.end()) + return nullptr; - return (CppSharp::CppParser::AST::Namespace*)currentNamespace; + currentNamespace = *childNamespace; } - Namespace* DeclarationContext::FindCreateNamespace(const std::string& Name) - { - auto _namespace = FindNamespace(Name); + return (Namespace*)currentNamespace; +} - if (!_namespace) - { - _namespace = new Namespace(); - _namespace->name = Name; - _namespace->_namespace = this; +Namespace& DeclarationContext::FindCreateNamespace(const std::string_view& Name) +{ + auto _namespace = FindNamespace(Name); - Namespaces.push_back(_namespace); - } + if (!_namespace) + { + _namespace = new Namespace(); + _namespace->name = Name; + _namespace->_namespace = this; - return _namespace; + Namespaces.push_back(_namespace); } - Class* DeclarationContext::FindClass(const void* OriginalPtr, - const std::string& Name, - bool IsComplete) - { - if (Name.empty()) - return nullptr; + return *_namespace; +} - auto entries = split(Name, "::"); +Class* DeclarationContext::FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete) +{ + if (Name.empty()) + return nullptr; - if (entries.size() == 1) - { - auto _class = std::find_if(Classes.begin(), Classes.end(), - [OriginalPtr, Name, IsComplete](Class* klass) - { - return (OriginalPtr && klass->originalPtr == OriginalPtr) || - (klass->name == Name && klass->isIncomplete == !IsComplete); - }); + auto namespaces = split(Name, "::"); - return _class != Classes.end() ? *_class : nullptr; - } + if (namespaces.size() == 1) + { + auto _class = std::find_if(Classes.begin(), Classes.end(), + [OriginalPtr, Name, IsComplete](const Class* klass) + { + return (OriginalPtr && klass->originalPtr == OriginalPtr) || + (klass->name == Name && klass->isIncomplete == !IsComplete); + }); - auto className = entries[entries.size() - 1]; + return _class != Classes.end() ? *_class : nullptr; + } - std::vector namespaces; - std::copy_n(entries.begin(), entries.size() - 1, std::back_inserter(namespaces)); + auto className = namespaces.back(); + namespaces.pop_back(); - auto _namespace = FindNamespace(namespaces); - if (!_namespace) - return nullptr; + auto _namespace = FindNamespace(namespaces); + if (!_namespace) + return nullptr; - return _namespace->FindClass(OriginalPtr, className, IsComplete); - } + return _namespace->FindClass(OriginalPtr, className, IsComplete); +} - Class* DeclarationContext::CreateClass(const std::string& Name, bool IsComplete) - { - auto _class = new Class(); - _class->name = Name; - _class->_namespace = this; - _class->isIncomplete = !IsComplete; +Class* DeclarationContext::CreateClass(const std::string_view& Name, bool IsComplete) +{ + auto _class = new Class(); + _class->name = Name; + _class->_namespace = this; + _class->isIncomplete = !IsComplete; - return _class; - } + return _class; +} - Class* DeclarationContext::FindClass(const void* OriginalPtr, - const std::string& Name, - bool IsComplete, - bool Create) - { - auto _class = FindClass(OriginalPtr, Name, IsComplete); +Class* DeclarationContext::FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete, bool Create) +{ + auto _class = FindClass(OriginalPtr, Name, IsComplete); - if (!_class) + if (!_class) + { + if (Create) { - if (Create) - { - _class = CreateClass(Name, IsComplete); - Classes.push_back(_class); - } - - return _class; + _class = CreateClass(Name, IsComplete); + Classes.push_back(_class); } return _class; } - Enumeration* DeclarationContext::FindEnum(const void* OriginalPtr) + return _class; +} + +Enumeration* DeclarationContext::FindEnum(const void* OriginalPtr) +{ + auto foundEnum = std::find_if(Enums.begin(), Enums.end(), + [&](const Enumeration* enumeration) + { + return enumeration->originalPtr == OriginalPtr; + }); + + if (foundEnum != Enums.end()) + return *foundEnum; + + return nullptr; +} + +Enumeration* DeclarationContext::FindEnum(const std::string_view& Name, bool Create) +{ + auto namespaces = split(Name, "::"); + + if (namespaces.size() == 1) { auto foundEnum = std::find_if(Enums.begin(), Enums.end(), - [&](Enumeration* enumeration) + [&](const Enumeration* _enum) { - return enumeration->originalPtr == OriginalPtr; + return _enum->name == Name; }); if (foundEnum != Enums.end()) return *foundEnum; - return nullptr; + if (!Create) + return nullptr; + + auto _enum = new Enumeration(); + _enum->name = Name; + _enum->_namespace = this; + Enums.push_back(_enum); + return _enum; } - Enumeration* DeclarationContext::FindEnum(const std::string& Name, bool Create) - { - auto entries = split(Name, "::"); + auto enumName = namespaces.back(); + namespaces.pop_back(); - if (entries.size() == 1) - { - auto foundEnum = std::find_if(Enums.begin(), Enums.end(), - [&](Enumeration* _enum) - { - return _enum->name == Name; - }); - - if (foundEnum != Enums.end()) - return *foundEnum; - - if (!Create) - return nullptr; - - auto _enum = new Enumeration(); - _enum->name = Name; - _enum->_namespace = this; - Enums.push_back(_enum); - return _enum; - } + auto _namespace = FindNamespace(namespaces); + if (!_namespace) + return nullptr; - auto enumName = entries[entries.size() - 1]; + return _namespace->FindEnum(enumName, Create); +} - std::vector namespaces; - std::copy_n(entries.begin(), entries.size() - 1, std::back_inserter(namespaces)); +Enumeration* DeclarationContext::FindEnumWithItem(const std::string_view& Name) +{ + auto foundEnumIt = std::find_if(Enums.begin(), Enums.end(), + [&](Enumeration* _enum) + { + return _enum->FindItemByName(Name) != nullptr; + }); - auto _namespace = FindNamespace(namespaces); - if (!_namespace) - return nullptr; + if (foundEnumIt != Enums.end()) + return *foundEnumIt; - return _namespace->FindEnum(enumName, Create); + for (auto& Namespace : Namespaces) + { + auto foundEnum = Namespace->FindEnumWithItem(Name); + if (foundEnum != nullptr) + return foundEnum; } - Enumeration* DeclarationContext::FindEnumWithItem(const std::string& Name) + for (auto& Class : Classes) { - auto foundEnumIt = std::find_if(Enums.begin(), Enums.end(), - [&](Enumeration* _enum) - { - return _enum->FindItemByName(Name) != nullptr; - }); - if (foundEnumIt != Enums.end()) - return *foundEnumIt; - for (auto it = Namespaces.begin(); it != Namespaces.end(); ++it) - { - auto foundEnum = (*it)->FindEnumWithItem(Name); - if (foundEnum != nullptr) - return foundEnum; - } - for (auto it = Classes.begin(); it != Classes.end(); ++it) - { - auto foundEnum = (*it)->FindEnumWithItem(Name); - if (foundEnum != nullptr) - return foundEnum; - } - return nullptr; + auto foundEnum = Class->FindEnumWithItem(Name); + if (foundEnum != nullptr) + return foundEnum; } - Function* DeclarationContext::FindFunction(const std::string& USR) - { - auto foundFunction = std::find_if(Functions.begin(), Functions.end(), - [&](Function* func) - { - return func->USR == USR; - }); + return nullptr; +} - if (foundFunction != Functions.end()) - return *foundFunction; +Function* DeclarationContext::FindFunction(const std::string_view& USR) +{ + auto foundFunction = std::find_if(Functions.begin(), Functions.end(), + [&](const Function* func) + { + return func->USR == USR; + }); - auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), - [&](Template* t) - { - return t->TemplatedDecl && t->TemplatedDecl->USR == USR; - }); + if (foundFunction != Functions.end()) + return *foundFunction; - if (foundTemplate != Templates.end()) - return static_cast((*foundTemplate)->TemplatedDecl); + auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), + [&](const Template* t) + { + return t->TemplatedDecl && t->TemplatedDecl->USR == USR; + }); - return nullptr; - } + if (foundTemplate != Templates.end()) + return static_cast((*foundTemplate)->TemplatedDecl); - TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Create) - { - auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(), - [&](TypedefDecl* tdef) - { - return tdef->name == Name; - }); + return nullptr; +} - if (foundTypedef != Typedefs.end()) - return *foundTypedef; +TypedefDecl* DeclarationContext::FindTypedef(const std::string_view& Name, bool Create) +{ + auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(), + [&](const TypedefDecl* tdef) + { + return tdef->name == Name; + }); - if (!Create) - return nullptr; + if (foundTypedef != Typedefs.end()) + return *foundTypedef; - auto tdef = new TypedefDecl(); - tdef->name = Name; - tdef->_namespace = this; + if (!Create) + return nullptr; - return tdef; - } + auto tdef = new TypedefDecl(); + tdef->name = Name; + tdef->_namespace = this; - TypeAlias* DeclarationContext::FindTypeAlias(const std::string& Name, bool Create) - { - auto foundTypeAlias = std::find_if(TypeAliases.begin(), TypeAliases.end(), - [&](TypeAlias* talias) - { - return talias->name == Name; - }); + return tdef; +} - if (foundTypeAlias != TypeAliases.end()) - return *foundTypeAlias; +TypeAlias* DeclarationContext::FindTypeAlias(const std::string_view& Name, bool Create) +{ + auto foundTypeAlias = std::find_if(TypeAliases.begin(), TypeAliases.end(), + [&](const TypeAlias* talias) + { + return talias->name == Name; + }); - if (!Create) - return nullptr; + if (foundTypeAlias != TypeAliases.end()) + return *foundTypeAlias; - auto talias = new TypeAlias(); - talias->name = Name; - talias->_namespace = this; + if (!Create) + return nullptr; - return talias; - } + auto talias = new TypeAlias(); + talias->name = Name; + talias->_namespace = this; - Variable* DeclarationContext::FindVariable(const std::string& USR) - { - auto found = std::find_if(Variables.begin(), Variables.end(), - [&](Variable* var) - { - return var->USR == USR; - }); + return talias; +} - if (found != Variables.end()) - return *found; +Variable* DeclarationContext::FindVariable(const std::string_view& USR) +{ + auto found = std::find_if(Variables.begin(), Variables.end(), + [&](const Variable* var) + { + return var->USR == USR; + }); - return nullptr; - } + if (found != Variables.end()) + return *found; - Friend* DeclarationContext::FindFriend(const std::string& USR) - { - auto found = std::find_if(Friends.begin(), Friends.end(), - [&](Friend* var) - { - return var->USR == USR; - }); + return nullptr; +} - if (found != Friends.end()) - return *found; +Friend* DeclarationContext::FindFriend(const std::string_view& USR) +{ + auto found = std::find_if(Friends.begin(), Friends.end(), + [&](const Friend* var) + { + return var->USR == USR; + }); - return nullptr; - } + if (found != Friends.end()) + return *found; - TypedefNameDecl::TypedefNameDecl(DeclarationKind Kind) - : Declaration(Kind) - { - } + return nullptr; +} - TypedefNameDecl::~TypedefNameDecl() {} +TypedefNameDecl::TypedefNameDecl(DeclarationKind Kind) + : Declaration(Kind) +{ +} - TypedefDecl::TypedefDecl() - : TypedefNameDecl(DeclarationKind::Typedef) - { - } +TypedefNameDecl::~TypedefNameDecl() {} - TypedefDecl::~TypedefDecl() {} +TypedefDecl::TypedefDecl() + : TypedefNameDecl(DeclarationKind::Typedef) +{ +} - TypeAlias::TypeAlias() - : TypedefNameDecl(DeclarationKind::TypeAlias) - , describedAliasTemplate(0) - { - } +TypedefDecl::~TypedefDecl() {} - TypeAlias::~TypeAlias() {} +TypeAlias::TypeAlias() + : TypedefNameDecl(DeclarationKind::TypeAlias) + , describedAliasTemplate(nullptr) +{ +} - Friend::Friend() - : CppSharp::CppParser::AST::Declaration(DeclarationKind::Friend) - , declaration(0) - { - } +TypeAlias::~TypeAlias() {} - Friend::~Friend() {} +Friend::Friend() + : Declaration(DeclarationKind::Friend) + , declaration(nullptr) +{ +} - StatementObsolete::StatementObsolete(const std::string& str, StatementClassObsolete stmtClass, Declaration* decl) - : string(str) - , _class(stmtClass) - , decl(decl) - { - } +Friend::~Friend() {} - ExpressionObsolete::ExpressionObsolete(const std::string& str, StatementClassObsolete stmtClass, Declaration* decl) - : StatementObsolete(str, stmtClass, decl) - { - } +StatementObsolete::StatementObsolete(const std::string& str, StatementClassObsolete stmtClass, Declaration* decl) + : string(str) + , _class(stmtClass) + , decl(decl) +{ +} - BinaryOperatorObsolete::BinaryOperatorObsolete(const std::string& str, ExpressionObsolete* lhs, ExpressionObsolete* rhs, const std::string& opcodeStr) - : ExpressionObsolete(str, StatementClassObsolete::BinaryOperator) - , LHS(lhs) - , RHS(rhs) - , opcodeStr(opcodeStr) - { - } +ExpressionObsolete::ExpressionObsolete(const std::string& str, StatementClassObsolete stmtClass, Declaration* decl) + : StatementObsolete(str, stmtClass, decl) +{ +} - BinaryOperatorObsolete::~BinaryOperatorObsolete() - { - deleteExpression(LHS); - deleteExpression(RHS); - } +BinaryOperatorObsolete::BinaryOperatorObsolete(const std::string& str, ExpressionObsolete* lhs, ExpressionObsolete* rhs, const std::string& opcodeStr) + : ExpressionObsolete(str, StatementClassObsolete::BinaryOperator) + , LHS(lhs) + , RHS(rhs) + , opcodeStr(opcodeStr) +{ +} +BinaryOperatorObsolete::~BinaryOperatorObsolete() +{ + deleteExpression(LHS); + deleteExpression(RHS); +} - CallExprObsolete::CallExprObsolete(const std::string& str, Declaration* decl) - : ExpressionObsolete(str, StatementClassObsolete::CallExprClass, decl) - { - } - CallExprObsolete::~CallExprObsolete() - { - for (auto& arg : Arguments) - deleteExpression(arg); - } +CallExprObsolete::CallExprObsolete(const std::string& str, Declaration* decl) + : ExpressionObsolete(str, StatementClassObsolete::CallExprClass, decl) +{ +} - DEF_VECTOR(CallExprObsolete, ExpressionObsolete*, Arguments) +CallExprObsolete::~CallExprObsolete() +{ + for (auto& arg : Arguments) + deleteExpression(arg); +} - CXXConstructExprObsolete::CXXConstructExprObsolete(const std::string& str, Declaration* decl) - : ExpressionObsolete(str, StatementClassObsolete::CXXConstructExprClass, decl) - { - } +DEF_VECTOR(CallExprObsolete, ExpressionObsolete*, Arguments) - CXXConstructExprObsolete::~CXXConstructExprObsolete() - { - for (auto& arg : Arguments) - deleteExpression(arg); - } +CXXConstructExprObsolete::CXXConstructExprObsolete(const std::string& str, Declaration* decl) + : ExpressionObsolete(str, StatementClassObsolete::CXXConstructExprClass, decl) +{ +} - DEF_VECTOR(CXXConstructExprObsolete, ExpressionObsolete*, Arguments) +CXXConstructExprObsolete::~CXXConstructExprObsolete() +{ + for (auto& arg : Arguments) + deleteExpression(arg); +} - Parameter::Parameter() - : Declaration(DeclarationKind::Parameter) - , isIndirect(false) - , hasDefaultValue(false) - , defaultArgument(0) - , defaultValue(0) - { - } +DEF_VECTOR(CXXConstructExprObsolete, ExpressionObsolete*, Arguments) - Parameter::~Parameter() - { - deleteExpression(defaultArgument); - } +Parameter::Parameter() + : Declaration(DeclarationKind::Parameter) + , isIndirect(false) + , hasDefaultValue(false) + , defaultArgument(nullptr) + , defaultValue(nullptr) +{ +} - Function::Function() - : DeclarationContext(DeclarationKind::Function) - , isReturnIndirect(false) - , isConstExpr(false) - , isVariadic(false) - , isInline(false) - , isPure(false) - , isDeleted(false) - , isDefaulted(false) - , friendKind(FriendKind::None) - , operatorKind(CXXOperatorKind::None) - , callingConvention(CallingConvention::Default) - , specializationInfo(0) - , instantiatedFrom(0) - , bodyStmt(0) - { - } +Parameter::~Parameter() +{ + deleteExpression(defaultArgument); +} - Function::~Function() {} - DEF_VECTOR(Function, Parameter*, Parameters) - - Method::Method() - : Function() - , isVirtual(false) - , isStatic(false) - , isConst(false) - , isExplicit(false) - , isVolatile(false) - , isDefaultConstructor(false) - , isCopyConstructor(false) - , isMoveConstructor(false) - , refQualifier(RefQualifierKind::None) - { - kind = DeclarationKind::Method; - } +Function::Function() + : DeclarationContext(DeclarationKind::Function) + , isReturnIndirect(false) + , isConstExpr(false) + , isVariadic(false) + , isInline(false) + , isPure(false) + , isDeleted(false) + , isDefaulted(false) + , friendKind(FriendKind::None) + , operatorKind(CXXOperatorKind::None) + , callingConvention(CallingConvention::Default) + , specializationInfo(nullptr) + , instantiatedFrom(nullptr) + , bodyStmt(nullptr) +{ +} - Method::~Method() {} +Function::~Function() {} +DEF_VECTOR(Function, Parameter*, Parameters) + +Method::Method() + : Function() + , isVirtual(false) + , isStatic(false) + , isConst(false) + , isExplicit(false) + , isVolatile(false) + , isDefaultConstructor(false) + , isCopyConstructor(false) + , isMoveConstructor(false) + , refQualifier(RefQualifierKind::None) +{ + kind = DeclarationKind::Method; +} - DEF_VECTOR(Method, Method*, OverriddenMethods) +Method::~Method() {} - // Enumeration +DEF_VECTOR(Method, Method*, OverriddenMethods) - Enumeration::Enumeration() - : DeclarationContext(DeclarationKind::Enumeration) - , modifiers((EnumModifiers)0) - , type(0) - , builtinType(0) - { - } +// Enumeration - Enumeration::~Enumeration() {} +Enumeration::Enumeration() + : DeclarationContext(DeclarationKind::Enumeration) + , modifiers((EnumModifiers)0) + , type(nullptr) + , builtinType(nullptr) +{ +} - DEF_VECTOR(Enumeration, Enumeration::Item*, Items) +Enumeration::~Enumeration() {} - Enumeration::Item::Item() - : Declaration(DeclarationKind::EnumerationItem) - { - } +DEF_VECTOR(Enumeration, Enumeration::Item*, Items) - Enumeration::Item::Item(const Item& rhs) - : Declaration(rhs) - , expression(rhs.expression) - , value(rhs.value) - { - } +Enumeration::Item::Item() + : Declaration(DeclarationKind::EnumerationItem) +{ +} - Enumeration::Item::~Item() {} +Enumeration::Item::Item(const Item& rhs) + : Declaration(rhs) + , expression(rhs.expression) + , value(rhs.value) +{ +} - Enumeration::Item* Enumeration::FindItemByName(const std::string& Name) - { - auto foundEnumItem = std::find_if(Items.begin(), Items.end(), - [&](Item* _item) - { - return _item->name == Name; - }); - if (foundEnumItem != Items.end()) - return *foundEnumItem; - return nullptr; - } +Enumeration::Item::~Item() {} - Variable::Variable() - : Declaration(DeclarationKind::Variable) - , isConstExpr(false) - , initializer(0) - { - } +Enumeration::Item* Enumeration::FindItemByName(const std::string_view& Name) +{ + auto foundEnumItem = std::find_if(Items.begin(), Items.end(), + [&](const Item* _item) + { + return _item->name == Name; + }); - Variable::~Variable() {} + if (foundEnumItem != Items.end()) + return *foundEnumItem; + return nullptr; +} - BaseClassSpecifier::BaseClassSpecifier() - : type(0) - , offset(0) - { - } +Variable::Variable() + : Declaration(DeclarationKind::Variable) + , isConstExpr(false) + , initializer(nullptr) +{ +} - Field::Field() - : Declaration(DeclarationKind::Field) - , _class(0) - , isBitField(false) - , bitWidth(0) - { - } +Variable::~Variable() {} - Field::~Field() {} +BaseClassSpecifier::BaseClassSpecifier() + : type(nullptr) + , offset(0) +{ +} - AccessSpecifierDecl::AccessSpecifierDecl() - : Declaration(DeclarationKind::AccessSpecifier) - { - } +Field::Field() + : Declaration(DeclarationKind::Field) + , _class(nullptr) + , isBitField(false) + , bitWidth(0) +{ +} - AccessSpecifierDecl::~AccessSpecifierDecl() {} - - Class::Class() - : DeclarationContext(DeclarationKind::Class) - , isPOD(false) - , isAbstract(false) - , isUnion(false) - , isDynamic(false) - , isPolymorphic(false) - , hasNonTrivialDefaultConstructor(false) - , hasNonTrivialCopyConstructor(false) - , hasNonTrivialDestructor(false) - , isExternCContext(false) - , isInjected(false) - , layout(0) - , tagKind(TagKind::Struct) - { - } +Field::~Field() {} - Class::~Class() - { - if (layout) - delete layout; - } +AccessSpecifierDecl::AccessSpecifierDecl() + : Declaration(DeclarationKind::AccessSpecifier) +{ +} - DEF_VECTOR(Class, BaseClassSpecifier*, Bases) - DEF_VECTOR(Class, Field*, Fields) - DEF_VECTOR(Class, Method*, Methods) - DEF_VECTOR(Class, AccessSpecifierDecl*, Specifiers) +AccessSpecifierDecl::~AccessSpecifierDecl() {} + +Class::Class() + : DeclarationContext(DeclarationKind::Class) + , isPOD(false) + , isAbstract(false) + , isUnion(false) + , isDynamic(false) + , isPolymorphic(false) + , hasNonTrivialDefaultConstructor(false) + , hasNonTrivialCopyConstructor(false) + , hasNonTrivialDestructor(false) + , isExternCContext(false) + , isInjected(false) + , layout(nullptr) + , tagKind(TagKind::Struct) +{ +} - Template::Template() - : Declaration(DeclarationKind::Template) - , TemplatedDecl(0) - { - } +Class::~Class() +{ + if (layout) + delete layout; +} - Template::Template(DeclarationKind kind) - : Declaration(kind) - , TemplatedDecl(0) - { - } +DEF_VECTOR(Class, BaseClassSpecifier*, Bases) +DEF_VECTOR(Class, Field*, Fields) +DEF_VECTOR(Class, Method*, Methods) +DEF_VECTOR(Class, AccessSpecifierDecl*, Specifiers) - DEF_VECTOR(Template, Declaration*, Parameters) +Template::Template() + : Declaration(DeclarationKind::Template) + , TemplatedDecl(nullptr) +{ +} - TypeAliasTemplate::TypeAliasTemplate() - : Template(DeclarationKind::TypeAliasTemplate) - { - } +Template::Template(DeclarationKind kind) + : Declaration(kind) + , TemplatedDecl(nullptr) +{ +} - TypeAliasTemplate::~TypeAliasTemplate() {} +DEF_VECTOR(Template, Declaration*, Parameters) - ClassTemplate::ClassTemplate() - : Template(DeclarationKind::ClassTemplate) - { - } +TypeAliasTemplate::TypeAliasTemplate() + : Template(DeclarationKind::TypeAliasTemplate) +{ +} - ClassTemplate::~ClassTemplate() {} +TypeAliasTemplate::~TypeAliasTemplate() {} - DEF_VECTOR(ClassTemplate, ClassTemplateSpecialization*, Specializations) +ClassTemplate::ClassTemplate() + : Template(DeclarationKind::ClassTemplate) +{ +} - ClassTemplateSpecialization::ClassTemplateSpecialization() - : Class() - , templatedDecl(0) - { - kind = DeclarationKind::ClassTemplateSpecialization; - } +ClassTemplate::~ClassTemplate() {} - ClassTemplateSpecialization::~ClassTemplateSpecialization() {} +DEF_VECTOR(ClassTemplate, ClassTemplateSpecialization*, Specializations) - DEF_VECTOR(ClassTemplateSpecialization, TemplateArgument, Arguments) +ClassTemplateSpecialization::ClassTemplateSpecialization() + : Class() + , templatedDecl(nullptr) +{ + kind = DeclarationKind::ClassTemplateSpecialization; +} - ClassTemplatePartialSpecialization::ClassTemplatePartialSpecialization() - : ClassTemplateSpecialization() - { - kind = DeclarationKind::ClassTemplatePartialSpecialization; - } +ClassTemplateSpecialization::~ClassTemplateSpecialization() {} - ClassTemplatePartialSpecialization::~ClassTemplatePartialSpecialization() {} +DEF_VECTOR(ClassTemplateSpecialization, TemplateArgument, Arguments) - DEF_VECTOR(ClassTemplatePartialSpecialization, Declaration*, Parameters) +ClassTemplatePartialSpecialization::ClassTemplatePartialSpecialization() + : ClassTemplateSpecialization() +{ + kind = DeclarationKind::ClassTemplatePartialSpecialization; +} - FunctionTemplate::FunctionTemplate() - : Template(DeclarationKind::FunctionTemplate) - { - } +ClassTemplatePartialSpecialization::~ClassTemplatePartialSpecialization() {} - FunctionTemplate::~FunctionTemplate() {} +DEF_VECTOR(ClassTemplatePartialSpecialization, Declaration*, Parameters) - DEF_VECTOR(FunctionTemplate, FunctionTemplateSpecialization*, Specializations) +FunctionTemplate::FunctionTemplate() + : Template(DeclarationKind::FunctionTemplate) +{ +} - FunctionTemplateSpecialization* FunctionTemplate::FindSpecialization(const std::string& usr) - { - auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), - [&](FunctionTemplateSpecialization* cts) - { - return cts->specializedFunction->USR == usr; - }); +FunctionTemplate::~FunctionTemplate() {} - if (foundSpec != Specializations.end()) - return static_cast(*foundSpec); +DEF_VECTOR(FunctionTemplate, FunctionTemplateSpecialization*, Specializations) - return nullptr; - } +FunctionTemplateSpecialization* FunctionTemplate::FindSpecialization(const std::string& usr) +{ + auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), + [&](FunctionTemplateSpecialization* cts) + { + return cts->specializedFunction->USR == usr; + }); - FunctionTemplateSpecialization::FunctionTemplateSpecialization() - : _template(0) - , specializedFunction(0) - { - } + if (foundSpec != Specializations.end()) + return static_cast(*foundSpec); - FunctionTemplateSpecialization::~FunctionTemplateSpecialization() - { - } + return nullptr; +} - DEF_VECTOR(FunctionTemplateSpecialization, TemplateArgument, Arguments) +FunctionTemplateSpecialization::FunctionTemplateSpecialization() + : _template(nullptr) + , specializedFunction(nullptr) +{ +} - VarTemplate::VarTemplate() - : Template(DeclarationKind::VarTemplate) - { - } +FunctionTemplateSpecialization::~FunctionTemplateSpecialization() +{ +} - VarTemplate::~VarTemplate() {} +DEF_VECTOR(FunctionTemplateSpecialization, TemplateArgument, Arguments) - DEF_VECTOR(VarTemplate, VarTemplateSpecialization*, Specializations) +VarTemplate::VarTemplate() + : Template(DeclarationKind::VarTemplate) +{ +} - VarTemplateSpecialization* VarTemplate::FindSpecialization(const std::string& usr) - { - auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), - [&](VarTemplateSpecialization* cts) - { - return cts->USR == usr; - }); +VarTemplate::~VarTemplate() {} - if (foundSpec != Specializations.end()) - return static_cast(*foundSpec); +DEF_VECTOR(VarTemplate, VarTemplateSpecialization*, Specializations) - return nullptr; - } +VarTemplateSpecialization* VarTemplate::FindSpecialization(const std::string& usr) +{ + auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), + [&](VarTemplateSpecialization* cts) + { + return cts->USR == usr; + }); - VarTemplatePartialSpecialization* VarTemplate::FindPartialSpecialization(const std::string& usr) - { - auto foundSpec = FindSpecialization(usr); - if (foundSpec != nullptr) - return static_cast(foundSpec); - return nullptr; - } + if (foundSpec != Specializations.end()) + return static_cast(*foundSpec); - VarTemplateSpecialization::VarTemplateSpecialization() - : Variable() - , templatedDecl(0) - { - kind = DeclarationKind::VarTemplateSpecialization; - } + return nullptr; +} - VarTemplateSpecialization::~VarTemplateSpecialization() {} +VarTemplatePartialSpecialization* VarTemplate::FindPartialSpecialization(const std::string& usr) +{ + auto foundSpec = FindSpecialization(usr); + if (foundSpec != nullptr) + return static_cast(foundSpec); + return nullptr; +} - DEF_VECTOR(VarTemplateSpecialization, TemplateArgument, Arguments) +VarTemplateSpecialization::VarTemplateSpecialization() + : Variable() + , templatedDecl(nullptr) +{ + kind = DeclarationKind::VarTemplateSpecialization; +} - VarTemplatePartialSpecialization::VarTemplatePartialSpecialization() - : VarTemplateSpecialization() - { - kind = DeclarationKind::VarTemplatePartialSpecialization; - } +VarTemplateSpecialization::~VarTemplateSpecialization() {} - VarTemplatePartialSpecialization::~VarTemplatePartialSpecialization() - { - } +DEF_VECTOR(VarTemplateSpecialization, TemplateArgument, Arguments) - UnresolvedUsingTypename::UnresolvedUsingTypename() - : Declaration(DeclarationKind::UnresolvedUsingTypename) - { - } +VarTemplatePartialSpecialization::VarTemplatePartialSpecialization() + : VarTemplateSpecialization() +{ + kind = DeclarationKind::VarTemplatePartialSpecialization; +} - UnresolvedUsingTypename::~UnresolvedUsingTypename() {} +VarTemplatePartialSpecialization::~VarTemplatePartialSpecialization() +{ +} - Namespace::Namespace() - : DeclarationContext(DeclarationKind::Namespace) - , isInline(false) - { - } +UnresolvedUsingTypename::UnresolvedUsingTypename() + : Declaration(DeclarationKind::UnresolvedUsingTypename) +{ +} - Namespace::~Namespace() {} +UnresolvedUsingTypename::~UnresolvedUsingTypename() {} - PreprocessedEntity::PreprocessedEntity() - : macroLocation(AST::MacroLocation::Unknown) - , originalPtr(0) - , kind(DeclarationKind::PreprocessedEntity) - { - } +Namespace::Namespace() + : DeclarationContext(DeclarationKind::Namespace) + , isInline(false) +{ +} - MacroDefinition::MacroDefinition() - : lineNumberStart(0) - , lineNumberEnd(0) - { - kind = DeclarationKind::MacroDefinition; - } +Namespace::~Namespace() {} - MacroDefinition::~MacroDefinition() {} +PreprocessedEntity::PreprocessedEntity() + : macroLocation(MacroLocation::Unknown) + , originalPtr(nullptr) + , kind(DeclarationKind::PreprocessedEntity) +{ +} - MacroExpansion::MacroExpansion() - : definition(0) - { - kind = DeclarationKind::MacroExpansion; - } +MacroDefinition::MacroDefinition() + : lineNumberStart(0) + , lineNumberEnd(0) +{ + kind = DeclarationKind::MacroDefinition; +} - MacroExpansion::~MacroExpansion() {} +MacroDefinition::~MacroDefinition() {} - TranslationUnit::TranslationUnit() - { - kind = DeclarationKind::TranslationUnit; - } +MacroExpansion::MacroExpansion() + : definition(nullptr) +{ + kind = DeclarationKind::MacroExpansion; +} - TranslationUnit::~TranslationUnit() {} - DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros) +MacroExpansion::~MacroExpansion() {} - NativeLibrary::NativeLibrary() - : archType(AST::ArchType::UnknownArch) - { - } +TranslationUnit::TranslationUnit() +{ + kind = DeclarationKind::TranslationUnit; +} - NativeLibrary::~NativeLibrary() {} +TranslationUnit::~TranslationUnit() {} +DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros) - // NativeLibrary - DEF_VECTOR_STRING(NativeLibrary, Symbols) - DEF_VECTOR_STRING(NativeLibrary, Dependencies) +NativeLibrary::NativeLibrary() + : archType(ArchType::UnknownArch) +{ +} - // ASTContext - DEF_VECTOR(ASTContext, TranslationUnit*, TranslationUnits) +NativeLibrary::~NativeLibrary() {} - ClassTemplateSpecialization* ClassTemplate::FindSpecialization(const std::string& usr) - { - auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), - [&](ClassTemplateSpecialization* cts) - { - return cts->USR == usr; - }); +// NativeLibrary +DEF_VECTOR_STRING(NativeLibrary, Symbols) +DEF_VECTOR_STRING(NativeLibrary, Dependencies) - if (foundSpec != Specializations.end()) - return static_cast(*foundSpec); +// ASTContext +DEF_VECTOR(ASTContext, TranslationUnit*, TranslationUnits) - return nullptr; - } +ClassTemplateSpecialization* ClassTemplate::FindSpecialization(const std::string& usr) +{ + auto foundSpec = std::find_if(Specializations.begin(), Specializations.end(), + [&](ClassTemplateSpecialization* cts) + { + return cts->USR == usr; + }); - ClassTemplatePartialSpecialization* ClassTemplate::FindPartialSpecialization(const std::string& usr) - { - auto foundSpec = FindSpecialization(usr); - if (foundSpec != nullptr) - return static_cast(foundSpec); - return nullptr; - } + if (foundSpec != Specializations.end()) + return static_cast(*foundSpec); - ASTContext::ASTContext() {} + return nullptr; +} - ASTContext::~ASTContext() {} +ClassTemplatePartialSpecialization* ClassTemplate::FindPartialSpecialization(const std::string& usr) +{ + auto foundSpec = FindSpecialization(usr); + if (foundSpec != nullptr) + return static_cast(foundSpec); + return nullptr; +} - TranslationUnit* ASTContext::FindOrCreateModule(const std::string& File) - { - auto normalizedFile = normalizePath(File); +ASTContext::ASTContext() {} - auto existingUnit = std::find_if(TranslationUnits.begin(), - TranslationUnits.end(), [&](TranslationUnit* unit) - { - return unit && unit->fileName == normalizedFile; - }); +ASTContext::~ASTContext() {} - if (existingUnit != TranslationUnits.end()) - return *existingUnit; +TranslationUnit* ASTContext::FindOrCreateModule(const std::string& File) +{ + auto normalizedFile = normalizePath(File); - auto unit = new TranslationUnit(); - unit->fileName = normalizedFile; - TranslationUnits.push_back(unit); + auto existingUnit = std::find_if(TranslationUnits.begin(), + TranslationUnits.end(), [&](TranslationUnit* unit) + { + return unit && unit->fileName == normalizedFile; + }); - return unit; - } + if (existingUnit != TranslationUnits.end()) + return *existingUnit; - // Comments - Comment::Comment(CommentKind kind) - : kind(kind) - { - } + auto unit = new TranslationUnit(); + unit->fileName = normalizedFile; + TranslationUnits.push_back(unit); - RawComment::RawComment() - : fullCommentBlock(0) - { - } + return unit; +} - RawComment::~RawComment() - { - if (fullCommentBlock) - delete fullCommentBlock; - } +// Comments +Comment::Comment(CommentKind kind) + : kind(kind) +{ +} - FullComment::FullComment() - : Comment(CommentKind::FullComment) - { - } +RawComment::RawComment() + : fullCommentBlock(nullptr) +{ +} - FullComment::~FullComment() +RawComment::~RawComment() +{ + if (fullCommentBlock) + delete fullCommentBlock; +} + +FullComment::FullComment() + : Comment(CommentKind::FullComment) +{ +} + +FullComment::~FullComment() +{ + for (auto& block : Blocks) { - for (auto& block : Blocks) + // HACK: see https://github.com/mono/CppSharp/issues/599 + switch (block->kind) { - // HACK: see https://github.com/mono/CppSharp/issues/599 - switch (block->kind) - { - case CommentKind::BlockCommandComment: - delete static_cast(block); - break; - case CommentKind::ParamCommandComment: - delete static_cast(block); - break; - case CommentKind::TParamCommandComment: - delete static_cast(block); - break; - case CommentKind::VerbatimBlockComment: - delete static_cast(block); - break; - case CommentKind::VerbatimLineComment: - delete static_cast(block); - break; - case CommentKind::ParagraphComment: - delete static_cast(block); - break; - default: - delete block; - break; - } + case CommentKind::BlockCommandComment: + delete static_cast(block); + break; + case CommentKind::ParamCommandComment: + delete static_cast(block); + break; + case CommentKind::TParamCommandComment: + delete static_cast(block); + break; + case CommentKind::VerbatimBlockComment: + delete static_cast(block); + break; + case CommentKind::VerbatimLineComment: + delete static_cast(block); + break; + case CommentKind::ParagraphComment: + delete static_cast(block); + break; + default: + delete block; + break; } } +} - DEF_VECTOR(FullComment, BlockContentComment*, Blocks) +DEF_VECTOR(FullComment, BlockContentComment*, Blocks) - BlockContentComment::BlockContentComment() - : Comment(CommentKind::BlockContentComment) - { - } +BlockContentComment::BlockContentComment() + : Comment(CommentKind::BlockContentComment) +{ +} - BlockContentComment::BlockContentComment(CommentKind Kind) - : Comment(Kind) - { - } +BlockContentComment::BlockContentComment(CommentKind Kind) + : Comment(Kind) +{ +} - BlockCommandComment::Argument::Argument() {} +BlockCommandComment::Argument::Argument() {} - BlockCommandComment::Argument::Argument(const Argument& rhs) - : text(rhs.text) - { - } +BlockCommandComment::Argument::Argument(const Argument& rhs) + : text(rhs.text) +{ +} - BlockCommandComment::Argument::~Argument() {} +BlockCommandComment::Argument::~Argument() {} - BlockCommandComment::BlockCommandComment() - : BlockContentComment(CommentKind::BlockCommandComment) - , commandId(0) - , paragraphComment(0) - { - } +BlockCommandComment::BlockCommandComment() + : BlockContentComment(CommentKind::BlockCommandComment) + , commandId(0) + , paragraphComment(nullptr) +{ +} - BlockCommandComment::BlockCommandComment(CommentKind Kind) - : BlockContentComment(Kind) - , commandId(0) - , paragraphComment(0) - { - } +BlockCommandComment::BlockCommandComment(CommentKind Kind) + : BlockContentComment(Kind) + , commandId(0) + , paragraphComment(nullptr) +{ +} - BlockCommandComment::~BlockCommandComment() - { - delete paragraphComment; - } +BlockCommandComment::~BlockCommandComment() +{ + delete paragraphComment; +} - DEF_VECTOR(BlockCommandComment, BlockCommandComment::Argument, Arguments) +DEF_VECTOR(BlockCommandComment, BlockCommandComment::Argument, Arguments) - ParamCommandComment::ParamCommandComment() - : BlockCommandComment(CommentKind::ParamCommandComment) - , direction(PassDirection::In) - , paramIndex(0) - { - } +ParamCommandComment::ParamCommandComment() + : BlockCommandComment(CommentKind::ParamCommandComment) + , direction(In) + , paramIndex(0) +{ +} - TParamCommandComment::TParamCommandComment() - : BlockCommandComment(CommentKind::TParamCommandComment) - { - } +TParamCommandComment::TParamCommandComment() + : BlockCommandComment(CommentKind::TParamCommandComment) +{ +} - DEF_VECTOR(TParamCommandComment, unsigned, Position) +DEF_VECTOR(TParamCommandComment, unsigned, Position) - VerbatimBlockComment::VerbatimBlockComment() - : BlockCommandComment(CommentKind::VerbatimBlockComment) - { - } +VerbatimBlockComment::VerbatimBlockComment() + : BlockCommandComment(CommentKind::VerbatimBlockComment) +{ +} - VerbatimBlockComment::~VerbatimBlockComment() - { - for (auto& line : Lines) - delete line; - } +VerbatimBlockComment::~VerbatimBlockComment() +{ + for (auto& line : Lines) + delete line; +} - DEF_VECTOR(VerbatimBlockComment, VerbatimBlockLineComment*, Lines) +DEF_VECTOR(VerbatimBlockComment, VerbatimBlockLineComment*, Lines) - VerbatimLineComment::VerbatimLineComment() - : BlockCommandComment(CommentKind::VerbatimLineComment) - { - } +VerbatimLineComment::VerbatimLineComment() + : BlockCommandComment(CommentKind::VerbatimLineComment) +{ +} - ParagraphComment::ParagraphComment() - : BlockContentComment(CommentKind::ParagraphComment) - , isWhitespace(false) - { - } +ParagraphComment::ParagraphComment() + : BlockContentComment(CommentKind::ParagraphComment) + , isWhitespace(false) +{ +} - ParagraphComment::~ParagraphComment() +ParagraphComment::~ParagraphComment() +{ + for (auto& content : Content) { - for (auto& content : Content) + // HACK: see https://github.com/mono/CppSharp/issues/599 + switch (content->kind) { - // HACK: see https://github.com/mono/CppSharp/issues/599 - switch (content->kind) - { - case CommentKind::InlineCommandComment: - delete static_cast(content); - break; - case CommentKind::HTMLTagComment: - delete static_cast(content); - break; - case CommentKind::HTMLStartTagComment: - delete static_cast(content); - break; - case CommentKind::HTMLEndTagComment: - delete static_cast(content); - break; - case CommentKind::TextComment: - delete static_cast(content); - break; - default: - delete content; - break; - } + case CommentKind::InlineCommandComment: + delete static_cast(content); + break; + case CommentKind::HTMLTagComment: + delete static_cast(content); + break; + case CommentKind::HTMLStartTagComment: + delete static_cast(content); + break; + case CommentKind::HTMLEndTagComment: + delete static_cast(content); + break; + case CommentKind::TextComment: + delete static_cast(content); + break; + default: + delete content; + break; } } +} - DEF_VECTOR(ParagraphComment, InlineContentComment*, Content) +DEF_VECTOR(ParagraphComment, InlineContentComment*, Content) - HTMLTagComment::HTMLTagComment() - : InlineContentComment(CommentKind::HTMLTagComment) - { - } +HTMLTagComment::HTMLTagComment() + : InlineContentComment(CommentKind::HTMLTagComment) +{ +} - HTMLTagComment::HTMLTagComment(CommentKind Kind) - : InlineContentComment(Kind) - { - } +HTMLTagComment::HTMLTagComment(CommentKind Kind) + : InlineContentComment(Kind) +{ +} - HTMLStartTagComment::Attribute::Attribute() {} +HTMLStartTagComment::Attribute::Attribute() {} - HTMLStartTagComment::Attribute::Attribute(const Attribute& rhs) - : name(rhs.name) - , value(rhs.value) - { - } +HTMLStartTagComment::Attribute::Attribute(const Attribute& rhs) + : name(rhs.name) + , value(rhs.value) +{ +} - HTMLStartTagComment::Attribute::~Attribute() {} +HTMLStartTagComment::Attribute::~Attribute() {} - HTMLStartTagComment::HTMLStartTagComment() - : HTMLTagComment(CommentKind::HTMLStartTagComment) - { - } +HTMLStartTagComment::HTMLStartTagComment() + : HTMLTagComment(CommentKind::HTMLStartTagComment) +{ +} - DEF_VECTOR(HTMLStartTagComment, HTMLStartTagComment::Attribute, Attributes) +DEF_VECTOR(HTMLStartTagComment, HTMLStartTagComment::Attribute, Attributes) - HTMLEndTagComment::HTMLEndTagComment() - : HTMLTagComment(CommentKind::HTMLEndTagComment) - { - } +HTMLEndTagComment::HTMLEndTagComment() + : HTMLTagComment(CommentKind::HTMLEndTagComment) +{ +} - InlineContentComment::InlineContentComment() - : Comment(CommentKind::InlineContentComment) - , hasTrailingNewline(false) - { - } +InlineContentComment::InlineContentComment() + : Comment(CommentKind::InlineContentComment) + , hasTrailingNewline(false) +{ +} - InlineContentComment::InlineContentComment(CommentKind Kind) - : Comment(Kind) - , hasTrailingNewline(false) - { - } +InlineContentComment::InlineContentComment(CommentKind Kind) + : Comment(Kind) + , hasTrailingNewline(false) +{ +} - TextComment::TextComment() - : InlineContentComment(CommentKind::TextComment) - { - } +TextComment::TextComment() + : InlineContentComment(CommentKind::TextComment) +{ +} - InlineCommandComment::Argument::Argument() {} +InlineCommandComment::Argument::Argument() {} - InlineCommandComment::Argument::Argument(const Argument& rhs) - : text(rhs.text) - { - } +InlineCommandComment::Argument::Argument(const Argument& rhs) + : text(rhs.text) +{ +} - InlineCommandComment::Argument::~Argument() {} +InlineCommandComment::Argument::~Argument() {} - InlineCommandComment::InlineCommandComment() - : InlineContentComment(CommentKind::InlineCommandComment) - , commandId(0) - , commentRenderKind(RenderNormal) - { - } +InlineCommandComment::InlineCommandComment() + : InlineContentComment(CommentKind::InlineCommandComment) + , commandId(0) + , commentRenderKind(RenderNormal) +{ +} - DEF_VECTOR(InlineCommandComment, InlineCommandComment::Argument, Arguments) +DEF_VECTOR(InlineCommandComment, InlineCommandComment::Argument, Arguments) - VerbatimBlockLineComment::VerbatimBlockLineComment() - : Comment(CommentKind::VerbatimBlockLineComment) - { - } +VerbatimBlockLineComment::VerbatimBlockLineComment() + : Comment(CommentKind::VerbatimBlockLineComment) +{ +} -}}} // namespace CppSharp::CppParser::AST \ No newline at end of file +} // namespace CppSharp::CppParser::AST \ No newline at end of file diff --git a/src/CppParser/ASTNodeVisitor.cpp b/src/CppParser/ASTNodeVisitor.cpp new file mode 100644 index 0000000000..e923c51b26 --- /dev/null +++ b/src/CppParser/ASTNodeVisitor.cpp @@ -0,0 +1,2352 @@ +/************************************************************************ + * + * CppSharp + * Licensed under the simplified BSD license. All rights reserved. + * + ************************************************************************/ + +#include "ASTNodeVisitor.h" + +#include +#include +#include +#include +#include + +#include + +#include + +#include "Types.h" +#include "Decl.h" +#include "Parser.h" + +using namespace CppSharp::CppParser; +using namespace clang; + +namespace { +AST::AccessSpecifier ConvertToAccess(clang::AccessSpecifier AS) +{ + switch (AS) + { + case clang::AS_private: + return AST::AccessSpecifier::Private; + case clang::AS_protected: + return AST::AccessSpecifier::Protected; + case clang::AS_public: + return AST::AccessSpecifier::Public; + case clang::AS_none: + return AST::AccessSpecifier::Public; + } + + llvm_unreachable("Unknown AccessSpecifier"); +} + +std::string GetDeclUSR(const clang::Decl* D) +{ + using namespace clang; + SmallString<128> usr; + if (!index::generateUSRForDecl(D, usr)) + return usr.c_str(); + return ""; +} + +std::string GetDeclName(const clang::NamedDecl* D) +{ + if (const clang::IdentifierInfo* II = D->getIdentifier()) + return II->getName().str(); + return D->getDeclName().getAsString(); +} + +AST::TypeQualifiers GetTypeQualifiers(const clang::Qualifiers& quals) +{ + AST::TypeQualifiers ret; + ret.isConst = quals.hasConst(); + ret.isRestrict = quals.hasRestrict(); + ret.isVolatile = quals.hasVolatile(); + return ret; +} +} // namespace + +void ASTNodeVisitor::ConvertNamedRecord(AST::Declaration& dst, const clang::NamedDecl& src) const +{ + if (!src.getDeclName()) + return; + + dst.name = src.getNameAsString(); + dst.mangledName = GetMangledName(src); +} + +std::string ASTNodeVisitor::GetMangledName(const clang::NamedDecl& ND) const +{ + // Source adapted from https://clang.llvm.org/doxygen/JSONNodeDumper_8cpp_source.html#l00845 + + // If the declaration is dependent or is in a dependent context, then the + // mangling is unlikely to be meaningful (and in some cases may cause + // "don't know how to mangle this" assertion failures.) + if (ND.isTemplated()) + return {}; + + // FIXME: There are likely other contexts in which it makes no sense to ask + // for a mangled name. + if (isa(ND.getDeclContext())) + return {}; + + // Do not mangle template deduction guides. + if (isa(ND)) + return {}; + + // Mangled names are not meaningful for locals, and may not be well-defined + // in the case of VLAs. + auto* VD = dyn_cast(&ND); + if (VD && VD->hasLocalStorage()) + return {}; + + return NameMangler.GetName(&ND); +} + +void ASTNodeVisitor::addPreviousDeclaration(const Decl* D) +{ + switch (D->getKind()) + { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + return writePreviousDeclImpl(cast(D)); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + +#undef ABSTRACT_DECL +#undef DECL + } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +} + +void ASTNodeVisitor::Visit(const Attr* A) +{ + const char* AttrName = nullptr; + switch (A->getKind()) + { +#define ATTR(X) \ + case attr::X: \ + AttrName = #X "Attr"; \ + break; +#include "clang/Basic/AttrList.inc" + +#undef ATTR + } + JOS.attribute("id", createPointerRepresentation(A)); + JOS.attribute("kind", AttrName); + JOS.attributeObject("range", [A, this] + { + writeSourceRange(A->getRange()); + }); + attributeOnlyIfTrue("inherited", A->isInherited()); + attributeOnlyIfTrue("implicit", A->isImplicit()); + + // FIXME: it would be useful for us to output the spelling kind as well as + // the actual spelling. This would allow us to distinguish between the + // various attribute syntaxes, but we don't currently track that information + // within the AST. + // JOS.attribute("spelling", A->getSpelling()); + + InnerAttrVisitor::Visit(A); +} + +void ASTNodeVisitor::Visit(const Stmt* S) +{ + JOS.attribute("id", createPointerRepresentation(S)); + + if (!S) + return; + + if (auto it = stmtMap.find(S); it != stmtMap.end()) + return; + stmtMap.emplace(S); + + JOS.attribute("kind", S->getStmtClassName()); + JOS.attributeObject("range", + [S, this] + { + writeSourceRange(S->getSourceRange()); + }); + + if (const auto* E = dyn_cast(S)) + { + JOS.attribute("type", createQualType(E->getType())); + const char* Category = nullptr; + switch (E->getValueKind()) + { + case VK_LValue: Category = "lvalue"; break; + case VK_XValue: Category = "xvalue"; break; + case VK_PRValue: + Category = "prvalue"; + break; + } + JOS.attribute("valueCategory", Category); + } + InnerStmtVisitor::Visit(S); +} + +void ASTNodeVisitor::Visit(const Type* T) +{ + JOS.attribute("id", createPointerRepresentation(T)); + + if (!T) + return; + + if (auto it = typeMap.find(T); it != typeMap.end()) + return; + typeMap.emplace(T); + + JOS.attribute("kind", (llvm::Twine(T->getTypeClassName()) + "Type").str()); + JOS.attribute("type", createQualType(QualType(T, 0), /*Desugar=*/false)); + attributeOnlyIfTrue("containsErrors", T->containsErrors()); + attributeOnlyIfTrue("isDependent", T->isDependentType()); + attributeOnlyIfTrue("isInstantiationDependent", + T->isInstantiationDependentType()); + attributeOnlyIfTrue("isVariablyModified", T->isVariablyModifiedType()); + attributeOnlyIfTrue("containsUnexpandedPack", + T->containsUnexpandedParameterPack()); + attributeOnlyIfTrue("isImported", T->isFromAST()); + InnerTypeVisitor::Visit(T); +} + +void ASTNodeVisitor::Visit(QualType T) +{ + JOS.attribute("id", createPointerRepresentation(T.getAsOpaquePtr())); + JOS.attribute("kind", "QualType"); + JOS.attribute("type", createQualType(T)); + JOS.attribute("qualifiers", T.split().Quals.getAsString()); +} + +void ASTNodeVisitor::Visit(TypeLoc TL) +{ + if (TL.isNull()) + return; + JOS.attribute("kind", + (llvm::Twine(TL.getTypeLocClass() == TypeLoc::Qualified ? "Qualified" : TL.getTypePtr()->getTypeClassName()) + + "TypeLoc") + .str()); + JOS.attribute("type", + createQualType(QualType(TL.getType()), /*Desugar=*/false)); + JOS.attributeObject("range", + [TL, this] + { + writeSourceRange(TL.getSourceRange()); + }); +} + +AST::Declaration* ASTNodeVisitor::Visit(const Decl* D) +{ + JOS.attribute("id", createPointerRepresentation(D)); + + if (!D) + return nullptr; + + if (auto it = declMap.find(D); it != declMap.end()) + return it->second; + + JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()); + JOS.attributeObject("loc", + [D, this] + { + writeSourceLocation(D->getLocation()); + }); + JOS.attributeObject("range", + [D, this] + { + writeSourceRange(D->getSourceRange()); + }); + attributeOnlyIfTrue("isImplicit", D->isImplicit()); + attributeOnlyIfTrue("isInvalid", D->isInvalidDecl()); + + if (D->isUsed()) + JOS.attribute("isUsed", true); + else if (D->isThisDeclarationReferenced()) + JOS.attribute("isReferenced", true); + + if (D->getLexicalDeclContext() != D->getDeclContext()) + { + // Because of multiple inheritance, a DeclContext pointer does not produce + // the same pointer representation as a Decl pointer that references the + // same AST Node. + const auto* ParentDeclContextDecl = dyn_cast(D->getDeclContext()); + JOS.attribute("parentDeclContextId", + createPointerRepresentation(ParentDeclContextDecl)); + } + + addPreviousDeclaration(D); + AST::Declaration* AST_D = InnerDeclVisitor::Visit(D); + if (!AST_D) + return nullptr; + + AST_D->originalPtr = (void*)D; + AST_D->kind = (AST::DeclarationKind)D->getKind(); + AST_D->location = SourceLocation(D->getLocation().getRawEncoding()); + + AST_D->isImplicit = D->isImplicit(); + AST_D->isInvalid = D->isInvalidDecl(); + AST_D->isUsed = D->isUsed(); + AST_D->isReferenced = D->isUsed() && D->isThisDeclarationReferenced(); + + AST_D->USR = GetDeclUSR(D); + AST_D->access = ConvertToAccess(D->getAccess()); + + return AST_D; +} + +void ASTNodeVisitor::Visit(const comments::Comment* C, const comments::FullComment* FC) +{ + if (!C) + return; + + JOS.attribute("id", createPointerRepresentation(C)); + JOS.attribute("kind", C->getCommentKindName()); + JOS.attributeObject("loc", + [C, this] + { + writeSourceLocation(C->getLocation()); + }); + JOS.attributeObject("range", + [C, this] + { + writeSourceRange(C->getSourceRange()); + }); + + InnerCommentVisitor::visit(C, FC); +} + +void ASTNodeVisitor::Visit(const TemplateArgument& TA, clang::SourceRange R, const Decl* From, StringRef Label) +{ + JOS.attribute("kind", "TemplateArgument"); + if (R.isValid()) + JOS.attributeObject("range", [R, this] + { + writeSourceRange(R); + }); + + if (From) + JOS.attribute(Label.empty() ? "fromDecl" : Label, createBareDeclRef(From)); + + InnerTemplateArgVisitor::Visit(TA); +} + +void ASTNodeVisitor::Visit(const CXXCtorInitializer* Init) +{ + JOS.attribute("kind", "CXXCtorInitializer"); + if (Init->isAnyMemberInitializer()) + JOS.attribute("anyInit", createBareDeclRef(Init->getAnyMember())); + else if (Init->isBaseInitializer()) + JOS.attribute("baseInit", + createQualType(QualType(Init->getBaseClass(), 0))); + else if (Init->isDelegatingInitializer()) + JOS.attribute("delegatingInit", + createQualType(Init->getTypeSourceInfo()->getType())); + else + llvm_unreachable("Unknown initializer type"); +} + +void ASTNodeVisitor::Visit(const BlockDecl::Capture& C) +{ + JOS.attribute("kind", "Capture"); + attributeOnlyIfTrue("byref", C.isByRef()); + attributeOnlyIfTrue("nested", C.isNested()); + if (C.getVariable()) + JOS.attribute("var", createBareDeclRef(C.getVariable())); +} + +void ASTNodeVisitor::Visit(const GenericSelectionExpr::ConstAssociation& A) +{ + JOS.attribute("associationKind", A.getTypeSourceInfo() ? "case" : "default"); + attributeOnlyIfTrue("selected", A.isSelected()); +} + +void ASTNodeVisitor::Visit(const concepts::Requirement* R) +{ + if (!R) + return; + + switch (R->getKind()) + { + case concepts::Requirement::RK_Type: + JOS.attribute("kind", "TypeRequirement"); + break; + case concepts::Requirement::RK_Simple: + JOS.attribute("kind", "SimpleRequirement"); + break; + case concepts::Requirement::RK_Compound: + JOS.attribute("kind", "CompoundRequirement"); + break; + case concepts::Requirement::RK_Nested: + JOS.attribute("kind", "NestedRequirement"); + break; + } + + if (auto* ER = dyn_cast(R)) + attributeOnlyIfTrue("noexcept", ER->hasNoexceptRequirement()); + + attributeOnlyIfTrue("isDependent", R->isDependent()); + if (!R->isDependent()) + JOS.attribute("satisfied", R->isSatisfied()); + attributeOnlyIfTrue("containsUnexpandedPack", + R->containsUnexpandedParameterPack()); +} + +void ASTNodeVisitor::Visit(const APValue& Value, QualType Ty) +{ + std::string Str; + llvm::raw_string_ostream OS(Str); + Value.printPretty(OS, Ctx, Ty); + JOS.attribute("value", Str); +} + +void ASTNodeVisitor::Visit(const ConceptReference* CR) +{ + JOS.attribute("kind", "ConceptReference"); + JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept())); + if (const auto* Args = CR->getTemplateArgsAsWritten()) + { + JOS.attributeArray("templateArgsAsWritten", [Args, this] + { + for (const TemplateArgumentLoc& TAL : Args->arguments()) + JOS.object( + [&TAL, this] + { + Visit(TAL.getArgument(), TAL.getSourceRange()); + }); + }); + } + /*JOS.attributeObject("loc", + [CR, this] { writeSourceLocation(CR->getLocation()); }); + JOS.attributeObject("range", + [CR, this] { writeSourceRange(CR->getSourceRange()); });*/ +} + +void ASTNodeVisitor::writeIncludeStack(PresumedLoc Loc, bool JustFirst) +{ + if (Loc.isInvalid()) + return; + + JOS.attributeBegin("includedFrom"); + JOS.objectBegin(); + + if (!JustFirst) + { + // Walk the stack recursively, then print out the presumed location. + writeIncludeStack(SM.getPresumedLoc(Loc.getIncludeLoc())); + } + + JOS.attribute("file", Loc.getFilename()); + JOS.objectEnd(); + JOS.attributeEnd(); +} + +void ASTNodeVisitor::writeBareSourceLocation(clang::SourceLocation Loc, bool IsSpelling, bool addFileInfo) +{ + PresumedLoc Presumed = SM.getPresumedLoc(Loc); + unsigned ActualLine = IsSpelling ? SM.getSpellingLineNumber(Loc) : SM.getExpansionLineNumber(Loc); + StringRef ActualFile = SM.getBufferName(Loc); + + if (!Presumed.isValid()) + return; + + JOS.attribute("offset", SM.getDecomposedLoc(Loc).second); + if (LastLocFilename != ActualFile) + { + if (addFileInfo) + JOS.attribute("file", ActualFile); + JOS.attribute("line", ActualLine); + } + else if (LastLocLine != ActualLine) + JOS.attribute("line", ActualLine); + + StringRef PresumedFile = Presumed.getFilename(); + if (PresumedFile != ActualFile && LastLocPresumedFilename != PresumedFile && addFileInfo) + JOS.attribute("presumedFile", PresumedFile); + + unsigned PresumedLine = Presumed.getLine(); + if (ActualLine != PresumedLine && LastLocPresumedLine != PresumedLine) + JOS.attribute("presumedLine", PresumedLine); + + JOS.attribute("col", Presumed.getColumn()); + JOS.attribute("tokLen", + Lexer::MeasureTokenLength(Loc, SM, Ctx.getLangOpts())); + LastLocFilename = ActualFile; + LastLocPresumedFilename = PresumedFile; + LastLocPresumedLine = PresumedLine; + LastLocLine = ActualLine; + + if (addFileInfo) + { + // Orthogonal to the file, line, and column de-duplication is whether the + // given location was a result of an include. If so, print where the + // include location came from. + writeIncludeStack(SM.getPresumedLoc(Presumed.getIncludeLoc()), + /*JustFirst*/ true); + } +} + +void ASTNodeVisitor::writeSourceLocation(clang::SourceLocation Loc, bool addFileInfo) +{ + clang::SourceLocation Spelling = SM.getSpellingLoc(Loc); + clang::SourceLocation Expansion = SM.getExpansionLoc(Loc); + + if (Expansion != Spelling) + { + // If the expansion and the spelling are different, output subobjects + // describing both locations. + JOS.attributeObject("spellingLoc", [Spelling, addFileInfo, this] + { + writeBareSourceLocation(Spelling, /*IsSpelling*/ true, addFileInfo); + }); + JOS.attributeObject("expansionLoc", [Expansion, addFileInfo, Loc, this] + { + writeBareSourceLocation(Expansion, /*IsSpelling*/ false, addFileInfo); + // If there is a macro expansion, add extra information if the interesting + // bit is the macro arg expansion. + if (SM.isMacroArgExpansion(Loc)) + JOS.attribute("isMacroArgExpansion", true); + }); + } + else + writeBareSourceLocation(Spelling, /*IsSpelling*/ true, addFileInfo); +} + +void ASTNodeVisitor::writeSourceRange(clang::SourceRange R) +{ + JOS.attributeObject("begin", + [R, this] + { + writeSourceLocation(R.getBegin(), false); + }); + + JOS.attributeObject("end", [R, this] + { + writeSourceLocation(R.getEnd(), false); + }); +} + +std::string ASTNodeVisitor::createPointerRepresentation(const void* Ptr) +{ + // Because JSON stores integer values as signed 64-bit integers, trying to + // represent them as such makes for very ugly pointer values in the resulting + // output. Instead, we convert the value to hex and treat it as a string. + return "0x" + llvm::utohexstr(reinterpret_cast(Ptr), true); +} + +llvm::json::Object ASTNodeVisitor::createQualType(QualType QT, bool Desugar) +{ + SplitQualType SQT = QT.split(); + std::string SQTS = QualType::getAsString(SQT, PrintPolicy); + llvm::json::Object Ret{ { "qualType", SQTS } }; + + if (Desugar && !QT.isNull()) + { + SplitQualType DSQT = QT.getSplitDesugaredType(); + if (DSQT != SQT) + { + std::string DSQTS = QualType::getAsString(DSQT, PrintPolicy); + if (DSQTS != SQTS) + Ret["desugaredQualType"] = DSQTS; + } + if (const auto* TT = QT->getAs()) + Ret["typeAliasDeclId"] = createPointerRepresentation(TT->getDecl()); + } + return Ret; +} + +AST::QualifiedType ASTNodeVisitor::CreateQualifiedType(QualType QT, bool Desugar) +{ + if (QT.isNull()) + return {}; + + SplitQualType SQT = QT.split(); + AST::QualifiedType Ret; + Ret.qualifiers = GetTypeQualifiers(SQT.Quals); + // Ret.type = Visit(SQT.Ty); // TODO: Implement Visit + + if (Desugar) + { + SplitQualType DSQT = QT.getSplitDesugaredType(); + if (DSQT != SQT) + { + // Ret.desugaredType = Visit(DSQT.Ty); + } + + if (const auto* TT = QT->getAs()) + Ret.typeAliasDeclId = (void*)TT->getDecl(); + } + return Ret; +} + +void ASTNodeVisitor::writeBareDeclRef(const Decl* D) +{ + JOS.attribute("id", createPointerRepresentation(D)); + if (!D) + return; + + JOS.attribute("kind", (llvm::Twine(D->getDeclKindName()) + "Decl").str()); + if (const auto* ND = dyn_cast(D)) + JOS.attribute("name", ND->getDeclName().getAsString()); + if (const auto* VD = dyn_cast(D)) + JOS.attribute("type", createQualType(VD->getType())); +} + +llvm::json::Object ASTNodeVisitor::createBareDeclRef(const Decl* D) +{ + llvm::json::Object Ret{ { "id", createPointerRepresentation(D) } }; + if (!D) + return Ret; + + Ret["kind"] = (llvm::Twine(D->getDeclKindName()) + "Decl").str(); + if (const auto* ND = dyn_cast(D)) + Ret["name"] = ND->getDeclName().getAsString(); + if (const auto* VD = dyn_cast(D)) + Ret["type"] = createQualType(VD->getType()); + return Ret; +} + +llvm::json::Array ASTNodeVisitor::createCastPath(const CastExpr* C) +{ + llvm::json::Array Ret; + if (C->path_empty()) + return Ret; + + for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) + { + const CXXBaseSpecifier* Base = *I; + const auto* RD = + cast(Base->getType()->castAs()->getDecl()); + + llvm::json::Object Val{ { "name", RD->getName() } }; + if (Base->isVirtual()) + Val["isVirtual"] = true; + Ret.push_back(std::move(Val)); + } + return Ret; +} + +#define FIELD2(Name, Flag) \ + if (RD->Flag()) \ + Ret[Name] = true +#define FIELD1(Flag) FIELD2(#Flag, Flag) + +static llvm::json::Object createDefaultConstructorDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("exists", hasDefaultConstructor); + FIELD2("trivial", hasTrivialDefaultConstructor); + FIELD2("nonTrivial", hasNonTrivialDefaultConstructor); + FIELD2("userProvided", hasUserProvidedDefaultConstructor); + FIELD2("isConstexpr", hasConstexprDefaultConstructor); + FIELD2("needsImplicit", needsImplicitDefaultConstructor); + FIELD2("defaultedIsConstexpr", defaultedDefaultConstructorIsConstexpr); + + return Ret; +} + +static llvm::json::Object createCopyConstructorDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("simple", hasSimpleCopyConstructor); + FIELD2("trivial", hasTrivialCopyConstructor); + FIELD2("nonTrivial", hasNonTrivialCopyConstructor); + FIELD2("userDeclared", hasUserDeclaredCopyConstructor); + FIELD2("hasConstParam", hasCopyConstructorWithConstParam); + FIELD2("implicitHasConstParam", implicitCopyConstructorHasConstParam); + FIELD2("needsImplicit", needsImplicitCopyConstructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyConstructor); + if (!RD->needsOverloadResolutionForCopyConstructor()) + FIELD2("defaultedIsDeleted", defaultedCopyConstructorIsDeleted); + + return Ret; +} + +static llvm::json::Object createMoveConstructorDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("exists", hasMoveConstructor); + FIELD2("simple", hasSimpleMoveConstructor); + FIELD2("trivial", hasTrivialMoveConstructor); + FIELD2("nonTrivial", hasNonTrivialMoveConstructor); + FIELD2("userDeclared", hasUserDeclaredMoveConstructor); + FIELD2("needsImplicit", needsImplicitMoveConstructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveConstructor); + if (!RD->needsOverloadResolutionForMoveConstructor()) + FIELD2("defaultedIsDeleted", defaultedMoveConstructorIsDeleted); + + return Ret; +} + +static llvm::json::Object createCopyAssignmentDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("simple", hasSimpleCopyAssignment); + FIELD2("trivial", hasTrivialCopyAssignment); + FIELD2("nonTrivial", hasNonTrivialCopyAssignment); + FIELD2("hasConstParam", hasCopyAssignmentWithConstParam); + FIELD2("implicitHasConstParam", implicitCopyAssignmentHasConstParam); + FIELD2("userDeclared", hasUserDeclaredCopyAssignment); + FIELD2("needsImplicit", needsImplicitCopyAssignment); + FIELD2("needsOverloadResolution", needsOverloadResolutionForCopyAssignment); + + return Ret; +} + +static llvm::json::Object createMoveAssignmentDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("exists", hasMoveAssignment); + FIELD2("simple", hasSimpleMoveAssignment); + FIELD2("trivial", hasTrivialMoveAssignment); + FIELD2("nonTrivial", hasNonTrivialMoveAssignment); + FIELD2("userDeclared", hasUserDeclaredMoveAssignment); + FIELD2("needsImplicit", needsImplicitMoveAssignment); + FIELD2("needsOverloadResolution", needsOverloadResolutionForMoveAssignment); + + return Ret; +} + +static llvm::json::Object createDestructorDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + FIELD2("simple", hasSimpleDestructor); + FIELD2("irrelevant", hasIrrelevantDestructor); + FIELD2("trivial", hasTrivialDestructor); + FIELD2("nonTrivial", hasNonTrivialDestructor); + FIELD2("userDeclared", hasUserDeclaredDestructor); + FIELD2("needsImplicit", needsImplicitDestructor); + FIELD2("needsOverloadResolution", needsOverloadResolutionForDestructor); + if (!RD->needsOverloadResolutionForDestructor()) + FIELD2("defaultedIsDeleted", defaultedDestructorIsDeleted); + + return Ret; +} + +llvm::json::Object ASTNodeVisitor::createCXXRecordDefinitionData(const CXXRecordDecl* RD) +{ + llvm::json::Object Ret; + + // This data is common to all C++ classes. + FIELD1(isGenericLambda); + FIELD1(isLambda); + FIELD1(isEmpty); + FIELD1(isAggregate); + FIELD1(isStandardLayout); + FIELD1(isTriviallyCopyable); + FIELD1(isPOD); + FIELD1(isTrivial); + FIELD1(isPolymorphic); + FIELD1(isAbstract); + FIELD1(isLiteral); + FIELD1(canPassInRegisters); + FIELD1(hasUserDeclaredConstructor); + FIELD1(hasConstexprNonCopyMoveConstructor); + FIELD1(hasMutableFields); + FIELD1(hasVariantMembers); + FIELD2("canConstDefaultInit", allowConstDefaultInit); + + Ret["defaultCtor"] = createDefaultConstructorDefinitionData(RD); + Ret["copyCtor"] = createCopyConstructorDefinitionData(RD); + Ret["moveCtor"] = createMoveConstructorDefinitionData(RD); + Ret["copyAssign"] = createCopyAssignmentDefinitionData(RD); + Ret["moveAssign"] = createMoveAssignmentDefinitionData(RD); + Ret["dtor"] = createDestructorDefinitionData(RD); + + return Ret; +} + +#undef FIELD1 +#undef FIELD2 + +std::string ASTNodeVisitor::createAccessSpecifier(AccessSpecifier AS) +{ + const auto AccessSpelling = getAccessSpelling(AS); + if (AccessSpelling.empty()) + return "none"; + return AccessSpelling.str(); +} + +llvm::json::Object ASTNodeVisitor::createCXXBaseSpecifier(const CXXBaseSpecifier& BS) +{ + llvm::json::Object Ret; + + Ret["type"] = createQualType(BS.getType()); + Ret["access"] = createAccessSpecifier(BS.getAccessSpecifier()); + Ret["writtenAccess"] = + createAccessSpecifier(BS.getAccessSpecifierAsWritten()); + if (BS.isVirtual()) + Ret["isVirtual"] = true; + if (BS.isPackExpansion()) + Ret["isPackExpansion"] = true; + + return Ret; +} + +void ASTNodeVisitor::VisitAliasAttr(const AliasAttr* AA) +{ + JOS.attribute("aliasee", AA->getAliasee()); +} + +void ASTNodeVisitor::VisitCleanupAttr(const CleanupAttr* CA) +{ + JOS.attribute("cleanup_function", createBareDeclRef(CA->getFunctionDecl())); +} + +void ASTNodeVisitor::VisitDeprecatedAttr(const DeprecatedAttr* DA) +{ + if (!DA->getMessage().empty()) + JOS.attribute("message", DA->getMessage()); + if (!DA->getReplacement().empty()) + JOS.attribute("replacement", DA->getReplacement()); +} + +void ASTNodeVisitor::VisitUnavailableAttr(const UnavailableAttr* UA) +{ + if (!UA->getMessage().empty()) + JOS.attribute("message", UA->getMessage()); +} + +void ASTNodeVisitor::VisitSectionAttr(const SectionAttr* SA) +{ + JOS.attribute("section_name", SA->getName()); +} + +void ASTNodeVisitor::VisitVisibilityAttr(const VisibilityAttr* VA) +{ + JOS.attribute("visibility", VisibilityAttr::ConvertVisibilityTypeToStr( + VA->getVisibility())); +} + +void ASTNodeVisitor::VisitTLSModelAttr(const TLSModelAttr* TA) +{ + JOS.attribute("tls_model", TA->getModel()); +} + +void ASTNodeVisitor::VisitTypedefType(const TypedefType* TT) +{ + JOS.attribute("decl", createBareDeclRef(TT->getDecl())); + if (!TT->typeMatchesDecl()) + JOS.attribute("type", createQualType(TT->desugar())); +} + +void ASTNodeVisitor::VisitUsingType(const UsingType* TT) +{ + JOS.attribute("decl", createBareDeclRef(TT->getFoundDecl())); + if (!TT->typeMatchesDecl()) + JOS.attribute("type", createQualType(TT->desugar())); +} + +void ASTNodeVisitor::VisitFunctionType(const FunctionType* T) +{ + FunctionType::ExtInfo E = T->getExtInfo(); + attributeOnlyIfTrue("noreturn", E.getNoReturn()); + attributeOnlyIfTrue("producesResult", E.getProducesResult()); + if (E.getHasRegParm()) + JOS.attribute("regParm", E.getRegParm()); + JOS.attribute("cc", FunctionType::getNameForCallConv(E.getCC())); +} + +void ASTNodeVisitor::VisitFunctionProtoType(const FunctionProtoType* T) +{ + FunctionProtoType::ExtProtoInfo E = T->getExtProtoInfo(); + attributeOnlyIfTrue("trailingReturn", E.HasTrailingReturn); + attributeOnlyIfTrue("const", T->isConst()); + attributeOnlyIfTrue("volatile", T->isVolatile()); + attributeOnlyIfTrue("restrict", T->isRestrict()); + attributeOnlyIfTrue("variadic", E.Variadic); + switch (E.RefQualifier) + { + case RQ_LValue: JOS.attribute("refQualifier", "&"); break; + case RQ_RValue: JOS.attribute("refQualifier", "&&"); break; + case RQ_None: break; + } + switch (E.ExceptionSpec.Type) + { + case EST_DynamicNone: + case EST_Dynamic: + { + JOS.attribute("exceptionSpec", "throw"); + llvm::json::Array Types; + for (QualType QT : E.ExceptionSpec.Exceptions) + Types.push_back(createQualType(QT)); + JOS.attribute("exceptionTypes", std::move(Types)); + } + break; + case EST_MSAny: + JOS.attribute("exceptionSpec", "throw"); + JOS.attribute("throwsAny", true); + break; + case EST_BasicNoexcept: + JOS.attribute("exceptionSpec", "noexcept"); + break; + case EST_NoexceptTrue: + case EST_NoexceptFalse: + JOS.attribute("exceptionSpec", "noexcept"); + JOS.attribute("conditionEvaluatesTo", + E.ExceptionSpec.Type == EST_NoexceptTrue); + // JOS.attributeWithCall("exceptionSpecExpr", + // [this, E]() { Visit(E.ExceptionSpec.NoexceptExpr); }); + break; + case EST_NoThrow: + JOS.attribute("exceptionSpec", "nothrow"); + break; + // FIXME: I cannot find a way to trigger these cases while dumping the AST. I + // suspect you can only run into them when executing an AST dump from within + // the debugger, which is not a use case we worry about for the JSON dumping + // feature. + case EST_DependentNoexcept: + case EST_Unevaluated: + case EST_Uninstantiated: + case EST_Unparsed: + case EST_None: break; + } + VisitFunctionType(T); +} + +void ASTNodeVisitor::VisitRValueReferenceType(const ReferenceType* RT) +{ + attributeOnlyIfTrue("spelledAsLValue", RT->isSpelledAsLValue()); +} + +void ASTNodeVisitor::VisitArrayType(const ArrayType* AT) +{ + switch (AT->getSizeModifier()) + { + case ArrayType::ArraySizeModifier::Star: + JOS.attribute("sizeModifier", "*"); + break; + case ArrayType::ArraySizeModifier::Static: + JOS.attribute("sizeModifier", "static"); + break; + case ArrayType::ArraySizeModifier::Normal: + break; + } + + std::string Str = AT->getIndexTypeQualifiers().getAsString(); + if (!Str.empty()) + JOS.attribute("indexTypeQualifiers", Str); +} + +void ASTNodeVisitor::VisitConstantArrayType(const ConstantArrayType* CAT) +{ + // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a + // narrowing conversion to int64_t so it cannot be expressed. + JOS.attribute("size", CAT->getSize().getSExtValue()); + VisitArrayType(CAT); +} + +void ASTNodeVisitor::VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType* VT) +{ + JOS.attributeObject( + "attrLoc", [VT, this] + { + writeSourceLocation(VT->getAttributeLoc()); + }); +} + +void ASTNodeVisitor::VisitVectorType(const VectorType* VT) +{ + JOS.attribute("numElements", VT->getNumElements()); + switch (VT->getVectorKind()) + { + case VectorType::VectorKind::GenericVector: + break; + case VectorType::VectorKind::AltiVecVector: + JOS.attribute("vectorKind", "altivec"); + break; + case VectorType::VectorKind::AltiVecPixel: + JOS.attribute("vectorKind", "altivec pixel"); + break; + case VectorType::VectorKind::AltiVecBool: + JOS.attribute("vectorKind", "altivec bool"); + break; + case VectorType::VectorKind::NeonVector: + JOS.attribute("vectorKind", "neon"); + break; + case VectorType::VectorKind::NeonPolyVector: + JOS.attribute("vectorKind", "neon poly"); + break; + case VectorType::VectorKind::SveFixedLengthDataVector: + JOS.attribute("vectorKind", "fixed-length sve data vector"); + break; + case VectorType::VectorKind::SveFixedLengthPredicateVector: + JOS.attribute("vectorKind", "fixed-length sve predicate vector"); + break; + case VectorType::VectorKind::RVVFixedLengthDataVector: + JOS.attribute("vectorKind", "fixed-length rvv data vector"); + break; + /*case VectorType::VectorKind::RVVFixedLengthMask: + case VectorType::VectorKind::RVVFixedLengthMask_1: + case VectorType::VectorKind::RVVFixedLengthMask_2: + case VectorType::VectorKind::RVVFixedLengthMask_4: + JOS.attribute("vectorKind", "fixed-length rvv mask vector"); + break;*/ + } +} + +void ASTNodeVisitor::VisitUnresolvedUsingType(const UnresolvedUsingType* UUT) +{ + JOS.attribute("decl", createBareDeclRef(UUT->getDecl())); +} + +void ASTNodeVisitor::VisitUnaryTransformType(const UnaryTransformType* UTT) +{ + switch (UTT->getUTTKind()) + { +#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \ + case UnaryTransformType::Enum: \ + JOS.attribute("transformKind", #Trait); \ + break; +#include "clang/Basic/TransformTypeTraits.def" + } +} + +void ASTNodeVisitor::VisitTagType(const TagType* TT) +{ + JOS.attribute("decl", createBareDeclRef(TT->getDecl())); +} + +void ASTNodeVisitor::VisitTemplateTypeParmType( + const TemplateTypeParmType* TTPT) +{ + JOS.attribute("depth", TTPT->getDepth()); + JOS.attribute("index", TTPT->getIndex()); + attributeOnlyIfTrue("isPack", TTPT->isParameterPack()); + JOS.attribute("decl", createBareDeclRef(TTPT->getDecl())); +} + +void ASTNodeVisitor::VisitSubstTemplateTypeParmType( + const SubstTemplateTypeParmType* STTPT) +{ + JOS.attribute("index", STTPT->getIndex()); + if (auto PackIndex = STTPT->getPackIndex()) + JOS.attribute("pack_index", *PackIndex); +} + +void ASTNodeVisitor::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType* T) +{ + JOS.attribute("index", T->getIndex()); +} + +void ASTNodeVisitor::VisitAutoType(const AutoType* AT) +{ + JOS.attribute("undeduced", !AT->isDeduced()); + switch (AT->getKeyword()) + { + case AutoTypeKeyword::Auto: + JOS.attribute("typeKeyword", "auto"); + break; + case AutoTypeKeyword::DecltypeAuto: + JOS.attribute("typeKeyword", "decltype(auto)"); + break; + case AutoTypeKeyword::GNUAutoType: + JOS.attribute("typeKeyword", "__auto_type"); + break; + } +} + +void ASTNodeVisitor::VisitTemplateSpecializationType( + const TemplateSpecializationType* TST) +{ + attributeOnlyIfTrue("isAlias", TST->isTypeAlias()); + + std::string Str; + llvm::raw_string_ostream OS(Str); + TST->getTemplateName().print(OS, PrintPolicy); + JOS.attribute("templateName", Str); +} + +void ASTNodeVisitor::VisitInjectedClassNameType( + const InjectedClassNameType* ICNT) +{ + JOS.attribute("decl", createBareDeclRef(ICNT->getDecl())); +} + +void ASTNodeVisitor::VisitObjCInterfaceType(const ObjCInterfaceType* OIT) +{ + JOS.attribute("decl", createBareDeclRef(OIT->getDecl())); +} + +void ASTNodeVisitor::VisitPackExpansionType(const PackExpansionType* PET) +{ + if (std::optional N = PET->getNumExpansions()) + JOS.attribute("numExpansions", *N); +} + +void ASTNodeVisitor::VisitElaboratedType(const ElaboratedType* ET) +{ + if (const NestedNameSpecifier* NNS = ET->getQualifier()) + { + std::string Str; + llvm::raw_string_ostream OS(Str); + NNS->print(OS, PrintPolicy, /*ResolveTemplateArgs*/ true); + JOS.attribute("qualifier", Str); + } + if (const TagDecl* TD = ET->getOwnedTagDecl()) + JOS.attribute("ownedTagDecl", createBareDeclRef(TD)); +} + +void ASTNodeVisitor::VisitMacroQualifiedType(const MacroQualifiedType* MQT) +{ + JOS.attribute("macroName", MQT->getMacroIdentifier()->getName()); +} + +void ASTNodeVisitor::VisitMemberPointerType(const MemberPointerType* MPT) +{ + attributeOnlyIfTrue("isData", MPT->isMemberDataPointer()); + attributeOnlyIfTrue("isFunction", MPT->isMemberFunctionPointer()); +} + +AST::Declaration* ASTNodeVisitor::VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D) +{ + AST::TranslationUnit* TU = parser.GetOrCreateTranslationUnit(D); + declMap.emplace(D, TU); + return TU; +} + +AST::Declaration* ASTNodeVisitor::VisitNamedDecl(const NamedDecl* ND) +{ + if (!ND) + return nullptr; + + if (!ND->getDeclName()) + return nullptr; + + JOS.attribute("name", ND->getNameAsString()); + + std::string MangledName = parser.GetDeclMangledName(ND); + if (!MangledName.empty()) + JOS.attribute("mangledName", MangledName); + + declMap.try_emplace(ND, nullptr); + + return nullptr; +} + +void ASTNodeVisitor::HandleNamedDecl(AST::Declaration& AST_ND, const NamedDecl* ND) +{ + if (!ND) + return; + + declMap.emplace(ND, &AST_ND); + + AST_ND.name = ND->getName(); + AST_ND.mangledName = parser.GetDeclMangledName(ND); + AST_ND.isHidden = !ND->isUnconditionallyVisible(); // TODO: Sema::isVisible()? +} + +AST::Declaration* ASTNodeVisitor::VisitTypedefDecl(const TypedefDecl* TD) +{ + AST::Declaration* Decl = VisitNamedDecl(TD); + JOS.attribute("type", createQualType(TD->getUnderlyingType())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitTypeAliasDecl(const TypeAliasDecl* TAD) +{ + auto NS = parser.GetNamespace(TAD); + auto Name = GetDeclName(TAD); + + auto AST_TAD = NS->FindTypeAlias(Name, /*Create=*/false); + + if (AST_TAD) + return AST_TAD; + + AST_TAD = NS->FindTypeAlias(Name, /*Create=*/true); + HandleNamedDecl(*AST_TAD, TAD); + + VisitNamedDecl(TAD); + JOS.attribute("type", createQualType(TAD->getUnderlyingType())); + return AST_TAD; +} + +AST::Declaration* ASTNodeVisitor::VisitNamespaceDecl(const NamespaceDecl* ND) +{ + AST::TranslationUnit* Unit = parser.GetOrCreateTranslationUnit(cast(ND->getDeclContext())); + AST::Namespace& NS = Unit->FindCreateNamespace(ND->getName()); + + NS.isInline = ND->isInline(); + NS.isNested = ND->isNested(); + NS.isAnonymous = ND->isAnonymousNamespace(); + + HandleNamedDecl(NS, ND); + + VisitNamedDecl(ND); + attributeOnlyIfTrue("isInline", ND->isInline()); + attributeOnlyIfTrue("isNested", ND->isNested()); + if (!ND->isFirstDecl()) + JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl())); + + return &NS; +} + +AST::Declaration* ASTNodeVisitor::VisitUsingDirectiveDecl(const UsingDirectiveDecl* UDD) +{ + JOS.attribute("nominatedNamespace", + createBareDeclRef(UDD->getNominatedNamespace())); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitNamespaceAliasDecl(const NamespaceAliasDecl* NAD) +{ + AST::Declaration* Decl = VisitNamedDecl(NAD); + JOS.attribute("aliasedNamespace", + createBareDeclRef(NAD->getAliasedNamespace())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitUsingDecl(const UsingDecl* UD) +{ + std::string Name; + if (const NestedNameSpecifier* NNS = UD->getQualifier()) + { + llvm::raw_string_ostream SOS(Name); + NNS->print(SOS, UD->getASTContext().getPrintingPolicy()); + } + Name += UD->getNameAsString(); + JOS.attribute("name", Name); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitUsingEnumDecl(const UsingEnumDecl* UED) +{ + JOS.attribute("target", createBareDeclRef(UED->getEnumDecl())); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitUsingShadowDecl(const UsingShadowDecl* USD) +{ + JOS.attribute("target", createBareDeclRef(USD->getTargetDecl())); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitVarDecl(const VarDecl* VD) +{ + AST::Declaration* Decl = VisitNamedDecl(VD); + JOS.attribute("type", createQualType(VD->getType())); + + // TODO: clang 19 + // if (const auto* P = dyn_cast(VD)) + // attributeOnlyIfTrue("explicitObjectParameter", P-isExplicitObjectParameter()); + + StorageClass SC = VD->getStorageClass(); + if (SC != SC_None) + JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); + switch (VD->getTLSKind()) + { + case VarDecl::TLS_Dynamic: JOS.attribute("tls", "dynamic"); break; + case VarDecl::TLS_Static: JOS.attribute("tls", "static"); break; + case VarDecl::TLS_None: break; + } + attributeOnlyIfTrue("nrvo", VD->isNRVOVariable()); + attributeOnlyIfTrue("inline", VD->isInline()); + attributeOnlyIfTrue("constexpr", VD->isConstexpr()); + attributeOnlyIfTrue("modulePrivate", VD->isModulePrivate()); + if (VD->hasInit()) + { + switch (VD->getInitStyle()) + { + case VarDecl::CInit: JOS.attribute("init", "c"); break; + case VarDecl::CallInit: JOS.attribute("init", "call"); break; + case VarDecl::ListInit: JOS.attribute("init", "list"); break; + case VarDecl::ParenListInit: + JOS.attribute("init", "paren-list"); + break; + } + } + attributeOnlyIfTrue("isParameterPack", VD->isParameterPack()); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitFieldDecl(const FieldDecl* FD) +{ + AST::Declaration* Decl = VisitNamedDecl(FD); + JOS.attribute("type", createQualType(FD->getType())); + attributeOnlyIfTrue("mutable", FD->isMutable()); + attributeOnlyIfTrue("modulePrivate", FD->isModulePrivate()); + attributeOnlyIfTrue("isBitfield", FD->isBitField()); + attributeOnlyIfTrue("hasInClassInitializer", FD->hasInClassInitializer()); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitFunctionDecl(const FunctionDecl* FD) +{ + AST::Declaration* Decl = VisitNamedDecl(FD); + JOS.attribute("type", createQualType(FD->getType())); + StorageClass SC = FD->getStorageClass(); + if (SC != SC_None) + JOS.attribute("storageClass", VarDecl::getStorageClassSpecifierString(SC)); + attributeOnlyIfTrue("inline", FD->isInlineSpecified()); + attributeOnlyIfTrue("virtual", FD->isVirtualAsWritten()); + attributeOnlyIfTrue("pure", FD->isPure()); // // TODO: clang 19 isPureVirtual + attributeOnlyIfTrue("explicitlyDeleted", FD->isDeletedAsWritten()); + attributeOnlyIfTrue("constexpr", FD->isConstexpr()); + attributeOnlyIfTrue("variadic", FD->isVariadic()); + attributeOnlyIfTrue("immediate", FD->isImmediateFunction()); + + if (FD->isDefaulted()) + JOS.attribute("explicitlyDefaulted", + FD->isDeleted() ? "deleted" : "default"); + + // TODO: clang 19 + /*if (StringLiteral* Msg = FD->getDeletedMessage()) + JOS.attribute("deletedMessage", Msg->getString());*/ + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitEnumDecl(const EnumDecl* ED) +{ + AST::Declaration* Decl = VisitNamedDecl(ED); + if (ED->isFixed()) + JOS.attribute("fixedUnderlyingType", createQualType(ED->getIntegerType())); + if (ED->isScoped()) + JOS.attribute("scopedEnumTag", + ED->isScopedUsingClassTag() ? "class" : "struct"); + return Decl; +} +AST::Declaration* ASTNodeVisitor::VisitEnumConstantDecl(const EnumConstantDecl* ECD) +{ + AST::Declaration* Decl = VisitNamedDecl(ECD); + JOS.attribute("type", createQualType(ECD->getType())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitRecordDecl(const RecordDecl* RD) +{ + AST::Declaration* Decl = VisitNamedDecl(RD); + JOS.attribute("tagUsed", RD->getKindName()); + attributeOnlyIfTrue("completeDefinition", RD->isCompleteDefinition()); + return Decl; +} +AST::Declaration* ASTNodeVisitor::VisitCXXRecordDecl(const CXXRecordDecl* RD) +{ + return FindOrInsertLazy(RD, [&]() -> AST::Class* + { + VisitRecordDecl(RD); + + // All other information requires a complete definition. + if (!RD->isCompleteDefinition()) + return nullptr; + + JOS.attribute("definitionData", createCXXRecordDefinitionData(RD)); + if (RD->getNumBases()) + { + JOS.attributeArray("bases", [this, RD] + { + for (const auto& Spec : RD->bases()) + JOS.value(createCXXBaseSpecifier(Spec)); + }); + } + + bool Process = false; + AST::Class* RC = parser.GetRecord(RD, Process); + + if (!RC || !Process) + return RC; + + parser.WalkRecordCXX(RD, RC); + return RC; + }); +} + +AST::Declaration* ASTNodeVisitor::VisitHLSLBufferDecl(const HLSLBufferDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("bufferKind", D->isCBuffer() ? "cbuffer" : "tbuffer"); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("tagUsed", D->wasDeclaredWithTypename() ? "typename" : "class"); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); + + // TODO: clang 19 + /*if (D->hasDefaultArgument()) + JOS.attributeObject("defaultArg", [=] { + Visit(D->getDefaultArgument().getArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + });*/ + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("type", createQualType(D->getType())); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); + + // TODO: clang 19 + /*if (D->hasDefaultArgument()) + JOS.attributeObject("defaultArg", [=] { + Visit(D->getDefaultArgument().getArgument(), SourceRange(), + D->getDefaultArgStorage().getInheritedFrom(), + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + });*/ + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("depth", D->getDepth()); + JOS.attribute("index", D->getIndex()); + attributeOnlyIfTrue("isParameterPack", D->isParameterPack()); + + if (D->hasDefaultArgument()) + JOS.attributeObject("defaultArg", [&] + { + const auto* InheritedFrom = D->getDefaultArgStorage().getInheritedFrom(); + Visit(D->getDefaultArgument().getArgument(), + InheritedFrom ? InheritedFrom->getSourceRange() : clang::SourceLocation{}, + InheritedFrom, + D->defaultArgumentWasInherited() ? "inherited from" : "previous"); + }); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitLinkageSpecDecl(const LinkageSpecDecl* LSD) +{ + StringRef Lang; + switch (LSD->getLanguage()) + { + case LinkageSpecDecl::LanguageIDs::lang_c: + Lang = "C"; + break; + case LinkageSpecDecl::LanguageIDs::lang_cxx: + Lang = "C++"; + break; + } + JOS.attribute("language", Lang); + attributeOnlyIfTrue("hasBraces", LSD->hasBraces()); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitAccessSpecDecl(const AccessSpecDecl* ASD) +{ + JOS.attribute("access", createAccessSpecifier(ASD->getAccess())); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitFriendDecl(const FriendDecl* FD) +{ + if (const TypeSourceInfo* T = FD->getFriendType()) + JOS.attribute("type", createQualType(T->getType())); + // TODO: clang 19 + // attributeOnlyIfTrue("isPackExpansion", FD->isPackExpansion()); + return nullptr; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCIvarDecl(const ObjCIvarDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("type", createQualType(D->getType())); + attributeOnlyIfTrue("synthesized", D->getSynthesize()); + switch (D->getAccessControl()) + { + case ObjCIvarDecl::None: JOS.attribute("access", "none"); break; + case ObjCIvarDecl::Private: JOS.attribute("access", "private"); break; + case ObjCIvarDecl::Protected: JOS.attribute("access", "protected"); break; + case ObjCIvarDecl::Public: JOS.attribute("access", "public"); break; + case ObjCIvarDecl::Package: JOS.attribute("access", "package"); break; + } + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCMethodDecl(const ObjCMethodDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("returnType", createQualType(D->getReturnType())); + JOS.attribute("instance", D->isInstanceMethod()); + attributeOnlyIfTrue("variadic", D->isVariadic()); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCTypeParamDecl(const ObjCTypeParamDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("type", createQualType(D->getUnderlyingType())); + attributeOnlyIfTrue("bounded", D->hasExplicitBound()); + switch (D->getVariance()) + { + case ObjCTypeParamVariance::Invariant: + break; + case ObjCTypeParamVariance::Covariant: + JOS.attribute("variance", "covariant"); + break; + case ObjCTypeParamVariance::Contravariant: + JOS.attribute("variance", "contravariant"); + break; + } + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("interface", createBareDeclRef(D->getClassInterface())); + JOS.attribute("implementation", createBareDeclRef(D->getImplementation())); + + llvm::json::Array Protocols; + for (const auto* P : D->protocols()) + Protocols.push_back(createBareDeclRef(P)); + if (!Protocols.empty()) + JOS.attribute("protocols", std::move(Protocols)); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("interface", createBareDeclRef(D->getClassInterface())); + JOS.attribute("categoryDecl", createBareDeclRef(D->getCategoryDecl())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCProtocolDecl(const ObjCProtocolDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + + llvm::json::Array Protocols; + for (const auto* P : D->protocols()) + Protocols.push_back(createBareDeclRef(P)); + if (!Protocols.empty()) + JOS.attribute("protocols", std::move(Protocols)); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("super", createBareDeclRef(D->getSuperClass())); + JOS.attribute("implementation", createBareDeclRef(D->getImplementation())); + + llvm::json::Array Protocols; + for (const auto* P : D->protocols()) + Protocols.push_back(createBareDeclRef(P)); + if (!Protocols.empty()) + JOS.attribute("protocols", std::move(Protocols)); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCImplementationDecl( + const ObjCImplementationDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("super", createBareDeclRef(D->getSuperClass())); + JOS.attribute("interface", createBareDeclRef(D->getClassInterface())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCCompatibleAliasDecl( + const ObjCCompatibleAliasDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("interface", createBareDeclRef(D->getClassInterface())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCPropertyDecl(const ObjCPropertyDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D); + JOS.attribute("type", createQualType(D->getType())); + + switch (D->getPropertyImplementation()) + { + case ObjCPropertyDecl::None: break; + case ObjCPropertyDecl::Required: JOS.attribute("control", "required"); break; + case ObjCPropertyDecl::Optional: JOS.attribute("control", "optional"); break; + } + + ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes(); + if (Attrs != ObjCPropertyAttribute::kind_noattr) + { + if (Attrs & ObjCPropertyAttribute::kind_getter) + JOS.attribute("getter", createBareDeclRef(D->getGetterMethodDecl())); + if (Attrs & ObjCPropertyAttribute::kind_setter) + JOS.attribute("setter", createBareDeclRef(D->getSetterMethodDecl())); + attributeOnlyIfTrue("readonly", + Attrs & ObjCPropertyAttribute::kind_readonly); + attributeOnlyIfTrue("assign", Attrs & ObjCPropertyAttribute::kind_assign); + attributeOnlyIfTrue("readwrite", + Attrs & ObjCPropertyAttribute::kind_readwrite); + attributeOnlyIfTrue("retain", Attrs & ObjCPropertyAttribute::kind_retain); + attributeOnlyIfTrue("copy", Attrs & ObjCPropertyAttribute::kind_copy); + attributeOnlyIfTrue("nonatomic", + Attrs & ObjCPropertyAttribute::kind_nonatomic); + attributeOnlyIfTrue("atomic", Attrs & ObjCPropertyAttribute::kind_atomic); + attributeOnlyIfTrue("weak", Attrs & ObjCPropertyAttribute::kind_weak); + attributeOnlyIfTrue("strong", Attrs & ObjCPropertyAttribute::kind_strong); + attributeOnlyIfTrue("unsafe_unretained", + Attrs & ObjCPropertyAttribute::kind_unsafe_unretained); + attributeOnlyIfTrue("class", Attrs & ObjCPropertyAttribute::kind_class); + attributeOnlyIfTrue("direct", Attrs & ObjCPropertyAttribute::kind_direct); + attributeOnlyIfTrue("nullability", + Attrs & ObjCPropertyAttribute::kind_nullability); + attributeOnlyIfTrue("null_resettable", + Attrs & ObjCPropertyAttribute::kind_null_resettable); + } + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl* D) +{ + AST::Declaration* Decl = VisitNamedDecl(D->getPropertyDecl()); + JOS.attribute("implKind", D->getPropertyImplementation() == + ObjCPropertyImplDecl::Synthesize ? + "synthesize" : + "dynamic"); + JOS.attribute("propertyDecl", createBareDeclRef(D->getPropertyDecl())); + JOS.attribute("ivarDecl", createBareDeclRef(D->getPropertyIvarDecl())); + return Decl; +} + +AST::Declaration* ASTNodeVisitor::VisitBlockDecl(const BlockDecl* D) +{ + attributeOnlyIfTrue("variadic", D->isVariadic()); + attributeOnlyIfTrue("capturesThis", D->capturesCXXThis()); + return nullptr; +} + +void ASTNodeVisitor::VisitAtomicExpr(const AtomicExpr* AE) +{ + // JOS.attribute("name", AE->getOp()); +} + +void ASTNodeVisitor::VisitObjCEncodeExpr(const ObjCEncodeExpr* OEE) +{ + JOS.attribute("encodedType", createQualType(OEE->getEncodedType())); +} + +void ASTNodeVisitor::VisitObjCMessageExpr(const ObjCMessageExpr* OME) +{ + std::string Str; + llvm::raw_string_ostream OS(Str); + + OME->getSelector().print(OS); + JOS.attribute("selector", Str); + + switch (OME->getReceiverKind()) + { + case ObjCMessageExpr::Instance: + JOS.attribute("receiverKind", "instance"); + break; + case ObjCMessageExpr::Class: + JOS.attribute("receiverKind", "class"); + JOS.attribute("classType", createQualType(OME->getClassReceiver())); + break; + case ObjCMessageExpr::SuperInstance: + JOS.attribute("receiverKind", "super (instance)"); + JOS.attribute("superType", createQualType(OME->getSuperType())); + break; + case ObjCMessageExpr::SuperClass: + JOS.attribute("receiverKind", "super (class)"); + JOS.attribute("superType", createQualType(OME->getSuperType())); + break; + } + + QualType CallReturnTy = OME->getCallReturnType(Ctx); + if (OME->getType() != CallReturnTy) + JOS.attribute("callReturnType", createQualType(CallReturnTy)); +} + +void ASTNodeVisitor::VisitObjCBoxedExpr(const ObjCBoxedExpr* OBE) +{ + if (const ObjCMethodDecl* MD = OBE->getBoxingMethod()) + { + std::string Str; + llvm::raw_string_ostream OS(Str); + + MD->getSelector().print(OS); + JOS.attribute("selector", Str); + } +} + +void ASTNodeVisitor::VisitObjCSelectorExpr(const ObjCSelectorExpr* OSE) +{ + std::string Str; + llvm::raw_string_ostream OS(Str); + + OSE->getSelector().print(OS); + JOS.attribute("selector", Str); +} + +void ASTNodeVisitor::VisitObjCProtocolExpr(const ObjCProtocolExpr* OPE) +{ + JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol())); +} + +void ASTNodeVisitor::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr* OPRE) +{ + if (OPRE->isImplicitProperty()) + { + JOS.attribute("propertyKind", "implicit"); + if (const ObjCMethodDecl* MD = OPRE->getImplicitPropertyGetter()) + JOS.attribute("getter", createBareDeclRef(MD)); + if (const ObjCMethodDecl* MD = OPRE->getImplicitPropertySetter()) + JOS.attribute("setter", createBareDeclRef(MD)); + } + else + { + JOS.attribute("propertyKind", "explicit"); + JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty())); + } + + attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver()); + attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter()); + attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter()); +} + +void ASTNodeVisitor::VisitObjCSubscriptRefExpr( + const ObjCSubscriptRefExpr* OSRE) +{ + JOS.attribute("subscriptKind", + OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary"); + + if (const ObjCMethodDecl* MD = OSRE->getAtIndexMethodDecl()) + JOS.attribute("getter", createBareDeclRef(MD)); + if (const ObjCMethodDecl* MD = OSRE->setAtIndexMethodDecl()) + JOS.attribute("setter", createBareDeclRef(MD)); +} + +void ASTNodeVisitor::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* OIRE) +{ + JOS.attribute("decl", createBareDeclRef(OIRE->getDecl())); + attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar()); + JOS.attribute("isArrow", OIRE->isArrow()); +} + +void ASTNodeVisitor::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr* OBLE) +{ + JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no"); +} + +void ASTNodeVisitor::VisitDeclRefExpr(const DeclRefExpr* DRE) +{ + JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); + if (DRE->getDecl() != DRE->getFoundDecl()) + JOS.attribute("foundReferencedDecl", + createBareDeclRef(DRE->getFoundDecl())); + switch (DRE->isNonOdrUse()) + { + case NOUR_None: break; + case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break; + case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break; + case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break; + } + attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating()); +} + +void ASTNodeVisitor::VisitSYCLUniqueStableNameExpr( + const SYCLUniqueStableNameExpr* E) +{ + JOS.attribute("typeSourceInfo", + createQualType(E->getTypeSourceInfo()->getType())); +} + +void ASTNodeVisitor::VisitPredefinedExpr(const PredefinedExpr* PE) +{ + JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); +} + +void ASTNodeVisitor::VisitUnaryOperator(const UnaryOperator* UO) +{ + JOS.attribute("isPostfix", UO->isPostfix()); + JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); + if (!UO->canOverflow()) + JOS.attribute("canOverflow", false); +} + +void ASTNodeVisitor::VisitBinaryOperator(const BinaryOperator* BO) +{ + JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); +} + +void ASTNodeVisitor::VisitCompoundAssignOperator( + const CompoundAssignOperator* CAO) +{ + VisitBinaryOperator(CAO); + JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); + JOS.attribute("computeResultType", + createQualType(CAO->getComputationResultType())); +} + +void ASTNodeVisitor::VisitMemberExpr(const MemberExpr* ME) +{ + // Note, we always write this Boolean field because the information it conveys + // is critical to understanding the AST node. + ValueDecl* VD = ME->getMemberDecl(); + JOS.attribute("name", VD && VD->getDeclName() ? VD->getNameAsString() : ""); + JOS.attribute("isArrow", ME->isArrow()); + JOS.attribute("referencedMemberDecl", createPointerRepresentation(VD)); + switch (ME->isNonOdrUse()) + { + case NOUR_None: break; + case NOUR_Unevaluated: JOS.attribute("nonOdrUseReason", "unevaluated"); break; + case NOUR_Constant: JOS.attribute("nonOdrUseReason", "constant"); break; + case NOUR_Discarded: JOS.attribute("nonOdrUseReason", "discarded"); break; + } +} + +void ASTNodeVisitor::VisitCXXNewExpr(const CXXNewExpr* NE) +{ + attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); + attributeOnlyIfTrue("isArray", NE->isArray()); + attributeOnlyIfTrue("isPlacement", NE->getNumPlacementArgs() != 0); + switch (NE->getInitializationStyle()) + { + case CXXNewExpr::InitializationStyle::NoInit: + break; + case CXXNewExpr::InitializationStyle::CallInit: // Parens + JOS.attribute("initStyle", "call"); + break; + case CXXNewExpr::InitializationStyle::ListInit: // Braces + JOS.attribute("initStyle", "list"); + break; + } + if (const FunctionDecl* FD = NE->getOperatorNew()) + JOS.attribute("operatorNewDecl", createBareDeclRef(FD)); + if (const FunctionDecl* FD = NE->getOperatorDelete()) + JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); +} +void ASTNodeVisitor::VisitCXXDeleteExpr(const CXXDeleteExpr* DE) +{ + attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); + attributeOnlyIfTrue("isArray", DE->isArrayForm()); + attributeOnlyIfTrue("isArrayAsWritten", DE->isArrayFormAsWritten()); + if (const FunctionDecl* FD = DE->getOperatorDelete()) + JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); +} + +void ASTNodeVisitor::VisitCXXThisExpr(const CXXThisExpr* TE) +{ + attributeOnlyIfTrue("implicit", TE->isImplicit()); +} + +void ASTNodeVisitor::VisitCastExpr(const CastExpr* CE) +{ + JOS.attribute("castKind", CE->getCastKindName()); + llvm::json::Array Path = createCastPath(CE); + if (!Path.empty()) + JOS.attribute("path", std::move(Path)); + // FIXME: This may not be useful information as it can be obtusely gleaned + // from the inner[] array. + if (const NamedDecl* ND = CE->getConversionFunction()) + JOS.attribute("conversionFunc", createBareDeclRef(ND)); +} + +void ASTNodeVisitor::VisitImplicitCastExpr(const ImplicitCastExpr* ICE) +{ + VisitCastExpr(ICE); + attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); +} + +void ASTNodeVisitor::VisitCallExpr(const CallExpr* CE) +{ + attributeOnlyIfTrue("adl", CE->usesADL()); +} + +void ASTNodeVisitor::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr* TTE) +{ + JOS.attribute("name", getTraitSpelling(TTE->getKind())); + if (TTE->isArgumentType()) + JOS.attribute("argType", createQualType(TTE->getArgumentType())); +} + +void ASTNodeVisitor::VisitSizeOfPackExpr(const SizeOfPackExpr* SOPE) +{ + VisitNamedDecl(SOPE->getPack()); +} + +void ASTNodeVisitor::VisitUnresolvedLookupExpr( + const UnresolvedLookupExpr* ULE) +{ + JOS.attribute("usesADL", ULE->requiresADL()); + JOS.attribute("name", ULE->getName().getAsString()); + + JOS.attributeArray("lookups", [this, ULE] + { + for (const NamedDecl* D : ULE->decls()) + JOS.value(createBareDeclRef(D)); + }); +} + +void ASTNodeVisitor::VisitAddrLabelExpr(const AddrLabelExpr* ALE) +{ + JOS.attribute("name", ALE->getLabel()->getName()); + JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); +} + +void ASTNodeVisitor::VisitCXXTypeidExpr(const CXXTypeidExpr* CTE) +{ + if (CTE->isTypeOperand()) + { + QualType Adjusted = CTE->getTypeOperand(Ctx); + QualType Unadjusted = CTE->getTypeOperandSourceInfo()->getType(); + JOS.attribute("typeArg", createQualType(Unadjusted)); + if (Adjusted != Unadjusted) + JOS.attribute("adjustedTypeArg", createQualType(Adjusted)); + } +} + +void ASTNodeVisitor::VisitConstantExpr(const ConstantExpr* CE) +{ + if (CE->getResultAPValueKind() != APValue::None) + Visit(CE->getAPValueResult(), CE->getType()); +} + +void ASTNodeVisitor::VisitInitListExpr(const InitListExpr* ILE) +{ + if (const FieldDecl* FD = ILE->getInitializedFieldInUnion()) + JOS.attribute("field", createBareDeclRef(FD)); +} + +void ASTNodeVisitor::VisitGenericSelectionExpr( + const GenericSelectionExpr* GSE) +{ + attributeOnlyIfTrue("resultDependent", GSE->isResultDependent()); +} + +void ASTNodeVisitor::VisitCXXUnresolvedConstructExpr( + const CXXUnresolvedConstructExpr* UCE) +{ + if (UCE->getType() != UCE->getTypeAsWritten()) + JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten())); + attributeOnlyIfTrue("list", UCE->isListInitialization()); +} + +void ASTNodeVisitor::VisitCXXConstructExpr(const CXXConstructExpr* CE) +{ + CXXConstructorDecl* Ctor = CE->getConstructor(); + JOS.attribute("ctorType", createQualType(Ctor->getType())); + attributeOnlyIfTrue("elidable", CE->isElidable()); + attributeOnlyIfTrue("list", CE->isListInitialization()); + attributeOnlyIfTrue("initializer_list", CE->isStdInitListInitialization()); + attributeOnlyIfTrue("zeroing", CE->requiresZeroInitialization()); + attributeOnlyIfTrue("hadMultipleCandidates", CE->hadMultipleCandidates()); + attributeOnlyIfTrue("isImmediateEscalating", CE->isImmediateEscalating()); + + switch (CE->getConstructionKind()) + { + case CXXConstructExpr::ConstructionKind::CK_Complete: + JOS.attribute("constructionKind", "complete"); + break; + case CXXConstructExpr::ConstructionKind::CK_Delegating: + JOS.attribute("constructionKind", "delegating"); + break; + case CXXConstructExpr::ConstructionKind::CK_NonVirtualBase: + JOS.attribute("constructionKind", "non-virtual base"); + break; + case CXXConstructExpr::ConstructionKind::CK_VirtualBase: + JOS.attribute("constructionKind", "virtual base"); + break; + } +} + +void ASTNodeVisitor::VisitExprWithCleanups(const ExprWithCleanups* EWC) +{ + attributeOnlyIfTrue("cleanupsHaveSideEffects", + EWC->cleanupsHaveSideEffects()); + if (EWC->getNumObjects()) + { + JOS.attributeArray("cleanups", [this, EWC] + { + for (const ExprWithCleanups::CleanupObject& CO : EWC->getObjects()) + if (auto* BD = CO.dyn_cast()) + { + JOS.value(createBareDeclRef(BD)); + } + else if (auto* CLE = CO.dyn_cast()) + { + llvm::json::Object Obj; + Obj["id"] = createPointerRepresentation(CLE); + Obj["kind"] = CLE->getStmtClassName(); + JOS.value(std::move(Obj)); + } + else + { + llvm_unreachable("unexpected cleanup object type"); + } + }); + } +} + +void ASTNodeVisitor::VisitCXXBindTemporaryExpr( + const CXXBindTemporaryExpr* BTE) +{ + const CXXTemporary* Temp = BTE->getTemporary(); + JOS.attribute("temp", createPointerRepresentation(Temp)); + if (const CXXDestructorDecl* Dtor = Temp->getDestructor()) + JOS.attribute("dtor", createBareDeclRef(Dtor)); +} + +void ASTNodeVisitor::VisitMaterializeTemporaryExpr( + const MaterializeTemporaryExpr* MTE) +{ + if (const ValueDecl* VD = MTE->getExtendingDecl()) + JOS.attribute("extendingDecl", createBareDeclRef(VD)); + + switch (MTE->getStorageDuration()) + { + case SD_Automatic: + JOS.attribute("storageDuration", "automatic"); + break; + case SD_Dynamic: + JOS.attribute("storageDuration", "dynamic"); + break; + case SD_FullExpression: + JOS.attribute("storageDuration", "full expression"); + break; + case SD_Static: + JOS.attribute("storageDuration", "static"); + break; + case SD_Thread: + JOS.attribute("storageDuration", "thread"); + break; + } + + attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference()); +} + +void ASTNodeVisitor::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr* Node) +{ + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + +void ASTNodeVisitor::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr* Node) +{ + attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); +} + +void ASTNodeVisitor::VisitCXXDependentScopeMemberExpr( + const CXXDependentScopeMemberExpr* DSME) +{ + JOS.attribute("isArrow", DSME->isArrow()); + JOS.attribute("member", DSME->getMember().getAsString()); + attributeOnlyIfTrue("hasTemplateKeyword", DSME->hasTemplateKeyword()); + attributeOnlyIfTrue("hasExplicitTemplateArgs", + DSME->hasExplicitTemplateArgs()); + + if (DSME->getNumTemplateArgs()) + { + JOS.attributeArray("explicitTemplateArgs", [DSME, this] + { + for (const TemplateArgumentLoc& TAL : DSME->template_arguments()) + JOS.object( + [&TAL, this] + { + Visit(TAL.getArgument(), TAL.getSourceRange()); + }); + }); + } +} + +void ASTNodeVisitor::VisitRequiresExpr(const RequiresExpr* RE) +{ + if (!RE->isValueDependent()) + JOS.attribute("satisfied", RE->isSatisfied()); +} + +void ASTNodeVisitor::VisitIntegerLiteral(const IntegerLiteral* IL) +{ + llvm::SmallString<16> Buffer; + IL->getValue().toString(Buffer, + /*Radix=*/10, IL->getType()->isSignedIntegerType()); + JOS.attribute("value", Buffer); +} +void ASTNodeVisitor::VisitCharacterLiteral(const CharacterLiteral* CL) +{ + // FIXME: This should probably print the character literal as a string, + // rather than as a numerical value. It would be nice if the behavior matched + // what we do to print a string literal; right now, it is impossible to tell + // the difference between 'a' and L'a' in C from the JSON output. + JOS.attribute("value", CL->getValue()); +} +void ASTNodeVisitor::VisitFixedPointLiteral(const FixedPointLiteral* FPL) +{ + JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); +} +void ASTNodeVisitor::VisitFloatingLiteral(const FloatingLiteral* FL) +{ + llvm::SmallString<16> Buffer; + FL->getValue().toString(Buffer); + JOS.attribute("value", Buffer); +} +void ASTNodeVisitor::VisitStringLiteral(const StringLiteral* SL) +{ + std::string Buffer; + llvm::raw_string_ostream SS(Buffer); + SL->outputString(SS); + JOS.attribute("value", Buffer); +} +void ASTNodeVisitor::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr* BLE) +{ + JOS.attribute("value", BLE->getValue()); +} + +void ASTNodeVisitor::VisitIfStmt(const IfStmt* IS) +{ + attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); + attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); + attributeOnlyIfTrue("hasElse", IS->hasElseStorage()); + attributeOnlyIfTrue("isConstexpr", IS->isConstexpr()); + attributeOnlyIfTrue("isConsteval", IS->isConsteval()); + attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval()); +} + +void ASTNodeVisitor::VisitSwitchStmt(const SwitchStmt* SS) +{ + attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); + attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); +} +void ASTNodeVisitor::VisitCaseStmt(const CaseStmt* CS) +{ + attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); +} + +void ASTNodeVisitor::VisitLabelStmt(const LabelStmt* LS) +{ + JOS.attribute("name", LS->getName()); + JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); + attributeOnlyIfTrue("sideEntry", LS->isSideEntry()); +} +void ASTNodeVisitor::VisitGotoStmt(const GotoStmt* GS) +{ + JOS.attribute("targetLabelDeclId", + createPointerRepresentation(GS->getLabel())); +} + +void ASTNodeVisitor::VisitWhileStmt(const WhileStmt* WS) +{ + attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); +} + +void ASTNodeVisitor::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) +{ + // FIXME: it would be nice for the ASTNodeTraverser would handle the catch + // parameter the same way for C++ and ObjC rather. In this case, C++ gets a + // null child node and ObjC gets no child node. + attributeOnlyIfTrue("isCatchAll", OACS->getCatchParamDecl() == nullptr); +} + +void ASTNodeVisitor::VisitNullTemplateArgument(const TemplateArgument& TA) +{ + JOS.attribute("isNull", true); +} +void ASTNodeVisitor::VisitTypeTemplateArgument(const TemplateArgument& TA) +{ + JOS.attribute("type", createQualType(TA.getAsType())); +} +void ASTNodeVisitor::VisitDeclarationTemplateArgument( + const TemplateArgument& TA) +{ + JOS.attribute("decl", createBareDeclRef(TA.getAsDecl())); +} +void ASTNodeVisitor::VisitNullPtrTemplateArgument(const TemplateArgument& TA) +{ + JOS.attribute("isNullptr", true); +} +void ASTNodeVisitor::VisitIntegralTemplateArgument(const TemplateArgument& TA) +{ + JOS.attribute("value", TA.getAsIntegral().getSExtValue()); +} +void ASTNodeVisitor::VisitTemplateTemplateArgument(const TemplateArgument& TA) +{ + // FIXME: cannot just call dump() on the argument, as that doesn't specify + // the output format. +} +void ASTNodeVisitor::VisitTemplateExpansionTemplateArgument( + const TemplateArgument& TA) +{ + // FIXME: cannot just call dump() on the argument, as that doesn't specify + // the output format. +} +void ASTNodeVisitor::VisitExpressionTemplateArgument( + const TemplateArgument& TA) +{ + JOS.attribute("isExpr", true); +} +void ASTNodeVisitor::VisitPackTemplateArgument(const TemplateArgument& TA) +{ + JOS.attribute("isPack", true); +} + +StringRef ASTNodeVisitor::getCommentCommandName(unsigned CommandID) const +{ + return Traits.getCommandInfo(CommandID)->Name; +} + +void ASTNodeVisitor::visitTextComment(const comments::TextComment* C, + const comments::FullComment*) +{ + JOS.attribute("text", C->getText()); +} + +void ASTNodeVisitor::visitInlineCommandComment( + const comments::InlineCommandComment* C, + const comments::FullComment*) +{ + JOS.attribute("name", getCommentCommandName(C->getCommandID())); + + switch (C->getRenderKind()) + { + case comments::InlineCommandComment::RenderKind::RenderNormal: + JOS.attribute("renderKind", "normal"); + break; + case comments::InlineCommandComment::RenderKind::RenderBold: + JOS.attribute("renderKind", "bold"); + break; + case comments::InlineCommandComment::RenderKind::RenderEmphasized: + JOS.attribute("renderKind", "emphasized"); + break; + case comments::InlineCommandComment::RenderKind::RenderMonospaced: + JOS.attribute("renderKind", "monospaced"); + break; + case comments::InlineCommandComment::RenderKind::RenderAnchor: + JOS.attribute("renderKind", "anchor"); + break; + } + + llvm::json::Array Args; + for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) + Args.push_back(C->getArgText(I)); + + if (!Args.empty()) + JOS.attribute("args", std::move(Args)); +} + +void ASTNodeVisitor::visitHTMLStartTagComment( + const comments::HTMLStartTagComment* C, + const comments::FullComment*) +{ + JOS.attribute("name", C->getTagName()); + attributeOnlyIfTrue("selfClosing", C->isSelfClosing()); + attributeOnlyIfTrue("malformed", C->isMalformed()); + + llvm::json::Array Attrs; + for (unsigned I = 0, E = C->getNumAttrs(); I < E; ++I) + Attrs.push_back( + { { "name", C->getAttr(I).Name }, { "value", C->getAttr(I).Value } }); + + if (!Attrs.empty()) + JOS.attribute("attrs", std::move(Attrs)); +} + +void ASTNodeVisitor::visitHTMLEndTagComment( + const comments::HTMLEndTagComment* C, + const comments::FullComment*) +{ + JOS.attribute("name", C->getTagName()); +} + +void ASTNodeVisitor::visitBlockCommandComment( + const comments::BlockCommandComment* C, + const comments::FullComment*) +{ + JOS.attribute("name", getCommentCommandName(C->getCommandID())); + + llvm::json::Array Args; + for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I) + Args.push_back(C->getArgText(I)); + + if (!Args.empty()) + JOS.attribute("args", std::move(Args)); +} + +void ASTNodeVisitor::visitParamCommandComment( + const comments::ParamCommandComment* C, + const comments::FullComment* FC) +{ + switch (C->getDirection()) + { + case comments::ParamCommandComment::PassDirection::In: + JOS.attribute("direction", "in"); + break; + case comments::ParamCommandComment::PassDirection::Out: + JOS.attribute("direction", "out"); + break; + case comments::ParamCommandComment::PassDirection::InOut: + JOS.attribute("direction", "in,out"); + break; + } + attributeOnlyIfTrue("explicit", C->isDirectionExplicit()); + + if (C->hasParamName()) + JOS.attribute("param", C->isParamIndexValid() ? C->getParamName(FC) : C->getParamNameAsWritten()); + + if (C->isParamIndexValid() && !C->isVarArgParam()) + JOS.attribute("paramIdx", C->getParamIndex()); +} + +void ASTNodeVisitor::visitTParamCommandComment( + const comments::TParamCommandComment* C, + const comments::FullComment* FC) +{ + if (C->hasParamName()) + JOS.attribute("param", C->isPositionValid() ? C->getParamName(FC) : C->getParamNameAsWritten()); + if (C->isPositionValid()) + { + llvm::json::Array Positions; + for (unsigned I = 0, E = C->getDepth(); I < E; ++I) + Positions.push_back(C->getIndex(I)); + + if (!Positions.empty()) + JOS.attribute("positions", std::move(Positions)); + } +} + +void ASTNodeVisitor::visitVerbatimBlockComment( + const comments::VerbatimBlockComment* C, + const comments::FullComment*) +{ + JOS.attribute("name", getCommentCommandName(C->getCommandID())); + JOS.attribute("closeName", C->getCloseName()); +} + +void ASTNodeVisitor::visitVerbatimBlockLineComment( + const comments::VerbatimBlockLineComment* C, + const comments::FullComment*) +{ + JOS.attribute("text", C->getText()); +} + +void ASTNodeVisitor::visitVerbatimLineComment( + const comments::VerbatimLineComment* C, + const comments::FullComment*) +{ + JOS.attribute("text", C->getText()); +} + +llvm::json::Object ASTNodeVisitor::createFPOptions(FPOptionsOverride FPO) +{ + llvm::json::Object Ret; +#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ + if (FPO.has##NAME##Override()) \ + Ret.try_emplace(#NAME, static_cast(FPO.get##NAME##Override())); +#include "clang/Basic/FPOptions.def" + + return Ret; +} + +void ASTNodeVisitor::VisitCompoundStmt(const CompoundStmt* S) +{ + VisitStmt(S); + if (S->hasStoredFPFeatures()) + JOS.attribute("fpoptions", createFPOptions(S->getStoredFPFeatures())); +} \ No newline at end of file diff --git a/src/CppParser/ASTNodeVisitor.h b/src/CppParser/ASTNodeVisitor.h new file mode 100644 index 0000000000..e010f034b5 --- /dev/null +++ b/src/CppParser/ASTNodeVisitor.h @@ -0,0 +1,545 @@ +/************************************************************************ + * + * CppSharp + * Licensed under the simplified BSD license. All rights reserved. + * + ************************************************************************/ + +#pragma once +#include + +#include "ASTNameMangler.h" +#include "Types.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDumperUtils.h" +#include "clang/AST/ASTNodeTraverser.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/AttrVisitor.h" +#include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/CommentVisitor.h" +#include "clang/AST/ExprConcepts.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/Type.h" + +#include + +namespace CppSharp::CppParser { + namespace AST { + class Stmt; + } + class Parser; + + class NodeStreamer + { + bool FirstChild = true; + bool TopLevel = true; + llvm::SmallVector, 32> Pending; + + protected: + llvm::json::OStream JOS; + + public: + /// Add a child of the current node. Calls DoAddChild without arguments + template + void AddChild(Fn DoAddChild) + { + return AddChild("", DoAddChild); + } + + /// Add a child of the current node with an optional label. + /// Calls DoAddChild without arguments. + template + void AddChild(llvm::StringRef Label, Fn DoAddChild) + { + // If we're at the top level, there's nothing interesting to do; just + // run the dumper. + if (TopLevel) + { + TopLevel = false; + JOS.objectBegin(); + + DoAddChild(); + + while (!Pending.empty()) + { + Pending.back()(true); + Pending.pop_back(); + } + + JOS.objectEnd(); + TopLevel = true; + return; + } + + // We need to capture an owning-string in the lambda because the lambda + // is invoked in a deferred manner. + std::string LabelStr(!Label.empty() ? Label : "inner"); + bool WasFirstChild = FirstChild; + auto DumpWithIndent = [=](bool IsLastChild) + { + if (WasFirstChild) + { + JOS.attributeBegin(LabelStr); + JOS.arrayBegin(); + } + + FirstChild = true; + unsigned Depth = Pending.size(); + JOS.objectBegin(); + + DoAddChild(); + + // If any children are left, they're the last at their nesting level. + // Dump those ones out now. + while (Depth < Pending.size()) + { + Pending.back()(true); + this->Pending.pop_back(); + } + + JOS.objectEnd(); + + if (IsLastChild) + { + JOS.arrayEnd(); + JOS.attributeEnd(); + } + }; + + if (FirstChild) + { + Pending.push_back(std::move(DumpWithIndent)); + } + else + { + Pending.back()(false); + Pending.back() = std::move(DumpWithIndent); + } + FirstChild = false; + } + + NodeStreamer(llvm::raw_ostream& OS) + : JOS(OS, 2) + { + } + }; + + // Dumps AST nodes in JSON format. There is no implied stability for the + // content or format of the dump between major releases of Clang, other than it + // being valid JSON output. Further, there is no requirement that the + // information dumped is a complete representation of the AST, only that the + // information presented is correct. + class ASTNodeVisitor + : public clang::ConstAttrVisitor, + public clang::comments::ConstCommentVisitor, + public clang::ConstTemplateArgumentVisitor, + public clang::ConstStmtVisitor, + public clang::TypeVisitor, + public clang::ConstDeclVisitor, + public NodeStreamer + { + friend class ASTNodeDumper; + + using InnerAttrVisitor = ConstAttrVisitor; + using InnerCommentVisitor = ConstCommentVisitor; + using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor; + using InnerStmtVisitor = ConstStmtVisitor; + using InnerTypeVisitor = TypeVisitor; + using InnerDeclVisitor = ConstDeclVisitor; + + public: + ASTNodeVisitor(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) + : NodeStreamer(OS) + , parser(parser) + , SM(Ctx.getSourceManager()) + , Ctx(Ctx) + , NameMangler(Ctx) + , PrintPolicy(Ctx.getPrintingPolicy()) + , Traits(Ctx.getCommentCommandTraits()) + , LastLocLine(0) + , LastLocPresumedLine(0) + { + declMap.reserve(32768); + typeMap.reserve(32768); + stmtMap.reserve(32768); + } + + void Visit(const clang::Attr* A); + void Visit(const clang::Stmt* S); + void Visit(const clang::Type* T); + void Visit(clang::QualType T); + AST::Declaration* Visit(const clang::Decl* D); + void Visit(clang::TypeLoc TL); + + void Visit(const clang::comments::Comment* C, const clang::comments::FullComment* FC); + void Visit(const clang::TemplateArgument& TA, clang::SourceRange R = {}, const clang::Decl* From = nullptr, llvm::StringRef Label = {}); + void Visit(const clang::CXXCtorInitializer* Init); + // void Visit(const OpenACCClause* C) {} + void Visit(const clang::OMPClause* C) {} + void Visit(const clang::BlockDecl::Capture& C); + void Visit(const clang::GenericSelectionExpr::ConstAssociation& A); + void Visit(const clang::concepts::Requirement* R); + void Visit(const clang::APValue& Value, clang::QualType Ty); + void Visit(const clang::ConceptReference*); + + void VisitAliasAttr(const clang::AliasAttr* AA); + void VisitCleanupAttr(const clang::CleanupAttr* CA); + void VisitDeprecatedAttr(const clang::DeprecatedAttr* DA); + void VisitUnavailableAttr(const clang::UnavailableAttr* UA); + void VisitSectionAttr(const clang::SectionAttr* SA); + void VisitVisibilityAttr(const clang::VisibilityAttr* VA); + void VisitTLSModelAttr(const clang::TLSModelAttr* TA); + + void VisitTypedefType(const clang::TypedefType* TT); + void VisitUsingType(const clang::UsingType* TT); + void VisitFunctionType(const clang::FunctionType* T); + void VisitFunctionProtoType(const clang::FunctionProtoType* T); + void VisitRValueReferenceType(const clang::ReferenceType* RT); + void VisitArrayType(const clang::ArrayType* AT); + void VisitConstantArrayType(const clang::ConstantArrayType* CAT); + void VisitDependentSizedExtVectorType(const clang::DependentSizedExtVectorType* VT); + void VisitVectorType(const clang::VectorType* VT); + void VisitUnresolvedUsingType(const clang::UnresolvedUsingType* UUT); + void VisitUnaryTransformType(const clang::UnaryTransformType* UTT); + void VisitTagType(const clang::TagType* TT); + void VisitTemplateTypeParmType(const clang::TemplateTypeParmType* TTPT); + void VisitSubstTemplateTypeParmType(const clang::SubstTemplateTypeParmType* STTPT); + void VisitSubstTemplateTypeParmPackType(const clang::SubstTemplateTypeParmPackType* T); + void VisitAutoType(const clang::AutoType* AT); + void VisitTemplateSpecializationType(const clang::TemplateSpecializationType* TST); + void VisitInjectedClassNameType(const clang::InjectedClassNameType* ICNT); + void VisitObjCInterfaceType(const clang::ObjCInterfaceType* OIT); + void VisitPackExpansionType(const clang::PackExpansionType* PET); + void VisitElaboratedType(const clang::ElaboratedType* ET); + void VisitMacroQualifiedType(const clang::MacroQualifiedType* MQT); + void VisitMemberPointerType(const clang::MemberPointerType* MPT); + + AST::Declaration* VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); + AST::Declaration* VisitNamedDecl(const clang::NamedDecl* ND); + void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); + AST::Declaration* VisitTypedefDecl(const clang::TypedefDecl* TD); + AST::Declaration* VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); + AST::Declaration* VisitNamespaceDecl(const clang::NamespaceDecl* ND); + AST::Declaration* VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); + AST::Declaration* VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); + AST::Declaration* VisitUsingDecl(const clang::UsingDecl* UD); + AST::Declaration* VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); + AST::Declaration* VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); + AST::Declaration* VisitVarDecl(const clang::VarDecl* VD); + AST::Declaration* VisitFieldDecl(const clang::FieldDecl* FD); + AST::Declaration* VisitFunctionDecl(const clang::FunctionDecl* FD); + AST::Declaration* VisitEnumDecl(const clang::EnumDecl* ED); + AST::Declaration* VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); + AST::Declaration* VisitRecordDecl(const clang::RecordDecl* RD); + AST::Declaration* VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); + AST::Declaration* VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); + AST::Declaration* VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); + AST::Declaration* VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); + AST::Declaration* VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); + AST::Declaration* VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); + AST::Declaration* VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); + AST::Declaration* VisitFriendDecl(const clang::FriendDecl* FD); + + AST::Declaration* VisitObjCIvarDecl(const clang::ObjCIvarDecl* D); + AST::Declaration* VisitObjCMethodDecl(const clang::ObjCMethodDecl* D); + AST::Declaration* VisitObjCTypeParamDecl(const clang::ObjCTypeParamDecl* D); + AST::Declaration* VisitObjCCategoryDecl(const clang::ObjCCategoryDecl* D); + AST::Declaration* VisitObjCCategoryImplDecl(const clang::ObjCCategoryImplDecl* D); + AST::Declaration* VisitObjCProtocolDecl(const clang::ObjCProtocolDecl* D); + AST::Declaration* VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl* D); + AST::Declaration* VisitObjCImplementationDecl(const clang::ObjCImplementationDecl* D); + AST::Declaration* VisitObjCCompatibleAliasDecl(const clang::ObjCCompatibleAliasDecl* D); + AST::Declaration* VisitObjCPropertyDecl(const clang::ObjCPropertyDecl* D); + AST::Declaration* VisitObjCPropertyImplDecl(const clang::ObjCPropertyImplDecl* D); + AST::Declaration* VisitBlockDecl(const clang::BlockDecl* D); + + void VisitDeclRefExpr(const clang::DeclRefExpr* DRE); + void VisitSYCLUniqueStableNameExpr(const clang::SYCLUniqueStableNameExpr* E); + // void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr* E) {} + void VisitPredefinedExpr(const clang::PredefinedExpr* PE); + void VisitUnaryOperator(const clang::UnaryOperator* UO); + void VisitBinaryOperator(const clang::BinaryOperator* BO); + void VisitCompoundAssignOperator(const clang::CompoundAssignOperator* CAO); + void VisitMemberExpr(const clang::MemberExpr* ME); + void VisitAtomicExpr(const clang::AtomicExpr* AE); + void VisitCXXNewExpr(const clang::CXXNewExpr* NE); + void VisitCXXDeleteExpr(const clang::CXXDeleteExpr* DE); + void VisitCXXThisExpr(const clang::CXXThisExpr* TE); + void VisitCastExpr(const clang::CastExpr* CE); + void VisitImplicitCastExpr(const clang::ImplicitCastExpr* ICE); + void VisitCallExpr(const clang::CallExpr* CE); + void VisitUnaryExprOrTypeTraitExpr(const clang::UnaryExprOrTypeTraitExpr* TTE); + void VisitSizeOfPackExpr(const clang::SizeOfPackExpr* SOPE); + void VisitUnresolvedLookupExpr(const clang::UnresolvedLookupExpr* ULE); + void VisitAddrLabelExpr(const clang::AddrLabelExpr* ALE); + void VisitCXXTypeidExpr(const clang::CXXTypeidExpr* CTE); + void VisitConstantExpr(const clang::ConstantExpr* CE); + void VisitInitListExpr(const clang::InitListExpr* ILE); + void VisitGenericSelectionExpr(const clang::GenericSelectionExpr* GSE); + void VisitCXXUnresolvedConstructExpr(const clang::CXXUnresolvedConstructExpr* UCE); + void VisitCXXConstructExpr(const clang::CXXConstructExpr* CE); + void VisitExprWithCleanups(const clang::ExprWithCleanups* EWC); + void VisitCXXBindTemporaryExpr(const clang::CXXBindTemporaryExpr* BTE); + void VisitMaterializeTemporaryExpr(const clang::MaterializeTemporaryExpr* MTE); + void VisitCXXDependentScopeMemberExpr(const clang::CXXDependentScopeMemberExpr* ME); + void VisitRequiresExpr(const clang::RequiresExpr* RE); + void VisitCXXDefaultArgExpr(const clang::CXXDefaultArgExpr* Node); + void VisitCXXDefaultInitExpr(const clang::CXXDefaultInitExpr* Node); + void VisitCXXBoolLiteralExpr(const clang::CXXBoolLiteralExpr* BLE); + + void VisitObjCEncodeExpr(const clang::ObjCEncodeExpr* OEE); + void VisitObjCMessageExpr(const clang::ObjCMessageExpr* OME); + void VisitObjCBoxedExpr(const clang::ObjCBoxedExpr* OBE); + void VisitObjCSelectorExpr(const clang::ObjCSelectorExpr* OSE); + void VisitObjCProtocolExpr(const clang::ObjCProtocolExpr* OPE); + void VisitObjCPropertyRefExpr(const clang::ObjCPropertyRefExpr* OPRE); + void VisitObjCSubscriptRefExpr(const clang::ObjCSubscriptRefExpr* OSRE); + void VisitObjCIvarRefExpr(const clang::ObjCIvarRefExpr* OIRE); + void VisitObjCBoolLiteralExpr(const clang::ObjCBoolLiteralExpr* OBLE); + + void VisitIntegerLiteral(const clang::IntegerLiteral* IL); + void VisitCharacterLiteral(const clang::CharacterLiteral* CL); + void VisitFixedPointLiteral(const clang::FixedPointLiteral* FPL); + void VisitFloatingLiteral(const clang::FloatingLiteral* FL); + void VisitStringLiteral(const clang::StringLiteral* SL); + + void VisitIfStmt(const clang::IfStmt* IS); + void VisitSwitchStmt(const clang::SwitchStmt* SS); + void VisitCaseStmt(const clang::CaseStmt* CS); + void VisitLabelStmt(const clang::LabelStmt* LS); + void VisitGotoStmt(const clang::GotoStmt* GS); + void VisitWhileStmt(const clang::WhileStmt* WS); + void VisitObjCAtCatchStmt(const clang::ObjCAtCatchStmt* OACS); + void VisitCompoundStmt(const clang::CompoundStmt* IS); + + void VisitNullTemplateArgument(const clang::TemplateArgument& TA); + void VisitTypeTemplateArgument(const clang::TemplateArgument& TA); + void VisitDeclarationTemplateArgument(const clang::TemplateArgument& TA); + void VisitNullPtrTemplateArgument(const clang::TemplateArgument& TA); + void VisitIntegralTemplateArgument(const clang::TemplateArgument& TA); + void VisitTemplateTemplateArgument(const clang::TemplateArgument& TA); + void VisitTemplateExpansionTemplateArgument(const clang::TemplateArgument& TA); + void VisitExpressionTemplateArgument(const clang::TemplateArgument& TA); + void VisitPackTemplateArgument(const clang::TemplateArgument& TA); + + void visitTextComment(const clang::comments::TextComment* C, const clang::comments::FullComment*); + void visitInlineCommandComment(const clang::comments::InlineCommandComment* C, const clang::comments::FullComment*); + void visitHTMLStartTagComment(const clang::comments::HTMLStartTagComment* C, const clang::comments::FullComment*); + void visitHTMLEndTagComment(const clang::comments::HTMLEndTagComment* C, const clang::comments::FullComment*); + void visitBlockCommandComment(const clang::comments::BlockCommandComment* C, const clang::comments::FullComment*); + void visitParamCommandComment(const clang::comments::ParamCommandComment* C, const clang::comments::FullComment* FC); + void visitTParamCommandComment(const clang::comments::TParamCommandComment* C, const clang::comments::FullComment* FC); + void visitVerbatimBlockComment(const clang::comments::VerbatimBlockComment* C, const clang::comments::FullComment*); + void visitVerbatimBlockLineComment(const clang::comments::VerbatimBlockLineComment* C, const clang::comments::FullComment*); + void visitVerbatimLineComment(const clang::comments::VerbatimLineComment* C, const clang::comments::FullComment*); + + private: + void attributeOnlyIfTrue(llvm::StringRef Key, bool Value) + { + if (Value) + JOS.attribute(Key, Value); + } + + void writeIncludeStack(clang::PresumedLoc Loc, bool JustFirst = false); + + // Writes the attributes of a SourceLocation object without. + void writeBareSourceLocation(clang::SourceLocation Loc, bool IsSpelling, bool addFileInfo); + + // Writes the attributes of a SourceLocation to JSON based on its presumed + // spelling location. If the given location represents a macro invocation, + // this outputs two sub-objects: one for the spelling and one for the + // expansion location. + void writeSourceLocation(clang::SourceLocation Loc, bool addFileInfo = true); + void writeSourceRange(clang::SourceRange R); + std::string createPointerRepresentation(const void* Ptr); + llvm::json::Object createQualType(clang::QualType QT, bool Desugar = true); + AST::QualifiedType CreateQualifiedType(clang::QualType QT, bool Desugar = true); + llvm::json::Object createBareDeclRef(const clang::Decl* D); + llvm::json::Object createFPOptions(clang::FPOptionsOverride FPO); + void writeBareDeclRef(const clang::Decl* D); + llvm::json::Object createCXXRecordDefinitionData(const clang::CXXRecordDecl* RD); + llvm::json::Object createCXXBaseSpecifier(const clang::CXXBaseSpecifier& BS); + std::string createAccessSpecifier(clang::AccessSpecifier AS); + llvm::json::Array createCastPath(const clang::CastExpr* C); + + void writePreviousDeclImpl(...) {} + + template + void writePreviousDeclImpl(const clang::Mergeable* D) + { + const T* First = D->getFirstDecl(); + if (First != D) + JOS.attribute("firstRedecl", createPointerRepresentation(First)); + } + + template + void writePreviousDeclImpl(const clang::Redeclarable* D) + { + const T* Prev = D->getPreviousDecl(); + if (Prev) + JOS.attribute("previousDecl", createPointerRepresentation(Prev)); + } + + [[nodiscard]] std::string GetMangledName(const clang::NamedDecl& ND) const; + void ConvertNamedRecord(AST::Declaration& dst, const clang::NamedDecl& src) const; + + void addPreviousDeclaration(const clang::Decl* D); + + llvm::StringRef getCommentCommandName(unsigned CommandID) const; + + template + AST::Declaration* FindOrInsertLazy(const clang::Decl* D, Fn&& inserter) + { + if (auto it = declMap.find(D); it != declMap.end()) + return it->second; + + auto res = declMap.emplace(D, std::invoke(inserter)); + return res.first->second; + } + + std::unordered_map declMap; + std::unordered_set typeMap; + std::unordered_set stmtMap; + + Parser& parser; + const clang::SourceManager& SM; + clang::ASTContext& Ctx; + ASTNameMangler NameMangler; // TODO: Remove this, or the parser one + clang::PrintingPolicy PrintPolicy; + const clang::comments::CommandTraits& Traits; + llvm::StringRef LastLocFilename, LastLocPresumedFilename; + unsigned LastLocLine, LastLocPresumedLine; + }; + + class ASTNodeDumper : public clang::ASTNodeTraverser + { + public: + ASTNodeDumper(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) + : NodeVisitor(OS, Ctx, parser) + { + setDeserialize(true); + } + + ASTNodeVisitor& doGetNodeDelegate() { return NodeVisitor; } + + void VisitFunctionTemplateDecl(const clang::FunctionTemplateDecl* FTD) + { + writeTemplateDecl(FTD, true); + } + void VisitClassTemplateDecl(const clang::ClassTemplateDecl* CTD) + { + writeTemplateDecl(CTD, false); + } + void VisitVarTemplateDecl(const clang::VarTemplateDecl* VTD) + { + writeTemplateDecl(VTD, false); + } + + private: + template + void writeTemplateDeclSpecialization(const SpecializationDecl* SD, bool DumpExplicitInst, bool DumpRefOnly) + { + bool DumpedAny = false; + for (const auto* RedeclWithBadType : SD->redecls()) + { + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + const auto* Redecl = clang::dyn_cast(RedeclWithBadType); + if (!Redecl) + { + // Found the injected-class-name for a class template. This will be + // dumped as part of its surrounding class so we don't need to dump it + // here. + assert(clang::isa(RedeclWithBadType) && + "expected an injected-class-name"); + continue; + } + + switch (Redecl->getTemplateSpecializationKind()) + { + case clang::TSK_ExplicitInstantiationDeclaration: + case clang::TSK_ExplicitInstantiationDefinition: + if (!DumpExplicitInst) + break; + [[fallthrough]]; + case clang::TSK_Undeclared: + case clang::TSK_ImplicitInstantiation: + if (DumpRefOnly) + NodeVisitor.AddChild([=] + { + NodeVisitor.writeBareDeclRef(Redecl); + }); + else + Visit(Redecl); + DumpedAny = true; + break; + case clang::TSK_ExplicitSpecialization: + break; + } + } + + // Ensure we dump at least one decl for each specialization. + if (!DumpedAny) + NodeVisitor.AddChild([=] + { + NodeVisitor.writeBareDeclRef(SD); + }); + } + + template + void writeTemplateDecl(const TemplateDecl* TD, bool DumpExplicitInst) + { + // FIXME: it would be nice to dump template parameters and specializations + // to their own named arrays rather than shoving them into the "inner" + // array. However, template declarations are currently being handled at the + // wrong "level" of the traversal hierarchy and so it is difficult to + // achieve without losing information elsewhere. + + dumpTemplateParameters(TD->getTemplateParameters()); + + Visit(TD->getTemplatedDecl()); + + for (const auto* Child : TD->specializations()) + writeTemplateDeclSpecialization(Child, DumpExplicitInst, !TD->isCanonicalDecl()); + } + + ASTNodeVisitor NodeVisitor; + }; + + class ASTParser : public clang::RecursiveASTVisitor + { + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldWalkTypesOfTypeLocs() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + bool shouldVisitLambdaBody() const { return true; } + bool shouldTraversePostOrder() const { return true; } + + void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); + + bool VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); + bool VisitNamedDecl(const clang::NamedDecl* ND); + bool VisitTypedefDecl(const clang::TypedefDecl* TD); + bool VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); + bool VisitNamespaceDecl(const clang::NamespaceDecl* ND); + bool VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); + bool VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); + bool VisitUsingDecl(const clang::UsingDecl* UD); + bool VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); + bool VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); + bool VisitVarDecl(const clang::VarDecl* VD); + bool VisitFieldDecl(const clang::FieldDecl* FD); + bool VisitFunctionDecl(const clang::FunctionDecl* FD); + bool VisitEnumDecl(const clang::EnumDecl* ED); + bool VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); + bool VisitRecordDecl(const clang::RecordDecl* RD); + bool VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); + bool VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); + bool VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); + bool VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); + bool VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); + bool VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); + bool VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); + bool VisitFriendDecl(const clang::FriendDecl* FD); + }; +} // namespace CppSharp::CppParser \ No newline at end of file diff --git a/src/CppParser/Decl.h b/src/CppParser/Decl.h index b931e88eb8..a895b5299b 100644 --- a/src/CppParser/Decl.h +++ b/src/CppParser/Decl.h @@ -11,6 +11,7 @@ #include "Sources.h" #include "Types.h" #include +#include namespace CppSharp { namespace CppParser { @@ -82,6 +83,7 @@ namespace AST { int lineNumberStart; int lineNumberEnd; std::string name; + std::string mangledName; std::string USR; std::string debugText; bool isIncomplete; @@ -89,6 +91,9 @@ namespace AST { bool isImplicit; bool isInvalid; bool isDeprecated; + bool isHidden; + bool isUsed; + bool isReferenced; Declaration* completeDeclaration; unsigned definitionOrder; VECTOR(PreprocessedEntity*, PreprocessedEntities) @@ -115,32 +120,32 @@ namespace AST { public: DeclarationContext(DeclarationKind kind); - CS_IGNORE Declaration* FindAnonymous(const std::string& USR); + CS_IGNORE Declaration* FindAnonymous(const std::string_view& USR); - CS_IGNORE Namespace* FindNamespace(const std::string& Name); - CS_IGNORE Namespace* FindNamespace(const std::vector&); - CS_IGNORE Namespace* FindCreateNamespace(const std::string& Name); + CS_IGNORE Namespace* FindNamespace(const std::string_view& name); + CS_IGNORE Namespace* FindNamespace(const std::vector&); + CS_IGNORE Namespace& FindCreateNamespace(const std::string_view& Name); - CS_IGNORE Class* CreateClass(const std::string& Name, bool IsComplete); - CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete); - CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete, bool Create); + CS_IGNORE Class* CreateClass(const std::string_view& Name, bool IsComplete); + CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete); + CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete, bool Create); CS_IGNORE template - T* FindTemplate(const std::string& USR); + T* FindTemplate(const std::string_view& USR); CS_IGNORE Enumeration* FindEnum(const void* OriginalPtr); - CS_IGNORE Enumeration* FindEnum(const std::string& Name, bool Create = false); - CS_IGNORE Enumeration* FindEnumWithItem(const std::string& Name); + CS_IGNORE Enumeration* FindEnum(const std::string_view& Name, bool Create = false); + CS_IGNORE Enumeration* FindEnumWithItem(const std::string_view& Name); - CS_IGNORE Function* FindFunction(const std::string& USR); + CS_IGNORE Function* FindFunction(const std::string_view& USR); - CS_IGNORE TypedefDecl* FindTypedef(const std::string& Name, bool Create = false); + CS_IGNORE TypedefDecl* FindTypedef(const std::string_view& Name, bool Create = false); - CS_IGNORE TypeAlias* FindTypeAlias(const std::string& Name, bool Create = false); + CS_IGNORE TypeAlias* FindTypeAlias(const std::string_view& Name, bool Create = false); - CS_IGNORE Variable* FindVariable(const std::string& USR); + CS_IGNORE Variable* FindVariable(const std::string_view& USR); - CS_IGNORE Friend* FindFriend(const std::string& USR); + CS_IGNORE Friend* FindFriend(const std::string_view& USR); VECTOR(Namespace*, Namespaces) VECTOR(Enumeration*, Enums) @@ -152,7 +157,7 @@ namespace AST { VECTOR(Variable*, Variables) VECTOR(Friend*, Friends) - std::map anonymous; + std::map> anonymous; bool isAnonymous; }; @@ -203,7 +208,7 @@ namespace AST { class CS_API StatementObsolete { public: - StatementObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = 0); + StatementObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = nullptr); StatementClassObsolete _class; Declaration* decl; std::string string; @@ -212,7 +217,7 @@ namespace AST { class CS_API ExpressionObsolete : public StatementObsolete { public: - ExpressionObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = 0); + ExpressionObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = nullptr); }; class Expr; @@ -238,7 +243,7 @@ namespace AST { class CS_API CXXConstructExprObsolete : public ExpressionObsolete { public: - CXXConstructExprObsolete(const std::string& str, Declaration* decl = 0); + CXXConstructExprObsolete(const std::string& str, Declaration* decl = nullptr); ~CXXConstructExprObsolete(); VECTOR(ExpressionObsolete*, Arguments) }; @@ -417,7 +422,7 @@ namespace AST { BuiltinType* builtinType; VECTOR(Item*, Items) - Item* FindItemByName(const std::string& Name); + Item* FindItemByName(const std::string_view& Name); }; class CS_API Variable : public Declaration @@ -611,10 +616,10 @@ namespace AST { }; template - T* DeclarationContext::FindTemplate(const std::string& USR) + T* DeclarationContext::FindTemplate(const std::string_view& USR) { - auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), - [&](Template* t) + auto foundTemplate = std::find_if(Templates.cbegin(), Templates.cend(), + [&](const Template* t) { return t->USR == USR; }); @@ -782,6 +787,7 @@ namespace AST { Namespace(); ~Namespace(); bool isInline; + bool isNested; }; enum class MacroLocation @@ -845,4 +851,4 @@ namespace AST { } } -} // namespace CppSharp::CppParser::AST \ No newline at end of file +} // namespace CppSharp::CppParser::AST diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 6f268823f0..f3426da564 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -59,6 +59,7 @@ #include #include "ASTNameMangler.h" +#include "ASTNodeVisitor.h" #if defined(__APPLE__) || defined(__linux__) #ifndef _GNU_SOURCE @@ -514,12 +515,6 @@ std::string Parser::GetDeclMangledName(const clang::Decl* D) const if (ND->isTemplated()) return {}; - /*bool CanMangle = isa(D) || isa(D) - || isa(D) || isa(D); - - if (!CanMangle) - return {};*/ - // FIXME: There are likely other contexts in which it makes no sense to ask // for a mangled name. if (isa(ND->getDeclContext())) @@ -2125,8 +2120,8 @@ Field* Parser::WalkFieldCXX(const clang::FieldDecl* FD, Class* Class) //-----------------------------------// -TranslationUnit* Parser::GetTranslationUnit(clang::SourceLocation Loc, - SourceLocationKind* Kind) +TranslationUnit* Parser::GetOrCreateTranslationUnit(clang::SourceLocation Loc, + SourceLocationKind* Kind) { using namespace clang; @@ -2171,12 +2166,12 @@ TranslationUnit* Parser::GetTranslationUnit(clang::SourceLocation Loc, //-----------------------------------// -TranslationUnit* Parser::GetTranslationUnit(const clang::Decl* D) +TranslationUnit* Parser::GetOrCreateTranslationUnit(const clang::Decl* D) { clang::SourceLocation Loc = D->getLocation(); SourceLocationKind Kind; - TranslationUnit* Unit = GetTranslationUnit(Loc, &Kind); + TranslationUnit* Unit = GetOrCreateTranslationUnit(Loc, &Kind); return Unit; } @@ -2190,13 +2185,13 @@ DeclarationContext* Parser::GetNamespace(const clang::Decl* D, // If the declaration is at global scope, just early exit. if (Context->isTranslationUnit()) - return GetTranslationUnit(D); + return GetOrCreateTranslationUnit(D); auto NS = walkedNamespaces[Context]; if (NS) return NS; - TranslationUnit* Unit = GetTranslationUnit(cast(Context)); + TranslationUnit* Unit = GetOrCreateTranslationUnit(cast(Context)); // Else we need to do a more expensive check to get all the namespaces, // and then perform a reverse iteration to get the namespaces in order. @@ -2230,8 +2225,7 @@ DeclarationContext* Parser::GetNamespace(const clang::Decl* D, if (ND->isAnonymousNamespace()) break; - auto Name = ND->getName(); - DC = DC->FindCreateNamespace(Name.str()); + DC = &DC->FindCreateNamespace(ND->getName()); ((Namespace*)DC)->isAnonymous = ND->isAnonymousNamespace(); ((Namespace*)DC)->isInline = ND->isInline(); HandleDeclaration(ND, DC); @@ -3889,7 +3883,7 @@ PreprocessedEntity* Parser::WalkPreprocessedEntity( return nullptr; Entity->originalPtr = PPEntity; - auto Namespace = GetTranslationUnit(PPEntity->getSourceRange().getBegin()); + auto Namespace = GetOrCreateTranslationUnit(PPEntity->getSourceRange().getBegin()); if (Decl->kind == DeclarationKind::TranslationUnit) { @@ -4402,7 +4396,7 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D) } case Decl::TranslationUnit: { - Decl = GetTranslationUnit(D); + Decl = GetOrCreateTranslationUnit(D); break; } case Decl::Namespace: @@ -4676,6 +4670,15 @@ void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx) if (Unit->originalPtr == nullptr) Unit->originalPtr = (void*)FileEntry; + std::string Text; + Text.reserve(200000000); + { + llvm::raw_string_ostream OS(Text); + + ASTNodeDumper Dumper(OS, Ctx, Parser); + Dumper.Visit(TU); + } + Parser.WalkAST(TU); } diff --git a/src/CppParser/Parser.h b/src/CppParser/Parser.h index 08f6e6799c..c3be246669 100644 --- a/src/CppParser/Parser.h +++ b/src/CppParser/Parser.h @@ -97,8 +97,8 @@ namespace CppSharp { namespace CppParser { void WalkVariable(const clang::VarDecl* VD, AST::Variable* Var); AST::Friend* WalkFriend(const clang::FriendDecl* FD); AST::RawComment* WalkRawComment(const clang::RawComment* RC); - AST::Type* WalkType(clang::QualType QualType, const clang::TypeLoc* TL = 0, bool DesugarType = false); - AST::TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc = 0); + AST::Type* WalkType(clang::QualType QualType, const clang::TypeLoc* TL = nullptr, bool DesugarType = false); + AST::TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc = nullptr); AST::TemplateTemplateParameter* WalkTemplateTemplateParameter(const clang::TemplateTemplateParmDecl* TTP); AST::TypeTemplateParameter* WalkTypeTemplateParameter(const clang::TemplateTypeParmDecl* TTPD); AST::NonTypeTemplateParameter* WalkNonTypeTemplateParameter(const clang::NonTypeTemplateParmDecl* TTPD); @@ -116,7 +116,7 @@ namespace CppSharp { namespace CppParser { std::vector WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, TypeLoc* TSTL); std::vector WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, const clang::ASTTemplateArgumentListInfo* TSTL); void WalkVTable(const clang::CXXRecordDecl* RD, AST::Class* C); - AST::QualifiedType GetQualifiedType(clang::QualType qual, const clang::TypeLoc* TL = 0); + AST::QualifiedType GetQualifiedType(clang::QualType qual, const clang::TypeLoc* TL = nullptr); void ReadClassLayout(AST::Class* Class, const clang::RecordDecl* RD, clang::CharUnits Offset, bool IncludeVirtualBases); AST::LayoutField WalkVTablePointer(AST::Class* Class, const clang::CharUnits& Offset, const std::string& prefix); AST::VTableLayout WalkVTableLayout(const clang::VTableLayout& VTLayout); @@ -150,9 +150,9 @@ namespace CppSharp { namespace CppParser { bool GetDeclText(clang::SourceRange SR, std::string& Text); bool HasLayout(const clang::RecordDecl* Record); - AST::TranslationUnit* GetTranslationUnit(clang::SourceLocation Loc, - SourceLocationKind* Kind = 0); - AST::TranslationUnit* GetTranslationUnit(const clang::Decl* D); + AST::TranslationUnit* GetOrCreateTranslationUnit(clang::SourceLocation Loc, + SourceLocationKind* Kind = nullptr); + AST::TranslationUnit* GetOrCreateTranslationUnit(const clang::Decl* D); AST::DeclarationContext* GetNamespace(const clang::Decl* D, const clang::DeclContext* Ctx); AST::DeclarationContext* GetNamespace(const clang::Decl* D); diff --git a/src/CppParser/ParserGen/ParserGen.cs b/src/CppParser/ParserGen/ParserGen.cs index 98258a5e20..240837d9a6 100644 --- a/src/CppParser/ParserGen/ParserGen.cs +++ b/src/CppParser/ParserGen/ParserGen.cs @@ -28,6 +28,8 @@ public ParserGen(GeneratorKind kind, string triple, Kind = kind; Triple = triple; IsGnuCpp11Abi = isGnuCpp11Abi; + + Diagnostics.Level = DiagnosticKind.Debug; } static string GetSourceDirectory(string dir) diff --git a/src/CppParser/Types.h b/src/CppParser/Types.h index e8a05f32f1..8f6c8c3d60 100644 --- a/src/CppParser/Types.h +++ b/src/CppParser/Types.h @@ -9,324 +9,326 @@ #include "Helpers.h" -namespace CppSharp { namespace CppParser { namespace AST { - - enum class TypeKind - { - Tag, - Array, - Function, - Pointer, - MemberPointer, - Typedef, - Attributed, - Decayed, - TemplateSpecialization, - DependentTemplateSpecialization, - TemplateParameter, - TemplateParameterSubstitution, - InjectedClassName, - DependentName, - PackExpansion, - Builtin, - UnaryTransform, - UnresolvedUsing, - Vector - }; +namespace CppSharp::CppParser::AST { + +enum class TypeKind +{ + Tag, + Array, + Function, + Pointer, + MemberPointer, + Typedef, + Attributed, + Decayed, + TemplateSpecialization, + DependentTemplateSpecialization, + TemplateParameter, + TemplateParameterSubstitution, + InjectedClassName, + DependentName, + PackExpansion, + Builtin, + UnaryTransform, + UnresolvedUsing, + Vector +}; #define DECLARE_TYPE_KIND(kind) \ kind##Type(); - class CS_API Type - { - public: - Type(TypeKind kind); - Type(const Type&); - - TypeKind kind; - bool isDependent; - }; - - struct CS_API TypeQualifiers - { - bool isConst; - bool isVolatile; - bool isRestrict; - }; - - struct CS_API QualifiedType - { - QualifiedType(); - Type* type; - TypeQualifiers qualifiers; - }; - - class Declaration; - - class CS_API TagType : public Type - { - public: - DECLARE_TYPE_KIND(Tag) - Declaration* declaration; - }; - - class CS_API ArrayType : public Type - { - public: - enum class ArraySize - { - Constant, - Variable, - Dependent, - Incomplete - }; - - DECLARE_TYPE_KIND(Array) - QualifiedType qualifiedType; - ArraySize sizeType; - long size; - long elementSize; - }; - - class Parameter; - - enum class CallingConvention - { - Default, - C, - StdCall, - ThisCall, - FastCall, - Unknown - }; - - enum class ExceptionSpecType +class CS_API Type +{ +public: + Type(TypeKind kind); + Type(const Type&); + + TypeKind kind; + bool isDependent = false; +}; + +struct CS_API TypeQualifiers +{ + bool isConst = false; + bool isVolatile = false; + bool isRestrict = false; +}; + +struct CS_API QualifiedType +{ + QualifiedType(); + Type* type = nullptr; + Type* desugaredType = nullptr; + void* typeAliasDeclId = nullptr; + TypeQualifiers qualifiers; +}; + +class Declaration; + +class CS_API TagType : public Type +{ +public: + DECLARE_TYPE_KIND(Tag) + Declaration* declaration; +}; + +class CS_API ArrayType : public Type +{ +public: + enum class ArraySize { - None, - DynamicNone, - Dynamic, - MSAny, - BasicNoexcept, - DependentNoexcept, - NoexceptFalse, - NoexceptTrue, - Unevaluated, - Uninstantiated, - Unparsed + Constant, + Variable, + Dependent, + Incomplete }; - class CS_API FunctionType : public Type + DECLARE_TYPE_KIND(Array) + QualifiedType qualifiedType; + ArraySize sizeType; + long size; + long elementSize; +}; + +class Parameter; + +enum class CallingConvention +{ + Default, + C, + StdCall, + ThisCall, + FastCall, + Unknown +}; + +enum class ExceptionSpecType +{ + None, + DynamicNone, + Dynamic, + MSAny, + BasicNoexcept, + DependentNoexcept, + NoexceptFalse, + NoexceptTrue, + Unevaluated, + Uninstantiated, + Unparsed +}; + +class CS_API FunctionType : public Type +{ +public: + DECLARE_TYPE_KIND(Function) + ~FunctionType(); + QualifiedType returnType; + CallingConvention callingConvention; + ExceptionSpecType exceptionSpecType; + VECTOR(Parameter*, Parameters) +}; + +class CS_API PointerType : public Type +{ +public: + enum struct TypeModifier { - public: - DECLARE_TYPE_KIND(Function) - ~FunctionType(); - QualifiedType returnType; - CallingConvention callingConvention; - ExceptionSpecType exceptionSpecType; - VECTOR(Parameter*, Parameters) - }; - - class CS_API PointerType : public Type - { - public: - enum struct TypeModifier - { - Value, - Pointer, - LVReference, - RVReference - }; - - DECLARE_TYPE_KIND(Pointer) - QualifiedType qualifiedPointee; - TypeModifier modifier; - }; - - class CS_API MemberPointerType : public Type - { - public: - DECLARE_TYPE_KIND(MemberPointer) - QualifiedType pointee; - }; - - class TypedefNameDecl; - - class CS_API TypedefType : public Type - { - public: - TypedefType(); - TypedefNameDecl* declaration; - }; - - class CS_API AttributedType : public Type - { - public: - DECLARE_TYPE_KIND(Attributed) - QualifiedType modified; - QualifiedType equivalent; - }; - - class CS_API DecayedType : public Type - { - public: - DECLARE_TYPE_KIND(Decayed) - QualifiedType decayed; - QualifiedType original; - QualifiedType pointee; - }; - - struct CS_API TemplateArgument - { - TemplateArgument(); - - enum struct ArgumentKind - { - Type, - Declaration, - NullPtr, - Integral, - Template, - TemplateExpansion, - Expression, - Pack - }; - - ArgumentKind kind; - QualifiedType type; - Declaration* declaration; - long integral; - }; - - class Template; - - class CS_API TemplateSpecializationType : public Type - { - public: - TemplateSpecializationType(); - TemplateSpecializationType(const TemplateSpecializationType&); - ~TemplateSpecializationType(); - - VECTOR(TemplateArgument, Arguments) - Template* _template; - QualifiedType desugared; - }; - - class CS_API DependentTemplateSpecializationType : public Type - { - public: - DependentTemplateSpecializationType(); - DependentTemplateSpecializationType(const DependentTemplateSpecializationType&); - ~DependentTemplateSpecializationType(); - - VECTOR(TemplateArgument, Arguments) - QualifiedType desugared; - }; - - class TypeTemplateParameter; - - class CS_API TemplateParameterType : public Type - { - public: - DECLARE_TYPE_KIND(TemplateParameter) - ~TemplateParameterType(); - TypeTemplateParameter* parameter; - unsigned int depth; - unsigned int index; - bool isParameterPack; - }; - - class CS_API TemplateParameterSubstitutionType : public Type - { - public: - DECLARE_TYPE_KIND(TemplateParameterSubstitution) - QualifiedType replacement; - TemplateParameterType* replacedParameter; - }; - - class Class; - - class CS_API InjectedClassNameType : public Type - { - public: - DECLARE_TYPE_KIND(InjectedClassName) - QualifiedType injectedSpecializationType; - Class* _class; - }; - - class CS_API DependentNameType : public Type - { - public: - DECLARE_TYPE_KIND(DependentName) - ~DependentNameType(); - QualifiedType qualifier; - std::string identifier; - }; - - class CS_API PackExpansionType : public Type - { - public: - DECLARE_TYPE_KIND(PackExpansion) - }; - - class CS_API UnaryTransformType : public Type - { - public: - DECLARE_TYPE_KIND(UnaryTransform) - QualifiedType desugared; - QualifiedType baseType; - }; - - class UnresolvedUsingTypename; - - class CS_API UnresolvedUsingType : public Type - { - public: - DECLARE_TYPE_KIND(UnresolvedUsing) - UnresolvedUsingTypename* declaration; - }; - - class CS_API VectorType : public Type - { - public: - DECLARE_TYPE_KIND(Vector) - QualifiedType elementType; - unsigned numElements; - }; - - enum class PrimitiveType - { - Null, - Void, - Bool, - WideChar, - Char, - SChar, - UChar, - Char16, - Char32, - Short, - UShort, - Int, - UInt, - Long, - ULong, - LongLong, - ULongLong, - Int128, - UInt128, - Half, - Float, - Double, - LongDouble, - Float128, - IntPtr + Value, + Pointer, + LVReference, + RVReference }; - class CS_API BuiltinType : public Type + DECLARE_TYPE_KIND(Pointer) + QualifiedType qualifiedPointee; + TypeModifier modifier; +}; + +class CS_API MemberPointerType : public Type +{ +public: + DECLARE_TYPE_KIND(MemberPointer) + QualifiedType pointee; +}; + +class TypedefNameDecl; + +class CS_API TypedefType : public Type +{ +public: + TypedefType(); + TypedefNameDecl* declaration; +}; + +class CS_API AttributedType : public Type +{ +public: + DECLARE_TYPE_KIND(Attributed) + QualifiedType modified; + QualifiedType equivalent; +}; + +class CS_API DecayedType : public Type +{ +public: + DECLARE_TYPE_KIND(Decayed) + QualifiedType decayed; + QualifiedType original; + QualifiedType pointee; +}; + +struct CS_API TemplateArgument +{ + TemplateArgument(); + + enum struct ArgumentKind { - public: - DECLARE_TYPE_KIND(Builtin) - PrimitiveType type; + Type, + Declaration, + NullPtr, + Integral, + Template, + TemplateExpansion, + Expression, + Pack }; -}}} // namespace CppSharp::CppParser::AST + ArgumentKind kind; + QualifiedType type; + Declaration* declaration; + long integral; +}; + +class Template; + +class CS_API TemplateSpecializationType : public Type +{ +public: + TemplateSpecializationType(); + TemplateSpecializationType(const TemplateSpecializationType&); + ~TemplateSpecializationType(); + + VECTOR(TemplateArgument, Arguments) + Template* _template; + QualifiedType desugared; +}; + +class CS_API DependentTemplateSpecializationType : public Type +{ +public: + DependentTemplateSpecializationType(); + DependentTemplateSpecializationType(const DependentTemplateSpecializationType&); + ~DependentTemplateSpecializationType(); + + VECTOR(TemplateArgument, Arguments) + QualifiedType desugared; +}; + +class TypeTemplateParameter; + +class CS_API TemplateParameterType : public Type +{ +public: + DECLARE_TYPE_KIND(TemplateParameter) + ~TemplateParameterType(); + TypeTemplateParameter* parameter; + unsigned int depth; + unsigned int index; + bool isParameterPack; +}; + +class CS_API TemplateParameterSubstitutionType : public Type +{ +public: + DECLARE_TYPE_KIND(TemplateParameterSubstitution) + QualifiedType replacement; + TemplateParameterType* replacedParameter; +}; + +class Class; + +class CS_API InjectedClassNameType : public Type +{ +public: + DECLARE_TYPE_KIND(InjectedClassName) + QualifiedType injectedSpecializationType; + Class* _class; +}; + +class CS_API DependentNameType : public Type +{ +public: + DECLARE_TYPE_KIND(DependentName) + ~DependentNameType(); + QualifiedType qualifier; + std::string identifier; +}; + +class CS_API PackExpansionType : public Type +{ +public: + DECLARE_TYPE_KIND(PackExpansion) +}; + +class CS_API UnaryTransformType : public Type +{ +public: + DECLARE_TYPE_KIND(UnaryTransform) + QualifiedType desugared; + QualifiedType baseType; +}; + +class UnresolvedUsingTypename; + +class CS_API UnresolvedUsingType : public Type +{ +public: + DECLARE_TYPE_KIND(UnresolvedUsing) + UnresolvedUsingTypename* declaration; +}; + +class CS_API VectorType : public Type +{ +public: + DECLARE_TYPE_KIND(Vector) + QualifiedType elementType; + unsigned numElements; +}; + +enum class PrimitiveType +{ + Null, + Void, + Bool, + WideChar, + Char, + SChar, + UChar, + Char16, + Char32, + Short, + UShort, + Int, + UInt, + Long, + ULong, + LongLong, + ULongLong, + Int128, + UInt128, + Half, + Float, + Double, + LongDouble, + Float128, + IntPtr +}; + +class CS_API BuiltinType : public Type +{ +public: + DECLARE_TYPE_KIND(Builtin) + PrimitiveType type; +}; + +} // namespace CppSharp::CppParser::AST diff --git a/src/Generator.Tests/GeneratorTest.cs b/src/Generator.Tests/GeneratorTest.cs index 3805353ad7..709d943e53 100644 --- a/src/Generator.Tests/GeneratorTest.cs +++ b/src/Generator.Tests/GeneratorTest.cs @@ -28,6 +28,7 @@ public virtual void Setup(Driver driver) options.Quiet = true; options.GenerateDebugOutput = true; options.CheckSymbols = true; + driver.ParserOptions.SkipSystemHeaders = false; var testModule = options.AddModule(name); Diagnostics.Message(""); From 488ee7ebbb7fc3d52f56752fdefeeddb92b4a217 Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Sun, 23 Feb 2025 16:15:11 +0100 Subject: [PATCH 2/3] Using macros Still broken due to missing classes --- src/CppParser/ASTNodeVisitor.h | 938 ++++++++++++++++----------------- src/CppParser/StmtNodes.inc | 935 ++++++++++++++++++++++++++++++++ 2 files changed, 1401 insertions(+), 472 deletions(-) create mode 100644 src/CppParser/StmtNodes.inc diff --git a/src/CppParser/ASTNodeVisitor.h b/src/CppParser/ASTNodeVisitor.h index e010f034b5..d94c5e6e73 100644 --- a/src/CppParser/ASTNodeVisitor.h +++ b/src/CppParser/ASTNodeVisitor.h @@ -18,528 +18,522 @@ #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/CommentVisitor.h" #include "clang/AST/ExprConcepts.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include +#include "Decl.h" +#include "Stmt.h" + namespace CppSharp::CppParser { - namespace AST { - class Stmt; +namespace AST { + class Stmt; + + // TODO: Remove this once we have proper type conversions + using Decl = Declaration; +} // namespace AST +class Parser; + +class NodeStreamer +{ + bool FirstChild = true; + bool TopLevel = true; + llvm::SmallVector, 32> Pending; + +protected: + llvm::json::OStream JOS; + +public: + /// Add a child of the current node. Calls DoAddChild without arguments + template + void AddChild(Fn DoAddChild) + { + return AddChild("", DoAddChild); } - class Parser; - class NodeStreamer + /// Add a child of the current node with an optional label. + /// Calls DoAddChild without arguments. + template + void AddChild(llvm::StringRef Label, Fn DoAddChild) { - bool FirstChild = true; - bool TopLevel = true; - llvm::SmallVector, 32> Pending; + // If we're at the top level, there's nothing interesting to do; just + // run the dumper. + if (TopLevel) + { + TopLevel = false; + JOS.objectBegin(); - protected: - llvm::json::OStream JOS; + DoAddChild(); - public: - /// Add a child of the current node. Calls DoAddChild without arguments - template - void AddChild(Fn DoAddChild) - { - return AddChild("", DoAddChild); + while (!Pending.empty()) + { + Pending.back()(true); + Pending.pop_back(); + } + + JOS.objectEnd(); + TopLevel = true; + return; } - /// Add a child of the current node with an optional label. - /// Calls DoAddChild without arguments. - template - void AddChild(llvm::StringRef Label, Fn DoAddChild) + // We need to capture an owning-string in the lambda because the lambda + // is invoked in a deferred manner. + std::string LabelStr(!Label.empty() ? Label : "inner"); + bool WasFirstChild = FirstChild; + auto DumpWithIndent = [=](bool IsLastChild) { - // If we're at the top level, there's nothing interesting to do; just - // run the dumper. - if (TopLevel) + if (WasFirstChild) { - TopLevel = false; - JOS.objectBegin(); + JOS.attributeBegin(LabelStr); + JOS.arrayBegin(); + } - DoAddChild(); + FirstChild = true; + unsigned Depth = Pending.size(); + JOS.objectBegin(); - while (!Pending.empty()) - { - Pending.back()(true); - Pending.pop_back(); - } + DoAddChild(); - JOS.objectEnd(); - TopLevel = true; - return; - } - - // We need to capture an owning-string in the lambda because the lambda - // is invoked in a deferred manner. - std::string LabelStr(!Label.empty() ? Label : "inner"); - bool WasFirstChild = FirstChild; - auto DumpWithIndent = [=](bool IsLastChild) - { - if (WasFirstChild) - { - JOS.attributeBegin(LabelStr); - JOS.arrayBegin(); - } - - FirstChild = true; - unsigned Depth = Pending.size(); - JOS.objectBegin(); - - DoAddChild(); - - // If any children are left, they're the last at their nesting level. - // Dump those ones out now. - while (Depth < Pending.size()) - { - Pending.back()(true); - this->Pending.pop_back(); - } - - JOS.objectEnd(); - - if (IsLastChild) - { - JOS.arrayEnd(); - JOS.attributeEnd(); - } - }; - - if (FirstChild) + // If any children are left, they're the last at their nesting level. + // Dump those ones out now. + while (Depth < Pending.size()) { - Pending.push_back(std::move(DumpWithIndent)); + Pending.back()(true); + this->Pending.pop_back(); } - else + + JOS.objectEnd(); + + if (IsLastChild) { - Pending.back()(false); - Pending.back() = std::move(DumpWithIndent); + JOS.arrayEnd(); + JOS.attributeEnd(); } - FirstChild = false; - } + }; - NodeStreamer(llvm::raw_ostream& OS) - : JOS(OS, 2) + if (FirstChild) { + Pending.push_back(std::move(DumpWithIndent)); } - }; - - // Dumps AST nodes in JSON format. There is no implied stability for the - // content or format of the dump between major releases of Clang, other than it - // being valid JSON output. Further, there is no requirement that the - // information dumped is a complete representation of the AST, only that the - // information presented is correct. - class ASTNodeVisitor - : public clang::ConstAttrVisitor, - public clang::comments::ConstCommentVisitor, - public clang::ConstTemplateArgumentVisitor, - public clang::ConstStmtVisitor, - public clang::TypeVisitor, - public clang::ConstDeclVisitor, - public NodeStreamer - { - friend class ASTNodeDumper; - - using InnerAttrVisitor = ConstAttrVisitor; - using InnerCommentVisitor = ConstCommentVisitor; - using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor; - using InnerStmtVisitor = ConstStmtVisitor; - using InnerTypeVisitor = TypeVisitor; - using InnerDeclVisitor = ConstDeclVisitor; - - public: - ASTNodeVisitor(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) - : NodeStreamer(OS) - , parser(parser) - , SM(Ctx.getSourceManager()) - , Ctx(Ctx) - , NameMangler(Ctx) - , PrintPolicy(Ctx.getPrintingPolicy()) - , Traits(Ctx.getCommentCommandTraits()) - , LastLocLine(0) - , LastLocPresumedLine(0) + else { - declMap.reserve(32768); - typeMap.reserve(32768); - stmtMap.reserve(32768); + Pending.back()(false); + Pending.back() = std::move(DumpWithIndent); } + FirstChild = false; + } - void Visit(const clang::Attr* A); - void Visit(const clang::Stmt* S); - void Visit(const clang::Type* T); - void Visit(clang::QualType T); - AST::Declaration* Visit(const clang::Decl* D); - void Visit(clang::TypeLoc TL); - - void Visit(const clang::comments::Comment* C, const clang::comments::FullComment* FC); - void Visit(const clang::TemplateArgument& TA, clang::SourceRange R = {}, const clang::Decl* From = nullptr, llvm::StringRef Label = {}); - void Visit(const clang::CXXCtorInitializer* Init); - // void Visit(const OpenACCClause* C) {} - void Visit(const clang::OMPClause* C) {} - void Visit(const clang::BlockDecl::Capture& C); - void Visit(const clang::GenericSelectionExpr::ConstAssociation& A); - void Visit(const clang::concepts::Requirement* R); - void Visit(const clang::APValue& Value, clang::QualType Ty); - void Visit(const clang::ConceptReference*); - - void VisitAliasAttr(const clang::AliasAttr* AA); - void VisitCleanupAttr(const clang::CleanupAttr* CA); - void VisitDeprecatedAttr(const clang::DeprecatedAttr* DA); - void VisitUnavailableAttr(const clang::UnavailableAttr* UA); - void VisitSectionAttr(const clang::SectionAttr* SA); - void VisitVisibilityAttr(const clang::VisibilityAttr* VA); - void VisitTLSModelAttr(const clang::TLSModelAttr* TA); - - void VisitTypedefType(const clang::TypedefType* TT); - void VisitUsingType(const clang::UsingType* TT); - void VisitFunctionType(const clang::FunctionType* T); - void VisitFunctionProtoType(const clang::FunctionProtoType* T); - void VisitRValueReferenceType(const clang::ReferenceType* RT); - void VisitArrayType(const clang::ArrayType* AT); - void VisitConstantArrayType(const clang::ConstantArrayType* CAT); - void VisitDependentSizedExtVectorType(const clang::DependentSizedExtVectorType* VT); - void VisitVectorType(const clang::VectorType* VT); - void VisitUnresolvedUsingType(const clang::UnresolvedUsingType* UUT); - void VisitUnaryTransformType(const clang::UnaryTransformType* UTT); - void VisitTagType(const clang::TagType* TT); - void VisitTemplateTypeParmType(const clang::TemplateTypeParmType* TTPT); - void VisitSubstTemplateTypeParmType(const clang::SubstTemplateTypeParmType* STTPT); - void VisitSubstTemplateTypeParmPackType(const clang::SubstTemplateTypeParmPackType* T); - void VisitAutoType(const clang::AutoType* AT); - void VisitTemplateSpecializationType(const clang::TemplateSpecializationType* TST); - void VisitInjectedClassNameType(const clang::InjectedClassNameType* ICNT); - void VisitObjCInterfaceType(const clang::ObjCInterfaceType* OIT); - void VisitPackExpansionType(const clang::PackExpansionType* PET); - void VisitElaboratedType(const clang::ElaboratedType* ET); - void VisitMacroQualifiedType(const clang::MacroQualifiedType* MQT); - void VisitMemberPointerType(const clang::MemberPointerType* MPT); - - AST::Declaration* VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); - AST::Declaration* VisitNamedDecl(const clang::NamedDecl* ND); - void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); - AST::Declaration* VisitTypedefDecl(const clang::TypedefDecl* TD); - AST::Declaration* VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); - AST::Declaration* VisitNamespaceDecl(const clang::NamespaceDecl* ND); - AST::Declaration* VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); - AST::Declaration* VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); - AST::Declaration* VisitUsingDecl(const clang::UsingDecl* UD); - AST::Declaration* VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); - AST::Declaration* VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); - AST::Declaration* VisitVarDecl(const clang::VarDecl* VD); - AST::Declaration* VisitFieldDecl(const clang::FieldDecl* FD); - AST::Declaration* VisitFunctionDecl(const clang::FunctionDecl* FD); - AST::Declaration* VisitEnumDecl(const clang::EnumDecl* ED); - AST::Declaration* VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); - AST::Declaration* VisitRecordDecl(const clang::RecordDecl* RD); - AST::Declaration* VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); - AST::Declaration* VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); - AST::Declaration* VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); - AST::Declaration* VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); - AST::Declaration* VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); - AST::Declaration* VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); - AST::Declaration* VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); - AST::Declaration* VisitFriendDecl(const clang::FriendDecl* FD); - - AST::Declaration* VisitObjCIvarDecl(const clang::ObjCIvarDecl* D); - AST::Declaration* VisitObjCMethodDecl(const clang::ObjCMethodDecl* D); - AST::Declaration* VisitObjCTypeParamDecl(const clang::ObjCTypeParamDecl* D); - AST::Declaration* VisitObjCCategoryDecl(const clang::ObjCCategoryDecl* D); - AST::Declaration* VisitObjCCategoryImplDecl(const clang::ObjCCategoryImplDecl* D); - AST::Declaration* VisitObjCProtocolDecl(const clang::ObjCProtocolDecl* D); - AST::Declaration* VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl* D); - AST::Declaration* VisitObjCImplementationDecl(const clang::ObjCImplementationDecl* D); - AST::Declaration* VisitObjCCompatibleAliasDecl(const clang::ObjCCompatibleAliasDecl* D); - AST::Declaration* VisitObjCPropertyDecl(const clang::ObjCPropertyDecl* D); - AST::Declaration* VisitObjCPropertyImplDecl(const clang::ObjCPropertyImplDecl* D); - AST::Declaration* VisitBlockDecl(const clang::BlockDecl* D); - - void VisitDeclRefExpr(const clang::DeclRefExpr* DRE); - void VisitSYCLUniqueStableNameExpr(const clang::SYCLUniqueStableNameExpr* E); - // void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr* E) {} - void VisitPredefinedExpr(const clang::PredefinedExpr* PE); - void VisitUnaryOperator(const clang::UnaryOperator* UO); - void VisitBinaryOperator(const clang::BinaryOperator* BO); - void VisitCompoundAssignOperator(const clang::CompoundAssignOperator* CAO); - void VisitMemberExpr(const clang::MemberExpr* ME); - void VisitAtomicExpr(const clang::AtomicExpr* AE); - void VisitCXXNewExpr(const clang::CXXNewExpr* NE); - void VisitCXXDeleteExpr(const clang::CXXDeleteExpr* DE); - void VisitCXXThisExpr(const clang::CXXThisExpr* TE); - void VisitCastExpr(const clang::CastExpr* CE); - void VisitImplicitCastExpr(const clang::ImplicitCastExpr* ICE); - void VisitCallExpr(const clang::CallExpr* CE); - void VisitUnaryExprOrTypeTraitExpr(const clang::UnaryExprOrTypeTraitExpr* TTE); - void VisitSizeOfPackExpr(const clang::SizeOfPackExpr* SOPE); - void VisitUnresolvedLookupExpr(const clang::UnresolvedLookupExpr* ULE); - void VisitAddrLabelExpr(const clang::AddrLabelExpr* ALE); - void VisitCXXTypeidExpr(const clang::CXXTypeidExpr* CTE); - void VisitConstantExpr(const clang::ConstantExpr* CE); - void VisitInitListExpr(const clang::InitListExpr* ILE); - void VisitGenericSelectionExpr(const clang::GenericSelectionExpr* GSE); - void VisitCXXUnresolvedConstructExpr(const clang::CXXUnresolvedConstructExpr* UCE); - void VisitCXXConstructExpr(const clang::CXXConstructExpr* CE); - void VisitExprWithCleanups(const clang::ExprWithCleanups* EWC); - void VisitCXXBindTemporaryExpr(const clang::CXXBindTemporaryExpr* BTE); - void VisitMaterializeTemporaryExpr(const clang::MaterializeTemporaryExpr* MTE); - void VisitCXXDependentScopeMemberExpr(const clang::CXXDependentScopeMemberExpr* ME); - void VisitRequiresExpr(const clang::RequiresExpr* RE); - void VisitCXXDefaultArgExpr(const clang::CXXDefaultArgExpr* Node); - void VisitCXXDefaultInitExpr(const clang::CXXDefaultInitExpr* Node); - void VisitCXXBoolLiteralExpr(const clang::CXXBoolLiteralExpr* BLE); - - void VisitObjCEncodeExpr(const clang::ObjCEncodeExpr* OEE); - void VisitObjCMessageExpr(const clang::ObjCMessageExpr* OME); - void VisitObjCBoxedExpr(const clang::ObjCBoxedExpr* OBE); - void VisitObjCSelectorExpr(const clang::ObjCSelectorExpr* OSE); - void VisitObjCProtocolExpr(const clang::ObjCProtocolExpr* OPE); - void VisitObjCPropertyRefExpr(const clang::ObjCPropertyRefExpr* OPRE); - void VisitObjCSubscriptRefExpr(const clang::ObjCSubscriptRefExpr* OSRE); - void VisitObjCIvarRefExpr(const clang::ObjCIvarRefExpr* OIRE); - void VisitObjCBoolLiteralExpr(const clang::ObjCBoolLiteralExpr* OBLE); - - void VisitIntegerLiteral(const clang::IntegerLiteral* IL); - void VisitCharacterLiteral(const clang::CharacterLiteral* CL); - void VisitFixedPointLiteral(const clang::FixedPointLiteral* FPL); - void VisitFloatingLiteral(const clang::FloatingLiteral* FL); - void VisitStringLiteral(const clang::StringLiteral* SL); - - void VisitIfStmt(const clang::IfStmt* IS); - void VisitSwitchStmt(const clang::SwitchStmt* SS); - void VisitCaseStmt(const clang::CaseStmt* CS); - void VisitLabelStmt(const clang::LabelStmt* LS); - void VisitGotoStmt(const clang::GotoStmt* GS); - void VisitWhileStmt(const clang::WhileStmt* WS); - void VisitObjCAtCatchStmt(const clang::ObjCAtCatchStmt* OACS); - void VisitCompoundStmt(const clang::CompoundStmt* IS); - - void VisitNullTemplateArgument(const clang::TemplateArgument& TA); - void VisitTypeTemplateArgument(const clang::TemplateArgument& TA); - void VisitDeclarationTemplateArgument(const clang::TemplateArgument& TA); - void VisitNullPtrTemplateArgument(const clang::TemplateArgument& TA); - void VisitIntegralTemplateArgument(const clang::TemplateArgument& TA); - void VisitTemplateTemplateArgument(const clang::TemplateArgument& TA); - void VisitTemplateExpansionTemplateArgument(const clang::TemplateArgument& TA); - void VisitExpressionTemplateArgument(const clang::TemplateArgument& TA); - void VisitPackTemplateArgument(const clang::TemplateArgument& TA); - - void visitTextComment(const clang::comments::TextComment* C, const clang::comments::FullComment*); - void visitInlineCommandComment(const clang::comments::InlineCommandComment* C, const clang::comments::FullComment*); - void visitHTMLStartTagComment(const clang::comments::HTMLStartTagComment* C, const clang::comments::FullComment*); - void visitHTMLEndTagComment(const clang::comments::HTMLEndTagComment* C, const clang::comments::FullComment*); - void visitBlockCommandComment(const clang::comments::BlockCommandComment* C, const clang::comments::FullComment*); - void visitParamCommandComment(const clang::comments::ParamCommandComment* C, const clang::comments::FullComment* FC); - void visitTParamCommandComment(const clang::comments::TParamCommandComment* C, const clang::comments::FullComment* FC); - void visitVerbatimBlockComment(const clang::comments::VerbatimBlockComment* C, const clang::comments::FullComment*); - void visitVerbatimBlockLineComment(const clang::comments::VerbatimBlockLineComment* C, const clang::comments::FullComment*); - void visitVerbatimLineComment(const clang::comments::VerbatimLineComment* C, const clang::comments::FullComment*); - - private: - void attributeOnlyIfTrue(llvm::StringRef Key, bool Value) - { - if (Value) - JOS.attribute(Key, Value); - } + NodeStreamer(llvm::raw_ostream& OS) + : JOS(OS, 2) + { + } +}; + +// Dumps AST nodes in JSON format. There is no implied stability for the +// content or format of the dump between major releases of Clang, other than it +// being valid JSON output. Further, there is no requirement that the +// information dumped is a complete representation of the AST, only that the +// information presented is correct. +class ASTNodeVisitor + : public clang::ConstAttrVisitor, + public clang::comments::ConstCommentVisitor, + public clang::ConstTemplateArgumentVisitor, + public clang::ConstStmtVisitor, + public clang::TypeVisitor, + public clang::ConstDeclVisitor, + public NodeStreamer +{ + friend class ASTNodeDumper; + + using InnerAttrVisitor = ConstAttrVisitor; + using InnerCommentVisitor = ConstCommentVisitor; + using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor; + using InnerStmtVisitor = ConstStmtVisitor; + using InnerTypeVisitor = TypeVisitor; + using InnerDeclVisitor = ConstDeclVisitor; + +public: + ASTNodeVisitor(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) + : NodeStreamer(OS) + , parser(parser) + , SM(Ctx.getSourceManager()) + , Ctx(Ctx) + , NameMangler(Ctx) + , PrintPolicy(Ctx.getPrintingPolicy()) + , Traits(Ctx.getCommentCommandTraits()) + , LastLocLine(0) + , LastLocPresumedLine(0) + { + declMap.reserve(32768); + typeMap.reserve(32768); + stmtMap.reserve(32768); + } - void writeIncludeStack(clang::PresumedLoc Loc, bool JustFirst = false); - - // Writes the attributes of a SourceLocation object without. - void writeBareSourceLocation(clang::SourceLocation Loc, bool IsSpelling, bool addFileInfo); - - // Writes the attributes of a SourceLocation to JSON based on its presumed - // spelling location. If the given location represents a macro invocation, - // this outputs two sub-objects: one for the spelling and one for the - // expansion location. - void writeSourceLocation(clang::SourceLocation Loc, bool addFileInfo = true); - void writeSourceRange(clang::SourceRange R); - std::string createPointerRepresentation(const void* Ptr); - llvm::json::Object createQualType(clang::QualType QT, bool Desugar = true); - AST::QualifiedType CreateQualifiedType(clang::QualType QT, bool Desugar = true); - llvm::json::Object createBareDeclRef(const clang::Decl* D); - llvm::json::Object createFPOptions(clang::FPOptionsOverride FPO); - void writeBareDeclRef(const clang::Decl* D); - llvm::json::Object createCXXRecordDefinitionData(const clang::CXXRecordDecl* RD); - llvm::json::Object createCXXBaseSpecifier(const clang::CXXBaseSpecifier& BS); - std::string createAccessSpecifier(clang::AccessSpecifier AS); - llvm::json::Array createCastPath(const clang::CastExpr* C); - - void writePreviousDeclImpl(...) {} - - template - void writePreviousDeclImpl(const clang::Mergeable* D) - { - const T* First = D->getFirstDecl(); - if (First != D) - JOS.attribute("firstRedecl", createPointerRepresentation(First)); + void Visit(const clang::Attr* A); + void Visit(const clang::Stmt* S); + void Visit(const clang::Type* T); + void Visit(clang::QualType T); + AST::Declaration* Visit(const clang::Decl* D); + void Visit(clang::TypeLoc TL); + + void Visit(const clang::comments::Comment* C, const clang::comments::FullComment* FC); + void Visit(const clang::TemplateArgument& TA, clang::SourceRange R = {}, const clang::Decl* From = nullptr, llvm::StringRef Label = {}); + void Visit(const clang::CXXCtorInitializer* Init); + // void Visit(const OpenACCClause* C) {} + void Visit(const clang::OMPClause* C) {} + void Visit(const clang::BlockDecl::Capture& C); + void Visit(const clang::GenericSelectionExpr::ConstAssociation& A); + void Visit(const clang::concepts::Requirement* R); + void Visit(const clang::APValue& Value, clang::QualType Ty); + void Visit(const clang::ConceptReference*); + + void VisitAliasAttr(const clang::AliasAttr* AA); + void VisitCleanupAttr(const clang::CleanupAttr* CA); + void VisitDeprecatedAttr(const clang::DeprecatedAttr* DA); + void VisitUnavailableAttr(const clang::UnavailableAttr* UA); + void VisitSectionAttr(const clang::SectionAttr* SA); + void VisitVisibilityAttr(const clang::VisibilityAttr* VA); + void VisitTLSModelAttr(const clang::TLSModelAttr* TA); + + void VisitTypedefType(const clang::TypedefType* TT); + void VisitUsingType(const clang::UsingType* TT); + void VisitFunctionType(const clang::FunctionType* T); + void VisitFunctionProtoType(const clang::FunctionProtoType* T); + void VisitRValueReferenceType(const clang::ReferenceType* RT); + void VisitArrayType(const clang::ArrayType* AT); + void VisitConstantArrayType(const clang::ConstantArrayType* CAT); + void VisitDependentSizedExtVectorType(const clang::DependentSizedExtVectorType* VT); + void VisitVectorType(const clang::VectorType* VT); + void VisitUnresolvedUsingType(const clang::UnresolvedUsingType* UUT); + void VisitUnaryTransformType(const clang::UnaryTransformType* UTT); + void VisitTagType(const clang::TagType* TT); + void VisitTemplateTypeParmType(const clang::TemplateTypeParmType* TTPT); + void VisitSubstTemplateTypeParmType(const clang::SubstTemplateTypeParmType* STTPT); + void VisitSubstTemplateTypeParmPackType(const clang::SubstTemplateTypeParmPackType* T); + void VisitAutoType(const clang::AutoType* AT); + void VisitTemplateSpecializationType(const clang::TemplateSpecializationType* TST); + void VisitInjectedClassNameType(const clang::InjectedClassNameType* ICNT); + void VisitObjCInterfaceType(const clang::ObjCInterfaceType* OIT); + void VisitPackExpansionType(const clang::PackExpansionType* PET); + void VisitElaboratedType(const clang::ElaboratedType* ET); + void VisitMacroQualifiedType(const clang::MacroQualifiedType* MQT); + void VisitMemberPointerType(const clang::MemberPointerType* MPT); + + AST::Declaration* VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); + AST::Declaration* VisitNamedDecl(const clang::NamedDecl* ND); + void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); + AST::Declaration* VisitTypedefDecl(const clang::TypedefDecl* TD); + AST::Declaration* VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); + AST::Declaration* VisitNamespaceDecl(const clang::NamespaceDecl* ND); + AST::Declaration* VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); + AST::Declaration* VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); + AST::Declaration* VisitUsingDecl(const clang::UsingDecl* UD); + AST::Declaration* VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); + AST::Declaration* VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); + AST::Declaration* VisitVarDecl(const clang::VarDecl* VD); + AST::Declaration* VisitFieldDecl(const clang::FieldDecl* FD); + AST::Declaration* VisitFunctionDecl(const clang::FunctionDecl* FD); + AST::Declaration* VisitEnumDecl(const clang::EnumDecl* ED); + AST::Declaration* VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); + AST::Declaration* VisitRecordDecl(const clang::RecordDecl* RD); + AST::Declaration* VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); + AST::Declaration* VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); + AST::Declaration* VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); + AST::Declaration* VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); + AST::Declaration* VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); + AST::Declaration* VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); + AST::Declaration* VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); + AST::Declaration* VisitFriendDecl(const clang::FriendDecl* FD); + + AST::Declaration* VisitObjCIvarDecl(const clang::ObjCIvarDecl* D); + AST::Declaration* VisitObjCMethodDecl(const clang::ObjCMethodDecl* D); + AST::Declaration* VisitObjCTypeParamDecl(const clang::ObjCTypeParamDecl* D); + AST::Declaration* VisitObjCCategoryDecl(const clang::ObjCCategoryDecl* D); + AST::Declaration* VisitObjCCategoryImplDecl(const clang::ObjCCategoryImplDecl* D); + AST::Declaration* VisitObjCProtocolDecl(const clang::ObjCProtocolDecl* D); + AST::Declaration* VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl* D); + AST::Declaration* VisitObjCImplementationDecl(const clang::ObjCImplementationDecl* D); + AST::Declaration* VisitObjCCompatibleAliasDecl(const clang::ObjCCompatibleAliasDecl* D); + AST::Declaration* VisitObjCPropertyDecl(const clang::ObjCPropertyDecl* D); + AST::Declaration* VisitObjCPropertyImplDecl(const clang::ObjCPropertyImplDecl* D); + AST::Declaration* VisitBlockDecl(const clang::BlockDecl* D); + + /*#define DECL(CLASS, BASE) \ + void Convert##CLASS##DeclImpl(const clang::CLASS##Decl* Src, AST::CLASS##Decl& Dst); \ + void Convert##CLASS##Decl(const clang::CLASS##Decl* Src, AST::CLASS##Decl& Dst) \ + { \ + Convert##BASE##Decl(Src, Dst); \ + Convert##CLASS##DeclImpl(Src, Dst); \ } - - template - void writePreviousDeclImpl(const clang::Redeclarable* D) - { - const T* Prev = D->getPreviousDecl(); - if (Prev) - JOS.attribute("previousDecl", createPointerRepresentation(Prev)); + #include "clang/AST/DeclNodes.inc" + + // Declare Visit*() for all concrete Decl classes. + #define ABSTRACT_DECL(DECL) + #define DECL(CLASS, BASE) \ + void Visit##CLASS##Decl(const CLASS##Decl* D) \ + { \ + if (declMap.find(D) != declMap.end()) \ + return; \ + \ + auto res = declMap.emplace(D, new AST::CLASS##Decl()); \ + Convert##CLASS##Decl(D, res.first->second); \ } + #include "clang/AST/DeclNodes.inc" + // The above header #undefs ABSTRACT_DECL and DECL upon exit.*/ + +#define STMT(CLASS, BASE) \ + void Convert##CLASS##Impl(const clang::CLASS* Src, AST::CLASS& Dst); \ + void Convert##CLASS(const clang::CLASS* Src, AST::CLASS& Dst) \ + { \ + Convert##BASE(Src, Dst); \ + Convert##CLASS##Impl(Src, Dst); \ + } +#include "StmtNodes.inc" + +// Declare Visit*() for all concrete Stmt classes. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, BASE) \ + void Visit##CLASS(const clang::CLASS* S) \ + { \ + if (stmtMap.find(D) != stmtMap.end()) \ + return; \ + \ + auto res = stmtMap.emplace(S, new AST::CLASS()); \ + Convert##CLASS(S, res.first->second); \ + } +#include "StmtNodes.inc" + // The above header #undefs ABSTRACT_STMT and STMT upon exit. + + void VisitNullTemplateArgument(const clang::TemplateArgument& TA); + void VisitTypeTemplateArgument(const clang::TemplateArgument& TA); + void VisitDeclarationTemplateArgument(const clang::TemplateArgument& TA); + void VisitNullPtrTemplateArgument(const clang::TemplateArgument& TA); + void VisitIntegralTemplateArgument(const clang::TemplateArgument& TA); + void VisitTemplateTemplateArgument(const clang::TemplateArgument& TA); + void VisitTemplateExpansionTemplateArgument(const clang::TemplateArgument& TA); + void VisitExpressionTemplateArgument(const clang::TemplateArgument& TA); + void VisitPackTemplateArgument(const clang::TemplateArgument& TA); + + void visitTextComment(const clang::comments::TextComment* C, const clang::comments::FullComment*); + void visitInlineCommandComment(const clang::comments::InlineCommandComment* C, const clang::comments::FullComment*); + void visitHTMLStartTagComment(const clang::comments::HTMLStartTagComment* C, const clang::comments::FullComment*); + void visitHTMLEndTagComment(const clang::comments::HTMLEndTagComment* C, const clang::comments::FullComment*); + void visitBlockCommandComment(const clang::comments::BlockCommandComment* C, const clang::comments::FullComment*); + void visitParamCommandComment(const clang::comments::ParamCommandComment* C, const clang::comments::FullComment* FC); + void visitTParamCommandComment(const clang::comments::TParamCommandComment* C, const clang::comments::FullComment* FC); + void visitVerbatimBlockComment(const clang::comments::VerbatimBlockComment* C, const clang::comments::FullComment*); + void visitVerbatimBlockLineComment(const clang::comments::VerbatimBlockLineComment* C, const clang::comments::FullComment*); + void visitVerbatimLineComment(const clang::comments::VerbatimLineComment* C, const clang::comments::FullComment*); + +private: + void attributeOnlyIfTrue(llvm::StringRef Key, bool Value) + { + if (Value) + JOS.attribute(Key, Value); + } + + void writeIncludeStack(clang::PresumedLoc Loc, bool JustFirst = false); + + // Writes the attributes of a SourceLocation object without. + void writeBareSourceLocation(clang::SourceLocation Loc, bool IsSpelling, bool addFileInfo); + + // Writes the attributes of a SourceLocation to JSON based on its presumed + // spelling location. If the given location represents a macro invocation, + // this outputs two sub-objects: one for the spelling and one for the + // expansion location. + void writeSourceLocation(clang::SourceLocation Loc, bool addFileInfo = true); + void writeSourceRange(clang::SourceRange R); + std::string createPointerRepresentation(const void* Ptr); + llvm::json::Object createQualType(clang::QualType QT, bool Desugar = true); + AST::QualifiedType CreateQualifiedType(clang::QualType QT, bool Desugar = true); + llvm::json::Object createBareDeclRef(const clang::Decl* D); + llvm::json::Object createFPOptions(clang::FPOptionsOverride FPO); + void writeBareDeclRef(const clang::Decl* D); + llvm::json::Object createCXXRecordDefinitionData(const clang::CXXRecordDecl* RD); + llvm::json::Object createCXXBaseSpecifier(const clang::CXXBaseSpecifier& BS); + std::string createAccessSpecifier(clang::AccessSpecifier AS); + llvm::json::Array createCastPath(const clang::CastExpr* C); + + void writePreviousDeclImpl(...) {} + + template + void writePreviousDeclImpl(const clang::Mergeable* D) + { + const T* First = D->getFirstDecl(); + if (First != D) + JOS.attribute("firstRedecl", createPointerRepresentation(First)); + } + + template + void writePreviousDeclImpl(const clang::Redeclarable* D) + { + const T* Prev = D->getPreviousDecl(); + if (Prev) + JOS.attribute("previousDecl", createPointerRepresentation(Prev)); + } - [[nodiscard]] std::string GetMangledName(const clang::NamedDecl& ND) const; - void ConvertNamedRecord(AST::Declaration& dst, const clang::NamedDecl& src) const; + [[nodiscard]] std::string GetMangledName(const clang::NamedDecl& ND) const; + void ConvertNamedRecord(AST::Declaration& dst, const clang::NamedDecl& src) const; - void addPreviousDeclaration(const clang::Decl* D); + void addPreviousDeclaration(const clang::Decl* D); - llvm::StringRef getCommentCommandName(unsigned CommandID) const; + llvm::StringRef getCommentCommandName(unsigned CommandID) const; - template - AST::Declaration* FindOrInsertLazy(const clang::Decl* D, Fn&& inserter) - { - if (auto it = declMap.find(D); it != declMap.end()) - return it->second; + template + AST::Declaration* FindOrInsertLazy(const clang::Decl* D, Fn&& inserter) + { + if (auto it = declMap.find(D); it != declMap.end()) + return it->second; - auto res = declMap.emplace(D, std::invoke(inserter)); - return res.first->second; - } + auto res = declMap.emplace(D, std::invoke(inserter)); + return res.first->second; + } - std::unordered_map declMap; - std::unordered_set typeMap; - std::unordered_set stmtMap; - - Parser& parser; - const clang::SourceManager& SM; - clang::ASTContext& Ctx; - ASTNameMangler NameMangler; // TODO: Remove this, or the parser one - clang::PrintingPolicy PrintPolicy; - const clang::comments::CommandTraits& Traits; - llvm::StringRef LastLocFilename, LastLocPresumedFilename; - unsigned LastLocLine, LastLocPresumedLine; - }; - - class ASTNodeDumper : public clang::ASTNodeTraverser + std::unordered_map declMap; + std::unordered_set typeMap; + std::unordered_set stmtMap; + + Parser& parser; + const clang::SourceManager& SM; + clang::ASTContext& Ctx; + ASTNameMangler NameMangler; // TODO: Remove this, or the parser one + clang::PrintingPolicy PrintPolicy; + const clang::comments::CommandTraits& Traits; + llvm::StringRef LastLocFilename, LastLocPresumedFilename; + unsigned LastLocLine, LastLocPresumedLine; +}; + +class ASTNodeDumper : public clang::ASTNodeTraverser +{ +public: + ASTNodeDumper(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) + : NodeVisitor(OS, Ctx, parser) { - public: - ASTNodeDumper(llvm::raw_ostream& OS, clang::ASTContext& Ctx, Parser& parser) - : NodeVisitor(OS, Ctx, parser) - { - setDeserialize(true); - } + setDeserialize(true); + } - ASTNodeVisitor& doGetNodeDelegate() { return NodeVisitor; } + ASTNodeVisitor& doGetNodeDelegate() { return NodeVisitor; } - void VisitFunctionTemplateDecl(const clang::FunctionTemplateDecl* FTD) - { - writeTemplateDecl(FTD, true); - } - void VisitClassTemplateDecl(const clang::ClassTemplateDecl* CTD) - { - writeTemplateDecl(CTD, false); - } - void VisitVarTemplateDecl(const clang::VarTemplateDecl* VTD) - { - writeTemplateDecl(VTD, false); - } + void VisitFunctionTemplateDecl(const clang::FunctionTemplateDecl* FTD) + { + writeTemplateDecl(FTD, true); + } + void VisitClassTemplateDecl(const clang::ClassTemplateDecl* CTD) + { + writeTemplateDecl(CTD, false); + } + void VisitVarTemplateDecl(const clang::VarTemplateDecl* VTD) + { + writeTemplateDecl(VTD, false); + } - private: - template - void writeTemplateDeclSpecialization(const SpecializationDecl* SD, bool DumpExplicitInst, bool DumpRefOnly) +private: + template + void writeTemplateDeclSpecialization(const SpecializationDecl* SD, bool DumpExplicitInst, bool DumpRefOnly) + { + bool DumpedAny = false; + for (const auto* RedeclWithBadType : SD->redecls()) { - bool DumpedAny = false; - for (const auto* RedeclWithBadType : SD->redecls()) + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + const auto* Redecl = clang::dyn_cast(RedeclWithBadType); + if (!Redecl) { - // FIXME: The redecls() range sometimes has elements of a less-specific - // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives - // us TagDecls, and should give CXXRecordDecls). - const auto* Redecl = clang::dyn_cast(RedeclWithBadType); - if (!Redecl) - { - // Found the injected-class-name for a class template. This will be - // dumped as part of its surrounding class so we don't need to dump it - // here. - assert(clang::isa(RedeclWithBadType) && - "expected an injected-class-name"); - continue; - } - - switch (Redecl->getTemplateSpecializationKind()) - { - case clang::TSK_ExplicitInstantiationDeclaration: - case clang::TSK_ExplicitInstantiationDefinition: - if (!DumpExplicitInst) - break; - [[fallthrough]]; - case clang::TSK_Undeclared: - case clang::TSK_ImplicitInstantiation: - if (DumpRefOnly) - NodeVisitor.AddChild([=] - { - NodeVisitor.writeBareDeclRef(Redecl); - }); - else - Visit(Redecl); - DumpedAny = true; - break; - case clang::TSK_ExplicitSpecialization: - break; - } + // Found the injected-class-name for a class template. This will be + // dumped as part of its surrounding class so we don't need to dump it + // here. + assert(clang::isa(RedeclWithBadType) && + "expected an injected-class-name"); + continue; } - // Ensure we dump at least one decl for each specialization. - if (!DumpedAny) - NodeVisitor.AddChild([=] - { - NodeVisitor.writeBareDeclRef(SD); - }); + switch (Redecl->getTemplateSpecializationKind()) + { + case clang::TSK_ExplicitInstantiationDeclaration: + case clang::TSK_ExplicitInstantiationDefinition: + if (!DumpExplicitInst) + break; + [[fallthrough]]; + case clang::TSK_Undeclared: + case clang::TSK_ImplicitInstantiation: + if (DumpRefOnly) + NodeVisitor.AddChild([=] + { + NodeVisitor.writeBareDeclRef(Redecl); + }); + else + Visit(Redecl); + DumpedAny = true; + break; + case clang::TSK_ExplicitSpecialization: + break; + } } - template - void writeTemplateDecl(const TemplateDecl* TD, bool DumpExplicitInst) - { - // FIXME: it would be nice to dump template parameters and specializations - // to their own named arrays rather than shoving them into the "inner" - // array. However, template declarations are currently being handled at the - // wrong "level" of the traversal hierarchy and so it is difficult to - // achieve without losing information elsewhere. + // Ensure we dump at least one decl for each specialization. + if (!DumpedAny) + NodeVisitor.AddChild([=] + { + NodeVisitor.writeBareDeclRef(SD); + }); + } - dumpTemplateParameters(TD->getTemplateParameters()); + template + void writeTemplateDecl(const TemplateDecl* TD, bool DumpExplicitInst) + { + // FIXME: it would be nice to dump template parameters and specializations + // to their own named arrays rather than shoving them into the "inner" + // array. However, template declarations are currently being handled at the + // wrong "level" of the traversal hierarchy and so it is difficult to + // achieve without losing information elsewhere. - Visit(TD->getTemplatedDecl()); + dumpTemplateParameters(TD->getTemplateParameters()); - for (const auto* Child : TD->specializations()) - writeTemplateDeclSpecialization(Child, DumpExplicitInst, !TD->isCanonicalDecl()); - } + Visit(TD->getTemplatedDecl()); - ASTNodeVisitor NodeVisitor; - }; + for (const auto* Child : TD->specializations()) + writeTemplateDeclSpecialization(Child, DumpExplicitInst, !TD->isCanonicalDecl()); + } - class ASTParser : public clang::RecursiveASTVisitor - { - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldWalkTypesOfTypeLocs() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - bool shouldVisitLambdaBody() const { return true; } - bool shouldTraversePostOrder() const { return true; } - - void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); - - bool VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); - bool VisitNamedDecl(const clang::NamedDecl* ND); - bool VisitTypedefDecl(const clang::TypedefDecl* TD); - bool VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); - bool VisitNamespaceDecl(const clang::NamespaceDecl* ND); - bool VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); - bool VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); - bool VisitUsingDecl(const clang::UsingDecl* UD); - bool VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); - bool VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); - bool VisitVarDecl(const clang::VarDecl* VD); - bool VisitFieldDecl(const clang::FieldDecl* FD); - bool VisitFunctionDecl(const clang::FunctionDecl* FD); - bool VisitEnumDecl(const clang::EnumDecl* ED); - bool VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); - bool VisitRecordDecl(const clang::RecordDecl* RD); - bool VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); - bool VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); - bool VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); - bool VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); - bool VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); - bool VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); - bool VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); - bool VisitFriendDecl(const clang::FriendDecl* FD); - }; + ASTNodeVisitor NodeVisitor; +}; + +class ASTParser : public clang::RecursiveASTVisitor +{ + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldWalkTypesOfTypeLocs() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + bool shouldVisitLambdaBody() const { return true; } + bool shouldTraversePostOrder() const { return true; } + + /*void HandleNamedDecl(AST::Declaration& AST_ND, const clang::NamedDecl* ND); + + bool VisitTranslationUnitDecl(const clang::TranslationUnitDecl* D); + bool VisitNamedDecl(const clang::NamedDecl* ND); + bool VisitTypedefDecl(const clang::TypedefDecl* TD); + bool VisitTypeAliasDecl(const clang::TypeAliasDecl* TAD); + bool VisitNamespaceDecl(const clang::NamespaceDecl* ND); + bool VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl* UDD); + bool VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl* NAD); + bool VisitUsingDecl(const clang::UsingDecl* UD); + bool VisitUsingEnumDecl(const clang::UsingEnumDecl* UED); + bool VisitUsingShadowDecl(const clang::UsingShadowDecl* USD); + bool VisitVarDecl(const clang::VarDecl* VD); + bool VisitFieldDecl(const clang::FieldDecl* FD); + bool VisitFunctionDecl(const clang::FunctionDecl* FD); + bool VisitEnumDecl(const clang::EnumDecl* ED); + bool VisitEnumConstantDecl(const clang::EnumConstantDecl* ECD); + bool VisitRecordDecl(const clang::RecordDecl* RD); + bool VisitCXXRecordDecl(const clang::CXXRecordDecl* RD); + bool VisitHLSLBufferDecl(const clang::HLSLBufferDecl* D); + bool VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl* D); + bool VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl* D); + bool VisitTemplateTemplateParmDecl(const clang::TemplateTemplateParmDecl* D); + bool VisitLinkageSpecDecl(const clang::LinkageSpecDecl* LSD); + bool VisitAccessSpecDecl(const clang::AccessSpecDecl* ASD); + bool VisitFriendDecl(const clang::FriendDecl* FD);*/ +}; } // namespace CppSharp::CppParser \ No newline at end of file diff --git a/src/CppParser/StmtNodes.inc b/src/CppParser/StmtNodes.inc new file mode 100644 index 0000000000..db3d08ba30 --- /dev/null +++ b/src/CppParser/StmtNodes.inc @@ -0,0 +1,935 @@ +/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ +|* *| +|* List of AST nodes of a particular kind *| +|* *| +|* Automatically generated file, do not edit! *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef ABSTRACT_STMT +# define ABSTRACT_STMT(Type) Type +#endif +#ifndef STMT_RANGE +# define STMT_RANGE(Base, First, Last) +#endif + +#ifndef LAST_STMT_RANGE +# define LAST_STMT_RANGE(Base, First, Last) STMT_RANGE(Base, First, Last) +#endif + +#ifndef ASMSTMT +# define ASMSTMT(Type, Base) STMT(Type, Base) +#endif +ABSTRACT_STMT(ASMSTMT(AsmStmt, Stmt)) +#ifndef GCCASMSTMT +# define GCCASMSTMT(Type, Base) ASMSTMT(Type, Base) +#endif +GCCASMSTMT(GCCAsmStmt, AsmStmt) +#undef GCCASMSTMT + +#ifndef MSASMSTMT +# define MSASMSTMT(Type, Base) ASMSTMT(Type, Base) +#endif +MSASMSTMT(MSAsmStmt, AsmStmt) +#undef MSASMSTMT + +STMT_RANGE(AsmStmt, GCCAsmStmt, MSAsmStmt) + +#undef ASMSTMT + +#ifndef BREAKSTMT +# define BREAKSTMT(Type, Base) STMT(Type, Base) +#endif +BREAKSTMT(BreakStmt, Stmt) +#undef BREAKSTMT + +#ifndef CXXCATCHSTMT +# define CXXCATCHSTMT(Type, Base) STMT(Type, Base) +#endif +CXXCATCHSTMT(CXXCatchStmt, Stmt) +#undef CXXCATCHSTMT + +#ifndef CXXFORRANGESTMT +# define CXXFORRANGESTMT(Type, Base) STMT(Type, Base) +#endif +CXXFORRANGESTMT(CXXForRangeStmt, Stmt) +#undef CXXFORRANGESTMT + +#ifndef CXXTRYSTMT +# define CXXTRYSTMT(Type, Base) STMT(Type, Base) +#endif +CXXTRYSTMT(CXXTryStmt, Stmt) +#undef CXXTRYSTMT + +#ifndef CAPTUREDSTMT +# define CAPTUREDSTMT(Type, Base) STMT(Type, Base) +#endif +CAPTUREDSTMT(CapturedStmt, Stmt) +#undef CAPTUREDSTMT + +#ifndef COMPOUNDSTMT +# define COMPOUNDSTMT(Type, Base) STMT(Type, Base) +#endif +COMPOUNDSTMT(CompoundStmt, Stmt) +#undef COMPOUNDSTMT + +#ifndef CONTINUESTMT +# define CONTINUESTMT(Type, Base) STMT(Type, Base) +#endif +CONTINUESTMT(ContinueStmt, Stmt) +#undef CONTINUESTMT + +#ifndef CORETURNSTMT +# define CORETURNSTMT(Type, Base) STMT(Type, Base) +#endif +CORETURNSTMT(CoreturnStmt, Stmt) +#undef CORETURNSTMT + +#ifndef COROUTINEBODYSTMT +# define COROUTINEBODYSTMT(Type, Base) STMT(Type, Base) +#endif +COROUTINEBODYSTMT(CoroutineBodyStmt, Stmt) +#undef COROUTINEBODYSTMT + +#ifndef DECLSTMT +# define DECLSTMT(Type, Base) STMT(Type, Base) +#endif +DECLSTMT(DeclStmt, Stmt) +#undef DECLSTMT + +#ifndef DOSTMT +# define DOSTMT(Type, Base) STMT(Type, Base) +#endif +DOSTMT(DoStmt, Stmt) +#undef DOSTMT + +#ifndef FORSTMT +# define FORSTMT(Type, Base) STMT(Type, Base) +#endif +FORSTMT(ForStmt, Stmt) +#undef FORSTMT + +#ifndef GOTOSTMT +# define GOTOSTMT(Type, Base) STMT(Type, Base) +#endif +GOTOSTMT(GotoStmt, Stmt) +#undef GOTOSTMT + +#ifndef IFSTMT +# define IFSTMT(Type, Base) STMT(Type, Base) +#endif +IFSTMT(IfStmt, Stmt) +#undef IFSTMT + +#ifndef INDIRECTGOTOSTMT +# define INDIRECTGOTOSTMT(Type, Base) STMT(Type, Base) +#endif +INDIRECTGOTOSTMT(IndirectGotoStmt, Stmt) +#undef INDIRECTGOTOSTMT + +#ifndef MSDEPENDENTEXISTSSTMT +# define MSDEPENDENTEXISTSSTMT(Type, Base) STMT(Type, Base) +#endif +MSDEPENDENTEXISTSSTMT(MSDependentExistsStmt, Stmt) +#undef MSDEPENDENTEXISTSSTMT + +#ifndef NULLSTMT +# define NULLSTMT(Type, Base) STMT(Type, Base) +#endif +NULLSTMT(NullStmt, Stmt) +#undef NULLSTMT + +// Removed OMP nodes +// Removed OBJC nodes + +#ifndef RETURNSTMT +# define RETURNSTMT(Type, Base) STMT(Type, Base) +#endif +RETURNSTMT(ReturnStmt, Stmt) +#undef RETURNSTMT + +#ifndef SEHEXCEPTSTMT +# define SEHEXCEPTSTMT(Type, Base) STMT(Type, Base) +#endif +SEHEXCEPTSTMT(SEHExceptStmt, Stmt) +#undef SEHEXCEPTSTMT + +#ifndef SEHFINALLYSTMT +# define SEHFINALLYSTMT(Type, Base) STMT(Type, Base) +#endif +SEHFINALLYSTMT(SEHFinallyStmt, Stmt) +#undef SEHFINALLYSTMT + +#ifndef SEHLEAVESTMT +# define SEHLEAVESTMT(Type, Base) STMT(Type, Base) +#endif +SEHLEAVESTMT(SEHLeaveStmt, Stmt) +#undef SEHLEAVESTMT + +#ifndef SEHTRYSTMT +# define SEHTRYSTMT(Type, Base) STMT(Type, Base) +#endif +SEHTRYSTMT(SEHTryStmt, Stmt) +#undef SEHTRYSTMT + +#ifndef SWITCHCASE +# define SWITCHCASE(Type, Base) STMT(Type, Base) +#endif +ABSTRACT_STMT(SWITCHCASE(SwitchCase, Stmt)) +#ifndef CASESTMT +# define CASESTMT(Type, Base) SWITCHCASE(Type, Base) +#endif +CASESTMT(CaseStmt, SwitchCase) +#undef CASESTMT + +#ifndef DEFAULTSTMT +# define DEFAULTSTMT(Type, Base) SWITCHCASE(Type, Base) +#endif +DEFAULTSTMT(DefaultStmt, SwitchCase) +#undef DEFAULTSTMT + +STMT_RANGE(SwitchCase, CaseStmt, DefaultStmt) + +#undef SWITCHCASE + +#ifndef SWITCHSTMT +# define SWITCHSTMT(Type, Base) STMT(Type, Base) +#endif +SWITCHSTMT(SwitchStmt, Stmt) +#undef SWITCHSTMT + +#ifndef VALUESTMT +# define VALUESTMT(Type, Base) STMT(Type, Base) +#endif +ABSTRACT_STMT(VALUESTMT(ValueStmt, Stmt)) +#ifndef ATTRIBUTEDSTMT +# define ATTRIBUTEDSTMT(Type, Base) VALUESTMT(Type, Base) +#endif +ATTRIBUTEDSTMT(AttributedStmt, ValueStmt) +#undef ATTRIBUTEDSTMT + +#ifndef EXPR +# define EXPR(Type, Base) VALUESTMT(Type, Base) +#endif +ABSTRACT_STMT(EXPR(Expr, ValueStmt)) +#ifndef ABSTRACTCONDITIONALOPERATOR +# define ABSTRACTCONDITIONALOPERATOR(Type, Base) EXPR(Type, Base) +#endif +ABSTRACT_STMT(ABSTRACTCONDITIONALOPERATOR(AbstractConditionalOperator, Expr)) +#ifndef BINARYCONDITIONALOPERATOR +# define BINARYCONDITIONALOPERATOR(Type, Base) ABSTRACTCONDITIONALOPERATOR(Type, Base) +#endif +BINARYCONDITIONALOPERATOR(BinaryConditionalOperator, AbstractConditionalOperator) +#undef BINARYCONDITIONALOPERATOR + +#ifndef CONDITIONALOPERATOR +# define CONDITIONALOPERATOR(Type, Base) ABSTRACTCONDITIONALOPERATOR(Type, Base) +#endif +CONDITIONALOPERATOR(ConditionalOperator, AbstractConditionalOperator) +#undef CONDITIONALOPERATOR + +STMT_RANGE(AbstractConditionalOperator, BinaryConditionalOperator, ConditionalOperator) + +#undef ABSTRACTCONDITIONALOPERATOR + +#ifndef ADDRLABELEXPR +# define ADDRLABELEXPR(Type, Base) EXPR(Type, Base) +#endif +ADDRLABELEXPR(AddrLabelExpr, Expr) +#undef ADDRLABELEXPR + +#ifndef ARRAYINITINDEXEXPR +# define ARRAYINITINDEXEXPR(Type, Base) EXPR(Type, Base) +#endif +ARRAYINITINDEXEXPR(ArrayInitIndexExpr, Expr) +#undef ARRAYINITINDEXEXPR + +#ifndef ARRAYINITLOOPEXPR +# define ARRAYINITLOOPEXPR(Type, Base) EXPR(Type, Base) +#endif +ARRAYINITLOOPEXPR(ArrayInitLoopExpr, Expr) +#undef ARRAYINITLOOPEXPR + +#ifndef ARRAYSUBSCRIPTEXPR +# define ARRAYSUBSCRIPTEXPR(Type, Base) EXPR(Type, Base) +#endif +ARRAYSUBSCRIPTEXPR(ArraySubscriptExpr, Expr) +#undef ARRAYSUBSCRIPTEXPR + +#ifndef ARRAYTYPETRAITEXPR +# define ARRAYTYPETRAITEXPR(Type, Base) EXPR(Type, Base) +#endif +ARRAYTYPETRAITEXPR(ArrayTypeTraitExpr, Expr) +#undef ARRAYTYPETRAITEXPR + +#ifndef ASTYPEEXPR +# define ASTYPEEXPR(Type, Base) EXPR(Type, Base) +#endif +ASTYPEEXPR(AsTypeExpr, Expr) +#undef ASTYPEEXPR + +#ifndef ATOMICEXPR +# define ATOMICEXPR(Type, Base) EXPR(Type, Base) +#endif +ATOMICEXPR(AtomicExpr, Expr) +#undef ATOMICEXPR + +#ifndef BINARYOPERATOR +# define BINARYOPERATOR(Type, Base) EXPR(Type, Base) +#endif +BINARYOPERATOR(BinaryOperator, Expr) +#ifndef COMPOUNDASSIGNOPERATOR +# define COMPOUNDASSIGNOPERATOR(Type, Base) BINARYOPERATOR(Type, Base) +#endif +COMPOUNDASSIGNOPERATOR(CompoundAssignOperator, BinaryOperator) +#undef COMPOUNDASSIGNOPERATOR + +STMT_RANGE(BinaryOperator, BinaryOperator, CompoundAssignOperator) + +#undef BINARYOPERATOR + +#ifndef BLOCKEXPR +# define BLOCKEXPR(Type, Base) EXPR(Type, Base) +#endif +BLOCKEXPR(BlockExpr, Expr) +#undef BLOCKEXPR + +#ifndef CXXBINDTEMPORARYEXPR +# define CXXBINDTEMPORARYEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXBINDTEMPORARYEXPR(CXXBindTemporaryExpr, Expr) +#undef CXXBINDTEMPORARYEXPR + +#ifndef CXXBOOLLITERALEXPR +# define CXXBOOLLITERALEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXBOOLLITERALEXPR(CXXBoolLiteralExpr, Expr) +#undef CXXBOOLLITERALEXPR + +#ifndef CXXCONSTRUCTEXPR +# define CXXCONSTRUCTEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXCONSTRUCTEXPR(CXXConstructExpr, Expr) +#ifndef CXXTEMPORARYOBJECTEXPR +# define CXXTEMPORARYOBJECTEXPR(Type, Base) CXXCONSTRUCTEXPR(Type, Base) +#endif +CXXTEMPORARYOBJECTEXPR(CXXTemporaryObjectExpr, CXXConstructExpr) +#undef CXXTEMPORARYOBJECTEXPR + +STMT_RANGE(CXXConstructExpr, CXXConstructExpr, CXXTemporaryObjectExpr) + +#undef CXXCONSTRUCTEXPR + +#ifndef CXXDEFAULTARGEXPR +# define CXXDEFAULTARGEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXDEFAULTARGEXPR(CXXDefaultArgExpr, Expr) +#undef CXXDEFAULTARGEXPR + +#ifndef CXXDEFAULTINITEXPR +# define CXXDEFAULTINITEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXDEFAULTINITEXPR(CXXDefaultInitExpr, Expr) +#undef CXXDEFAULTINITEXPR + +#ifndef CXXDELETEEXPR +# define CXXDELETEEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXDELETEEXPR(CXXDeleteExpr, Expr) +#undef CXXDELETEEXPR + +#ifndef CXXDEPENDENTSCOPEMEMBEREXPR +# define CXXDEPENDENTSCOPEMEMBEREXPR(Type, Base) EXPR(Type, Base) +#endif +CXXDEPENDENTSCOPEMEMBEREXPR(CXXDependentScopeMemberExpr, Expr) +#undef CXXDEPENDENTSCOPEMEMBEREXPR + +#ifndef CXXFOLDEXPR +# define CXXFOLDEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXFOLDEXPR(CXXFoldExpr, Expr) +#undef CXXFOLDEXPR + +#ifndef CXXINHERITEDCTORINITEXPR +# define CXXINHERITEDCTORINITEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXINHERITEDCTORINITEXPR(CXXInheritedCtorInitExpr, Expr) +#undef CXXINHERITEDCTORINITEXPR + +#ifndef CXXNEWEXPR +# define CXXNEWEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXNEWEXPR(CXXNewExpr, Expr) +#undef CXXNEWEXPR + +#ifndef CXXNOEXCEPTEXPR +# define CXXNOEXCEPTEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXNOEXCEPTEXPR(CXXNoexceptExpr, Expr) +#undef CXXNOEXCEPTEXPR + +#ifndef CXXNULLPTRLITERALEXPR +# define CXXNULLPTRLITERALEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXNULLPTRLITERALEXPR(CXXNullPtrLiteralExpr, Expr) +#undef CXXNULLPTRLITERALEXPR + +#ifndef CXXPARENLISTINITEXPR +# define CXXPARENLISTINITEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXPARENLISTINITEXPR(CXXParenListInitExpr, Expr) +#undef CXXPARENLISTINITEXPR + +#ifndef CXXPSEUDODESTRUCTOREXPR +# define CXXPSEUDODESTRUCTOREXPR(Type, Base) EXPR(Type, Base) +#endif +CXXPSEUDODESTRUCTOREXPR(CXXPseudoDestructorExpr, Expr) +#undef CXXPSEUDODESTRUCTOREXPR + +#ifndef CXXREWRITTENBINARYOPERATOR +# define CXXREWRITTENBINARYOPERATOR(Type, Base) EXPR(Type, Base) +#endif +CXXREWRITTENBINARYOPERATOR(CXXRewrittenBinaryOperator, Expr) +#undef CXXREWRITTENBINARYOPERATOR + +#ifndef CXXSCALARVALUEINITEXPR +# define CXXSCALARVALUEINITEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXSCALARVALUEINITEXPR(CXXScalarValueInitExpr, Expr) +#undef CXXSCALARVALUEINITEXPR + +#ifndef CXXSTDINITIALIZERLISTEXPR +# define CXXSTDINITIALIZERLISTEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXSTDINITIALIZERLISTEXPR(CXXStdInitializerListExpr, Expr) +#undef CXXSTDINITIALIZERLISTEXPR + +#ifndef CXXTHISEXPR +# define CXXTHISEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXTHISEXPR(CXXThisExpr, Expr) +#undef CXXTHISEXPR + +#ifndef CXXTHROWEXPR +# define CXXTHROWEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXTHROWEXPR(CXXThrowExpr, Expr) +#undef CXXTHROWEXPR + +#ifndef CXXTYPEIDEXPR +# define CXXTYPEIDEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXTYPEIDEXPR(CXXTypeidExpr, Expr) +#undef CXXTYPEIDEXPR + +#ifndef CXXUNRESOLVEDCONSTRUCTEXPR +# define CXXUNRESOLVEDCONSTRUCTEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXUNRESOLVEDCONSTRUCTEXPR(CXXUnresolvedConstructExpr, Expr) +#undef CXXUNRESOLVEDCONSTRUCTEXPR + +#ifndef CXXUUIDOFEXPR +# define CXXUUIDOFEXPR(Type, Base) EXPR(Type, Base) +#endif +CXXUUIDOFEXPR(CXXUuidofExpr, Expr) +#undef CXXUUIDOFEXPR + +#ifndef CALLEXPR +# define CALLEXPR(Type, Base) EXPR(Type, Base) +#endif +CALLEXPR(CallExpr, Expr) +#ifndef CUDAKERNELCALLEXPR +# define CUDAKERNELCALLEXPR(Type, Base) CALLEXPR(Type, Base) +#endif +CUDAKERNELCALLEXPR(CUDAKernelCallExpr, CallExpr) +#undef CUDAKERNELCALLEXPR + +#ifndef CXXMEMBERCALLEXPR +# define CXXMEMBERCALLEXPR(Type, Base) CALLEXPR(Type, Base) +#endif +CXXMEMBERCALLEXPR(CXXMemberCallExpr, CallExpr) +#undef CXXMEMBERCALLEXPR + +#ifndef CXXOPERATORCALLEXPR +# define CXXOPERATORCALLEXPR(Type, Base) CALLEXPR(Type, Base) +#endif +CXXOPERATORCALLEXPR(CXXOperatorCallExpr, CallExpr) +#undef CXXOPERATORCALLEXPR + +#ifndef USERDEFINEDLITERAL +# define USERDEFINEDLITERAL(Type, Base) CALLEXPR(Type, Base) +#endif +USERDEFINEDLITERAL(UserDefinedLiteral, CallExpr) +#undef USERDEFINEDLITERAL + +STMT_RANGE(CallExpr, CallExpr, UserDefinedLiteral) + +#undef CALLEXPR + +#ifndef CASTEXPR +# define CASTEXPR(Type, Base) EXPR(Type, Base) +#endif +ABSTRACT_STMT(CASTEXPR(CastExpr, Expr)) +#ifndef EXPLICITCASTEXPR +# define EXPLICITCASTEXPR(Type, Base) CASTEXPR(Type, Base) +#endif +ABSTRACT_STMT(EXPLICITCASTEXPR(ExplicitCastExpr, CastExpr)) +#ifndef BUILTINBITCASTEXPR +# define BUILTINBITCASTEXPR(Type, Base) EXPLICITCASTEXPR(Type, Base) +#endif +BUILTINBITCASTEXPR(BuiltinBitCastExpr, ExplicitCastExpr) +#undef BUILTINBITCASTEXPR + +#ifndef CSTYLECASTEXPR +# define CSTYLECASTEXPR(Type, Base) EXPLICITCASTEXPR(Type, Base) +#endif +CSTYLECASTEXPR(CStyleCastExpr, ExplicitCastExpr) +#undef CSTYLECASTEXPR + +#ifndef CXXFUNCTIONALCASTEXPR +# define CXXFUNCTIONALCASTEXPR(Type, Base) EXPLICITCASTEXPR(Type, Base) +#endif +CXXFUNCTIONALCASTEXPR(CXXFunctionalCastExpr, ExplicitCastExpr) +#undef CXXFUNCTIONALCASTEXPR + +#ifndef CXXNAMEDCASTEXPR +# define CXXNAMEDCASTEXPR(Type, Base) EXPLICITCASTEXPR(Type, Base) +#endif +ABSTRACT_STMT(CXXNAMEDCASTEXPR(CXXNamedCastExpr, ExplicitCastExpr)) +#ifndef CXXADDRSPACECASTEXPR +# define CXXADDRSPACECASTEXPR(Type, Base) CXXNAMEDCASTEXPR(Type, Base) +#endif +CXXADDRSPACECASTEXPR(CXXAddrspaceCastExpr, CXXNamedCastExpr) +#undef CXXADDRSPACECASTEXPR + +#ifndef CXXCONSTCASTEXPR +# define CXXCONSTCASTEXPR(Type, Base) CXXNAMEDCASTEXPR(Type, Base) +#endif +CXXCONSTCASTEXPR(CXXConstCastExpr, CXXNamedCastExpr) +#undef CXXCONSTCASTEXPR + +#ifndef CXXDYNAMICCASTEXPR +# define CXXDYNAMICCASTEXPR(Type, Base) CXXNAMEDCASTEXPR(Type, Base) +#endif +CXXDYNAMICCASTEXPR(CXXDynamicCastExpr, CXXNamedCastExpr) +#undef CXXDYNAMICCASTEXPR + +#ifndef CXXREINTERPRETCASTEXPR +# define CXXREINTERPRETCASTEXPR(Type, Base) CXXNAMEDCASTEXPR(Type, Base) +#endif +CXXREINTERPRETCASTEXPR(CXXReinterpretCastExpr, CXXNamedCastExpr) +#undef CXXREINTERPRETCASTEXPR + +#ifndef CXXSTATICCASTEXPR +# define CXXSTATICCASTEXPR(Type, Base) CXXNAMEDCASTEXPR(Type, Base) +#endif +CXXSTATICCASTEXPR(CXXStaticCastExpr, CXXNamedCastExpr) +#undef CXXSTATICCASTEXPR + +STMT_RANGE(CXXNamedCastExpr, CXXAddrspaceCastExpr, CXXStaticCastExpr) + +#undef CXXNAMEDCASTEXPR + +STMT_RANGE(ExplicitCastExpr, BuiltinBitCastExpr, ObjCBridgedCastExpr) + +#undef EXPLICITCASTEXPR + +#ifndef IMPLICITCASTEXPR +# define IMPLICITCASTEXPR(Type, Base) CASTEXPR(Type, Base) +#endif +IMPLICITCASTEXPR(ImplicitCastExpr, CastExpr) +#undef IMPLICITCASTEXPR + +STMT_RANGE(CastExpr, BuiltinBitCastExpr, ImplicitCastExpr) + +#undef CASTEXPR + +#ifndef CHARACTERLITERAL +# define CHARACTERLITERAL(Type, Base) EXPR(Type, Base) +#endif +CHARACTERLITERAL(CharacterLiteral, Expr) +#undef CHARACTERLITERAL + +#ifndef CHOOSEEXPR +# define CHOOSEEXPR(Type, Base) EXPR(Type, Base) +#endif +CHOOSEEXPR(ChooseExpr, Expr) +#undef CHOOSEEXPR + +#ifndef COMPOUNDLITERALEXPR +# define COMPOUNDLITERALEXPR(Type, Base) EXPR(Type, Base) +#endif +COMPOUNDLITERALEXPR(CompoundLiteralExpr, Expr) +#undef COMPOUNDLITERALEXPR + +#ifndef CONCEPTSPECIALIZATIONEXPR +# define CONCEPTSPECIALIZATIONEXPR(Type, Base) EXPR(Type, Base) +#endif +CONCEPTSPECIALIZATIONEXPR(ConceptSpecializationExpr, Expr) +#undef CONCEPTSPECIALIZATIONEXPR + +#ifndef CONVERTVECTOREXPR +# define CONVERTVECTOREXPR(Type, Base) EXPR(Type, Base) +#endif +CONVERTVECTOREXPR(ConvertVectorExpr, Expr) +#undef CONVERTVECTOREXPR + +#ifndef COROUTINESUSPENDEXPR +# define COROUTINESUSPENDEXPR(Type, Base) EXPR(Type, Base) +#endif +ABSTRACT_STMT(COROUTINESUSPENDEXPR(CoroutineSuspendExpr, Expr)) +#ifndef COAWAITEXPR +# define COAWAITEXPR(Type, Base) COROUTINESUSPENDEXPR(Type, Base) +#endif +COAWAITEXPR(CoawaitExpr, CoroutineSuspendExpr) +#undef COAWAITEXPR + +#ifndef COYIELDEXPR +# define COYIELDEXPR(Type, Base) COROUTINESUSPENDEXPR(Type, Base) +#endif +COYIELDEXPR(CoyieldExpr, CoroutineSuspendExpr) +#undef COYIELDEXPR + +STMT_RANGE(CoroutineSuspendExpr, CoawaitExpr, CoyieldExpr) + +#undef COROUTINESUSPENDEXPR + +#ifndef DECLREFEXPR +# define DECLREFEXPR(Type, Base) EXPR(Type, Base) +#endif +DECLREFEXPR(DeclRefExpr, Expr) +#undef DECLREFEXPR + +#ifndef DEPENDENTCOAWAITEXPR +# define DEPENDENTCOAWAITEXPR(Type, Base) EXPR(Type, Base) +#endif +DEPENDENTCOAWAITEXPR(DependentCoawaitExpr, Expr) +#undef DEPENDENTCOAWAITEXPR + +#ifndef DEPENDENTSCOPEDECLREFEXPR +# define DEPENDENTSCOPEDECLREFEXPR(Type, Base) EXPR(Type, Base) +#endif +DEPENDENTSCOPEDECLREFEXPR(DependentScopeDeclRefExpr, Expr) +#undef DEPENDENTSCOPEDECLREFEXPR + +#ifndef DESIGNATEDINITEXPR +# define DESIGNATEDINITEXPR(Type, Base) EXPR(Type, Base) +#endif +DESIGNATEDINITEXPR(DesignatedInitExpr, Expr) +#undef DESIGNATEDINITEXPR + +#ifndef DESIGNATEDINITUPDATEEXPR +# define DESIGNATEDINITUPDATEEXPR(Type, Base) EXPR(Type, Base) +#endif +DESIGNATEDINITUPDATEEXPR(DesignatedInitUpdateExpr, Expr) +#undef DESIGNATEDINITUPDATEEXPR + +#ifndef EXPRESSIONTRAITEXPR +# define EXPRESSIONTRAITEXPR(Type, Base) EXPR(Type, Base) +#endif +EXPRESSIONTRAITEXPR(ExpressionTraitExpr, Expr) +#undef EXPRESSIONTRAITEXPR + +#ifndef EXTVECTORELEMENTEXPR +# define EXTVECTORELEMENTEXPR(Type, Base) EXPR(Type, Base) +#endif +EXTVECTORELEMENTEXPR(ExtVectorElementExpr, Expr) +#undef EXTVECTORELEMENTEXPR + +#ifndef FIXEDPOINTLITERAL +# define FIXEDPOINTLITERAL(Type, Base) EXPR(Type, Base) +#endif +FIXEDPOINTLITERAL(FixedPointLiteral, Expr) +#undef FIXEDPOINTLITERAL + +#ifndef FLOATINGLITERAL +# define FLOATINGLITERAL(Type, Base) EXPR(Type, Base) +#endif +FLOATINGLITERAL(FloatingLiteral, Expr) +#undef FLOATINGLITERAL + +#ifndef FULLEXPR +# define FULLEXPR(Type, Base) EXPR(Type, Base) +#endif +ABSTRACT_STMT(FULLEXPR(FullExpr, Expr)) +#ifndef CONSTANTEXPR +# define CONSTANTEXPR(Type, Base) FULLEXPR(Type, Base) +#endif +CONSTANTEXPR(ConstantExpr, FullExpr) +#undef CONSTANTEXPR + +#ifndef EXPRWITHCLEANUPS +# define EXPRWITHCLEANUPS(Type, Base) FULLEXPR(Type, Base) +#endif +EXPRWITHCLEANUPS(ExprWithCleanups, FullExpr) +#undef EXPRWITHCLEANUPS + +STMT_RANGE(FullExpr, ConstantExpr, ExprWithCleanups) + +#undef FULLEXPR + +#ifndef FUNCTIONPARMPACKEXPR +# define FUNCTIONPARMPACKEXPR(Type, Base) EXPR(Type, Base) +#endif +FUNCTIONPARMPACKEXPR(FunctionParmPackExpr, Expr) +#undef FUNCTIONPARMPACKEXPR + +#ifndef GNUNULLEXPR +# define GNUNULLEXPR(Type, Base) EXPR(Type, Base) +#endif +GNUNULLEXPR(GNUNullExpr, Expr) +#undef GNUNULLEXPR + +#ifndef GENERICSELECTIONEXPR +# define GENERICSELECTIONEXPR(Type, Base) EXPR(Type, Base) +#endif +GENERICSELECTIONEXPR(GenericSelectionExpr, Expr) +#undef GENERICSELECTIONEXPR + +#ifndef IMAGINARYLITERAL +# define IMAGINARYLITERAL(Type, Base) EXPR(Type, Base) +#endif +IMAGINARYLITERAL(ImaginaryLiteral, Expr) +#undef IMAGINARYLITERAL + +#ifndef IMPLICITVALUEINITEXPR +# define IMPLICITVALUEINITEXPR(Type, Base) EXPR(Type, Base) +#endif +IMPLICITVALUEINITEXPR(ImplicitValueInitExpr, Expr) +#undef IMPLICITVALUEINITEXPR + +#ifndef INITLISTEXPR +# define INITLISTEXPR(Type, Base) EXPR(Type, Base) +#endif +INITLISTEXPR(InitListExpr, Expr) +#undef INITLISTEXPR + +#ifndef INTEGERLITERAL +# define INTEGERLITERAL(Type, Base) EXPR(Type, Base) +#endif +INTEGERLITERAL(IntegerLiteral, Expr) +#undef INTEGERLITERAL + +#ifndef LAMBDAEXPR +# define LAMBDAEXPR(Type, Base) EXPR(Type, Base) +#endif +LAMBDAEXPR(LambdaExpr, Expr) +#undef LAMBDAEXPR + +#ifndef MSPROPERTYREFEXPR +# define MSPROPERTYREFEXPR(Type, Base) EXPR(Type, Base) +#endif +MSPROPERTYREFEXPR(MSPropertyRefExpr, Expr) +#undef MSPROPERTYREFEXPR + +#ifndef MSPROPERTYSUBSCRIPTEXPR +# define MSPROPERTYSUBSCRIPTEXPR(Type, Base) EXPR(Type, Base) +#endif +MSPROPERTYSUBSCRIPTEXPR(MSPropertySubscriptExpr, Expr) +#undef MSPROPERTYSUBSCRIPTEXPR + +#ifndef MATERIALIZETEMPORARYEXPR +# define MATERIALIZETEMPORARYEXPR(Type, Base) EXPR(Type, Base) +#endif +MATERIALIZETEMPORARYEXPR(MaterializeTemporaryExpr, Expr) +#undef MATERIALIZETEMPORARYEXPR + +#ifndef MATRIXSUBSCRIPTEXPR +# define MATRIXSUBSCRIPTEXPR(Type, Base) EXPR(Type, Base) +#endif +MATRIXSUBSCRIPTEXPR(MatrixSubscriptExpr, Expr) +#undef MATRIXSUBSCRIPTEXPR + +#ifndef MEMBEREXPR +# define MEMBEREXPR(Type, Base) EXPR(Type, Base) +#endif +MEMBEREXPR(MemberExpr, Expr) +#undef MEMBEREXPR + +#ifndef NOINITEXPR +# define NOINITEXPR(Type, Base) EXPR(Type, Base) +#endif +NOINITEXPR(NoInitExpr, Expr) +#undef NOINITEXPR + +// Removed OMP nodes +// Removed OBJC nodes + +#ifndef OFFSETOFEXPR +# define OFFSETOFEXPR(Type, Base) EXPR(Type, Base) +#endif +OFFSETOFEXPR(OffsetOfExpr, Expr) +#undef OFFSETOFEXPR + +#ifndef OPAQUEVALUEEXPR +# define OPAQUEVALUEEXPR(Type, Base) EXPR(Type, Base) +#endif +OPAQUEVALUEEXPR(OpaqueValueExpr, Expr) +#undef OPAQUEVALUEEXPR + +#ifndef OVERLOADEXPR +# define OVERLOADEXPR(Type, Base) EXPR(Type, Base) +#endif +ABSTRACT_STMT(OVERLOADEXPR(OverloadExpr, Expr)) +#ifndef UNRESOLVEDLOOKUPEXPR +# define UNRESOLVEDLOOKUPEXPR(Type, Base) OVERLOADEXPR(Type, Base) +#endif +UNRESOLVEDLOOKUPEXPR(UnresolvedLookupExpr, OverloadExpr) +#undef UNRESOLVEDLOOKUPEXPR + +#ifndef UNRESOLVEDMEMBEREXPR +# define UNRESOLVEDMEMBEREXPR(Type, Base) OVERLOADEXPR(Type, Base) +#endif +UNRESOLVEDMEMBEREXPR(UnresolvedMemberExpr, OverloadExpr) +#undef UNRESOLVEDMEMBEREXPR + +STMT_RANGE(OverloadExpr, UnresolvedLookupExpr, UnresolvedMemberExpr) + +#undef OVERLOADEXPR + +#ifndef PACKEXPANSIONEXPR +# define PACKEXPANSIONEXPR(Type, Base) EXPR(Type, Base) +#endif +PACKEXPANSIONEXPR(PackExpansionExpr, Expr) +#undef PACKEXPANSIONEXPR + +#ifndef PARENEXPR +# define PARENEXPR(Type, Base) EXPR(Type, Base) +#endif +PARENEXPR(ParenExpr, Expr) +#undef PARENEXPR + +#ifndef PARENLISTEXPR +# define PARENLISTEXPR(Type, Base) EXPR(Type, Base) +#endif +PARENLISTEXPR(ParenListExpr, Expr) +#undef PARENLISTEXPR + +#ifndef PREDEFINEDEXPR +# define PREDEFINEDEXPR(Type, Base) EXPR(Type, Base) +#endif +PREDEFINEDEXPR(PredefinedExpr, Expr) +#undef PREDEFINEDEXPR + +#ifndef PSEUDOOBJECTEXPR +# define PSEUDOOBJECTEXPR(Type, Base) EXPR(Type, Base) +#endif +PSEUDOOBJECTEXPR(PseudoObjectExpr, Expr) +#undef PSEUDOOBJECTEXPR + +#ifndef RECOVERYEXPR +# define RECOVERYEXPR(Type, Base) EXPR(Type, Base) +#endif +RECOVERYEXPR(RecoveryExpr, Expr) +#undef RECOVERYEXPR + +#ifndef REQUIRESEXPR +# define REQUIRESEXPR(Type, Base) EXPR(Type, Base) +#endif +REQUIRESEXPR(RequiresExpr, Expr) +#undef REQUIRESEXPR + +#ifndef SYCLUNIQUESTABLENAMEEXPR +# define SYCLUNIQUESTABLENAMEEXPR(Type, Base) EXPR(Type, Base) +#endif +SYCLUNIQUESTABLENAMEEXPR(SYCLUniqueStableNameExpr, Expr) +#undef SYCLUNIQUESTABLENAMEEXPR + +#ifndef SHUFFLEVECTOREXPR +# define SHUFFLEVECTOREXPR(Type, Base) EXPR(Type, Base) +#endif +SHUFFLEVECTOREXPR(ShuffleVectorExpr, Expr) +#undef SHUFFLEVECTOREXPR + +#ifndef SIZEOFPACKEXPR +# define SIZEOFPACKEXPR(Type, Base) EXPR(Type, Base) +#endif +SIZEOFPACKEXPR(SizeOfPackExpr, Expr) +#undef SIZEOFPACKEXPR + +#ifndef SOURCELOCEXPR +# define SOURCELOCEXPR(Type, Base) EXPR(Type, Base) +#endif +SOURCELOCEXPR(SourceLocExpr, Expr) +#undef SOURCELOCEXPR + +#ifndef STMTEXPR +# define STMTEXPR(Type, Base) EXPR(Type, Base) +#endif +STMTEXPR(StmtExpr, Expr) +#undef STMTEXPR + +#ifndef STRINGLITERAL +# define STRINGLITERAL(Type, Base) EXPR(Type, Base) +#endif +STRINGLITERAL(StringLiteral, Expr) +#undef STRINGLITERAL + +#ifndef SUBSTNONTYPETEMPLATEPARMEXPR +# define SUBSTNONTYPETEMPLATEPARMEXPR(Type, Base) EXPR(Type, Base) +#endif +SUBSTNONTYPETEMPLATEPARMEXPR(SubstNonTypeTemplateParmExpr, Expr) +#undef SUBSTNONTYPETEMPLATEPARMEXPR + +#ifndef SUBSTNONTYPETEMPLATEPARMPACKEXPR +# define SUBSTNONTYPETEMPLATEPARMPACKEXPR(Type, Base) EXPR(Type, Base) +#endif +SUBSTNONTYPETEMPLATEPARMPACKEXPR(SubstNonTypeTemplateParmPackExpr, Expr) +#undef SUBSTNONTYPETEMPLATEPARMPACKEXPR + +#ifndef TYPETRAITEXPR +# define TYPETRAITEXPR(Type, Base) EXPR(Type, Base) +#endif +TYPETRAITEXPR(TypeTraitExpr, Expr) +#undef TYPETRAITEXPR + +#ifndef TYPOEXPR +# define TYPOEXPR(Type, Base) EXPR(Type, Base) +#endif +TYPOEXPR(TypoExpr, Expr) +#undef TYPOEXPR + +#ifndef UNARYEXPRORTYPETRAITEXPR +# define UNARYEXPRORTYPETRAITEXPR(Type, Base) EXPR(Type, Base) +#endif +UNARYEXPRORTYPETRAITEXPR(UnaryExprOrTypeTraitExpr, Expr) +#undef UNARYEXPRORTYPETRAITEXPR + +#ifndef UNARYOPERATOR +# define UNARYOPERATOR(Type, Base) EXPR(Type, Base) +#endif +UNARYOPERATOR(UnaryOperator, Expr) +#undef UNARYOPERATOR + +#ifndef VAARGEXPR +# define VAARGEXPR(Type, Base) EXPR(Type, Base) +#endif +VAARGEXPR(VAArgExpr, Expr) +#undef VAARGEXPR + +STMT_RANGE(Expr, BinaryConditionalOperator, VAArgExpr) + +#undef EXPR + +#ifndef LABELSTMT +# define LABELSTMT(Type, Base) VALUESTMT(Type, Base) +#endif +LABELSTMT(LabelStmt, ValueStmt) +#undef LABELSTMT + +STMT_RANGE(ValueStmt, AttributedStmt, LabelStmt) + +#undef VALUESTMT + +#ifndef WHILESTMT +# define WHILESTMT(Type, Base) STMT(Type, Base) +#endif +WHILESTMT(WhileStmt, Stmt) +#undef WHILESTMT + +LAST_STMT_RANGE(Stmt, GCCAsmStmt, WhileStmt) + +#undef STMT +#undef STMT_RANGE +#undef LAST_STMT_RANGE +#undef ABSTRACT_STMT From c28a6d7539e9796ef8433fe5fd4336f759bb4469 Mon Sep 17 00:00:00 2001 From: duckdoom5 Date: Mon, 3 Mar 2025 16:07:04 +0100 Subject: [PATCH 3/3] Working Expr/Stmt visitors --- src/CppParser/ASTNodeVisitor.cpp | 382 +++++++++++++++---------------- src/CppParser/ASTNodeVisitor.h | 30 +-- src/CppParser/Parser.cpp | 3 + src/CppParser/StmtNodes.inc | 12 - 4 files changed, 210 insertions(+), 217 deletions(-) diff --git a/src/CppParser/ASTNodeVisitor.cpp b/src/CppParser/ASTNodeVisitor.cpp index e923c51b26..18ffd0f999 100644 --- a/src/CppParser/ASTNodeVisitor.cpp +++ b/src/CppParser/ASTNodeVisitor.cpp @@ -20,6 +20,7 @@ #include "Types.h" #include "Decl.h" #include "Parser.h" +#include "Sources.h" using namespace CppSharp::CppParser; using namespace clang; @@ -66,6 +67,21 @@ AST::TypeQualifiers GetTypeQualifiers(const clang::Qualifiers& quals) ret.isVolatile = quals.hasVolatile(); return ret; } + +CppSharp::CppParser::SourceLocation ConvertSourceLocation(const clang::SourceLocation& loc) +{ + // TODO: Incomplete. Should this include additional data or is it possible to lazy load that? + return { loc.getRawEncoding() }; +} + +CppSharp::CppParser::SourceRange ConvertSourceRange(const clang::SourceRange& range) +{ + return { + ConvertSourceLocation(range.getBegin()), + ConvertSourceLocation(range.getEnd()) + }; +} + } // namespace void ASTNodeVisitor::ConvertNamedRecord(AST::Declaration& dst, const clang::NamedDecl& src) const @@ -159,31 +175,6 @@ void ASTNodeVisitor::Visit(const Stmt* S) if (!S) return; - if (auto it = stmtMap.find(S); it != stmtMap.end()) - return; - stmtMap.emplace(S); - - JOS.attribute("kind", S->getStmtClassName()); - JOS.attributeObject("range", - [S, this] - { - writeSourceRange(S->getSourceRange()); - }); - - if (const auto* E = dyn_cast(S)) - { - JOS.attribute("type", createQualType(E->getType())); - const char* Category = nullptr; - switch (E->getValueKind()) - { - case VK_LValue: Category = "lvalue"; break; - case VK_XValue: Category = "xvalue"; break; - case VK_PRValue: - Category = "prvalue"; - break; - } - JOS.attribute("valueCategory", Category); - } InnerStmtVisitor::Visit(S); } @@ -1353,7 +1344,7 @@ AST::Declaration* ASTNodeVisitor::VisitCXXRecordDecl(const CXXRecordDecl* RD) if (!RC || !Process) return RC; - parser.WalkRecordCXX(RD, RC); + // parser.WalkRecordCXX(RD, RC); return RC; }); } @@ -1623,120 +1614,50 @@ AST::Declaration* ASTNodeVisitor::VisitBlockDecl(const BlockDecl* D) return nullptr; } -void ASTNodeVisitor::VisitAtomicExpr(const AtomicExpr* AE) -{ - // JOS.attribute("name", AE->getOp()); -} - -void ASTNodeVisitor::VisitObjCEncodeExpr(const ObjCEncodeExpr* OEE) -{ - JOS.attribute("encodedType", createQualType(OEE->getEncodedType())); -} - -void ASTNodeVisitor::VisitObjCMessageExpr(const ObjCMessageExpr* OME) -{ - std::string Str; - llvm::raw_string_ostream OS(Str); - - OME->getSelector().print(OS); - JOS.attribute("selector", Str); - - switch (OME->getReceiverKind()) - { - case ObjCMessageExpr::Instance: - JOS.attribute("receiverKind", "instance"); - break; - case ObjCMessageExpr::Class: - JOS.attribute("receiverKind", "class"); - JOS.attribute("classType", createQualType(OME->getClassReceiver())); - break; - case ObjCMessageExpr::SuperInstance: - JOS.attribute("receiverKind", "super (instance)"); - JOS.attribute("superType", createQualType(OME->getSuperType())); - break; - case ObjCMessageExpr::SuperClass: - JOS.attribute("receiverKind", "super (class)"); - JOS.attribute("superType", createQualType(OME->getSuperType())); - break; - } - - QualType CallReturnTy = OME->getCallReturnType(Ctx); - if (OME->getType() != CallReturnTy) - JOS.attribute("callReturnType", createQualType(CallReturnTy)); -} - -void ASTNodeVisitor::VisitObjCBoxedExpr(const ObjCBoxedExpr* OBE) +void ASTNodeVisitor::ConvertExprImpl(const clang::Expr* E, AST::Expr& Dst) { - if (const ObjCMethodDecl* MD = OBE->getBoxingMethod()) - { - std::string Str; - llvm::raw_string_ostream OS(Str); + // TODO: Incomplete + // Dst.type = parser.GetQualifiedType(E->getType()); + // JOS.attribute("type", createQualType(E->getType())); - MD->getSelector().print(OS); - JOS.attribute("selector", Str); - } -} + // TODO: Convert to functions instead of data + Dst.isLValue = E->isLValue(); + Dst.isXValue = E->isXValue(); + Dst.isPRValue = E->isPRValue(); + Dst.isGLValue = E->isGLValue(); -void ASTNodeVisitor::VisitObjCSelectorExpr(const ObjCSelectorExpr* OSE) -{ - std::string Str; - llvm::raw_string_ostream OS(Str); - - OSE->getSelector().print(OS); - JOS.attribute("selector", Str); + Dst.containsErrors = E->containsErrors(); + Dst.containsUnexpandedParameterPack = E->containsUnexpandedParameterPack(); + Dst.exprLoc = ConvertSourceLocation(E->getExprLoc()); + // Dst.hasPlaceholderType = E->hasPlaceholderType(); + Dst.isInstantiationDependent = E->isInstantiationDependent(); + Dst.isOrdinaryOrBitFieldObject = E->isOrdinaryOrBitFieldObject(); + // Dst.isReadIfDiscardedInCPlusPlus11 = E->isGLValue() && E->isReadIfDiscardedInCPlusPlus11(); + Dst.isTypeDependent = E->isTypeDependent(); + Dst.isValueDependent = E->isValueDependent(); + Dst.refersToMatrixElement = E->refersToMatrixElement(); } -void ASTNodeVisitor::VisitObjCProtocolExpr(const ObjCProtocolExpr* OPE) +void ASTNodeVisitor::ConvertStmt(const clang::Stmt* S, AST::Stmt& Dst) { - JOS.attribute("protocol", createBareDeclRef(OPE->getProtocol())); -} + // Dst.stmtClass = S->getStmtClass(); // Already set + Dst.sourceRange = ConvertSourceRange(S->getSourceRange()); -void ASTNodeVisitor::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr* OPRE) -{ - if (OPRE->isImplicitProperty()) - { - JOS.attribute("propertyKind", "implicit"); - if (const ObjCMethodDecl* MD = OPRE->getImplicitPropertyGetter()) - JOS.attribute("getter", createBareDeclRef(MD)); - if (const ObjCMethodDecl* MD = OPRE->getImplicitPropertySetter()) - JOS.attribute("setter", createBareDeclRef(MD)); - } - else - { - JOS.attribute("propertyKind", "explicit"); - JOS.attribute("property", createBareDeclRef(OPRE->getExplicitProperty())); - } - - attributeOnlyIfTrue("isSuperReceiver", OPRE->isSuperReceiver()); - attributeOnlyIfTrue("isMessagingGetter", OPRE->isMessagingGetter()); - attributeOnlyIfTrue("isMessagingSetter", OPRE->isMessagingSetter()); -} - -void ASTNodeVisitor::VisitObjCSubscriptRefExpr( - const ObjCSubscriptRefExpr* OSRE) -{ - JOS.attribute("subscriptKind", - OSRE->isArraySubscriptRefExpr() ? "array" : "dictionary"); - - if (const ObjCMethodDecl* MD = OSRE->getAtIndexMethodDecl()) - JOS.attribute("getter", createBareDeclRef(MD)); - if (const ObjCMethodDecl* MD = OSRE->setAtIndexMethodDecl()) - JOS.attribute("setter", createBareDeclRef(MD)); -} - -void ASTNodeVisitor::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* OIRE) -{ - JOS.attribute("decl", createBareDeclRef(OIRE->getDecl())); - attributeOnlyIfTrue("isFreeIvar", OIRE->isFreeIvar()); - JOS.attribute("isArrow", OIRE->isArrow()); + /*JOS.attribute("kind", S->getStmtClassName()); + JOS.attributeObject("range", + [S, this] + { + writeSourceRange(S->getSourceRange()); + });*/ } -void ASTNodeVisitor::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr* OBLE) +void ASTNodeVisitor::ConvertAtomicExprImpl(const AtomicExpr* Src, AST::AtomicExpr& Dst) { - JOS.attribute("value", OBLE->getValue() ? "__objc_yes" : "__objc_no"); + // TODO: Clang 19 + // JOS.attribute("name", Src->getOp()); } -void ASTNodeVisitor::VisitDeclRefExpr(const DeclRefExpr* DRE) +void ASTNodeVisitor::ConvertDeclRefExprImpl(const DeclRefExpr* DRE, AST::DeclRefExpr& Dst) { JOS.attribute("referencedDecl", createBareDeclRef(DRE->getDecl())); if (DRE->getDecl() != DRE->getFoundDecl()) @@ -1752,19 +1673,18 @@ void ASTNodeVisitor::VisitDeclRefExpr(const DeclRefExpr* DRE) attributeOnlyIfTrue("isImmediateEscalating", DRE->isImmediateEscalating()); } -void ASTNodeVisitor::VisitSYCLUniqueStableNameExpr( - const SYCLUniqueStableNameExpr* E) +void ASTNodeVisitor::ConvertSYCLUniqueStableNameExprImpl(const SYCLUniqueStableNameExpr* E, AST::SYCLUniqueStableNameExpr& Dst) { JOS.attribute("typeSourceInfo", createQualType(E->getTypeSourceInfo()->getType())); } -void ASTNodeVisitor::VisitPredefinedExpr(const PredefinedExpr* PE) +void ASTNodeVisitor::ConvertPredefinedExprImpl(const PredefinedExpr* PE, AST::PredefinedExpr& Dst) { JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind())); } -void ASTNodeVisitor::VisitUnaryOperator(const UnaryOperator* UO) +void ASTNodeVisitor::ConvertUnaryOperatorImpl(const UnaryOperator* UO, AST::UnaryOperator& Dst) { JOS.attribute("isPostfix", UO->isPostfix()); JOS.attribute("opcode", UnaryOperator::getOpcodeStr(UO->getOpcode())); @@ -1772,13 +1692,12 @@ void ASTNodeVisitor::VisitUnaryOperator(const UnaryOperator* UO) JOS.attribute("canOverflow", false); } -void ASTNodeVisitor::VisitBinaryOperator(const BinaryOperator* BO) +void ASTNodeVisitor::ConvertBinaryOperatorImpl(const BinaryOperator* BO, AST::BinaryOperator& Dst) { JOS.attribute("opcode", BinaryOperator::getOpcodeStr(BO->getOpcode())); } -void ASTNodeVisitor::VisitCompoundAssignOperator( - const CompoundAssignOperator* CAO) +void ASTNodeVisitor::ConvertCompoundAssignOperatorImpl(const CompoundAssignOperator* CAO, AST::CompoundAssignOperator& Dst) { VisitBinaryOperator(CAO); JOS.attribute("computeLHSType", createQualType(CAO->getComputationLHSType())); @@ -1786,7 +1705,7 @@ void ASTNodeVisitor::VisitCompoundAssignOperator( createQualType(CAO->getComputationResultType())); } -void ASTNodeVisitor::VisitMemberExpr(const MemberExpr* ME) +void ASTNodeVisitor::ConvertMemberExprImpl(const MemberExpr* ME, AST::MemberExpr& Dst) { // Note, we always write this Boolean field because the information it conveys // is critical to understanding the AST node. @@ -1803,7 +1722,7 @@ void ASTNodeVisitor::VisitMemberExpr(const MemberExpr* ME) } } -void ASTNodeVisitor::VisitCXXNewExpr(const CXXNewExpr* NE) +void ASTNodeVisitor::ConvertCXXNewExprImpl(const CXXNewExpr* NE, AST::CXXNewExpr& Dst) { attributeOnlyIfTrue("isGlobal", NE->isGlobalNew()); attributeOnlyIfTrue("isArray", NE->isArray()); @@ -1824,7 +1743,7 @@ void ASTNodeVisitor::VisitCXXNewExpr(const CXXNewExpr* NE) if (const FunctionDecl* FD = NE->getOperatorDelete()) JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); } -void ASTNodeVisitor::VisitCXXDeleteExpr(const CXXDeleteExpr* DE) +void ASTNodeVisitor::ConvertCXXDeleteExprImpl(const CXXDeleteExpr* DE, AST::CXXDeleteExpr& Dst) { attributeOnlyIfTrue("isGlobal", DE->isGlobalDelete()); attributeOnlyIfTrue("isArray", DE->isArrayForm()); @@ -1833,12 +1752,12 @@ void ASTNodeVisitor::VisitCXXDeleteExpr(const CXXDeleteExpr* DE) JOS.attribute("operatorDeleteDecl", createBareDeclRef(FD)); } -void ASTNodeVisitor::VisitCXXThisExpr(const CXXThisExpr* TE) +void ASTNodeVisitor::ConvertCXXThisExprImpl(const CXXThisExpr* TE, AST::CXXThisExpr& Dst) { attributeOnlyIfTrue("implicit", TE->isImplicit()); } -void ASTNodeVisitor::VisitCastExpr(const CastExpr* CE) +void ASTNodeVisitor::ConvertCastExprImpl(const CastExpr* CE, AST::CastExpr& Dst) { JOS.attribute("castKind", CE->getCastKindName()); llvm::json::Array Path = createCastPath(CE); @@ -1850,32 +1769,30 @@ void ASTNodeVisitor::VisitCastExpr(const CastExpr* CE) JOS.attribute("conversionFunc", createBareDeclRef(ND)); } -void ASTNodeVisitor::VisitImplicitCastExpr(const ImplicitCastExpr* ICE) +void ASTNodeVisitor::ConvertImplicitCastExprImpl(const ImplicitCastExpr* ICE, AST::ImplicitCastExpr& Dst) { VisitCastExpr(ICE); attributeOnlyIfTrue("isPartOfExplicitCast", ICE->isPartOfExplicitCast()); } -void ASTNodeVisitor::VisitCallExpr(const CallExpr* CE) +void ASTNodeVisitor::ConvertCallExprImpl(const CallExpr* CE, AST::CallExpr& Dst) { attributeOnlyIfTrue("adl", CE->usesADL()); } -void ASTNodeVisitor::VisitUnaryExprOrTypeTraitExpr( - const UnaryExprOrTypeTraitExpr* TTE) +void ASTNodeVisitor::ConvertUnaryExprOrTypeTraitExprImpl(const UnaryExprOrTypeTraitExpr* TTE, AST::UnaryExprOrTypeTraitExpr& Dst) { JOS.attribute("name", getTraitSpelling(TTE->getKind())); if (TTE->isArgumentType()) JOS.attribute("argType", createQualType(TTE->getArgumentType())); } -void ASTNodeVisitor::VisitSizeOfPackExpr(const SizeOfPackExpr* SOPE) +void ASTNodeVisitor::ConvertSizeOfPackExprImpl(const SizeOfPackExpr* SOPE, AST::SizeOfPackExpr& Dst) { VisitNamedDecl(SOPE->getPack()); } -void ASTNodeVisitor::VisitUnresolvedLookupExpr( - const UnresolvedLookupExpr* ULE) +void ASTNodeVisitor::ConvertUnresolvedLookupExprImpl(const UnresolvedLookupExpr* ULE, AST::UnresolvedLookupExpr& Dst) { JOS.attribute("usesADL", ULE->requiresADL()); JOS.attribute("name", ULE->getName().getAsString()); @@ -1887,13 +1804,13 @@ void ASTNodeVisitor::VisitUnresolvedLookupExpr( }); } -void ASTNodeVisitor::VisitAddrLabelExpr(const AddrLabelExpr* ALE) +void ASTNodeVisitor::ConvertAddrLabelExprImpl(const AddrLabelExpr* ALE, AST::AddrLabelExpr& Dst) { JOS.attribute("name", ALE->getLabel()->getName()); JOS.attribute("labelDeclId", createPointerRepresentation(ALE->getLabel())); } -void ASTNodeVisitor::VisitCXXTypeidExpr(const CXXTypeidExpr* CTE) +void ASTNodeVisitor::ConvertCXXTypeidExprImpl(const CXXTypeidExpr* CTE, AST::CXXTypeidExpr& Dst) { if (CTE->isTypeOperand()) { @@ -1905,33 +1822,31 @@ void ASTNodeVisitor::VisitCXXTypeidExpr(const CXXTypeidExpr* CTE) } } -void ASTNodeVisitor::VisitConstantExpr(const ConstantExpr* CE) +void ASTNodeVisitor::ConvertConstantExprImpl(const ConstantExpr* CE, AST::ConstantExpr& Dst) { if (CE->getResultAPValueKind() != APValue::None) Visit(CE->getAPValueResult(), CE->getType()); } -void ASTNodeVisitor::VisitInitListExpr(const InitListExpr* ILE) +void ASTNodeVisitor::ConvertInitListExprImpl(const InitListExpr* ILE, AST::InitListExpr& Dst) { if (const FieldDecl* FD = ILE->getInitializedFieldInUnion()) JOS.attribute("field", createBareDeclRef(FD)); } -void ASTNodeVisitor::VisitGenericSelectionExpr( - const GenericSelectionExpr* GSE) +void ASTNodeVisitor::ConvertGenericSelectionExprImpl(const GenericSelectionExpr* GSE, AST::GenericSelectionExpr& Dst) { attributeOnlyIfTrue("resultDependent", GSE->isResultDependent()); } -void ASTNodeVisitor::VisitCXXUnresolvedConstructExpr( - const CXXUnresolvedConstructExpr* UCE) +void ASTNodeVisitor::ConvertCXXUnresolvedConstructExprImpl(const CXXUnresolvedConstructExpr* UCE, AST::CXXUnresolvedConstructExpr& Dst) { if (UCE->getType() != UCE->getTypeAsWritten()) JOS.attribute("typeAsWritten", createQualType(UCE->getTypeAsWritten())); attributeOnlyIfTrue("list", UCE->isListInitialization()); } -void ASTNodeVisitor::VisitCXXConstructExpr(const CXXConstructExpr* CE) +void ASTNodeVisitor::ConvertCXXConstructExprImpl(const CXXConstructExpr* CE, AST::CXXConstructExpr& Dst) { CXXConstructorDecl* Ctor = CE->getConstructor(); JOS.attribute("ctorType", createQualType(Ctor->getType())); @@ -1959,7 +1874,7 @@ void ASTNodeVisitor::VisitCXXConstructExpr(const CXXConstructExpr* CE) } } -void ASTNodeVisitor::VisitExprWithCleanups(const ExprWithCleanups* EWC) +void ASTNodeVisitor::ConvertExprWithCleanupsImpl(const ExprWithCleanups* EWC, AST::ExprWithCleanups& Dst) { attributeOnlyIfTrue("cleanupsHaveSideEffects", EWC->cleanupsHaveSideEffects()); @@ -1987,8 +1902,7 @@ void ASTNodeVisitor::VisitExprWithCleanups(const ExprWithCleanups* EWC) } } -void ASTNodeVisitor::VisitCXXBindTemporaryExpr( - const CXXBindTemporaryExpr* BTE) +void ASTNodeVisitor::ConvertCXXBindTemporaryExprImpl(const CXXBindTemporaryExpr* BTE, AST::CXXBindTemporaryExpr& Dst) { const CXXTemporary* Temp = BTE->getTemporary(); JOS.attribute("temp", createPointerRepresentation(Temp)); @@ -1996,8 +1910,7 @@ void ASTNodeVisitor::VisitCXXBindTemporaryExpr( JOS.attribute("dtor", createBareDeclRef(Dtor)); } -void ASTNodeVisitor::VisitMaterializeTemporaryExpr( - const MaterializeTemporaryExpr* MTE) +void ASTNodeVisitor::ConvertMaterializeTemporaryExprImpl(const MaterializeTemporaryExpr* MTE, AST::MaterializeTemporaryExpr& Dst) { if (const ValueDecl* VD = MTE->getExtendingDecl()) JOS.attribute("extendingDecl", createBareDeclRef(VD)); @@ -2024,18 +1937,17 @@ void ASTNodeVisitor::VisitMaterializeTemporaryExpr( attributeOnlyIfTrue("boundToLValueRef", MTE->isBoundToLvalueReference()); } -void ASTNodeVisitor::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr* Node) +void ASTNodeVisitor::ConvertCXXDefaultArgExprImpl(const CXXDefaultArgExpr* Node, AST::CXXDefaultArgExpr& Dst) { attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); } -void ASTNodeVisitor::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr* Node) +void ASTNodeVisitor::ConvertCXXDefaultInitExprImpl(const CXXDefaultInitExpr* Node, AST::CXXDefaultInitExpr& Dst) { attributeOnlyIfTrue("hasRewrittenInit", Node->hasRewrittenInit()); } -void ASTNodeVisitor::VisitCXXDependentScopeMemberExpr( - const CXXDependentScopeMemberExpr* DSME) +void ASTNodeVisitor::ConvertCXXDependentScopeMemberExprImpl(const CXXDependentScopeMemberExpr* DSME, AST::CXXDependentScopeMemberExpr& Dst) { JOS.attribute("isArrow", DSME->isArrow()); JOS.attribute("member", DSME->getMember().getAsString()); @@ -2057,20 +1969,14 @@ void ASTNodeVisitor::VisitCXXDependentScopeMemberExpr( } } -void ASTNodeVisitor::VisitRequiresExpr(const RequiresExpr* RE) -{ - if (!RE->isValueDependent()) - JOS.attribute("satisfied", RE->isSatisfied()); -} - -void ASTNodeVisitor::VisitIntegerLiteral(const IntegerLiteral* IL) +void ASTNodeVisitor::ConvertIntegerLiteralImpl(const IntegerLiteral* IL, AST::IntegerLiteral& Dst) { llvm::SmallString<16> Buffer; IL->getValue().toString(Buffer, /*Radix=*/10, IL->getType()->isSignedIntegerType()); JOS.attribute("value", Buffer); } -void ASTNodeVisitor::VisitCharacterLiteral(const CharacterLiteral* CL) +void ASTNodeVisitor::ConvertCharacterLiteralImpl(const CharacterLiteral* CL, AST::CharacterLiteral& Dst) { // FIXME: This should probably print the character literal as a string, // rather than as a numerical value. It would be nice if the behavior matched @@ -2078,29 +1984,29 @@ void ASTNodeVisitor::VisitCharacterLiteral(const CharacterLiteral* CL) // the difference between 'a' and L'a' in C from the JSON output. JOS.attribute("value", CL->getValue()); } -void ASTNodeVisitor::VisitFixedPointLiteral(const FixedPointLiteral* FPL) +void ASTNodeVisitor::ConvertFixedPointLiteralImpl(const FixedPointLiteral* FPL, AST::FixedPointLiteral& Dst) { JOS.attribute("value", FPL->getValueAsString(/*Radix=*/10)); } -void ASTNodeVisitor::VisitFloatingLiteral(const FloatingLiteral* FL) +void ASTNodeVisitor::ConvertFloatingLiteralImpl(const FloatingLiteral* FL, AST::FloatingLiteral& Dst) { llvm::SmallString<16> Buffer; FL->getValue().toString(Buffer); JOS.attribute("value", Buffer); } -void ASTNodeVisitor::VisitStringLiteral(const StringLiteral* SL) +void ASTNodeVisitor::ConvertStringLiteralImpl(const StringLiteral* SL, AST::StringLiteral& Dst) { std::string Buffer; llvm::raw_string_ostream SS(Buffer); SL->outputString(SS); JOS.attribute("value", Buffer); } -void ASTNodeVisitor::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr* BLE) +void ASTNodeVisitor::ConvertCXXBoolLiteralExprImpl(const CXXBoolLiteralExpr* BLE, AST::CXXBoolLiteralExpr& Dst) { JOS.attribute("value", BLE->getValue()); } -void ASTNodeVisitor::VisitIfStmt(const IfStmt* IS) +void ASTNodeVisitor::ConvertIfStmtImpl(const IfStmt* IS, AST::IfStmt& Dst) { attributeOnlyIfTrue("hasInit", IS->hasInitStorage()); attributeOnlyIfTrue("hasVar", IS->hasVarStorage()); @@ -2110,40 +2016,134 @@ void ASTNodeVisitor::VisitIfStmt(const IfStmt* IS) attributeOnlyIfTrue("constevalIsNegated", IS->isNegatedConsteval()); } -void ASTNodeVisitor::VisitSwitchStmt(const SwitchStmt* SS) +void ASTNodeVisitor::ConvertSwitchStmtImpl(const SwitchStmt* SS, AST::SwitchStmt& Dst) { attributeOnlyIfTrue("hasInit", SS->hasInitStorage()); attributeOnlyIfTrue("hasVar", SS->hasVarStorage()); } -void ASTNodeVisitor::VisitCaseStmt(const CaseStmt* CS) +void ASTNodeVisitor::ConvertCaseStmtImpl(const CaseStmt* CS, AST::CaseStmt& Dst) { attributeOnlyIfTrue("isGNURange", CS->caseStmtIsGNURange()); } -void ASTNodeVisitor::VisitLabelStmt(const LabelStmt* LS) +void ASTNodeVisitor::ConvertLabelStmtImpl(const LabelStmt* LS, AST::LabelStmt& Dst) { JOS.attribute("name", LS->getName()); JOS.attribute("declId", createPointerRepresentation(LS->getDecl())); attributeOnlyIfTrue("sideEntry", LS->isSideEntry()); } -void ASTNodeVisitor::VisitGotoStmt(const GotoStmt* GS) +void ASTNodeVisitor::ConvertGotoStmtImpl(const GotoStmt* GS, AST::GotoStmt& Dst) { JOS.attribute("targetLabelDeclId", createPointerRepresentation(GS->getLabel())); } -void ASTNodeVisitor::VisitWhileStmt(const WhileStmt* WS) +void ASTNodeVisitor::ConvertWhileStmtImpl(const WhileStmt* WS, AST::WhileStmt& Dst) { attributeOnlyIfTrue("hasVar", WS->hasVarStorage()); } -void ASTNodeVisitor::VisitObjCAtCatchStmt(const ObjCAtCatchStmt* OACS) -{ - // FIXME: it would be nice for the ASTNodeTraverser would handle the catch - // parameter the same way for C++ and ObjC rather. In this case, C++ gets a - // null child node and ObjC gets no child node. - attributeOnlyIfTrue("isCatchAll", OACS->getCatchParamDecl() == nullptr); -} +void ASTNodeVisitor::ConvertAsmStmtImpl(class clang::AsmStmt const*, class CppSharp::CppParser::AST::AsmStmt&) {} +void ASTNodeVisitor::ConvertGCCAsmStmtImpl(class clang::GCCAsmStmt const*, class CppSharp::CppParser::AST::GCCAsmStmt&) {} +void ASTNodeVisitor::ConvertMSAsmStmtImpl(class clang::MSAsmStmt const*, class CppSharp::CppParser::AST::MSAsmStmt&) {} +void ASTNodeVisitor::ConvertBreakStmtImpl(class clang::BreakStmt const*, class CppSharp::CppParser::AST::BreakStmt&) {} +void ASTNodeVisitor::ConvertCXXCatchStmtImpl(class clang::CXXCatchStmt const*, class CppSharp::CppParser::AST::CXXCatchStmt&) {} +void ASTNodeVisitor::ConvertCXXForRangeStmtImpl(class clang::CXXForRangeStmt const*, class CppSharp::CppParser::AST::CXXForRangeStmt&) {} +void ASTNodeVisitor::ConvertCXXTryStmtImpl(class clang::CXXTryStmt const*, class CppSharp::CppParser::AST::CXXTryStmt&) {} +void ASTNodeVisitor::ConvertCapturedStmtImpl(class clang::CapturedStmt const*, class CppSharp::CppParser::AST::CapturedStmt&) {} +void ASTNodeVisitor::ConvertContinueStmtImpl(class clang::ContinueStmt const*, class CppSharp::CppParser::AST::ContinueStmt&) {} +void ASTNodeVisitor::ConvertCoreturnStmtImpl(class clang::CoreturnStmt const*, class CppSharp::CppParser::AST::CoreturnStmt&) {} +void ASTNodeVisitor::ConvertCoroutineBodyStmtImpl(class clang::CoroutineBodyStmt const*, class CppSharp::CppParser::AST::CoroutineBodyStmt&) {} +void ASTNodeVisitor::ConvertDeclStmtImpl(class clang::DeclStmt const*, class CppSharp::CppParser::AST::DeclStmt&) {} +void ASTNodeVisitor::ConvertDoStmtImpl(class clang::DoStmt const*, class CppSharp::CppParser::AST::DoStmt&) {} +void ASTNodeVisitor::ConvertForStmtImpl(class clang::ForStmt const*, class CppSharp::CppParser::AST::ForStmt&) {} +void ASTNodeVisitor::ConvertIndirectGotoStmtImpl(class clang::IndirectGotoStmt const*, class CppSharp::CppParser::AST::IndirectGotoStmt&) {} +void ASTNodeVisitor::ConvertMSDependentExistsStmtImpl(class clang::MSDependentExistsStmt const*, class CppSharp::CppParser::AST::MSDependentExistsStmt&) {} +void ASTNodeVisitor::ConvertNullStmtImpl(class clang::NullStmt const*, class CppSharp::CppParser::AST::NullStmt&) {} +void ASTNodeVisitor::ConvertReturnStmtImpl(class clang::ReturnStmt const*, class CppSharp::CppParser::AST::ReturnStmt&) {} +void ASTNodeVisitor::ConvertSEHExceptStmtImpl(class clang::SEHExceptStmt const*, class CppSharp::CppParser::AST::SEHExceptStmt&) {} +void ASTNodeVisitor::ConvertSEHFinallyStmtImpl(class clang::SEHFinallyStmt const*, class CppSharp::CppParser::AST::SEHFinallyStmt&) {} +void ASTNodeVisitor::ConvertSEHLeaveStmtImpl(class clang::SEHLeaveStmt const*, class CppSharp::CppParser::AST::SEHLeaveStmt&) {} +void ASTNodeVisitor::ConvertSEHTryStmtImpl(class clang::SEHTryStmt const*, class CppSharp::CppParser::AST::SEHTryStmt&) {} +void ASTNodeVisitor::ConvertSwitchCaseImpl(class clang::SwitchCase const*, class CppSharp::CppParser::AST::SwitchCase&) {} +void ASTNodeVisitor::ConvertDefaultStmtImpl(class clang::DefaultStmt const*, class CppSharp::CppParser::AST::DefaultStmt&) {} +void ASTNodeVisitor::ConvertValueStmtImpl(class clang::ValueStmt const*, class CppSharp::CppParser::AST::ValueStmt&) {} +void ASTNodeVisitor::ConvertAttributedStmtImpl(class clang::AttributedStmt const*, class CppSharp::CppParser::AST::AttributedStmt&) {} +void ASTNodeVisitor::ConvertAbstractConditionalOperatorImpl(class clang::AbstractConditionalOperator const*, class CppSharp::CppParser::AST::AbstractConditionalOperator&) {} +void ASTNodeVisitor::ConvertBinaryConditionalOperatorImpl(class clang::BinaryConditionalOperator const*, class CppSharp::CppParser::AST::BinaryConditionalOperator&) {} +void ASTNodeVisitor::ConvertConditionalOperatorImpl(class clang::ConditionalOperator const*, class CppSharp::CppParser::AST::ConditionalOperator&) {} +void ASTNodeVisitor::ConvertArrayInitIndexExprImpl(class clang::ArrayInitIndexExpr const*, class CppSharp::CppParser::AST::ArrayInitIndexExpr&) {} +void ASTNodeVisitor::ConvertArrayInitLoopExprImpl(class clang::ArrayInitLoopExpr const*, class CppSharp::CppParser::AST::ArrayInitLoopExpr&) {} +void ASTNodeVisitor::ConvertArraySubscriptExprImpl(class clang::ArraySubscriptExpr const*, class CppSharp::CppParser::AST::ArraySubscriptExpr&) {} +void ASTNodeVisitor::ConvertArrayTypeTraitExprImpl(class clang::ArrayTypeTraitExpr const*, class CppSharp::CppParser::AST::ArrayTypeTraitExpr&) {} +void ASTNodeVisitor::ConvertAsTypeExprImpl(class clang::AsTypeExpr const*, class CppSharp::CppParser::AST::AsTypeExpr&) {} +void ASTNodeVisitor::ConvertBlockExprImpl(class clang::BlockExpr const*, class CppSharp::CppParser::AST::BlockExpr&) {} +void ASTNodeVisitor::ConvertCXXTemporaryObjectExprImpl(class clang::CXXTemporaryObjectExpr const*, class CppSharp::CppParser::AST::CXXTemporaryObjectExpr&) {} +void ASTNodeVisitor::ConvertCXXFoldExprImpl(class clang::CXXFoldExpr const*, class CppSharp::CppParser::AST::CXXFoldExpr&) {} +void ASTNodeVisitor::ConvertCXXInheritedCtorInitExprImpl(class clang::CXXInheritedCtorInitExpr const*, class CppSharp::CppParser::AST::CXXInheritedCtorInitExpr&) {} +void ASTNodeVisitor::ConvertCXXNoexceptExprImpl(class clang::CXXNoexceptExpr const*, class CppSharp::CppParser::AST::CXXNoexceptExpr&) {} +void ASTNodeVisitor::ConvertCXXNullPtrLiteralExprImpl(class clang::CXXNullPtrLiteralExpr const*, class CppSharp::CppParser::AST::CXXNullPtrLiteralExpr&) {} +void ASTNodeVisitor::ConvertCXXParenListInitExprImpl(class clang::CXXParenListInitExpr const*, class CppSharp::CppParser::AST::CXXParenListInitExpr&) {} +void ASTNodeVisitor::ConvertCXXPseudoDestructorExprImpl(class clang::CXXPseudoDestructorExpr const*, class CppSharp::CppParser::AST::CXXPseudoDestructorExpr&) {} +void ASTNodeVisitor::ConvertCXXRewrittenBinaryOperatorImpl(class clang::CXXRewrittenBinaryOperator const*, class CppSharp::CppParser::AST::CXXRewrittenBinaryOperator&) {} +void ASTNodeVisitor::ConvertCXXScalarValueInitExprImpl(class clang::CXXScalarValueInitExpr const*, class CppSharp::CppParser::AST::CXXScalarValueInitExpr&) {} +void ASTNodeVisitor::ConvertCXXStdInitializerListExprImpl(class clang::CXXStdInitializerListExpr const*, class CppSharp::CppParser::AST::CXXStdInitializerListExpr&) {} +void ASTNodeVisitor::ConvertCXXThrowExprImpl(class clang::CXXThrowExpr const*, class CppSharp::CppParser::AST::CXXThrowExpr&) {} +void ASTNodeVisitor::ConvertCXXUuidofExprImpl(class clang::CXXUuidofExpr const*, class CppSharp::CppParser::AST::CXXUuidofExpr&) {} +void ASTNodeVisitor::ConvertCUDAKernelCallExprImpl(class clang::CUDAKernelCallExpr const*, class CppSharp::CppParser::AST::CUDAKernelCallExpr&) {} +void ASTNodeVisitor::ConvertCXXMemberCallExprImpl(class clang::CXXMemberCallExpr const*, class CppSharp::CppParser::AST::CXXMemberCallExpr&) {} +void ASTNodeVisitor::ConvertCXXOperatorCallExprImpl(class clang::CXXOperatorCallExpr const*, class CppSharp::CppParser::AST::CXXOperatorCallExpr&) {} +void ASTNodeVisitor::ConvertUserDefinedLiteralImpl(class clang::UserDefinedLiteral const*, class CppSharp::CppParser::AST::UserDefinedLiteral&) {} +void ASTNodeVisitor::ConvertExplicitCastExprImpl(class clang::ExplicitCastExpr const*, class CppSharp::CppParser::AST::ExplicitCastExpr&) {} +void ASTNodeVisitor::ConvertBuiltinBitCastExprImpl(class clang::BuiltinBitCastExpr const*, class CppSharp::CppParser::AST::BuiltinBitCastExpr&) {} +void ASTNodeVisitor::ConvertCStyleCastExprImpl(class clang::CStyleCastExpr const*, class CppSharp::CppParser::AST::CStyleCastExpr&) {} +void ASTNodeVisitor::ConvertCXXFunctionalCastExprImpl(class clang::CXXFunctionalCastExpr const*, class CppSharp::CppParser::AST::CXXFunctionalCastExpr&) {} +void ASTNodeVisitor::ConvertCXXNamedCastExprImpl(class clang::CXXNamedCastExpr const*, class CppSharp::CppParser::AST::CXXNamedCastExpr&) {} +void ASTNodeVisitor::ConvertCXXAddrspaceCastExprImpl(class clang::CXXAddrspaceCastExpr const*, class CppSharp::CppParser::AST::CXXAddrspaceCastExpr&) {} +void ASTNodeVisitor::ConvertCXXConstCastExprImpl(class clang::CXXConstCastExpr const*, class CppSharp::CppParser::AST::CXXConstCastExpr&) {} +void ASTNodeVisitor::ConvertCXXDynamicCastExprImpl(class clang::CXXDynamicCastExpr const*, class CppSharp::CppParser::AST::CXXDynamicCastExpr&) {} +void ASTNodeVisitor::ConvertCXXReinterpretCastExprImpl(class clang::CXXReinterpretCastExpr const*, class CppSharp::CppParser::AST::CXXReinterpretCastExpr&) {} +void ASTNodeVisitor::ConvertCXXStaticCastExprImpl(class clang::CXXStaticCastExpr const*, class CppSharp::CppParser::AST::CXXStaticCastExpr&) {} +void ASTNodeVisitor::ConvertChooseExprImpl(class clang::ChooseExpr const*, class CppSharp::CppParser::AST::ChooseExpr&) {} +void ASTNodeVisitor::ConvertCompoundLiteralExprImpl(class clang::CompoundLiteralExpr const*, class CppSharp::CppParser::AST::CompoundLiteralExpr&) {} +void ASTNodeVisitor::ConvertConvertVectorExprImpl(class clang::ConvertVectorExpr const*, class CppSharp::CppParser::AST::ConvertVectorExpr&) {} +void ASTNodeVisitor::ConvertCoroutineSuspendExprImpl(class clang::CoroutineSuspendExpr const*, class CppSharp::CppParser::AST::CoroutineSuspendExpr&) {} +void ASTNodeVisitor::ConvertCoawaitExprImpl(class clang::CoawaitExpr const*, class CppSharp::CppParser::AST::CoawaitExpr&) {} +void ASTNodeVisitor::ConvertCoyieldExprImpl(class clang::CoyieldExpr const*, class CppSharp::CppParser::AST::CoyieldExpr&) {} +void ASTNodeVisitor::ConvertDependentCoawaitExprImpl(class clang::DependentCoawaitExpr const*, class CppSharp::CppParser::AST::DependentCoawaitExpr&) {} +void ASTNodeVisitor::ConvertDependentScopeDeclRefExprImpl(class clang::DependentScopeDeclRefExpr const*, class CppSharp::CppParser::AST::DependentScopeDeclRefExpr&) {} +void ASTNodeVisitor::ConvertDesignatedInitExprImpl(class clang::DesignatedInitExpr const*, class CppSharp::CppParser::AST::DesignatedInitExpr&) {} +void ASTNodeVisitor::ConvertDesignatedInitUpdateExprImpl(class clang::DesignatedInitUpdateExpr const*, class CppSharp::CppParser::AST::DesignatedInitUpdateExpr&) {} +void ASTNodeVisitor::ConvertExpressionTraitExprImpl(class clang::ExpressionTraitExpr const*, class CppSharp::CppParser::AST::ExpressionTraitExpr&) {} +void ASTNodeVisitor::ConvertExtVectorElementExprImpl(class clang::ExtVectorElementExpr const*, class CppSharp::CppParser::AST::ExtVectorElementExpr&) {} +void ASTNodeVisitor::ConvertFullExprImpl(class clang::FullExpr const*, class CppSharp::CppParser::AST::FullExpr&) {} +void ASTNodeVisitor::ConvertFunctionParmPackExprImpl(class clang::FunctionParmPackExpr const*, class CppSharp::CppParser::AST::FunctionParmPackExpr&) {} +void ASTNodeVisitor::ConvertGNUNullExprImpl(class clang::GNUNullExpr const*, class CppSharp::CppParser::AST::GNUNullExpr&) {} +void ASTNodeVisitor::ConvertImaginaryLiteralImpl(class clang::ImaginaryLiteral const*, class CppSharp::CppParser::AST::ImaginaryLiteral&) {} +void ASTNodeVisitor::ConvertImplicitValueInitExprImpl(class clang::ImplicitValueInitExpr const*, class CppSharp::CppParser::AST::ImplicitValueInitExpr&) {} +void ASTNodeVisitor::ConvertLambdaExprImpl(class clang::LambdaExpr const*, class CppSharp::CppParser::AST::LambdaExpr&) {} +void ASTNodeVisitor::ConvertMSPropertyRefExprImpl(class clang::MSPropertyRefExpr const*, class CppSharp::CppParser::AST::MSPropertyRefExpr&) {} +void ASTNodeVisitor::ConvertMSPropertySubscriptExprImpl(class clang::MSPropertySubscriptExpr const*, class CppSharp::CppParser::AST::MSPropertySubscriptExpr&) {} +void ASTNodeVisitor::ConvertMatrixSubscriptExprImpl(class clang::MatrixSubscriptExpr const*, class CppSharp::CppParser::AST::MatrixSubscriptExpr&) {} +void ASTNodeVisitor::ConvertNoInitExprImpl(class clang::NoInitExpr const*, class CppSharp::CppParser::AST::NoInitExpr&) {} +void ASTNodeVisitor::ConvertOffsetOfExprImpl(class clang::OffsetOfExpr const*, class CppSharp::CppParser::AST::OffsetOfExpr&) {} +void ASTNodeVisitor::ConvertOpaqueValueExprImpl(class clang::OpaqueValueExpr const*, class CppSharp::CppParser::AST::OpaqueValueExpr&) {} +void ASTNodeVisitor::ConvertOverloadExprImpl(class clang::OverloadExpr const*, class CppSharp::CppParser::AST::OverloadExpr&) {} +void ASTNodeVisitor::ConvertUnresolvedMemberExprImpl(class clang::UnresolvedMemberExpr const*, class CppSharp::CppParser::AST::UnresolvedMemberExpr&) {} +void ASTNodeVisitor::ConvertPackExpansionExprImpl(class clang::PackExpansionExpr const*, class CppSharp::CppParser::AST::PackExpansionExpr&) {} +void ASTNodeVisitor::ConvertParenExprImpl(class clang::ParenExpr const*, class CppSharp::CppParser::AST::ParenExpr&) {} +void ASTNodeVisitor::ConvertParenListExprImpl(class clang::ParenListExpr const*, class CppSharp::CppParser::AST::ParenListExpr&) {} +void ASTNodeVisitor::ConvertPseudoObjectExprImpl(class clang::PseudoObjectExpr const*, class CppSharp::CppParser::AST::PseudoObjectExpr&) {} +void ASTNodeVisitor::ConvertRecoveryExprImpl(class clang::RecoveryExpr const*, class CppSharp::CppParser::AST::RecoveryExpr&) {} +void ASTNodeVisitor::ConvertShuffleVectorExprImpl(class clang::ShuffleVectorExpr const*, class CppSharp::CppParser::AST::ShuffleVectorExpr&) {} +void ASTNodeVisitor::ConvertSourceLocExprImpl(class clang::SourceLocExpr const*, class CppSharp::CppParser::AST::SourceLocExpr&) {} +void ASTNodeVisitor::ConvertStmtExprImpl(class clang::StmtExpr const*, class CppSharp::CppParser::AST::StmtExpr&) {} +void ASTNodeVisitor::ConvertSubstNonTypeTemplateParmExprImpl(class clang::SubstNonTypeTemplateParmExpr const*, class CppSharp::CppParser::AST::SubstNonTypeTemplateParmExpr&) {} +void ASTNodeVisitor::ConvertSubstNonTypeTemplateParmPackExprImpl(class clang::SubstNonTypeTemplateParmPackExpr const*, class CppSharp::CppParser::AST::SubstNonTypeTemplateParmPackExpr&) {} +void ASTNodeVisitor::ConvertTypeTraitExprImpl(class clang::TypeTraitExpr const*, class CppSharp::CppParser::AST::TypeTraitExpr&) {} +void ASTNodeVisitor::ConvertTypoExprImpl(class clang::TypoExpr const*, class CppSharp::CppParser::AST::TypoExpr&) {} +void ASTNodeVisitor::ConvertVAArgExprImpl(class clang::VAArgExpr const*, class CppSharp::CppParser::AST::VAArgExpr&) {} + void ASTNodeVisitor::VisitNullTemplateArgument(const TemplateArgument& TA) { @@ -2344,7 +2344,7 @@ llvm::json::Object ASTNodeVisitor::createFPOptions(FPOptionsOverride FPO) return Ret; } -void ASTNodeVisitor::VisitCompoundStmt(const CompoundStmt* S) +void ASTNodeVisitor::ConvertCompoundStmtImpl(const CompoundStmt* S, AST::CompoundStmt& Dst) { VisitStmt(S); if (S->hasStoredFPFeatures()) diff --git a/src/CppParser/ASTNodeVisitor.h b/src/CppParser/ASTNodeVisitor.h index d94c5e6e73..4a38eef870 100644 --- a/src/CppParser/ASTNodeVisitor.h +++ b/src/CppParser/ASTNodeVisitor.h @@ -25,14 +25,12 @@ #include #include "Decl.h" +#include "Expr.h" #include "Stmt.h" namespace CppSharp::CppParser { namespace AST { class Stmt; - - // TODO: Remove this once we have proper type conversions - using Decl = Declaration; } // namespace AST class Parser; @@ -283,6 +281,9 @@ class ASTNodeVisitor #include "clang/AST/DeclNodes.inc" // The above header #undefs ABSTRACT_DECL and DECL upon exit.*/ + + void ConvertStmt(const clang::Stmt* Src, AST::Stmt& Dst); + #define STMT(CLASS, BASE) \ void Convert##CLASS##Impl(const clang::CLASS* Src, AST::CLASS& Dst); \ void Convert##CLASS(const clang::CLASS* Src, AST::CLASS& Dst) \ @@ -294,14 +295,14 @@ class ASTNodeVisitor // Declare Visit*() for all concrete Stmt classes. #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, BASE) \ - void Visit##CLASS(const clang::CLASS* S) \ - { \ - if (stmtMap.find(D) != stmtMap.end()) \ - return; \ - \ - auto res = stmtMap.emplace(S, new AST::CLASS()); \ - Convert##CLASS(S, res.first->second); \ +#define STMT(CLASS, BASE) \ + void Visit##CLASS(const clang::CLASS* S) \ + { \ + if (!S || stmtMap.find(S) != stmtMap.end()) \ + return; \ + \ + auto res = stmtMap.emplace(S, new AST::CLASS()); \ + Convert##CLASS(S, static_cast(*res.first->second)); \ } #include "StmtNodes.inc" // The above header #undefs ABSTRACT_STMT and STMT upon exit. @@ -393,7 +394,7 @@ class ASTNodeVisitor std::unordered_map declMap; std::unordered_set typeMap; - std::unordered_set stmtMap; + std::unordered_map stmtMap; Parser& parser; const clang::SourceManager& SM; @@ -494,8 +495,9 @@ class ASTNodeDumper : public clang::ASTNodeTraversergetTemplatedDecl()); - for (const auto* Child : TD->specializations()) - writeTemplateDeclSpecialization(Child, DumpExplicitInst, !TD->isCanonicalDecl()); + // TODO: Fixme. Crash in specializations iterator (clang bug?) + // for (const auto* Child : TD->specializations()) + // writeTemplateDeclSpecialization(Child, DumpExplicitInst, !TD->isCanonicalDecl()); } ASTNodeVisitor NodeVisitor; diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index f3426da564..3d0a91873b 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -984,6 +984,8 @@ static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::ASTContex return dyn_cast(RT->getDecl()); else if (auto TST = Ty->getAs()) return GetCXXRecordDeclFromTemplateName(TST->getTemplateName()); + else if (auto DTST = Ty->getAs()) + return nullptr; else if (auto Injected = Ty->getAs()) return Injected->getDecl(); else if (auto TTPT = Ty->getAs()) @@ -4677,6 +4679,7 @@ void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx) ASTNodeDumper Dumper(OS, Ctx, Parser); Dumper.Visit(TU); + debug_break(); } Parser.WalkAST(TU); diff --git a/src/CppParser/StmtNodes.inc b/src/CppParser/StmtNodes.inc index db3d08ba30..e1a4a926c3 100644 --- a/src/CppParser/StmtNodes.inc +++ b/src/CppParser/StmtNodes.inc @@ -562,12 +562,6 @@ CHOOSEEXPR(ChooseExpr, Expr) COMPOUNDLITERALEXPR(CompoundLiteralExpr, Expr) #undef COMPOUNDLITERALEXPR -#ifndef CONCEPTSPECIALIZATIONEXPR -# define CONCEPTSPECIALIZATIONEXPR(Type, Base) EXPR(Type, Base) -#endif -CONCEPTSPECIALIZATIONEXPR(ConceptSpecializationExpr, Expr) -#undef CONCEPTSPECIALIZATIONEXPR - #ifndef CONVERTVECTOREXPR # define CONVERTVECTOREXPR(Type, Base) EXPR(Type, Base) #endif @@ -823,12 +817,6 @@ PSEUDOOBJECTEXPR(PseudoObjectExpr, Expr) RECOVERYEXPR(RecoveryExpr, Expr) #undef RECOVERYEXPR -#ifndef REQUIRESEXPR -# define REQUIRESEXPR(Type, Base) EXPR(Type, Base) -#endif -REQUIRESEXPR(RequiresExpr, Expr) -#undef REQUIRESEXPR - #ifndef SYCLUNIQUESTABLENAMEEXPR # define SYCLUNIQUESTABLENAMEEXPR(Type, Base) EXPR(Type, Base) #endif