diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 45a16896e1053e6ae18c08179c7e6109bd6cfd85..01f3a9f264a1b4928b78d630237564a3cce72996 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -44,7 +44,7 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
                              bool fc, EShMessages m) : 
             intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
             numErrors(0), lexAfterType(false), loopNestingLevel(0),
-            inTypeParen(false),
+            structNestingLevel(0), inTypeParen(false),
             version(v), profile(p), forwardCompatible(fc), messages(m),
             contextPragma(true, false)
 {
@@ -1072,6 +1072,20 @@ void TParseContext::paramCheck(int line, TStorageQualifier qualifier, TType* typ
     }
 }
 
+void TParseContext::nestedBlockCheck(int line)
+{
+    if (structNestingLevel > 0)
+        error(line, "cannot nest a block definition inside a structure or block", "", "");
+    ++structNestingLevel;
+}
+
+void TParseContext::nestedStructCheck(int line)
+{
+    if (structNestingLevel > 0)
+        error(line, "cannot nest a structure definition inside a structure or block", "", "");
+    ++structNestingLevel;
+}
+
 //
 // Layout qualifier stuff.
 //
@@ -1449,26 +1463,26 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
 //
 // Do everything needed to add an interface block.
 //
-void TParseContext::addBlock(int line, TPublicType& publicType, const TString& blockName, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
+void TParseContext::addBlock(int line, TTypeList& typeList, const TString* instanceName, TArraySizes arraySizes)
 {
     // First, error checks
 
-    if (reservedErrorCheck(line, blockName))
+    if (reservedErrorCheck(line, *blockName))
         return;
 
     if (instanceName && reservedErrorCheck(line, *instanceName))
         return;
 
-    if (publicType.basicType != EbtVoid) {
-        error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
+    if (blockType.basicType != EbtVoid) {
+        error(line, "interface blocks cannot be declared with a type", blockName->c_str(), "");
 
         return;
     }
-    if (publicType.qualifier.storage == EvqUniform) {
+    if (blockType.qualifier.storage == EvqUniform) {
         requireProfile(line, (EProfileMask)(~ENoProfileMask), "uniform block");
         profileRequires(line, EEsProfile, 300, 0, "uniform block");
     } else {
-        error(line, "only uniform interface blocks are supported", blockName.c_str(), "");
+        error(line, "only uniform interface blocks are supported", blockName->c_str(), "");
 
         return;
     }
@@ -1476,9 +1490,9 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
     // check for qualifiers and types that don't belong within a block
     for (unsigned int member = 0; member < typeList.size(); ++member) {
         TQualifier memberQualifier = typeList[member].type->getQualifier();
-        if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != publicType.qualifier.storage)
+        if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != blockType.qualifier.storage)
             error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
-        if (publicType.qualifier.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
+        if (blockType.qualifier.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
             error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
 
         TBasicType basicType = typeList[member].type->getBasicType();
@@ -1489,7 +1503,7 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
     // Make default block qualification, and adjust the member qualifications
 
     TQualifier defaultQualification = defaultGlobalQualification;
-    mergeLayoutQualifiers(line, defaultQualification, publicType.qualifier);
+    mergeLayoutQualifiers(line, defaultQualification, blockType.qualifier);
     for (unsigned int member = 0; member < typeList.size(); ++member) {
         TQualifier memberQualification = defaultQualification;
         mergeLayoutQualifiers(line, memberQualification, typeList[member].type->getQualifier());
@@ -1498,13 +1512,13 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
 
     // Build and add the interface block as a new type named blockName
 
-    TType blockType(&typeList, blockName, publicType.qualifier.storage);
+    TType blockType(&typeList, *blockName, blockType.qualifier.storage);
     if (arraySizes)
         blockType.setArraySizes(arraySizes);
     blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking;
-    TVariable* userTypeDef = new TVariable(&blockName, blockType, true);
+    TVariable* userTypeDef = new TVariable(blockName, blockType, true);
     if (! symbolTable.insert(*userTypeDef)) {
-        error(line, "redefinition", blockName.c_str(), "block name");
+        error(line, "redefinition", blockName->c_str(), "block name");
 
         return;
     }
@@ -1518,7 +1532,7 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
     TVariable* variable = new TVariable(instanceName, blockType);
     if (! symbolTable.insert(*variable)) {
         if (*instanceName == "")
-            error(line, "nameless block contains a member that already has a name at global scope", blockName.c_str(), "");
+            error(line, "nameless block contains a member that already has a name at global scope", blockName->c_str(), "");
         else
             error(line, "block instance name redefinition", variable->getName().c_str(), "");
 
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index b5370a57b8a88cb8f151536850c0bdccce24a91d..e776a4adf14961ad6cc488033977f43b66a21a0f 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -77,6 +77,7 @@ struct TParseContext {
     int numErrors;               // number of compile-time errors encountered
     bool lexAfterType;           // true if we've recognized a type, so can only be looking for an identifier
     int loopNestingLevel;        // 0 if outside all loops
+    int structNestingLevel;      // 0 if outside blocks and structures
     TList<TIntermSequence*> switchSequenceStack;  // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
     bool inTypeParen;            // true if in parentheses, looking only for an identifier
     const TType* currentFunctionType;  // the return type of the function that's currently being parsed
@@ -93,6 +94,8 @@ struct TParseContext {
     TQualifier defaultGlobalQualification;
 	TString HashErrMsg;
     bool AfterEOF;
+    const TString* blockName;
+    TPublicType blockType;
 
     void initializeExtensionBehavior();
     const char* getPreamble();
@@ -130,6 +133,8 @@ struct TParseContext {
     void nonInitConstCheck(int line, TString& identifier, TPublicType& type);
     void nonInitCheck(int line, TString& identifier, TPublicType& type);
     void paramCheck(int line, TStorageQualifier qualifier, TType* type);
+    void nestedBlockCheck(int line);
+    void nestedStructCheck(int line);
 
     void setLayoutQualifier(int line, TPublicType&, TString&);
     void setLayoutQualifier(int line, TPublicType&, TString&, int);
@@ -141,7 +146,7 @@ struct TParseContext {
     TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
     TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
-    void addBlock(int line, TPublicType& qualifier, const TString& blockName, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
+    void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
     TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
     void updateDefaults(int line, const TPublicType&, const TString* id);
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index 12e6ab92405fa4f33ded19c89642b0e115b5fd69..0dc84055ff15302d5219ccf9f55e344046d9e6bb 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -208,6 +208,7 @@ extern void yyerror(const char*);
 %type <interm.type> struct_specifier
 %type <interm.typeLine> struct_declarator
 %type <interm.typeList> struct_declarator_list struct_declaration struct_declaration_list type_name_list
+%type <interm> block_structure
 %type <interm.function> function_header function_declarator
 %type <interm.function> function_header_with_parameters
 %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
@@ -1102,16 +1103,16 @@ declaration
 		parseContext.setDefaultPrecision($1.line, $3, $2.qualifier.precision);
         $$ = 0;
     }
-    | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE SEMICOLON {
-        parseContext.addBlock($2.line, $1, *$2.string, *$4);
+    | block_structure SEMICOLON {
+        parseContext.addBlock($1.line, *$1.typeList);
         $$ = 0;
     }
-    | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
-        parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string);
+    | block_structure IDENTIFIER SEMICOLON {
+        parseContext.addBlock($1.line, *$1.typeList, $2.string);
         $$ = 0;
     }
-    | type_qualifier IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE IDENTIFIER array_specifier SEMICOLON {
-        parseContext.addBlock($2.line, $1, *$2.string, *$4, $6.string, $7.arraySizes);
+    | block_structure IDENTIFIER array_specifier SEMICOLON {
+        parseContext.addBlock($1.line, *$1.typeList, $2.string, $3.arraySizes);
         $$ = 0;
     }
     | type_qualifier SEMICOLON {
@@ -1130,6 +1131,15 @@ declaration
     }
     ;
 
+block_structure
+    : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.line); } struct_declaration_list RIGHT_BRACE {
+        --parseContext.structNestingLevel;
+        parseContext.blockName = $2.string;
+        parseContext.blockType = $1;
+        $$.line = $1.line;
+        $$.typeList = $5;
+    }
+
 identifier_list
     : COMMA IDENTIFIER {
     }
@@ -2397,25 +2407,22 @@ precision_qualifier
     ;
 
 struct_specifier
-    : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
-        // TODO: semantics: check for qualifiers that don't belong in a struct
-
-        // TODO: semantics: check that this is not nested inside a block or structure
-        //     parseContext.error($1.line, "cannot nest a block or structure definitions", $1.userDef->getTypeName().c_str(), "");
-
-        TType* structure = new TType($4, *$2.string);
+    : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.line); } struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($5, *$2.string);
         TVariable* userTypeDef = new TVariable($2.string, *structure, true);
         if (! parseContext.symbolTable.insert(*userTypeDef))
             parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
         $$.init($1.line);
         $$.basicType = EbtStruct;
         $$.userDef = structure;
+        --parseContext.structNestingLevel;
     }
-    | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE {
-        TType* structure = new TType($3, TString(""));
+    | STRUCT LEFT_BRACE { parseContext.nestedStructCheck($1.line); } struct_declaration_list RIGHT_BRACE {
+        TType* structure = new TType($4, TString(""));
         $$.init($1.line);
         $$.basicType = EbtStruct;
         $$.userDef = structure;
+        --parseContext.structNestingLevel;
     }
     ;