HLSL: Fix #747: accept 'struct' in front of previously user-defined type name.
This commit is contained in:
@@ -1268,9 +1268,8 @@ bool HlslGrammar::acceptType(TType& type)
|
||||
// An identifier could be for a user-defined type.
|
||||
// Note we cache the symbol table lookup, to save for a later rule
|
||||
// when this is not a type.
|
||||
token.symbol = parseContext.symbolTable.find(*token.string);
|
||||
if (token.symbol && token.symbol->getAsVariable() && token.symbol->getAsVariable()->isUserType()) {
|
||||
type.shallowCopy(token.symbol->getType());
|
||||
token.symbol = parseContext.lookupUserType(*token.string, type);
|
||||
if (token.symbol != nullptr) {
|
||||
advanceToken();
|
||||
return true;
|
||||
} else
|
||||
@@ -1729,6 +1728,7 @@ bool HlslGrammar::acceptType(TType& type)
|
||||
// struct
|
||||
// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
|
||||
// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE
|
||||
// | struct_type IDENTIFIER // use of previously declared struct type
|
||||
//
|
||||
// struct_type
|
||||
// : STRUCT
|
||||
@@ -1761,12 +1761,18 @@ bool HlslGrammar::acceptStruct(TType& type)
|
||||
// post_decls
|
||||
TQualifier postDeclQualifier;
|
||||
postDeclQualifier.clear();
|
||||
acceptPostDecls(postDeclQualifier);
|
||||
bool postDeclsFound = acceptPostDecls(postDeclQualifier);
|
||||
|
||||
// LEFT_BRACE
|
||||
// struct_type IDENTIFIER
|
||||
if (! acceptTokenClass(EHTokLeftBrace)) {
|
||||
expected("{");
|
||||
return false;
|
||||
if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
|
||||
// struct_type IDENTIFIER
|
||||
return true;
|
||||
} else {
|
||||
expected("{");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// struct_declaration_list
|
||||
@@ -3274,11 +3280,18 @@ void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes)
|
||||
// COLON LAYOUT layout_qualifier_list
|
||||
// annotations // optional
|
||||
//
|
||||
void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
// Return true if any tokens were accepted. That is,
|
||||
// false can be returned on successfully recognizing nothing,
|
||||
// not necessarily meaning bad syntax.
|
||||
//
|
||||
bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
do {
|
||||
// COLON
|
||||
if (acceptTokenClass(EHTokColon)) {
|
||||
found = true;
|
||||
HlslToken idToken;
|
||||
if (peekTokenClass(EHTokLayout))
|
||||
acceptLayoutQualifierList(qualifier);
|
||||
@@ -3286,18 +3299,18 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
// PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN
|
||||
if (! acceptTokenClass(EHTokLeftParen)) {
|
||||
expected("(");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
HlslToken locationToken;
|
||||
if (! acceptIdentifier(locationToken)) {
|
||||
expected("c[subcomponent][.component]");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
HlslToken componentToken;
|
||||
if (acceptTokenClass(EHTokDot)) {
|
||||
if (! acceptIdentifier(componentToken)) {
|
||||
expected("component");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (! acceptTokenClass(EHTokRightParen)) {
|
||||
@@ -3307,19 +3320,19 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string);
|
||||
} else if (! acceptIdentifier(idToken)) {
|
||||
expected("layout, semantic, packoffset, or register");
|
||||
return;
|
||||
return false;
|
||||
} else if (*idToken.string == "register") {
|
||||
// REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN
|
||||
// LEFT_PAREN
|
||||
if (! acceptTokenClass(EHTokLeftParen)) {
|
||||
expected("(");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
HlslToken registerDesc; // for Type#
|
||||
HlslToken profile;
|
||||
if (! acceptIdentifier(registerDesc)) {
|
||||
expected("register number description");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) &&
|
||||
acceptTokenClass(EHTokComma)) {
|
||||
@@ -3328,7 +3341,7 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
profile = registerDesc;
|
||||
if (! acceptIdentifier(registerDesc)) {
|
||||
expected("register number description");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int subComponent = 0;
|
||||
@@ -3336,7 +3349,7 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
// LEFT_BRACKET subcomponent RIGHT_BRACKET
|
||||
if (! peekTokenClass(EHTokIntConstant)) {
|
||||
expected("literal integer");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
subComponent = token.i;
|
||||
advanceToken();
|
||||
@@ -3350,7 +3363,7 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
if (acceptTokenClass(EHTokComma)) {
|
||||
if (! acceptIdentifier(spaceDesc)) {
|
||||
expected ("space identifier");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// RIGHT_PAREN
|
||||
@@ -3363,12 +3376,15 @@ void HlslGrammar::acceptPostDecls(TQualifier& qualifier)
|
||||
// semantic, in idToken.string
|
||||
parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
|
||||
}
|
||||
} else if (peekTokenClass(EHTokLeftAngle))
|
||||
} else if (peekTokenClass(EHTokLeftAngle)) {
|
||||
found = true;
|
||||
acceptAnnotations(qualifier);
|
||||
else
|
||||
} else
|
||||
break;
|
||||
|
||||
} while (true);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
} // end namespace glslang
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace glslang {
|
||||
bool acceptCaseLabel(TIntermNode*&);
|
||||
bool acceptDefaultLabel(TIntermNode*&);
|
||||
void acceptArraySpecifier(TArraySizes*&);
|
||||
void acceptPostDecls(TQualifier&);
|
||||
bool acceptPostDecls(TQualifier&);
|
||||
bool acceptDefaultParameterDeclaration(const TType&, TIntermTyped*&);
|
||||
|
||||
HlslParseContext& parseContext; // state of parsing and helper functions for building the intermediate
|
||||
|
||||
@@ -6098,6 +6098,19 @@ void HlslParseContext::declareStruct(const TSourceLoc& loc, TString& structName,
|
||||
ioTypeMap[type.getStruct()] = newLists;
|
||||
}
|
||||
|
||||
// Lookup a user-type by name.
|
||||
// If found, fill in the type and return the defining symbol.
|
||||
// If not found, return nullptr.
|
||||
TSymbol* HlslParseContext::lookupUserType(const TString& typeName, TType& type)
|
||||
{
|
||||
TSymbol* symbol = symbolTable.find(typeName);
|
||||
if (symbol && symbol->getAsVariable() && symbol->getAsVariable()->isUserType()) {
|
||||
type.shallowCopy(symbol->getType());
|
||||
return symbol;
|
||||
} else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//
|
||||
// Do everything necessary to handle a variable (non-block) declaration.
|
||||
// Either redeclaring a variable, or making a new one, updating the symbol
|
||||
|
||||
@@ -133,6 +133,7 @@ public:
|
||||
const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args);
|
||||
void declareTypedef(const TSourceLoc&, TString& identifier, const TType&);
|
||||
void declareStruct(const TSourceLoc&, TString& structName, TType&);
|
||||
TSymbol* lookupUserType(const TString&, TType&);
|
||||
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0);
|
||||
void lengthenList(const TSourceLoc&, TIntermSequence& list, int size);
|
||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
|
||||
|
||||
Reference in New Issue
Block a user