Commits (2)
......@@ -180,7 +180,6 @@ typedef boost::shared_ptr<TypeInfoProvider> TypeInfoProviderPtr;
class TypeInfoProvider
{
public:
virtual TypeInfoPtr getTypeByName(const std::wstring& name) = 0;
virtual TypeInfoEnumeratorPtr getTypeEnumerator(const std::wstring& mask = L"") = 0;
};
......@@ -190,11 +189,21 @@ public:
virtual TypeInfoPtr Next() = 0;
};
class SymbolEnumerator {
public:
virtual std::wstring Next() = 0;
};
typedef boost::shared_ptr<SymbolEnumerator> SymbolEnumeratorPtr;
TypeInfoProviderPtr getTypeInfoProviderFromSource( const std::wstring& source, const std::wstring& opts = L"" );
TypeInfoProviderPtr getTypeInfoProviderFromSource(const std::string& source, const std::string& opts = "");
TypeInfoProviderPtr getTypeInfoProviderFromPdb( const std::wstring& pdbFile, MEMOFFSET_64 loadBase = 0 );
TypeInfoProviderPtr getDefaultTypeInfoProvider();
SymbolEnumeratorPtr getSymbolEnumeratorFromSource(const std::wstring& source, const std::wstring& opts = L"");
SymbolEnumeratorPtr getSymbolEnumeratorFromSource(const std::string& source, const std::string& opts = "");
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr makeCharConst(char val);
......
......@@ -624,7 +624,7 @@ private:
///////////////////////////////////////////////////////////////////////////////
class DeclNextVisitor : public RecursiveASTVisitor<DeclNextVisitor>
class DeclNextVisitor : public RecursiveASTVisitor<DeclNextVisitor>
{
public:
......@@ -632,7 +632,7 @@ public:
DeclNextVisitor(ClangASTSessionPtr& astSession, std::map<std::string, TypeInfoPtr>* typeMap) :
m_session(astSession),
m_typeMap(typeMap)
{}
{}
bool VisitCXXRecordDecl(CXXRecordDecl *Declaration)
{
......@@ -672,7 +672,7 @@ public:
}
else
{
std::string name = Declaration->getQualifiedNameAsString();
const std::string &name = Declaration->getQualifiedNameAsString();
(*m_typeMap)[name] = TypeInfoPtr(new TypeInfoClangStructNoDef(strToWStr(name), m_session, Declaration));
}
......@@ -689,7 +689,7 @@ public:
try {
if ( Declaration->isInvalidDecl() )
if (Declaration->isInvalidDecl())
return true;
const std::string& name = Declaration->getQualifiedNameAsString();
......@@ -698,8 +698,10 @@ public:
(*m_typeMap)[name] = getTypeForClangType(m_session, decl);
} catch(TypeException& )
{}
}
catch (TypeException&)
{
}
return true;
}
......@@ -709,15 +711,15 @@ public:
{
try {
if ( Declaration->isInvalidDecl() )
if (Declaration->isInvalidDecl())
return true;
if ( Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind:: TK_FunctionTemplate )
if (Declaration->getTemplatedKind() == FunctionDecl::TemplatedKind::TK_FunctionTemplate)
return true;
if ( CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(Declaration->getDeclContext()))
if (CXXRecordDecl *parentClassDecl = llvm::dyn_cast<CXXRecordDecl>(Declaration->getDeclContext()))
{
if ( parentClassDecl->getDescribedClassTemplate() )
if (parentClassDecl->getDescribedClassTemplate())
return true;
}
......@@ -725,31 +727,35 @@ public:
const FunctionProtoType* protoType = Declaration->getFunctionType()->getAs<FunctionProtoType>();
TypeInfoPtr typeInfo = TypeInfoPtr( new TypeInfoClangFunc(m_session, protoType ) );
TypeInfoPtr typeInfo = TypeInfoPtr(new TypeInfoClangFunc(m_session, protoType));
(*m_typeMap)[name] = typeInfo;
} catch(TypeException& )
{}
}
catch (TypeException&)
{
}
return true;
}
bool VisitEnumDecl (EnumDecl *Declaration)
bool VisitEnumDecl(EnumDecl *Declaration)
{
try {
if ( Declaration->isInvalidDecl() )
try {
if (Declaration->isInvalidDecl())
return true;
std::string name = Declaration->getQualifiedNameAsString();
TypeInfoPtr typeInfo = TypeInfoPtr( new TypeInfoClangEnum(m_session, Declaration) );
TypeInfoPtr typeInfo = TypeInfoPtr(new TypeInfoClangEnum(m_session, Declaration));
(*m_typeMap)[name] = typeInfo;
} catch(TypeException& )
{}
}
catch (TypeException&)
{
}
return true;
}
......@@ -764,6 +770,53 @@ private:
///////////////////////////////////////////////////////////////////////////////
class FuncVisitor : public RecursiveASTVisitor<FuncVisitor>
{
public:
FuncVisitor(ClangASTSessionPtr& astSession, std::vector<std::string>& symbols) :
m_session(astSession),
m_symbols(symbols)
{}
bool VisitFunctionDecl(FunctionDecl *Declaration)
{
try {
if ( Declaration->isInvalidDecl() )
return true;
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());
} catch(TypeException& )
{}
return true;
}
private:
ClangASTSessionPtr m_session;
std::vector<std::string> &m_symbols;
};
///////////////////////////////////////////////////////////////////////////////
size_t ClangASTSession::getPtrSize()
{
const Type* sizeType = getASTContext().getSizeType()->getTypePtr();
......@@ -919,5 +972,84 @@ TypeInfoProviderPtr getTypeInfoProviderFromSource(const std::string& source, c
///////////////////////////////////////////////////////////////////////////////
SymbolEnumeratorClang::SymbolEnumeratorClang(const std::string& sourceCode, const std::string& compileOptions)
{
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
new vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
std::vector< std::string > args;
args.push_back("clang-tool");
args.push_back("-fsyntax-only");
typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
boost::escaped_list_separator<char> Separator('\\', ' ', '\"');
Tokenizer tok(compileOptions, Separator);
std::copy(tok.begin(), tok.end(), std::inserter(args, args.end()));
args.push_back("input.cc");
ToolInvocation toolInvocation(
args,
&Action,
Files.get(),
std::move(std::make_shared< PCHContainerOperations >())
);
InMemoryFileSystem->addFile("input.cc", 0, llvm::MemoryBuffer::getMemBuffer(sourceCode.c_str()));
#ifndef _DEBUG
IgnoringDiagConsumer diagnosticConsumer;
toolInvocation.setDiagnosticConsumer(&diagnosticConsumer);
#endif
toolInvocation.run();
std::unique_ptr<ASTUnit> ast = std::move(ASTs[0]);
auto astSession = ClangASTSession::getASTSession(ast);
FuncVisitor visitor(astSession, m_symbols);
visitor.TraverseDecl(astSession->getASTContext().getTranslationUnitDecl());
}
///////////////////////////////////////////////////////////////////////////////
std::wstring SymbolEnumeratorClang::Next()
{
if (m_index < m_symbols.size())
return strToWStr(m_symbols[m_index++]);
return std::wstring();
}
///////////////////////////////////////////////////////////////////////////////
SymbolEnumeratorPtr getSymbolEnumeratorFromSource(const std::wstring& source, const std::wstring& opts)
{
return SymbolEnumeratorPtr( new SymbolEnumeratorClang(wstrToStr(source), wstrToStr(opts) ) );
}
///////////////////////////////////////////////////////////////////////////////
SymbolEnumeratorPtr getSymbolEnumeratorFromSource(const std::string& source, const std::string& opts)
{
return SymbolEnumeratorPtr(new SymbolEnumeratorClang(source, opts));
}
///////////////////////////////////////////////////////////////////////////////
}
......@@ -383,9 +383,25 @@ private:
ClangASTSessionPtr m_astSession;
std::map< std::string, TypeInfoPtr> m_typeCache;
};
class SymbolEnumeratorClang : public SymbolEnumerator, public boost::enable_shared_from_this<SymbolEnumeratorClang>
{
public:
SymbolEnumeratorClang(const std::string& sourceCode, const std::string& compileOptions);
private:
std::wstring Next() override;
private:
size_t m_index = 0;
std::vector<std::string> m_symbols;
};
}
......@@ -820,38 +820,6 @@ std::wstring TypedVarBase::printValue() const
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr TypedVarUdt::getElement( const std::wstring& fieldName )
{
TypeInfoPtr fieldType = m_typeInfo->getElement( fieldName );
if ( m_typeInfo->isStaticMember(fieldName) )
{
MEMOFFSET_64 staticOffset = m_typeInfo->getElementVa(fieldName);
return loadTypedVar( fieldType, staticOffset );
}
if (fieldType->isConstant())
{
return TypedValue(fieldType->getValue()).get();
}
MEMOFFSET_32 fieldOffset = m_typeInfo->getElementOffset(fieldName);
if ( m_typeInfo->isVirtualMember( fieldName ) )
{
fieldOffset += getVirtualBaseDisplacement( fieldName );
}
return loadTypedVar( fieldType, m_varData->copy(fieldOffset, fieldType->getSize()) );
}
///////////////////////////////////////////////////////////////////////////////
void TypedVarUdt::setElement( const std::wstring& fieldName, const TypedValue& value)
{
getElement(fieldName)->setValue(value);
}
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr TypedVarUdt::getMethod( const std::wstring &methodName, const std::wstring& prototype)
{
......@@ -996,6 +964,40 @@ TypedVarPtr TypedVarUdt::getVirtualMethodRecursive(
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr TypedVarUdt::getElement(const std::wstring& fieldName)
{
TypeInfoPtr fieldType = m_typeInfo->getElement(fieldName);
if (m_typeInfo->isStaticMember(fieldName))
{
MEMOFFSET_64 staticOffset = m_typeInfo->getElementVa(fieldName);
return loadTypedVar(fieldType, staticOffset);
}
if (fieldType->isConstant())
{
return TypedValue(fieldType->getValue()).get();
}
MEMOFFSET_32 fieldOffset = m_typeInfo->getElementOffset(fieldName);
if (m_typeInfo->isVirtualMember(fieldName))
{
fieldOffset += getVirtualBaseDisplacement(fieldName);
}
return loadTypedVar(fieldType, m_varData->copy(fieldOffset, fieldType->getSize()));
}
///////////////////////////////////////////////////////////////////////////////
void TypedVarUdt::setElement(const std::wstring& fieldName, const TypedValue& value)
{
getElement(fieldName)->setValue(value);
}
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr TypedVarUdt::getElement( size_t index )
{
TypeInfoPtr fieldType = m_typeInfo->getElement( index );
......@@ -1007,6 +1009,11 @@ TypedVarPtr TypedVarUdt::getElement( size_t index )
return loadTypedVar( fieldType, staticOffset );
}
if (fieldType->isConstant())
{
return TypedValue(fieldType->getValue()).get();
}
MEMOFFSET_32 fieldOffset = m_typeInfo->getElementOffset(index);
if ( m_typeInfo->isVirtualMember( index ) )
......
......@@ -593,4 +593,37 @@ TEST_F(ClangTest, isInheritedMember)
EXPECT_FALSE(testStruct->isInheritedMember(L"mchild"));
EXPECT_TRUE(testStruct->isInheritedMember(0));
EXPECT_FALSE(testStruct->isInheritedMember(1));
}
\ No newline at end of file
}
TEST_F(ClangTest, EnumFuncNames)
{
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 { \
voit method(int) \
}; \
";
SymbolEnumeratorPtr symEnum = getSymbolEnumeratorFromSource(srcCode);
std::wstring symbol;
std::vector<std::wstring> symbols;
while ( !(symbol = symEnum->Next()).empty() )
{
symbols.push_back(symbol);
}
EXPECT_EQ( std::vector<std::wstring>({
L"func",
L"func1",
L"func2<2>",
L"testns::func3",
L"testcls::method"
}), symbols);
}
\ No newline at end of file