Author: david2050 Date: Tue Jan 24 19:55:28 2017 New Revision: 293004 URL: http://llvm.org/viewvc/llvm-project?rev=293004&view=rev Log: Use filename in linemarker when compiling preprocessed source
Summary: Clang appears to always use name as specified on the command line, whereas gcc uses the name as specified in the linemarker at the first line when compiling a preprocessed source. This results mismatch between two compilers in FILE symbol table entry. This patch makes clang to resemble gcc's behavior in finding the original source file name and use it as an input file name. Even with this patch, values of FILE symbol table entry may still be different because clang uses dirname+basename for the entry whlie gcc uses basename only. I'll write a patch for that once this patch is committed. Reviewers: dblaikie, inglorion Reviewed By: inglorion Subscribers: inglorion, aprantl, bruno Differential Revision: https://reviews.llvm.org/D28796 Added: cfe/trunk/test/Frontend/preprocessed-input.c Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h cfe/trunk/lib/Frontend/FrontendAction.cpp Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=293004&r1=293003&r2=293004&view=diff ============================================================================== --- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original) +++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Tue Jan 24 19:55:28 2017 @@ -81,7 +81,7 @@ enum InputKind { IK_LLVM_IR }; - + /// \brief An input file for the front end. class FrontendInputFile { /// \brief The file name, or "-" to read from standard input. @@ -109,6 +109,13 @@ public: bool isEmpty() const { return File.empty() && Buffer == nullptr; } bool isFile() const { return !isBuffer(); } bool isBuffer() const { return Buffer != nullptr; } + bool isPreprocessed() const { + return Kind == IK_PreprocessedC || + Kind == IK_PreprocessedCXX || + Kind == IK_PreprocessedObjC || + Kind == IK_PreprocessedObjCXX || + Kind == IK_PreprocessedCuda; + } StringRef getFile() const { assert(isFile()); Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=293004&r1=293003&r2=293004&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/FrontendAction.cpp (original) +++ cfe/trunk/lib/Frontend/FrontendAction.cpp Tue Jan 24 19:55:28 2017 @@ -19,6 +19,7 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/ParseAST.h" @@ -187,6 +188,42 @@ FrontendAction::CreateWrappedASTConsumer return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } +// For preprocessed files, if the first line is the linemarker and specifies +// the original source file name, use that name as the input file name. +static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) +{ + bool Invalid = false; + auto &SourceMgr = CI.getSourceManager(); + auto MainFileID = SourceMgr.getMainFileID(); + const auto *MainFileBuf = SourceMgr.getBuffer(MainFileID, &Invalid); + if (Invalid) + return false; + + std::unique_ptr<Lexer> RawLexer( + new Lexer(MainFileID, MainFileBuf, SourceMgr, CI.getLangOpts())); + + // If the first line has the syntax of + // + // # NUM "FILENAME" + // + // we use FILENAME as the input file name. + Token T; + if (RawLexer->LexFromRawLexer(T) || T.getKind() != tok::hash) + return false; + if (RawLexer->LexFromRawLexer(T) || T.isAtStartOfLine() || + T.getKind() != tok::numeric_constant) + return false; + RawLexer->LexFromRawLexer(T); + if (T.isAtStartOfLine() || T.getKind() != tok::string_literal) + return false; + + StringLiteralParser Literal(T, CI.getPreprocessor()); + if (Literal.hadError) + return false; + InputFile = Literal.GetString().str(); + return true; +} + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -335,6 +372,13 @@ bool FrontendAction::BeginSourceFile(Com if (!isModelParsingAction()) CI.createASTContext(); + // For preprocessed files, check if the first line specifies the original + // source file name with a linemarker. + std::string OrigFile; + if (Input.isPreprocessed()) + if (ReadOriginalFileName(CI, OrigFile)) + InputFile = OrigFile; + std::unique_ptr<ASTConsumer> Consumer = CreateWrappedASTConsumer(CI, InputFile); if (!Consumer) @@ -421,9 +465,9 @@ bool FrontendAction::BeginSourceFile(Com // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. - if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && + if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { - IntrusiveRefCntPtr<ExternalASTSource> + IntrusiveRefCntPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); Added: cfe/trunk/test/Frontend/preprocessed-input.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/preprocessed-input.c?rev=293004&view=auto ============================================================================== --- cfe/trunk/test/Frontend/preprocessed-input.c (added) +++ cfe/trunk/test/Frontend/preprocessed-input.c Tue Jan 24 19:55:28 2017 @@ -0,0 +1,4 @@ +// RUN: %clang -E -o %t.i %s +// RUN: %clang -Xclang -triple -Xclang i686-linux-gnu -c -o %t.o %t.i +// RUN: llvm-objdump -t %t.o | FileCheck %s +// CHECK: l{{ +}}df{{ +}}*ABS*{{ +}}{{0+}}{{.+}}preprocessed-input.c{{$}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits