diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 4ea961384..d133b5948 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -582,7 +582,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionOutputPreprocessed) { std::string str; - glslang::TShader::ForbidInclude includer; + glslang::TShader::ForbidIncluder includer; if (shader->preprocess(&Resources, defaultVersion, ENoProfile, false, false, messages, &str, includer)) { PutsIfNonEmpty(str.c_str()); diff --git a/Test/baseResults/preprocessor.include.disabled.vert.err b/Test/baseResults/preprocessor.include.disabled.vert.err index 836a3d674..14192046a 100644 --- a/Test/baseResults/preprocessor.include.disabled.vert.err +++ b/Test/baseResults/preprocessor.include.disabled.vert.err @@ -3,7 +3,7 @@ ERROR: 0:8000: '#include' : must be followed by a header name ERROR: 0:8001: '#include' : required extension not requested: GL_GOOGLE_include_directive ERROR: 0:8001: '#include' : must be followed by a header name ERROR: 0:8002: '#include' : required extension not requested: GL_GOOGLE_include_directive -ERROR: 0:8002: '#include' : unexpected include directive for header name: foo +ERROR: 0:8002: '#include' : Could not process include directive for header name: foo ERROR: 0:8003: '#include' : required extension not requested: GL_GOOGLE_include_directive ERROR: 0:8003: '#include' : extra content after header name: foo ERROR: 0:8004: '#include' : required extension not requested: GL_GOOGLE_include_directive diff --git a/Test/baseResults/preprocessor.include.enabled.vert.err b/Test/baseResults/preprocessor.include.enabled.vert.err index 0b0cbae1f..252e661f0 100644 --- a/Test/baseResults/preprocessor.include.enabled.vert.err +++ b/Test/baseResults/preprocessor.include.enabled.vert.err @@ -1,19 +1,19 @@ ERROR: 0:8000: '#include' : must be followed by a header name ERROR: 0:8001: '#include' : must be followed by a header name -ERROR: 0:8002: '#include' : unexpected include directive for header name: foo.oeu -ERROR: 0:8003: '#include' : unexpected include directive for header name: foo.oeu/ao eu/ao.h -ERROR: 0:8004: '#include' : unexpected include directive for header name: foo -ERROR: 0:8006: '#include' : unexpected include directive for header name: foo.oe -ERROR: 0:8007: '#include' : unexpected include directive for header name: foo"bar" -ERROR: 0:8008: '#include' : unexpected include directive for header name: foo\bar -ERROR: 0:8009: '#include' : unexpected include directive for header name: foo.oe> -ERROR: 0:8010: '#include' : unexpected include directive for header name: foo +ERROR: 0:8002: '#include' : Could not process include directive for header name: foo.oeu +ERROR: 0:8003: '#include' : Could not process include directive for header name: foo.oeu/ao eu/ao.h +ERROR: 0:8004: '#include' : Could not process include directive for header name: foo +ERROR: 0:8006: '#include' : Could not process include directive for header name: foo.oe +ERROR: 0:8007: '#include' : Could not process include directive for header name: foo"bar" +ERROR: 0:8008: '#include' : Could not process include directive for header name: foo\bar +ERROR: 0:8009: '#include' : Could not process include directive for header name: foo.oe> +ERROR: 0:8010: '#include' : Could not process include directive for header name: foo ERROR: 0:8011: '#include' : extra content after header name: foo2.h ERROR: 0:8012: '#include' : extra content after header name: foo.h -ERROR: 0:8014: '#include' : unexpected include directive for header name: ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 +ERROR: 0:8014: '#include' : Could not process include directive for header name: ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 ERROR: 0:8016: '' : header name too long -ERROR: 0:8016: '#include' : unexpected include directive for header name: ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 +ERROR: 0:8016: '#include' : Could not process include directive for header name: ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789 ERROR: 0:8017: '#include' : expected newline after header name: no-eol ERROR: 17 compilation errors. No code generated. diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 6abf1f3b0..852dd2e51 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.1747" +#define GLSLANG_REVISION "Overload400-PrecQual.1750" #define GLSLANG_DATE "06-Jan-2017" diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index e552d1a42..469ae1e69 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -232,7 +232,7 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil language, infoSink, spvVersion, true, EShMsgDefault, true)); - TShader::ForbidInclude includer; + TShader::ForbidIncluder includer; TPpContext ppContext(*parseContext, "", includer); TScanContext scanContext(*parseContext); parseContext->setScanContext(&scanContext); @@ -1232,7 +1232,7 @@ int ShCompile( compiler->infoSink.debug.erase(); TIntermediate intermediate(compiler->getLanguage()); - TShader::ForbidInclude includer; + TShader::ForbidIncluder includer; bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, "", optLevel, resources, defaultVersion, ENoProfile, false, forwardCompatible, messages, intermediate, includer); diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index de1b83bb2..49c78ef88 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -576,12 +576,12 @@ int TPpContext::CPPifdef(int defined, TPpToken* ppToken) int TPpContext::CPPinclude(TPpToken* ppToken) { const TSourceLoc directiveLoc = ppToken->loc; - TShader::Includer::IncludeType includeType = TShader::Includer::EIncludeRelative; + bool startWithLocalSearch = true; // to additionally include the extra "" paths int token = scanToken(ppToken); // handle -style #include if (token == '<') { - includeType = TShader::Includer::EIncludeStandard; + startWithLocalSearch = false; token = scanHeaderName(ppToken, '>'); } // otherwise ppToken already has the header name and it was "header-name" style @@ -605,16 +605,26 @@ int TPpContext::CPPinclude(TPpToken* ppToken) } // Process well-formed directive - TShader::Includer::IncludeResult* res = includer.include(filename.c_str(), includeType, currentSourceFile.c_str(), - includeStack.size() + 1); - if (res && !res->file_name.empty()) { - if (res->file_data && res->file_length) { + + // Find the inclusion, first look in "Local" ("") paths, if requested, + // otherwise, only search the "System" (<>) paths. + TShader::Includer::IncludeResult* res = nullptr; + if (startWithLocalSearch) + res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); + if (! res || res->headerName.empty()) { + includer.releaseInclude(res); + res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); + } + + // Process the results + if (res && !res->headerName.empty()) { + if (res->headerData && res->headerLength) { // path for processing one or more tokens from an included header, hand off 'res' const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); std::ostringstream prologue; std::ostringstream epilogue; - prologue << "#line " << forNextLine << " " << "\"" << res->file_name << "\"\n"; - epilogue << (res->file_data[res->file_length - 1] == '\n'? "" : "\n") << + prologue << "#line " << forNextLine << " " << "\"" << res->headerName << "\"\n"; + epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") << "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); // There's no "current" location anymore. @@ -626,7 +636,7 @@ int TPpContext::CPPinclude(TPpToken* ppToken) } else { // error path, clean up std::string message = - res ? std::string(res->file_data, res->file_length) + res ? std::string(res->headerData, res->headerLength) : std::string("Could not process include directive"); parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str()); includer.releaseInclude(res); diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index a766d917c..15e54b79f 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -507,11 +507,11 @@ protected: stringInput(pp, scanner) { strings[0] = prologue_.data(); - strings[1] = includedFile_->file_data; + strings[1] = includedFile_->headerData; strings[2] = epilogue_.data(); lengths[0] = prologue_.size(); - lengths[1] = includedFile_->file_length; + lengths[1] = includedFile_->headerLength; lengths[2] = epilogue_.size(); scanner.setLine(startLoc.line); @@ -552,7 +552,7 @@ protected: // Points to the IncludeResult that this TokenizableIncludeFile represents. TShader::Includer::IncludeResult* includedFile_; - // Will point to prologue_, includedFile_->file_data and epilogue_ + // Will point to prologue_, includedFile_->headerData and epilogue_ // This is passed to scanner constructor. // These do not own the storage and it must remain valid until this // object has been destroyed. @@ -576,7 +576,7 @@ protected: void push_include(TShader::Includer::IncludeResult* result) { - currentSourceFile = result->file_name; + currentSourceFile = result->headerName; includeStack.push(result); } @@ -588,7 +588,7 @@ protected: if (includeStack.empty()) { currentSourceFile = rootFileName; } else { - currentSourceFile = includeStack.top()->file_name; + currentSourceFile = includeStack.top()->headerName; } } diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 944bc0e47..60e539b4a 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -331,72 +331,76 @@ public: // release the IncludeResult object. class Includer { public: - typedef enum { - EIncludeRelative, // For #include "something" - EIncludeStandard // Reserved. For #include - } IncludeType; - // An IncludeResult contains the resolved name and content of a source // inclusion. struct IncludeResult { - IncludeResult(const std::string& file_name, const char* const file_data, const size_t file_length, void* user_data) : - file_name(file_name), file_data(file_data), file_length(file_length), user_data(user_data) { } + IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : + headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } // For a successful inclusion, the fully resolved name of the requested // include. For example, in a file system-based includer, full resolution // should convert a relative path name into an absolute path name. // For a failed inclusion, this is an empty string. - const std::string file_name; + const std::string headerName; // The content and byte length of the requested inclusion. The // Includer producing this IncludeResult retains ownership of the // storage. - // For a failed inclusion, the file_data + // For a failed inclusion, the header // field points to a string containing error details. - const char* const file_data; - const size_t file_length; + const char* const headerData; + const size_t headerLength; // Include resolver's context. - void* user_data; + void* userData; protected: IncludeResult& operator=(const IncludeResult&); IncludeResult(); }; - // Resolves an inclusion request by name, type, current source name, + // For both include methods below: + // + // Resolves an inclusion request by name, current source name, // and include depth. // On success, returns an IncludeResult containing the resolved name - // and content of the include. On failure, returns an IncludeResult - // with an empty string for the file_name and error details in the - // file_data field. The Includer retains ownership of the contents + // and content of the include. + // On failure, returns a nullptr, or an IncludeResult + // with an empty string for the headerName and error details in the + // header field. + // The Includer retains ownership of the contents // of the returned IncludeResult value, and those contents must // remain valid until the releaseInclude method is called on that // IncludeResult object. - virtual IncludeResult* include(const char* requested_source, - IncludeType type, - const char* requesting_source, - size_t inclusion_depth) = 0; + // + // Note "local" vs. "system" is not an "either/or": "local" is an + // extra thing to do over "system". Both might get called, as per + // the C++ specification. + + // For the "system" or <>-style includes; search the "system" paths. + virtual IncludeResult* includeSystem(const char* headerName, + const char* includerName, + size_t inclusionDepth) { return nullptr; } + + // For the "local"-only aspect of a "" include. Should not search in the + // "system" paths, because on returning a failure, the parser will + // call includeSystem() to look in the "system" locations. + virtual IncludeResult* includeLocal(const char* headerName, + const char* includerName, + size_t inclusionDepth) { return nullptr; } + // Signals that the parser will no longer use the contents of the // specified IncludeResult. - virtual void releaseInclude(IncludeResult* result) = 0; + virtual void releaseInclude(IncludeResult*) = 0; virtual ~Includer() {} }; - // Returns an error message for any #include directive. - class ForbidInclude : public Includer { + // Fail all Includer searches + class ForbidIncluder : public Includer { public: - IncludeResult* include(const char*, IncludeType, const char*, size_t) override - { - const char* unexpected_include = "unexpected include directive"; - return new IncludeResult(std::string(""), unexpected_include, strlen(unexpected_include), nullptr); - } - virtual void releaseInclude(IncludeResult* result) override - { - delete result; - } + virtual void releaseInclude(IncludeResult*) override { } }; bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages) { - TShader::ForbidInclude includer; + TShader::ForbidIncluder includer; return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); } diff --git a/gtests/TestFixture.h b/gtests/TestFixture.h index e795e8dc9..6f4afc661 100644 --- a/gtests/TestFixture.h +++ b/gtests/TestFixture.h @@ -521,7 +521,7 @@ public: glslang::TShader shader(EShLangVertex); shader.setStringsWithLengths(&shaderStrings, &shaderLengths, 1); std::string ppShader; - glslang::TShader::ForbidInclude includer; + glslang::TShader::ForbidIncluder includer; const bool success = shader.preprocess( &glslang::DefaultTBuiltInResource, defaultVersion, defaultProfile, forceVersionProfile, isForwardCompatible, (EShMessages)(EShMsgOnlyPreprocessor | EShMsgCascadingErrors),