diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index c06b60fd2d9a9..adc9a4c17b88b 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1760,12 +1760,21 @@ 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(); + if (IsDefined) Check(!GV->hasPrivateLinkage(), "comdat global value has private linkage", GV); + else + Check(C.getUsers().empty(), + "COFF comdats must have a defined global value with the same name", + GV); + } } void Verifier::visitModuleIdents() { 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 may not be in a Comdat! + +;--- private.ll +; RUN: llvm-as %t/private.ll -o /dev/null +; RUN: opt -mtriple=x86_64-unknown-linux %t/private.ll -o /dev/null +; RUN: not opt -mtriple=x86_64-pc-win32 %t/private.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-PRIVATE +$v = comdat any +@v = private global i32 0, comdat($v) +; CHECK-PRIVATE: comdat global value has private linkage + +;--- noleader.ll +; RUN: llvm-as %t/noleader.ll -o /dev/null +; RUN: opt -mtriple=x86_64-unknown-linux %t/noleader.ll -o /dev/null +; RUN: not opt -mtriple=x86_64-pc-win32 %t/noleader.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-NOLEADER + +$v = comdat any +@unrelated = internal global i32 0, comdat($v) +; CHECK-NOLEADER: COFF comdats must have a defined global value with the same name + +;--- undefined.ll +; RUN: llvm-as %t/undefined.ll -o /dev/null +; RUN: opt -mtriple=x86_64-unknown-linux %t/undefined.ll -o /dev/null +; RUN: not opt -mtriple=x86_64-pc-win32 %t/undefined.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED + +$v = comdat any +@v = external global i32 +@unrelated = internal global i32 0, comdat($v) +; CHECK-UNDEFINED: COFF comdats must have a defined global value with the same name + +;--- largest.ll +; RUN: llvm-as %t/largest.ll -o /dev/null +; This used to be invalid, but now it's valid. Ensure the verifier +; doesn't reject it. + +$v = comdat largest diff --git a/llvm/test/Verifier/comdat2.ll b/llvm/test/Verifier/comdat2.ll deleted file mode 100644 index b461d5846f9ca..0000000000000 --- a/llvm/test/Verifier/comdat2.ll +++ /dev/null @@ -1,7 +0,0 @@ -; RUN: llvm-as %s -o /dev/null -; RUN: opt -mtriple=x86_64-unknown-linux -o /dev/null -; RUN: not opt -mtriple=x86_64-pc-win32 %s -o /dev/null 2>&1 | FileCheck %s - -$v = comdat any -@v = private global i32 0, comdat($v) -; CHECK: comdat global value has private linkage diff --git a/llvm/test/Verifier/comdat3.ll b/llvm/test/Verifier/comdat3.ll deleted file mode 100644 index 28df930d9dddf..0000000000000 --- a/llvm/test/Verifier/comdat3.ll +++ /dev/null @@ -1,5 +0,0 @@ -; This used to be invalid, but now it's valid. Ensure the verifier -; doesn't reject it. -; RUN: llvm-as %s -o /dev/null - -$v = comdat largest