Allow referring to the struct type being defined in its members.
It's now legal to write:
struct Foo { Foo *next; };
previously, a predeclaration "struct Foo;" was required. This fixes
issue #287.
This change also fixes a bug where multiple forward declarations
"struct Foo; struct Foo;" would incorrectly issue an error on the
second one.
This commit is contained in:
61
parse.yy
61
parse.yy
@@ -232,6 +232,7 @@ struct ForeachDimension {
|
|||||||
%type <enumType> enum_specifier
|
%type <enumType> enum_specifier
|
||||||
|
|
||||||
%type <type> specifier_qualifier_list struct_or_union_specifier
|
%type <type> specifier_qualifier_list struct_or_union_specifier
|
||||||
|
%type <type> struct_or_union_and_name
|
||||||
%type <type> type_specifier type_name rate_qualified_type_specifier
|
%type <type> type_specifier type_name rate_qualified_type_specifier
|
||||||
%type <type> short_vec_specifier
|
%type <type> short_vec_specifier
|
||||||
%type <typeList> type_specifier_list
|
%type <typeList> type_specifier_list
|
||||||
@@ -876,18 +877,44 @@ struct_or_union_name
|
|||||||
| TOKEN_TYPE_NAME { $$ = strdup(yytext); }
|
| TOKEN_TYPE_NAME { $$ = strdup(yytext); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
struct_or_union_and_name
|
||||||
|
: struct_or_union struct_or_union_name
|
||||||
|
{
|
||||||
|
const Type *st = m->symbolTable->LookupType($2);
|
||||||
|
if (st == NULL) {
|
||||||
|
st = new UndefinedStructType($2, Variability::Unbound, false, @2);
|
||||||
|
m->symbolTable->AddType($2, st, @2);
|
||||||
|
$$ = st;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (CastType<StructType>(st) == NULL &&
|
||||||
|
CastType<UndefinedStructType>(st) == NULL) {
|
||||||
|
Error(@2, "Type \"%s\" is not a struct type! (%s)", $2,
|
||||||
|
st->GetString().c_str());
|
||||||
|
$$ = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$$ = st;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
struct_or_union_specifier
|
struct_or_union_specifier
|
||||||
: struct_or_union struct_or_union_name '{' struct_declaration_list '}'
|
: struct_or_union_and_name
|
||||||
|
| struct_or_union_and_name '{' struct_declaration_list '}'
|
||||||
{
|
{
|
||||||
if ($4 != NULL) {
|
if ($3 != NULL) {
|
||||||
llvm::SmallVector<const Type *, 8> elementTypes;
|
llvm::SmallVector<const Type *, 8> elementTypes;
|
||||||
llvm::SmallVector<std::string, 8> elementNames;
|
llvm::SmallVector<std::string, 8> elementNames;
|
||||||
llvm::SmallVector<SourcePos, 8> elementPositions;
|
llvm::SmallVector<SourcePos, 8> elementPositions;
|
||||||
GetStructTypesNamesPositions(*$4, &elementTypes, &elementNames,
|
GetStructTypesNamesPositions(*$3, &elementTypes, &elementNames,
|
||||||
&elementPositions);
|
&elementPositions);
|
||||||
StructType *st = new StructType($2, elementTypes, elementNames,
|
const std::string &name = CastType<StructType>($1) ?
|
||||||
elementPositions, false, Variability::Unbound, @2);
|
CastType<StructType>($1)->GetStructName() :
|
||||||
m->symbolTable->AddType($2, st, @2);
|
CastType<UndefinedStructType>($1)->GetStructName();
|
||||||
|
StructType *st = new StructType(name, elementTypes, elementNames,
|
||||||
|
elementPositions, false, Variability::Unbound, @1);
|
||||||
|
m->symbolTable->AddType(name.c_str(), st, @1);
|
||||||
$$ = st;
|
$$ = st;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -915,26 +942,18 @@ struct_or_union_specifier
|
|||||||
$$ = new StructType("", elementTypes, elementNames, elementPositions,
|
$$ = new StructType("", elementTypes, elementNames, elementPositions,
|
||||||
false, Variability::Unbound, @1);
|
false, Variability::Unbound, @1);
|
||||||
}
|
}
|
||||||
| struct_or_union struct_or_union_name '{' '}'
|
| struct_or_union_and_name '{' '}'
|
||||||
{
|
{
|
||||||
llvm::SmallVector<const Type *, 8> elementTypes;
|
llvm::SmallVector<const Type *, 8> elementTypes;
|
||||||
llvm::SmallVector<std::string, 8> elementNames;
|
llvm::SmallVector<std::string, 8> elementNames;
|
||||||
llvm::SmallVector<SourcePos, 8> elementPositions;
|
llvm::SmallVector<SourcePos, 8> elementPositions;
|
||||||
StructType *st = new StructType($2, elementTypes, elementNames, elementPositions,
|
const std::string &name = CastType<StructType>($1) ?
|
||||||
|
CastType<StructType>($1)->GetStructName() :
|
||||||
|
CastType<UndefinedStructType>($1)->GetStructName();
|
||||||
|
StructType *st = new StructType(name, elementTypes,
|
||||||
|
elementNames, elementPositions,
|
||||||
false, Variability::Unbound, @1);
|
false, Variability::Unbound, @1);
|
||||||
m->symbolTable->AddType($2, st, @2);
|
m->symbolTable->AddType(name.c_str(), st, @2);
|
||||||
$$ = st;
|
|
||||||
}
|
|
||||||
| struct_or_union struct_or_union_name
|
|
||||||
{
|
|
||||||
const Type *st = m->symbolTable->LookupType($2);
|
|
||||||
if (st == NULL) {
|
|
||||||
st = new UndefinedStructType($2, Variability::Unbound, false, @2);
|
|
||||||
m->symbolTable->AddType($2, st, @2);
|
|
||||||
}
|
|
||||||
else if (CastType<StructType>(st) == NULL)
|
|
||||||
Error(@2, "Type \"%s\" is not a struct type! (%s)", $2,
|
|
||||||
st->GetString().c_str());
|
|
||||||
$$ = st;
|
$$ = st;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user