mirror of
https://github.com/KhronosGroup/glslang
synced 2024-11-09 20:10:06 +00:00
HLSL: Fix #747: accept 'struct' in front of previously user-defined type name.
This commit is contained in:
parent
0479437a5c
commit
854fe24786
84
Test/baseResults/hlsl.structStructName.frag.out
Executable file
84
Test/baseResults/hlsl.structStructName.frag.out
Executable file
@ -0,0 +1,84 @@
|
||||
hlsl.structStructName.frag
|
||||
Shader version: 450
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:4 Function Definition: @main( (temp int)
|
||||
0:4 Function Parameters:
|
||||
0:? Sequence
|
||||
0:6 Branch: Return with expression
|
||||
0:6 s: direct index for structure (temp int)
|
||||
0:6 't' (temp structure{temp int s})
|
||||
0:6 Constant:
|
||||
0:6 0 (const int)
|
||||
0:4 Function Definition: main( (temp void)
|
||||
0:4 Function Parameters:
|
||||
0:? Sequence
|
||||
0:4 move second child to first child (temp int)
|
||||
0:? '@entryPointOutput' (layout(location=0 ) out int)
|
||||
0:4 Function Call: @main( (temp int)
|
||||
0:? Linker Objects
|
||||
0:? '@entryPointOutput' (layout(location=0 ) out int)
|
||||
|
||||
|
||||
Linked fragment stage:
|
||||
|
||||
|
||||
Shader version: 450
|
||||
gl_FragCoord origin is upper left
|
||||
0:? Sequence
|
||||
0:4 Function Definition: @main( (temp int)
|
||||
0:4 Function Parameters:
|
||||
0:? Sequence
|
||||
0:6 Branch: Return with expression
|
||||
0:6 s: direct index for structure (temp int)
|
||||
0:6 't' (temp structure{temp int s})
|
||||
0:6 Constant:
|
||||
0:6 0 (const int)
|
||||
0:4 Function Definition: main( (temp void)
|
||||
0:4 Function Parameters:
|
||||
0:? Sequence
|
||||
0:4 move second child to first child (temp int)
|
||||
0:? '@entryPointOutput' (layout(location=0 ) out int)
|
||||
0:4 Function Call: @main( (temp int)
|
||||
0:? Linker Objects
|
||||
0:? '@entryPointOutput' (layout(location=0 ) out int)
|
||||
|
||||
// Module Version 10000
|
||||
// Generated by (magic number): 80001
|
||||
// Id's are bound by 22
|
||||
|
||||
Capability Shader
|
||||
1: ExtInstImport "GLSL.std.450"
|
||||
MemoryModel Logical GLSL450
|
||||
EntryPoint Fragment 4 "main" 20
|
||||
ExecutionMode 4 OriginUpperLeft
|
||||
Name 4 "main"
|
||||
Name 8 "@main("
|
||||
Name 10 "S"
|
||||
MemberName 10(S) 0 "s"
|
||||
Name 12 "t"
|
||||
Name 20 "@entryPointOutput"
|
||||
Decorate 20(@entryPointOutput) Location 0
|
||||
2: TypeVoid
|
||||
3: TypeFunction 2
|
||||
6: TypeInt 32 1
|
||||
7: TypeFunction 6(int)
|
||||
10(S): TypeStruct 6(int)
|
||||
11: TypePointer Function 10(S)
|
||||
13: 6(int) Constant 0
|
||||
14: TypePointer Function 6(int)
|
||||
19: TypePointer Output 6(int)
|
||||
20(@entryPointOutput): 19(ptr) Variable Output
|
||||
4(main): 2 Function None 3
|
||||
5: Label
|
||||
21: 6(int) FunctionCall 8(@main()
|
||||
Store 20(@entryPointOutput) 21
|
||||
Return
|
||||
FunctionEnd
|
||||
8(@main(): 6(int) Function None 7
|
||||
9: Label
|
||||
12(t): 11(ptr) Variable Function
|
||||
15: 14(ptr) AccessChain 12(t) 13
|
||||
16: 6(int) Load 15
|
||||
ReturnValue 16
|
||||
FunctionEnd
|
7
Test/hlsl.structStructName.frag
Executable file
7
Test/hlsl.structStructName.frag
Executable file
@ -0,0 +1,7 @@
|
||||
struct S { int s; };
|
||||
|
||||
int main()
|
||||
{
|
||||
struct S t;
|
||||
return t.s;
|
||||
}
|
@ -2,5 +2,5 @@
|
||||
// For the version, it uses the latest git tag followed by the number of commits.
|
||||
// For the date, it uses the current date (when then script is run).
|
||||
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1870"
|
||||
#define GLSLANG_DATE "01-Mar-2017"
|
||||
#define GLSLANG_REVISION "Overload400-PrecQual.1871"
|
||||
#define GLSLANG_DATE "02-Mar-2017"
|
||||
|
@ -231,6 +231,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
{"hlsl.structbuffer.rwbyte.frag", "main"},
|
||||
{"hlsl.structin.vert", "main"},
|
||||
{"hlsl.structIoFourWay.frag", "main"},
|
||||
{"hlsl.structStructName.frag", "main"},
|
||||
{"hlsl.intrinsics.vert", "VertexShaderFunction"},
|
||||
{"hlsl.matType.frag", "PixelShaderFunction"},
|
||||
{"hlsl.matType.bool.frag", "main"},
|
||||
|
@ -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&);
|
||||
|
Loading…
Reference in New Issue
Block a user