From e7350423067442f616431c1cdf4f18dd7990a491 Mon Sep 17 00:00:00 2001
From: St0fF <st0ff.npl@gmail.com>
Date: Mon, 9 Apr 2018 19:28:45 +0200
Subject: [PATCH] add ability to record accessed and declared "named defines"

Added the needed 2 sets to TIntermediate, added accessor-functions, inserter functions.  Implemented recording of such named defines inside the preprocessor parser.
---
 glslang/MachineIndependent/Intermediate.cpp    | 11 +++++++++++
 glslang/MachineIndependent/localintermediate.h |  9 +++++++++
 glslang/MachineIndependent/preprocessor/Pp.cpp | 15 +++++++++++----
 3 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index 0333e5d01..7f4d7d06c 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 17e076519..28509e624 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 8048fa513..b75608462 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') {
-- 
GitLab