diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index 0333e5d01f87c5265d5bc640c9b49e4d57b89d29..7f4d7d06c350d37fce9096ad9a18c63ec60a8433 100644
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -3812,4 +3812,15 @@ const char* TIntermediate::getResourceName(TResourceType res)
 }
 
 
+// Access recorded named preprocessor-defines from the outside
+// ->	needs to take into account, that the outside may want to use the set
+//		even after the memory pool got released
+void TIntermediate::getAddDefines( std::unordered_set< std::string > &targetSet, const std::unordered_set< TString > &sourceSet ) const
+{
+	targetSet.reserve( targetSet.size() + sourceSet.size() );
+	for ( auto &i: sourceSet )
+		targetSet.emplace( i.c_str() );		// need to convert from TString (pool-allocated) to normal std::basic_string, so it may be used after the pool is released
+}
+
+
 } // end namespace glslang
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 17e076519282225cfb3e7b3edfb8ecb6ff159f07..28509e62493aadee573deb09cdc4f6ca6f431bb7 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -637,6 +637,11 @@ public:
     const char* const implicitThisName;
     const char* const implicitCounterName;
 
+	void insertAccessedNamedDefine( const char *defName ) { accessedNamedDefines.emplace( defName ); }
+	void insertDeclaredNamedDefine( const char *defName ) { declaredNamedDefines.emplace( defName ); }
+	void getAddAccessedNamedDefines( std::unordered_set< std::string > &targetSet ) const { getAddDefines( targetSet, accessedNamedDefines ); }
+	void getAddDeclaredNamedDefines( std::unordered_set< std::string > &targetSet ) const { getAddDefines( targetSet, declaredNamedDefines ); }
+
 protected:
     TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
     void error(TInfoSink& infoSink, const char*);
@@ -665,6 +670,7 @@ protected:
     std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
     bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
     static const char* getResourceName(TResourceType);
+	void getAddDefines( std::unordered_set< std::string > &targetSet, const std::unordered_set< TString > &sourceSet ) const;
 
     const EShLanguage language;  // stage, known at construction time
     EShSource source;            // source language, known a bit later
@@ -743,6 +749,9 @@ protected:
 
     bool needToLegalize;
 
+	// storage for (accessed/declared) "named defines"
+	std::unordered_set< TString > accessedNamedDefines, declaredNamedDefines;
+
 private:
     void operator=(TIntermediate&); // prevent assignments
 };
diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp
index 8048fa513d2837dc1bb9e4a47d76987f709774dd..b7560846274f5b82d80efba1be84b41f1f365768 100644
--- a/glslang/MachineIndependent/preprocessor/Pp.cpp
+++ b/glslang/MachineIndependent/preprocessor/Pp.cpp
@@ -102,7 +102,8 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
         parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", "");
         return token;
     }
-    if (ppToken->loc.string >= 0) {
+	bool inUserCode(ppToken->loc.string >= 0);
+    if (inUserCode) {
         // We are in user code; check for reserved name use:
         parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define");
     }
@@ -186,8 +187,11 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
             }
         }
         *existing = mac;
-    } else
-        addMacroDef(defAtom, mac);
+    } else {
+		addMacroDef(defAtom, mac);
+		if ( inUserCode && mac.args.empty() && mac.body.atEnd() )
+			parseContext.intermediate.insertDeclaredNamedDefine( atomStrings.getString( defAtom ) );
+	}
 
     return '\n';
 }
@@ -248,6 +252,8 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
             } else {
                 ifdepth++;
                 elsetracker++;
+				if ( nextAtom != PpAtomIf && scanToken( ppToken ) == PpAtomIdentifier )
+					parseContext.intermediate.insertAccessedNamedDefine( ppToken->name );
             }
         } else if (nextAtom == PpAtomEndif) {
             token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
@@ -420,7 +426,7 @@ int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, boo
 
                 return token;
             }
-
+            parseContext.intermediate.insertAccessedNamedDefine( ppToken->name );
             MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
             res = macro != nullptr ? !macro->undef : 0;
             token = scanToken(ppToken);
@@ -577,6 +583,7 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
         else
             parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", "");
     } else {
+        parseContext.intermediate.insertAccessedNamedDefine( ppToken->name );
         MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
         token = scanToken(ppToken);
         if (token != '\n') {