From: Duncan P. N. Exon Smith Date: Fri, 27 Mar 2015 17:29:58 +0000 (+0000) Subject: Verifier: Check fields of MDVariable subclasses X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=a9902daa5c1bdb080bc850e46f653ea7db055573;p=oota-llvm.git Verifier: Check fields of MDVariable subclasses Check fields from `MDLocalVariable` and `MDGlobalVariable` and change the accessors to downcast to the right types. `getType()` still returns `Metadata*` since it could be an `MDString`-based reference. Since local variables require non-null scopes, I also updated `LLParser` to require a `scope:` field. A number of testcases had grown bitrot and started failing with this patch; I committed them separately in r233349. If I just broke your out-of-tree testcases, you're probably hitting similar problems (so have a look there). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233389 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d7563fce940..d174a536c1b 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1315,12 +1315,15 @@ protected: public: unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } + MDScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(1); } - Metadata *getFile() const { return getOperand(2); } - Metadata *getType() const { return getOperand(3); } + MDFile *getFile() const { return cast_or_null(getRawFile()); } + Metadata *getType() const { return getRawType(); } + Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind || @@ -1347,10 +1350,10 @@ class MDGlobalVariable : public MDVariable { ~MDGlobalVariable() {} static MDGlobalVariable * - getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, - StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration, StorageType Storage, + getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, ConstantAsMetadata *Variable, + MDDerivedType *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, @@ -1373,10 +1376,11 @@ class MDGlobalVariable : public MDVariable { public: DEFINE_MDNODE_GET(MDGlobalVariable, - (Metadata * Scope, StringRef Name, StringRef LinkageName, - Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration), + (MDScope * Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, Metadata *Type, + bool IsLocalToUnit, bool IsDefinition, + ConstantAsMetadata *Variable, + MDDerivedType *StaticDataMemberDeclaration), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) DEFINE_MDNODE_GET(MDGlobalVariable, @@ -1393,10 +1397,16 @@ public: bool isDefinition() const { return IsDefinition; } StringRef getDisplayName() const { return getStringOperand(4); } StringRef getLinkageName() const { return getStringOperand(5); } - Metadata *getVariable() const { return getOperand(6); } - Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + ConstantAsMetadata *getVariable() const { + return cast_or_null(getRawVariable()); + } + MDDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null(getRawStaticDataMemberDeclaration()); + } MDString *getRawLinkageName() const { return getOperandAs(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDGlobalVariableKind; @@ -1423,10 +1433,10 @@ class MDLocalVariable : public MDVariable { ~MDLocalVariable() {} static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt, StorageType Storage, + MDScope *Scope, StringRef Name, MDFile *File, + unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, MDLocation *InlinedAt, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), File, Line, Type, Arg, Flags, InlinedAt, Storage, @@ -1447,10 +1457,9 @@ class MDLocalVariable : public MDVariable { public: DEFINE_MDNODE_GET(MDLocalVariable, - (unsigned Tag, Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt = nullptr), + (unsigned Tag, MDLocalScope *Scope, StringRef Name, + MDFile *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, MDLocation *InlinedAt = nullptr), (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) DEFINE_MDNODE_GET(MDLocalVariable, (unsigned Tag, Metadata *Scope, MDString *Name, @@ -1461,9 +1470,20 @@ public: TempMDLocalVariable clone() const { return cloneImpl(); } + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + MDLocalScope *getScope() const { + return cast(MDVariable::getScope()); + } + unsigned getArg() const { return Arg; } unsigned getFlags() const { return Flags; } - Metadata *getInlinedAt() const { return getOperand(4); } + MDLocation *getInlinedAt() const { + return cast_or_null(getRawInlinedAt()); + } + + Metadata *getRawInlinedAt() const { return getOperand(4); } /// \brief Get an inlined version of this variable. /// diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 103c8c48a5e..484a7250e2e 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -3035,8 +3035,8 @@ struct MDField : public MDFieldImpl { struct MDConstant : public MDFieldImpl { MDConstant() : ImplTy(nullptr) {} }; -struct MDStringField : public MDFieldImpl { - MDStringField() : ImplTy(std::string()) {} +struct MDStringField : public MDFieldImpl { + MDStringField() : ImplTy(nullptr) {} }; struct MDFieldList : public MDFieldImpl> { MDFieldList() : ImplTy(SmallVector()) {} @@ -3250,7 +3250,7 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { if (ParseStringConstant(S)) return true; - Result.assign(std::move(S)); + Result.assign(S.empty() ? nullptr : MDString::get(Context, S)); return false; } @@ -3675,7 +3675,7 @@ bool LLParser::ParseMDGlobalVariable(MDNode *&Result, bool IsDistinct) { bool LLParser::ParseMDLocalVariable(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(tag, DwarfTagField, ); \ - OPTIONAL(scope, MDField, ); \ + REQUIRED(scope, MDField, ); \ OPTIONAL(name, MDStringField, ); \ OPTIONAL(file, MDField, ); \ OPTIONAL(line, LineField, ); \ diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index ae0beba730b..460e3f1b619 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1720,14 +1720,14 @@ static void writeMDGlobalVariable(raw_ostream &Out, const MDGlobalVariable *N, MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); Printer.printString("name", N->getName()); Printer.printString("linkageName", N->getLinkageName()); - Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); - Printer.printMetadata("type", N->getType()); + Printer.printMetadata("type", N->getRawType()); Printer.printBool("isLocal", N->isLocalToUnit()); Printer.printBool("isDefinition", N->isDefinition()); - Printer.printMetadata("variable", N->getVariable()); - Printer.printMetadata("declaration", N->getStaticDataMemberDeclaration()); + Printer.printMetadata("variable", N->getRawVariable()); + Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); Out << ")"; } @@ -1741,12 +1741,12 @@ static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N, Printer.printInt("arg", N->getArg(), /* ShouldSkipZero */ N->getTag() == dwarf::DW_TAG_auto_variable); - Printer.printMetadata("scope", N->getScope(), /* ShouldSkipNull */ false); - Printer.printMetadata("file", N->getFile()); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); - Printer.printMetadata("type", N->getType()); + Printer.printMetadata("type", N->getRawType()); Printer.printDIFlags("flags", N->getFlags()); - Printer.printMetadata("inlinedAt", N->getInlinedAt()); + Printer.printMetadata("inlinedAt", N->getRawInlinedAt()); Out << ")"; } diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 9677de47f7b..ec5ee7da5cb 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -582,9 +582,10 @@ DIGlobalVariable DIBuilder::createGlobalVariable( MDNode *Decl) { checkGlobalVariableScope(Context); - auto *N = MDGlobalVariable::get(VMContext, Context, Name, LinkageName, F, - LineNumber, Ty, isLocalToUnit, true, - getConstantOrNull(Val), Decl); + auto *N = MDGlobalVariable::get( + VMContext, cast_or_null(Context.get()), Name, LinkageName, F, + LineNumber, Ty, isLocalToUnit, true, getConstantOrNull(Val), + cast_or_null(Decl)); AllGVs.push_back(N); return N; } @@ -595,9 +596,10 @@ DIGlobalVariable DIBuilder::createTempGlobalVariableFwdDecl( MDNode *Decl) { checkGlobalVariableScope(Context); - return MDGlobalVariable::getTemporary(VMContext, Context, Name, LinkageName, - F, LineNumber, Ty, isLocalToUnit, false, - getConstantOrNull(Val), Decl).release(); + return MDGlobalVariable::getTemporary( + VMContext, cast_or_null(Context.get()), Name, LinkageName, + F, LineNumber, Ty, isLocalToUnit, false, getConstantOrNull(Val), + cast_or_null(Decl)).release(); } DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, @@ -613,9 +615,9 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, assert((!Context || Context.isScope()) && "createLocalVariable should be called with a valid Context"); - auto *Node = - MDLocalVariable::get(VMContext, Tag, getNonCompileUnitScope(Scope), Name, - File, LineNo, Ty, ArgNo, Flags); + auto *Node = MDLocalVariable::get(VMContext, Tag, + cast_or_null(Context.get()), + Name, File, LineNo, Ty, ArgNo, Flags); if (AlwaysPreserve) { // The optimizer may remove local variable. If there is an interest // to preserve variable info in such situation then stash it in a diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index e3806652830..d735c33d2ac 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -699,21 +699,22 @@ template <> struct MDNodeKeyImpl { IsDefinition(IsDefinition), Variable(Variable), StaticDataMemberDeclaration(StaticDataMemberDeclaration) {} MDNodeKeyImpl(const MDGlobalVariable *N) - : Scope(N->getScope()), Name(N->getName()), - LinkageName(N->getLinkageName()), File(N->getFile()), - Line(N->getLine()), Type(N->getType()), + : Scope(N->getRawScope()), Name(N->getName()), + LinkageName(N->getLinkageName()), File(N->getRawFile()), + Line(N->getLine()), Type(N->getRawType()), IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), - Variable(N->getVariable()), - StaticDataMemberDeclaration(N->getStaticDataMemberDeclaration()) {} + Variable(N->getRawVariable()), + StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()) {} bool isKeyOf(const MDGlobalVariable *RHS) const { - return Scope == RHS->getScope() && Name == RHS->getName() && - LinkageName == RHS->getLinkageName() && File == RHS->getFile() && - Line == RHS->getLine() && Type == RHS->getType() && + return Scope == RHS->getRawScope() && Name == RHS->getName() && + LinkageName == RHS->getLinkageName() && File == RHS->getRawFile() && + Line == RHS->getLine() && Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() && IsDefinition == RHS->isDefinition() && - Variable == RHS->getVariable() && - StaticDataMemberDeclaration == RHS->getStaticDataMemberDeclaration(); + Variable == RHS->getRawVariable() && + StaticDataMemberDeclaration == + RHS->getRawStaticDataMemberDeclaration(); } unsigned getHashValue() const { return hash_combine(Scope, Name, LinkageName, File, Line, Type, @@ -739,16 +740,17 @@ template <> struct MDNodeKeyImpl { : Tag(Tag), Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg), Flags(Flags), InlinedAt(InlinedAt) {} MDNodeKeyImpl(const MDLocalVariable *N) - : Tag(N->getTag()), Scope(N->getScope()), Name(N->getName()), - File(N->getFile()), Line(N->getLine()), Type(N->getType()), - Arg(N->getArg()), Flags(N->getFlags()), InlinedAt(N->getInlinedAt()) {} + : Tag(N->getTag()), Scope(N->getRawScope()), Name(N->getName()), + File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), + Arg(N->getArg()), Flags(N->getFlags()), + InlinedAt(N->getRawInlinedAt()) {} bool isKeyOf(const MDLocalVariable *RHS) const { - return Tag == RHS->getTag() && Scope == RHS->getScope() && - Name == RHS->getName() && File == RHS->getFile() && - Line == RHS->getLine() && Type == RHS->getType() && + return Tag == RHS->getTag() && Scope == RHS->getRawScope() && + Name == RHS->getName() && File == RHS->getRawFile() && + Line == RHS->getLine() && Type == RHS->getRawType() && Arg == RHS->getArg() && Flags == RHS->getFlags() && - InlinedAt == RHS->getInlinedAt(); + InlinedAt == RHS->getRawInlinedAt(); } unsigned getHashValue() const { return hash_combine(Tag, Scope, Name, File, Line, Type, Arg, Flags, diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index bba24c39221..22b6bf80807 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -298,6 +298,7 @@ private: #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); #include "llvm/IR/Metadata.def" + void visitMDVariable(const MDVariable &N); // InstVisitor overrides... using InstVisitor::visit; @@ -658,6 +659,15 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { visitValueAsMetadata(*V, F); } +/// \brief Check if a value can be a reference to a type. +static bool isTypeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast(MD)) + return !S->getString().empty(); + return isa(MD); +} + void Verifier::visitMDLocation(const MDLocation &N) { Assert(N.getRawScope() && isa(N.getRawScope()), "location requires a valid scope", &N, N.getRawScope()); @@ -749,14 +759,42 @@ void Verifier::visitMDTemplateValueParameter( "invalid tag", &N); } +void Verifier::visitMDVariable(const MDVariable &N) { + if (auto *S = N.getRawScope()) + Assert(isa(S), "invalid scope", &N, S); + Assert(isTypeRef(N.getRawType()), "invalid type ref", &N, N.getRawType()); + if (auto *F = N.getRawFile()) + Assert(isa(F), "invalid file", &N, F); +} + void Verifier::visitMDGlobalVariable(const MDGlobalVariable &N) { + // Checks common to all variables. + visitMDVariable(N); + Assert(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N); + if (auto *V = N.getRawVariable()) { + Assert(isa(V) && + !isa(cast(V)->getValue()), + "invalid global varaible ref", &N, V); + } + if (auto *Member = N.getRawStaticDataMemberDeclaration()) { + Assert(isa(Member), "invalid static data member declaration", + &N, Member); + } } void Verifier::visitMDLocalVariable(const MDLocalVariable &N) { + // Checks common to all variables. + visitMDVariable(N); + Assert(N.getTag() == dwarf::DW_TAG_auto_variable || N.getTag() == dwarf::DW_TAG_arg_variable, "invalid tag", &N); + Assert(N.getRawScope() && isa(N.getRawScope()), + "local variable requires a valid scope", &N, N.getRawScope()); + if (auto *IA = N.getRawInlinedAt()) + Assert(isa(IA), "local variable requires a valid scope", &N, + IA); } void Verifier::visitMDExpression(const MDExpression &N) { diff --git a/test/Assembler/invalid-mdlocalvariable-missing-name.ll b/test/Assembler/invalid-mdlocalvariable-missing-name.ll deleted file mode 100644 index 5b23600a0e4..00000000000 --- a/test/Assembler/invalid-mdlocalvariable-missing-name.ll +++ /dev/null @@ -1,4 +0,0 @@ -; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s - -; CHECK: :[[@LINE+1]]:29: error: missing required field 'tag' -!0 = !MDLocalVariable(arg: 7) diff --git a/test/Assembler/invalid-mdlocalvariable-missing-scope.ll b/test/Assembler/invalid-mdlocalvariable-missing-scope.ll new file mode 100644 index 00000000000..d8ee8a97307 --- /dev/null +++ b/test/Assembler/invalid-mdlocalvariable-missing-scope.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:48: error: missing required field 'scope' +!0 = !MDLocalVariable(tag: DW_TAG_auto_variable) diff --git a/test/Assembler/invalid-mdlocalvariable-missing-tag.ll b/test/Assembler/invalid-mdlocalvariable-missing-tag.ll new file mode 100644 index 00000000000..d3ca10a2013 --- /dev/null +++ b/test/Assembler/invalid-mdlocalvariable-missing-tag.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@LINE+1]]:45: error: missing required field 'tag' +!0 = !MDLocalVariable(scope: !MDSubprogram()) diff --git a/test/Assembler/mdglobalvariable.ll b/test/Assembler/mdglobalvariable.ll index 09d20bf5188..d48fef93cda 100644 --- a/test/Assembler/mdglobalvariable.ll +++ b/test/Assembler/mdglobalvariable.ll @@ -3,20 +3,25 @@ @foo = global i32 0 -; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6} -!named = !{!0, !1, !2, !3, !4, !5, !6} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} -!0 = distinct !{} +!0 = !MDFile(filename: "scope.h", directory: "/path/to/dir") !1 = distinct !{} !2 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") -!3 = distinct !{} +!3 = !MDBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) !4 = distinct !{} -; CHECK: !5 = !MDGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, variable: i32* @foo, declaration: !4) +; CHECK: !5 = !MDGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, variable: i32* @foo) !5 = !MDGlobalVariable(name: "foo", linkageName: "foo", scope: !0, file: !2, line: 7, type: !3, isLocal: true, - isDefinition: false, variable: i32* @foo, - declaration: !4) + isDefinition: false, variable: i32* @foo) -; CHECK: !6 = !MDGlobalVariable(scope: null, isLocal: false, isDefinition: true) -!6 = !MDGlobalVariable() +; CHECK: !6 = !MDGlobalVariable(scope: !0, isLocal: false, isDefinition: true) +!6 = !MDGlobalVariable(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) + +; CHECK: !9 = !MDGlobalVariable(name: "mem", scope: !0, isLocal: false, isDefinition: true, declaration: !8) +!9 = !MDGlobalVariable(name: "mem", scope: !0, declaration: !8) diff --git a/test/Assembler/mdlocalvariable.ll b/test/Assembler/mdlocalvariable.ll index 3a36c7d719a..e9ab8f80101 100644 --- a/test/Assembler/mdlocalvariable.ll +++ b/test/Assembler/mdlocalvariable.ll @@ -6,11 +6,11 @@ ; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} -!0 = distinct !{} +!0 = distinct !MDSubprogram() !1 = distinct !{} !2 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") -!3 = distinct !{} -!4 = distinct !{} +!3 = !MDBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!4 = !MDLocation(scope: !0) ; CHECK: !5 = !MDLocalVariable(tag: DW_TAG_arg_variable, name: "foo", arg: 3, scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial, inlinedAt: !4) ; CHECK: !6 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "foo", scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial, inlinedAt: !4) @@ -20,7 +20,7 @@ !6 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "foo", scope: !0, file: !2, line: 7, type: !3, flags: DIFlagArtificial, inlinedAt: !4) -; CHECK: !7 = !MDLocalVariable(tag: DW_TAG_arg_variable, arg: 0, scope: null) -; CHECK: !8 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: null) -!7 = !MDLocalVariable(tag: DW_TAG_arg_variable) -!8 = !MDLocalVariable(tag: DW_TAG_auto_variable) +; CHECK: !7 = !MDLocalVariable(tag: DW_TAG_arg_variable, arg: 0, scope: !0) +; CHECK: !8 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: !0) +!7 = !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !0) +!8 = !MDLocalVariable(tag: DW_TAG_auto_variable, scope: !0) diff --git a/test/Verifier/llvm.dbg.declare-address.ll b/test/Verifier/llvm.dbg.declare-address.ll index f4a93662416..b7735b02a13 100644 --- a/test/Verifier/llvm.dbg.declare-address.ll +++ b/test/Verifier/llvm.dbg.declare-address.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.declare(metadata !"", metadata !MDLocalVariable(tag: DW_TAG_arg_variable), metadata !MDExpression()) + call void @llvm.dbg.declare(metadata !"", metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !MDExpression()) ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram() diff --git a/test/Verifier/llvm.dbg.declare-expression.ll b/test/Verifier/llvm.dbg.declare-expression.ll index 1121e43ee5a..0491fdc95aa 100644 --- a/test/Verifier/llvm.dbg.declare-expression.ll +++ b/test/Verifier/llvm.dbg.declare-expression.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.declare(metadata i32* %s, metadata !MDLocalVariable(tag: DW_TAG_arg_variable), metadata !"") + call void @llvm.dbg.declare(metadata i32* %s, metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !"") ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram() diff --git a/test/Verifier/llvm.dbg.value-expression.ll b/test/Verifier/llvm.dbg.value-expression.ll index c0d14a5a2c2..b60c4722fac 100644 --- a/test/Verifier/llvm.dbg.value-expression.ll +++ b/test/Verifier/llvm.dbg.value-expression.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable), metadata !"") + call void @llvm.dbg.value(metadata i32* %s, i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !"") ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram() diff --git a/test/Verifier/llvm.dbg.value-value.ll b/test/Verifier/llvm.dbg.value-value.ll index b64febe0702..37e3309a219 100644 --- a/test/Verifier/llvm.dbg.value-value.ll +++ b/test/Verifier/llvm.dbg.value-value.ll @@ -6,7 +6,7 @@ define void @foo(i32 %a) { entry: %s = alloca i32 - call void @llvm.dbg.value(metadata !"", i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable), metadata !MDExpression()) + call void @llvm.dbg.value(metadata !"", i64 0, metadata !MDLocalVariable(tag: DW_TAG_arg_variable, scope: !1), metadata !MDExpression()) ret void } @@ -14,3 +14,4 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !MDSubprogram() diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 51a9e0bfc12..9d779d92935 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -61,8 +61,13 @@ TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) { } class MetadataTest : public testing::Test { +public: + MetadataTest() : Counter(0) {} + protected: LLVMContext Context; + int Counter; + MDNode *getNode() { return MDNode::get(Context, None); } MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); } MDNode *getNode(Metadata *MD1, Metadata *MD2) { @@ -75,6 +80,21 @@ protected: nullptr, false, false, 0, nullptr, 0, 0, 0, 0); } + MDFile *getFile() { + return MDFile::getDistinct(Context, "file.c", "/path/to/dir"); + } + MDBasicType *getBasicType(StringRef Name) { + return MDBasicType::get(Context, dwarf::DW_TAG_unspecified_type, Name); + } + MDDerivedType *getDerivedType() { + return MDDerivedType::getDistinct(Context, dwarf::DW_TAG_pointer_type, "", + nullptr, 0, nullptr, + getBasicType("basictype"), 1, 2, 0, 0); + } + ConstantAsMetadata *getConstantAsMetadata() { + return ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(Context), Counter++)); + } }; typedef MetadataTest MDStringTest; @@ -1646,16 +1666,16 @@ TEST_F(MDTemplateValueParameterTest, get) { typedef MetadataTest MDGlobalVariableTest; TEST_F(MDGlobalVariableTest, get) { - Metadata *Scope = MDTuple::getDistinct(Context, None); + MDScope *Scope = getSubprogram(); StringRef Name = "name"; StringRef LinkageName = "linkage"; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); unsigned Line = 5; Metadata *Type = MDTuple::getDistinct(Context, None); bool IsLocalToUnit = false; bool IsDefinition = true; - Metadata *Variable = MDTuple::getDistinct(Context, None); - Metadata *StaticDataMemberDeclaration = MDTuple::getDistinct(Context, None); + ConstantAsMetadata *Variable = getConstantAsMetadata(); + MDDerivedType *StaticDataMemberDeclaration = getDerivedType(); auto *N = MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, @@ -1675,18 +1695,20 @@ TEST_F(MDGlobalVariableTest, get) { Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)); - EXPECT_NE(N, MDGlobalVariable::get(Context, File, Name, LinkageName, File, - Line, Type, IsLocalToUnit, IsDefinition, - Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, + MDGlobalVariable::get(Context, getSubprogram(), Name, LinkageName, + File, Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)); EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, "other", File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)); - EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, Scope, - Line, Type, IsLocalToUnit, IsDefinition, - Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, + MDGlobalVariable::get(Context, Scope, Name, LinkageName, getFile(), + Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line + 1, Type, IsLocalToUnit, IsDefinition, @@ -1702,10 +1724,11 @@ TEST_F(MDGlobalVariableTest, get) { Variable, StaticDataMemberDeclaration)); EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Type, StaticDataMemberDeclaration)); + getConstantAsMetadata(), + StaticDataMemberDeclaration)); EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - Variable, Type)); + Variable, getDerivedType())); TempMDGlobalVariable Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -1715,16 +1738,15 @@ typedef MetadataTest MDLocalVariableTest; TEST_F(MDLocalVariableTest, get) { unsigned Tag = dwarf::DW_TAG_arg_variable; - Metadata *Scope = MDTuple::getDistinct(Context, None); + MDLocalScope *Scope = getSubprogram(); StringRef Name = "name"; - Metadata *File = MDTuple::getDistinct(Context, None); + MDFile *File = getFile(); unsigned Line = 5; Metadata *Type = MDTuple::getDistinct(Context, None); unsigned Arg = 6; unsigned Flags = 7; - Metadata *InlinedAtScope = MDTuple::getDistinct(Context, None); - Metadata *InlinedAt = - MDLocation::getDistinct(Context, 10, 20, InlinedAtScope); + MDLocation *InlinedAt = + MDLocation::getDistinct(Context, 10, 20, getSubprogram()); auto *N = MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt); @@ -1743,11 +1765,11 @@ TEST_F(MDLocalVariableTest, get) { EXPECT_NE(N, MDLocalVariable::get(Context, dwarf::DW_TAG_auto_variable, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)); - EXPECT_NE(N, MDLocalVariable::get(Context, Tag, File, Name, File, Line, - Type, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, getSubprogram(), Name, File, + Line, Type, Arg, Flags, InlinedAt)); EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, "other", File, Line, Type, Arg, Flags, InlinedAt)); - EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, Scope, Line, + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, getFile(), Line, Type, Arg, Flags, InlinedAt)); EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line + 1, Type, Arg, Flags, InlinedAt)); @@ -1757,8 +1779,9 @@ TEST_F(MDLocalVariableTest, get) { Arg + 1, Flags, InlinedAt)); EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, Arg, ~Flags, InlinedAt)); - EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, - Arg, Flags, Scope)); + EXPECT_NE(N, MDLocalVariable::get( + Context, Tag, Scope, Name, File, Line, Type, Arg, Flags, + MDLocation::getDistinct(Context, 10, 20, getSubprogram()))); TempMDLocalVariable Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));