in facebook-clang-plugins/libtooling/ASTExporter.h [1541:1655]
void ASTExporter<ATDWriter>::VisitFunctionDecl(const FunctionDecl *D) {
ASTExporter<ATDWriter>::VisitDeclaratorDecl(D);
// We purposedly do not call VisitDeclContext(D).
auto DNkind = D->getDeclName().getNameKind();
bool ShouldMangleName = Mangler->shouldMangleDeclName(D) &&
DNkind != DeclarationName::CXXDeductionGuideName &&
DNkind != DeclarationName::CXXUsingDirective;
bool IsInlineSpecified = D->isInlineSpecified();
bool IsModulePrivate = D->isModulePrivate();
bool IsPure = D->isPure();
bool IsDeletedAsWritten = D->isDeletedAsWritten();
bool IsCpp = Mangler->getASTContext().getLangOpts().CPlusPlus;
bool IsVariadic = D->isVariadic();
bool IsStatic = false; // static functions
if (D->getStorageClass() == SC_Static) {
IsStatic = true;
}
auto IsNoReturn = D->isNoReturn();
bool IsConstexpr = D->isConstexpr();
bool HasParameters = !D->param_empty();
const FunctionDecl *DeclWithBody = D;
// FunctionDecl::hasBody() will set DeclWithBody pointer to decl that
// has body. If there is no body in all decls of that function,
// then we need to set DeclWithBody to nullptr manually
if (!D->hasBody(DeclWithBody)) {
DeclWithBody = nullptr;
}
bool HasDeclarationBody = D->doesThisDeclarationHaveABody();
FunctionTemplateDecl *TemplateDecl = D->getPrimaryTemplate();
int size = ShouldMangleName + IsCpp + IsInlineSpecified + IsModulePrivate +
IsPure + IsDeletedAsWritten + IsNoReturn + IsConstexpr +
IsVariadic + IsStatic + HasParameters + (bool)DeclWithBody +
HasDeclarationBody + (bool)TemplateDecl;
ObjectScope Scope(OF, size);
if (ShouldMangleName) {
OF.emitTag("mangled_name");
SmallString<64> Buf;
llvm::raw_svector_ostream StrOS(Buf);
GlobalDecl GD;
if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
GD = GlobalDecl(CD, Ctor_Base);
} else if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
GD = GlobalDecl(DD, Dtor_Base);
} else {
GD = GlobalDecl(D);
}
Mangler->mangleName(GD, StrOS);
// mangled names can get ridiculously long, so hash them to a fixed size
OF.emitString(std::to_string(fnv64Hash(StrOS)));
}
OF.emitFlag("is_cpp", IsCpp);
OF.emitFlag("is_inline", IsInlineSpecified);
OF.emitFlag("is_module_private", IsModulePrivate);
OF.emitFlag("is_pure", IsPure);
OF.emitFlag("is_delete_as_written", IsDeletedAsWritten);
OF.emitFlag("is_no_return", IsNoReturn);
OF.emitFlag("is_constexpr", IsConstexpr);
OF.emitFlag("is_variadic", IsVariadic);
OF.emitFlag("is_static", IsStatic);
// if (const FunctionProtoType *FPT =
// D->getType()->getAs<FunctionProtoType>()) {
// FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
// switch (EPI.ExceptionSpec.Type) {
// default: break;
// case EST_Unevaluated:
// OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
// break;
// case EST_Uninstantiated:
// OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
// break;
// }
// }
//
// const FunctionTemplateSpecializationInfo *FTSI =
// D->getTemplateSpecializationInfo();
// bool HasTemplateSpecialization = FTSI;
//
//
// if (HasTemplateSpecialization) {
// dumpTemplateArgumentList(*FTSI->TemplateArguments);
// }
if (HasParameters) {
FunctionDecl::param_const_iterator I = D->param_begin(), E = D->param_end();
if (I != E) {
OF.emitTag("parameters");
ArrayScope Scope(OF, std::distance(I, E));
for (; I != E; ++I) {
dumpDecl(*I);
}
}
}
if (DeclWithBody) {
OF.emitTag("decl_ptr_with_body");
dumpPointer(DeclWithBody);
}
if (HasDeclarationBody) {
const Stmt *Body = D->getBody();
if (Body) {
OF.emitTag("body");
dumpStmt(Body);
}
}
if (TemplateDecl) {
OF.emitTag("template_specialization");
dumpTemplateSpecialization(TemplateDecl,
*D->getTemplateSpecializationArgs());
}
}