Various fixes for C++ class parsing (nesting, templates) (from test
cases provided by Michael Lin).
This commit is contained in:
parent
5e2075be3a
commit
e4a44b3545
@ -104,9 +104,18 @@ static void stab_strcpy(char* dest, int sz, const char* source)
|
|||||||
* A strcpy routine that stops when we hit the ':' character.
|
* A strcpy routine that stops when we hit the ':' character.
|
||||||
* Faster than copying the whole thing, and then nuking the
|
* Faster than copying the whole thing, and then nuking the
|
||||||
* ':'.
|
* ':'.
|
||||||
|
* Takes also care of (valid) a::b constructs
|
||||||
*/
|
*/
|
||||||
while (*source != '\0' && *source != ':' && sz-- > 0)
|
while (*source != '\0')
|
||||||
|
{
|
||||||
|
if (source[0] != ':' && sz-- > 0) *dest++ = *source++;
|
||||||
|
else if (source[1] == ':' && (sz -= 2) > 0)
|
||||||
|
{
|
||||||
*dest++ = *source++;
|
*dest++ = *source++;
|
||||||
|
*dest++ = *source++;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
*dest-- = '\0';
|
*dest-- = '\0';
|
||||||
/* GCC seems to emit, in some cases, a .<digit>+ suffix.
|
/* GCC seems to emit, in some cases, a .<digit>+ suffix.
|
||||||
* This is used for static variable inside functions, so
|
* This is used for static variable inside functions, so
|
||||||
@ -358,17 +367,30 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd,
|
|||||||
static int stabs_pts_read_id(struct ParseTypedefData* ptd)
|
static int stabs_pts_read_id(struct ParseTypedefData* ptd)
|
||||||
{
|
{
|
||||||
const char* first = ptd->ptr;
|
const char* first = ptd->ptr;
|
||||||
unsigned int len;
|
unsigned int template = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL);
|
while ((ch = *ptd->ptr++) != '\0')
|
||||||
len = ptd->ptr - first;
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case ':':
|
||||||
|
if (template == 0)
|
||||||
|
{
|
||||||
|
unsigned int len = ptd->ptr - first - 1;
|
||||||
PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
|
PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
|
||||||
memcpy(ptd->buf + ptd->idx, first, len);
|
memcpy(ptd->buf + ptd->idx, first, len);
|
||||||
ptd->buf[ptd->idx + len] = '\0';
|
ptd->buf[ptd->idx + len] = '\0';
|
||||||
ptd->idx += len + 1;
|
ptd->idx += len + 1;
|
||||||
ptd->ptr++; /* ':' */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case '<': template++; break;
|
||||||
|
case '>': PTS_ABORTIF(ptd, template == 0); template--; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
|
static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
|
||||||
{
|
{
|
||||||
@ -604,7 +626,7 @@ static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd,
|
|||||||
DWORD size;
|
DWORD size;
|
||||||
|
|
||||||
symt_get_info(adt, TI_GET_SYMNAME, &name);
|
symt_get_info(adt, TI_GET_SYMNAME, &name);
|
||||||
strcmp(tmp, "__inherited_class_");
|
strcpy(tmp, "__inherited_class_");
|
||||||
WideCharToMultiByte(CP_ACP, 0, name, -1,
|
WideCharToMultiByte(CP_ACP, 0, name, -1,
|
||||||
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
|
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@ -845,16 +867,28 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
unsigned l1, l2;
|
||||||
if (udt->symt.tag != SymTagUDT)
|
if (udt->symt.tag != SymTagUDT)
|
||||||
{
|
{
|
||||||
ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n",
|
ERR("Forward declaration (%p/%s) is not an aggregate (%u)\n",
|
||||||
udt, symt_get_name(&udt->symt), udt->symt.tag);
|
udt, symt_get_name(&udt->symt), udt->symt.tag);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (strcmp(udt->hash_elt.name, typename))
|
/* FIXME: we currently don't correctly construct nested C++
|
||||||
|
* classes names. Therefore, we could be here with either:
|
||||||
|
* - typename and udt->hash_elt.name being the same string
|
||||||
|
* (non embedded case)
|
||||||
|
* - typename being foo::bar while udt->hash_elt.name being
|
||||||
|
* just bar
|
||||||
|
* So, we twist the comparison to test both occurrences. When
|
||||||
|
* we have proper C++ types in this file, this twist has to be
|
||||||
|
* removed
|
||||||
|
*/
|
||||||
|
l1 = strlen(udt->hash_elt.name);
|
||||||
|
l2 = strlen(typename);
|
||||||
|
if (l1 > l2 || strcmp(udt->hash_elt.name, typename + l2 - l1))
|
||||||
ERR("Forward declaration name mismatch %s <> %s\n",
|
ERR("Forward declaration name mismatch %s <> %s\n",
|
||||||
udt->hash_elt.name, typename);
|
udt->hash_elt.name, typename);
|
||||||
/* should check typename is the same too */
|
|
||||||
new_dt = &udt->symt;
|
new_dt = &udt->symt;
|
||||||
}
|
}
|
||||||
PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1);
|
PTS_ABORTIF(ptd, stabs_pts_read_aggregate(ptd, udt) == -1);
|
||||||
@ -971,7 +1005,7 @@ static int stabs_parse_typedef(struct module* module, const char* ptr,
|
|||||||
|
|
||||||
/* check for already existing definition */
|
/* check for already existing definition */
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_a(ptr));
|
TRACE("%s => %s\n", typename, debugstr_a(ptr));
|
||||||
ptd.module = module;
|
ptd.module = module;
|
||||||
ptd.idx = 0;
|
ptd.idx = 0;
|
||||||
#ifdef PTS_DEBUG
|
#ifdef PTS_DEBUG
|
||||||
|
Loading…
x
Reference in New Issue
Block a user