Added the needed 2 sets to TIntermediate, added accessor-functions, inserter functions. Implemented recording of such named defines inside the preprocessor parser.
}
+// 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
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*);
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
bool needToLegalize;
+ // storage for (accessed/declared) "named defines"
+ std::unordered_set< TString > accessedNamedDefines, declaredNamedDefines;
+
private:
void operator=(TIntermediate&); // prevent assignments
};
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");
}
}
}
*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';
}
} else {
ifdepth++;
elsetracker++;
+ if ( nextAtom != PpAtomIf && scanToken( ppToken ) == PpAtomIdentifier )
+ parseContext.intermediate.insertAccessedNamedDefine( ppToken->name );
}
} else if (nextAtom == PpAtomEndif) {
token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
return token;
}
-
+ parseContext.intermediate.insertAccessedNamedDefine( ppToken->name );
MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name));
res = macro != nullptr ? !macro->undef : 0;
token = scanToken(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') {