Author: Konstantinos Parasyris
Date: 2026-08-25T14:53:30-07:00
New Revision: 554dd47f288782e6e37f0c903e5851bf5d8a9228

URL: 
https://github.com/llvm/llvm-project/commit/554dd47f288782e6e37f0c903e5851bf5d8a9228
DIFF: 
https://github.com/llvm/llvm-project/commit/554dd47f288782e6e37f0c903e5851bf5d8a9228.diff

LOG: [CIR] Add cir.cxx_module_init_fn_name and cir.static_local_info attributes 
(#215921)

Adds two CIR attributes that record specific declaration facts, so
passes that consume them don't have to query the AST for those particular
facts.

Added: 
    clang/test/CIR/CodeGen/cxx20-module-initializer.cppm
    clang/test/CIR/CodeGen/static-local-info.cpp
    clang/test/CIR/IR/static-local-info.cir

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
    clang/include/clang/CIR/Dialect/IR/CIRDialect.td
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenCXX.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.cpp
    clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index ff66eead4a7db..4c9b41b55ee1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -2011,6 +2011,91 @@ def CIR_ASTVarDeclAttr : CIR_AST<"VarDecl", "var.decl", [
   ASTVarDeclInterface
 ]>;
 
+//===----------------------------------------------------------------------===//
+// StaticLocalInfoAttr
+//===----------------------------------------------------------------------===//
+
+// CIR-native thread-local storage kind. Cases mirror clang::VarDecl::TLSKind
+// so CIRGen can map between them, but CIR does not depend on the underlying
+// clang enumerator values.
+def CIR_TLSKind : CIR_I32EnumAttr<"TLSKind", "thread-local storage kind", [
+  I32EnumAttrCase<"None", 0, "none">,          // clang::VarDecl::TLS_None
+  I32EnumAttrCase<"Static", 1, "static">,      // clang::VarDecl::TLS_Static
+  I32EnumAttrCase<"Dynamic", 2, "dynamic">     // clang::VarDecl::TLS_Dynamic
+]> {
+  let genSpecializedAttr = 0;
+}
+
+// CIR-native template-specialization kind. Cases mirror
+// clang::TemplateSpecializationKind.
+def CIR_TemplateSpecializationKind
+    : CIR_I32EnumAttr<"TemplateSpecializationKind",
+                      "template specialization kind", [
+  // clang::TSK_Undeclared
+  I32EnumAttrCase<"Undeclared", 0, "undeclared">,
+  // clang::TSK_ImplicitInstantiation
+  I32EnumAttrCase<"ImplicitInstantiation", 1, "implicit_instantiation">,
+  // clang::TSK_ExplicitSpecialization
+  I32EnumAttrCase<"ExplicitSpecialization", 2, "explicit_specialization">,
+  // clang::TSK_ExplicitInstantiationDeclaration
+  I32EnumAttrCase<"ExplicitInstantiationDeclaration", 3,
+                  "explicit_instantiation_declaration">,
+  // clang::TSK_ExplicitInstantiationDefinition
+  I32EnumAttrCase<"ExplicitInstantiationDefinition", 4,
+                  "explicit_instantiation_definition">
+]> {
+  let genSpecializedAttr = 0;
+}
+
+def CIR_StaticLocalInfoAttr
+    : CIR_Attr<"StaticLocalInfo", "static_local_info"> {
+  let summary = "Static-local variable facts needed by later lowering";
+  let description = [{
+    Holds the subset of a static-local variable's declaration facts that
+    post-CIRGen lowering needs, as plain data (no `clang::VarDecl` pointer).
+
+    - `local`: whether the variable is a block-scope (local) declaration.
+      Mirrors `clang::VarDecl::isLocalVarDecl()`. The namespace-scope inline
+      variables that also reach guarded initialization are not local.
+
+    - `tls`: the thread-local storage kind (`none`, `static`, or `dynamic`).
+
+    - `is_inline`: whether the variable is inline. Mirrors
+      `clang::VarDecl::isInline()`.
+
+    - `tsk`: the template-specialization kind (`undeclared`,
+      `implicit_instantiation`, `explicit_specialization`,
+      `explicit_instantiation_declaration`, or
+      `explicit_instantiation_definition`).
+
+    Example:
+    ```
+    cir.global ... @x = ...
+      {static_local_info = #cir.static_local_info<
+         local = true, tls = none, is_inline = false, tsk = undeclared>}
+    ```
+
+    Because it stores plain data rather than a `clang::VarDecl` pointer, it
+    round-trips through textual CIR and stays valid once the AST is gone.
+    This is what lets LoweringPrepare consume these facts without a live
+    `clang::ASTContext`; the `$ast` `ASTVarDeclAttr` remains a separate,
+    live-AST handle for consumers that need arbitrary AST properties.
+  }];
+
+  let parameters = (ins
+    "bool":$local,
+    EnumParameter<CIR_TLSKind>:$tls,
+    "bool":$is_inline,
+    EnumParameter<CIR_TemplateSpecializationKind>:$tsk
+  );
+
+  let assemblyFormat = [{
+    `<` struct($local, $tls, $is_inline, $tsk) `>`
+  }];
+
+  let canHaveIllegalCXXABIType = 0;
+}
+
 
//===----------------------------------------------------------------------===//
 // AnnotationAttr
 
//===----------------------------------------------------------------------===//

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index d974cb1fa4544..c0ece1f5ee1df 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -81,6 +81,9 @@ def CIR_Dialect : Dialect {
     static llvm::StringRef getTuneCPUAttrName() { return "cir.tune-cpu"; }
     static llvm::StringRef getTargetFeaturesAttrName() { return 
"cir.target-features"; }
     static llvm::StringRef getCUDABinaryHandleAttrName() { return 
"cir.cu.binary_handle"; }
+    // Mangled symbol name of the C++20 named-module initializer function,
+    // precomputed by CIRGen so later passes don't need a live ASTContext.
+    static llvm::StringRef getCXXModuleInitFnNameAttrName() { return 
"cir.cxx_module_init_fn_name"; }
     static llvm::StringRef getMustTailAttrName() { return "musttail"; }
     static llvm::StringRef getCatchCopyThunkAttrName() { return 
"cir.eh.catch_copy_thunk"; }
 

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a52c37e4860ce..6b57604770420 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3388,6 +3388,7 @@ def CIR_GlobalOp : CIR_Op<"global", [
                        
OptionalAttr<CIR_StaticLocalGuardAttr>:$static_local_guard,
                        OptionalAttr<I64Attr>:$alignment,
                        OptionalAttr<ASTVarDeclInterface>:$ast,
+                       
OptionalAttr<CIR_StaticLocalInfoAttr>:$static_local_info,
                        OptionalAttr<StrAttr>:$section,
                        OptionalAttr<CIR_AnnotationArrayAttr>:$annotations,
                        OptionalAttr<FlatSymbolRefAttr>:$aliasee,

diff  --git a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
index 925df05de91a5..e05074699bd6e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
@@ -237,6 +237,37 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl 
gd) {
 // initialization for each global there. In CIR, we attach a ctor
 // region to the global variable and insert the initialization code
 // into the ctor region. This will be moved into the
+// Map clang's VarDecl::TLSKind onto the CIR-native enum.
+static cir::TLSKind getCIRTLSKind(clang::VarDecl::TLSKind kind) {
+  switch (kind) {
+  case clang::VarDecl::TLS_None:
+    return cir::TLSKind::None;
+  case clang::VarDecl::TLS_Static:
+    return cir::TLSKind::Static;
+  case clang::VarDecl::TLS_Dynamic:
+    return cir::TLSKind::Dynamic;
+  }
+  llvm_unreachable("unknown TLSKind");
+}
+
+// Map clang's TemplateSpecializationKind onto the CIR-native enum.
+static cir::TemplateSpecializationKind
+getCIRTemplateSpecializationKind(clang::TemplateSpecializationKind kind) {
+  switch (kind) {
+  case clang::TSK_Undeclared:
+    return cir::TemplateSpecializationKind::Undeclared;
+  case clang::TSK_ImplicitInstantiation:
+    return cir::TemplateSpecializationKind::ImplicitInstantiation;
+  case clang::TSK_ExplicitSpecialization:
+    return cir::TemplateSpecializationKind::ExplicitSpecialization;
+  case clang::TSK_ExplicitInstantiationDeclaration:
+    return cir::TemplateSpecializationKind::ExplicitInstantiationDeclaration;
+  case clang::TSK_ExplicitInstantiationDefinition:
+    return cir::TemplateSpecializationKind::ExplicitInstantiationDefinition;
+  }
+  llvm_unreachable("unknown clang::TemplateSpecializationKind");
+}
+
 // __cxx_global_var_init function during the LoweringPrepare pass.
 void CIRGenModule::emitCXXSpecialVarDeclInit(const VarDecl *varDecl,
                                              cir::GlobalOp addr,
@@ -270,8 +301,20 @@ void CIRGenModule::emitCXXSpecialVarDeclInit(const VarDecl 
*varDecl,
   // expects "this" in the "generic" address space.
   assert(!cir::MissingFeatures::addressSpace());
 
+  // Attach the AST handle for consumers that need arbitrary AST properties.
   addr.setAstAttr(cir::ASTVarDeclAttr::get(&getMLIRContext(), varDecl));
 
+  // For static-local guarded globals, also materialize the specific facts
+  // LoweringPrepare needs into a serializable attribute, so that lowering can
+  // run without a live ASTContext (e.g. on serialized CIR in split-compilation
+  // flows). This is orthogonal to the AST handle above.
+  if (addr.getStaticLocalGuard().has_value())
+    addr.setStaticLocalInfoAttr(cir::StaticLocalInfoAttr::get(
+        &getMLIRContext(), varDecl->isLocalVarDecl(),
+        getCIRTLSKind(varDecl->getTLSKind()), varDecl->isInline(),
+        getCIRTemplateSpecializationKind(
+            varDecl->getTemplateSpecializationKind())));
+
   if (!ty->isReferenceType()) {
     assert(!cir::MissingFeatures::openMP());
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp 
b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 6c49afe243606..9db6edbc9b519 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -24,9 +24,11 @@
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclOpenACC.h"
 #include "clang/AST/GlobalDecl.h"
+#include "clang/AST/Mangle.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtOpenMP.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
@@ -3889,6 +3891,23 @@ void CIRGenModule::release() {
 
   emitLLVMUsed();
 
+  // Precompute the mangled C++20 named-module initializer function name and
+  // stash it on the ModuleOp so LoweringPrepare (which may run without a live
+  // ASTContext in split-compilation flows) can read it back as an attribute.
+  if (langOpts.CPlusPlusModules &&
+      getCXXABI().getMangleContext().getKind() ==
+          clang::ItaniumMangleContext::MK_Itanium) {
+    if (clang::Module *primary = astContext.getCurrentNamedModule();
+        primary && !primary->isModuleImplementation()) {
+      llvm::SmallString<256> fnName;
+      llvm::raw_svector_ostream out(fnName);
+      cast<clang::ItaniumMangleContext>(getCXXABI().getMangleContext())
+          .mangleModuleInitializer(primary, out);
+      theModule->setAttr(cir::CIRDialect::getCXXModuleInitFnNameAttrName(),
+                         builder.getStringAttr(fnName));
+    }
+  }
+
   // Classic codegen calls `checkAliases` here to validate any alias
   // definitions emitted during codegen.
   assert(!cir::MissingFeatures::checkAliases());

diff  --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index 5ede978c4d671..f4ea135032493 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -425,9 +425,8 @@ struct LoweringPreparePass
   /// following OG's ItaniumCXXABI::EmitGuardedInit skeleton.
   void emitCXXGuardedInitIf(CIRBaseBuilderTy &builder, cir::GlobalOp globalOp,
                             mlir::Region &ctorRegion, mlir::Region &dtorRegion,
-                            cir::ASTVarDeclInterface varDecl,
-                            mlir::Value guardPtr, cir::PointerType guardPtrTy,
-                            bool threadsafe) {
+                            bool isLocalVarDecl, mlir::Value guardPtr,
+                            cir::PointerType guardPtrTy, bool threadsafe) {
     auto loc = globalOp->getLoc();
 
     // The semantics of dynamic initialization of variables with static or
@@ -525,7 +524,7 @@ struct LoweringPreparePass
                            mlir::ValueRange{guardPtr});
 
       builder.createYield(loc);
-    } else if (!varDecl.isLocalVarDecl()) {
+    } else if (!isLocalVarDecl) {
       // For non-local variables, store 1 into the first byte of the guard
       // variable before the object initialization begins so that references
       // to the variable during initialization don't restart initialization.
@@ -1353,9 +1352,12 @@ void 
LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
                                             cir::LocalInitOp localInitOp) {
   CIRBaseBuilderTy builder(getContext());
 
-  std::optional<cir::ASTVarDeclInterface> astOption = globalOp.getAst();
-  assert(astOption.has_value());
-  cir::ASTVarDeclInterface varDecl = astOption.value();
+  // Static-local facts are materialized into a serializable attribute by
+  // CIRGen, so this pass does not need a live ASTContext to read them.
+  std::optional<cir::StaticLocalInfoAttr> infoOption =
+      globalOp.getStaticLocalInfo();
+  assert(infoOption.has_value());
+  cir::StaticLocalInfoAttr info = infoOption.value();
 
   builder.setInsertionPointAfter(localInitOp);
   mlir::Block *localInitBlock = builder.getInsertionBlock();
@@ -1369,9 +1371,13 @@ void 
LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
 
   // Inline variables that weren't instantiated from variable templates have
   // partially-ordered initialization within their translation unit.
-  bool nonTemplateInline =
-      varDecl.isInline() &&
-      !clang::isTemplateInstantiation(varDecl.getTemplateSpecializationKind());
+  cir::TemplateSpecializationKind tsk = info.getTsk();
+  bool isTemplateInstantiation =
+      tsk == cir::TemplateSpecializationKind::ImplicitInstantiation ||
+      tsk ==
+          cir::TemplateSpecializationKind::ExplicitInstantiationDeclaration ||
+      tsk == cir::TemplateSpecializationKind::ExplicitInstantiationDefinition;
+  bool nonTemplateInline = info.getIsInline() && !isTemplateInstantiation;
 
   // Inline namespace-scope variables require guarded initialization in a
   // __cxx_global_var_init function. This is not yet implemented.
@@ -1385,8 +1391,8 @@ void LoweringPreparePass::handleStaticLocal(cir::GlobalOp 
globalOp,
   // inline variables; other global initialization is always single-threaded
   // or (through lazy dynamic loading in multiple threads) unsequenced.
   bool threadsafe = astCtx->getLangOpts().ThreadsafeStatics &&
-                    (varDecl.isLocalVarDecl() || nonTemplateInline) &&
-                    !varDecl.getTLSKind();
+                    (info.getLocal() || nonTemplateInline) &&
+                    info.getTls() == cir::TLSKind::None;
 
   // If we have a global variable with internal linkage and thread-safe statics
   // are disabled, we can just let the guard variable be of type i8.
@@ -1395,7 +1401,7 @@ void LoweringPreparePass::handleStaticLocal(cir::GlobalOp 
globalOp,
   // Create the guard variable if we don't already have it.
   cir::GlobalOp guard = getOrCreateStaticLocalDeclGuardAddress(
       builder, globalOp, globalOp.getStaticLocalGuard()->getName().getValue(),
-      varDecl.isLocalVarDecl(), useInt8GuardVariable);
+      info.getLocal(), useInt8GuardVariable);
   if (!guard) {
     // Error was already emitted, just restore the terminator and return.
     localInitBlock->push_back(ret);
@@ -1483,10 +1489,10 @@ void 
LoweringPreparePass::handleStaticLocal(cir::GlobalOp globalOp,
     cir::IfOp::create(
         builder, globalOp.getLoc(), needsInit,
         /*withElseRegion=*/false, [&](mlir::OpBuilder &, mlir::Location) {
-          emitCXXGuardedInitIf(builder, globalOp, localInitOp.getCtorRegion(),
-                               localInitOp.getDtorRegion(), varDecl, guardPtr,
-                               builder.getPointerTo(guard.getSymType()),
-                               threadsafe);
+          emitCXXGuardedInitIf(
+              builder, globalOp, localInitOp.getCtorRegion(),
+              localInitOp.getDtorRegion(), info.getLocal(), guardPtr,
+              builder.getPointerTo(guard.getSymType()), threadsafe);
         });
   } else {
     // Threadsafe statics without inline atomics - call __cxa_guard_acquire
@@ -1967,9 +1973,16 @@ void LoweringPreparePass::buildCXXGlobalInitFunc() {
   // and makes sure these symbols appear lexicographically behind the symbols
   // with priority (TBD).  Module implementation units behave the same
   // way as a non-modular TU with imports.
-  // TODO: check CXX20ModuleInits
-  if (astCtx->getCurrentNamedModule() &&
-      !astCtx->getCurrentNamedModule()->isModuleImplementation()) {
+  // The C++20 named-module init function name is precomputed by CIRGen and
+  // stored as a module-level attribute, so this pass does not need a live
+  // ASTContext in split-compilation flows. Fall back to the AST-based path
+  // only when the attribute is absent (e.g. tests that bypass CIRGen).
+  if (auto fnNameAttr = mlirModule->getAttrOfType<mlir::StringAttr>(
+          cir::CIRDialect::getCXXModuleInitFnNameAttrName())) {
+    fnName += fnNameAttr.getValue();
+    linkage = cir::GlobalLinkageKind::ExternalLinkage;
+  } else if (astCtx && astCtx->getCurrentNamedModule() &&
+             !astCtx->getCurrentNamedModule()->isModuleImplementation()) {
     llvm::raw_svector_ostream out(fnName);
     std::unique_ptr<clang::MangleContext> mangleCtx(
         astCtx->createMangleContext());

diff  --git a/clang/test/CIR/CodeGen/cxx20-module-initializer.cppm 
b/clang/test/CIR/CodeGen/cxx20-module-initializer.cppm
new file mode 100644
index 0000000000000..2122a5e97636d
--- /dev/null
+++ b/clang/test/CIR/CodeGen/cxx20-module-initializer.cppm
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+
+// CIRGen precomputes the mangled C++20 named-module initializer function
+// name and stores it as a module-level attribute so LoweringPrepare can
+// build the initializer without a live ASTContext after split-compilation.
+// The dynamic initializer below forces LoweringPrepare to actually emit that
+// initializer function, which must have external linkage for a named-module
+// interface unit.
+
+export module A;
+
+int foo();
+int x = foo();
+
+// CIR: module
+// CIR-SAME: cir.cxx_module_init_fn_name = "_ZGIW1A"
+
+// The initializer for a named-module interface unit has external linkage.
+// (Internal linkage would render as "cir.func internal private", so matching
+// "cir.func private" immediately after the name asserts external linkage.)
+// CIR: cir.func private @_ZGIW1A()

diff  --git a/clang/test/CIR/CodeGen/static-local-info.cpp 
b/clang/test/CIR/CodeGen/static-local-info.cpp
new file mode 100644
index 0000000000000..2345703d8a875
--- /dev/null
+++ b/clang/test/CIR/CodeGen/static-local-info.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir \
+// RUN:   -emit-cir %s -o - | FileCheck %s
+
+// CIRGen attaches the VarDecl facts LoweringPrepare needs (isLocalVarDecl,
+// TLSKind, isInline, TemplateSpecializationKind) to static-local guarded
+// globals as a #cir.static_local_info attribute, so the facts survive without
+// a live ASTContext. This is orthogonal to the #cir.var.decl AST handle, which
+// is still attached for consumers that need arbitrary AST properties.
+
+struct HasCtor {
+  HasCtor();
+  int x;
+};
+
+int regular() {
+  static HasCtor s;
+  return s.x;
+}
+
+int tls() {
+  static thread_local HasCtor s;
+  return s.x;
+}
+
+// The thread_local static local materializes a non-default TLS kind, alongside
+// the retained AST handle.
+// CHECK: @_ZZ3tlsvE1s
+// CHECK-SAME: ast = #cir.var.decl.ast
+// CHECK-SAME: static_local_info = #cir.static_local_info<local = true, tls = 
dynamic, is_inline = false, tsk = undeclared>
+
+// CHECK: @_ZZ7regularvE1s
+// CHECK-SAME: ast = #cir.var.decl.ast
+// CHECK-SAME: static_local_info = #cir.static_local_info<local = true, tls = 
none, is_inline = false, tsk = undeclared>

diff  --git a/clang/test/CIR/IR/static-local-info.cir 
b/clang/test/CIR/IR/static-local-info.cir
new file mode 100644
index 0000000000000..b5c8f8919224a
--- /dev/null
+++ b/clang/test/CIR/IR/static-local-info.cir
@@ -0,0 +1,21 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+// #cir.static_local_info holds plain data (no AST pointer), so it parses and
+// prints without a live ASTContext. Check that each field round-trips,
+// including the named tls / tsk enum keywords at non-default values.
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.global "private" internal @regular = #cir.int<0> : !s32i
+    {static_local_info = #cir.static_local_info<
+       local = true, tls = none, is_inline = false, tsk = undeclared>}
+  // CHECK: @regular
+  // CHECK-SAME: static_local_info = #cir.static_local_info<local = true, tls 
= none, is_inline = false, tsk = undeclared>
+
+  cir.global "private" internal @tls = #cir.int<0> : !s32i
+    {static_local_info = #cir.static_local_info<
+       local = true, tls = dynamic, is_inline = true, tsk = 
implicit_instantiation>}
+  // CHECK: @tls
+  // CHECK-SAME: static_local_info = #cir.static_local_info<local = true, tls 
= dynamic, is_inline = true, tsk = implicit_instantiation>
+}


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

Reply via email to