Commit c9e7f4b8 authored by ussrhero's avatar ussrhero
Browse files

fixed getting function prototype

parent 60f7380b
......@@ -25,6 +25,40 @@
using namespace clang;
using namespace clang::tooling;
namespace {
std::string getFunctionNameFromDecl(FunctionDecl* funcDec)
{
SmallString<64> buf;
llvm::raw_svector_ostream stream(buf);
LangOptions lo;
PrintingPolicy pp(lo);
pp.SuppressTagKeyword = true;
pp.MSVCFormatting = true;
funcDec->getNameForDiagnostic(stream, pp, true);
return stream.str();
}
std::string getRecordNameFromDecl(CXXRecordDecl* decl)
{
auto templateSpecialization = llvm::dyn_cast<ClassTemplateSpecializationDecl>(decl);
if (templateSpecialization)
{
SmallString<64> buf;
llvm::raw_svector_ostream stream(buf);
LangOptions lo;
PrintingPolicy pp(lo);
pp.SuppressTagKeyword = true;
pp.MSVCFormatting = true;
templateSpecialization->getNameForDiagnostic(stream, pp, true);
return stream.str();
}
return decl->getQualifiedNameAsString();
}
}
namespace kdlib{
TypeInfoPtr getTypeForClangBuiltinType(const clang::BuiltinType* builtinType)
......@@ -112,9 +146,9 @@ TypeInfoPtr getTypeForClangType( ClangASTSessionPtr& astSession, const clang::Q
if ( qualType->isFunctionProtoType() )
{
const FunctionProtoType* funcType = qualType->getAs<FunctionProtoType>();
auto funcProto = qualType->getAs<FunctionProtoType>();
return TypeInfoPtr( new TypeInfoClangFunc(astSession, funcType) );
return TypeInfoPtr( new TypeInfoClangFuncPrototype(astSession, funcProto) );
}
if ( qualType->isEnumeralType() )
......@@ -185,8 +219,8 @@ TypeInfoPtr TypeFieldClangField::getTypeInfo()
sstr << m_recordDecl->getNameAsString() << "::<unnamed-type-" << wstrToStr(getName()) << '>';
name = sstr.str();
}
return TypeInfoPtr( new TypeInfoClangStruct( strToWStr(name), m_astSession, decl->getDefinition() ) );
return TypeInfoPtr( new TypeInfoClangStruct( strToWStr(name), m_astSession, decl->getDefinition() ) );
}
clang::FieldDecl *fieldDecl = llvm::dyn_cast<clang::FieldDecl>(m_fieldDecl);
......@@ -448,15 +482,16 @@ TypeInfoPtr TypeInfoClangRef::deref()
///////////////////////////////////////////////////////////////////////////////
TypeInfoClangFunc::TypeInfoClangFunc(ClangASTSessionPtr& session, const FunctionProtoType* funcProto)
TypeInfoClangFuncPrototype::TypeInfoClangFuncPrototype(ClangASTSessionPtr& session, const FunctionProtoType* funcProto)
{
m_returnType = getTypeForClangType(session, funcProto->getReturnType());
switch ( funcProto->getCallConv() )
switch (funcProto->getCallConv())
{
case CC_C:
m_callconv = CallConv_NearC;
break;
m_callconv = CallConv_NearC;
break;
case CC_X86StdCall:
m_callconv = CallConv_NearStd;
......@@ -475,9 +510,21 @@ TypeInfoClangFunc::TypeInfoClangFunc(ClangASTSessionPtr& session, const Function
}
for ( clang::FunctionProtoType::param_type_iterator paramIt = funcProto->param_type_begin(); paramIt != funcProto->param_type_end(); paramIt++)
for (clang::FunctionProtoType::param_type_iterator paramIt = funcProto->param_type_begin(); paramIt != funcProto->param_type_end(); paramIt++)
{
m_args.push_back(getTypeForClangType(session, *paramIt));
}
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoClangFunc::TypeInfoClangFunc(ClangASTSessionPtr& session, clang::FunctionDecl* funcDecl) :
TypeInfoClangFuncPrototype(session, funcDecl->getFunctionType()->getAs< FunctionProtoType>() )
{
CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(funcDecl->getDeclContext());
if (parentClassDecl)
{
m_args.push_back( getTypeForClangType(session, *paramIt ) );
auto name = strToWStr(getRecordNameFromDecl(parentClassDecl));
m_classParent = TypeInfoPtr(new TypeInfoClangStruct(name, session, parentClassDecl->getDefinition()));
}
}
......@@ -524,106 +571,6 @@ void TypeInfoClangEnum::getFields()
///////////////////////////////////////////////////////////////////////////////
class DeclNamedVisitor : public RecursiveASTVisitor<DeclNamedVisitor>
{
public:
DeclNamedVisitor(ClangASTSessionPtr& astSession, const std::string& typeName) :
m_session(astSession),
m_typeName(typeName)
{}
bool VisitCXXRecordDecl(CXXRecordDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
const std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
return true;
if ( Declaration->getDefinition() )
m_typeInfo = TypeInfoPtr( new TypeInfoClangStruct( strToWStr(Declaration->getNameAsString()), m_session, Declaration->getDefinition() ) );
else
m_typeInfo = TypeInfoPtr( new TypeInfoClangStructNoDef( strToWStr(Declaration->getNameAsString()), m_session, Declaration ) );
return false;
}
bool VisitTypedefDecl(TypedefDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
const std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
return true;
QualType decl = Declaration->getUnderlyingType().getCanonicalType();
m_typeInfo = getTypeForClangType(m_session, decl);
return false;
}
bool VisitFunctionDecl(FunctionDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
if ( Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind:: TK_FunctionTemplate )
return true;
if ( CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(Declaration->getDeclContext()))
{
if ( parentClassDecl->getDescribedClassTemplate() )
return true;
}
const std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
return true;
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
m_typeInfo = TypeInfoPtr( new TypeInfoClangFunc(m_session, protoType ) );
return false;
}
bool VisitEnumDecl (EnumDecl *Declaration)
{
if ( Declaration->isInvalidDecl() )
return true;
const std::string& name = Declaration->getQualifiedNameAsString();
if ( name != m_typeName)
return true;
m_typeInfo = TypeInfoPtr( new TypeInfoClangEnum(m_session, Declaration) );
return false;
}
TypeInfoPtr getTypeInfo() {
return m_typeInfo;
}
private:
std::string m_typeName;
ClangASTSessionPtr m_session;
TypeInfoPtr m_typeInfo;
};
///////////////////////////////////////////////////////////////////////////////
class DeclNextVisitor : public RecursiveASTVisitor<DeclNextVisitor>
{
......@@ -675,7 +622,6 @@ public:
const std::string &name = Declaration->getQualifiedNameAsString();
(*m_typeMap)[name] = TypeInfoPtr(new TypeInfoClangStructNoDef(strToWStr(name), m_session, Declaration));
}
}
catch (TypeException&)
{
......@@ -723,11 +669,9 @@ public:
return true;
}
std::string name = Declaration->getQualifiedNameAsString();
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
std::string name = getFunctionNameFromDecl(Declaration);
TypeInfoPtr typeInfo = TypeInfoPtr(new TypeInfoClangFunc(m_session, protoType));
TypeInfoPtr typeInfo = TypeInfoPtr(new TypeInfoClangFunc(m_session, Declaration));
(*m_typeMap)[name] = typeInfo;
......@@ -791,16 +735,7 @@ public:
if ( Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind::TK_FunctionTemplate )
return true;
SmallString<64> buf;
llvm::raw_svector_ostream stream(buf);
LangOptions lo;
PrintingPolicy pp(lo);
pp.SuppressTagKeyword = true;
pp.MSVCFormatting = true;
Declaration->getNameForDiagnostic(stream, pp, true);
m_symbols.push_back(stream.str());
m_symbols.push_back(getFunctionNameFromDecl(Declaration));
} catch(TypeException& )
{}
......
......@@ -282,13 +282,27 @@ protected:
const clang::ReferenceType* m_refType;
};
class TypeInfoClangFunc : public TypeInfoFunctionPrototype
class TypeInfoClangFuncPrototype : public TypeInfoFunctionPrototype
{
public:
TypeInfoClangFuncPrototype(ClangASTSessionPtr& session, const clang::FunctionProtoType* functionProtoType);
};
class TypeInfoClangFunc : public TypeInfoClangFuncPrototype
{
public:
TypeInfoClangFunc(ClangASTSessionPtr& session, const clang::FunctionProtoType* funcProto);
TypeInfoClangFunc(ClangASTSessionPtr& session, clang::FunctionDecl* funcDecl);
private:
TypeInfoPtr getClassParent() override
{
return m_classParent;
}
TypeInfoPtr m_classParent;
};
......
......@@ -316,7 +316,7 @@ TEST_F(ClangTest, WindowsH)
TEST_F(ClangTest, NtddkH)
{
std::wstring src = L"#include <ntddk.h>\r\n";
std::wstring opt = L"-I\"C:/Program Files (x86)/Windows Kits/8.1/Include/km\" \
std::wstring opt = L"-I\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.16299.0/km\" \
-I\"C:/Program Files (x86)/Windows Kits/8.1/Include/shared\" \
-D_AMD64_ --target=x86_64-pc-windows-msvc -w";
......@@ -392,48 +392,6 @@ TEST_F(ClangTest, TypeProviderEnum)
}
static const wchar_t template_func_src1[] = L"\
\
template<typename T1, typename T2> \
T1 func(T2 v) { \
return v * 10; \
} \
";
static const wchar_t template_func_src2[] = L"\
\
template<typename T1, typename T2> \
T1 func(T2 v) { \
return v * 10; \
} \
\
template<> \
int func<int,int>(int v); \
";
static const wchar_t template_func_src3[] = L"\
\
template<typename T> \
class Generic { \
\
int intMethod() { \
return 0; \
} \
\
T tMethod() { \
return 0; \
} \
}; \
";
TEST_F(ClangTest, TemplateFunc)
{
EXPECT_THROW(compileType(template_func_src1, L"func"), TypeException );
EXPECT_NO_THROW( compileType(template_func_src2, L"func") );
EXPECT_THROW( compileType(template_func_src3, L"Generic::intMethod"), TypeException );
EXPECT_THROW( compileType(template_func_src3, L"Generic::tMethod"), TypeException );
}
TEST_F(ClangTest, TemplateStruct)
{
......@@ -606,7 +564,7 @@ TEST_F(ClangTest, EnumFuncNames)
char func3(void); \
} \
class testcls { \
voit method(int) \
void method(int); \
}; \
";
......@@ -626,4 +584,41 @@ TEST_F(ClangTest, EnumFuncNames)
L"testns::func3",
L"testcls::method"
}), symbols);
}
\ No newline at end of file
}
TEST_F(ClangTest, Func)
{
static const wchar_t srcCode[] = L" \
void func(int, char); \
inline void func1() {} \
template <int> int func2() { return 0; } \
template<> int func2<2>() { return 1; } \
namespace testns { \
char func3(void); \
} \
class testcls { \
void method(int); \
}; \
template<typename T> \
class testcls1 { \
void method(); \
}; \
template<> \
class testcls1<int> { \
void method(); \
}; \
";
EXPECT_EQ(L"Void(__cdecl)(Int4B, Char)", compileType(srcCode, L"func")->getName());
EXPECT_EQ(L"Void(__cdecl)()", compileType(srcCode, L"func1")->getName());
EXPECT_EQ(L"Int4B(__cdecl)()", compileType(srcCode, L"func2<2>")->getName());
EXPECT_EQ(L"Char(__cdecl)()", compileType(srcCode, L"testns::func3")->getName());
EXPECT_EQ(L"Void(__cdecl testcls::)(Int4B)", compileType(srcCode, L"testcls::method")->getName());
EXPECT_EQ(L"Void(__cdecl testcls1<int>::)()", compileType(srcCode, L"testcls1<int>::method")->getName());
EXPECT_THROW(compileType(srcCode, L"func2"), TypeException);
EXPECT_THROW(compileType(srcCode, L"func3"), TypeException);
EXPECT_THROW(compileType(srcCode, L"method"), TypeException);
EXPECT_THROW(compileType(srcCode, L"testcls1::method"), TypeException);
EXPECT_THROW(compileType(srcCode, L"testcls1<char>::method"), TypeException);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment