src: small code cleanup

This commit is contained in:
malte_langkabel
2016-03-22 10:14:59 +01:00
parent 6743336f03
commit d1a4bc7b08
6 changed files with 256 additions and 283 deletions
+1 -1
View File
@@ -98,7 +98,7 @@ public:
const NameHierarchy& templateNameHierarchy) = 0;
virtual Id onTemplateDefaultArgumentTypeParsed(
const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy,
const NameHierarchy& templateArgumentTypeNameHierarchy) = 0;
const NameHierarchy& templateParameterNameHierarchy) = 0;
virtual Id onTemplateSpecializationParsed(
const ParseLocation& location, const NameHierarchy& specializedNameHierarchy,
const NameHierarchy& specializedFromNameHierarchy) = 0;
+1 -1
View File
@@ -71,7 +71,7 @@ public:
const NameHierarchy& templateNameHierarchy);
virtual Id onTemplateDefaultArgumentTypeParsed(
const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy,
const NameHierarchy& templateArgumentTypeNameHierarchy);
const NameHierarchy& templateParameterNameHierarchy);
virtual Id onTemplateSpecializationParsed(
const ParseLocation& location, const NameHierarchy& specializedNameHierarchy,
const NameHierarchy& specializedFromNameHierarchy);
+245 -242
View File
@@ -6,13 +6,13 @@
#include <llvm/Support/Casting.h>
#include <string>
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "data/parser/cxx/utilityCxx.h"
#include "data/parser/ParseLocation.h"
#include "utility/file/FileManager.h"
#include "utility/ScopedSwitcher.h"
// TODO: For an array access, X[I], skip over the array-to-pointer decay. We
// currently record that X's address is taken, which is technically true, but
// the address does not generally escape.
@@ -278,8 +278,8 @@ bool ASTVisitor::TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializa
bool ASTVisitor::TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff
{
std::shared_ptr<ContextNameGenerator> n;
ScopedSwitcher<std::shared_ptr<ContextNameGenerator>> sw(m_childContextNameGenerator, n);
std::shared_ptr<ContextNameGenerator> clear;
ScopedSwitcher<std::shared_ptr<ContextNameGenerator>> sw(m_childContextNameGenerator, clear);
return base::TraverseUnresolvedLookupExpr(e);
}
@@ -636,8 +636,8 @@ bool ASTVisitor::TraverseNestedNameSpecifierLoc(
}
}
break;
default:
// TODO: Do these cases matter?
default: // case Global: case Super:
// do nothing for the remaining cases
break;
}
}
@@ -796,7 +796,7 @@ bool ASTVisitor::VisitDecl(clang::Decl *d)
RecordDeclRef(nd, loc, refType, symbolType);
if (fd->isFunctionTemplateSpecialization())
{
RecordDeclRef(nd, loc, refType, ST_FunctionTemplateSpecialization); // TODO: functiontemplatespec is more reftype than symboltype
RecordDeclRef(nd, loc, RT_TemplateSpecialization, symbolType);
}
//}
} else if (clang::VarDecl *vd = llvm::dyn_cast<clang::VarDecl>(d)) {
@@ -873,7 +873,7 @@ bool ASTVisitor::VisitDecl(clang::Decl *d)
if (clang::isa<clang::ClassTemplateSpecializationDecl>(td))
{
RecordDeclRef(nd, loc, refType, ST_ClassTemplateSpecialization); // TODO: classtemplatespec is more reftype than symboltype
RecordDeclRef(nd, loc, RT_TemplateSpecialization, symbolType);
}
} else if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(d)) {
RecordDeclRef(
@@ -1127,7 +1127,7 @@ void ASTVisitor::RecordTypeRef(
}
else if (refType == RT_TemplateDefaultArgument)
{
m_client->onTemplateDefaultArgumentTypeParsed( // TODO: rename second parameter to "parameter"
m_client->onTemplateDefaultArgumentTypeParsed(
parseLocation, typeNameHierarchy, contextNameHierarchy);
}
else
@@ -1138,36 +1138,6 @@ void ASTVisitor::RecordTypeRef(
}
}
bool ASTVisitor::isPartOfImplicitTemplateSpecialization(clang::Decl* d) const
{
if (!d)
{
return false;
}
if (clang::ClassTemplateSpecializationDecl* ctsd = clang::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(d))
{
if (!ctsd->isExplicitSpecialization())
{
return true;
}
}
else if (clang::FunctionDecl* fd = clang::dyn_cast_or_null<clang::FunctionDecl>(d))
{
if (fd->isTemplateInstantiation() && fd->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization) // or undefined??
{
return true;
}
}
return isPartOfImplicitTemplateSpecialization(clang::dyn_cast_or_null<clang::Decl>(d->getDeclContext()));
}
bool ASTVisitor::isImplicit(clang::Decl* d) const
{
return d->isImplicit() || isPartOfImplicitTemplateSpecialization(d);
}
void ASTVisitor::RecordDeclRef(
clang::NamedDecl* d,
clang::SourceLocation beginLoc,
@@ -1188,153 +1158,164 @@ void ASTVisitor::RecordDeclRef(
bool fallback = false;
if (
refType == RT_Declaration ||
refType == RT_Definition
)
switch (refType)
{
switch (symbolType)
case RT_Declaration:
case RT_Definition:
{
case ST_Typedef:
if (clang::TypedefDecl* typedefDecl = clang::dyn_cast<clang::TypedefDecl>(d))
switch (symbolType)
{
m_client->onTypedefParsed(
parseLocation,
declNameHierarchy,
convertAccessType(typedefDecl->getAccess()),
declIsImplicit);
}
break;
case ST_Class:
if (clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(d))
{
m_client->onClassParsed(
parseLocation,
declNameHierarchy,
convertAccessType(recordDecl->getAccess()),
(refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_Struct:
if (clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(d))
{
m_client->onStructParsed(
parseLocation,
declNameHierarchy,
convertAccessType(recordDecl->getAccess()),
(refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_GlobalVariable:
m_client->onGlobalVariableParsed(
parseLocation,
declNameHierarchy,
declIsImplicit);
break;
case ST_Field:
//if (clang::VarDecl* varDecl = clang::dyn_cast<clang::VarDecl>(d))
{
m_client->onFieldParsed(
parseLocation,
declNameHierarchy,
convertAccessType(d->getAccess()),
declIsImplicit);
}
break;
case ST_Function:
if (clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(d))
{
m_client->onFunctionParsed(
parseLocation,
declNameHierarchy,
(refType == RT_Definition ? getParseLocationOfFunctionBody(functionDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_Constructor:
case ST_Destructor:
case ST_Method:
if (clang::CXXMethodDecl* methodDecl = clang::dyn_cast<clang::CXXMethodDecl>(d))
{
m_client->onMethodParsed(
parseLocation,
declNameHierarchy,
convertAccessType(methodDecl->getAccess()),
getAbstractionType(methodDecl),
(refType == RT_Definition ? getParseLocationOfFunctionBody(methodDecl) : ParseLocation()),
declIsImplicit);
for (clang::CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); // iterate in traversal and use RT_Overridden or so..
it != methodDecl->end_overridden_methods(); it++)
case ST_Typedef:
if (clang::TypedefDecl* typedefDecl = clang::dyn_cast<clang::TypedefDecl>(d))
{
m_client->onMethodOverrideParsed(
m_client->onTypedefParsed(
parseLocation,
m_declNameCache->getValue(*it),
declNameHierarchy);
declNameHierarchy,
convertAccessType(typedefDecl->getAccess()),
declIsImplicit);
}
clang::MemberSpecializationInfo* memberSpecializationInfo = methodDecl->getMemberSpecializationInfo();
if (memberSpecializationInfo)
break;
case ST_Class:
if (clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(d))
{
clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom();
if (clang::isa<clang::FunctionDecl>(specializedNamedDecl))
m_client->onClassParsed(
parseLocation,
declNameHierarchy,
convertAccessType(recordDecl->getAccess()),
(refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_Struct:
if (clang::RecordDecl* recordDecl = clang::dyn_cast<clang::RecordDecl>(d))
{
m_client->onStructParsed(
parseLocation,
declNameHierarchy,
convertAccessType(recordDecl->getAccess()),
(refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_GlobalVariable:
m_client->onGlobalVariableParsed(
parseLocation,
declNameHierarchy,
declIsImplicit);
break;
case ST_Field:
//if (clang::VarDecl* varDecl = clang::dyn_cast<clang::VarDecl>(d))
{
m_client->onFieldParsed(
parseLocation,
declNameHierarchy,
convertAccessType(d->getAccess()),
declIsImplicit);
}
break;
case ST_Function:
if (clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(d))
{
m_client->onFunctionParsed(
parseLocation,
declNameHierarchy,
(refType == RT_Definition ? getParseLocationOfFunctionBody(functionDecl) : ParseLocation()),
declIsImplicit);
}
break;
case ST_Constructor:
case ST_Destructor:
case ST_Method:
if (clang::CXXMethodDecl* methodDecl = clang::dyn_cast<clang::CXXMethodDecl>(d))
{
m_client->onMethodParsed(
parseLocation,
declNameHierarchy,
convertAccessType(methodDecl->getAccess()),
getAbstractionType(methodDecl),
(refType == RT_Definition ? getParseLocationOfFunctionBody(methodDecl) : ParseLocation()),
declIsImplicit);
for (clang::CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); // iterate in traversal and use RT_Overridden or so..
it != methodDecl->end_overridden_methods(); it++)
{
m_client->onTemplateMemberFunctionSpecializationParsed(
m_client->onMethodOverrideParsed(
parseLocation,
declNameHierarchy,
m_declNameCache->getValue(specializedNamedDecl));
m_declNameCache->getValue(*it),
declNameHierarchy);
}
clang::MemberSpecializationInfo* memberSpecializationInfo = methodDecl->getMemberSpecializationInfo();
if (memberSpecializationInfo)
{
clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom();
if (clang::isa<clang::FunctionDecl>(specializedNamedDecl))
{
m_client->onTemplateMemberFunctionSpecializationParsed(
parseLocation,
declNameHierarchy,
m_declNameCache->getValue(specializedNamedDecl));
}
}
}
}
break;
case ST_Namespace:
if (clang::NamespaceDecl* namespaceDecl = clang::dyn_cast<clang::NamespaceDecl>(d))
{
m_client->onNamespaceParsed(
namespaceDecl->isAnonymousNamespace() ? ParseLocation() : parseLocation,
declNameHierarchy,
getParseLocation(namespaceDecl->getSourceRange()),
declIsImplicit);
}
else if (clang::NamespaceAliasDecl* namespaceAliasDecl = clang::dyn_cast<clang::NamespaceAliasDecl>(d))
{
m_client->onNamespaceParsed(
parseLocation,
declNameHierarchy,
getParseLocation(namespaceAliasDecl->getAliasedNamespace()->getSourceRange()),
declIsImplicit);
}
break;
case ST_Enum:
if (clang::EnumDecl* enumDecl = clang::dyn_cast<clang::EnumDecl>(d))
{
m_client->onEnumParsed(
parseLocation,
declNameHierarchy,
convertAccessType(enumDecl->getAccess()),
getParseLocation(enumDecl->getSourceRange()),
declIsImplicit);
}
break;
case ST_Enumerator:
m_client->onEnumConstantParsed(
parseLocation,
declNameHierarchy,
declIsImplicit);
break;
case ST_TemplateParameter:
if (!d->getName().empty()) // We don't create symbols for unnamed template parameters.
{
m_client->onTemplateParameterTypeParsed(
break;
case ST_Namespace:
if (clang::NamespaceDecl* namespaceDecl = clang::dyn_cast<clang::NamespaceDecl>(d))
{
m_client->onNamespaceParsed(
namespaceDecl->isAnonymousNamespace() ? ParseLocation() : parseLocation,
declNameHierarchy,
getParseLocation(namespaceDecl->getSourceRange()),
declIsImplicit);
}
else if (clang::NamespaceAliasDecl* namespaceAliasDecl = clang::dyn_cast<clang::NamespaceAliasDecl>(d))
{
m_client->onNamespaceParsed(
parseLocation,
declNameHierarchy,
getParseLocation(namespaceAliasDecl->getAliasedNamespace()->getSourceRange()),
declIsImplicit);
}
break;
case ST_Enum:
if (clang::EnumDecl* enumDecl = clang::dyn_cast<clang::EnumDecl>(d))
{
m_client->onEnumParsed(
parseLocation,
declNameHierarchy,
convertAccessType(enumDecl->getAccess()),
getParseLocation(enumDecl->getSourceRange()),
declIsImplicit);
}
break;
case ST_Enumerator:
m_client->onEnumConstantParsed(
parseLocation,
declNameHierarchy,
declIsImplicit);
break;
case ST_TemplateParameter:
if (!d->getName().empty()) // We don't create symbols for unnamed template parameters.
{
m_client->onTemplateParameterTypeParsed(
parseLocation,
declNameHierarchy,
declIsImplicit);
}
break;
case ST_LocalVariable:
case ST_Parameter:
// Do nothing.
break;
default:
fallback = true;
break;
}
break;
case ST_ClassTemplateSpecialization:
if (clang::ClassTemplateSpecializationDecl* classTemplateSpecializationDecl = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(d)) // TODO: we need a different reftype here! and st_max? mabe rewrite TraverseClassTemplateSpecializationDecl()
}
case RT_TemplateSpecialization:
{
if (clang::ClassTemplateSpecializationDecl* classTemplateSpecializationDecl = clang::dyn_cast<clang::ClassTemplateSpecializationDecl>(d))
{
clang::NamedDecl* specializedFromDecl;
llvm::PointerUnion<clang::ClassTemplateDecl*, clang::ClassTemplatePartialSpecializationDecl*> pu = classTemplateSpecializationDecl->getSpecializedTemplateOrPartial();
@@ -1350,100 +1331,91 @@ void ASTVisitor::RecordDeclRef(
m_client->onTemplateSpecializationParsed(
parseLocation,
declNameHierarchy,
m_declNameCache->getValue(specializedFromDecl)); // use context and childcontext!!
m_declNameCache->getValue(specializedFromDecl)); // todo: use context and childcontext!!
}
break;
case ST_FunctionTemplateSpecialization:
if (clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(d))
else if (clang::FunctionDecl* functionDecl = clang::dyn_cast<clang::FunctionDecl>(d))
{
m_client->onTemplateSpecializationParsed(
parseLocation,
declNameHierarchy,
m_declNameCache->getValue(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use contect and childcontext!!
m_declNameCache->getValue(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use context and childcontext!!
}
break;
case ST_LocalVariable:
case ST_Parameter:
// Do nothing.
break;
default:
fallback = true;
break;
}
}
else
{
const NameHierarchy contextNameHierarchy = getContextName();
switch (symbolType)
default:
{
case ST_Field:
m_client->onFieldUsageParsed(
parseLocation,
contextNameHierarchy,
declNameHierarchy
);
break;
case ST_GlobalVariable:
if (refType == RT_TemplateArgument)
const NameHierarchy contextNameHierarchy = getContextName();
switch (symbolType)
{
m_client->onTemplateArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
}
else
{
m_client->onGlobalVariableUsageParsed(
case ST_Field:
m_client->onFieldUsageParsed(
parseLocation,
contextNameHierarchy,
declNameHierarchy
);
break;
case ST_GlobalVariable:
if (refType == RT_TemplateArgument)
{
m_client->onTemplateArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
}
else
{
m_client->onGlobalVariableUsageParsed(
parseLocation,
contextNameHierarchy,
declNameHierarchy);
}
break;
case ST_Enumerator:
m_client->onEnumConstantUsageParsed(
parseLocation,
contextNameHierarchy,
declNameHierarchy);
}
break;
case ST_Enumerator:
m_client->onEnumConstantUsageParsed(
parseLocation,
contextNameHierarchy,
declNameHierarchy);
break;
case ST_Max:
switch (refType)
{
case RT_Called:
m_client->onCallParsed(
parseLocation, contextNameHierarchy, declNameHierarchy);
break;
case RT_Reference:
m_client->onTypeUsageParsed(
parseLocation, contextNameHierarchy, declNameHierarchy);
case ST_Max:
switch (refType)
{
case RT_Called:
m_client->onCallParsed(
parseLocation, contextNameHierarchy, declNameHierarchy);
break;
case RT_Reference:
m_client->onTypeUsageParsed(
parseLocation, contextNameHierarchy, declNameHierarchy);
break;
case RT_TemplateArgument:
m_client->onTemplateArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
break;
case RT_TemplateDefaultArgument:
m_client->onTemplateDefaultArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
break;
case RT_BaseClass:
m_client->onInheritanceParsed(
parseLocation, contextNameHierarchy, declNameHierarchy, m_contextAccess);
break;
case RT_Assigned:
case RT_AddressTaken:
case RT_Read:
case RT_Qualifier:
// Do nothing.
break;
default:
fallback = true;
break;
}
break;
case RT_TemplateArgument:
m_client->onTemplateArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
break;
case RT_TemplateDefaultArgument:
m_client->onTemplateDefaultArgumentTypeParsed(
parseLocation, declNameHierarchy, contextNameHierarchy);
break;
case RT_BaseClass:
m_client->onInheritanceParsed(
parseLocation, contextNameHierarchy, declNameHierarchy, m_contextAccess);
break;
case RT_Assigned:
case RT_AddressTaken:
case RT_Read:
case RT_Qualifier:
case ST_LocalVariable:
case ST_Parameter:
// Do nothing.
break;
default:
fallback = true;
break;
}
break;
case ST_LocalVariable:
case ST_Parameter:
// Do nothing.
break;
default:
fallback = true;
break;
}
}
@@ -1487,6 +1459,37 @@ void ASTVisitor::RecordDeclRef(
// }
//}
}
bool ASTVisitor::isPartOfImplicitTemplateSpecialization(clang::Decl* d) const
{
if (!d)
{
return false;
}
if (clang::ClassTemplateSpecializationDecl* ctsd = clang::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(d))
{
if (!ctsd->isExplicitSpecialization())
{
return true;
}
}
else if (clang::FunctionDecl* fd = clang::dyn_cast_or_null<clang::FunctionDecl>(d))
{
if (fd->isTemplateInstantiation() && fd->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization) // or undefined??
{
return true;
}
}
return isPartOfImplicitTemplateSpecialization(clang::dyn_cast_or_null<clang::Decl>(d->getDeclContext()));
}
bool ASTVisitor::isImplicit(clang::Decl* d) const
{
return d->isImplicit() || isPartOfImplicitTemplateSpecialization(d);
}
bool ASTVisitor::isLocatedInUnparsedProjectFile(clang::SourceLocation loc)
{
clang::SourceManager& sourceManager = m_context->getSourceManager();
+4 -16
View File
@@ -12,11 +12,6 @@
#include "utility/file/FileRegister.h"
#include "utility/Cache.h"
#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h"
#include "data/parser/cxx/utilityCxx.h"
class ASTVisitor: clang::RecursiveASTVisitor<ASTVisitor>
{
public:
@@ -113,6 +108,7 @@ private:
RT_Reference,
RT_TemplateArgument,
RT_TemplateDefaultArgument,
RT_TemplateSpecialization,
RT_Undefinition,
RT_Using,
RT_UsingDirective,
@@ -121,14 +117,12 @@ private:
enum SymbolType : int { // we dont need this. decl already knows it!
ST_Class,
ST_ClassTemplateSpecialization,
ST_Constructor,
ST_Destructor,
ST_Enum,
ST_Enumerator,
ST_Field,
ST_Function,
ST_FunctionTemplateSpecialization,
ST_GlobalVariable,
ST_LocalVariable,
ST_Macro,
@@ -143,12 +137,6 @@ private:
ST_Max
};
struct Location {
unsigned int fileID;
unsigned int line; // 1-based
int column; // 1-based
};
typedef unsigned int Context;
clang::ASTContext* m_context;
@@ -238,15 +226,15 @@ private:
RefType refType,
SymbolType symbolType = ST_Max);
bool isPartOfImplicitTemplateSpecialization(clang::Decl* d) const;
bool isImplicit(clang::Decl* d) const;
void RecordDeclRef(
clang::NamedDecl *d,
clang::SourceLocation beginLoc,
RefType refType,
SymbolType symbolType = ST_Max);
bool isPartOfImplicitTemplateSpecialization(clang::Decl* d) const;
bool isImplicit(clang::Decl* d) const;
bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc);
bool isLocatedInProjectFile(clang::SourceLocation loc);
@@ -15,9 +15,6 @@ class NameHierarchy;
namespace utility
{
template <typename TypeLocType>
TypeLocType getNextTypeLoc(clang::TypeLoc loc);
std::shared_ptr<DataType> qualTypeToDataType(clang::QualType qualType);
NameHierarchy getDeclNameHierarchy(const clang::Decl* declaration);
@@ -25,19 +22,4 @@ namespace utility
NameHierarchy getTemplateSpecializationParentNameHierarchy(clang::ClassTemplateSpecializationDecl* declaration);
}
template <typename TypeLocType>
TypeLocType utility::getNextTypeLoc(clang::TypeLoc loc)
{
while (!loc.isNull())
{
TypeLocType ret = loc.getAs<TypeLocType>();
if (!ret.isNull())
{
return ret;
}
loc = loc.getNextTypeLoc();
}
return TypeLocType(); // isNull() of this object returns true.
}
#endif // UTILITY_CLANG_H
+5 -5
View File
@@ -76,10 +76,10 @@ public:
std::shared_ptr<TestParserClient> client = parseCode(
"class A\n"
"{\n"
" int a;"
" int a;\n"
"public:\n"
" A() : d(0) {};\n"
" int b;"
" int b;\n"
"protected:\n"
" static int c;\n"
"private:\n"
@@ -89,9 +89,9 @@ public:
TS_ASSERT_EQUALS(client->fields.size(), 4);
TS_ASSERT_EQUALS(client->fields[0], "private A::a <3:6 3:6>");
TS_ASSERT_EQUALS(client->fields[1], "public A::b <5:6 5:6>");
TS_ASSERT_EQUALS(client->fields[2], "protected A::c <6:13 6:13>");
TS_ASSERT_EQUALS(client->fields[3], "private A::d <8:12 8:12>");
TS_ASSERT_EQUALS(client->fields[1], "public A::b <6:6 6:6>");
TS_ASSERT_EQUALS(client->fields[2], "protected A::c <8:13 8:13>");
TS_ASSERT_EQUALS(client->fields[3], "private A::d <10:12 10:12>");
}
void test_cxx_parser_finds_function_declaration()