Commit 722bfb51 by Olli Etuaho Committed by Commit Bot

Fix detecting duplicate field names in structures

Previously field names that were listed in the first declarator list inside a struct declaration were not checked against each other. BUG=angleproject:2204 TEST=angle_unittests Change-Id: Ibf821d45556f6dfe0223dae673644f6795daf4cb Reviewed-on: https://chromium-review.googlesource.com/739825Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 9088557f
...@@ -4573,19 +4573,39 @@ TField *TParseContext::parseStructArrayDeclarator(TString *identifier, ...@@ -4573,19 +4573,39 @@ TField *TParseContext::parseStructArrayDeclarator(TString *identifier,
return new TField(type, identifier, loc); return new TField(type, identifier, loc);
} }
void TParseContext::checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
const TFieldList::const_iterator end,
const TString &name,
const TSourceLoc &location)
{
for (auto fieldIter = begin; fieldIter != end; ++fieldIter)
{
if ((*fieldIter)->name() == name)
{
error(location, "duplicate field name in structure", name.c_str());
}
}
}
TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
{
for (TFieldList::const_iterator fieldIter = fields->begin(); fieldIter != fields->end();
++fieldIter)
{
checkDoesNotHaveDuplicateFieldName(fields->begin(), fieldIter, (*fieldIter)->name(),
location);
}
return fields;
}
TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields, TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
const TFieldList *newlyAddedFields, const TFieldList *newlyAddedFields,
const TSourceLoc &location) const TSourceLoc &location)
{ {
for (TField *field : *newlyAddedFields) for (TField *field : *newlyAddedFields)
{ {
for (TField *oldField : *processedFields) checkDoesNotHaveDuplicateFieldName(processedFields->begin(), processedFields->end(),
{ field->name(), location);
if (oldField->name() == field->name())
{
error(location, "duplicate field name in structure", field->name().c_str());
}
}
processedFields->push_back(field); processedFields->push_back(field);
} }
return processedFields; return processedFields;
......
...@@ -306,6 +306,11 @@ class TParseContext : angle::NonCopyable ...@@ -306,6 +306,11 @@ class TParseContext : angle::NonCopyable
unsigned int arraySize, unsigned int arraySize,
const TSourceLoc &arraySizeLoc); const TSourceLoc &arraySizeLoc);
void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
const TFieldList::const_iterator end,
const TString &name,
const TSourceLoc &location);
TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location);
TFieldList *combineStructFieldLists(TFieldList *processedFields, TFieldList *combineStructFieldLists(TFieldList *processedFields,
const TFieldList *newlyAddedFields, const TFieldList *newlyAddedFields,
const TSourceLoc &location); const TSourceLoc &location);
......
...@@ -1187,7 +1187,7 @@ struct_specifier ...@@ -1187,7 +1187,7 @@ struct_specifier
struct_declaration_list struct_declaration_list
: struct_declaration { : struct_declaration {
$$ = $1; $$ = context->addStructFieldList($1, @1);
} }
| struct_declaration_list struct_declaration { | struct_declaration_list struct_declaration {
$$ = context->combineStructFieldLists($1, $2, @2); $$ = context->combineStructFieldLists($1, $2, @2);
......
...@@ -4358,7 +4358,7 @@ yyreduce: ...@@ -4358,7 +4358,7 @@ yyreduce:
case 229: case 229:
{ {
(yyval.interm.fieldList) = (yyvsp[0].interm.fieldList); (yyval.interm.fieldList) = context->addStructFieldList((yyvsp[0].interm.fieldList), (yylsp[0]));
} }
break; break;
......
...@@ -5172,4 +5172,25 @@ TEST_F(FragmentShaderValidationTest, PartiallyUnsizedArrayOfArraysConstructor) ...@@ -5172,4 +5172,25 @@ TEST_F(FragmentShaderValidationTest, PartiallyUnsizedArrayOfArraysConstructor)
{ {
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
} }
} }
\ No newline at end of file
// Test that duplicate field names in a struct declarator list are validated.
TEST_F(FragmentShaderValidationTest, DuplicateFieldNamesInStructDeclaratorList)
{
const std::string &shaderString =
R"(precision mediump float;
struct S {
float f, f;
};
void main()
{
gl_FragColor = vec4(1.0);
})";
if (compile(shaderString))
{
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment