Skip to content

Conversation

@rnk
Copy link
Collaborator

@rnk rnk commented Sep 16, 2025

Find issues like the whole-program-vtables one (#87503) earlier.

Find issues like the whole-program-vtables one earlier.
@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2025

@llvm/pr-subscribers-llvm-ir

Author: Reid Kleckner (rnk)

Changes

Find issues like the whole-program-vtables one (#87503) earlier.


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

2 Files Affected:

  • (modified) llvm/lib/IR/Verifier.cpp (+82-63)
  • (modified) llvm/test/Verifier/comdat.ll (+38-2)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c06b60fd2d9a9..0f47049a6457d 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -271,7 +271,7 @@ struct VerifierSupport {
   }
 
   template <typename T1, typename... Ts>
-  void WriteTs(const T1 &V1, const Ts &... Vs) {
+  void WriteTs(const T1 &V1, const Ts &...Vs) {
     Write(V1);
     WriteTs(Vs...);
   }
@@ -294,7 +294,7 @@ struct VerifierSupport {
   /// This calls the Message-only version so that the above is easier to set a
   /// breakpoint on.
   template <typename T1, typename... Ts>
-  void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) {
+  void CheckFailed(const Twine &Message, const T1 &V1, const Ts &...Vs) {
     CheckFailed(Message);
     if (OS)
       WriteTs(V1, Vs...);
@@ -311,7 +311,7 @@ struct VerifierSupport {
   /// A debug info check failed (with values to print).
   template <typename T1, typename... Ts>
   void DebugInfoCheckFailed(const Twine &Message, const T1 &V1,
-                            const Ts &... Vs) {
+                            const Ts &...Vs) {
     DebugInfoCheckFailed(Message);
     if (OS)
       WriteTs(V1, Vs...);
@@ -715,7 +715,8 @@ void Verifier::visit(Instruction &I) {
   InstVisitor<Verifier>::visit(I);
 }
 
-// Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further.
+// Helper to iterate over indirect users. By returning false, the callback can
+// ask to stop traversing further.
 static void forEachUser(const Value *User,
                         SmallPtrSet<const Value *, 32> &Visited,
                         llvm::function_ref<bool(const Value *)> Callback) {
@@ -724,7 +725,7 @@ static void forEachUser(const Value *User,
 
   SmallVector<const Value *> WorkList(User->materialized_users());
   while (!WorkList.empty()) {
-   const Value *Cur = WorkList.pop_back_val();
+    const Value *Cur = WorkList.pop_back_val();
     if (!Visited.insert(Cur).second)
       continue;
     if (Callback(Cur))
@@ -876,8 +877,8 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
     }
   }
 
-  if (GV.hasName() && (GV.getName() == "llvm.used" ||
-                       GV.getName() == "llvm.compiler.used")) {
+  if (GV.hasName() &&
+      (GV.getName() == "llvm.used" || GV.getName() == "llvm.compiler.used")) {
     Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),
           "invalid linkage for intrinsic global variable", &GV);
     Check(GV.materialized_use_empty(),
@@ -936,13 +937,14 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
 }
 
 void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) {
-  SmallPtrSet<const GlobalAlias*, 4> Visited;
+  SmallPtrSet<const GlobalAlias *, 4> Visited;
   Visited.insert(&GA);
   visitAliaseeSubExpr(Visited, GA, C);
 }
 
-void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
-                                   const GlobalAlias &GA, const Constant &C) {
+void Verifier::visitAliaseeSubExpr(
+    SmallPtrSetImpl<const GlobalAlias *> &Visited, const GlobalAlias &GA,
+    const Constant &C) {
   if (GA.hasAvailableExternallyLinkage()) {
     Check(isa<GlobalValue>(C) &&
               cast<GlobalValue>(C).hasAvailableExternallyLinkage(),
@@ -1760,12 +1762,20 @@ void Verifier::visitDIImportedEntity(const DIImportedEntity &N) {
 }
 
 void Verifier::visitComdat(const Comdat &C) {
-  // In COFF the Module is invalid if the GlobalValue has private linkage.
-  // Entities with private linkage don't have entries in the symbol table.
-  if (TT.isOSBinFormatCOFF())
-    if (const GlobalValue *GV = M.getNamedValue(C.getName()))
+  // Comdats in COFF modules must have a corresponding global that is not
+  // private. If the global is private, there will be no symbol table entry.
+  // We consider unused or dead comdat entries to be valid, since they won't
+  // make it into the COFF object file.
+  if (TT.isOSBinFormatCOFF()) {
+    const GlobalValue *GV = M.getNamedValue(C.getName());
+    bool IsDefined = GV != nullptr && !GV->isDeclarationForLinker();
+    Check(IsDefined || C.getUsers().empty(),
+          "COFF comdats must have a defined global value with the same name",
+          GV);
+    if (IsDefined)
       Check(!GV->hasPrivateLinkage(), "comdat global value has private linkage",
             GV);
+  }
 }
 
 void Verifier::visitModuleIdents() {
@@ -1805,11 +1815,12 @@ void Verifier::visitModuleCommandLines() {
 
 void Verifier::visitModuleFlags() {
   const NamedMDNode *Flags = M.getModuleFlagsMetadata();
-  if (!Flags) return;
+  if (!Flags)
+    return;
 
   // Scan each flag, and track the flags and requirements.
-  DenseMap<const MDString*, const MDNode*> SeenIDs;
-  SmallVector<const MDNode*, 16> Requirements;
+  DenseMap<const MDString *, const MDNode *> SeenIDs;
+  SmallVector<const MDNode *, 16> Requirements;
   uint64_t PAuthABIPlatform = -1;
   uint64_t PAuthABIVersion = -1;
   for (const MDNode *MDN : Flags->operands()) {
@@ -1854,10 +1865,9 @@ void Verifier::visitModuleFlags() {
   }
 }
 
-void
-Verifier::visitModuleFlag(const MDNode *Op,
-                          DenseMap<const MDString *, const MDNode *> &SeenIDs,
-                          SmallVectorImpl<const MDNode *> &Requirements) {
+void Verifier::visitModuleFlag(
+    const MDNode *Op, DenseMap<const MDString *, const MDNode *> &SeenIDs,
+    SmallVectorImpl<const MDNode *> &Requirements) {
   // Each module flag should have three arguments, the merge behavior (a
   // constant int), the flag ID (an MDString), and the value.
   Check(Op->getNumOperands() == 3,
@@ -1936,8 +1946,8 @@ Verifier::visitModuleFlag(const MDNode *Op,
   }
 
   if (ID->getString() == "wchar_size") {
-    ConstantInt *Value
-      = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
+    ConstantInt *Value =
+        mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
     Check(Value, "wchar_size metadata requires constant integer argument");
   }
 
@@ -2099,7 +2109,8 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
     if (!Attr.isStringAttribute() &&
         IncompatibleAttrs.contains(Attr.getKindAsEnum())) {
       CheckFailed("Attribute '" + Attr.getAsString() +
-                  "' applied to incompatible type!", V);
+                      "' applied to incompatible type!",
+                  V);
       return;
     }
   }
@@ -2335,15 +2346,15 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
   }
 
   Check(!Attrs.hasAttrSomewhere(Attribute::Writable) ||
-        isModSet(Attrs.getMemoryEffects().getModRef(IRMemLocation::ArgMem)),
+            isModSet(Attrs.getMemoryEffects().getModRef(IRMemLocation::ArgMem)),
         "Attribute writable and memory without argmem: write are incompatible!",
         V);
 
   if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled")) {
     Check(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"),
-           "Attributes 'aarch64_pstate_sm_enabled and "
-           "aarch64_pstate_sm_compatible' are incompatible!",
-           V);
+          "Attributes 'aarch64_pstate_sm_enabled and "
+          "aarch64_pstate_sm_compatible' are incompatible!",
+          V);
   }
 
   Check((Attrs.hasFnAttr("aarch64_new_za") + Attrs.hasFnAttr("aarch64_in_za") +
@@ -2724,7 +2735,8 @@ void Verifier::verifyStatepoint(const CallBase &Call) {
   Check(TargetFuncType,
         "gc.statepoint callee elementtype must be function type", Call);
 
-  const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
+  const int NumCallArgs =
+      cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
   Check(NumCallArgs >= 0,
         "gc.statepoint number of arguments to underlying call "
         "must be positive",
@@ -2743,8 +2755,8 @@ void Verifier::verifyStatepoint(const CallBase &Call) {
     Check(NumCallArgs == NumParams,
           "gc.statepoint mismatch in number of call args", Call);
 
-  const uint64_t Flags
-    = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue();
+  const uint64_t Flags =
+      cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue();
   Check((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,
         "unknown flag used in gc.statepoint flags argument", Call);
 
@@ -3241,7 +3253,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
   // it.
   if (isa<PHINode>(BB.front())) {
     SmallVector<BasicBlock *, 8> Preds(predecessors(&BB));
-    SmallVector<std::pair<BasicBlock*, Value*>, 8> Values;
+    SmallVector<std::pair<BasicBlock *, Value *>, 8> Values;
     llvm::sort(Preds);
     for (const PHINode &PN : BB.phis()) {
       Check(PN.getNumIncomingValues() == Preds.size(),
@@ -3278,8 +3290,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
   }
 
   // Check that all instructions have their parent pointers set up correctly.
-  for (auto &I : BB)
-  {
+  for (auto &I : BB) {
     Check(I.getParent() == &BB, "Instruction has bogus parent pointer!");
   }
 
@@ -3327,7 +3338,7 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
   // Check to make sure that all of the constants in the switch instruction
   // have the same type as the switched-on value.
   Type *SwitchTy = SI.getCondition()->getType();
-  SmallPtrSet<ConstantInt*, 32> Constants;
+  SmallPtrSet<ConstantInt *, 32> Constants;
   for (auto &Case : SI.cases()) {
     Check(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex() * 2 + 2)),
           "Case value is not a constant integer.", &SI);
@@ -3754,7 +3765,8 @@ void Verifier::visitCallBase(CallBase &Call) {
   for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
     if (Call.paramHasAttr(i, Attribute::SwiftError)) {
       Value *SwiftErrorArg = Call.getArgOperand(i);
-      if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
+      if (auto AI =
+              dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) {
         Check(AI->isSwiftError(),
               "swifterror argument for call has mismatched alloca", AI, Call);
         continue;
@@ -3999,7 +4011,8 @@ static bool isTypeCongruent(Type *L, Type *R) {
   return PL->getAddressSpace() == PR->getAddressSpace();
 }
 
-static AttrBuilder getParameterABIAttributes(LLVMContext& C, unsigned I, AttributeList Attrs) {
+static AttrBuilder getParameterABIAttributes(LLVMContext &C, unsigned I,
+                                             AttributeList Attrs) {
   static const Attribute::AttrKind ABIAttrs[] = {
       Attribute::StructRet,  Attribute::ByVal,          Attribute::InAlloca,
       Attribute::InReg,      Attribute::StackAlignment, Attribute::SwiftSelf,
@@ -4067,12 +4080,14 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
     // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes
     //   are allowed in swifttailcc call
     for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
-      AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs);
+      AttrBuilder ABIAttrs =
+          getParameterABIAttributes(F->getContext(), I, CallerAttrs);
       SmallString<32> Context{CCName, StringRef(" musttail caller")};
       verifyTailCCMustTailAttrs(ABIAttrs, Context);
     }
     for (unsigned I = 0, E = CalleeTy->getNumParams(); I != E; ++I) {
-      AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs);
+      AttrBuilder ABIAttrs =
+          getParameterABIAttributes(F->getContext(), I, CalleeAttrs);
       SmallString<32> Context{CCName, StringRef(" musttail callee")};
       verifyTailCCMustTailAttrs(ABIAttrs, Context);
     }
@@ -4098,8 +4113,10 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
   // - All ABI-impacting function attributes, such as sret, byval, inreg,
   //   returned, preallocated, and inalloca, must match.
   for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
-    AttrBuilder CallerABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs);
-    AttrBuilder CalleeABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs);
+    AttrBuilder CallerABIAttrs =
+        getParameterABIAttributes(F->getContext(), I, CallerAttrs);
+    AttrBuilder CalleeABIAttrs =
+        getParameterABIAttributes(F->getContext(), I, CalleeAttrs);
     Check(CallerABIAttrs == CalleeABIAttrs,
           "cannot guarantee tail call due to mismatched ABI impacting "
           "function attributes",
@@ -4491,7 +4508,7 @@ void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) {
 
 void Verifier::visitAllocaInst(AllocaInst &AI) {
   Type *Ty = AI.getAllocatedType();
-  SmallPtrSet<Type*, 4> Visited;
+  SmallPtrSet<Type *, 4> Visited;
   Check(Ty->isSized(&Visited), "Cannot allocate unsized type", &AI);
   // Check if it's a target extension type that disallows being used on the
   // stack.
@@ -4541,7 +4558,8 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
   } else if (AtomicRMWInst::isFPOperation(Op)) {
     Check(ElTy->isFPOrFPVectorTy() && !isa<ScalableVectorType>(ElTy),
           "atomicrmw " + AtomicRMWInst::getOperationName(Op) +
-              " operand must have floating-point or fixed vector of floating-point "
+              " operand must have floating-point or fixed vector of "
+              "floating-point "
               "type!",
           &RMWI, ElTy);
   } else {
@@ -5020,7 +5038,7 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
   Check(DT.dominates(Op, U), "Instruction does not dominate all uses!", Op, &I);
 }
 
-void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) {
+void Verifier::visitDereferenceableMetadata(Instruction &I, MDNode *MD) {
   Check(I.getType()->isPointerTy(),
         "dereferenceable, dereferenceable_or_null "
         "apply only to pointer types",
@@ -5353,7 +5371,7 @@ void Verifier::visitInstruction(Instruction &I) {
   BasicBlock *BB = I.getParent();
   Check(BB, "Instruction not embedded in basic block!", &I);
 
-  if (!isa<PHINode>(I)) {   // Check that non-phi nodes are not self referential
+  if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential
     for (User *U : I.users()) {
       Check(U != (User *)&I || !DT.isReachableFromEntry(BB),
             "Only PHI nodes may reference their own value!", &I);
@@ -7097,7 +7115,8 @@ void Verifier::visitVPIntrinsic(VPIntrinsic &VPI) {
     case Intrinsic::vp_llrint:
       Check(
           RetTy->isIntOrIntVectorTy() && ValTy->isFPOrFPVectorTy(),
-          "llvm.vp.fptoui, llvm.vp.fptosi, llvm.vp.lrint or llvm.vp.llrint" "intrinsic first argument element "
+          "llvm.vp.fptoui, llvm.vp.fptosi, llvm.vp.lrint or llvm.vp.llrint"
+          "intrinsic first argument element "
           "type must be floating-point and result element type must be integer",
           *VPCast);
       break;
@@ -7587,8 +7606,7 @@ struct VerifierLegacyPass : public FunctionPass {
     initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
   }
   explicit VerifierLegacyPass(bool FatalErrors)
-      : FunctionPass(ID),
-        FatalErrors(FatalErrors) {
+      : FunctionPass(ID), FatalErrors(FatalErrors) {
     initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
   }
 
@@ -7626,7 +7644,7 @@ struct VerifierLegacyPass : public FunctionPass {
 } // end anonymous namespace
 
 /// Helper to issue failure from the TBAA verification
-template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) {
+template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&...Args) {
   if (Diagnostic)
     return Diagnostic->CheckFailed(Args...);
 }
@@ -7676,7 +7694,8 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode,
   if (IsNewFormat) {
     if (BaseNode->getNumOperands() % 3 != 0) {
       CheckFailed("Access tag nodes must have the number of operands that is a "
-                  "multiple of 3!", BaseNode);
+                  "multiple of 3!",
+                  BaseNode);
       return InvalidNode;
     }
   } else {
@@ -7689,8 +7708,8 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode,
 
   // Check the type size field.
   if (IsNewFormat) {
-    auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>(
-        BaseNode->getOperand(1));
+    auto *TypeSizeNode =
+        mdconst::dyn_extract_or_null<ConstantInt>(BaseNode->getOperand(1));
     if (!TypeSizeNode) {
       CheckFailed("Type size nodes must be constants!", &I, BaseNode);
       return InvalidNode;
@@ -7714,7 +7733,7 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode,
   unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1;
   unsigned NumOpsPerField = IsNewFormat ? 3 : 2;
   for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands();
-           Idx += NumOpsPerField) {
+       Idx += NumOpsPerField) {
     const MDOperand &FieldTy = BaseNode->getOperand(Idx);
     const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1);
     if (!isa<MDNode>(FieldTy)) {
@@ -7828,7 +7847,7 @@ MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I,
   unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1;
   unsigned NumOpsPerField = IsNewFormat ? 3 : 2;
   for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands();
-           Idx += NumOpsPerField) {
+       Idx += NumOpsPerField) {
     auto *OffsetEntryCI =
         mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1));
     if (OffsetEntryCI->getValue().ugt(Offset)) {
@@ -7847,8 +7866,8 @@ MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I,
   }
 
   unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField;
-  auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>(
-      BaseNode->getOperand(LastIdx + 1));
+  auto *LastOffsetEntryCI =
+      mdconst::extract<ConstantInt>(BaseNode->getOperand(LastIdx + 1));
   Offset -= LastOffsetEntryCI->getValue();
   return cast<MDNode>(BaseNode->getOperand(LastIdx));
 }
@@ -7893,8 +7912,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
 
   // Check the access size field.
   if (IsNewFormat) {
-    auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>(
-        MD->getOperand(3));
+    auto *AccessSizeNode =
+        mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(3));
     CheckTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD);
   }
 
@@ -7932,8 +7951,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
   SmallPtrSet<MDNode *, 4> StructPath;
 
   for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode);
-       BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset,
-                                               IsNewFormat)) {
+       BaseNode =
+           getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, IsNewFormat)) {
     if (!StructPath.insert(BaseNode).second) {
       CheckFailed("Cycle detected in struct path", &I, MD);
       return false;
@@ -7941,8 +7960,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
 
     bool Invalid;
     unsigned BaseNodeBitWidth;
-    std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode,
-                                                             IsNewFormat);
+    std::tie(Invalid, BaseNodeBitWidth) =
+        verifyTBAABaseNode(I, BaseNode, IsNewFormat);
 
     // If the base node is invalid in itself, then we've already printed all the
     // errors we wanted to print.
@@ -7987,7 +8006,7 @@ VerifierAnalysis::Result VerifierAnalysis::run(Module &M,
 
 VerifierAnalysis::Result VerifierAnalysis::run(Function &F,
                                                FunctionAnalysisManager &) {
-  return { llvm::verifyFunction(F, &dbgs()), false };
+  return {llvm::verifyFunction(F, &dbgs()), false};
 }
 
 PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) {
diff --git a/llvm/test/Verifier/comdat.ll b/llvm/test/Verifier/comdat.ll
index dcf67d89f8d7d..84f401a321480 100644
--- a/llvm/test/Verifier/comdat.ll
+++ b/llvm/test/Verifier/comdat.ll
@@ -1,5 +1,41 @@
-; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+; RUN: split-file %s %t
 
+;--- common.ll
+; RUN: not llvm-as %t/common.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-COMMON
 $v = comdat any
 @v = common global i32 0, comdat($v)
-; CHECK: 'common' global may not be in a Comdat!
+; CHECK-COMMON: 'common' global ...
[truncated]

Copy link
Contributor

@mizvekov mizvekov left a comment

Choose a reason for hiding this comment

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

Would you please pre-commit the formatting changes only?
That would make this a bit easier to review.

Thanks!

Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
@github-actions
Copy link

github-actions bot commented Sep 17, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@rnk rnk enabled auto-merge (squash) September 17, 2025 22:04
@aganea
Copy link
Member

aganea commented Sep 18, 2025

@rnk The test seem to be failing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants