dwarf2read: Restrict ICC workaround to ICC<14

GDB has a workaround for DWARF output by ICC, related to missing
DW_AT_declaration on incomplete types.  The bug was fixed in ICC 14,
so this commit adjusts GDB accordingly.

For the version check, this adds a new parser function for the ICC
producer string.  While at it, it also adds unit tests for the
producer parsing covering the new function and preexisting parsers.

gdb/ChangeLog:
2017-09-26  Walfred Tedeschi  <walfred.tedeschi@intel.com>
	    Pedro Alves <palves@redhat.com>

	* dwarf2read.c (dwarf2_cu): Remove field producer_is_icc and add
	producer_is_icc_lt_14.
	(producer_is_icc_lt_14): New function.
	(check_producer): Add code for checking version of ICC.
	(producer_is_icc): Move to producer.c.
	(read_structure_type): Restrict ICC workaround to ICC<14.
	* producer.c: Include selftest.h.
	(producer_is_icc, producer_parsing_tests, _initialize_producer):
	New functions.
	* producer.h (producer_is_icc): New declaration.
This commit is contained in:
Walfred Tedeschi 2017-09-26 18:26:41 +01:00 committed by Pedro Alves
parent b32b108aba
commit 5230b05a94
4 changed files with 200 additions and 17 deletions

View File

@ -1,3 +1,17 @@
2017-09-26 Walfred Tedeschi <walfred.tedeschi@intel.com>
Pedro Alves <palves@redhat.com>
* dwarf2read.c (dwarf2_cu): Remove field producer_is_icc and add
producer_is_icc_lt_14.
(producer_is_icc_lt_14): New function.
(check_producer): Add code for checking version of ICC.
(producer_is_icc): Move to producer.c.
(read_structure_type): Restrict ICC workaround to ICC<14.
* producer.c: Include selftest.h.
(producer_is_icc, producer_parsing_tests, _initialize_producer):
New functions.
* producer.h (producer_is_icc): New declaration.
2017-09-26 Walfred Tedeschi <walfred.tedeschi@intel.com>
* Makefile.in (SFILES): Add producer.c.

View File

@ -603,7 +603,7 @@ struct dwarf2_cu
unsigned int checked_producer : 1;
unsigned int producer_is_gxx_lt_4_6 : 1;
unsigned int producer_is_gcc_lt_4_3 : 1;
unsigned int producer_is_icc : 1;
unsigned int producer_is_icc_lt_14 : 1;
/* When set, the file that we're processing is known to have
debugging info for C++ namespaces. GCC 3.3.x did not produce
@ -9348,6 +9348,19 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
&objfile->objfile_obstack);
}
/* ICC<14 does not output the required DW_AT_declaration on incomplete
types, but gives them a size of zero. Starting with version 14,
ICC is compatible with GCC. */
static int
producer_is_icc_lt_14 (struct dwarf2_cu *cu)
{
if (!cu->checked_producer)
check_producer (cu);
return cu->producer_is_icc_lt_14;
}
/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
directory paths. GCC SVN r127613 (new option -fdebug-prefix-map) fixed
this, it was first present in GCC release 4.3.0. */
@ -12853,8 +12866,8 @@ check_producer (struct dwarf2_cu *cu)
cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
}
else if (startswith (cu->producer, "Intel(R) C"))
cu->producer_is_icc = 1;
else if (producer_is_icc (cu->producer, &major, &minor))
cu->producer_is_icc_lt_14 = major < 14;
else
{
/* For other non-GCC compilers, expect their behavior is DWARF version
@ -13595,17 +13608,6 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
smash_to_methodptr_type (type, new_type);
}
/* Return non-zero if the CU's PRODUCER string matches the Intel C/C++ compiler
(icc). */
static int
producer_is_icc (struct dwarf2_cu *cu)
{
if (!cu->checked_producer)
check_producer (cu);
return cu->producer_is_icc;
}
/* Called when we find the DIE that starts a structure or union scope
(definition) to create a type for the structure or union. Fill in
@ -13711,10 +13713,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
TYPE_LENGTH (type) = 0;
}
if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
if (producer_is_icc_lt_14 (cu) && (TYPE_LENGTH (type) == 0))
{
/* ICC does not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. */
/* ICC<14 does not output the required DW_AT_declaration on
incomplete types, but gives them a size of zero. */
TYPE_STUB (type) = 1;
}
else

View File

@ -19,6 +19,7 @@
#include "defs.h"
#include "producer.h"
#include "selftest.h"
/* See producer.h. */
@ -71,3 +72,147 @@ producer_is_gcc (const char *producer, int *major, int *minor)
return 0;
}
/* See producer.h. */
bool
producer_is_icc (const char *producer, int *major, int *minor)
{
if (producer == NULL || !startswith (producer, "Intel(R)"))
return false;
/* Prepare the used fields. */
int maj, min;
if (major == NULL)
major = &maj;
if (minor == NULL)
minor = &min;
*minor = 0;
*major = 0;
/* Consumes the string till a "Version" is found. */
const char *cs = strstr (producer, "Version");
if (cs != NULL)
{
cs = skip_to_space (cs);
int intermediate = 0;
int nof = sscanf (cs, "%d.%d.%d.%*d", major, &intermediate, minor);
/* Internal versions are represented only as MAJOR.MINOR, where
minor is usually 0.
Public versions have 3 fields as described with the command
above. */
if (nof == 3)
return true;
if (nof == 2)
{
*minor = intermediate;
return true;
}
}
static bool warning_printed = false;
/* Not recognized as Intel, let the user know. */
if (!warning_printed)
{
warning (_("Could not recognize version of Intel Compiler in: \"%s\""),
producer);
warning_printed = true;
}
return false;
}
#if defined GDB_SELF_TEST
namespace selftests {
namespace producer {
static void
producer_parsing_tests ()
{
{
/* Check that we don't crash if "Version" is not found in what
looks like an ICC producer string. */
static const char icc_no_version[] = "Intel(R) foo bar";
int major = 0, minor = 0;
SELF_CHECK (!producer_is_icc (icc_no_version, &major, &minor));
SELF_CHECK (!producer_is_gcc (icc_no_version, &major, &minor));
}
{
static const char extern_f_14_1[] = "\
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
Intel(R) 64, \
Version 14.0.1.074 Build 20130716";
int major = 0, minor = 0;
SELF_CHECK (producer_is_icc (extern_f_14_1, &major, &minor)
&& major == 14 && minor == 1);
SELF_CHECK (!producer_is_gcc (extern_f_14_1, &major, &minor));
}
{
static const char intern_f_14[] = "\
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on \
Intel(R) 64, \
Version 14.0";
int major = 0, minor = 0;
SELF_CHECK (producer_is_icc (intern_f_14, &major, &minor)
&& major == 14 && minor == 0);
SELF_CHECK (!producer_is_gcc (intern_f_14, &major, &minor));
}
{
static const char intern_c_14[] = "\
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on \
Intel(R) 64, \
Version 14.0";
int major = 0, minor = 0;
SELF_CHECK (producer_is_icc (intern_c_14, &major, &minor)
&& major == 14 && minor == 0);
SELF_CHECK (!producer_is_gcc (intern_c_14, &major, &minor));
}
{
static const char intern_c_18[] = "\
Intel(R) C++ Intel(R) 64 Compiler for applications running on \
Intel(R) 64, \
Version 18.0 Beta";
int major = 0, minor = 0;
SELF_CHECK (producer_is_icc (intern_c_18, &major, &minor)
&& major == 18 && minor == 0);
}
{
static const char gnu[] = "GNU C 4.7.2";
SELF_CHECK (!producer_is_icc (gnu, NULL, NULL));
int major = 0, minor = 0;
SELF_CHECK (producer_is_gcc (gnu, &major, &minor)
&& major == 4 && minor == 7);
}
{
static const char gnu_exp[] = "GNU C++14 5.0.0 20150123 (experimental)";
int major = 0, minor = 0;
SELF_CHECK (!producer_is_icc (gnu_exp, NULL, NULL));
SELF_CHECK (producer_is_gcc (gnu_exp, &major, &minor)
&& major == 5 && minor == 0);
}
}
}
}
#endif
void
_initialize_producer ()
{
#if defined GDB_SELF_TEST
selftests::register_test
("producer-parser", selftests::producer::producer_parsing_tests);
#endif
}

View File

@ -30,4 +30,26 @@ extern int producer_is_gcc_ge_4 (const char *producer);
is NULL or it isn't GCC. */
extern int producer_is_gcc (const char *producer, int *major, int *minor);
/* Returns true if the given PRODUCER string is Intel or false
otherwise. Sets the MAJOR and MINOR versions when not NULL.
Internal and external ICC versions have to be taken into account.
PRODUCER strings for internal releases are slightly different than
for public ones. Internal releases have a major release number and
0 as minor release. External releases have 4 fields, 3 of them are
not 0 and only two are of interest, major and update.
Examples are:
Public release:
"Intel(R) Fortran Intel(R) 64 Compiler XE for applications
running on Intel(R) 64, Version 14.0.1.074 Build 20130716";
"Intel(R) C++ Intel(R) 64 Compiler XE for applications
running on Intel(R) 64, Version 14.0.1.074 Build 20130716";
Internal releases:
"Intel(R) C++ Intel(R) 64 Compiler for applications
running on Intel(R) 64, Version 18.0 Beta ....". */
extern bool producer_is_icc (const char *producer, int *major, int *minor);
#endif