Generate a more descriptive error when trying to initialize a const array.

TRAC #21589 Issue=359 Signed-off-by: Daniel Koch Signed-off-by: Shannon Woods Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@1286 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 22ba0f70
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 1285 #define BUILD_REVISION 1286
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -846,14 +846,26 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, ...@@ -846,14 +846,26 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type) bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
{ {
// if (type.qualifier == EvqConst)
// Make the qualifier make sense. {
// // Make the qualifier make sense.
if (type.qualifier == EvqConst) {
type.qualifier = EvqTemporary; type.qualifier = EvqTemporary;
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
if (array)
{
error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
}
else if (type.isStructureContainingArrays())
{
error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
}
else
{
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
}
return true; return true;
} }
......
// //
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -97,7 +97,7 @@ struct TParseContext { ...@@ -97,7 +97,7 @@ struct TParseContext {
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool structQualifierErrorCheck(int line, const TPublicType& pType); bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type); bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type); bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable); bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(int line, const TString&); bool extensionErrorCheck(int line, const TString&);
......
// //
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -20,9 +20,16 @@ ...@@ -20,9 +20,16 @@
#include "common/angleutils.h" #include "common/angleutils.h"
// TType::TType(const TPublicType &p) :
// TType helper function needs a place to live. type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
// maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{
if (p.userDef) {
structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
computeDeepestStructNesting();
}
}
// //
// Recursively generate mangled names. // Recursively generate mangled names.
...@@ -92,6 +99,25 @@ void TType::computeDeepestStructNesting() ...@@ -92,6 +99,25 @@ void TType::computeDeepestStructNesting()
deepestStructNesting = 1 + maxNesting; deepestStructNesting = 1 + maxNesting;
} }
bool TType::isStructureContainingArrays() const
{
if (!structure)
{
return false;
}
for (TTypeList::const_iterator member = structure->begin(); member != structure->end(); member++)
{
if (member->type->isArray() ||
member->type->isStructureContainingArrays())
{
return true;
}
}
return false;
}
// //
// Dump functions. // Dump functions.
// //
......
// //
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/debug.h" #include "compiler/debug.h"
class TType;
struct TPublicType;
// //
// Need to have association of line numbers to types in a list for building structs. // Need to have association of line numbers to types in a list for building structs.
// //
class TType;
struct TTypeLine { struct TTypeLine {
TType* type; TType* type;
int line; int line;
...@@ -27,59 +29,14 @@ inline TTypeList* NewPoolTTypeList() ...@@ -27,59 +29,14 @@ inline TTypeList* NewPoolTTypeList()
return new(memory) TTypeList; return new(memory) TTypeList;
} }
//
// This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers
// could be used, but also trying to avoid lots of memory management overhead.
//
// Not as bad as it looks, there is no actual assumption that the fields
// match up or are name the same or anything like that.
//
class TPublicType {
public:
TBasicType type;
TQualifier qualifier;
TPrecision precision;
int size; // size of vector or matrix, not size of array
bool matrix;
bool array;
int arraySize;
TType* userDef;
int line;
void setBasic(TBasicType bt, TQualifier q, int ln = 0)
{
type = bt;
qualifier = q;
precision = EbpUndefined;
size = 1;
matrix = false;
array = false;
arraySize = 0;
userDef = 0;
line = ln;
}
void setAggregate(int s, bool m = false)
{
size = s;
matrix = m;
}
void setArray(bool a, int s = 0)
{
array = a;
arraySize = s;
}
};
typedef TMap<TTypeList*, TTypeList*> TStructureMap; typedef TMap<TTypeList*, TTypeList*> TStructureMap;
typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator; typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
// //
// Base class for things that have a type. // Base class for things that have a type.
// //
class TType { class TType
{
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TType() {} TType() {}
...@@ -88,16 +45,7 @@ public: ...@@ -88,16 +45,7 @@ public:
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0) maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{ {
} }
explicit TType(const TPublicType &p) : explicit TType(const TPublicType &p);
type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize),
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{
if (p.userDef) {
structure = p.userDef->getStruct();
typeName = NewPoolTString(p.userDef->getTypeName().c_str());
computeDeepestStructNesting();
}
}
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) : TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0) maxArraySize(0), arrayInformationType(0), structure(userDef), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0)
...@@ -284,6 +232,8 @@ public: ...@@ -284,6 +232,8 @@ public:
// deepest field (nesting2.field1.position). // deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; } int getDeepestStructNesting() const { return deepestStructNesting; }
bool isStructureContainingArrays() const;
protected: protected:
void buildMangledName(TString&); void buildMangledName(TString&);
int getStructSize() const; int getStructSize() const;
...@@ -308,4 +258,61 @@ protected: ...@@ -308,4 +258,61 @@ protected:
TString *typeName; // for structure field type name TString *typeName; // for structure field type name
}; };
//
// This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers
// could be used, but also trying to avoid lots of memory management overhead.
//
// Not as bad as it looks, there is no actual assumption that the fields
// match up or are name the same or anything like that.
//
struct TPublicType
{
TBasicType type;
TQualifier qualifier;
TPrecision precision;
int size; // size of vector or matrix, not size of array
bool matrix;
bool array;
int arraySize;
TType* userDef;
int line;
void setBasic(TBasicType bt, TQualifier q, int ln = 0)
{
type = bt;
qualifier = q;
precision = EbpUndefined;
size = 1;
matrix = false;
array = false;
arraySize = 0;
userDef = 0;
line = ln;
}
void setAggregate(int s, bool m = false)
{
size = s;
matrix = m;
}
void setArray(bool a, int s = 0)
{
array = a;
arraySize = s;
}
bool isStructureContainingArrays() const
{
if (!userDef)
{
return false;
}
return userDef->isStructureContainingArrays();
}
};
#endif // _TYPES_INCLUDED_ #endif // _TYPES_INCLUDED_
...@@ -1200,7 +1200,7 @@ init_declarator_list ...@@ -1200,7 +1200,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $$.type)) if (context->structQualifierErrorCheck($3.line, $$.type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type)) if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false))
context->recover(); context->recover();
TVariable* variable = 0; TVariable* variable = 0;
...@@ -1213,7 +1213,7 @@ init_declarator_list ...@@ -1213,7 +1213,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $1.type)) if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
context->recover(); context->recover();
$$ = $1; $$ = $1;
...@@ -1231,7 +1231,7 @@ init_declarator_list ...@@ -1231,7 +1231,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $1.type)) if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type)) if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
context->recover(); context->recover();
$$ = $1; $$ = $1;
...@@ -1285,7 +1285,7 @@ single_declaration ...@@ -1285,7 +1285,7 @@ single_declaration
if (context->structQualifierErrorCheck($2.line, $$.type)) if (context->structQualifierErrorCheck($2.line, $$.type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type)) if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
context->recover(); context->recover();
$$.type = $1; $$.type = $1;
...@@ -1316,7 +1316,7 @@ single_declaration ...@@ -1316,7 +1316,7 @@ single_declaration
if (context->structQualifierErrorCheck($2.line, $1)) if (context->structQualifierErrorCheck($2.line, $1))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $1)) if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
context->recover(); context->recover();
$$.type = $1; $$.type = $1;
......
...@@ -3333,7 +3333,7 @@ yyreduce: ...@@ -3333,7 +3333,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type)) if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type)) if (context->nonInitConstErrorCheck((yyvsp[(3) - (3)].lex).line, *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false))
context->recover(); context->recover();
TVariable* variable = 0; TVariable* variable = 0;
...@@ -3350,7 +3350,7 @@ yyreduce: ...@@ -3350,7 +3350,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type)) if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type)) if (context->nonInitConstErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true))
context->recover(); context->recover();
(yyval.interm) = (yyvsp[(1) - (5)].interm); (yyval.interm) = (yyvsp[(1) - (5)].interm);
...@@ -3372,7 +3372,7 @@ yyreduce: ...@@ -3372,7 +3372,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type)) if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type)) if (context->nonInitConstErrorCheck((yyvsp[(3) - (6)].lex).line, *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true))
context->recover(); context->recover();
(yyval.interm) = (yyvsp[(1) - (6)].interm); (yyval.interm) = (yyvsp[(1) - (6)].interm);
...@@ -3435,7 +3435,7 @@ yyreduce: ...@@ -3435,7 +3435,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type)) if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type)) if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
context->recover(); context->recover();
(yyval.interm).type = (yyvsp[(1) - (2)].interm.type); (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
...@@ -3474,7 +3474,7 @@ yyreduce: ...@@ -3474,7 +3474,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type))) if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
context->recover(); context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type))) if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
context->recover(); context->recover();
(yyval.interm).type = (yyvsp[(1) - (5)].interm.type); (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
......
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