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 MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 1285
#define BUILD_REVISION 1286
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -846,14 +846,26 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
//
// 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.
//
if (type.qualifier == EvqConst) {
type.qualifier = EvqTemporary;
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;
}
......
//
// 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
// found in the LICENSE file.
//
......@@ -97,7 +97,7 @@ struct TParseContext {
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool structQualifierErrorCheck(int line, const TPublicType& pType);
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 paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
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
// found in the LICENSE file.
//
......@@ -20,9 +20,16 @@
#include "common/angleutils.h"
//
// TType helper function needs a place to live.
//
TType::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();
}
}
//
// Recursively generate mangled names.
......@@ -92,6 +99,25 @@ void TType::computeDeepestStructNesting()
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.
//
......
//
// 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
// found in the LICENSE file.
//
......@@ -11,10 +11,12 @@
#include "compiler/Common.h"
#include "compiler/debug.h"
class TType;
struct TPublicType;
//
// Need to have association of line numbers to types in a list for building structs.
//
class TType;
struct TTypeLine {
TType* type;
int line;
......@@ -27,59 +29,14 @@ inline TTypeList* NewPoolTTypeList()
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*>::iterator TStructureMapIterator;
//
// Base class for things that have a type.
//
class TType {
class TType
{
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TType() {}
......@@ -88,16 +45,7 @@ public:
maxArraySize(0), arrayInformationType(0), structure(0), structureSize(0), deepestStructNesting(0), fieldName(0), mangled(0), typeName(0)
{
}
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();
}
}
explicit TType(const TPublicType &p);
TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
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)
......@@ -284,6 +232,8 @@ public:
// deepest field (nesting2.field1.position).
int getDeepestStructNesting() const { return deepestStructNesting; }
bool isStructureContainingArrays() const;
protected:
void buildMangledName(TString&);
int getStructSize() const;
......@@ -308,4 +258,61 @@ protected:
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_
......@@ -1200,7 +1200,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $$.type))
context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type))
if (context->nonInitConstErrorCheck($3.line, *$3.string, $$.type, false))
context->recover();
TVariable* variable = 0;
......@@ -1213,7 +1213,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
context->recover();
$$ = $1;
......@@ -1231,7 +1231,7 @@ init_declarator_list
if (context->structQualifierErrorCheck($3.line, $1.type))
context->recover();
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type))
if (context->nonInitConstErrorCheck($3.line, *$3.string, $1.type, true))
context->recover();
$$ = $1;
......@@ -1285,7 +1285,7 @@ single_declaration
if (context->structQualifierErrorCheck($2.line, $$.type))
context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type))
if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
context->recover();
$$.type = $1;
......@@ -1316,7 +1316,7 @@ single_declaration
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $1))
if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
context->recover();
$$.type = $1;
......
......@@ -3333,7 +3333,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (3)].lex).line, (yyval.interm).type))
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();
TVariable* variable = 0;
......@@ -3350,7 +3350,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm).type))
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();
(yyval.interm) = (yyvsp[(1) - (5)].interm);
......@@ -3372,7 +3372,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(3) - (6)].lex).line, (yyvsp[(1) - (6)].interm).type))
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();
(yyval.interm) = (yyvsp[(1) - (6)].interm);
......@@ -3435,7 +3435,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
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();
(yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
......@@ -3474,7 +3474,7 @@ yyreduce:
if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
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();
(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