Output wrapping #line directives for included content.

Also changed the includer interface to let it return the actual
full path of the included file.
This commit is contained in:
Lei Zhang 2015-07-06 10:32:46 -04:00
parent 2b4ebbb1e1
commit 1eed969b2d
4 changed files with 35 additions and 20 deletions

View File

@ -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.

View File

@ -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.

View File

@ -83,6 +83,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <stdio.h>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@ -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", "");
}
}
}

View File

@ -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<bool, std::string> 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<std::string, std::string> 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<bool, std::string> include(const char* filename) const override
std::pair<std::string, std::string> include(const char* filename) const override
{
return std::make_pair<bool, std::string>(true, "#error unexpected include directive\n");
return std::make_pair<std::string, std::string>("", "unexpected include directive");
}
};