mirror of https://github.com/mono/CppSharp.git
Browse Source
I benchmarked it and it's about the same speed in Release mode (maybe a bit faster) but 3x slower in VS Debug mode due to all the STL usage.pull/72/merge
9 changed files with 4117 additions and 0 deletions
@ -0,0 +1,260 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the MIT license. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#include "AST.h" |
||||||
|
#include <algorithm> |
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
|
||||||
|
template<typename T> |
||||||
|
static std::vector<T> split(const T & str, const T & delimiters) { |
||||||
|
std::vector<T> v; |
||||||
|
T::size_type start = 0; |
||||||
|
auto pos = str.find_first_of(delimiters, start); |
||||||
|
while(pos != T::npos) { |
||||||
|
if(pos != start) // ignore empty tokens
|
||||||
|
v.emplace_back(str, start, pos - start); |
||||||
|
start = pos + 1; |
||||||
|
pos = str.find_first_of(delimiters, start); |
||||||
|
} |
||||||
|
if(start < str.length()) // ignore trailing delimiter
|
||||||
|
// add what's left of the string
|
||||||
|
v.emplace_back(str, start, str.length() - start); |
||||||
|
return v; |
||||||
|
} |
||||||
|
|
||||||
|
namespace CppSharp { namespace CppParser { |
||||||
|
|
||||||
|
Declaration* DeclarationContext::FindAnonymous(uint64_t key) |
||||||
|
{ |
||||||
|
auto it = Anonymous.find(key); |
||||||
|
return (it != Anonymous.end()) ? it->second : 0; |
||||||
|
} |
||||||
|
|
||||||
|
Namespace* DeclarationContext::FindNamespace(const std::string& Name) |
||||||
|
{ |
||||||
|
auto namespaces = split<std::string>(Name, "::"); |
||||||
|
return FindNamespace(namespaces); |
||||||
|
} |
||||||
|
|
||||||
|
Namespace* |
||||||
|
DeclarationContext::FindNamespace(const std::vector<std::string>& Namespaces) |
||||||
|
{ |
||||||
|
auto currentNamespace = this; |
||||||
|
for (auto I = Namespaces.begin(), E = Namespaces.end(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto& _namespace = *I; |
||||||
|
|
||||||
|
auto childNamespace = std::find_if(currentNamespace->Namespaces.begin(), |
||||||
|
currentNamespace->Namespaces.end(), |
||||||
|
[&](CppSharp::CppParser::Namespace* ns) { |
||||||
|
return ns->Name == _namespace; |
||||||
|
}); |
||||||
|
|
||||||
|
if (childNamespace == currentNamespace->Namespaces.end()) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
currentNamespace = *childNamespace; |
||||||
|
} |
||||||
|
|
||||||
|
return (CppSharp::CppParser::Namespace*) currentNamespace; |
||||||
|
} |
||||||
|
|
||||||
|
Namespace* DeclarationContext::FindCreateNamespace(const std::string& Name) |
||||||
|
{ |
||||||
|
auto _namespace = FindNamespace(Name); |
||||||
|
|
||||||
|
if (!_namespace) |
||||||
|
{ |
||||||
|
_namespace = new Namespace(); |
||||||
|
_namespace->Name = Name; |
||||||
|
_namespace->_Namespace = this; |
||||||
|
|
||||||
|
Namespaces.push_back(_namespace); |
||||||
|
} |
||||||
|
|
||||||
|
return _namespace; |
||||||
|
} |
||||||
|
|
||||||
|
Class* DeclarationContext::FindClass(const std::string& Name) |
||||||
|
{ |
||||||
|
if (Name.empty()) return nullptr; |
||||||
|
|
||||||
|
auto entries = split<std::string>(Name, "::"); |
||||||
|
|
||||||
|
if (entries.size() == 1) |
||||||
|
{ |
||||||
|
auto _class = std::find_if(Classes.begin(), Classes.end(), |
||||||
|
[&](Class* klass) { return klass->Name == Name; }); |
||||||
|
|
||||||
|
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 _namespace = FindNamespace(namespaces); |
||||||
|
if (!_namespace) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
return _namespace->FindClass(className); |
||||||
|
} |
||||||
|
|
||||||
|
Class* DeclarationContext::CreateClass(std::string Name, bool IsComplete) |
||||||
|
{ |
||||||
|
auto _class = new Class(); |
||||||
|
_class->Name = Name; |
||||||
|
_class->_Namespace = this; |
||||||
|
_class->IsIncomplete = !IsComplete; |
||||||
|
|
||||||
|
return _class; |
||||||
|
} |
||||||
|
|
||||||
|
Class* DeclarationContext::FindClass(const std::string& Name, bool IsComplete, |
||||||
|
bool Create) |
||||||
|
{ |
||||||
|
auto _class = FindClass(Name); |
||||||
|
|
||||||
|
if (!_class) |
||||||
|
{ |
||||||
|
if (Create) |
||||||
|
{ |
||||||
|
_class = CreateClass(Name, IsComplete); |
||||||
|
Classes.push_back(_class); |
||||||
|
} |
||||||
|
|
||||||
|
return _class; |
||||||
|
} |
||||||
|
|
||||||
|
if (_class->IsIncomplete == !IsComplete) |
||||||
|
return _class; |
||||||
|
|
||||||
|
if (!Create) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
auto newClass = CreateClass(Name, IsComplete); |
||||||
|
|
||||||
|
// Replace the incomplete declaration with the complete one.
|
||||||
|
if (_class->IsIncomplete) |
||||||
|
{ |
||||||
|
_class->CompleteDeclaration = newClass; |
||||||
|
|
||||||
|
std::replace_if(Classes.begin(), Classes.end(), |
||||||
|
[&](Class* klass) { return klass == _class; }, newClass); |
||||||
|
} |
||||||
|
|
||||||
|
return newClass; |
||||||
|
} |
||||||
|
|
||||||
|
Enumeration* DeclarationContext::FindEnum(const std::string& Name, bool Create) |
||||||
|
{ |
||||||
|
if (Name.empty()) return nullptr; |
||||||
|
|
||||||
|
auto entries = split<std::string>(Name, "::"); |
||||||
|
|
||||||
|
if (entries.size() == 1) |
||||||
|
{ |
||||||
|
auto foundEnum = std::find_if(Enums.begin(), Enums.end(), |
||||||
|
[&](Enumeration* _enum) { return _enum->Name == Name; }); |
||||||
|
|
||||||
|
if (foundEnum != Enums.end()) |
||||||
|
return *foundEnum; |
||||||
|
|
||||||
|
if (!Create) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
auto _enum = new Enumeration(); |
||||||
|
_enum->Name = Name; |
||||||
|
_enum->_Namespace = this; |
||||||
|
Enums.push_back(_enum); |
||||||
|
return _enum; |
||||||
|
} |
||||||
|
|
||||||
|
auto enumName = entries[entries.size() - 1]; |
||||||
|
|
||||||
|
std::vector<std::string> namespaces; |
||||||
|
std::copy_n(entries.begin(), entries.size() - 1, std::back_inserter(namespaces)); |
||||||
|
|
||||||
|
auto _namespace = FindNamespace(namespaces); |
||||||
|
if (!_namespace) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
return _namespace->FindEnum(enumName, Create); |
||||||
|
} |
||||||
|
|
||||||
|
Function* DeclarationContext::FindFunction(const std::string& Name, bool Create) |
||||||
|
{ |
||||||
|
auto foundFunction = std::find_if(Functions.begin(), Functions.end(), |
||||||
|
[&](Function* func) { return func->Name == Name; }); |
||||||
|
|
||||||
|
if (foundFunction != Functions.end()) |
||||||
|
return *foundFunction; |
||||||
|
|
||||||
|
if (!Create) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
auto function = new Function(); |
||||||
|
function->Name = Name; |
||||||
|
function->_Namespace = this; |
||||||
|
Functions.push_back(function); |
||||||
|
|
||||||
|
return function; |
||||||
|
} |
||||||
|
|
||||||
|
TypedefDecl* DeclarationContext::FindTypedef(const std::string& Name, bool Create) |
||||||
|
{ |
||||||
|
auto foundTypedef = std::find_if(Typedefs.begin(), Typedefs.end(), |
||||||
|
[&](TypedefDecl* tdef) { return tdef->Name == Name; }); |
||||||
|
|
||||||
|
if (foundTypedef != Typedefs.end()) |
||||||
|
return *foundTypedef; |
||||||
|
|
||||||
|
if (!Create) |
||||||
|
return nullptr; |
||||||
|
|
||||||
|
auto tdef = new TypedefDecl(); |
||||||
|
tdef->Name = Name; |
||||||
|
tdef->_Namespace = this; |
||||||
|
Typedefs.push_back(tdef); |
||||||
|
|
||||||
|
return tdef; |
||||||
|
} |
||||||
|
|
||||||
|
TranslationUnit* Library::FindOrCreateModule(const std::string& File) |
||||||
|
{ |
||||||
|
auto existingUnit = std::find_if(TranslationUnits.begin(), |
||||||
|
TranslationUnits.end(), [&](TranslationUnit* unit) { |
||||||
|
return unit && unit->FileName == File; |
||||||
|
}); |
||||||
|
|
||||||
|
if (existingUnit != TranslationUnits.end()) |
||||||
|
return *existingUnit; |
||||||
|
|
||||||
|
auto unit = new TranslationUnit(); |
||||||
|
unit->FileName = File; |
||||||
|
TranslationUnits.push_back(unit); |
||||||
|
|
||||||
|
return unit; |
||||||
|
} |
||||||
|
|
||||||
|
NativeLibrary* Library::FindOrCreateLibrary(const std::string& File) |
||||||
|
{ |
||||||
|
auto existingLib = std::find_if(Libraries.begin(), |
||||||
|
Libraries.end(), [&](NativeLibrary* lib) { |
||||||
|
return lib && lib->FileName == File; |
||||||
|
}); |
||||||
|
|
||||||
|
auto lib = new NativeLibrary(); |
||||||
|
lib->FileName = File; |
||||||
|
Libraries.push_back(lib); |
||||||
|
|
||||||
|
return lib; |
||||||
|
} |
||||||
|
|
||||||
|
} } |
||||||
@ -0,0 +1,599 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the MIT license. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <cstdint> |
||||||
|
#include <vector> |
||||||
|
#include <map> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
#define CS_FLAGS |
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__) |
||||||
|
#define CS_API __declspec(dllexport) |
||||||
|
#else |
||||||
|
#define CS_API |
||||||
|
#endif |
||||||
|
|
||||||
|
namespace CppSharp { namespace CppParser { |
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
struct CS_API Type |
||||||
|
{ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TypeQualifiers |
||||||
|
{ |
||||||
|
bool IsConst; |
||||||
|
bool IsVolatile; |
||||||
|
bool IsRestrict; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API QualifiedType |
||||||
|
{ |
||||||
|
Type* Type; |
||||||
|
TypeQualifiers Qualifiers; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Declaration; |
||||||
|
|
||||||
|
struct CS_API TagType : public Type |
||||||
|
{ |
||||||
|
Declaration* Declaration; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ArrayType : public Type |
||||||
|
{ |
||||||
|
enum class ArraySize |
||||||
|
{ |
||||||
|
Constant, |
||||||
|
Variable, |
||||||
|
Dependent, |
||||||
|
Incomplete |
||||||
|
}; |
||||||
|
|
||||||
|
QualifiedType QualifiedType; |
||||||
|
ArraySize SizeType; |
||||||
|
long Size; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Parameter; |
||||||
|
|
||||||
|
enum class CallingConvention |
||||||
|
{ |
||||||
|
Default, |
||||||
|
C, |
||||||
|
StdCall, |
||||||
|
ThisCall, |
||||||
|
FastCall, |
||||||
|
Unknown |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API FunctionType : public Type |
||||||
|
{ |
||||||
|
QualifiedType ReturnType; |
||||||
|
std::vector<Parameter*> Parameters; |
||||||
|
CallingConvention CallingConvention; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API PointerType : public Type |
||||||
|
{ |
||||||
|
enum struct TypeModifier |
||||||
|
{ |
||||||
|
Value, |
||||||
|
Pointer, |
||||||
|
LVReference, |
||||||
|
RVReference |
||||||
|
}; |
||||||
|
|
||||||
|
QualifiedType QualifiedPointee; |
||||||
|
TypeModifier Modifier; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API MemberPointerType : public Type |
||||||
|
{ |
||||||
|
QualifiedType Pointee; |
||||||
|
}; |
||||||
|
|
||||||
|
struct TypedefDecl; |
||||||
|
|
||||||
|
struct CS_API TypedefType : public Type |
||||||
|
{ |
||||||
|
TypedefDecl* Declaration; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API DecayedType : public Type |
||||||
|
{ |
||||||
|
QualifiedType Decayed; |
||||||
|
QualifiedType Original; |
||||||
|
QualifiedType Pointee; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TemplateArgument |
||||||
|
{ |
||||||
|
enum struct ArgumentKind |
||||||
|
{ |
||||||
|
Type, |
||||||
|
Declaration, |
||||||
|
NullPtr, |
||||||
|
Integral, |
||||||
|
Template, |
||||||
|
TemplateExpansion, |
||||||
|
Expression, |
||||||
|
Pack |
||||||
|
}; |
||||||
|
|
||||||
|
ArgumentKind Kind; |
||||||
|
QualifiedType Type; |
||||||
|
Declaration* Declaration; |
||||||
|
long Integral; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Template; |
||||||
|
|
||||||
|
struct CS_API TemplateSpecializationType : public Type |
||||||
|
{ |
||||||
|
std::vector<TemplateArgument> Arguments; |
||||||
|
Template* Template; |
||||||
|
Type* Desugared; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TemplateParameter |
||||||
|
{ |
||||||
|
std::string Name; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TemplateParameterType : public Type |
||||||
|
{ |
||||||
|
TemplateParameter Parameter; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TemplateParameterSubstitutionType : public Type |
||||||
|
{ |
||||||
|
QualifiedType Replacement; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Class; |
||||||
|
|
||||||
|
struct CS_API InjectedClassNameType : public Type |
||||||
|
{ |
||||||
|
TemplateSpecializationType TemplateSpecialization; |
||||||
|
Class* Class; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API DependentNameType : public Type |
||||||
|
{ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
enum struct PrimitiveType |
||||||
|
{ |
||||||
|
Null, |
||||||
|
Void, |
||||||
|
Bool, |
||||||
|
WideChar, |
||||||
|
Int8, |
||||||
|
Char = Int8, |
||||||
|
UInt8, |
||||||
|
UChar = UInt8, |
||||||
|
Int16, |
||||||
|
UInt16, |
||||||
|
Int32, |
||||||
|
UInt32, |
||||||
|
Int64, |
||||||
|
UInt64, |
||||||
|
Float, |
||||||
|
Double, |
||||||
|
IntPtr |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API BuiltinType : public Type |
||||||
|
{ |
||||||
|
PrimitiveType Type; |
||||||
|
}; |
||||||
|
|
||||||
|
// Comments
|
||||||
|
|
||||||
|
enum struct RawCommentKind |
||||||
|
{ |
||||||
|
Invalid, |
||||||
|
OrdinaryBCPL, |
||||||
|
OrdinaryC, |
||||||
|
BCPLSlash, |
||||||
|
BCPLExcl, |
||||||
|
JavaDoc, |
||||||
|
Qt, |
||||||
|
Merged |
||||||
|
}; |
||||||
|
|
||||||
|
struct FullComment; |
||||||
|
|
||||||
|
struct CS_API RawComment |
||||||
|
{ |
||||||
|
RawCommentKind Kind; |
||||||
|
std::string Text; |
||||||
|
std::string BriefText; |
||||||
|
FullComment* FullComment; |
||||||
|
}; |
||||||
|
|
||||||
|
// Class layouts
|
||||||
|
|
||||||
|
enum struct VTableComponentKind |
||||||
|
{ |
||||||
|
VCallOffset, |
||||||
|
VBaseOffset, |
||||||
|
OffsetToTop, |
||||||
|
RTTI, |
||||||
|
FunctionPointer, |
||||||
|
CompleteDtorPointer, |
||||||
|
DeletingDtorPointer, |
||||||
|
UnusedFunctionPointer, |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API VTableComponent |
||||||
|
{ |
||||||
|
VTableComponentKind Kind; |
||||||
|
unsigned Offset; |
||||||
|
Declaration* Declaration; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API VTableLayout |
||||||
|
{ |
||||||
|
std::vector<VTableComponent> Components; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API VFTableInfo |
||||||
|
{ |
||||||
|
uint64_t VBTableIndex; |
||||||
|
uint32_t VFPtrOffset; |
||||||
|
uint32_t VFPtrFullOffset; |
||||||
|
VTableLayout Layout; |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct CppAbi |
||||||
|
{ |
||||||
|
Itanium, |
||||||
|
Microsoft, |
||||||
|
ARM |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ClassLayout |
||||||
|
{ |
||||||
|
CppAbi ABI; |
||||||
|
std::vector<VFTableInfo> VFTables; |
||||||
|
VTableLayout Layout; |
||||||
|
bool HasOwnVFPtr; |
||||||
|
long VBPtrOffset; |
||||||
|
int Alignment; |
||||||
|
int Size; |
||||||
|
int DataSize; |
||||||
|
}; |
||||||
|
|
||||||
|
// Declarations
|
||||||
|
|
||||||
|
enum struct MacroLocation |
||||||
|
{ |
||||||
|
Unknown, |
||||||
|
ClassHead, |
||||||
|
ClassBody, |
||||||
|
FunctionHead, |
||||||
|
FunctionParameters, |
||||||
|
FunctionBody, |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct AccessSpecifier |
||||||
|
{ |
||||||
|
Private, |
||||||
|
Protected, |
||||||
|
Public |
||||||
|
}; |
||||||
|
|
||||||
|
struct DeclarationContext; |
||||||
|
struct PreprocessedEntity; |
||||||
|
|
||||||
|
struct CS_API Declaration |
||||||
|
{ |
||||||
|
AccessSpecifier Access; |
||||||
|
DeclarationContext* _Namespace; |
||||||
|
std::string Name; |
||||||
|
RawComment* Comment; |
||||||
|
std::string DebugText; |
||||||
|
bool IsIncomplete; |
||||||
|
bool IsDependent; |
||||||
|
Declaration* CompleteDeclaration; |
||||||
|
unsigned DefinitionOrder; |
||||||
|
std::vector<PreprocessedEntity*> PreprocessedEntities; |
||||||
|
void* OriginalPtr; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Class; |
||||||
|
struct Enumeration; |
||||||
|
struct Function; |
||||||
|
struct TypedefDecl; |
||||||
|
struct Namespace; |
||||||
|
struct Template; |
||||||
|
struct Variable; |
||||||
|
|
||||||
|
struct CS_API DeclarationContext : public Declaration |
||||||
|
{ |
||||||
|
Declaration* FindAnonymous(uint64_t key); |
||||||
|
|
||||||
|
CppSharp::CppParser::Namespace* FindNamespace(const std::string& Name); |
||||||
|
CppSharp::CppParser::Namespace* FindNamespace(const std::vector<std::string>&); |
||||||
|
CppSharp::CppParser::Namespace* FindCreateNamespace(const std::string& Name); |
||||||
|
|
||||||
|
Class* CreateClass(std::string Name, bool IsComplete); |
||||||
|
Class* FindClass(const std::string& Name); |
||||||
|
Class* FindClass(const std::string& Name, bool IsComplete, |
||||||
|
bool Create = false); |
||||||
|
|
||||||
|
Enumeration* FindEnum(const std::string& Name, bool Create = false); |
||||||
|
|
||||||
|
Function* FindFunction(const std::string& Name, bool Create = false); |
||||||
|
|
||||||
|
TypedefDecl* FindTypedef(const std::string& Name, bool Create = false); |
||||||
|
|
||||||
|
std::vector<CppSharp::CppParser::Namespace*> Namespaces; |
||||||
|
std::vector<Enumeration*> Enums; |
||||||
|
std::vector<Function*> Functions; |
||||||
|
std::vector<Class*> Classes; |
||||||
|
std::vector<Template*> Templates; |
||||||
|
std::vector<TypedefDecl*> Typedefs; |
||||||
|
std::vector<Variable*> Variables; |
||||||
|
std::map<uint64_t, Declaration*> Anonymous; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API TypedefDecl : public Declaration |
||||||
|
{ |
||||||
|
QualifiedType QualifiedType; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Parameter : public Declaration |
||||||
|
{ |
||||||
|
Parameter() : IsIndirect(false) {} |
||||||
|
|
||||||
|
QualifiedType QualifiedType; |
||||||
|
bool IsIndirect; |
||||||
|
bool HasDefaultValue; |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct CXXMethodKind |
||||||
|
{ |
||||||
|
Normal, |
||||||
|
Constructor, |
||||||
|
Destructor, |
||||||
|
Conversion, |
||||||
|
Operator, |
||||||
|
UsingDirective |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct CXXOperatorKind |
||||||
|
{ |
||||||
|
None, |
||||||
|
New, |
||||||
|
Delete, |
||||||
|
Array_New, |
||||||
|
Array_Delete, |
||||||
|
Plus, |
||||||
|
Minus, |
||||||
|
Star, |
||||||
|
Slash, |
||||||
|
Percent, |
||||||
|
Caret, |
||||||
|
Amp, |
||||||
|
Pipe, |
||||||
|
Tilde, |
||||||
|
Exclaim, |
||||||
|
Equal, |
||||||
|
Less, |
||||||
|
Greater, |
||||||
|
PlusEqual, |
||||||
|
MinusEqual, |
||||||
|
StarEqual, |
||||||
|
SlashEqual, |
||||||
|
PercentEqual, |
||||||
|
CaretEqual, |
||||||
|
AmpEqual, |
||||||
|
PipeEqual, |
||||||
|
LessLess, |
||||||
|
GreaterGreater, |
||||||
|
LessLessEqual, |
||||||
|
GreaterGreaterEqual, |
||||||
|
EqualEqual, |
||||||
|
ExclaimEqual, |
||||||
|
LessEqual, |
||||||
|
GreaterEqual, |
||||||
|
AmpAmp, |
||||||
|
PipePipe, |
||||||
|
PlusPlus, |
||||||
|
MinusMinus, |
||||||
|
Comma, |
||||||
|
ArrowStar, |
||||||
|
Arrow, |
||||||
|
Call, |
||||||
|
Subscript, |
||||||
|
Conditional |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Function : public Declaration |
||||||
|
{ |
||||||
|
Function() : IsReturnIndirect(false) {} |
||||||
|
|
||||||
|
QualifiedType ReturnType; |
||||||
|
bool IsReturnIndirect; |
||||||
|
|
||||||
|
bool IsVariadic; |
||||||
|
bool IsInline; |
||||||
|
bool IsPure; |
||||||
|
CXXOperatorKind OperatorKind; |
||||||
|
std::string Mangled; |
||||||
|
CallingConvention CallingConvention; |
||||||
|
std::vector<Parameter*> Parameters; |
||||||
|
}; |
||||||
|
|
||||||
|
struct AccessSpecifierDecl; |
||||||
|
|
||||||
|
struct CS_API Method : public Function |
||||||
|
{ |
||||||
|
AccessSpecifierDecl* AccessDecl; |
||||||
|
|
||||||
|
bool IsVirtual; |
||||||
|
bool IsStatic; |
||||||
|
bool IsConst; |
||||||
|
bool IsImplicit; |
||||||
|
bool IsOverride; |
||||||
|
|
||||||
|
CXXMethodKind Kind; |
||||||
|
|
||||||
|
bool IsDefaultConstructor; |
||||||
|
bool IsCopyConstructor; |
||||||
|
bool IsMoveConstructor; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Enumeration : public Declaration |
||||||
|
{ |
||||||
|
struct CS_API Item : public Declaration |
||||||
|
{ |
||||||
|
std::string Name; |
||||||
|
std::string Expression; |
||||||
|
std::string Comment; |
||||||
|
uint64_t Value; |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct CS_FLAGS EnumModifiers |
||||||
|
{ |
||||||
|
Anonymous = 1 << 0, |
||||||
|
Scoped = 1 << 1, |
||||||
|
Flags = 1 << 2, |
||||||
|
}; |
||||||
|
|
||||||
|
EnumModifiers Modifiers; |
||||||
|
Type* Type; |
||||||
|
BuiltinType* BuiltinType; |
||||||
|
std::vector<Item> Items; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Variable : public Declaration |
||||||
|
{ |
||||||
|
std::string Mangled; |
||||||
|
QualifiedType QualifiedType; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API BaseClassSpecifier |
||||||
|
{ |
||||||
|
AccessSpecifier Access; |
||||||
|
bool IsVirtual; |
||||||
|
Type* Type; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Class; |
||||||
|
|
||||||
|
struct CS_API Field : public Declaration |
||||||
|
{ |
||||||
|
QualifiedType QualifiedType; |
||||||
|
AccessSpecifier Access; |
||||||
|
unsigned Offset; |
||||||
|
Class* Class; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
struct CS_API AccessSpecifierDecl : public Declaration |
||||||
|
{ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Class : public DeclarationContext |
||||||
|
{ |
||||||
|
std::vector<BaseClassSpecifier*> Bases; |
||||||
|
std::vector<Field*> Fields; |
||||||
|
std::vector<Method*> Methods; |
||||||
|
std::vector<AccessSpecifierDecl*> Specifiers; |
||||||
|
|
||||||
|
bool IsPOD; |
||||||
|
bool IsAbstract; |
||||||
|
bool IsUnion; |
||||||
|
bool IsDynamic; |
||||||
|
bool IsPolymorphic; |
||||||
|
bool HasNonTrivialDefaultConstructor; |
||||||
|
bool HasNonTrivialCopyConstructor; |
||||||
|
|
||||||
|
ClassLayout Layout; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Template : public Declaration |
||||||
|
{ |
||||||
|
Declaration* TemplatedDecl; |
||||||
|
std::vector<TemplateParameter> Parameters; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ClassTemplate : public Template |
||||||
|
{ |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ClassTemplateSpecialization : public Declaration |
||||||
|
{ |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ClassTemplatePartialSpecialization : public Declaration |
||||||
|
{ |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API FunctionTemplate : public Template |
||||||
|
{ |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Namespace : public DeclarationContext |
||||||
|
{ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API PreprocessedEntity : public Declaration |
||||||
|
{ |
||||||
|
PreprocessedEntity() : Location(MacroLocation::Unknown) {} |
||||||
|
|
||||||
|
MacroLocation Location; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API MacroDefinition : public PreprocessedEntity |
||||||
|
{ |
||||||
|
std::string Expression; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API MacroExpansion : public PreprocessedEntity |
||||||
|
{ |
||||||
|
std::string Text; |
||||||
|
MacroDefinition* Definition; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
struct CS_API TranslationUnit : public Namespace |
||||||
|
{ |
||||||
|
std::string FileName; |
||||||
|
bool IsSystemHeader; |
||||||
|
std::vector<Namespace*> Namespaces; |
||||||
|
std::vector<MacroDefinition*> Macros; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API NativeLibrary |
||||||
|
{ |
||||||
|
std::string FileName; |
||||||
|
std::vector<std::string> Symbols; |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API Library |
||||||
|
{ |
||||||
|
TranslationUnit* FindOrCreateModule(const std::string& File); |
||||||
|
NativeLibrary* FindOrCreateLibrary(const std::string& File); |
||||||
|
|
||||||
|
std::vector<TranslationUnit*> TranslationUnits; |
||||||
|
std::vector<NativeLibrary*> Libraries; |
||||||
|
}; |
||||||
|
|
||||||
|
} } |
||||||
@ -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,283 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the simplified BSD license. All rights reserved. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#include "Parser.h" |
||||||
|
|
||||||
|
#include <clang/AST/ASTContext.h> |
||||||
|
|
||||||
|
using namespace CppSharp::CppParser; |
||||||
|
|
||||||
|
//-----------------------------------//
|
||||||
|
|
||||||
|
static RawCommentKind |
||||||
|
ConvertCommentKind(clang::RawComment::CommentKind Kind) |
||||||
|
{ |
||||||
|
using clang::RawComment; |
||||||
|
|
||||||
|
switch(Kind) |
||||||
|
{ |
||||||
|
case RawComment::RCK_Invalid: return RawCommentKind::Invalid; |
||||||
|
case RawComment::RCK_OrdinaryBCPL: return RawCommentKind::OrdinaryBCPL; |
||||||
|
case RawComment::RCK_OrdinaryC: return RawCommentKind::OrdinaryC; |
||||||
|
case RawComment::RCK_BCPLSlash: return RawCommentKind::BCPLSlash; |
||||||
|
case RawComment::RCK_BCPLExcl: return RawCommentKind::BCPLExcl; |
||||||
|
case RawComment::RCK_JavaDoc: return RawCommentKind::JavaDoc; |
||||||
|
case RawComment::RCK_Qt: return RawCommentKind::Qt; |
||||||
|
case RawComment::RCK_Merged: return RawCommentKind::Merged; |
||||||
|
} |
||||||
|
|
||||||
|
llvm_unreachable("Unknown comment kind"); |
||||||
|
} |
||||||
|
|
||||||
|
RawComment* Parser::WalkRawComment(const clang::RawComment* RC) |
||||||
|
{ |
||||||
|
using namespace clang; |
||||||
|
|
||||||
|
auto &SM = C->getSourceManager(); |
||||||
|
auto Comment = new RawComment(); |
||||||
|
Comment->Kind = ConvertCommentKind(RC->getKind()); |
||||||
|
Comment->Text = RC->getRawText(SM); |
||||||
|
Comment->BriefText = RC->getBriefText(*AST); |
||||||
|
|
||||||
|
return Comment; |
||||||
|
} |
||||||
|
|
||||||
|
#if 0 |
||||||
|
static InlineCommandComment::RenderKind |
||||||
|
ConvertRenderKind(clang::comments::InlineCommandComment::RenderKind Kind) |
||||||
|
{ |
||||||
|
using namespace clang::comments; |
||||||
|
switch(Kind) |
||||||
|
{ |
||||||
|
case InlineCommandComment::RenderNormal: |
||||||
|
return InlineCommandComment::RenderKind::RenderNormal; |
||||||
|
case InlineCommandComment::RenderBold: |
||||||
|
return InlineCommandComment::RenderKind::RenderBold; |
||||||
|
case InlineCommandComment::RenderMonospaced: |
||||||
|
return InlineCommandComment::RenderKind::RenderMonospaced; |
||||||
|
case InlineCommandComment::RenderEmphasized: |
||||||
|
return InlineCommandComment::RenderKind::RenderEmphasized; |
||||||
|
} |
||||||
|
llvm_unreachable("Unknown render kind"); |
||||||
|
} |
||||||
|
|
||||||
|
static ParamCommandComment::PassDirection |
||||||
|
ConvertParamPassDirection(clang::comments::ParamCommandComment::PassDirection Dir) |
||||||
|
{ |
||||||
|
using namespace clang::comments; |
||||||
|
switch(Dir) |
||||||
|
{ |
||||||
|
case ParamCommandComment::In: |
||||||
|
return ParamCommandComment::PassDirection::In; |
||||||
|
case ParamCommandComment::Out: |
||||||
|
return ParamCommandComment::PassDirection::Out; |
||||||
|
case ParamCommandComment::InOut: |
||||||
|
return ParamCommandComment::PassDirection::InOut; |
||||||
|
} |
||||||
|
llvm_unreachable("Unknown parameter pass direction"); |
||||||
|
} |
||||||
|
|
||||||
|
static void HandleBlockCommand(const clang::comments::BlockCommandComment *CK, |
||||||
|
BlockCommandComment^ BC) |
||||||
|
{ |
||||||
|
using namespace clix; |
||||||
|
|
||||||
|
BC->CommandId = CK->getCommandID(); |
||||||
|
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto Arg = BlockCommandComment::Argument(); |
||||||
|
Arg.Text = marshalString<E_UTF8>(CK->getArgText(I)); |
||||||
|
BC->Arguments->Add(Arg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static Comment^ ConvertCommentBlock(clang::comments::Comment* C) |
||||||
|
{ |
||||||
|
using namespace clang; |
||||||
|
using clang::comments::Comment; |
||||||
|
|
||||||
|
using namespace clix; |
||||||
|
using namespace CppSharp::AST; |
||||||
|
|
||||||
|
// This needs to have an underscore else we get an ICE under VS2012.
|
||||||
|
Comment^ _Comment; |
||||||
|
|
||||||
|
switch(C->getCommentKind()) |
||||||
|
{ |
||||||
|
case Comment::BlockCommandCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<const clang::comments::BlockCommandComment>(C); |
||||||
|
auto BC = new BlockCommandComment(); |
||||||
|
_Comment = BC; |
||||||
|
HandleBlockCommand(CK, BC); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::ParamCommandCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::ParamCommandComment>(C); |
||||||
|
auto PC = new ParamCommandComment(); |
||||||
|
_Comment = PC; |
||||||
|
HandleBlockCommand(CK, PC); |
||||||
|
PC->Direction = ConvertParamPassDirection(CK->getDirection()); |
||||||
|
if (CK->isParamIndexValid() && !CK->isVarArgParam()) |
||||||
|
PC->ParamIndex = CK->getParamIndex(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::TParamCommandCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::TParamCommandComment>(C); |
||||||
|
_Comment = new TParamCommandComment(); |
||||||
|
auto TC = new TParamCommandComment(); |
||||||
|
_Comment = TC; |
||||||
|
HandleBlockCommand(CK, TC); |
||||||
|
if (CK->isPositionValid()) |
||||||
|
for (unsigned I = 0, E = CK->getDepth(); I != E; ++I) |
||||||
|
TC->Position->Add(CK->getIndex(I)); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::VerbatimBlockCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::VerbatimBlockComment>(C); |
||||||
|
auto VB = new VerbatimBlockComment(); |
||||||
|
_Comment = VB; |
||||||
|
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto Line = ConvertCommentBlock(*I); |
||||||
|
VB->Lines->Add(dynamic_cast<VerbatimBlockLineComment^>(Line)); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::VerbatimLineCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::VerbatimLineComment>(C); |
||||||
|
auto VL = new VerbatimLineComment(); |
||||||
|
_Comment = VL; |
||||||
|
VL->Text = marshalString<E_UTF8>(CK->getText()); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::ParagraphCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::ParagraphComment>(C); |
||||||
|
auto PC = new ParagraphComment(); |
||||||
|
_Comment = PC; |
||||||
|
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto Content = ConvertCommentBlock(*I); |
||||||
|
PC->Content->Add(dynamic_cast<InlineContentComment^>(Content)); |
||||||
|
} |
||||||
|
PC->IsWhitespace = CK->isWhitespace(); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::FullCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::FullComment>(C); |
||||||
|
auto FC = new FullComment(); |
||||||
|
_Comment = FC; |
||||||
|
for (auto I = CK->child_begin(), E = CK->child_end(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto Content = ConvertCommentBlock(*I); |
||||||
|
FC->Blocks->Add(dynamic_cast<BlockContentComment^>(Content)); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::HTMLStartTagCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::HTMLStartTagComment>(C); |
||||||
|
auto TC = new HTMLStartTagComment(); |
||||||
|
_Comment = TC; |
||||||
|
TC->TagName = marshalString<E_UTF8>(CK->getTagName()); |
||||||
|
for (unsigned I = 0, E = CK->getNumAttrs(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto A = CK->getAttr(I); |
||||||
|
auto Attr = HTMLStartTagComment::Attribute(); |
||||||
|
Attr.Name = marshalString<E_UTF8>(A.Name); |
||||||
|
Attr.Value = marshalString<E_UTF8>(A.Value); |
||||||
|
TC->Attributes->Add(Attr); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::HTMLEndTagCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::HTMLEndTagComment>(C); |
||||||
|
auto TC = new HTMLEndTagComment(); |
||||||
|
_Comment = TC; |
||||||
|
TC->TagName = marshalString<E_UTF8>(CK->getTagName()); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::TextCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::TextComment>(C); |
||||||
|
auto TC = new TextComment(); |
||||||
|
_Comment = TC; |
||||||
|
TC->Text = marshalString<E_UTF8>(CK->getText()); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::InlineCommandCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::InlineCommandComment>(C); |
||||||
|
auto IC = new InlineCommandComment(); |
||||||
|
_Comment = IC; |
||||||
|
IC->Kind = ConvertRenderKind(CK->getRenderKind()); |
||||||
|
for (unsigned I = 0, E = CK->getNumArgs(); I != E; ++I) |
||||||
|
{ |
||||||
|
auto Arg = InlineCommandComment::Argument(); |
||||||
|
Arg.Text = marshalString<E_UTF8>(CK->getArgText(I)); |
||||||
|
IC->Arguments->Add(Arg); |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::VerbatimBlockLineCommentKind: |
||||||
|
{ |
||||||
|
auto CK = cast<clang::comments::VerbatimBlockLineComment>(C); |
||||||
|
auto VL = new VerbatimBlockLineComment(); |
||||||
|
_Comment = VL; |
||||||
|
VL->Text = marshalString<E_UTF8>(CK->getText()); |
||||||
|
break; |
||||||
|
} |
||||||
|
case Comment::NoCommentKind: return nullptr; |
||||||
|
default: |
||||||
|
llvm_unreachable("Unknown comment kind"); |
||||||
|
} |
||||||
|
|
||||||
|
assert(_Comment && "Invalid comment instance"); |
||||||
|
return _Comment; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
void Parser::HandleComments(clang::Decl* D, Declaration* Decl) |
||||||
|
{ |
||||||
|
using namespace clang; |
||||||
|
using namespace clang::comments; |
||||||
|
|
||||||
|
const clang::RawComment* RC = 0; |
||||||
|
if (!(RC = AST->getRawCommentForAnyRedecl(D))) |
||||||
|
return; |
||||||
|
|
||||||
|
auto RawComment = WalkRawComment(RC); |
||||||
|
Decl->Comment = RawComment; |
||||||
|
|
||||||
|
#if 0 |
||||||
|
if (FullComment* FC = RC->parse(*AST, &C->getPreprocessor(), D)) |
||||||
|
{ |
||||||
|
auto CB = static_cast<FullComment^>(ConvertCommentBlock(FC)); |
||||||
|
RawComment->FullComment = CB; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
// Debug Text
|
||||||
|
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");
|
||||||
|
|
||||||
|
if (!Invalid) |
||||||
|
Decl->DebugText = DeclText; |
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the simplified BSD license. All rights reserved. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "AST.h" |
||||||
|
|
||||||
|
namespace CppSharp { namespace CppParser { |
||||||
|
|
||||||
|
struct CS_API ParserOptions |
||||||
|
{ |
||||||
|
ParserOptions() |
||||||
|
{ |
||||||
|
MicrosoftMode = false; |
||||||
|
NoStandardIncludes = false; |
||||||
|
NoBuiltinIncludes = false; |
||||||
|
} |
||||||
|
|
||||||
|
// Include directories
|
||||||
|
std::vector<std::string> IncludeDirs; |
||||||
|
std::vector<std::string> SystemIncludeDirs; |
||||||
|
std::vector<std::string> Defines; |
||||||
|
std::vector<std::string> LibraryDirs; |
||||||
|
|
||||||
|
// C/C++ header file name.
|
||||||
|
std::string FileName; |
||||||
|
|
||||||
|
Library* Library; |
||||||
|
|
||||||
|
int ToolSetToUse; |
||||||
|
std::string TargetTriple; |
||||||
|
|
||||||
|
bool NoStandardIncludes; |
||||||
|
bool NoBuiltinIncludes; |
||||||
|
bool MicrosoftMode; |
||||||
|
CppAbi Abi; |
||||||
|
|
||||||
|
bool Verbose; |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct ParserDiagnosticLevel |
||||||
|
{ |
||||||
|
Ignored, |
||||||
|
Note, |
||||||
|
Warning, |
||||||
|
Error, |
||||||
|
Fatal |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ParserDiagnostic |
||||||
|
{ |
||||||
|
std::string FileName; |
||||||
|
std::string Message; |
||||||
|
ParserDiagnosticLevel Level; |
||||||
|
int LineNumber; |
||||||
|
int ColumnNumber; |
||||||
|
}; |
||||||
|
|
||||||
|
enum struct ParserResultKind |
||||||
|
{ |
||||||
|
Success, |
||||||
|
Error, |
||||||
|
FileNotFound |
||||||
|
}; |
||||||
|
|
||||||
|
struct CS_API ParserResult |
||||||
|
{ |
||||||
|
ParserResultKind Kind; |
||||||
|
Library* Library; |
||||||
|
std::vector<ParserDiagnostic> Diagnostics; |
||||||
|
}; |
||||||
|
|
||||||
|
enum class SourceLocationKind |
||||||
|
{ |
||||||
|
Invalid, |
||||||
|
Builtin, |
||||||
|
CommandLine, |
||||||
|
System, |
||||||
|
User |
||||||
|
}; |
||||||
|
|
||||||
|
class CS_API ClangParser |
||||||
|
{ |
||||||
|
public: |
||||||
|
|
||||||
|
static ParserResult* ParseHeader(ParserOptions* Opts); |
||||||
|
static ParserResult* ParseLibrary(ParserOptions* Opts); |
||||||
|
}; |
||||||
|
|
||||||
|
} } |
||||||
@ -0,0 +1,118 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the simplified BSD license. All rights reserved. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#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/RawCommentList.h> |
||||||
|
#include <clang/AST/Comment.h> |
||||||
|
#include <clang/AST/RecordLayout.h> |
||||||
|
#include <clang/AST/VTableBuilder.h> |
||||||
|
#include <clang/Lex/Preprocessor.h> |
||||||
|
#include <clang/Lex/PreprocessingRecord.h> |
||||||
|
#include <clang/Parse/ParseAST.h> |
||||||
|
#include <clang/Sema/Sema.h> |
||||||
|
#include "CXXABI.h" |
||||||
|
|
||||||
|
#include "CppParser.h" |
||||||
|
|
||||||
|
#include <string> |
||||||
|
typedef std::string String; |
||||||
|
|
||||||
|
namespace clang { |
||||||
|
class TargetCodeGenInfo; |
||||||
|
namespace CodeGen { |
||||||
|
class CodeGenTypes; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#define Debug printf |
||||||
|
|
||||||
|
namespace CppSharp { namespace CppParser { |
||||||
|
|
||||||
|
struct Parser |
||||||
|
{ |
||||||
|
Parser(ParserOptions* Opts); |
||||||
|
|
||||||
|
void SetupHeader(); |
||||||
|
ParserResult* ParseHeader(const std::string& File); |
||||||
|
ParserResult* ParseLibrary(const std::string& File); |
||||||
|
ParserResultKind ParseArchive(llvm::StringRef File, |
||||||
|
llvm::MemoryBuffer *Buffer); |
||||||
|
ParserResultKind ParseSharedLib(llvm::StringRef File, |
||||||
|
llvm::MemoryBuffer *Buffer); |
||||||
|
|
||||||
|
protected: |
||||||
|
|
||||||
|
// AST traversers
|
||||||
|
void WalkAST(); |
||||||
|
void WalkMacros(clang::PreprocessingRecord* PR); |
||||||
|
Declaration* WalkDeclaration(clang::Decl* D, |
||||||
|
bool IgnoreSystemDecls = true, bool CanBeDefinition = false); |
||||||
|
Declaration* WalkDeclarationDef(clang::Decl* D); |
||||||
|
Enumeration* WalkEnum(clang::EnumDecl*); |
||||||
|
Function* WalkFunction(clang::FunctionDecl*, bool IsDependent = false, |
||||||
|
bool AddToNamespace = true); |
||||||
|
Class* WalkRecordCXX(clang::CXXRecordDecl*); |
||||||
|
Method* WalkMethodCXX(clang::CXXMethodDecl*); |
||||||
|
Field* WalkFieldCXX(clang::FieldDecl*, Class*); |
||||||
|
ClassTemplate* Parser::WalkClassTemplate(clang::ClassTemplateDecl*); |
||||||
|
FunctionTemplate* Parser::WalkFunctionTemplate( |
||||||
|
clang::FunctionTemplateDecl*); |
||||||
|
Variable* WalkVariable(clang::VarDecl*); |
||||||
|
RawComment* WalkRawComment(const clang::RawComment*); |
||||||
|
Type* WalkType(clang::QualType, clang::TypeLoc* = 0, |
||||||
|
bool DesugarType = false); |
||||||
|
void WalkVTable(clang::CXXRecordDecl*, Class*); |
||||||
|
VTableLayout WalkVTableLayout(const clang::VTableLayout&); |
||||||
|
VTableComponent WalkVTableComponent(const clang::VTableComponent&); |
||||||
|
|
||||||
|
// Clang helpers
|
||||||
|
SourceLocationKind GetLocationKind(const clang::SourceLocation& Loc); |
||||||
|
bool IsValidDeclaration(const clang::SourceLocation& Loc); |
||||||
|
std::string GetDeclMangledName(clang::Decl*, clang::TargetCXXABI, |
||||||
|
bool IsDependent = false); |
||||||
|
std::string GetTypeName(const clang::Type*); |
||||||
|
void HandleComments(clang::Decl* D, Declaration*); |
||||||
|
void WalkFunction(clang::FunctionDecl* FD, Function* F, |
||||||
|
bool IsDependent = false); |
||||||
|
void HandlePreprocessedEntities(Declaration* Decl, clang::SourceRange sourceRange, |
||||||
|
MacroLocation macroLocation = MacroLocation::Unknown); |
||||||
|
bool GetDeclText(clang::SourceRange, std::string& Text); |
||||||
|
|
||||||
|
TranslationUnit* GetTranslationUnit(clang::SourceLocation Loc, |
||||||
|
SourceLocationKind *Kind = 0); |
||||||
|
TranslationUnit* GetTranslationUnit(const clang::Decl*); |
||||||
|
|
||||||
|
DeclarationContext* GetNamespace(clang::Decl*, clang::DeclContext*); |
||||||
|
DeclarationContext* GetNamespace(clang::Decl*); |
||||||
|
|
||||||
|
clang::CallingConv GetAbiCallConv(clang::CallingConv CC, |
||||||
|
bool IsInstMethod, bool IsVariadic); |
||||||
|
|
||||||
|
void HandleDiagnostics(ParserResult* res); |
||||||
|
|
||||||
|
int Index; |
||||||
|
Library* Lib; |
||||||
|
ParserOptions* Opts; |
||||||
|
llvm::OwningPtr<clang::CompilerInstance> C; |
||||||
|
clang::ASTContext* AST; |
||||||
|
clang::TargetCXXABI::Kind TargetABI; |
||||||
|
clang::TargetCodeGenInfo* CodeGenInfo; |
||||||
|
clang::CodeGen::CodeGenTypes* CodeGenTypes; |
||||||
|
}; |
||||||
|
|
||||||
|
} } |
||||||
@ -0,0 +1,257 @@ |
|||||||
|
/************************************************************************
|
||||||
|
* |
||||||
|
* CppSharp |
||||||
|
* Licensed under the simplified BSD license. All rights reserved. |
||||||
|
* |
||||||
|
************************************************************************/ |
||||||
|
|
||||||
|
#ifdef _MSC_VER |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <vector> |
||||||
|
#include <cctype> |
||||||
|
|
||||||
|
// Include the necessary headers to interface with the Windows registry and
|
||||||
|
// environment.
|
||||||
|
#define WIN32_LEAN_AND_MEAN |
||||||
|
#define NOGDI |
||||||
|
#define NOMINMAX |
||||||
|
#include <Windows.h> |
||||||
|
|
||||||
|
/// \brief Read registry string.
|
||||||
|
/// This also supports a means to look for high-versioned keys by use
|
||||||
|
/// of a $VERSION placeholder in the key path.
|
||||||
|
/// $VERSION in the key path is a placeholder for the version number,
|
||||||
|
/// causing the highest value path to be searched for and used.
|
||||||
|
/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION".
|
||||||
|
/// There can be additional characters in the component. Only the numeric
|
||||||
|
/// characters are compared.
|
||||||
|
static bool getSystemRegistryString(const char *keyPath, const char *valueName, |
||||||
|
char *value, size_t maxLength) { |
||||||
|
HKEY hRootKey = NULL; |
||||||
|
HKEY hKey = NULL; |
||||||
|
const char* subKey = NULL; |
||||||
|
DWORD valueType; |
||||||
|
DWORD valueSize = maxLength - 1; |
||||||
|
long lResult; |
||||||
|
bool returnValue = false; |
||||||
|
|
||||||
|
if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { |
||||||
|
hRootKey = HKEY_CLASSES_ROOT; |
||||||
|
subKey = keyPath + 18; |
||||||
|
} else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { |
||||||
|
hRootKey = HKEY_USERS; |
||||||
|
subKey = keyPath + 11; |
||||||
|
} else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { |
||||||
|
hRootKey = HKEY_LOCAL_MACHINE; |
||||||
|
subKey = keyPath + 19; |
||||||
|
} else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { |
||||||
|
hRootKey = HKEY_CURRENT_USER; |
||||||
|
subKey = keyPath + 18; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
const char *placeHolder = strstr(subKey, "$VERSION"); |
||||||
|
char bestName[256]; |
||||||
|
bestName[0] = '\0'; |
||||||
|
// If we have a $VERSION placeholder, do the highest-version search.
|
||||||
|
if (placeHolder) { |
||||||
|
const char *keyEnd = placeHolder - 1; |
||||||
|
const char *nextKey = placeHolder; |
||||||
|
// Find end of previous key.
|
||||||
|
while ((keyEnd > subKey) && (*keyEnd != '\\')) |
||||||
|
keyEnd--; |
||||||
|
// Find end of key containing $VERSION.
|
||||||
|
while (*nextKey && (*nextKey != '\\')) |
||||||
|
nextKey++; |
||||||
|
size_t partialKeyLength = keyEnd - subKey; |
||||||
|
char partialKey[256]; |
||||||
|
if (partialKeyLength > sizeof(partialKey)) |
||||||
|
partialKeyLength = sizeof(partialKey); |
||||||
|
strncpy(partialKey, subKey, partialKeyLength); |
||||||
|
partialKey[partialKeyLength] = '\0'; |
||||||
|
HKEY hTopKey = NULL; |
||||||
|
lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ, &hTopKey); |
||||||
|
if (lResult == ERROR_SUCCESS) { |
||||||
|
char keyName[256]; |
||||||
|
int bestIndex = -1; |
||||||
|
double bestValue = 0.0; |
||||||
|
DWORD index, size = sizeof(keyName) - 1; |
||||||
|
for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, |
||||||
|
NULL, NULL, NULL) == ERROR_SUCCESS; index++) { |
||||||
|
const char *sp = keyName; |
||||||
|
while (*sp && !isdigit(*sp)) |
||||||
|
sp++; |
||||||
|
if (!*sp) |
||||||
|
continue; |
||||||
|
const char *ep = sp + 1; |
||||||
|
while (*ep && (isdigit(*ep) || (*ep == '.'))) |
||||||
|
ep++; |
||||||
|
char numBuf[32]; |
||||||
|
strncpy(numBuf, sp, sizeof(numBuf) - 1); |
||||||
|
numBuf[sizeof(numBuf) - 1] = '\0'; |
||||||
|
double value = strtod(numBuf, NULL); |
||||||
|
|
||||||
|
// Check if InstallDir key value exists.
|
||||||
|
bool isViableVersion = false; |
||||||
|
|
||||||
|
lResult = RegOpenKeyExA(hTopKey, keyName, 0, KEY_READ, &hKey); |
||||||
|
if (lResult == ERROR_SUCCESS) { |
||||||
|
lResult = RegQueryValueExA(hKey, valueName, NULL, NULL, NULL, NULL); |
||||||
|
if (lResult == ERROR_SUCCESS) |
||||||
|
isViableVersion = true; |
||||||
|
RegCloseKey(hKey); |
||||||
|
} |
||||||
|
|
||||||
|
if (isViableVersion && (value > bestValue)) { |
||||||
|
bestIndex = (int)index; |
||||||
|
bestValue = value; |
||||||
|
strcpy(bestName, keyName); |
||||||
|
goto Out; |
||||||
|
} |
||||||
|
size = sizeof(keyName) - 1; |
||||||
|
} |
||||||
|
Out: |
||||||
|
// If we found the highest versioned key, open the key and get the value.
|
||||||
|
if (bestIndex != -1) { |
||||||
|
// Append rest of key.
|
||||||
|
strncat(bestName, nextKey, sizeof(bestName) - 1); |
||||||
|
bestName[sizeof(bestName) - 1] = '\0'; |
||||||
|
// Open the chosen key path remainder.
|
||||||
|
lResult = RegOpenKeyExA(hTopKey, bestName, 0, KEY_READ, &hKey); |
||||||
|
if (lResult == ERROR_SUCCESS) { |
||||||
|
lResult = RegQueryValueExA(hKey, valueName, NULL, &valueType, |
||||||
|
(LPBYTE)value, &valueSize); |
||||||
|
if (lResult == ERROR_SUCCESS) |
||||||
|
returnValue = true; |
||||||
|
RegCloseKey(hKey); |
||||||
|
} |
||||||
|
} |
||||||
|
RegCloseKey(hTopKey); |
||||||
|
} |
||||||
|
} else { |
||||||
|
lResult = RegOpenKeyExA(hRootKey, subKey, 0, KEY_READ, &hKey); |
||||||
|
if (lResult == ERROR_SUCCESS) { |
||||||
|
lResult = RegQueryValueExA(hKey, valueName, NULL, &valueType, |
||||||
|
(LPBYTE)value, &valueSize); |
||||||
|
if (lResult == ERROR_SUCCESS) |
||||||
|
returnValue = true; |
||||||
|
RegCloseKey(hKey); |
||||||
|
} |
||||||
|
} |
||||||
|
return returnValue; |
||||||
|
} |
||||||
|
|
||||||
|
/// \brief Get Windows SDK installation directory.
|
||||||
|
static bool getWindowsSDKDir(std::string &path) { |
||||||
|
char windowsSDKInstallDir[256]; |
||||||
|
// Try the Windows registry.
|
||||||
|
bool hasSDKDir = getSystemRegistryString( |
||||||
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", |
||||||
|
"InstallationFolder", |
||||||
|
windowsSDKInstallDir, |
||||||
|
sizeof(windowsSDKInstallDir) - 1); |
||||||
|
// If we have both vc80 and vc90, pick version we were compiled with.
|
||||||
|
if (hasSDKDir && windowsSDKInstallDir[0]) { |
||||||
|
path = windowsSDKInstallDir; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// Get Visual Studio installation directory.
|
||||||
|
static bool getVisualStudioDir(std::string &path) { |
||||||
|
// First check the environment variables that vsvars32.bat sets.
|
||||||
|
const char* vcinstalldir = getenv("VCINSTALLDIR"); |
||||||
|
if (vcinstalldir) { |
||||||
|
char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); |
||||||
|
if (p) |
||||||
|
*p = '\0'; |
||||||
|
path = vcinstalldir; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
char vsIDEInstallDir[256]; |
||||||
|
char vsExpressIDEInstallDir[256]; |
||||||
|
// Then try the windows registry.
|
||||||
|
bool hasVCDir = getSystemRegistryString( |
||||||
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", |
||||||
|
"InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); |
||||||
|
bool hasVCExpressDir = getSystemRegistryString( |
||||||
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", |
||||||
|
"InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); |
||||||
|
// If we have both vc80 and vc90, pick version we were compiled with.
|
||||||
|
if (hasVCDir && vsIDEInstallDir[0]) { |
||||||
|
char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); |
||||||
|
if (p) |
||||||
|
*p = '\0'; |
||||||
|
path = vsIDEInstallDir; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { |
||||||
|
char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); |
||||||
|
if (p) |
||||||
|
*p = '\0'; |
||||||
|
path = vsExpressIDEInstallDir; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// Try the environment.
|
||||||
|
const char *vs100comntools = getenv("VS100COMNTOOLS"); |
||||||
|
const char *vs90comntools = getenv("VS90COMNTOOLS"); |
||||||
|
const char *vs80comntools = getenv("VS80COMNTOOLS"); |
||||||
|
const char *vscomntools = NULL; |
||||||
|
|
||||||
|
// Try to find the version that we were compiled with
|
||||||
|
if(false) {} |
||||||
|
#if (_MSC_VER >= 1600) // VC100
|
||||||
|
else if(vs100comntools) { |
||||||
|
vscomntools = vs100comntools; |
||||||
|
} |
||||||
|
#elif (_MSC_VER == 1500) // VC80
|
||||||
|
else if(vs90comntools) { |
||||||
|
vscomntools = vs90comntools; |
||||||
|
} |
||||||
|
#elif (_MSC_VER == 1400) // VC80
|
||||||
|
else if(vs80comntools) { |
||||||
|
vscomntools = vs80comntools; |
||||||
|
} |
||||||
|
#endif |
||||||
|
// Otherwise find any version we can
|
||||||
|
else if (vs100comntools) |
||||||
|
vscomntools = vs100comntools; |
||||||
|
else if (vs90comntools) |
||||||
|
vscomntools = vs90comntools; |
||||||
|
else if (vs80comntools) |
||||||
|
vscomntools = vs80comntools; |
||||||
|
|
||||||
|
if (vscomntools && *vscomntools) { |
||||||
|
const char *p = strstr(vscomntools, "\\Common7\\Tools"); |
||||||
|
path = p ? std::string(vscomntools, p) : vscomntools; |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
std::vector<std::string> GetWindowsSystemIncludeDirs() { |
||||||
|
std::vector<std::string> Paths; |
||||||
|
|
||||||
|
std::string VSDir; |
||||||
|
std::string WindowsSDKDir; |
||||||
|
|
||||||
|
// When built with access to the proper Windows APIs, try to actually find
|
||||||
|
// the correct include paths first.
|
||||||
|
if (getVisualStudioDir(VSDir)) { |
||||||
|
Paths.push_back(VSDir + "\\VC\\include"); |
||||||
|
if (getWindowsSDKDir(WindowsSDKDir)) |
||||||
|
Paths.push_back(WindowsSDKDir + "\\include"); |
||||||
|
else |
||||||
|
Paths.push_back(VSDir + "\\VC\\PlatformSDK\\Include"); |
||||||
|
} |
||||||
|
|
||||||
|
return Paths; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,88 @@ |
|||||||
|
clang_msvc_flags = |
||||||
|
{ |
||||||
|
"/wd4146", "/wd4244", "/wd4800", "/wd4345", |
||||||
|
"/wd4355", "/wd4996", "/wd4624", "/wd4291", |
||||||
|
"/wd4251" |
||||||
|
} |
||||||
|
|
||||||
|
project "CppSharp.CppParser" |
||||||
|
|
||||||
|
kind "SharedLib" |
||||||
|
language "C++" |
||||||
|
SetupNativeProject() |
||||||
|
flags { common_flags } |
||||||
|
|
||||||
|
|
||||||
|
configuration "vs*" |
||||||
|
buildoptions { clang_msvc_flags } |
||||||
|
files { "VSLookup.cpp" } |
||||||
|
|
||||||
|
configuration "*" |
||||||
|
|
||||||
|
files |
||||||
|
{ |
||||||
|
"*.h", |
||||||
|
"*.cpp", |
||||||
|
"*.lua" |
||||||
|
} |
||||||
|
|
||||||
|
includedirs |
||||||
|
{ |
||||||
|
"../../deps/LLVM/include", |
||||||
|
"../../deps/LLVM/build/include", |
||||||
|
"../../deps/LLVM/tools/clang/include", |
||||||
|
"../../deps/LLVM/tools/clang/lib", |
||||||
|
"../../deps/LLVM/build/tools/clang/include" |
||||||
|
} |
||||||
|
|
||||||
|
configuration "Debug" |
||||||
|
libdirs { "../../deps/LLVM/build/lib/Debug" } |
||||||
|
|
||||||
|
configuration "Release" |
||||||
|
libdirs { "../../deps/LLVM/build/lib/RelWithDebInfo" } |
||||||
|
|
||||||
|
configuration "*" |
||||||
|
|
||||||
|
links |
||||||
|
{ |
||||||
|
"clangAnalysis", |
||||||
|
"clangAST", |
||||||
|
"clangBasic", |
||||||
|
"clangCodeGen", |
||||||
|
"clangDriver", |
||||||
|
"clangEdit", |
||||||
|
"clangFrontend", |
||||||
|
"clangLex", |
||||||
|
"clangParse", |
||||||
|
"clangSema", |
||||||
|
"clangSerialization", |
||||||
|
"LLVMAnalysis", |
||||||
|
"LLVMAsmParser", |
||||||
|
"LLVMBitReader", |
||||||
|
"LLVMBitWriter", |
||||||
|
"LLVMCodeGen", |
||||||
|
"LLVMCore", |
||||||
|
"LLVMipa", |
||||||
|
"LLVMipo", |
||||||
|
"LLVMInstCombine", |
||||||
|
"LLVMInstrumentation", |
||||||
|
"LLVMIRReader", |
||||||
|
"LLVMLinker", |
||||||
|
"LLVMMC", |
||||||
|
"LLVMMCParser", |
||||||
|
"LLVMObjCARCOpts", |
||||||
|
"LLVMObject", |
||||||
|
"LLVMOption", |
||||||
|
"LLVMScalarOpts", |
||||||
|
"LLVMSupport", |
||||||
|
"LLVMTarget", |
||||||
|
"LLVMTransformUtils", |
||||||
|
"LLVMVectorize", |
||||||
|
"LLVMX86AsmParser", |
||||||
|
"LLVMX86AsmPrinter", |
||||||
|
"LLVMX86Desc", |
||||||
|
"LLVMX86Info", |
||||||
|
"LLVMX86Utils", |
||||||
|
} |
||||||
|
|
||||||
|
include ("Bindings") |
||||||
Loading…
Reference in new issue