in tools/apiview/parsers/cpp-api-parser/ApiViewProcessor/AstNode.cpp [145:279]
static bool IsTypeInGlobalNamespace(Type const* typePtr)
{
// clang TypeVisitor which will iterate over the type and return true if it finds a type which
// is a typedef in the global namespace.
struct IsTypeInGlobalNamespaceVisitor : public TypeVisitor<IsTypeInGlobalNamespaceVisitor, bool>
{
IsTypeInGlobalNamespaceVisitor(){};
bool VisitTypedefType(TypedefType const* typeDef)
{
clang::PrintingPolicy pp{LangOptions{}};
pp.adjustForCPlusPlus();
auto typeName{QualType::getAsString(QualType(typeDef, 0).split(), pp)};
if (typeName.find(':') == std::string::npos)
{
// size_t is valid in both the global namespace and std namespace.
if (typeName == "size_t")
{
return false;
}
return true;
}
return false;
}
bool VisitTemplateSpecializationType(TemplateSpecializationType const* tst)
{
for (const auto& arg : tst->template_arguments())
{
// We only care about type arguments.
if (arg.getKind() == TemplateArgument::ArgKind::Type)
{
if (TypeVisitor::Visit(arg.getAsType().split().Ty))
{
return true;
}
}
}
return false;
}
bool VisitTemplateArgumentType(TemplateArgument const* ta)
{
return TypeVisitor::Visit(ta->getAsType().split().Ty);
}
bool VisitElaboratedType(ElaboratedType const* et)
{
return TypeVisitor::Visit(et->getNamedType().split().Ty);
}
bool VisitLValueReferenceType(LValueReferenceType const* lrt)
{
return TypeVisitor::Visit(lrt->getPointeeType().split().Ty);
}
bool VisitRValueReferenceType(RValueReferenceType const* rrt)
{
return TypeVisitor::Visit(rrt->getPointeeType().split().Ty);
}
bool VisitPointerType(PointerType const* pt)
{
return TypeVisitor::Visit(pt->getPointeeType().split().Ty);
}
bool VisitPackExpansionType(PackExpansionType const* pe)
{
return TypeVisitor::Visit(pe->getPattern().split().Ty);
}
bool VisitIncompleteArrayType(IncompleteArrayType const* ia)
{
return TypeVisitor::Visit(ia->getArrayElementTypeNoTypeQual());
}
bool VisitConstantArrayType(ConstantArrayType const* ca)
{
return TypeVisitor::Visit(ca->getArrayElementTypeNoTypeQual());
}
bool VisitParenType(ParenType const* pt)
{
return TypeVisitor::Visit(pt->getInnerType().split().Ty);
}
// This type was declared with a "using" declaration.
//
bool VisitUsingType(UsingType const* ut)
{
bool rv{TypeVisitor::Visit(ut->getUnderlyingType().split().Ty)};
// If the underlying type is in the global namespace, but has a shadow declaration (a
// declaration introduced by a using declaration), then we treat it as if it wasn't in the
// global namespace (because it's not).
if (rv)
{
if (ut->getFoundDecl())
{
return false;
}
}
return rv;
}
bool VisitFunctionProtoType(FunctionProtoType const* fp)
{
for (const auto& arg : fp->param_types())
{
if (TypeVisitor::Visit(arg.split().Ty))
{
return true;
}
}
if (TypeVisitor::Visit(fp->getReturnType().split().Ty))
{
return true;
}
return false;
}
// Dependent names don't contain underlying types.
bool VisitDependentNameType(DependentNameType const* dn) { return false; }
// Template type params don't contain underlying types.
bool VisitTemplateTypeParmType(TemplateTypeParmType const* ttp) { return false; }
// An injected class name is a template name referenced without template parameters.
bool VisitInjectedClassNameType(InjectedClassNameType const* ic) { return false; }
// Record type params don't contain underlying types.
bool VisitRecordType(RecordType const* record) { return false; }
// Enum type params don't contain underlying types.
bool VisitEnumType(EnumType const* et) { return false; }
// Builtin type params don't contain underlying types.
bool VisitBuiltinType(BuiltinType const* bt) { return false; }
bool VisitType(const Type* t)
{
llvm::outs() << "Visit Type "
<< QualType::getAsString(QualType(t, 0).split(), LangOptions())
<< "Type class: " << t->getTypeClassName() << "\n";
t->dump();
return false;
}
};
IsTypeInGlobalNamespaceVisitor visitTypes;
return visitTypes.Visit(typePtr);
}