mirror of https://github.com/mono/CppSharp.git
5 changed files with 1253 additions and 0 deletions
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
//===----- CXXABI.h - Interface to C++ ABIs ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This provides an abstract class for C++ AST support. Concrete
|
||||
// subclasses of this implement AST support for specific C++ ABIs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_CXXABI_H |
||||
#define LLVM_CLANG_AST_CXXABI_H |
||||
|
||||
#include "clang/AST/Type.h" |
||||
|
||||
namespace clang { |
||||
|
||||
class ASTContext; |
||||
class MemberPointerType; |
||||
|
||||
/// Implements C++ ABI-specific semantic analysis functions.
|
||||
class CXXABI { |
||||
public: |
||||
virtual ~CXXABI(); |
||||
|
||||
/// Returns the size of a member pointer in multiples of the target
|
||||
/// pointer size.
|
||||
virtual unsigned getMemberPointerSize(const MemberPointerType *MPT) const = 0; |
||||
|
||||
/// Returns the default calling convention for C++ methods.
|
||||
virtual CallingConv getDefaultMethodCallConv() const = 0; |
||||
|
||||
// Returns whether the given class is nearly empty, with just virtual pointers
|
||||
// and no data except possibly virtual bases.
|
||||
virtual bool isNearlyEmpty(const CXXRecordDecl *RD) const = 0; |
||||
}; |
||||
|
||||
/// Creates an instance of a C++ ABI class.
|
||||
CXXABI *CreateARMCXXABI(ASTContext &Ctx); |
||||
CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); |
||||
CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,203 @@
@@ -0,0 +1,203 @@
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
// clix.hpp (from http://blog.nuclex-games.com/mono-dotnet/cxx-cli-string-marshaling)
|
||||
//
|
||||
// Marshals strings between .NET and C++ using C++/CLI (Visual C++ 2005 and later only).
|
||||
// Faster and cleaner than the System::Interop method because it uses garbage collected memory.
|
||||
// Use at your own leisure. No warranties whatsoever provided.
|
||||
//
|
||||
// Original code by Markus Ewald
|
||||
// Updated version including several improvements suggested by Neil Hunt
|
||||
//
|
||||
// Licensed under the IBM CPL (free of charge, closed source commercial use is okay)
|
||||
// ------------------------------------------------------------------------------------------- //
|
||||
#pragma once |
||||
|
||||
#include <string> |
||||
#include <vcclr.h> |
||||
|
||||
// CLI extensions namespace
|
||||
namespace clix { |
||||
|
||||
/// <summary>Encoding types for strings</summary>
|
||||
enum Encoding { |
||||
|
||||
/// <summary>ANSI encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the default encoding you've most likely been using all around in C++. ANSI
|
||||
/// means 8 Bit encoding with character codes depending on the system's selected code page.
|
||||
/// <remarks>
|
||||
E_ANSI, |
||||
|
||||
/// <summary>UTF-8 encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the encoding commonly used for multilingual C++ strings. All ASCII characters
|
||||
/// (0-127) will be represented as single bytes. Be aware that UTF-8 uses more than one
|
||||
/// byte for extended characters, so std::string::length() might not reflect the actual
|
||||
/// length of the string in characters if it contains any non-ASCII characters.
|
||||
/// <remarks>
|
||||
E_UTF8, |
||||
|
||||
/// <summary>UTF-16 encoding</summary>
|
||||
/// <remarks>
|
||||
/// This is the suggested to be used for marshaling and the native encoding of .NET
|
||||
/// strings. It is similar to UTF-8 but uses a minimum of two bytes per character, making
|
||||
/// the number of bytes required for a given string better predictable. Be aware, however,
|
||||
/// that UTF-16 can still use more than two bytes for a character, so std::wstring::length()
|
||||
/// might not reflect the actual length of the string.
|
||||
/// </remarks>
|
||||
E_UTF16, E_UNICODE = E_UTF16 |
||||
|
||||
}; |
||||
|
||||
// Ignore this if you're just scanning the headers for informations!
|
||||
/* All this template stuff might seem like overkill, but it is well thought out and enables
|
||||
you to use a readable and convenient call while still keeping the highest possible code |
||||
efficiency due to compile-time evaluation of the required conversion path. |
||||
*/ |
||||
namespace detail { |
||||
|
||||
// Get C++ string type for specified encoding
|
||||
template<Encoding encoding> struct StringTypeSelector; |
||||
template<> struct StringTypeSelector<E_ANSI> { typedef std::string Type; }; |
||||
template<> struct StringTypeSelector<E_UTF8> { typedef std::string Type; }; |
||||
template<> struct StringTypeSelector<E_UTF16> { typedef std::wstring Type; }; |
||||
|
||||
// Compile-time selection depending on whether a string is managed
|
||||
template<typename StringType> struct IfManaged { |
||||
struct Select { |
||||
template<typename TrueType, typename FalseType> |
||||
struct Either { typedef FalseType Type; }; |
||||
}; |
||||
enum { Result = false }; |
||||
}; |
||||
template<> struct IfManaged<System::String ^> { |
||||
struct Select { |
||||
template<typename TrueType, typename FalseType> |
||||
struct Either { typedef TrueType Type; }; |
||||
}; |
||||
enum { Result = true }; |
||||
}; |
||||
|
||||
// Direction of the marshaling process
|
||||
enum MarshalingDirection { |
||||
CxxFromNet, |
||||
NetFromCxx |
||||
}; |
||||
|
||||
// The actual marshaling code
|
||||
template<MarshalingDirection direction> struct StringMarshaler; |
||||
|
||||
// Marshals to .NET from C++ strings
|
||||
template<> struct StringMarshaler<NetFromCxx> { |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static System::String ^marshal(const SourceType &string) { |
||||
// Constructs a std::[w]string in case someone gave us a char * to choke on
|
||||
return marshalCxxString<encoding, SourceType>(string); |
||||
} |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static System::String ^marshalCxxString( |
||||
const typename StringTypeSelector<encoding>::Type &cxxString |
||||
) { |
||||
typedef typename StringTypeSelector<encoding>::Type SourceStringType; |
||||
size_t byteCount = cxxString.length() * sizeof(SourceStringType::value_type); |
||||
|
||||
if(byteCount == 0) return System::String::Empty; |
||||
|
||||
// Copy the C++ string contents into a managed array of bytes
|
||||
array<unsigned char> ^bytes = gcnew array<unsigned char>(byteCount); |
||||
{ pin_ptr<unsigned char> pinnedBytes = &bytes[0]; |
||||
memcpy(pinnedBytes, cxxString.c_str(), byteCount); |
||||
} |
||||
|
||||
// Now let one of .NET's encoding classes do the rest
|
||||
return decode<encoding>(bytes); |
||||
} |
||||
|
||||
private: |
||||
// Converts a byte array based on the selected encoding
|
||||
template<Encoding encoding> static System::String ^decode(array<unsigned char> ^bytes); |
||||
template<> static System::String ^decode<E_ANSI>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::Default->GetString(bytes); |
||||
} |
||||
template<> static System::String ^decode<E_UTF8>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::UTF8->GetString(bytes); |
||||
} |
||||
template<> static System::String ^decode<E_UTF16>(array<unsigned char> ^bytes) { |
||||
return System::Text::Encoding::Unicode->GetString(bytes); |
||||
} |
||||
}; |
||||
|
||||
// Marshals to C++ strings from .NET
|
||||
template<> struct StringMarshaler<CxxFromNet> { |
||||
|
||||
template<Encoding encoding, typename SourceType> |
||||
static typename detail::StringTypeSelector<encoding>::Type marshal( |
||||
System::String ^string |
||||
) { |
||||
typedef typename StringTypeSelector<encoding>::Type StringType; |
||||
|
||||
// First, we use .NET's encoding classes to convert the string into a byte array
|
||||
array<unsigned char> ^bytes = encode<encoding>(string); |
||||
|
||||
if(bytes->Length == 0) return StringType(); |
||||
|
||||
// Then we construct our native string from that byte array
|
||||
pin_ptr<unsigned char> pinnedBytes(&bytes[0]); |
||||
return StringType( |
||||
reinterpret_cast<StringType::value_type *>(static_cast<unsigned char *>(pinnedBytes)), |
||||
bytes->Length / sizeof(StringType::value_type) |
||||
); |
||||
} |
||||
|
||||
template<> static std::wstring marshal<E_UTF16, System::String ^>( |
||||
System::String ^string |
||||
) { |
||||
// We can directly accesss the characters in the managed string
|
||||
pin_ptr<const wchar_t> pinnedChars(::PtrToStringChars(string)); |
||||
return std::wstring(pinnedChars, string->Length); |
||||
} |
||||
|
||||
private: |
||||
// Converts a string based on the selected encoding
|
||||
template<Encoding encoding> static array<unsigned char> ^encode(System::String ^string); |
||||
template<> static array<unsigned char> ^encode<E_ANSI>(System::String ^string) { |
||||
return System::Text::Encoding::Default->GetBytes(string); |
||||
} |
||||
template<> static array<unsigned char> ^encode<E_UTF8>(System::String ^string) { |
||||
return System::Text::Encoding::UTF8->GetBytes(string); |
||||
} |
||||
template<> static array<unsigned char> ^encode<E_UTF16>(System::String ^string) { |
||||
return System::Text::Encoding::Unicode->GetBytes(string); |
||||
} |
||||
|
||||
}; |
||||
|
||||
} // namespace detail
|
||||
|
||||
// ----------------------------------------------------------------------------------------- //
|
||||
// clix::marshalString()
|
||||
// ----------------------------------------------------------------------------------------- //
|
||||
/// <summary>Marshals strings between .NET managed and C++ native</summary>
|
||||
/// <remarks>
|
||||
/// This all-in-one function marshals native C++ strings to .NET strings and vice versa.
|
||||
/// You have to specify an encoding to use for the conversion, which always applies to the
|
||||
/// native C++ string as .NET always uses UTF-16 for its own strings.
|
||||
/// </remarks>
|
||||
/// <param name="string">String to be marshalled to the other side</param>
|
||||
/// <returns>The marshaled representation of the string</returns>
|
||||
template<Encoding encoding, typename SourceType> |
||||
typename detail::IfManaged<SourceType>::Select::Either< |
||||
typename detail::StringTypeSelector<encoding>::Type, |
||||
System::String ^ |
||||
>::Type marshalString(SourceType string) { |
||||
|
||||
// Pass on the call to our nifty template routines
|
||||
return detail::StringMarshaler< |
||||
detail::IfManaged<SourceType>::Result ? detail::CxxFromNet : detail::NetFromCxx |
||||
>::marshal<encoding, SourceType>(string); |
||||
|
||||
} |
||||
|
||||
} // namespace clix
|
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
/************************************************************************
|
||||
* |
||||
* Flush3D <http://www.flush3d.com> © (2008-201x)
|
||||
* Licensed under the LGPL 2.1 (GNU Lesser General Public License) |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#include "Parser.h" |
||||
#include "Interop.h" |
||||
|
||||
public ref class ClangParser |
||||
{ |
||||
public: |
||||
|
||||
static bool Parse(ParserOptions^ Opts) |
||||
{ |
||||
if (!Opts->FileName) return false; |
||||
|
||||
using namespace clix; |
||||
std::string File = marshalString<E_UTF8>(Opts->FileName); |
||||
|
||||
Parser p(Opts); |
||||
return p.Parse(File); |
||||
} |
||||
}; |
@ -0,0 +1,897 @@
@@ -0,0 +1,897 @@
|
||||
/************************************************************************
|
||||
* |
||||
* Flush3D <http://www.flush3d.com> © (2008-201x)
|
||||
* Licensed under the LGPL 2.1 (GNU Lesser General Public License) |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#include "Parser.h" |
||||
|
||||
#include <llvm/Support/Path.h> |
||||
#include <clang/Basic/Version.h> |
||||
#include <clang/Config/config.h> |
||||
#include "clang/AST/ASTContext.h" |
||||
#include "clang/Lex/HeaderSearch.h" |
||||
#include <clang/Lex/PreprocessingRecord.h> |
||||
#include "clang/Frontend/HeaderSearchOptions.h" |
||||
#include <clang/Frontend/Utils.h> |
||||
#include <clang/Driver/Util.h> |
||||
|
||||
#include "Interop.h" |
||||
#include <string> |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Parser::Parser(ParserOptions^ Opts) : Lib(Opts->Library) |
||||
{ |
||||
Setup(Opts); |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static std::string GetClangResourceDir(const std::string& Dir) |
||||
{ |
||||
using namespace llvm; |
||||
using namespace clang; |
||||
|
||||
// Compute the path to the resource directory.
|
||||
StringRef ClangResourceDir(CLANG_RESOURCE_DIR); |
||||
|
||||
SmallString<128> P(Dir); |
||||
|
||||
if (ClangResourceDir != "") |
||||
llvm::sys::path::append(P, ClangResourceDir); |
||||
else |
||||
llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING); |
||||
|
||||
return P.str(); |
||||
} |
||||
|
||||
static std::string GetClangBuiltinIncludeDir() |
||||
{ |
||||
using namespace llvm; |
||||
|
||||
SmallString<128> P( GetClangResourceDir(".") ); |
||||
llvm::sys::path::append(P, "include"); |
||||
|
||||
return P.str(); |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
void Parser::Setup(ParserOptions^ Opts) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
const char* args[] = |
||||
{ |
||||
// Enable C++ language mode
|
||||
"-xc++", "-std=c++11", "-fno-rtti", |
||||
// Enable the Microsoft parsing extensions
|
||||
"-fms-extensions", "-fms-compatibility", "-fdelayed-template-parsing", |
||||
// Enable the Microsoft ABI
|
||||
//"-Xclang", "-cxx-abi", "-Xclang", "microsoft"
|
||||
}; |
||||
|
||||
C.reset(new CompilerInstance()); |
||||
C->createDiagnostics(ARRAY_SIZE(args), args); |
||||
|
||||
CompilerInvocation* Inv = new CompilerInvocation(); |
||||
CompilerInvocation::CreateFromArgs(*Inv, |
||||
args, args + ARRAY_SIZE(args), C->getDiagnostics()); |
||||
C->setInvocation(Inv); |
||||
|
||||
TargetOptions& TO = Inv->getTargetOpts(); |
||||
TO.Triple = llvm::sys::getDefaultTargetTriple(); |
||||
|
||||
TargetInfo* TI = TargetInfo::CreateTargetInfo(C->getDiagnostics(), TO); |
||||
TI->setCXXABI(CXXABI_Microsoft); |
||||
C->setTarget(TI); |
||||
|
||||
C->createFileManager(); |
||||
C->createSourceManager(C->getFileManager()); |
||||
|
||||
if (Opts->Verbose) |
||||
C->getHeaderSearchOpts().Verbose = true; |
||||
|
||||
// Initialize the default platform headers.
|
||||
std::string ResourceDir = GetClangResourceDir("."); |
||||
C->getHeaderSearchOpts().ResourceDir = ResourceDir; |
||||
C->getHeaderSearchOpts().AddPath(GetClangBuiltinIncludeDir(), |
||||
clang::frontend::System, false, false, true); |
||||
|
||||
#ifdef _WIN32 |
||||
std::vector<std::string> SystemDirs = clang::driver::GetWindowsSystemIncludeDirs(); |
||||
clang::HeaderSearchOptions& HSOpts = C->getHeaderSearchOpts(); |
||||
|
||||
for(size_t i = 0; i < SystemDirs.size(); ++i) { |
||||
HSOpts.AddPath(SystemDirs[i], frontend::System, false, false, true); |
||||
} |
||||
#endif |
||||
|
||||
C->createPreprocessor(); |
||||
C->createASTContext(); |
||||
|
||||
if (C->hasPreprocessor()) |
||||
{ |
||||
Preprocessor& P = C->getPreprocessor(); |
||||
P.createPreprocessingRecord(false /*RecordConditionals*/); |
||||
P.getBuiltinInfo().InitializeBuiltins(P.getIdentifierTable(), P.getLangOpts()); |
||||
} |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
std::string Parser::GetDeclMangledName(clang::Decl* D, clang::TargetCXXABI ABI) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
if(!D || !isa<NamedDecl>(D)) |
||||
return ""; |
||||
|
||||
bool CanMangle = isa<FunctionDecl>(D) || isa<VarDecl>(D) |
||||
|| isa<CXXConstructorDecl>(D) || isa<CXXDestructorDecl>(D); |
||||
|
||||
if (!CanMangle) return ""; |
||||
|
||||
NamedDecl* ND = cast<NamedDecl>(D); |
||||
llvm::OwningPtr<MangleContext> MC; |
||||
|
||||
switch(ABI) |
||||
{ |
||||
default: |
||||
llvm_unreachable("Unknown mangling ABI"); |
||||
break; |
||||
case CXXABI_Itanium: |
||||
MC.reset(createItaniumMangleContext(*AST, AST->getDiagnostics())); |
||||
//AST->setCXXABI(CreateItaniumCXXABI(*AST));
|
||||
break; |
||||
case CXXABI_Microsoft: |
||||
MC.reset(createMicrosoftMangleContext(*AST, AST->getDiagnostics())); |
||||
//AST->setCXXABI(CreateMicrosoftCXXABI(*AST));
|
||||
break; |
||||
} |
||||
|
||||
std::string Mangled; |
||||
llvm::raw_string_ostream Out(Mangled); |
||||
|
||||
if (!MC->shouldMangleDeclName(ND)) |
||||
{ |
||||
IdentifierInfo *II = ND->getIdentifier(); |
||||
return II->getName(); |
||||
} |
||||
|
||||
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(ND)) |
||||
MC->mangleCXXCtor(CD, Ctor_Base, Out); |
||||
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(ND)) |
||||
MC->mangleCXXDtor(DD, Dtor_Base, Out); |
||||
else if (const BlockDecl *BD = dyn_cast<BlockDecl>(ND)) |
||||
MC->mangleBlock(BD, Out); |
||||
else |
||||
MC->mangleName(ND, Out); |
||||
|
||||
Out.flush(); |
||||
|
||||
// Strip away LLVM name marker.
|
||||
if(!Mangled.empty() && Mangled[0] == '\01') |
||||
Mangled = Mangled.substr(1); |
||||
|
||||
return Mangled; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static std::string GetTagDeclName(const clang::TagDecl* D) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
if (const IdentifierInfo *II = D->getIdentifier()) |
||||
return II->getName(); |
||||
else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) |
||||
{ |
||||
assert(Typedef->getIdentifier() && "Typedef without identifier?"); |
||||
return Typedef->getIdentifier()->getName(); |
||||
} |
||||
else |
||||
return D->getNameAsString(); |
||||
|
||||
assert(0 && "Expected to have a name"); |
||||
return std::string(); |
||||
} |
||||
|
||||
std::string Parser::GetTypeBindName(const clang::Type* Type) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
if(Type->isAnyPointerType() || Type->isReferenceType()) |
||||
Type = Type->getPointeeType().getTypePtr(); |
||||
|
||||
if(Type->isEnumeralType() || Type->isRecordType()) |
||||
{ |
||||
const clang::TagType* Tag = Type->getAs<clang::TagType>(); |
||||
return GetTagDeclName(Tag->getDecl()); |
||||
} |
||||
|
||||
PrintingPolicy pp(C->getLangOpts()); |
||||
pp.SuppressTagKeyword = true; |
||||
//pp.SuppressSpecifiers = true;
|
||||
|
||||
std::string TypeName; |
||||
QualType::getAsStringInternal(Type, Qualifiers(), TypeName, pp); |
||||
|
||||
return std::string(); |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Class^ Parser::WalkRecordCXX(clang::CXXRecordDecl* Record) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
if (Record->isAnonymousStructOrUnion()) |
||||
return nullptr; |
||||
|
||||
auto RC = gcnew Cxxi::Class(); |
||||
RC->Name = marshalString<E_UTF8>(GetTagDeclName(Record)); |
||||
RC->IsPOD = Record->isPOD(); |
||||
|
||||
// Iterate through the record ctors.
|
||||
for(auto it = Record->ctor_begin(); it != Record->ctor_end(); ++it) |
||||
{ |
||||
CXXMethodDecl* Ctor = (*it); |
||||
Cxxi::Method^ Method = WalkMethodCXX(Ctor); |
||||
RC->Methods->Add(Method); |
||||
} |
||||
|
||||
// Iterate through the record methods.
|
||||
for(auto it = Record->method_begin(); it != Record->method_end(); ++it) |
||||
{ |
||||
CXXMethodDecl* M = (*it); |
||||
|
||||
if( isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M) ) |
||||
continue; |
||||
|
||||
Cxxi::Method^ Method = WalkMethodCXX(M); |
||||
RC->Methods->Add(Method); |
||||
} |
||||
|
||||
// Iterate through the record fields.
|
||||
for(auto it = Record->field_begin(); it != Record->field_end(); ++it) |
||||
{ |
||||
FieldDecl* FD = (*it); |
||||
Cxxi::Field^ Field = WalkFieldCXX(FD); |
||||
RC->Fields->Add(Field); |
||||
} |
||||
|
||||
// Get the record layout information.
|
||||
const ASTRecordLayout& Layout = C->getASTContext().getASTRecordLayout(Record); |
||||
//Debug("Size: %I64d\n", Layout.getSize().getQuantity());
|
||||
|
||||
return RC; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Method^ Parser::WalkMethodCXX(clang::CXXMethodDecl* Method) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
DeclarationName MethodName = Method->getDeclName(); |
||||
|
||||
Debug("Method: %s\n", MethodName.getAsString().c_str()); |
||||
|
||||
// Write the return type.
|
||||
QualType Return = Method->getResultType(); |
||||
|
||||
for(auto it = Method->param_begin(); it != Method->param_end(); ++it) |
||||
{ |
||||
ParmVarDecl* Parm = (*it); |
||||
|
||||
QualType ParmType = Parm->getType(); |
||||
std::string ParmTypeName = GetTypeBindName(ParmType.getTypePtr()); |
||||
|
||||
Debug("\tParameter: %s %s\n", |
||||
ParmTypeName.c_str(), Parm->getName().str().c_str()); |
||||
} |
||||
|
||||
std::string Mangled = GetDeclMangledName(Method, CXXABI_Microsoft); |
||||
Debug("\tMangling: %s\n", Mangled.c_str()); |
||||
|
||||
return nullptr; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static Cxxi::AccessSpecifier ConvertToAccess(clang::AccessSpecifier AS) |
||||
{ |
||||
switch(AS) |
||||
{ |
||||
case clang::AS_private: |
||||
return Cxxi::AccessSpecifier::Private; |
||||
case clang::AS_protected: |
||||
return Cxxi::AccessSpecifier::Protected; |
||||
case clang::AS_public: |
||||
return Cxxi::AccessSpecifier::Public; |
||||
} |
||||
|
||||
return Cxxi::AccessSpecifier::Public; |
||||
} |
||||
|
||||
Cxxi::Field^ Parser::WalkFieldCXX(clang::FieldDecl* FD) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
Cxxi::Field^ F = gcnew Cxxi::Field(); |
||||
F->Name = marshalString<E_UTF8>(FD->getName()); |
||||
F->Type = ConvertTypeToCLR(FD->getType()); |
||||
F->Access = ConvertToAccess(FD->getAccess()); |
||||
|
||||
HandleComments(FD, F); |
||||
|
||||
return F; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static Cxxi::PrimitiveType ConvertBuiltinTypeToCLR(const clang::BuiltinType* Builtin) |
||||
{ |
||||
using namespace Cxxi; |
||||
|
||||
assert(Builtin && "Expected a builtin type"); |
||||
|
||||
switch(Builtin->getKind()) |
||||
{ |
||||
case clang::BuiltinType::Void: return PrimitiveType::Void; |
||||
case clang::BuiltinType::Bool: return PrimitiveType::Bool; |
||||
|
||||
case clang::BuiltinType::SChar: |
||||
case clang::BuiltinType::Char_S: return PrimitiveType::Int8; |
||||
|
||||
case clang::BuiltinType::UChar: |
||||
case clang::BuiltinType::Char_U: return PrimitiveType::UInt8; |
||||
|
||||
case clang::BuiltinType::WChar_S: |
||||
case clang::BuiltinType::WChar_U: return PrimitiveType::WideChar; |
||||
|
||||
case clang::BuiltinType::Short: return PrimitiveType::Int16; |
||||
case clang::BuiltinType::UShort: return PrimitiveType::UInt16; |
||||
|
||||
case clang::BuiltinType::Int: return PrimitiveType::Int32; |
||||
case clang::BuiltinType::UInt: return PrimitiveType::UInt32; |
||||
|
||||
case clang::BuiltinType::Long: return PrimitiveType::Int32; |
||||
case clang::BuiltinType::ULong: return PrimitiveType::UInt32; |
||||
|
||||
case clang::BuiltinType::LongLong: return PrimitiveType::Int64; |
||||
case clang::BuiltinType::ULongLong: return PrimitiveType::UInt64; |
||||
|
||||
case clang::BuiltinType::Float: return PrimitiveType::Float; |
||||
case clang::BuiltinType::Double: return PrimitiveType::Double; |
||||
|
||||
case clang::BuiltinType::NullPtr: return PrimitiveType::Null; |
||||
|
||||
default: break; |
||||
} |
||||
|
||||
return PrimitiveType::Null; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Type^ Parser::ConvertTypeToCLR(clang::QualType QualType) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
if (QualType.isNull()) |
||||
return nullptr; |
||||
|
||||
clang::QualType Desugared = QualType.getDesugaredType(*AST); |
||||
|
||||
if (Desugared.isNull()) |
||||
return nullptr; |
||||
|
||||
const clang::Type* Type = QualType.getTypePtr(); |
||||
assert(Type && "Expected a valid type"); |
||||
|
||||
switch(Type->getTypeClass()) |
||||
{ |
||||
case Type::Builtin: |
||||
{ |
||||
auto Builtin = Type->getAs<clang::BuiltinType>(); |
||||
assert(Builtin && "Expected a builtin type"); |
||||
|
||||
auto BT = gcnew Cxxi::BuiltinType(); |
||||
BT->Type = ConvertBuiltinTypeToCLR(Builtin); |
||||
|
||||
return BT; |
||||
} |
||||
case Type::Enum: |
||||
{ |
||||
auto ET = Type->getAs<clang::EnumType>(); |
||||
const EnumDecl* ED = ET->getDecl(); |
||||
|
||||
// Assume that the type has already been defined for now.
|
||||
String Name(GetTagDeclName(ED)); |
||||
auto E = Lib->FindEnum(marshalString<E_UTF8>(Name)); |
||||
|
||||
auto TT = gcnew Cxxi::TagType(); |
||||
TT->Declaration = E; |
||||
|
||||
return TT; |
||||
} |
||||
case Type::Pointer: |
||||
{ |
||||
auto Pointer = Type->getAs<clang::PointerType>(); |
||||
|
||||
auto P = gcnew Cxxi::PointerType(); |
||||
P->Modifier = Cxxi::PointerType::TypeModifier::Pointer; |
||||
P->Pointee = ConvertTypeToCLR(Pointer->getPointeeType()); |
||||
|
||||
return P; |
||||
} |
||||
case Type::Typedef: |
||||
{ |
||||
auto TT = Type->getAs<clang::TypedefType>(); |
||||
const TypedefNameDecl* TND = TT->getDecl(); |
||||
|
||||
return ConvertTypeToCLR(TND->getUnderlyingType()); |
||||
} |
||||
case Type::Elaborated: |
||||
{ |
||||
auto ET = Type->getAs<clang::ElaboratedType>(); |
||||
return ConvertTypeToCLR(ET->getNamedType()); |
||||
} |
||||
case Type::Record: |
||||
{ |
||||
auto RT = Type->getAs<clang::RecordType>(); |
||||
const RecordDecl* RD = RT->getDecl(); |
||||
|
||||
// Assume that the type has already been defined for now.
|
||||
String Name(GetTagDeclName(RD)); |
||||
auto D = Lib->FindClass(marshalString<E_UTF8>(Name)); |
||||
|
||||
auto TT = gcnew Cxxi::TagType(); |
||||
TT->Declaration = D; |
||||
|
||||
return TT; |
||||
} |
||||
case Type::Paren: |
||||
{ |
||||
auto PT = Type->getAs<clang::ParenType>(); |
||||
return ConvertTypeToCLR(PT->getInnerType()); |
||||
} |
||||
case Type::ConstantArray: |
||||
{ |
||||
auto AT = AST->getAsConstantArrayType(QualType); |
||||
|
||||
auto A = gcnew Cxxi::ArrayType(); |
||||
A->Type = ConvertTypeToCLR(AT->getElementType()); |
||||
A->SizeType = Cxxi::ArrayType::ArraySize::Constant; |
||||
A->Size = AST->getConstantArrayElementCount(AT); |
||||
|
||||
return A; |
||||
} |
||||
case Type::FunctionProto: |
||||
{ |
||||
auto FP = Type->getAs<clang::FunctionProtoType>(); |
||||
|
||||
auto F = gcnew Cxxi::FunctionType(); |
||||
F->ReturnType = ConvertTypeToCLR(FP->getResultType()); |
||||
|
||||
return F; |
||||
} |
||||
case Type::TypeOf: |
||||
{ |
||||
auto TO = Type->getAs<clang::TypeOfType>(); |
||||
return ConvertTypeToCLR(TO->getUnderlyingType()); |
||||
} |
||||
case Type::TypeOfExpr: |
||||
{ |
||||
auto TO = Type->getAs<clang::TypeOfExprType>(); |
||||
return ConvertTypeToCLR(TO->getUnderlyingExpr()->getType()); |
||||
} |
||||
default: |
||||
{ |
||||
Debug("Unhandled type class '%s'\n", Type->getTypeClassName()); |
||||
return nullptr; |
||||
} } |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Enumeration^ Parser::WalkEnum(clang::EnumDecl* ED) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
auto E = gcnew Cxxi::Enumeration(); |
||||
E->Name = marshalString<E_UTF8>(GetTagDeclName(ED)); |
||||
|
||||
if (ED->isScoped()) |
||||
E->Modifiers |= Cxxi::Enumeration::EnumModifiers::Scoped; |
||||
|
||||
// Get the underlying integer backing the enum.
|
||||
QualType IntType = ED->getIntegerType(); |
||||
E->Type = safe_cast<Cxxi::BuiltinType^>(ConvertTypeToCLR(IntType)); |
||||
|
||||
for(auto it = ED->enumerator_begin(); it != ED->enumerator_end(); ++it) |
||||
{ |
||||
EnumConstantDecl* ECD = (*it); |
||||
|
||||
std::string BriefText; |
||||
if (const RawComment* Comment = AST->getRawCommentForAnyRedecl(ECD)) |
||||
BriefText = Comment->getBriefText(*AST); |
||||
|
||||
auto EnumItem = gcnew Cxxi::Enumeration::Item(); |
||||
EnumItem->Name = marshalString<E_UTF8>(ECD->getNameAsString()); |
||||
EnumItem->Value = (int) ECD->getInitVal().getLimitedValue(); |
||||
EnumItem->Comment = marshalString<E_UTF8>(BriefText); |
||||
//EnumItem->ExplicitValue = ECD->getExplicitValue();
|
||||
|
||||
E->AddItem(EnumItem); |
||||
} |
||||
|
||||
return E; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Function^ Parser::WalkFunction(clang::FunctionDecl* FD) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
auto F = gcnew Cxxi::Function(); |
||||
F->Name = marshalString<E_UTF8>(FD->getNameAsString()); |
||||
F->IsVariadic = FD->isVariadic(); |
||||
F->IsInline = FD->isInlined(); |
||||
F->CallingConvention = Cxxi::CallingConvention::Default; |
||||
F->ReturnType = ConvertTypeToCLR(FD->getResultType()); |
||||
|
||||
for(auto it = FD->param_begin(); it != FD->param_end(); ++it) |
||||
{ |
||||
ParmVarDecl* VD = (*it); |
||||
|
||||
auto P = gcnew Cxxi::Parameter(); |
||||
P->Name = marshalString<E_UTF8>(VD->getNameAsString()); |
||||
P->Type = ConvertTypeToCLR(VD->getType()); |
||||
P->HasDefaultValue = VD->hasDefaultArg(); |
||||
|
||||
F->Parameters->Add(P); |
||||
} |
||||
|
||||
return F; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
static bool IsUserLocation(clang::SourceManager& SM, clang::SourceLocation Loc) |
||||
{ |
||||
auto Kind = SM.getFileCharacteristic(Loc); |
||||
return Kind == clang::SrcMgr::C_User; |
||||
} |
||||
|
||||
bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
SourceManager& SM = C->getSourceManager(); |
||||
PresumedLoc PLoc = SM.getPresumedLoc(Loc); |
||||
|
||||
// Igore built in declarations.
|
||||
if(PLoc.isInvalid() || !strcmp(PLoc.getFilename(), "<built-in>")) |
||||
return false; |
||||
|
||||
// Also ignore declarations that come from system headers.
|
||||
if (!IsUserLocation(SM, Loc)) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
void Parser::WalkAST() |
||||
{ |
||||
using namespace clang; |
||||
|
||||
if (C->hasPreprocessor()) |
||||
{ |
||||
Preprocessor& P = C->getPreprocessor(); |
||||
PreprocessingRecord* PR = P.getPreprocessingRecord(); |
||||
assert(PR && "Expected a valid preprocessing record"); |
||||
|
||||
WalkMacros(PR); |
||||
} |
||||
|
||||
TranslationUnitDecl* TU = AST->getTranslationUnitDecl(); |
||||
|
||||
for(auto it = TU->decls_begin(); it != TU->decls_end(); ++it) |
||||
{ |
||||
Decl* D = (*it); |
||||
WalkDeclaration(D); |
||||
} |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
Cxxi::Module^ Parser::GetModule(clang::SourceLocation Loc) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
SourceManager& SM = C->getSourceManager(); |
||||
StringRef File = SM.getFilename(Loc); |
||||
|
||||
return Lib->FindOrCreateModule(marshalString<E_UTF8>(File)); |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
void Parser::WalkMacros(clang::PreprocessingRecord* PR) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
Preprocessor& P = C->getPreprocessor(); |
||||
|
||||
for(auto it = PR->begin(); it != PR->end(); ++it) |
||||
{ |
||||
const PreprocessedEntity* PE = (*it); |
||||
|
||||
switch(PE->getKind()) |
||||
{ |
||||
case PreprocessedEntity::MacroDefinitionKind: |
||||
{ |
||||
const MacroDefinition* MD = cast<MacroDefinition>(PE); |
||||
|
||||
if (!IsValidDeclaration(MD->getLocation())) |
||||
break; |
||||
|
||||
const IdentifierInfo* II = MD->getName(); |
||||
assert(II && "Expected valid identifier info"); |
||||
|
||||
MacroInfo* MI = P.getMacroInfo((IdentifierInfo*)II); |
||||
|
||||
if (!MI || MI->isBuiltinMacro() || MI->isFunctionLike()) |
||||
continue; |
||||
|
||||
SourceManager& SM = C->getSourceManager(); |
||||
const LangOptions &LangOpts = C->getLangOpts(); |
||||
|
||||
auto Loc = MI->getDefinitionLoc(); |
||||
|
||||
if (!IsUserLocation(SM, Loc)) |
||||
break; |
||||
|
||||
SourceLocation BeginExpr = |
||||
Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts); |
||||
|
||||
auto Range = CharSourceRange::getTokenRange( |
||||
BeginExpr, MI->getDefinitionEndLoc()); |
||||
|
||||
bool Invalid; |
||||
StringRef Expression = Lexer::getSourceText(Range, SM, LangOpts, &Invalid); |
||||
|
||||
if (Invalid || Expression.empty()) |
||||
break; |
||||
|
||||
auto macro = gcnew Cxxi::MacroDefine(); |
||||
macro->Name = marshalString<E_UTF8>(II->getName())->Trim(); |
||||
macro->Expression = marshalString<E_UTF8>(Expression)->Trim(); |
||||
|
||||
auto M = GetModule(BeginExpr); |
||||
M->Macros->Add(macro); |
||||
|
||||
break; |
||||
} |
||||
default: break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
void Parser::HandleComments(clang::Decl* D, Cxxi::Declaration^ Decl) |
||||
{ |
||||
using namespace clang; |
||||
using namespace clix; |
||||
|
||||
// Get the declaration comment.
|
||||
std::string BriefText; |
||||
if (const RawComment* Comment = AST->getRawCommentForAnyRedecl(D)) |
||||
BriefText = Comment->getBriefText(*AST); |
||||
|
||||
Decl->BriefComment = marshalString<E_UTF8>(BriefText); |
||||
|
||||
SourceManager& SM = C->getSourceManager(); |
||||
const LangOptions& LangOpts = C->getLangOpts(); |
||||
|
||||
auto Range = CharSourceRange::getTokenRange(D->getSourceRange()); |
||||
|
||||
bool Invalid; |
||||
StringRef DeclText = Lexer::getSourceText(Range, SM, LangOpts, &Invalid); |
||||
assert(!Invalid && "Should have a valid location"); |
||||
|
||||
Decl->DebugText = marshalString<E_UTF8>(DeclText); |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
void Parser::WalkDeclaration(clang::Decl* D) |
||||
{ |
||||
using namespace clang; |
||||
|
||||
if (!IsValidDeclaration(D->getLocation())) |
||||
return; |
||||
|
||||
if(NamedDecl* ND = dyn_cast<NamedDecl>(D)) |
||||
{ |
||||
const char* KindName = D->getDeclKindName(); |
||||
|
||||
DeclarationName DN = ND->getDeclName(); |
||||
std::string DeclName = DN.getAsString(); |
||||
|
||||
//Debug("(%s) %s\n", KindName, DeclName.c_str());
|
||||
|
||||
std::string Mangled = GetDeclMangledName(ND, CXXABI_Microsoft); |
||||
} |
||||
|
||||
for(auto it = D->attr_begin(); it != D->attr_end(); ++it) |
||||
{ |
||||
Attr* Attr = (*it); |
||||
|
||||
if(Attr->getKind() != clang::attr::Annotate) |
||||
continue; |
||||
|
||||
AnnotateAttr* Annotation = cast<AnnotateAttr>(Attr); |
||||
assert(Annotation != nullptr); |
||||
|
||||
StringRef AnnotationText = Annotation->getAnnotation(); |
||||
} |
||||
|
||||
using namespace clix; |
||||
|
||||
switch(D->getKind()) |
||||
{ |
||||
case Decl::CXXRecord: |
||||
{ |
||||
CXXRecordDecl* RD = cast<CXXRecordDecl>(D); |
||||
if (!RD->isThisDeclarationADefinition()) |
||||
break; |
||||
|
||||
auto Class = WalkRecordCXX(RD); |
||||
HandleComments(RD, Class); |
||||
|
||||
auto M = GetModule(RD->getLocation()); |
||||
M->Global->Classes->Add(Class); |
||||
|
||||
break; |
||||
} |
||||
case Decl::Enum: |
||||
{ |
||||
EnumDecl* ED = cast<EnumDecl>(D); |
||||
if (!ED->isThisDeclarationADefinition()) |
||||
break; |
||||
|
||||
auto E = WalkEnum(ED); |
||||
HandleComments(ED, E); |
||||
|
||||
auto M = GetModule(ED->getLocation()); |
||||
M->Global->Enums->Add(E); |
||||
|
||||
break; |
||||
} |
||||
case Decl::Function: |
||||
{ |
||||
FunctionDecl* FD = cast<FunctionDecl>(D); |
||||
if (!FD->isFirstDeclaration()) |
||||
break; |
||||
|
||||
auto F = WalkFunction(FD); |
||||
HandleComments(FD, F); |
||||
|
||||
auto M = GetModule(FD->getLocation()); |
||||
M->Global->Functions->Add(F); |
||||
|
||||
break; |
||||
} |
||||
case Decl::LinkageSpec: |
||||
{ |
||||
LinkageSpecDecl* LS = cast<LinkageSpecDecl>(D); |
||||
|
||||
for (auto it = LS->decls_begin(); it != LS->decls_end(); ++it) |
||||
{ |
||||
Decl* D = (*it); |
||||
WalkDeclaration(D); |
||||
} |
||||
|
||||
break; |
||||
} |
||||
case Decl::Typedef: |
||||
{ |
||||
TypedefDecl* TD = cast<TypedefDecl>(D); |
||||
|
||||
const QualType& Type = TD->getUnderlyingType(); |
||||
std::string Name = GetTypeBindName(Type.getTypePtr()); |
||||
|
||||
if (Type->isBuiltinType()) |
||||
break; |
||||
|
||||
#if 0 |
||||
// If we have a type name for a previously unnamed type,
|
||||
// then use this name as the name of the original type.
|
||||
|
||||
if(auto CType = ConvertTypeToCLR(Type)) |
||||
CType->Name = marshalString<E_UTF8>(Name); |
||||
#endif |
||||
|
||||
break; |
||||
} |
||||
case Decl::Namespace: |
||||
{ |
||||
NamespaceDecl* ND = cast<NamespaceDecl>(D); |
||||
|
||||
for (auto it = ND->decls_begin(); it != ND->decls_end(); ++it) |
||||
{ |
||||
Decl* D = (*it); |
||||
WalkDeclaration(D); |
||||
} |
||||
|
||||
break; |
||||
} |
||||
default: |
||||
{ |
||||
Debug("Unhandled declaration kind: %s\n", D->getDeclKindName()); |
||||
//assert(0 && "Unhandled declaration kind");
|
||||
break; |
||||
} }; |
||||
} |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
struct ParseConsumer : public clang::ASTConsumer |
||||
{ |
||||
virtual ~ParseConsumer() { } |
||||
virtual bool HandleTopLevelDecl(clang::DeclGroupRef) { return true; } |
||||
}; |
||||
|
||||
bool Parser::Parse(const std::string& File) |
||||
{ |
||||
if (File.empty()) |
||||
return false; |
||||
|
||||
C->setASTConsumer(new ParseConsumer()); |
||||
|
||||
// Get the file from the file system
|
||||
const clang::FileEntry* file = C->getFileManager().getFile(File.c_str()); |
||||
|
||||
if (!file) |
||||
{ |
||||
Debug("Filename '%s' was not found." |
||||
"Check your compiler paths.\n", File.c_str()); |
||||
return false; |
||||
} |
||||
|
||||
C->getSourceManager().createMainFileID(file); |
||||
|
||||
clang::DiagnosticConsumer* client = C->getDiagnostics().getClient(); |
||||
client->BeginSourceFile(C->getLangOpts(), &C->getPreprocessor()); |
||||
ParseAST(C->getPreprocessor(), &C->getASTConsumer(), C->getASTContext()); |
||||
client->EndSourceFile(); |
||||
|
||||
if(client->getNumErrors() != 0) |
||||
{ |
||||
// We had some errors while parsing the file.
|
||||
// Report this...
|
||||
return false; |
||||
} |
||||
|
||||
AST = &C->getASTContext(); |
||||
WalkAST(); |
||||
|
||||
return true; |
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/************************************************************************
|
||||
* |
||||
* Flush3D <http://www.flush3d.com> © (2008-201x)
|
||||
* Licensed under the LGPL 2.1 (GNU Lesser General Public License) |
||||
* |
||||
************************************************************************/ |
||||
|
||||
#include <llvm/Support/Host.h> |
||||
#include <clang/Frontend/CompilerInstance.h> |
||||
#include <clang/Frontend/CompilerInvocation.h> |
||||
#include <clang/Frontend/ASTConsumers.h> |
||||
#include <clang/Basic/FileManager.h> |
||||
#include <clang/Basic/TargetOptions.h> |
||||
#include <clang/Basic/TargetInfo.h> |
||||
#include <clang/Basic/IdentifierTable.h> |
||||
#include <clang/AST/ASTConsumer.h> |
||||
#include <clang/AST/Mangle.h> |
||||
#include <clang/AST/RecordLayout.h> |
||||
#include <clang/Lex/Preprocessor.h> |
||||
#include <clang/Parse/ParseAST.h> |
||||
#include <clang/Sema/Sema.h> |
||||
#include "CXXABI.h" |
||||
|
||||
#include <string> |
||||
#include <cstdarg> |
||||
|
||||
#using <Bridge.dll> |
||||
#include <vcclr.h> |
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) |
||||
#define Debug printf |
||||
|
||||
public ref struct ParserOptions |
||||
{ |
||||
// C/C++ header file name.
|
||||
System::String^ FileName; |
||||
|
||||
Cxxi::Library^ Library; |
||||
|
||||
bool Verbose; |
||||
}; |
||||
|
||||
struct Parser |
||||
{ |
||||
Parser(ParserOptions^ Opts); |
||||
|
||||
void Setup(ParserOptions^ Opts); |
||||
bool Parse(const std::string& File); |
||||
|
||||
protected: |
||||
|
||||
// AST traversers
|
||||
void WalkAST(); |
||||
void WalkDeclaration(clang::Decl* D); |
||||
void WalkMacros(clang::PreprocessingRecord* PR); |
||||
Cxxi::Enumeration^ WalkEnum(clang::EnumDecl*); |
||||
Cxxi::Function^ WalkFunction(clang::FunctionDecl*); |
||||
Cxxi::Class^ WalkRecordCXX(clang::CXXRecordDecl*); |
||||
Cxxi::Method^ WalkMethodCXX(clang::CXXMethodDecl*); |
||||
Cxxi::Field^ WalkFieldCXX(clang::FieldDecl*); |
||||
|
||||
// Clang helpers
|
||||
bool IsValidDeclaration(const clang::SourceLocation& Loc); |
||||
std::string GetDeclMangledName(clang::Decl*, clang::TargetCXXABI); |
||||
std::string GetTypeBindName(const clang::Type*); |
||||
Cxxi::Module^ GetModule(clang::SourceLocation Loc); |
||||
Cxxi::Type^ ConvertTypeToCLR(clang::QualType QualType); |
||||
void HandleComments(clang::Decl* D, Cxxi::Declaration^); |
||||
|
||||
gcroot<Cxxi::Library^> Lib; |
||||
llvm::OwningPtr<clang::CompilerInstance> C; |
||||
clang::ASTContext* AST; |
||||
}; |
||||
|
||||
//-----------------------------------//
|
||||
|
||||
typedef std::string String; |
||||
|
||||
String StringFormatArgs(const char* str, va_list args); |
||||
String StringFormat(const char* str, ...); |
Loading…
Reference in new issue