diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index e4ff5c62..eaae2ce6 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -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.1920" -#define GLSLANG_DATE "16-Mar-2017" +#define GLSLANG_REVISION "Overload400-PrecQual.1921" +#define GLSLANG_DATE "19-Mar-2017" diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index ff4a3945..035b0fd0 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -145,6 +145,8 @@ public: virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); + const char* const scopeMangler = "::"; + protected: TParseContextBase(TParseContextBase&); TParseContextBase& operator=(TParseContextBase&); diff --git a/hlsl/hlslAttributes.h b/hlsl/hlslAttributes.h index e093760c..ad44d2ab 100644 --- a/hlsl/hlslAttributes.h +++ b/hlsl/hlslAttributes.h @@ -95,9 +95,11 @@ namespace glslang { class TFunctionDeclarator { public: + TFunctionDeclarator() : function(nullptr), body(nullptr) { } TSourceLoc loc; TFunction* function; TAttributeMap attributes; + TVector* body; }; } // end namespace glslang diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 1dc500bb..be58dbc0 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -1788,7 +1788,7 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) postDeclQualifier.clear(); bool postDeclsFound = acceptPostDecls(postDeclQualifier); - // LEFT_BRACE + // LEFT_BRACE, or // struct_type IDENTIFIER if (! acceptTokenClass(EHTokLeftBrace)) { if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) { @@ -1800,9 +1800,17 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) } } + // struct_declaration_list TTypeList* typeList; - if (! acceptStructDeclarationList(typeList, nodeList, structName)) { + // Save each member function so they can be processed after we have a fully formed 'this'. + TVector functionDeclarators; + + parseContext.pushNamespace(structName); + bool acceptedList = acceptStructDeclarationList(typeList, nodeList, structName, functionDeclarators); + parseContext.popNamespace(); + + if (! acceptedList) { expected("struct member declarations"); return false; } @@ -1823,7 +1831,20 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) parseContext.declareStruct(token.loc, structName, type); - return true; + // All member functions get parsed inside the class/struct namespace and with the + // class/struct members in a symbol-table level. + parseContext.pushNamespace(structName); + bool deferredSuccess = true; + for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) { + // parse body + pushTokenStream(functionDeclarators[b].body); + if (! acceptFunctionBody(functionDeclarators[b], nodeList)) + deferredSuccess = false; + popTokenStream(); + } + parseContext.popNamespace(); + + return deferredSuccess; } // struct_buffer @@ -1934,16 +1955,12 @@ bool HlslGrammar::acceptStructBufferType(TType& type) // | IDENTIFIER array_specifier post_decls // | IDENTIFIER function_parameters post_decls // member-function prototype // -bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, const TString& typeName) +bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, const TString& typeName, + TVector& declarators) { typeList = new TTypeList(); HlslToken idToken; - // Save these away for each member function so they can be processed after - // all member variables/types have been declared. - TVector*> memberBodies; - TVector declarators; - do { // success on seeing the RIGHT_BRACE coming up if (peekTokenClass(EHTokRightBrace)) @@ -1973,11 +1990,8 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode* if (!declarator_list) { declarators.resize(declarators.size() + 1); // request a token stream for deferred processing - TVector* deferredTokens = new TVector; - functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, typeName, memberType, - *idToken.string, declarators.back(), - deferredTokens); - memberBodies.push_back(deferredTokens); + functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string, + declarators.back()); if (functionDefinitionAccepted) break; } @@ -2030,14 +2044,6 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode* } while (true); - // parse member-function bodies now - for (int b = 0; b < (int)memberBodies.size(); ++b) { - pushTokenStream(memberBodies[b]); - if (! acceptFunctionBody(declarators[b], nodeList)) - return false; - popTokenStream(); - } - return true; } @@ -2046,15 +2052,12 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode* // // Expects type to have EvqGlobal for a static member and // EvqTemporary for non-static member. -bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName, - const TType& type, const TString& memberName, - TFunctionDeclarator& declarator, TVector* deferredTokens) +bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, const TString& memberName, + TFunctionDeclarator& declarator) { - // watch early returns... - parseContext.pushThis(typeName); bool accepted = false; - TString* functionName = parseContext.getFullMemberFunctionName(memberName, type.getQualifier().storage == EvqGlobal); + TString* functionName = parseContext.getFullNamespaceName(memberName); declarator.function = new TFunction(functionName, type); // function_parameters @@ -2070,12 +2073,12 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T } declarator.loc = token.loc; - accepted = acceptFunctionDefinition(declarator, nodeList, deferredTokens); + declarator.body = new TVector; + accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body); } } else expected("function parameter list"); - parseContext.popThis(); return accepted; } @@ -2781,13 +2784,8 @@ bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, T functionName = callToken.string; else { functionName = NewPoolTString(""); - if (baseObject != nullptr) { - functionName->append(baseObject->getType().getTypeName().c_str()); - functionName->append("."); - } else if (baseType != nullptr) { - functionName->append(baseType->getType().getTypeName()); - functionName->append("::"); - } + functionName->append(baseType->getType().getTypeName()); + parseContext.addScopeMangler(*functionName); functionName->append(*callToken.string); } @@ -2795,7 +2793,6 @@ bool HlslGrammar::acceptFunctionCall(HlslToken callToken, TIntermTyped*& node, T TFunction* function = new TFunction(functionName, TType(EbtVoid)); // arguments - // Non-static member functions have an implicit first argument of the base object. TIntermTyped* arguments = nullptr; if (baseObject != nullptr) parseContext.handleFunctionArgument(function, arguments, baseObject); diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index e95fab0d..968364fa 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -87,10 +87,10 @@ namespace glslang { bool acceptTextureType(TType&); bool acceptStructBufferType(TType&); bool acceptStruct(TType&, TIntermNode*& nodeList); - bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, const TString& typeName); - bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TString& typeName, - const TType&, const TString& memberName, TFunctionDeclarator&, - TVector* deferredTokens); + bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, const TString& typeName, + TVector&); + bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType&, const TString& memberName, + TFunctionDeclarator&); bool acceptFunctionParameters(TFunction&); bool acceptParameterDeclaration(TFunction&); bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector* deferredTokens); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 34cf5d37..f30acbed 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -7085,7 +7085,7 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex return switchNode; } -// Track levels of class/struct nesting with a prefix string using +// Track levels of class/struct/namespace nesting with a prefix string using // the type names separated by the scoping operator. E.g., two levels // would look like: // @@ -7093,41 +7093,43 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex // // The string is empty when at normal global level. // -void HlslParseContext::pushThis(const TString& typeName) +void HlslParseContext::pushNamespace(const TString& typeName) { // make new type prefix TString newPrefix; if (currentTypePrefix.size() > 0) { newPrefix = currentTypePrefix.back(); - newPrefix.append("::"); + newPrefix.append(scopeMangler); } newPrefix.append(typeName); currentTypePrefix.push_back(newPrefix); } -// Opposite of pushThis(), see above -void HlslParseContext::popThis() +// Opposite of pushNamespace(), see above +void HlslParseContext::popNamespace() { currentTypePrefix.pop_back(); } // Use the class/struct nesting string to create a global name for -// a member of a class/struct. Static members use "::" for the final -// step, while non-static members use ".". -TString* HlslParseContext::getFullMemberFunctionName(const TString& memberName, bool isStatic) const +// a member of a class/struct. +TString* HlslParseContext::getFullNamespaceName(const TString& localName) const { TString* name = NewPoolTString(""); if (currentTypePrefix.size() > 0) name->append(currentTypePrefix.back()); - if (isStatic) - name->append("::"); - else - name->append("."); - name->append(memberName); + name->append(scopeMangler); + name->append(localName); return name; } +// Helper function to add the namespace scope mangling syntax to a string. +void HlslParseContext::addScopeMangler(TString& name) +{ + name.append(scopeMangler); +} + // Potentially rename shader entry point function void HlslParseContext::renameShaderFunction(TString*& name) const { diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 602bb86a..904ec0f8 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -160,9 +160,10 @@ public: void pushScope() { symbolTable.push(); } void popScope() { symbolTable.pop(0); } - void pushThis(const TString& name); - void popThis(); - TString* getFullMemberFunctionName(const TString& name, bool isStatic) const; + void pushNamespace(const TString& name); + void popNamespace(); + TString* getFullNamespaceName(const TString& localName) const; + void addScopeMangler(TString&); void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } void popSwitchSequence() { switchSequenceStack.pop_back(); }