llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Changqing  Jing (Changqing-JING)

<details>
<summary>Changes</summary>

This adds a source-level way to override the import module for imported
WebAssembly globals without introducing new global-specific attributes.

Clang lowers annotate("wasm-import-module", "...") on globals to
!wasm.import.module metadata, and the WebAssembly backend uses that metadata
when emitting the import. Invalid uses are ignored with a warning.

---

Patch is 53.44 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/200720.diff


5 Files Affected:

- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+243-232) 
- (modified) clang/lib/CodeGen/Targets/WebAssembly.cpp (+45) 
- (added) clang/test/CodeGen/WebAssembly/wasm-global-import-module.cpp (+19) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+24-4) 
- (added) llvm/test/CodeGen/WebAssembly/import-module-global-metadata.ll (+24) 


``````````diff
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index 236738e9975d3..f6dbb30300a57 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -463,14 +463,15 @@ CodeGenModule::CodeGenModule(ASTContext &C,
       C.toCharUnitsFromBits(C.getTargetInfo().getPointerAlign(LangAS::Default))
           .getQuantity();
   SizeSizeInBytes =
-    
C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth()).getQuantity();
+      C.toCharUnitsFromBits(C.getTargetInfo().getMaxPointerWidth())
+          .getQuantity();
   IntAlignInBytes =
-    C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
+      C.toCharUnitsFromBits(C.getTargetInfo().getIntAlign()).getQuantity();
   CharTy =
-    llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth());
+      llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getCharWidth());
   IntTy = llvm::IntegerType::get(LLVMContext, C.getTargetInfo().getIntWidth());
   IntPtrTy = llvm::IntegerType::get(LLVMContext,
-    C.getTargetInfo().getMaxPointerWidth());
+                                    C.getTargetInfo().getMaxPointerWidth());
   Int8PtrTy = llvm::PointerType::get(LLVMContext,
                                      C.getTargetAddressSpace(LangAS::Default));
   const llvm::DataLayout &DL = M.getDataLayout();
@@ -687,7 +688,8 @@ void CodeGenModule::applyReplacements() {
   }
 }
 
-void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV, 
llvm::Constant *C) {
+void CodeGenModule::addGlobalValReplacement(llvm::GlobalValue *GV,
+                                            llvm::Constant *C) {
   GlobalValReplacements.push_back(std::make_pair(GV, C));
 }
 
@@ -724,8 +726,9 @@ static const llvm::GlobalValue *getAliasedGlobal(const 
llvm::GlobalValue *GV) {
 }
 
 static bool checkAliasedGlobal(
-    const ASTContext &Context, DiagnosticsEngine &Diags, SourceLocation 
Location,
-    bool IsIFunc, const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV,
+    const ASTContext &Context, DiagnosticsEngine &Diags,
+    SourceLocation Location, bool IsIFunc, const llvm::GlobalValue *Alias,
+    const llvm::GlobalValue *&GV,
     const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames,
     SourceRange AliasRange) {
   GV = getAliasedGlobal(Alias);
@@ -971,7 +974,8 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine 
&Diags,
     Diags.Report(diag::warn_profile_data_unprofiled) << MainFile;
   } else {
     if (Mismatched > 0)
-      Diags.Report(diag::warn_profile_data_out_of_date) << Visited << 
Mismatched;
+      Diags.Report(diag::warn_profile_data_out_of_date)
+          << Visited << Mismatched;
 
     if (Missing > 0)
       Diags.Report(diag::warn_profile_data_missing) << Visited << Missing;
@@ -1220,7 +1224,8 @@ void CodeGenModule::Release() {
   // usage of #pragma comment(lib, *) is intended for host libraries on
   // Windows. Therefore emit llvm.dependent-libraries only for host.
   if (!ELFDependentLibraries.empty() && !Context.getLangOpts().CUDAIsDevice) {
-    auto *NMD = 
getModule().getOrInsertNamedMetadata("llvm.dependent-libraries");
+    auto *NMD =
+        getModule().getOrInsertNamedMetadata("llvm.dependent-libraries");
     for (auto *MD : ELFDependentLibraries)
       NMD->addOperand(MD);
   }
@@ -1275,12 +1280,12 @@ void CodeGenModule::Release() {
     // FIXME: we could support it by stripping all the information introduced
     // by StrictVTablePointers.
 
-    getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers",1);
+    getModule().addModuleFlag(llvm::Module::Error, "StrictVTablePointers", 1);
 
     llvm::Metadata *Ops[2] = {
-              llvm::MDString::get(VMContext, "StrictVTablePointers"),
-              llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-                  llvm::Type::getInt32Ty(VMContext), 1))};
+        llvm::MDString::get(VMContext, "StrictVTablePointers"),
+        llvm::ConstantAsMetadata::get(
+            llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1))};
 
     getModule().addModuleFlag(llvm::Module::Require,
                               "StrictVTablePointersRequirement",
@@ -1411,15 +1416,13 @@ void CodeGenModule::Release() {
   if (CodeGenOpts.CFProtectionReturn &&
       Target.checkCFProtectionReturnSupported(getDiags())) {
     // Indicate that we want to instrument return control flow protection.
-    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return",
-                              1);
+    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-return", 1);
   }
 
   if (CodeGenOpts.CFProtectionBranch &&
       Target.checkCFProtectionBranchSupported(getDiags())) {
     // Indicate that we want to instrument branch control flow protection.
-    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch",
-                              1);
+    getModule().addModuleFlag(llvm::Module::Min, "cf-protection-branch", 1);
 
     auto Scheme = CodeGenOpts.getCFBranchLabelScheme();
     if (Target.checkCFBranchLabelSchemeSupported(Scheme, getDiags())) {
@@ -1433,10 +1436,12 @@ void CodeGenModule::Release() {
   }
 
   if (CodeGenOpts.FunctionReturnThunks)
-    getModule().addModuleFlag(llvm::Module::Override, 
"function_return_thunk_extern", 1);
+    getModule().addModuleFlag(llvm::Module::Override,
+                              "function_return_thunk_extern", 1);
 
   if (CodeGenOpts.IndirectBranchCSPrefix)
-    getModule().addModuleFlag(llvm::Module::Override, 
"indirect_branch_cs_prefix", 1);
+    getModule().addModuleFlag(llvm::Module::Override,
+                              "indirect_branch_cs_prefix", 1);
 
   // Add module metadata for return address signing (ignoring
   // non-leaf/all) and stack tagging. These are actually turned on by function
@@ -1616,10 +1621,10 @@ void CodeGenModule::Release() {
       // OpenCL.
       auto Version = LangOpts.getOpenCLCompatibleVersion();
       llvm::Metadata *SPIRVerElts[] = {
-          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-              Int32Ty, Version / 100)),
-          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
-              Int32Ty, (Version / 100 > 1) ? 0 : 2))};
+          llvm::ConstantAsMetadata::get(
+              llvm::ConstantInt::get(Int32Ty, Version / 100)),
+          llvm::ConstantAsMetadata::get(
+              llvm::ConstantInt::get(Int32Ty, (Version / 100 > 1) ? 0 : 2))};
       llvm::NamedMDNode *SPIRVerMD =
           TheModule.getOrInsertNamedMetadata("opencl.spir.version");
       llvm::LLVMContext &Ctx = TheModule.getContext();
@@ -1640,14 +1645,15 @@ void CodeGenModule::Release() {
 
   if (getCodeGenOpts().CodeModel.size() > 0) {
     unsigned CM = llvm::StringSwitch<unsigned>(getCodeGenOpts().CodeModel)
-                  .Case("tiny", llvm::CodeModel::Tiny)
-                  .Case("small", llvm::CodeModel::Small)
-                  .Case("kernel", llvm::CodeModel::Kernel)
-                  .Case("medium", llvm::CodeModel::Medium)
-                  .Case("large", llvm::CodeModel::Large)
-                  .Default(~0u);
+                      .Case("tiny", llvm::CodeModel::Tiny)
+                      .Case("small", llvm::CodeModel::Small)
+                      .Case("kernel", llvm::CodeModel::Kernel)
+                      .Case("medium", llvm::CodeModel::Medium)
+                      .Case("large", llvm::CodeModel::Large)
+                      .Default(~0u);
     if (CM != ~0u) {
-      llvm::CodeModel::Model codeModel = 
static_cast<llvm::CodeModel::Model>(CM);
+      llvm::CodeModel::Model codeModel =
+          static_cast<llvm::CodeModel::Model>(CM);
       getModule().setCodeModel(codeModel);
 
       if ((CM == llvm::CodeModel::Medium || CM == llvm::CodeModel::Large) &&
@@ -2254,8 +2260,7 @@ static void AppendCPUSpecificCPUDispatchMangling(const 
CodeGenModule &CGM,
 
 // Returns true if GD is a function decl with internal linkage and
 // needs a unique suffix after the mangled name.
-static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
-                                        CodeGenModule &CGM) {
+static bool isUniqueInternalLinkageDecl(GlobalDecl GD, CodeGenModule &CGM) {
   const Decl *D = GD.getDecl();
   return !CGM.getModuleNameHash().empty() && isa<FunctionDecl>(D) &&
          (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
@@ -2394,7 +2399,8 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
       auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD));
       StringRef OtherNameRef = MangledDeclNames[OtherGD.getCanonicalDecl()] =
           Result.first->first();
-      // If this is the current decl is being created, make sure we update the 
name.
+      // If this is the current decl is being created, make sure we update the
+      // name.
       if (GD.getCanonicalDecl() == OtherGD.getCanonicalDecl())
         CurName = OtherNameRef;
       if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName))
@@ -2473,8 +2479,8 @@ StringRef CodeGenModule::getBlockMangledName(GlobalDecl 
GD,
   SmallString<256> Buffer;
   llvm::raw_svector_ostream Out(Buffer);
   if (!D)
-    MangleCtx.mangleGlobalBlock(BD,
-      dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
+    MangleCtx.mangleGlobalBlock(
+        BD, dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
   else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D))
     MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out);
   else if (const auto *DD = dyn_cast<CXXDestructorDecl>(D))
@@ -2524,7 +2530,8 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, 
int Priority,
 }
 
 void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
-  if (Fns.empty()) return;
+  if (Fns.empty())
+    return;
 
   const PointerAuthSchema &InitFiniAuthSchema =
       getCodeGenOpts().PointerAuth.InitFiniPointers;
@@ -2591,7 +2598,8 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) {
 
 llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
   llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
-  if (!MDS) return nullptr;
+  if (!MDS)
+    return nullptr;
 
   return llvm::ConstantInt::get(Int64Ty, llvm::MD5Hash(MDS->getString()));
 }
@@ -2689,7 +2697,7 @@ void CodeGenModule::SetLLVMFunctionAttributes(GlobalDecl 
GD,
   F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
 }
 
-static void removeImageAccessQualifier(std::string& TyName) {
+static void removeImageAccessQualifier(std::string &TyName) {
   std::string ReadOnlyQual("__read_only");
   std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual);
   if (ReadOnlyPos != std::string::npos)
@@ -2875,8 +2883,7 @@ void CodeGenModule::GenKernelArgMetadata(llvm::Function 
*Fn,
   }
   if (getCodeGenOpts().EmitOpenCLArgMetadata ||
       getCodeGenOpts().HIPSaveKernelArgName)
-    Fn->setMetadata("kernel_arg_name",
-                    llvm::MDNode::get(VMContext, argNames));
+    Fn->setMetadata("kernel_arg_name", llvm::MDNode::get(VMContext, argNames));
 }
 
 /// Determines whether the language options require us to model
@@ -2886,10 +2893,12 @@ void CodeGenModule::GenKernelArgMetadata(llvm::Function 
*Fn,
 /// enables this.
 static bool hasUnwindExceptions(const LangOptions &LangOpts) {
   // If exceptions are completely disabled, obviously this is false.
-  if (!LangOpts.Exceptions) return false;
+  if (!LangOpts.Exceptions)
+    return false;
 
   // If C++ exceptions are enabled, this is true.
-  if (LangOpts.CXXExceptions) return true;
+  if (LangOpts.CXXExceptions)
+    return true;
 
   // If ObjC exceptions are enabled, this depends on the ABI.
   if (LangOpts.ObjCExceptions) {
@@ -2916,7 +2925,7 @@ SmallVector<const CXXRecordDecl *, 0>
 CodeGenModule::getMostBaseClasses(const CXXRecordDecl *RD) {
   llvm::SetVector<const CXXRecordDecl *> MostBases;
 
-  std::function<void (const CXXRecordDecl *)> CollectMostBases;
+  std::function<void(const CXXRecordDecl *)> CollectMostBases;
   CollectMostBases = [&](const CXXRecordDecl *RD) {
     if (RD->getNumBases() == 0)
       MostBases.insert(RD);
@@ -3259,8 +3268,8 @@ bool 
CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD,
     AddedAttr = true;
   }
   if (!Features.empty() && SetTargetFeatures) {
-    llvm::erase_if(Features, [&](const std::string& F) {
-       return getTarget().isReadOnlyFeature(F.substr(1));
+    llvm::erase_if(Features, [&](const std::string &F) {
+      return getTarget().isReadOnlyFeature(F.substr(1));
     });
     llvm::sort(Features);
     Attrs.addAttribute("target-features", llvm::join(Features, ","));
@@ -3509,10 +3518,10 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl 
GD, llvm::Function *F,
   // GCC and does not actually return "this".
   if (!IsThunk && getCXXABI().HasThisReturn(GD) &&
       !(getTriple().isiOS() && getTriple().isOSVersionLT(6))) {
-    assert(!F->arg_empty() &&
-           F->arg_begin()->getType()
-             ->canLosslesslyBitCastTo(F->getReturnType()) &&
-           "unexpected this return");
+    assert(
+        !F->arg_empty() &&
+        F->arg_begin()->getType()->canLosslesslyBitCastTo(F->getReturnType()) 
&&
+        "unexpected this return");
     F->addParamAttr(0, llvm::Attribute::Returned);
   }
 
@@ -3529,7 +3538,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, 
llvm::Function *F,
   if (const auto *CSA = FD->getAttr<CodeSegAttr>())
     F->setSection(CSA->getName());
   else if (const auto *SA = FD->getAttr<SectionAttr>())
-     F->setSection(SA->getName());
+    F->setSection(SA->getName());
 
   if (const auto *EA = FD->getAttr<ErrorAttr>()) {
     if (EA->isError())
@@ -3579,7 +3588,8 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, 
llvm::Function *F,
     getOpenMPRuntime().emitDeclareSimdFunction(FD, F);
 
   if (CodeGenOpts.InlineMaxStackSize != UINT_MAX)
-    F->addFnAttr("inline-max-stacksize", 
llvm::utostr(CodeGenOpts.InlineMaxStackSize));
+    F->addFnAttr("inline-max-stacksize",
+                 llvm::utostr(CodeGenOpts.InlineMaxStackSize));
 
   if (const auto *CB = FD->getAttr<CallbackAttr>()) {
     // Annotate the callback behavior as metadata:
@@ -3627,12 +3637,11 @@ static void emitUsed(CodeGenModule &CGM, StringRef Name,
     return;
 
   // Convert List to what ConstantArray needs.
-  SmallVector<llvm::Constant*, 8> UsedArray;
+  SmallVector<llvm::Constant *, 8> UsedArray;
   UsedArray.resize(List.size());
   for (unsigned i = 0, e = List.size(); i != e; ++i) {
-    UsedArray[i] =
-        llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
-            cast<llvm::Constant>(&*List[i]), CGM.Int8PtrTy);
+    UsedArray[i] = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
+        cast<llvm::Constant>(&*List[i]), CGM.Int8PtrTy);
   }
 
   if (UsedArray.empty())
@@ -3668,7 +3677,7 @@ void CodeGenModule::AddDetectMismatch(StringRef Name, 
StringRef Value) {
 void CodeGenModule::AddDependentLib(StringRef Lib) {
   auto &C = getLLVMContext();
   if (getTarget().getTriple().isOSBinFormatELF()) {
-      ELFDependentLibraries.push_back(
+    ELFDependentLibraries.push_back(
         llvm::MDNode::get(C, llvm::MDString::get(C, Lib)));
     return;
   }
@@ -3890,8 +3899,8 @@ void CodeGenModule::EmitDeferred() {
     // to get GlobalValue with exactly the type we need, not something that
     // might had been created for another decl with the same mangled name but
     // different type.
-    llvm::GlobalValue *GV = dyn_cast<llvm::GlobalValue>(
-        GetAddrOfGlobal(D, ForDefinition));
+    llvm::GlobalValue *GV =
+        dyn_cast<llvm::GlobalValue>(GetAddrOfGlobal(D, ForDefinition));
 
     // In case of different address spaces, we may still get a cast, even with
     // IsForDefinition equal to true. Query mangled names table to get
@@ -3934,8 +3943,9 @@ void CodeGenModule::EmitVTablesOpportunistically() {
   // is not allowed to create new references to things that need to be emitted
   // lazily. Note that it also uses fact that we eagerly emitting RTTI.
 
-  assert((OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables())
-         && "Only emit opportunistic vtables with optimizations");
+  assert(
+      (OpportunisticVTables.empty() || shouldOpportunisticallyEmitVTables()) &&
+      "Only emit opportunistic vtables with optimizations");
 
   for (const CXXRecordDecl *RD : OpportunisticVTables) {
     assert(getVTables().isVTableExternal(RD) &&
@@ -3947,7 +3957,7 @@ void CodeGenModule::EmitVTablesOpportunistically() {
 }
 
 void CodeGenModule::EmitGlobalAnnotations() {
-  for (const auto& [MangledName, VD] : DeferredAnnotations) {
+  for (const auto &[MangledName, VD] : DeferredAnnotations) {
     llvm::GlobalValue *GV = GetGlobalValue(MangledName);
     if (GV)
       AddGlobalAnnotations(VD, GV);
@@ -3958,8 +3968,9 @@ void CodeGenModule::EmitGlobalAnnotations() {
     return;
 
   // Create a new global variable for the ConstantStruct in the Module.
-  llvm::Constant *Array = llvm::ConstantArray::get(llvm::ArrayType::get(
-    Annotations[0]->getType(), Annotations.size()), Annotations);
+  llvm::Constant *Array = llvm::ConstantArray::get(
+      llvm::ArrayType::get(Annotations[0]->getType(), Annotations.size()),
+      Annotations);
   auto *gv = new llvm::GlobalVariable(getModule(), Array->getType(), false,
                                       llvm::GlobalValue::AppendingLinkage,
                                       Array, "llvm.global.annotations");
@@ -3994,8 +4005,8 @@ llvm::Constant 
*CodeGenModule::EmitAnnotationUnit(SourceLocation Loc) {
 llvm::Constant *CodeGenModule::EmitAnnotationLineNo(SourceLocation L) {
   SourceManager &SM = getContext().getSourceManager();
   PresumedLoc PLoc = SM.getPresumedLoc(L);
-  unsigned LineNo = PLoc.isValid() ? PLoc.getLine() :
-    SM.getExpansionLineNumber(L);
+  unsigned LineNo =
+      PLoc.isValid() ? PLoc.getLine() : SM.getExpansionLineNumber(L);
   return llvm::ConstantInt::get(Int32Ty, LineNo);
 }
 
@@ -4343,7 +4354,7 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
 
   ConstantEmitter Emitter(*this);
   llvm::Constant *Init = Emitter.emitForInitializer(
-        TPO->getValue(), TPO->getType().getAddressSpace(), TPO->getType());
+      TPO->getValue(), TPO->getType().getAddressSpace(), TPO->getType());
 
   if (!Init) {
     ErrorUnsupported(TPO, "template parameter object");
@@ -4361,7 +4372,7 @@ ConstantAddress 
CodeGenModule::GetAddrOfTemplateParamObject(
     GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);
 
-    return ConstantAddress(GV, GV->getValueType(), Alignment);
+  return ConstantAddress(GV, GV->getValueType(), Alignment);
 }
 
 ConstantAddress CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
@@ -4644,105 +4655,104 @@ static bool HasNonDllImportDtor(QualType T) {
 }
 
 namespace {
-  struct FunctionIsDirectlyRecursive
-      : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
-    const StringRef Name;
-    const Builtin::Context &BI;
-    FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C)
-        : Name(N), BI(C) {}
-
-    bool VisitCallExpr(const CallExpr *E) {
-      const FunctionDecl *FD = E->getDirectCallee();
-      if (!FD)
-        return false;
-      AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
-      if (Attr && Name == Attr->getLabel())
-        return true;
-      unsigned BuiltinID = FD->getBuiltinID();
-      if (!BuiltinID || !BI.isLibFunction(BuiltinID))
-        return false;
-      std::string BuiltinNameStr = BI.getName(BuiltinID);
-      StringRef BuiltinName = BuiltinNameStr;
-      return BuiltinName.consume_front("__builtin_") && Name == BuiltinName;
-    }
-
-    bool VisitStmt(const Stmt *S) {
-      for (const Stmt *Child : S->children())
-        if (Child && this->Visit(Child))
-          return true;
+struct FunctionIsDirectlyRecursive
+    : public ConstStmtVisitor<FunctionIsDirectlyRecursive, bool> {
+  const StringRef Name;
+  const Builtin::Context &BI;
+  FunctionIsDirectlyRecursive(StringRef N, const Builtin::Context &C)
+      : Name(N), BI(C) {}
+
+  bool VisitCallExpr(const CallExpr *E) {
+    const FunctionDecl *FD = E->getDirectCallee();
+    if (!FD)
       return false;
-    }
-  };
+    AsmLabelAttr *Attr = FD->getAttr<AsmLabelAttr>();
+    if (Attr && Name == Attr->getLabel())
+      return true;
+    unsigned BuiltinID = FD->getBuiltinID();
+    if (!BuiltinID || !...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/200720
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to