From 5fde038b1a6b3c8b335cd5b380c3ee8d15403052 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Wed, 31 Mar 2021 13:11:49 -0400 Subject: Support for __LINE__ and __FILE__ in preprocessor (#1772) * #include an absolute path didn't work - because paths were taken to always be relative. * First pass support for __LINE__ and __FILE__. * Test include handling with __FILE__ Fix diagnostic compare when input is empty. * Fix some issues in preprocessor handling of special macros like __LINE__ Add a more complex test. * Use CONCAT2 in tests, because preprocessor doesn't quite get parameter expansion correct. * Make __FILE__ and __LINE__ behave more like Clang/Gcc. * A test for preprocessor bug. * Fix __LINE__ and __FILE__ in macro expansion, should be initiating location. * Fix some comments. * Small tidy up around builtin macros. * Small improvements for macro type names. Escape found paths. --- source/slang/slang.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'source/slang/slang.cpp') diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 93d7be310..bcc3d1c67 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -1186,7 +1186,7 @@ static ISlangWriter* _getDefaultWriter(WriterChannel chan) void EndToEndCompileRequest::setWriter(WriterChannel chan, ISlangWriter* writer) { // If the user passed in null, we will use the default writer on that channel - m_writers[int(chan)] = writer ? writer : _getDefaultWriter(chan); + m_writers->setWriter(SlangWriterChannel(chan), writer ? writer : _getDefaultWriter(chan)); // For diagnostic output, if the user passes in nullptr, we set on mSink.writer as that enables buffering on DiagnosticSink if (chan == WriterChannel::Diagnostic) @@ -1307,8 +1307,10 @@ CompileRequestBase::CompileRequestBase( FrontEndCompileRequest::FrontEndCompileRequest( Linkage* linkage, + StdWriters* writers, DiagnosticSink* sink) : CompileRequestBase(linkage, sink) + , m_writers(writers) { } @@ -1540,6 +1542,26 @@ static void _outputIncludesRec(SourceView* sourceView, Index depth, ViewInitiati } } +static void _outputPreprocessorTokens(const TokenList& toks, ISlangWriter* writer) +{ + if (writer == nullptr) + { + return; + } + + StringBuilder buf; + for (const auto& tok : toks) + { + buf << tok.getContent(); + // We'll separate tokens with space for now + buf.appendChar(' '); + } + + buf.appendChar('\n'); + + writer->write(buf.getBuffer(), buf.getLength()); +} + static void _outputIncludes(const List& sourceFiles, SourceManager* sourceManager, DiagnosticSink* sink) { // Set up the hierarchy to know how all the source views relate. This could be argued as overkill, but makes recursive @@ -1651,6 +1673,16 @@ void FrontEndCompileRequest::parseTranslationUnit( _outputIncludes(translationUnit->getSourceFiles(), getSink()->getSourceManager(), getSink()); } + if (outputPreprocessor) + { + if (m_writers) + { + _outputPreprocessorTokens(tokens, m_writers->getWriter(SLANG_WRITER_CHANNEL_STD_OUTPUT)); + } + // If we output the preprocessor output then we are done doing anything else + return; + } + parseSourceFile( astBuilder, translationUnit, @@ -1828,6 +1860,12 @@ SlangResult FrontEndCompileRequest::executeActionsInner() parseTranslationUnit(translationUnit.Ptr()); } + if (outputPreprocessor) + { + // If doing pre-processor output, then we are done + return SLANG_OK; + } + if (getSink()->getErrorCount() != 0) return SLANG_FAIL; @@ -1954,13 +1992,15 @@ void EndToEndCompileRequest::init() { m_sink.setSourceManager(m_linkage->getSourceManager()); + m_writers = new StdWriters; + // Set all the default writers for (int i = 0; i < int(WriterChannel::CountOf); ++i) { setWriter(WriterChannel(i), nullptr); } - m_frontEndReq = new FrontEndCompileRequest(getLinkage(), getSink()); + m_frontEndReq = new FrontEndCompileRequest(getLinkage(), m_writers, getSink()); m_backEndReq = new BackEndCompileRequest(getLinkage(), getSink()); } @@ -1999,6 +2039,11 @@ SlangResult EndToEndCompileRequest::executeActionsInner() SLANG_RETURN_ON_FAIL(getFrontEndReq()->executeActionsInner()); } + if (getFrontEndReq()->outputPreprocessor) + { + return SLANG_OK; + } + // If command line specifies to skip codegen, we exit here. // Note: this is a debugging option. // @@ -2288,7 +2333,7 @@ RefPtr Linkage::loadModule( SourceLoc const& srcLoc, DiagnosticSink* sink) { - RefPtr frontEndReq = new FrontEndCompileRequest(this, sink); + RefPtr frontEndReq = new FrontEndCompileRequest(this, nullptr, sink); RefPtr translationUnit = new TranslationUnitRequest(frontEndReq); translationUnit->compileRequest = frontEndReq; @@ -3674,6 +3719,7 @@ void Session::addBuiltinSource( DiagnosticSink sink(sourceManager, Lexer::sourceLocationLexer); RefPtr compileRequest = new FrontEndCompileRequest( m_builtinLinkage, + nullptr, &sink); compileRequest->m_isStandardLibraryCode = true; -- cgit v1.2.3