Verifier: Move more debug info checks away from Verify()
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 31 Mar 2015 01:28:22 +0000 (01:28 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 31 Mar 2015 01:28:22 +0000 (01:28 +0000)
Most of these checks were already in the `Verifier` so this is more of a
cleanup.  Now almost everything is over there.

Now that require a `name:` for `MDGlobalVariable`, add a check in
`LLParser` for it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233657 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AsmParser/LLParser.cpp
lib/IR/DebugInfo.cpp
lib/IR/Verifier.cpp
test/Assembler/invalid-mdglobalvariable-empty-name.ll [new file with mode: 0644]
test/Assembler/invalid-mdglobalvariable-missing-name.ll [new file with mode: 0644]
test/Assembler/mdglobalvariable.ll

index 6e79960e3db8f2e873736d6e441bb3d6b1b08006..ed1d0ff9ee646bbe9874479e65b99846690d8828 100644 (file)
@@ -3041,7 +3041,9 @@ struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> {
   MDConstant() : ImplTy(nullptr) {}
 };
 struct MDStringField : public MDFieldImpl<MDString *> {
-  MDStringField() : ImplTy(nullptr) {}
+  bool AllowEmpty;
+  MDStringField(bool AllowEmpty = true)
+      : ImplTy(nullptr), AllowEmpty(AllowEmpty) {}
 };
 struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> {
   MDFieldList() : ImplTy(SmallVector<Metadata *, 4>()) {}
@@ -3253,10 +3255,14 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDConstant &Result) {
 
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
+  LocTy ValueLoc = Lex.getLoc();
   std::string S;
   if (ParseStringConstant(S))
     return true;
 
+  if (!Result.AllowEmpty && S.empty())
+    return Error(ValueLoc, "'" + Name + "' cannot be empty");
+
   Result.assign(S.empty() ? nullptr : MDString::get(Context, S));
   return false;
 }
@@ -3655,8 +3661,8 @@ bool LLParser::ParseMDTemplateValueParameter(MDNode *&Result, bool IsDistinct) {
 ///                         declaration: !3)
 bool LLParser::ParseMDGlobalVariable(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
+  REQUIRED(name, MDStringField, (/* AllowEmpty */ false));                     \
   OPTIONAL(scope, MDField, );                                                  \
-  OPTIONAL(name, MDStringField, );                                             \
   OPTIONAL(linkageName, MDStringField, );                                      \
   OPTIONAL(file, MDField, );                                                   \
   OPTIONAL(line, LineField, );                                                 \
index 4e5b5f1f97561b0f453a57938e68cff329bfe2a8..91823773212b442d90216e81c1928fdaa0944f82 100644 (file)
@@ -275,16 +275,6 @@ bool DISubprogram::Verify() const {
   if (!N)
     return false;
 
-  if (!isScopeRef(N->getScope()))
-    return false;
-
-  if (auto *Op = N->getType())
-    if (!isa<MDNode>(Op))
-      return false;
-
-  if (!isTypeRef(getContainingType()))
-    return false;
-
   if (isLValueReference() && isRValueReference())
     return false;
 
@@ -315,38 +305,8 @@ bool DISubprogram::Verify() const {
   return true;
 }
 
-bool DIGlobalVariable::Verify() const {
-  auto *N = dyn_cast_or_null<MDGlobalVariable>(DbgNode);
-
-  if (!N)
-    return false;
-
-  if (N->getDisplayName().empty())
-    return false;
-
-  if (auto *Op = N->getScope())
-    if (!isa<MDNode>(Op))
-      return false;
-
-  if (auto *Op = N->getStaticDataMemberDeclaration())
-    if (!isa<MDNode>(Op))
-      return false;
-
-  return isTypeRef(N->getType());
-}
-
-bool DIVariable::Verify() const {
-  auto *N = dyn_cast_or_null<MDLocalVariable>(DbgNode);
-
-  if (!N)
-    return false;
-
-  if (auto *Op = N->getScope())
-    if (!isa<MDNode>(Op))
-      return false;
-
-  return isTypeRef(N->getType());
-}
+bool DIGlobalVariable::Verify() const { return isGlobalVariable(); }
+bool DIVariable::Verify() const { return isVariable(); }
 
 bool DILocation::Verify() const {
   return dyn_cast_or_null<MDLocation>(DbgNode);
index 4bf24211963868aca4b704acf7c6e76f0e4bbe9f..19897d4c0308faa6a0082da78f48dc6d6d9a53d1 100644 (file)
@@ -969,6 +969,7 @@ void Verifier::visitMDGlobalVariable(const MDGlobalVariable &N) {
   visitMDVariable(N);
 
   Assert(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);
+  Assert(!N.getName().empty(), "missing global variable name", &N);
   if (auto *V = N.getRawVariable()) {
     Assert(isa<ConstantAsMetadata>(V) &&
                !isa<Function>(cast<ConstantAsMetadata>(V)->getValue()),
diff --git a/test/Assembler/invalid-mdglobalvariable-empty-name.ll b/test/Assembler/invalid-mdglobalvariable-empty-name.ll
new file mode 100644 (file)
index 0000000..77a9f4d
--- /dev/null
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:30: error: 'name' cannot be empty
+!0 = !MDGlobalVariable(name: "")
diff --git a/test/Assembler/invalid-mdglobalvariable-missing-name.ll b/test/Assembler/invalid-mdglobalvariable-missing-name.ll
new file mode 100644 (file)
index 0000000..d57d71e
--- /dev/null
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:24: error: missing required field 'name'
+!0 = !MDGlobalVariable()
index d48fef93cda104e7a85bd66edf12bf8691493b64..2726f4f3510f32b7d47b4cdbf960d6dea94a9078 100644 (file)
@@ -17,8 +17,8 @@
                        file: !2, line: 7, type: !3, isLocal: true,
                        isDefinition: false, variable: i32* @foo)
 
-; CHECK: !6 = !MDGlobalVariable(scope: !0, isLocal: false, isDefinition: true)
-!6 = !MDGlobalVariable(scope: !0)
+; CHECK: !6 = !MDGlobalVariable(name: "foo", scope: !0, isLocal: false, isDefinition: true)
+!6 = !MDGlobalVariable(name: "foo", scope: !0)
 
 !7 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Class", size: 8, align: 8)
 !8 = !MDDerivedType(tag: DW_TAG_member, name: "mem", flags: DIFlagStaticMember, scope: !7, baseType: !3)