[libclang] Add entry points that take a full command line including argv[0].

This provides both a more uniform interface and makes libclang behave like
clang tooling wrt relative paths against argv[0]. This is necessary for
finding paths to a c++ standard library relative to a clang binary given
in a compilation database. It can also be used to find paths relative to
libclang.so if the full path to it is passed in.

Differential Revision: http://reviews.llvm.org/D14695

llvm-svn: 253466
This commit is contained in:
Benjamin Kramer 2015-11-18 16:14:27 +00:00
parent 4ba4816b97
commit c02670ed50
7 changed files with 93 additions and 17 deletions

View File

@ -1288,6 +1288,17 @@ clang_parseTranslationUnit2(CXIndex CIdx,
unsigned options,
CXTranslationUnit *out_TU);
/**
* \brief Same as clang_parseTranslationUnit2 but requires a full command line
* for \c command_line_args including argv[0]. This is useful if the standard
* library paths are relative to the binary.
*/
CINDEX_LINKAGE enum CXErrorCode clang_parseTranslationUnit2FullArgv(
CXIndex CIdx, const char *source_filename,
const char *const *command_line_args, int num_command_line_args,
struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
unsigned options, CXTranslationUnit *out_TU);
/**
* \brief Flags that control how translation units are saved.
*
@ -5680,6 +5691,18 @@ CINDEX_LINKAGE int clang_indexSourceFile(CXIndexAction,
CXTranslationUnit *out_TU,
unsigned TU_options);
/**
* \brief Same as clang_indexSourceFile but requires a full command line
* for \c command_line_args including argv[0]. This is useful if the standard
* library paths are relative to the binary.
*/
CINDEX_LINKAGE int clang_indexSourceFileFullArgv(
CXIndexAction, CXClientData client_data, IndexerCallbacks *index_callbacks,
unsigned index_callbacks_size, unsigned index_options,
const char *source_filename, const char *const *command_line_args,
int num_command_line_args, struct CXUnsavedFile *unsaved_files,
unsigned num_unsaved_files, CXTranslationUnit *out_TU, unsigned TU_options);
/**
* \brief Index the given translation unit via callbacks implemented through
* #IndexerCallbacks.

View File

@ -39,15 +39,13 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions);
}
SmallVector<const char *, 16> Args;
Args.push_back("<clang>"); // FIXME: Remove dummy argument.
Args.insert(Args.end(), ArgList.begin(), ArgList.end());
SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end());
// FIXME: Find a cleaner way to force the driver into restricted modes.
Args.push_back("-fsyntax-only");
// FIXME: We shouldn't have to pass in the path info.
driver::Driver TheDriver("clang", llvm::sys::getDefaultTargetTriple(),
driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(),
*Diags);
// Don't check that inputs exist, they may have been remapped.

View File

@ -64,9 +64,11 @@ createDiagnostics(unsigned int argc, char **argv) {
new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
// Try to build a CompilerInvocation.
SmallVector<const char *, 4> Args;
Args.push_back("diagtool");
Args.append(argv, argv + argc);
std::unique_ptr<CompilerInvocation> Invocation(
createInvocationFromCommandLine(llvm::makeArrayRef(argv, argc),
InterimDiags));
createInvocationFromCommandLine(Args, InterimDiags));
if (!Invocation)
return nullptr;

View File

@ -3089,12 +3089,12 @@ clang_parseTranslationUnit_Impl(CXIndex CIdx, const char *source_filename,
break;
}
}
if (!FoundSpellCheckingArgument)
Args->push_back("-fno-spell-checking");
Args->insert(Args->end(), command_line_args,
command_line_args + num_command_line_args);
if (!FoundSpellCheckingArgument)
Args->insert(Args->begin() + 1, "-fno-spell-checking");
// The 'source_filename' argument is optional. If the caller does not
// specify it then it is assumed that the source file is specified
// in the actual argument list.
@ -3157,14 +3157,23 @@ clang_parseTranslationUnit(CXIndex CIdx,
}
enum CXErrorCode clang_parseTranslationUnit2(
CXIndex CIdx,
const char *source_filename,
const char *const *command_line_args,
int num_command_line_args,
struct CXUnsavedFile *unsaved_files,
unsigned num_unsaved_files,
unsigned options,
CXTranslationUnit *out_TU) {
CXIndex CIdx, const char *source_filename,
const char *const *command_line_args, int num_command_line_args,
struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
unsigned options, CXTranslationUnit *out_TU) {
SmallVector<const char *, 4> Args;
Args.push_back("clang");
Args.append(command_line_args, command_line_args + num_command_line_args);
return clang_parseTranslationUnit2FullArgv(
CIdx, source_filename, Args.data(), Args.size(), unsaved_files,
num_unsaved_files, options, out_TU);
}
enum CXErrorCode clang_parseTranslationUnit2FullArgv(
CXIndex CIdx, const char *source_filename,
const char *const *command_line_args, int num_command_line_args,
struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
unsigned options, CXTranslationUnit *out_TU) {
LOG_FUNC_SECTION {
*Log << source_filename << ": ";
for (int i = 0; i != num_command_line_args; ++i)

View File

@ -907,6 +907,22 @@ int clang_indexSourceFile(CXIndexAction idxAction,
unsigned num_unsaved_files,
CXTranslationUnit *out_TU,
unsigned TU_options) {
SmallVector<const char *, 4> Args;
Args.push_back("clang");
Args.append(command_line_args, command_line_args + num_command_line_args);
return clang_indexSourceFileFullArgv(
idxAction, client_data, index_callbacks, index_callbacks_size,
index_options, source_filename, Args.data(), Args.size(), unsaved_files,
num_unsaved_files, out_TU, TU_options);
}
int clang_indexSourceFileFullArgv(
CXIndexAction idxAction, CXClientData client_data,
IndexerCallbacks *index_callbacks, unsigned index_callbacks_size,
unsigned index_options, const char *source_filename,
const char *const *command_line_args, int num_command_line_args,
struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files,
CXTranslationUnit *out_TU, unsigned TU_options) {
LOG_FUNC_SECTION {
*Log << source_filename << ": ";
for (int i = 0; i != num_command_line_args; ++i)

View File

@ -249,6 +249,7 @@ clang_hashCursor
clang_indexLoc_getCXSourceLocation
clang_indexLoc_getFileLocation
clang_indexSourceFile
clang_indexSourceFileFullArgv
clang_indexTranslationUnit
clang_index_getCXXClassDeclInfo
clang_index_getClientContainer
@ -284,6 +285,7 @@ clang_Location_isInSystemHeader
clang_Location_isFromMainFile
clang_parseTranslationUnit
clang_parseTranslationUnit2
clang_parseTranslationUnit2FullArgv
clang_remap_dispose
clang_remap_getFilenames
clang_remap_getNumFiles

View File

@ -379,8 +379,10 @@ public:
Filename = Path.str();
Files.insert(Filename);
}
llvm::sys::fs::create_directories(llvm::sys::path::parent_path(Filename));
std::ofstream OS(Filename);
OS << Contents;
assert(OS.good());
}
void DisplayDiagnostics() {
unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
@ -465,3 +467,27 @@ TEST_F(LibclangReparseTest, ReparseWithModule) {
ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
}
TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
std::string EmptyFiles[] = {"lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",
"include/arm-linux-gnueabi/.keep",
"include/c++/4.6.1/vector"};
for (auto &Name : EmptyFiles)
WriteFile(Name, "\n");
std::string Filename = "test.cc";
WriteFile(Filename, "#include <vector>\n");
std::string Clang = "bin/clang";
WriteFile(Clang, "");
const char *Argv[] = {Clang.c_str(), "-target", "arm-linux-gnueabi"};
EXPECT_EQ(CXError_Success,
clang_parseTranslationUnit2FullArgv(Index, Filename.c_str(), Argv,
sizeof(Argv) / sizeof(Argv[0]),
nullptr, 0, TUFlags, &ClangTU));
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
DisplayDiagnostics();
}