static bool IsTypeInGlobalNamespace()

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);
  }