Browse Source

Node Visitor WIP

pull/1922/head
duckdoom5 4 months ago
parent
commit
bb5aae1cf5
  1. 4
      src/Core/Diagnostics.cs
  2. 236
      src/CppParser/AST.cpp
  3. 2352
      src/CppParser/ASTNodeVisitor.cpp
  4. 545
      src/CppParser/ASTNodeVisitor.h
  5. 52
      src/CppParser/Decl.h
  6. 33
      src/CppParser/Parser.cpp
  7. 12
      src/CppParser/Parser.h
  8. 2
      src/CppParser/ParserGen/ParserGen.cs
  9. 16
      src/CppParser/Types.h
  10. 1
      src/Generator.Tests/GeneratorTest.cs

4
src/Core/Diagnostics.cs

@ -128,7 +128,9 @@ namespace CppSharp @@ -128,7 +128,9 @@ namespace CppSharp
{
Console.WriteLine(message);
}
Debug.WriteLine(message);
// Super slow, don't use this for now
// Debug.WriteLine(message);
}
public void PushIndent(int level)

236
src/CppParser/AST.cpp

@ -11,17 +11,20 @@ @@ -11,17 +11,20 @@
#include <llvm/ADT/SmallString.h>
#include <llvm/Support/Path.h>
// copy from widenPath ('llvm/lib/Support/Windows/Path.inc')
static std::string normalizePath(const std::string& File)
namespace CppSharp::CppParser::AST {
namespace {
// Adapted from widenPath ('llvm/lib/Support/Windows/Path.inc')
std::string normalizePath(const std::string_view& file)
{
llvm::SmallString<2 * 128> Result;
for (llvm::sys::path::const_iterator I = llvm::sys::path::begin(File),
E = llvm::sys::path::end(File);
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
@ -36,33 +39,33 @@ static std::string normalizePath(const std::string& File) @@ -36,33 +39,33 @@ static std::string normalizePath(const std::string& File)
return Result.c_str();
}
template <typename T>
static std::vector<T> split(const T& str, const T& delimiters)
std::vector<std::string_view> split(const std::string_view& str, const std::string_view& delimiters)
{
std::vector<T> v;
if (str.length() == 0)
std::vector<std::string_view> v;
if (str.empty())
{
v.push_back(str);
v.emplace_back(str);
return v;
}
typename T::size_type start = 0;
std::string_view::size_type start = 0;
auto pos = str.find_first_of(delimiters, start);
while (pos != T::npos)
while (pos != std::string_view::npos)
{
if (pos != start) // ignore empty tokens
v.emplace_back(str, start, pos - start);
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
// add what's left of the string
v.emplace_back(str, start, str.length() - 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;
}
namespace CppSharp { namespace CppParser { namespace AST {
static void deleteExpression(ExpressionObsolete* expression)
void deleteExpression(ExpressionObsolete* expression)
{
if (expression)
{
@ -84,6 +87,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -84,6 +87,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
}
}
}
} // namespace
Type::Type(TypeKind kind)
: kind(kind)
@ -95,10 +99,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -95,10 +99,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
{
}
QualifiedType::QualifiedType()
: type(0)
{
}
QualifiedType::QualifiedType() {}
TagType::TagType()
: Type(TypeKind::Tag)
@ -135,7 +136,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -135,7 +136,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
TypedefType::TypedefType()
: Type(TypeKind::Typedef)
, declaration(0)
, declaration(nullptr)
{
}
@ -190,7 +191,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -190,7 +191,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
NonTypeTemplateParameter::NonTypeTemplateParameter()
: TemplateParameter(DeclarationKind::NonTypeTemplateParm)
, defaultArgument(0)
, defaultArgument(nullptr)
, position(0)
, isPackExpansion(false)
, isExpandedParameterPack(false)
@ -213,14 +214,14 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -213,14 +214,14 @@ namespace CppSharp { namespace CppParser { namespace AST {
}
TemplateArgument::TemplateArgument()
: declaration(0)
: declaration(nullptr)
, integral(0)
{
}
TemplateSpecializationType::TemplateSpecializationType()
: Type(TypeKind::TemplateSpecialization)
, _template(0)
, _template(nullptr)
{
}
@ -256,7 +257,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -256,7 +257,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
TemplateParameterType::TemplateParameterType()
: Type(TypeKind::TemplateParameter)
, parameter(0)
, parameter(nullptr)
{
}
@ -264,13 +265,13 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -264,13 +265,13 @@ namespace CppSharp { namespace CppParser { namespace AST {
TemplateParameterSubstitutionType::TemplateParameterSubstitutionType()
: Type(TypeKind::TemplateParameterSubstitution)
, replacedParameter(0)
, replacedParameter(nullptr)
{
}
InjectedClassNameType::InjectedClassNameType()
: Type(TypeKind::InjectedClassName)
, _class(0)
, _class(nullptr)
{
}
@ -303,13 +304,13 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -303,13 +304,13 @@ namespace CppSharp { namespace CppParser { namespace AST {
}
BuiltinType::BuiltinType()
: CppSharp::CppParser::AST::Type(TypeKind::Builtin)
: Type(TypeKind::Builtin)
{
}
VTableComponent::VTableComponent()
: offset(0)
, declaration(0)
, declaration(nullptr)
{
}
@ -339,7 +340,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -339,7 +340,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
LayoutField::LayoutField()
: offset(0)
, fieldPtr(0)
, fieldPtr(nullptr)
{
}
@ -355,7 +356,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -355,7 +356,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
LayoutBase::LayoutBase()
: offset(0)
, _class(0)
, _class(nullptr)
{
}
@ -387,19 +388,19 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -387,19 +388,19 @@ namespace CppSharp { namespace CppParser { namespace AST {
Declaration::Declaration(DeclarationKind kind)
: kind(kind)
, access(AccessSpecifier::Public)
, _namespace(0)
, _namespace(nullptr)
, location(0)
, lineNumberStart(0)
, lineNumberEnd(0)
, comment(0)
, comment(nullptr)
, isIncomplete(false)
, isDependent(false)
, isImplicit(false)
, isInvalid(false)
, isDeprecated(false)
, completeDeclaration(0)
, completeDeclaration(nullptr)
, definitionOrder(0)
, originalPtr(0)
, originalPtr(nullptr)
, alignAs(0)
, maxFieldAlignment(0)
{
@ -450,29 +451,26 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -450,29 +451,26 @@ namespace CppSharp { namespace CppParser { namespace AST {
DEF_VECTOR(DeclarationContext, Variable*, Variables)
DEF_VECTOR(DeclarationContext, Friend*, Friends)
Declaration* DeclarationContext::FindAnonymous(const std::string& key)
Declaration* DeclarationContext::FindAnonymous(const std::string_view& key)
{
auto it = anonymous.find(key);
return (it != anonymous.end()) ? it->second : 0;
return (it != anonymous.end()) ? it->second : nullptr;
}
Namespace* DeclarationContext::FindNamespace(const std::string& Name)
Namespace* DeclarationContext::FindNamespace(const std::string_view& name)
{
auto namespaces = split<std::string>(Name, "::");
const auto namespaces = split(name, "::");
return FindNamespace(namespaces);
}
Namespace*
DeclarationContext::FindNamespace(const std::vector<std::string>& Namespaces)
Namespace* DeclarationContext::FindNamespace(const std::vector<std::string_view>& namespaces)
{
auto currentNamespace = this;
for (auto I = Namespaces.begin(), E = Namespaces.end(); I != E; ++I)
for (auto& _namespace : namespaces)
{
auto& _namespace = *I;
auto childNamespace = std::find_if(currentNamespace->Namespaces.begin(),
currentNamespace->Namespaces.end(),
[&](CppSharp::CppParser::AST::Namespace* ns)
[&](const Namespace* ns)
{
return ns->name == _namespace;
});
@ -483,10 +481,10 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -483,10 +481,10 @@ namespace CppSharp { namespace CppParser { namespace AST {
currentNamespace = *childNamespace;
}
return (CppSharp::CppParser::AST::Namespace*)currentNamespace;
return (Namespace*)currentNamespace;
}
Namespace* DeclarationContext::FindCreateNamespace(const std::string& Name)
Namespace& DeclarationContext::FindCreateNamespace(const std::string_view& Name)
{
auto _namespace = FindNamespace(Name);
@ -499,22 +497,20 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -499,22 +497,20 @@ namespace CppSharp { namespace CppParser { namespace AST {
Namespaces.push_back(_namespace);
}
return _namespace;
return *_namespace;
}
Class* DeclarationContext::FindClass(const void* OriginalPtr,
const std::string& Name,
bool IsComplete)
Class* DeclarationContext::FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete)
{
if (Name.empty())
return nullptr;
auto entries = split<std::string>(Name, "::");
auto namespaces = split(Name, "::");
if (entries.size() == 1)
if (namespaces.size() == 1)
{
auto _class = std::find_if(Classes.begin(), Classes.end(),
[OriginalPtr, Name, IsComplete](Class* klass)
[OriginalPtr, Name, IsComplete](const Class* klass)
{
return (OriginalPtr && klass->originalPtr == OriginalPtr) ||
(klass->name == Name && klass->isIncomplete == !IsComplete);
@ -523,10 +519,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -523,10 +519,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
return _class != Classes.end() ? *_class : nullptr;
}
auto className = entries[entries.size() - 1];
std::vector<std::string> 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)
@ -535,7 +529,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -535,7 +529,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
return _namespace->FindClass(OriginalPtr, className, IsComplete);
}
Class* DeclarationContext::CreateClass(const std::string& Name, bool IsComplete)
Class* DeclarationContext::CreateClass(const std::string_view& Name, bool IsComplete)
{
auto _class = new Class();
_class->name = Name;
@ -545,10 +539,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -545,10 +539,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
return _class;
}
Class* DeclarationContext::FindClass(const void* OriginalPtr,
const std::string& Name,
bool IsComplete,
bool Create)
Class* DeclarationContext::FindClass(const void* OriginalPtr, const std::string_view& Name, bool IsComplete, bool Create)
{
auto _class = FindClass(OriginalPtr, Name, IsComplete);
@ -569,7 +560,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -569,7 +560,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
Enumeration* DeclarationContext::FindEnum(const void* OriginalPtr)
{
auto foundEnum = std::find_if(Enums.begin(), Enums.end(),
[&](Enumeration* enumeration)
[&](const Enumeration* enumeration)
{
return enumeration->originalPtr == OriginalPtr;
});
@ -580,14 +571,14 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -580,14 +571,14 @@ namespace CppSharp { namespace CppParser { namespace AST {
return nullptr;
}
Enumeration* DeclarationContext::FindEnum(const std::string& Name, bool Create)
Enumeration* DeclarationContext::FindEnum(const std::string_view& Name, bool Create)
{
auto entries = split<std::string>(Name, "::");
auto namespaces = split(Name, "::");
if (entries.size() == 1)
if (namespaces.size() == 1)
{
auto foundEnum = std::find_if(Enums.begin(), Enums.end(),
[&](Enumeration* _enum)
[&](const Enumeration* _enum)
{
return _enum->name == Name;
});
@ -605,10 +596,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -605,10 +596,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
return _enum;
}
auto enumName = entries[entries.size() - 1];
std::vector<std::string> namespaces;
std::copy_n(entries.begin(), entries.size() - 1, std::back_inserter(namespaces));
auto enumName = namespaces.back();
namespaces.pop_back();
auto _namespace = FindNamespace(namespaces);
if (!_namespace)
@ -617,34 +606,38 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -617,34 +606,38 @@ namespace CppSharp { namespace CppParser { namespace AST {
return _namespace->FindEnum(enumName, Create);
}
Enumeration* DeclarationContext::FindEnumWithItem(const std::string& Name)
Enumeration* DeclarationContext::FindEnumWithItem(const std::string_view& Name)
{
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)
for (auto& Namespace : Namespaces)
{
auto foundEnum = (*it)->FindEnumWithItem(Name);
auto foundEnum = Namespace->FindEnumWithItem(Name);
if (foundEnum != nullptr)
return foundEnum;
}
for (auto it = Classes.begin(); it != Classes.end(); ++it)
for (auto& Class : Classes)
{
auto foundEnum = (*it)->FindEnumWithItem(Name);
auto foundEnum = Class->FindEnumWithItem(Name);
if (foundEnum != nullptr)
return foundEnum;
}
return nullptr;
}
Function* DeclarationContext::FindFunction(const std::string& USR)
Function* DeclarationContext::FindFunction(const std::string_view& USR)
{
auto foundFunction = std::find_if(Functions.begin(), Functions.end(),
[&](Function* func)
[&](const Function* func)
{
return func->USR == USR;
});
@ -653,7 +646,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -653,7 +646,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
return *foundFunction;
auto foundTemplate = std::find_if(Templates.begin(), Templates.end(),
[&](Template* t)
[&](const Template* t)
{
return t->TemplatedDecl && t->TemplatedDecl->USR == USR;
});
@ -664,10 +657,10 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -664,10 +657,10 @@ namespace CppSharp { namespace CppParser { namespace AST {
return nullptr;
}
TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Create)
TypedefDecl* DeclarationContext::FindTypedef(const std::string_view& Name, bool Create)
{
auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(),
[&](TypedefDecl* tdef)
[&](const TypedefDecl* tdef)
{
return tdef->name == Name;
});
@ -685,10 +678,10 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -685,10 +678,10 @@ namespace CppSharp { namespace CppParser { namespace AST {
return tdef;
}
TypeAlias* DeclarationContext::FindTypeAlias(const std::string& Name, bool Create)
TypeAlias* DeclarationContext::FindTypeAlias(const std::string_view& Name, bool Create)
{
auto foundTypeAlias = std::find_if(TypeAliases.begin(), TypeAliases.end(),
[&](TypeAlias* talias)
[&](const TypeAlias* talias)
{
return talias->name == Name;
});
@ -706,10 +699,10 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -706,10 +699,10 @@ namespace CppSharp { namespace CppParser { namespace AST {
return talias;
}
Variable* DeclarationContext::FindVariable(const std::string& USR)
Variable* DeclarationContext::FindVariable(const std::string_view& USR)
{
auto found = std::find_if(Variables.begin(), Variables.end(),
[&](Variable* var)
[&](const Variable* var)
{
return var->USR == USR;
});
@ -720,10 +713,10 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -720,10 +713,10 @@ namespace CppSharp { namespace CppParser { namespace AST {
return nullptr;
}
Friend* DeclarationContext::FindFriend(const std::string& USR)
Friend* DeclarationContext::FindFriend(const std::string_view& USR)
{
auto found = std::find_if(Friends.begin(), Friends.end(),
[&](Friend* var)
[&](const Friend* var)
{
return var->USR == USR;
});
@ -750,15 +743,15 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -750,15 +743,15 @@ namespace CppSharp { namespace CppParser { namespace AST {
TypeAlias::TypeAlias()
: TypedefNameDecl(DeclarationKind::TypeAlias)
, describedAliasTemplate(0)
, describedAliasTemplate(nullptr)
{
}
TypeAlias::~TypeAlias() {}
Friend::Friend()
: CppSharp::CppParser::AST::Declaration(DeclarationKind::Friend)
, declaration(0)
: Declaration(DeclarationKind::Friend)
, declaration(nullptr)
{
}
@ -821,8 +814,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -821,8 +814,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
: Declaration(DeclarationKind::Parameter)
, isIndirect(false)
, hasDefaultValue(false)
, defaultArgument(0)
, defaultValue(0)
, defaultArgument(nullptr)
, defaultValue(nullptr)
{
}
@ -843,9 +836,9 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -843,9 +836,9 @@ namespace CppSharp { namespace CppParser { namespace AST {
, friendKind(FriendKind::None)
, operatorKind(CXXOperatorKind::None)
, callingConvention(CallingConvention::Default)
, specializationInfo(0)
, instantiatedFrom(0)
, bodyStmt(0)
, specializationInfo(nullptr)
, instantiatedFrom(nullptr)
, bodyStmt(nullptr)
{
}
@ -876,8 +869,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -876,8 +869,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
Enumeration::Enumeration()
: DeclarationContext(DeclarationKind::Enumeration)
, modifiers((EnumModifiers)0)
, type(0)
, builtinType(0)
, type(nullptr)
, builtinType(nullptr)
{
}
@ -899,13 +892,14 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -899,13 +892,14 @@ namespace CppSharp { namespace CppParser { namespace AST {
Enumeration::Item::~Item() {}
Enumeration::Item* Enumeration::FindItemByName(const std::string& Name)
Enumeration::Item* Enumeration::FindItemByName(const std::string_view& Name)
{
auto foundEnumItem = std::find_if(Items.begin(), Items.end(),
[&](Item* _item)
[&](const Item* _item)
{
return _item->name == Name;
});
if (foundEnumItem != Items.end())
return *foundEnumItem;
return nullptr;
@ -914,21 +908,21 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -914,21 +908,21 @@ namespace CppSharp { namespace CppParser { namespace AST {
Variable::Variable()
: Declaration(DeclarationKind::Variable)
, isConstExpr(false)
, initializer(0)
, initializer(nullptr)
{
}
Variable::~Variable() {}
BaseClassSpecifier::BaseClassSpecifier()
: type(0)
: type(nullptr)
, offset(0)
{
}
Field::Field()
: Declaration(DeclarationKind::Field)
, _class(0)
, _class(nullptr)
, isBitField(false)
, bitWidth(0)
{
@ -955,7 +949,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -955,7 +949,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
, hasNonTrivialDestructor(false)
, isExternCContext(false)
, isInjected(false)
, layout(0)
, layout(nullptr)
, tagKind(TagKind::Struct)
{
}
@ -973,13 +967,13 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -973,13 +967,13 @@ namespace CppSharp { namespace CppParser { namespace AST {
Template::Template()
: Declaration(DeclarationKind::Template)
, TemplatedDecl(0)
, TemplatedDecl(nullptr)
{
}
Template::Template(DeclarationKind kind)
: Declaration(kind)
, TemplatedDecl(0)
, TemplatedDecl(nullptr)
{
}
@ -1003,7 +997,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1003,7 +997,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
ClassTemplateSpecialization::ClassTemplateSpecialization()
: Class()
, templatedDecl(0)
, templatedDecl(nullptr)
{
kind = DeclarationKind::ClassTemplateSpecialization;
}
@ -1046,8 +1040,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1046,8 +1040,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
}
FunctionTemplateSpecialization::FunctionTemplateSpecialization()
: _template(0)
, specializedFunction(0)
: _template(nullptr)
, specializedFunction(nullptr)
{
}
@ -1090,7 +1084,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1090,7 +1084,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
VarTemplateSpecialization::VarTemplateSpecialization()
: Variable()
, templatedDecl(0)
, templatedDecl(nullptr)
{
kind = DeclarationKind::VarTemplateSpecialization;
}
@ -1125,8 +1119,8 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1125,8 +1119,8 @@ namespace CppSharp { namespace CppParser { namespace AST {
Namespace::~Namespace() {}
PreprocessedEntity::PreprocessedEntity()
: macroLocation(AST::MacroLocation::Unknown)
, originalPtr(0)
: macroLocation(MacroLocation::Unknown)
, originalPtr(nullptr)
, kind(DeclarationKind::PreprocessedEntity)
{
}
@ -1141,7 +1135,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1141,7 +1135,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
MacroDefinition::~MacroDefinition() {}
MacroExpansion::MacroExpansion()
: definition(0)
: definition(nullptr)
{
kind = DeclarationKind::MacroExpansion;
}
@ -1157,7 +1151,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1157,7 +1151,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
DEF_VECTOR(TranslationUnit, MacroDefinition*, Macros)
NativeLibrary::NativeLibrary()
: archType(AST::ArchType::UnknownArch)
: archType(ArchType::UnknownArch)
{
}
@ -1223,7 +1217,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1223,7 +1217,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
}
RawComment::RawComment()
: fullCommentBlock(0)
: fullCommentBlock(nullptr)
{
}
@ -1294,14 +1288,14 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1294,14 +1288,14 @@ namespace CppSharp { namespace CppParser { namespace AST {
BlockCommandComment::BlockCommandComment()
: BlockContentComment(CommentKind::BlockCommandComment)
, commandId(0)
, paragraphComment(0)
, paragraphComment(nullptr)
{
}
BlockCommandComment::BlockCommandComment(CommentKind Kind)
: BlockContentComment(Kind)
, commandId(0)
, paragraphComment(0)
, paragraphComment(nullptr)
{
}
@ -1314,7 +1308,7 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1314,7 +1308,7 @@ namespace CppSharp { namespace CppParser { namespace AST {
ParamCommandComment::ParamCommandComment()
: BlockCommandComment(CommentKind::ParamCommandComment)
, direction(PassDirection::In)
, direction(In)
, paramIndex(0)
{
}
@ -1453,4 +1447,4 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -1453,4 +1447,4 @@ namespace CppSharp { namespace CppParser { namespace AST {
{
}
}}} // namespace CppSharp::CppParser::AST
} // namespace CppSharp::CppParser::AST

2352
src/CppParser/ASTNodeVisitor.cpp

File diff suppressed because it is too large Load Diff

545
src/CppParser/ASTNodeVisitor.h

@ -0,0 +1,545 @@ @@ -0,0 +1,545 @@
/************************************************************************
*
* CppSharp
* Licensed under the simplified BSD license. All rights reserved.
*
************************************************************************/
#pragma once
#include <llvm/Support/JSON.h>
#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 <unordered_set>
namespace CppSharp::CppParser {
namespace AST {
class Stmt;
}
class Parser;
class NodeStreamer
{
bool FirstChild = true;
bool TopLevel = true;
llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
protected:
llvm::json::OStream JOS;
public:
/// Add a child of the current node. Calls DoAddChild without arguments
template <typename Fn>
void AddChild(Fn DoAddChild)
{
return AddChild("", DoAddChild);
}
/// Add a child of the current node with an optional label.
/// Calls DoAddChild without arguments.
template <typename Fn>
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<ASTNodeVisitor>,
public clang::comments::ConstCommentVisitor<ASTNodeVisitor, void, const clang::comments::FullComment*>,
public clang::ConstTemplateArgumentVisitor<ASTNodeVisitor>,
public clang::ConstStmtVisitor<ASTNodeVisitor>,
public clang::TypeVisitor<ASTNodeVisitor>,
public clang::ConstDeclVisitor<ASTNodeVisitor, AST::Declaration*>,
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 <typename T>
void writePreviousDeclImpl(const clang::Mergeable<T>* D)
{
const T* First = D->getFirstDecl();
if (First != D)
JOS.attribute("firstRedecl", createPointerRepresentation(First));
}
template <typename T>
void writePreviousDeclImpl(const clang::Redeclarable<T>* 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 <typename Fn>
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<const clang::Decl*, AST::Declaration*> declMap;
std::unordered_set<const clang::Type*> typeMap;
std::unordered_set<const clang::Stmt*> 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<ASTNodeDumper, ASTNodeVisitor>
{
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 <typename SpecializationDecl>
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<SpecializationDecl>(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<clang::CXXRecordDecl>(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 <typename TemplateDecl>
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<ASTParser>
{
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

52
src/CppParser/Decl.h

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
#include "Sources.h"
#include "Types.h"
#include <algorithm>
#include <unordered_map>
namespace CppSharp {
namespace CppParser {
@ -82,6 +83,7 @@ namespace AST { @@ -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 { @@ -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 { @@ -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<std::string>&);
CS_IGNORE Namespace* FindCreateNamespace(const std::string& Name);
CS_IGNORE Namespace* FindNamespace(const std::string_view& name);
CS_IGNORE Namespace* FindNamespace(const std::vector<std::string_view>&);
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 <typename T>
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 { @@ -152,7 +157,7 @@ namespace AST {
VECTOR(Variable*, Variables)
VECTOR(Friend*, Friends)
std::map<std::string, Declaration*> anonymous;
std::map<std::string, Declaration*, std::less<>> anonymous;
bool isAnonymous;
};
@ -203,7 +208,7 @@ namespace AST { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -611,10 +616,10 @@ namespace AST {
};
template <typename T>
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 { @@ -782,6 +787,7 @@ namespace AST {
Namespace();
~Namespace();
bool isInline;
bool isNested;
};
enum class MacroLocation

33
src/CppParser/Parser.cpp

@ -59,6 +59,7 @@ @@ -59,6 +59,7 @@
#include <Driver/ToolChains/MSVC.h>
#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 @@ -514,12 +515,6 @@ std::string Parser::GetDeclMangledName(const clang::Decl* D) const
if (ND->isTemplated())
return {};
/*bool CanMangle = isa<FunctionDecl>(D) || isa<VarDecl>(D)
|| isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D);
if (!CanMangle)
return {};*/
// FIXME: There are likely other contexts in which it makes no sense to ask
// for a mangled name.
if (isa<RequiresExprBodyDecl>(ND->getDeclContext()))
@ -2125,7 +2120,7 @@ Field* Parser::WalkFieldCXX(const clang::FieldDecl* FD, Class* Class) @@ -2125,7 +2120,7 @@ Field* Parser::WalkFieldCXX(const clang::FieldDecl* FD, Class* Class)
//-----------------------------------//
TranslationUnit* Parser::GetTranslationUnit(clang::SourceLocation Loc,
TranslationUnit* Parser::GetOrCreateTranslationUnit(clang::SourceLocation Loc,
SourceLocationKind* Kind)
{
using namespace clang;
@ -2171,12 +2166,12 @@ TranslationUnit* Parser::GetTranslationUnit(clang::SourceLocation Loc, @@ -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, @@ -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<Decl>(Context));
TranslationUnit* Unit = GetOrCreateTranslationUnit(cast<Decl>(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, @@ -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( @@ -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) @@ -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) @@ -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);
}

12
src/CppParser/Parser.h

@ -97,8 +97,8 @@ namespace CppSharp { namespace CppParser { @@ -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 { @@ -116,7 +116,7 @@ namespace CppSharp { namespace CppParser {
std::vector<AST::TemplateArgument> WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, TypeLoc* TSTL);
std::vector<AST::TemplateArgument> 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 { @@ -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);

2
src/CppParser/ParserGen/ParserGen.cs

@ -28,6 +28,8 @@ namespace CppSharp @@ -28,6 +28,8 @@ namespace CppSharp
Kind = kind;
Triple = triple;
IsGnuCpp11Abi = isGnuCpp11Abi;
Diagnostics.Level = DiagnosticKind.Debug;
}
static string GetSourceDirectory(string dir)

16
src/CppParser/Types.h

@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
#include "Helpers.h"
namespace CppSharp { namespace CppParser { namespace AST {
namespace CppSharp::CppParser::AST {
enum class TypeKind
{
@ -44,20 +44,22 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -44,20 +44,22 @@ namespace CppSharp { namespace CppParser { namespace AST {
Type(const Type&);
TypeKind kind;
bool isDependent;
bool isDependent = false;
};
struct CS_API TypeQualifiers
{
bool isConst;
bool isVolatile;
bool isRestrict;
bool isConst = false;
bool isVolatile = false;
bool isRestrict = false;
};
struct CS_API QualifiedType
{
QualifiedType();
Type* type;
Type* type = nullptr;
Type* desugaredType = nullptr;
void* typeAliasDeclId = nullptr;
TypeQualifiers qualifiers;
};
@ -329,4 +331,4 @@ namespace CppSharp { namespace CppParser { namespace AST { @@ -329,4 +331,4 @@ namespace CppSharp { namespace CppParser { namespace AST {
PrimitiveType type;
};
}}} // namespace CppSharp::CppParser::AST
} // namespace CppSharp::CppParser::AST

1
src/Generator.Tests/GeneratorTest.cs

@ -28,6 +28,7 @@ namespace CppSharp.Utils @@ -28,6 +28,7 @@ namespace CppSharp.Utils
options.Quiet = true;
options.GenerateDebugOutput = true;
options.CheckSymbols = true;
driver.ParserOptions.SkipSystemHeaders = false;
var testModule = options.AddModule(name);
Diagnostics.Message("");

Loading…
Cancel
Save