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,13 +1761,19 @@ 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)) {
 | 
			
		||||
        if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) {
 | 
			
		||||
            // struct_type IDENTIFIER
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            expected("{");
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // struct_declaration_list
 | 
			
		||||
    TTypeList* typeList;
 | 
			
		||||
@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user