Index: flang/lib/Parser/preprocessor.cpp =================================================================== --- flang/lib/Parser/preprocessor.cpp +++ flang/lib/Parser/preprocessor.cpp @@ -416,6 +416,26 @@ return tokens; } +static std::string getFileName(const std::string &fileNamePath, + const TokenSequence &dir, Prescanner &prescanner, size_t tokenPosition) { + int offset = 0; + int numberOfSkippedCharacters = 0; + // skip outer quotation marks + if (fileNamePath.length() > 2 && fileNamePath[0] == '\"') { + if (fileNamePath[fileNamePath.length() - 1] != '\"') { + prescanner.Say( + dir.GetTokenProvenanceRange(tokenPosition), "missing '\"'"_err_en_US); + return std::string(); + } else { + offset = 1; + numberOfSkippedCharacters = 2; + } + } + + return fileNamePath.substr( + offset, fileNamePath.length() - numberOfSkippedCharacters); +} + void Preprocessor::Directive(const TokenSequence &dir, Prescanner &prescanner) { std::size_t tokens{dir.SizeInTokens()}; std::size_t j{dir.SkipBlanks(0)}; @@ -444,7 +464,36 @@ nameToken = dir.TokenAt(j); } if (dirName == "line") { - // #line is ignored + std::optional prependPath; + if (const auto *currentFile{allSources_.GetSourceFile(j)}) { + prependPath = DirectoryName(currentFile->path()); + } + std::string fileNamePath{dir.TokenAt(j).ToString()}; + std::string fileName = getFileName(fileNamePath, dir, prescanner, j); + if (fileName.empty()) + return; + std::string buf; + llvm::raw_string_ostream error{buf}; + // Read original file to get propper token localization + const SourceFile *originalFile{ + allSources_.Open(fileName, error, std::move(prependPath))}; + if (!originalFile) { + prescanner.Say(dir.GetTokenProvenanceRange(j), "line error %s"_err_en_US, + error.str()); + } else if (originalFile->bytes() > 0) { + ProvenanceRange fileRange{ + allSources_.AddIncludedFile(*originalFile, dir.GetProvenanceRange())}; + Prescanner{prescanner} + .set_encoding(originalFile->encoding()) + .Prescan(fileRange); + } + // Skip tokens from preprocessed file which are located in the original file + while (!prescanner.IsAtEnd()) { + if (!prescanner.IsNextLinePreprocessorDirective()) { + prescanner.NextLine(); + continue; + } + } } else if (dirName == "define") { if (nameToken.empty()) { prescanner.Say(dir.GetTokenProvenanceRange(j < tokens ? j : tokens - 1), Index: flang/test/Driver/save-temps-token-localization.f90 =================================================================== --- /dev/null +++ flang/test/Driver/save-temps-token-localization.f90 @@ -0,0 +1,16 @@ +! Ensure -save-temps flag does not have influence on error diagnostic + +!-------------------------- +! FLANG DRIVER (flang) +!-------------------------- +! RUN: not %flang -save-temps %s 2>&1 | FileCheck %s --check-prefix=WITH_SAVE_TEMPS + + +! WITH_SAVE_TEMPS: save-temps-token-localization.f90:14:3: error: No explicit type declared for 'ij' + +subroutine test + implicit none + integer :: i + ij=10 + print *,i +end subroutine