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 llvm-svn: 293004
This commit is contained in:
parent
86f9e46365
commit
ae7e0da4f8
|
@ -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());
|
||||
|
|
|
@ -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(CompilerInstance &CI,
|
|||
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(CompilerInstance &CI,
|
|||
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)
|
||||
|
|
|
@ -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{{$}}
|
Loading…
Reference in New Issue