Skip to content

Conversation

@jurahul
Copy link
Contributor

@jurahul jurahul commented Nov 13, 2025

Always rely on local scopes to enforce the lifetime of these helper objects and by extension where the "closing" of various C++ code constructs happens.

Always rely on local scopes to enforce the lifetime of these
helper objects and by extension where the "closing" of various
C++ code constructs happens.
@jurahul jurahul marked this pull request as ready for review November 13, 2025 17:22
@llvmbot llvmbot added mlir:core MLIR Core Infrastructure tablegen mlir labels Nov 13, 2025
@jurahul jurahul requested a review from topperc November 13, 2025 17:23
@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-tablegen

@llvm/pr-subscribers-mlir

Author: Rahul Joshi (jurahul)

Changes

Always rely on local scopes to enforce the lifetime of these helper objects and by extension where the "closing" of various C++ code constructs happens.


Full diff: https://github.com/llvm/llvm-project/pull/167904.diff

3 Files Affected:

  • (modified) llvm/include/llvm/TableGen/CodeGenHelpers.h (+3-27)
  • (modified) llvm/utils/TableGen/Basic/DirectiveEmitter.cpp (+62-61)
  • (modified) mlir/tools/mlir-tblgen/EnumsGen.cpp (+41-38)
diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h
index e357b2670be15..1b1b5e63a8fc4 100644
--- a/llvm/include/llvm/TableGen/CodeGenHelpers.h
+++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h
@@ -33,25 +33,17 @@ class IfDefEmitter {
       OS << "#undef " << Name << "\n";
     OS << "\n";
   }
-  ~IfDefEmitter() { close(); }
-
-  // Explicit function to close the ifdef scopes.
-  void close() {
-    if (Closed)
-      return;
-
+  ~IfDefEmitter() {
     OS << "\n";
     if (LateUndef)
       OS << "#undef " << Name << "\n";
     OS << "#endif // " << Name << "\n\n";
-    Closed = true;
   }
 
 private:
   std::string Name;
   raw_ostream &OS;
   bool LateUndef;
-  bool Closed = false;
 };
 
 // Simple RAII helper for emitting header include guard (ifndef-define-endif).
@@ -62,20 +54,11 @@ class IncludeGuardEmitter {
     OS << "#ifndef " << Name << "\n"
        << "#define " << Name << "\n\n";
   }
-  ~IncludeGuardEmitter() { close(); }
-
-  // Explicit function to close the ifdef scopes.
-  void close() {
-    if (Closed)
-      return;
-    OS << "\n#endif // " << Name << "\n\n";
-    Closed = true;
-  }
+  ~IncludeGuardEmitter() { OS << "\n#endif // " << Name << "\n\n"; }
 
 private:
   std::string Name;
   raw_ostream &OS;
-  bool Closed = false;
 };
 
 // Simple RAII helper for emitting namespace scope. Name can be a single
@@ -89,15 +72,9 @@ class NamespaceEmitter {
       OS << "namespace " << Name << " {\n\n";
   }
 
-  ~NamespaceEmitter() { close(); }
-
-  // Explicit function to close the namespace scopes.
-  void close() {
-    if (Closed)
-      return;
+  ~NamespaceEmitter() {
     if (!Name.empty())
       OS << "\n} // namespace " << Name << "\n";
-    Closed = true;
   }
 
 private:
@@ -114,7 +91,6 @@ class NamespaceEmitter {
   }
   std::string Name;
   raw_ostream &OS;
-  bool Closed = false;
 };
 
 } // end namespace llvm
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 0bb743dc8a7f5..3a488ed952210 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -276,80 +276,81 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
   OS << "#include <utility>\n"; // for std::pair
   OS << "\n";
   NamespaceEmitter LlvmNS(OS, "llvm");
-  NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
-
-  if (DirLang.hasEnableBitmaskEnumInNamespace())
-    OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n\n";
-
-  // Emit Directive associations
-  std::vector<const Record *> Associations;
-  copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
-          // Skip the "special" value
-          [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
-  generateEnumClass(Associations, OS, "Association",
-                    /*Prefix=*/"", /*ExportEnums=*/false);
+  {
+    NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
+
+    if (DirLang.hasEnableBitmaskEnumInNamespace())
+      OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n\n";
+
+    // Emit Directive associations
+    std::vector<const Record *> Associations;
+    copy_if(
+        DirLang.getAssociations(), std::back_inserter(Associations),
+        // Skip the "special" value
+        [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
+    generateEnumClass(Associations, OS, "Association",
+                      /*Prefix=*/"", /*ExportEnums=*/false);
 
-  generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
-                    /*ExportEnums=*/false);
+    generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
+                      /*ExportEnums=*/false);
 
-  generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
-                      /*Prefix=*/"", /*ExportEnums=*/false);
+    generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
+                        /*Prefix=*/"", /*ExportEnums=*/false);
 
-  // Emit Directive enumeration
-  generateEnumClass(DirLang.getDirectives(), OS, "Directive",
-                    DirLang.getDirectivePrefix(),
-                    DirLang.hasMakeEnumAvailableInNamespace());
+    // Emit Directive enumeration
+    generateEnumClass(DirLang.getDirectives(), OS, "Directive",
+                      DirLang.getDirectivePrefix(),
+                      DirLang.hasMakeEnumAvailableInNamespace());
 
-  // Emit Clause enumeration
-  generateEnumClass(DirLang.getClauses(), OS, "Clause",
-                    DirLang.getClausePrefix(),
-                    DirLang.hasMakeEnumAvailableInNamespace());
+    // Emit Clause enumeration
+    generateEnumClass(DirLang.getClauses(), OS, "Clause",
+                      DirLang.getClausePrefix(),
+                      DirLang.hasMakeEnumAvailableInNamespace());
 
-  // Emit ClauseVals enumeration
-  std::string EnumHelperFuncs;
-  generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
+    // Emit ClauseVals enumeration
+    std::string EnumHelperFuncs;
+    generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
 
-  // Generic function signatures
-  OS << "// Enumeration helper functions\n";
+    // Generic function signatures
+    OS << "// Enumeration helper functions\n";
 
-  OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
-     << "DirectiveKindAndVersions(StringRef Str);\n";
+    OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
+       << "DirectiveKindAndVersions(StringRef Str);\n";
 
-  OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
-  OS << "  return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
-  OS << "}\n";
-  OS << "\n";
+    OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
+    OS << "  return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
+    OS << "}\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI StringRef get" << Lang
-     << "DirectiveName(Directive D, unsigned Ver = 0);\n";
-  OS << "\n";
+    OS << "LLVM_ABI StringRef get" << Lang
+       << "DirectiveName(Directive D, unsigned Ver = 0);\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
-     << "ClauseKindAndVersions(StringRef Str);\n";
-  OS << "\n";
+    OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
+       << "ClauseKindAndVersions(StringRef Str);\n";
+    OS << "\n";
 
-  OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
-  OS << "  return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
-  OS << "}\n";
-  OS << "\n";
+    OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
+    OS << "  return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
+    OS << "}\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI StringRef get" << Lang
-     << "ClauseName(Clause C, unsigned Ver = 0);\n";
-  OS << "\n";
+    OS << "LLVM_ABI StringRef get" << Lang
+       << "ClauseName(Clause C, unsigned Ver = 0);\n";
+    OS << "\n";
 
-  OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
-     << "Version.\n";
-  OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
-     << "Clause C, unsigned Version);\n";
-  OS << "\n";
-  OS << "constexpr std::size_t getMaxLeafCount() { return "
-     << getMaxLeafCount(DirLang) << "; }\n";
-  OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
-  OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
-  OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
-  OS << EnumHelperFuncs;
-
-  DirLangNS.close();
+    OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
+       << "Version.\n";
+    OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
+       << "Clause C, unsigned Version);\n";
+    OS << "\n";
+    OS << "constexpr std::size_t getMaxLeafCount() { return "
+       << getMaxLeafCount(DirLang) << "; }\n";
+    OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
+    OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
+    OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
+    OS << EnumHelperFuncs;
+  } // close DirLangNS
 
   // These specializations need to be in ::llvm.
   for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) {
diff --git a/mlir/tools/mlir-tblgen/EnumsGen.cpp b/mlir/tools/mlir-tblgen/EnumsGen.cpp
index 11bf9ce732ce6..8c7f9f7b4bc49 100644
--- a/mlir/tools/mlir-tblgen/EnumsGen.cpp
+++ b/mlir/tools/mlir-tblgen/EnumsGen.cpp
@@ -702,41 +702,45 @@ static void emitEnumDecl(const Record &enumDef, raw_ostream &os) {
   StringRef underlyingToSymFnName = enumInfo.getUnderlyingToSymbolFnName();
   auto enumerants = enumInfo.getAllCases();
 
-  llvm::NamespaceEmitter ns(os, cppNamespace);
-
-  // Emit the enum class definition
-  emitEnumClass(enumDef, enumName, underlyingType, description, enumerants, os);
-
-  // Emit conversion function declarations
-  if (llvm::all_of(enumerants, [](EnumCase enumerant) {
-        return enumerant.getValue() >= 0;
-      })) {
-    os << formatv(
-        "::std::optional<{0}> {1}({2});\n", enumName, underlyingToSymFnName,
-        underlyingType.empty() ? std::string("unsigned") : underlyingType);
-  }
-  os << formatv("{2} {1}({0});\n", enumName, symToStrFnName, symToStrFnRetType);
-  os << formatv("::std::optional<{0}> {1}(::llvm::StringRef);\n", enumName,
-                strToSymFnName);
-
-  if (enumInfo.isBitEnum()) {
-    emitOperators(enumDef, os);
-  } else {
-    emitMaxValueFn(enumDef, os);
-  }
+  {
+    llvm::NamespaceEmitter ns(os, cppNamespace);
+
+    // Emit the enum class definition
+    emitEnumClass(enumDef, enumName, underlyingType, description, enumerants,
+                  os);
+
+    // Emit conversion function declarations
+    if (llvm::all_of(enumerants, [](EnumCase enumerant) {
+          return enumerant.getValue() >= 0;
+        })) {
+      os << formatv(
+          "::std::optional<{0}> {1}({2});\n", enumName, underlyingToSymFnName,
+          underlyingType.empty() ? std::string("unsigned") : underlyingType);
+    }
+    os << formatv("{2} {1}({0});\n", enumName, symToStrFnName,
+                  symToStrFnRetType);
+    os << formatv("::std::optional<{0}> {1}(::llvm::StringRef);\n", enumName,
+                  strToSymFnName);
+
+    if (enumInfo.isBitEnum()) {
+      emitOperators(enumDef, os);
+    } else {
+      emitMaxValueFn(enumDef, os);
+    }
 
-  // Generate a generic `stringifyEnum` function that forwards to the method
-  // specified by the user.
-  const char *const stringifyEnumStr = R"(
+    // Generate a generic `stringifyEnum` function that forwards to the method
+    // specified by the user.
+    const char *const stringifyEnumStr = R"(
 inline {0} stringifyEnum({1} enumValue) {{
   return {2}(enumValue);
 }
 )";
-  os << formatv(stringifyEnumStr, symToStrFnRetType, enumName, symToStrFnName);
+    os << formatv(stringifyEnumStr, symToStrFnRetType, enumName,
+                  symToStrFnName);
 
-  // Generate a generic `symbolizeEnum` function that forwards to the method
-  // specified by the user.
-  const char *const symbolizeEnumStr = R"(
+    // Generate a generic `symbolizeEnum` function that forwards to the method
+    // specified by the user.
+    const char *const symbolizeEnumStr = R"(
 template <typename EnumType>
 ::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);
 
@@ -745,9 +749,9 @@ inline ::std::optional<{0}> symbolizeEnum<{0}>(::llvm::StringRef str) {
   return {1}(str);
 }
 )";
-  os << formatv(symbolizeEnumStr, enumName, strToSymFnName);
+    os << formatv(symbolizeEnumStr, enumName, strToSymFnName);
 
-  const char *const attrClassDecl = R"(
+    const char *const attrClassDecl = R"(
 class {1} : public ::mlir::{2} {
 public:
   using ValueType = {0};
@@ -757,13 +761,12 @@ class {1} : public ::mlir::{2} {
   {0} getValue() const;
 };
 )";
-  if (enumInfo.genSpecializedAttr()) {
-    StringRef attrClassName = enumInfo.getSpecializedAttrClassName();
-    StringRef baseAttrClassName = "IntegerAttr";
-    os << formatv(attrClassDecl, enumName, attrClassName, baseAttrClassName);
-  }
-
-  ns.close();
+    if (enumInfo.genSpecializedAttr()) {
+      StringRef attrClassName = enumInfo.getSpecializedAttrClassName();
+      StringRef baseAttrClassName = "IntegerAttr";
+      os << formatv(attrClassDecl, enumName, attrClassName, baseAttrClassName);
+    }
+  } // close `ns`.
 
   // Generate a generic parser and printer for the enum.
   std::string qualName =

@llvmbot
Copy link
Member

llvmbot commented Nov 13, 2025

@llvm/pr-subscribers-mlir-core

Author: Rahul Joshi (jurahul)

Changes

Always rely on local scopes to enforce the lifetime of these helper objects and by extension where the "closing" of various C++ code constructs happens.


Full diff: https://github.com/llvm/llvm-project/pull/167904.diff

3 Files Affected:

  • (modified) llvm/include/llvm/TableGen/CodeGenHelpers.h (+3-27)
  • (modified) llvm/utils/TableGen/Basic/DirectiveEmitter.cpp (+62-61)
  • (modified) mlir/tools/mlir-tblgen/EnumsGen.cpp (+41-38)
diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h
index e357b2670be15..1b1b5e63a8fc4 100644
--- a/llvm/include/llvm/TableGen/CodeGenHelpers.h
+++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h
@@ -33,25 +33,17 @@ class IfDefEmitter {
       OS << "#undef " << Name << "\n";
     OS << "\n";
   }
-  ~IfDefEmitter() { close(); }
-
-  // Explicit function to close the ifdef scopes.
-  void close() {
-    if (Closed)
-      return;
-
+  ~IfDefEmitter() {
     OS << "\n";
     if (LateUndef)
       OS << "#undef " << Name << "\n";
     OS << "#endif // " << Name << "\n\n";
-    Closed = true;
   }
 
 private:
   std::string Name;
   raw_ostream &OS;
   bool LateUndef;
-  bool Closed = false;
 };
 
 // Simple RAII helper for emitting header include guard (ifndef-define-endif).
@@ -62,20 +54,11 @@ class IncludeGuardEmitter {
     OS << "#ifndef " << Name << "\n"
        << "#define " << Name << "\n\n";
   }
-  ~IncludeGuardEmitter() { close(); }
-
-  // Explicit function to close the ifdef scopes.
-  void close() {
-    if (Closed)
-      return;
-    OS << "\n#endif // " << Name << "\n\n";
-    Closed = true;
-  }
+  ~IncludeGuardEmitter() { OS << "\n#endif // " << Name << "\n\n"; }
 
 private:
   std::string Name;
   raw_ostream &OS;
-  bool Closed = false;
 };
 
 // Simple RAII helper for emitting namespace scope. Name can be a single
@@ -89,15 +72,9 @@ class NamespaceEmitter {
       OS << "namespace " << Name << " {\n\n";
   }
 
-  ~NamespaceEmitter() { close(); }
-
-  // Explicit function to close the namespace scopes.
-  void close() {
-    if (Closed)
-      return;
+  ~NamespaceEmitter() {
     if (!Name.empty())
       OS << "\n} // namespace " << Name << "\n";
-    Closed = true;
   }
 
 private:
@@ -114,7 +91,6 @@ class NamespaceEmitter {
   }
   std::string Name;
   raw_ostream &OS;
-  bool Closed = false;
 };
 
 } // end namespace llvm
diff --git a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
index 0bb743dc8a7f5..3a488ed952210 100644
--- a/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/DirectiveEmitter.cpp
@@ -276,80 +276,81 @@ static void emitDirectivesDecl(const RecordKeeper &Records, raw_ostream &OS) {
   OS << "#include <utility>\n"; // for std::pair
   OS << "\n";
   NamespaceEmitter LlvmNS(OS, "llvm");
-  NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
-
-  if (DirLang.hasEnableBitmaskEnumInNamespace())
-    OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n\n";
-
-  // Emit Directive associations
-  std::vector<const Record *> Associations;
-  copy_if(DirLang.getAssociations(), std::back_inserter(Associations),
-          // Skip the "special" value
-          [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
-  generateEnumClass(Associations, OS, "Association",
-                    /*Prefix=*/"", /*ExportEnums=*/false);
+  {
+    NamespaceEmitter DirLangNS(OS, DirLang.getCppNamespace());
+
+    if (DirLang.hasEnableBitmaskEnumInNamespace())
+      OS << "LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n\n";
+
+    // Emit Directive associations
+    std::vector<const Record *> Associations;
+    copy_if(
+        DirLang.getAssociations(), std::back_inserter(Associations),
+        // Skip the "special" value
+        [](const Record *Def) { return Def->getName() != "AS_FromLeaves"; });
+    generateEnumClass(Associations, OS, "Association",
+                      /*Prefix=*/"", /*ExportEnums=*/false);
 
-  generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
-                    /*ExportEnums=*/false);
+    generateEnumClass(DirLang.getCategories(), OS, "Category", /*Prefix=*/"",
+                      /*ExportEnums=*/false);
 
-  generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
-                      /*Prefix=*/"", /*ExportEnums=*/false);
+    generateEnumBitmask(DirLang.getSourceLanguages(), OS, "SourceLanguage",
+                        /*Prefix=*/"", /*ExportEnums=*/false);
 
-  // Emit Directive enumeration
-  generateEnumClass(DirLang.getDirectives(), OS, "Directive",
-                    DirLang.getDirectivePrefix(),
-                    DirLang.hasMakeEnumAvailableInNamespace());
+    // Emit Directive enumeration
+    generateEnumClass(DirLang.getDirectives(), OS, "Directive",
+                      DirLang.getDirectivePrefix(),
+                      DirLang.hasMakeEnumAvailableInNamespace());
 
-  // Emit Clause enumeration
-  generateEnumClass(DirLang.getClauses(), OS, "Clause",
-                    DirLang.getClausePrefix(),
-                    DirLang.hasMakeEnumAvailableInNamespace());
+    // Emit Clause enumeration
+    generateEnumClass(DirLang.getClauses(), OS, "Clause",
+                      DirLang.getClausePrefix(),
+                      DirLang.hasMakeEnumAvailableInNamespace());
 
-  // Emit ClauseVals enumeration
-  std::string EnumHelperFuncs;
-  generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
+    // Emit ClauseVals enumeration
+    std::string EnumHelperFuncs;
+    generateClauseEnumVal(DirLang.getClauses(), OS, DirLang, EnumHelperFuncs);
 
-  // Generic function signatures
-  OS << "// Enumeration helper functions\n";
+    // Generic function signatures
+    OS << "// Enumeration helper functions\n";
 
-  OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
-     << "DirectiveKindAndVersions(StringRef Str);\n";
+    OS << "LLVM_ABI std::pair<Directive, directive::VersionRange> get" << Lang
+       << "DirectiveKindAndVersions(StringRef Str);\n";
 
-  OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
-  OS << "  return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
-  OS << "}\n";
-  OS << "\n";
+    OS << "inline Directive get" << Lang << "DirectiveKind(StringRef Str) {\n";
+    OS << "  return get" << Lang << "DirectiveKindAndVersions(Str).first;\n";
+    OS << "}\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI StringRef get" << Lang
-     << "DirectiveName(Directive D, unsigned Ver = 0);\n";
-  OS << "\n";
+    OS << "LLVM_ABI StringRef get" << Lang
+       << "DirectiveName(Directive D, unsigned Ver = 0);\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
-     << "ClauseKindAndVersions(StringRef Str);\n";
-  OS << "\n";
+    OS << "LLVM_ABI std::pair<Clause, directive::VersionRange> get" << Lang
+       << "ClauseKindAndVersions(StringRef Str);\n";
+    OS << "\n";
 
-  OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
-  OS << "  return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
-  OS << "}\n";
-  OS << "\n";
+    OS << "inline Clause get" << Lang << "ClauseKind(StringRef Str) {\n";
+    OS << "  return get" << Lang << "ClauseKindAndVersions(Str).first;\n";
+    OS << "}\n";
+    OS << "\n";
 
-  OS << "LLVM_ABI StringRef get" << Lang
-     << "ClauseName(Clause C, unsigned Ver = 0);\n";
-  OS << "\n";
+    OS << "LLVM_ABI StringRef get" << Lang
+       << "ClauseName(Clause C, unsigned Ver = 0);\n";
+    OS << "\n";
 
-  OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
-     << "Version.\n";
-  OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
-     << "Clause C, unsigned Version);\n";
-  OS << "\n";
-  OS << "constexpr std::size_t getMaxLeafCount() { return "
-     << getMaxLeafCount(DirLang) << "; }\n";
-  OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
-  OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
-  OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
-  OS << EnumHelperFuncs;
-
-  DirLangNS.close();
+    OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
+       << "Version.\n";
+    OS << "LLVM_ABI bool isAllowedClauseForDirective(Directive D, "
+       << "Clause C, unsigned Version);\n";
+    OS << "\n";
+    OS << "constexpr std::size_t getMaxLeafCount() { return "
+       << getMaxLeafCount(DirLang) << "; }\n";
+    OS << "LLVM_ABI Association getDirectiveAssociation(Directive D);\n";
+    OS << "LLVM_ABI Category getDirectiveCategory(Directive D);\n";
+    OS << "LLVM_ABI SourceLanguage getDirectiveLanguages(Directive D);\n";
+    OS << EnumHelperFuncs;
+  } // close DirLangNS
 
   // These specializations need to be in ::llvm.
   for (StringRef Enum : {"Association", "Category", "Directive", "Clause"}) {
diff --git a/mlir/tools/mlir-tblgen/EnumsGen.cpp b/mlir/tools/mlir-tblgen/EnumsGen.cpp
index 11bf9ce732ce6..8c7f9f7b4bc49 100644
--- a/mlir/tools/mlir-tblgen/EnumsGen.cpp
+++ b/mlir/tools/mlir-tblgen/EnumsGen.cpp
@@ -702,41 +702,45 @@ static void emitEnumDecl(const Record &enumDef, raw_ostream &os) {
   StringRef underlyingToSymFnName = enumInfo.getUnderlyingToSymbolFnName();
   auto enumerants = enumInfo.getAllCases();
 
-  llvm::NamespaceEmitter ns(os, cppNamespace);
-
-  // Emit the enum class definition
-  emitEnumClass(enumDef, enumName, underlyingType, description, enumerants, os);
-
-  // Emit conversion function declarations
-  if (llvm::all_of(enumerants, [](EnumCase enumerant) {
-        return enumerant.getValue() >= 0;
-      })) {
-    os << formatv(
-        "::std::optional<{0}> {1}({2});\n", enumName, underlyingToSymFnName,
-        underlyingType.empty() ? std::string("unsigned") : underlyingType);
-  }
-  os << formatv("{2} {1}({0});\n", enumName, symToStrFnName, symToStrFnRetType);
-  os << formatv("::std::optional<{0}> {1}(::llvm::StringRef);\n", enumName,
-                strToSymFnName);
-
-  if (enumInfo.isBitEnum()) {
-    emitOperators(enumDef, os);
-  } else {
-    emitMaxValueFn(enumDef, os);
-  }
+  {
+    llvm::NamespaceEmitter ns(os, cppNamespace);
+
+    // Emit the enum class definition
+    emitEnumClass(enumDef, enumName, underlyingType, description, enumerants,
+                  os);
+
+    // Emit conversion function declarations
+    if (llvm::all_of(enumerants, [](EnumCase enumerant) {
+          return enumerant.getValue() >= 0;
+        })) {
+      os << formatv(
+          "::std::optional<{0}> {1}({2});\n", enumName, underlyingToSymFnName,
+          underlyingType.empty() ? std::string("unsigned") : underlyingType);
+    }
+    os << formatv("{2} {1}({0});\n", enumName, symToStrFnName,
+                  symToStrFnRetType);
+    os << formatv("::std::optional<{0}> {1}(::llvm::StringRef);\n", enumName,
+                  strToSymFnName);
+
+    if (enumInfo.isBitEnum()) {
+      emitOperators(enumDef, os);
+    } else {
+      emitMaxValueFn(enumDef, os);
+    }
 
-  // Generate a generic `stringifyEnum` function that forwards to the method
-  // specified by the user.
-  const char *const stringifyEnumStr = R"(
+    // Generate a generic `stringifyEnum` function that forwards to the method
+    // specified by the user.
+    const char *const stringifyEnumStr = R"(
 inline {0} stringifyEnum({1} enumValue) {{
   return {2}(enumValue);
 }
 )";
-  os << formatv(stringifyEnumStr, symToStrFnRetType, enumName, symToStrFnName);
+    os << formatv(stringifyEnumStr, symToStrFnRetType, enumName,
+                  symToStrFnName);
 
-  // Generate a generic `symbolizeEnum` function that forwards to the method
-  // specified by the user.
-  const char *const symbolizeEnumStr = R"(
+    // Generate a generic `symbolizeEnum` function that forwards to the method
+    // specified by the user.
+    const char *const symbolizeEnumStr = R"(
 template <typename EnumType>
 ::std::optional<EnumType> symbolizeEnum(::llvm::StringRef);
 
@@ -745,9 +749,9 @@ inline ::std::optional<{0}> symbolizeEnum<{0}>(::llvm::StringRef str) {
   return {1}(str);
 }
 )";
-  os << formatv(symbolizeEnumStr, enumName, strToSymFnName);
+    os << formatv(symbolizeEnumStr, enumName, strToSymFnName);
 
-  const char *const attrClassDecl = R"(
+    const char *const attrClassDecl = R"(
 class {1} : public ::mlir::{2} {
 public:
   using ValueType = {0};
@@ -757,13 +761,12 @@ class {1} : public ::mlir::{2} {
   {0} getValue() const;
 };
 )";
-  if (enumInfo.genSpecializedAttr()) {
-    StringRef attrClassName = enumInfo.getSpecializedAttrClassName();
-    StringRef baseAttrClassName = "IntegerAttr";
-    os << formatv(attrClassDecl, enumName, attrClassName, baseAttrClassName);
-  }
-
-  ns.close();
+    if (enumInfo.genSpecializedAttr()) {
+      StringRef attrClassName = enumInfo.getSpecializedAttrClassName();
+      StringRef baseAttrClassName = "IntegerAttr";
+      os << formatv(attrClassDecl, enumName, attrClassName, baseAttrClassName);
+    }
+  } // close `ns`.
 
   // Generate a generic parser and printer for the enum.
   std::string qualName =

@jurahul
Copy link
Contributor Author

jurahul commented Nov 18, 2025

@s-barannikov @topperc gentle ping.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jurahul
Copy link
Contributor Author

jurahul commented Nov 18, 2025

Thanks

@jurahul jurahul merged commit 8f67759 into llvm:main Nov 18, 2025
16 checks passed
@jurahul jurahul deleted the nfc_tablegen_cghelpers_remove_close branch November 18, 2025 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mlir:core MLIR Core Infrastructure mlir tablegen

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants