diff --git a/Test/baseResults/preprocessor.include.disabled.vert.err b/Test/baseResults/preprocessor.include.disabled.vert.err index 85428de85..1145a3147 100644 --- a/Test/baseResults/preprocessor.include.disabled.vert.err +++ b/Test/baseResults/preprocessor.include.disabled.vert.err @@ -3,11 +3,11 @@ ERROR: 0:8000: '#include' : must be followed by a file designation ERROR: 0:8001: '#include' : required extension not requested: GL_GOOGLE_include_directive ERROR: 0:8001: '#include' : must be followed by a file designation ERROR: 0:8002: '#include' : required extension not requested: GL_GOOGLE_include_directive -ERROR: 0:8002: '#error' : unexpected include directive +ERROR: 0:8002: '#include' : unexpected include directive ERROR: 0:8003: '#include' : required extension not requested: GL_GOOGLE_include_directive ERROR: 0:8003: '#include' : extra content after file designation ERROR: 0:8004: '#include' : required extension not requested: GL_GOOGLE_include_directive -ERROR: 0:8004: '#error' : unexpected include directive +ERROR: 0:8004: '#include' : unexpected include directive ERROR: 10 compilation errors. No code generated. diff --git a/Test/baseResults/preprocessor.include.enabled.vert.err b/Test/baseResults/preprocessor.include.enabled.vert.err index edc9ba9d8..2cdf3f283 100644 --- a/Test/baseResults/preprocessor.include.enabled.vert.err +++ b/Test/baseResults/preprocessor.include.enabled.vert.err @@ -1,8 +1,8 @@ -ERROR: 0:8000: '#include' : must be followed by a file designation -ERROR: 0:8001: '#include' : must be followed by a file designation -ERROR: 0:8002: '#error' : unexpected include directive -ERROR: 0:8003: '#include' : extra content after file designation -ERROR: 0:8004: '#error' : unexpected include directive +ERROR: 0:8000: '#include' : must be followed by a file designation +ERROR: 0:8001: '#include' : must be followed by a file designation +ERROR: 0:8002: '#include' : unexpected include directive +ERROR: 0:8003: '#include' : extra content after file designation +ERROR: 0:8004: '#include' : unexpected include directive ERROR: 5 compilation errors. No code generated. diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index 8e58a8c23..2ec7e74c5 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -83,6 +83,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include #include @@ -605,23 +606,36 @@ int TPpContext::CPPinclude(TPpToken* ppToken) // TODO: handle angle brackets. parseContext.ppError(directiveLoc, "must be followed by a file designation", "#include", ""); } else { - const char* name = GetAtomString(ppToken->atom); + // Make a copy of the name because it will be overwritten by the next token scan. + const std::string filename = ppToken->name; token = scanToken(ppToken); if (token != '\n' && token != EndOfInput) { parseContext.ppError(ppToken->loc, "extra content after file designation", "#include", ""); } else { - if (!inputStack.empty()) ungetChar(); + std::string sourceName; std::string replacement; - bool success; - std::tie(success, replacement) = includer.include(name); - if (success) { - pushInput(new TokenizableString(directiveLoc, replacement, this)); + std::tie(sourceName, replacement) = includer.include(filename.c_str()); + if (!sourceName.empty()) { + if (!replacement.empty()) { + const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); + std::ostringstream content; + content << "#line " << forNextLine << " " << "\"" << sourceName << "\"\n"; + content << replacement << (replacement.back() == '\n' ? "" : "\n"); + content << "#line " << directiveLoc.line + forNextLine << " "; + if (directiveLoc.name != nullptr) { + content << "\"" << directiveLoc.name << "\""; + } else { + content << directiveLoc.string; + } + content << "\n"; + pushInput(new TokenizableString(directiveLoc, content.str(), this)); + } // At EOF, there's no "current" location anymore. if (token != EndOfInput) parseContext.setCurrentColumn(0); // Don't accidentally return EndOfInput, which will end all preprocessing. return '\n'; } else { - parseContext.ppError(ppToken->loc, "not found", name, ""); + parseContext.ppError(directiveLoc, replacement.c_str(), "#include", ""); } } } diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 7b12ad07c..3fbfe3547 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -293,17 +293,18 @@ public: // Interface to #include handlers. class Includer { public: - // On success, returns true and the content that replaces "#include - // filename". On failure, returns false and an arbitrary string. - virtual std::pair include(const char* filename) const = 0; + // On success, returns the full path and content of the file with the given + // filename that replaces "#include filename". On failure, returns an empty + // string and an error message. + virtual std::pair include(const char* filename) const = 0; }; - // Generates #error as #include content. + // Returns an error message for any #include directive. class ForbidInclude : public Includer { public: - std::pair include(const char* filename) const override + std::pair include(const char* filename) const override { - return std::make_pair(true, "#error unexpected include directive\n"); + return std::make_pair("", "unexpected include directive"); } };