Track whether function declarations are prototypes, and only allow at most one prototype for ES 100.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24342 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-12-04 19:43:05 +00:00
parent e1f0f5b31f
commit b88c60b03f
13 changed files with 101 additions and 25 deletions

View file

@ -9,5 +9,5 @@
// source have to figure out how to create revision.h just to get a build
// going. However, if it is not updated, it can be a version behind.
#define GLSLANG_REVISION "24330"
#define GLSLANG_DATE "2013/12/04 09:43:00"
#define GLSLANG_REVISION "24331"
#define GLSLANG_DATE "2013/12/04 10:23:03"

View file

@ -671,19 +671,20 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
// Handle seeing a function declarator in the grammar. This is the precursor
// to recognizing a function prototype or function definition.
//
TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& function)
TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype)
{
// ES can't declare prototypes inside functions
if (! symbolTable.atGlobalLevel())
requireProfile(loc, ~EEsProfile, "local function declaration");
//
// Multiple declarations of the same function are allowed.
// Multiple declarations of the same function name are allowed.
//
// If this is a definition, the definition production code will check for redefinitions
// (we don't know at this point if it's a definition or not).
//
// Redeclarations (full prototype match) are allowed. But, return types and parameter qualifiers must match.
// Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match.
// - except ES 100, which only allows a single prototype
//
// ES 100 does not allow redefining, but does allow overloading of built-in functions.
// ES 300 does not allow redefining or overloading of built-in functions.
@ -694,9 +695,10 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu
requireProfile(loc, ~EEsProfile, "redefinition of built-in function");
const TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
if (prevDec) {
if (prevDec->getType() != function.getType()) {
if (prevDec->isPrototyped() && prototype)
profileRequires(loc, EEsProfile, 300, 0, "multiple prototypes for same function");
if (prevDec->getType() != function.getType())
error(loc, "overloaded functions must have the same return type", function.getType().getBasicTypeString().c_str(), "");
}
for (int i = 0; i < prevDec->getParamCount(); ++i) {
if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage)
error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1);
@ -708,16 +710,26 @@ TFunction* TParseContext::handleFunctionDeclarator(TSourceLoc loc, TFunction& fu
arrayObjectCheck(loc, function.getType(), "array in function return type");
// All built-in functions are defined, even though they don't have a body.
if (symbolTable.atBuiltInLevel())
function.setDefined();
if (prototype) {
// All built-in functions are defined, even though they don't have a body.
// Count their prototype as a definition instead.
if (symbolTable.atBuiltInLevel())
function.setDefined();
else {
if (prevDec && ! builtIn)
symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const
function.setPrototyped();
}
}
// This insert won't actually insert it if it's a duplicate signature, but it will still check for
// other forms of name collisions.
if (! symbolTable.insert(function))
error(loc, "redeclaration of existing name", function.getName().c_str(), "");
error(loc, "function name is redeclaration of existing name", function.getName().c_str(), "");
//
// If this is a redeclaration, it could also be a definition,
// in which case, we want to use the variable names from this one, and not the one that's
// in which case, we need to use the parameter names from this one, and not the one that's
// being redeclared. So, pass back this declaration, not the one in the symbol table.
//
return &function;

View file

@ -88,7 +88,7 @@ public:
void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function);
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*, TIntermAggregate*);
void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&);

View file

@ -286,6 +286,7 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
mangledName = copyOf.mangledName;
op = copyOf.op;
defined = copyOf.defined;
prototyped = copyOf.prototyped;
}
TFunction* TFunction::clone() const

View file

@ -194,12 +194,12 @@ public:
explicit TFunction(TOperator o) :
TSymbol(0),
op(o),
defined(false) { }
defined(false), prototyped(false) { }
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
TSymbol(name),
mangledName(*name + '('),
op(tOp),
defined(false) { returnType.shallowCopy(retType); }
defined(false), prototyped(false) { returnType.shallowCopy(retType); }
virtual TFunction* clone() const;
virtual ~TFunction();
@ -220,6 +220,8 @@ public:
virtual TOperator getBuiltInOp() const { return op; }
virtual void setDefined() { assert(writable); defined = true; }
virtual bool isDefined() const { return defined; }
virtual void setPrototyped() { assert(writable); prototyped = true; }
virtual bool isPrototyped() const { return prototyped; }
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
@ -237,6 +239,7 @@ protected:
TString mangledName;
TOperator op;
bool defined;
bool prototyped;
};
class TAnonMember : public TSymbol {

View file

@ -748,6 +748,7 @@ constant_expression
declaration
: function_prototype SEMICOLON {
parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */);
$$ = 0;
// TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
}
@ -820,7 +821,7 @@ identifier_list
function_prototype
: function_declarator RIGHT_PAREN {
$$.function = parseContext.handleFunctionDeclarator($2.loc, *$1);
$$.function = $1;
$$.loc = $2.loc;
}
;
@ -2389,6 +2390,7 @@ external_declaration
function_definition
: function_prototype {
$1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
$1.intermAggregate = parseContext.handleFunctionDefinition($1.loc, *$1.function);
}
compound_statement_no_new_scope {