@@ -30,14 +30,17 @@ extern const char *TestMainArgv0;
3030namespace {
3131
3232const char *DwarfClang = " test-dwarf-clang.o" ;
33+ // Two compile units: one declares `extern int foo_printf(const char *, ...);`
34+ // and another one that defines the function.
35+ const char *DwarfClangUnspecParams = " test-dwarf-clang-unspec-params.elf" ;
3336const char *DwarfGcc = " test-dwarf-gcc.o" ;
3437
3538// Helper function to get the first compile unit.
3639LVScopeCompileUnit *getFirstCompileUnit (LVScopeRoot *Root) {
3740 EXPECT_NE (Root, nullptr );
3841 const LVScopes *CompileUnits = Root->getScopes ();
3942 EXPECT_NE (CompileUnits, nullptr );
40- EXPECT_EQ (CompileUnits->size (), 1u );
43+ EXPECT_GT (CompileUnits->size (), 0u );
4144
4245 LVScopes::const_iterator Iter = CompileUnits->begin ();
4346 EXPECT_NE (Iter, nullptr );
@@ -129,6 +132,36 @@ void checkElementProperties(LVReader *Reader) {
129132 ASSERT_EQ (Lines->size (), 0x12u );
130133}
131134
135+ // Check proper handling of DW_AT_unspecified_parameters in
136+ // LVScope::addMissingElements().
137+ void checkUnspecifiedParameters (LVReader *Reader) {
138+ LVScopeRoot *Root = Reader->getScopesRoot ();
139+ LVScopeCompileUnit *CompileUnit = getFirstCompileUnit (Root);
140+
141+ EXPECT_EQ (Root->getFileFormatName (), " elf64-x86-64" );
142+ EXPECT_EQ (Root->getName (), DwarfClangUnspecParams);
143+
144+ const LVPublicNames &PublicNames = CompileUnit->getPublicNames ();
145+ ASSERT_EQ (PublicNames.size (), 1u );
146+
147+ LVPublicNames::const_iterator IterNames = PublicNames.cbegin ();
148+ LVScope *Function = (*IterNames).first ;
149+ EXPECT_EQ (Function->getName (), " foo_printf" );
150+ const LVElements *Elements = Function->getChildren ();
151+ ASSERT_NE (Elements, nullptr );
152+ // foo_printf is a variadic function whose prototype is
153+ // `int foo_printf(const char *, ...)`, where the '...' is represented by a
154+ // DW_TAG_unspecified_parameters, i.e. we expect to find at least one child
155+ // for which getIsUnspecified() returns true.
156+ EXPECT_EQ (std::any_of (
157+ Elements->begin (), Elements->end (),
158+ [](const LVElement *elt) {
159+ return elt->getIsSymbol () &&
160+ static_cast <const LVSymbol *>(elt)->getIsUnspecified ();
161+ }),
162+ true );
163+ }
164+
132165// Check the logical elements selection.
133166void checkElementSelection (LVReader *Reader) {
134167 LVScopeRoot *Root = Reader->getScopesRoot ();
@@ -258,6 +291,7 @@ void elementProperties(SmallString<128> &InputsDir) {
258291 ReaderOptions.setAttributePublics ();
259292 ReaderOptions.setAttributeRange ();
260293 ReaderOptions.setAttributeLocation ();
294+ ReaderOptions.setAttributeInserted ();
261295 ReaderOptions.setPrintAll ();
262296 ReaderOptions.resolveDependencies ();
263297
@@ -269,6 +303,9 @@ void elementProperties(SmallString<128> &InputsDir) {
269303 std::unique_ptr<LVReader> Reader =
270304 createReader (ReaderHandler, InputsDir, DwarfClang);
271305 checkElementProperties (Reader.get ());
306+
307+ Reader = createReader (ReaderHandler, InputsDir, DwarfClangUnspecParams);
308+ checkUnspecifiedParameters (Reader.get ());
272309}
273310
274311// Logical elements selection.
0 commit comments