r201249 - libclang: report error code for bad PCH files
Dmitri Gribenko
gribozavr at gmail.com
Wed Feb 12 11:12:37 PST 2014
Author: gribozavr
Date: Wed Feb 12 13:12:37 2014
New Revision: 201249
URL: http://llvm.org/viewvc/llvm-project?rev=201249&view=rev
Log:
libclang: report error code for bad PCH files
This commit improves libclang to report the error condition when
CXTranslationUnit can not be created because of a stale PCH file. This allows
the caller, for example, to rebuild the PCH file and retry the request.
There two are APIs in libclang that return a CXTranslationUnit and don't
support reporting detailed errors (the only error condition is a NULL result).
For these APIs, a second, superior, version is introduced --
clang_createTranslationUnit2 and clang_parseTranslationUnit2. These functions
return a CXTranslationUnit indirectly and also return an error code. Old
functions are still supported and are nothing more than convenience wrappers
that ignore extended error codes.
As a cleanup, this commit also categorizes some libclang errors in the
functions I had to modify anyway.
Added:
cfe/trunk/test/Index/pch-depending-on-deleted-module.c
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
cfe/trunk/test/Modules/fatal-module-loader-error.m
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CXTranslationUnit.h
cfe/trunk/tools/libclang/Indexing.cpp
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Wed Feb 12 13:12:37 2014
@@ -30,7 +30,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 22
+#define CINDEX_VERSION_MINOR 23
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -73,6 +73,43 @@ extern "C" {
*/
/**
+ * \brief Error codes returned by libclang routines.
+ *
+ * Zero (\c CXError_Success) is the only error code indicating success. Other
+ * error codes, including not yet assigned non-zero values, indicate errors.
+ */
+enum CXErrorCode {
+ /**
+ * \brief No error.
+ */
+ CXError_Success = 0,
+
+ /**
+ * \brief A generic error code, no further details are available.
+ *
+ * Errors of this kind can get their own specific error codes in future
+ * libclang versions.
+ */
+ CXError_Failure = 1,
+
+ /**
+ * \brief libclang crashed while performing the requested operation.
+ */
+ CXError_Crashed = 2,
+
+ /**
+ * \brief The function detected that the arguments violate the function
+ * contract.
+ */
+ CXError_InvalidArguments = 3,
+
+ /**
+ * \brief An AST deserialization error has occurred.
+ */
+ CXError_ASTReadError = 4
+};
+
+/**
* \brief An "index" that consists of a set of translation units that would
* typically be linked together into an executable or library.
*/
@@ -1076,10 +1113,27 @@ CINDEX_LINKAGE CXTranslationUnit clang_c
struct CXUnsavedFile *unsaved_files);
/**
- * \brief Create a translation unit from an AST file (-emit-ast).
+ * \brief Same as \c clang_createTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(
+ CXIndex CIdx,
+ const char *ast_filename);
+
+/**
+ * \brief Create a translation unit from an AST file (\c -emit-ast).
+ *
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit.
+ *
+ * \returns Zero on success, otherwise returns an error code.
*/
-CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
- const char *ast_filename);
+CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2(
+ CXIndex CIdx,
+ const char *ast_filename,
+ CXTranslationUnit *out_TU);
/**
* \brief Flags that control the creation of translation units.
@@ -1193,7 +1247,22 @@ enum CXTranslationUnit_Flags {
* set of optimizations enabled may change from one version to the next.
*/
CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
-
+
+/**
+ * \brief Same as \c clang_parseTranslationUnit2, but returns
+ * the \c CXTranslationUnit instead of an error code. In case of an error this
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed
+ * error codes.
+ */
+CINDEX_LINKAGE CXTranslationUnit
+clang_parseTranslationUnit(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);
+
/**
* \brief Parse the given source file and the translation unit corresponding
* to that file.
@@ -1208,7 +1277,7 @@ CINDEX_LINKAGE unsigned clang_defaultEdi
* associated.
*
* \param source_filename The name of the source file to load, or NULL if the
- * source file is included in \p command_line_args.
+ * source file is included in \c command_line_args.
*
* \param command_line_args The command-line arguments that would be
* passed to the \c clang executable if it were being invoked out-of-process.
@@ -1217,7 +1286,7 @@ CINDEX_LINKAGE unsigned clang_defaultEdi
* '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.
*
* \param num_command_line_args The number of command-line arguments in
- * \p command_line_args.
+ * \c command_line_args.
*
* \param unsaved_files the files that have not yet been saved to disk
* but may be required for parsing, including the contents of
@@ -1232,18 +1301,22 @@ CINDEX_LINKAGE unsigned clang_defaultEdi
* is managed but not its compilation. This should be a bitwise OR of the
* CXTranslationUnit_XXX flags.
*
- * \returns A new translation unit describing the parsed code and containing
- * any diagnostics produced by the compiler. If there is a failure from which
- * the compiler cannot recover, returns NULL.
- */
-CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(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);
-
+ * \param[out] out_TU A non-NULL pointer to store the created
+ * \c CXTranslationUnit, describing the parsed code and containing any
+ * diagnostics produced by the compiler.
+ *
+ * \returns Zero on success, otherwise returns an error code.
+ */
+CINDEX_LINKAGE 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);
+
/**
* \brief Flags that control how translation units are saved.
*
@@ -1395,10 +1468,11 @@ CINDEX_LINKAGE unsigned clang_defaultRep
* The function \c clang_defaultReparseOptions() produces a default set of
* options recommended for most uses, based on the translation unit.
*
- * \returns 0 if the sources could be reparsed. A non-zero value will be
+ * \returns 0 if the sources could be reparsed. A non-zero error code will be
* returned if reparsing was impossible, such that the translation unit is
- * invalid. In such cases, the only valid call for \p TU is
- * \c clang_disposeTranslationUnit(TU).
+ * invalid. In such cases, the only valid call for \c TU is
+ * \c clang_disposeTranslationUnit(TU). The error codes returned by this
+ * routine are described by the \c CXErrorCode enum.
*/
CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
unsigned num_unsaved_files,
@@ -5789,11 +5863,12 @@ typedef enum {
* \param index_options A bitmask of options that affects how indexing is
* performed. This should be a bitwise OR of the CXIndexOpt_XXX flags.
*
- * \param out_TU [out] pointer to store a CXTranslationUnit that can be reused
- * after indexing is finished. Set to NULL if you do not require it.
+ * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be
+ * reused after indexing is finished. Set to \c NULL if you do not require it.
*
- * \returns If there is a failure from which the there is no recovery, returns
- * non-zero, otherwise returns 0.
+ * \returns 0 on success or if there were errors from which the compiler could
+ * recover. If there is a failure from which the there is no recovery, returns
+ * a non-zero \c CXErrorCode.
*
* The rest of the parameters are the same as #clang_parseTranslationUnit.
*/
Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Wed Feb 12 13:12:37 2014
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
let Component = "Serialization" in {
+let CategoryName = "AST Deserialization Issue" in {
def err_fe_unable_to_read_pch_file : Error<
"unable to read PCH file %0: '%1'">;
@@ -78,4 +79,6 @@ def note_module_odr_violation_no_possibl
def note_module_odr_violation_possible_decl : Note<
"declaration of %0 does not match">;
-}
+} // let CategoryName
+} // let Component
+
Added: cfe/trunk/test/Index/pch-depending-on-deleted-module.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/pch-depending-on-deleted-module.c?rev=201249&view=auto
==============================================================================
--- cfe/trunk/test/Index/pch-depending-on-deleted-module.c (added)
+++ cfe/trunk/test/Index/pch-depending-on-deleted-module.c Wed Feb 12 13:12:37 2014
@@ -0,0 +1,14 @@
+#include "a.h"
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+
+// RUN: %clang_cc1 -x c-header -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -emit-pch -I %S/Inputs/Headers -o %t/use_LibA.pch %s
+// RUN: %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -verify-pch %t/use_LibA.pch
+// RUN: rm -f %t/modules-cache/LibA.pcm
+// RUN: not %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=modules-cache -verify-pch %t/use_LibA.pch 2>&1 | FileCheck -check-prefix=VERIFY %s
+// RUN: not c-index-test -test-load-source all -x c -fmodules -fdisable-module-hash -fmodules-cache-path=modules-cache -include-pch %t/use_LibA.pch %s 2>&1 | FileCheck -check-prefix=INDEX %s
+
+// VERIFY: fatal error: malformed or corrupted AST file: 'Unable to load module
+// INDEX: {{^}}Failure: AST deserialization error occurred{{$}}
+
Modified: cfe/trunk/test/Modules/fatal-module-loader-error.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/fatal-module-loader-error.m?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/test/Modules/fatal-module-loader-error.m (original)
+++ cfe/trunk/test/Modules/fatal-module-loader-error.m Wed Feb 12 13:12:37 2014
@@ -23,4 +23,4 @@
// Also check that libclang does not create a PCH with such an error.
// RUN: not c-index-test -write-pch %t.pch -fmodules -fmodules-cache-path=%t \
// RUN: %s -Xclang -fdisable-module-hash -F %S/Inputs 2>&1 | FileCheck %s
-// CHECK: Unable to write PCH file
+// CHECK: {{^}}Failure: AST deserialization error occurred{{$}}
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Wed Feb 12 13:12:37 2014
@@ -79,8 +79,33 @@ static unsigned getDefaultParsingOptions
return options;
}
+/// \brief Returns 0 in case of success, non-zero in case of a failure.
static int checkForErrors(CXTranslationUnit TU);
+static void describeLibclangFailure(enum CXErrorCode Err) {
+ switch (Err) {
+ case CXError_Success:
+ fprintf(stderr, "Success\n");
+ return;
+
+ case CXError_Failure:
+ fprintf(stderr, "Failure (no details available)\n");
+ return;
+
+ case CXError_Crashed:
+ fprintf(stderr, "Failure: libclang crashed\n");
+ return;
+
+ case CXError_InvalidArguments:
+ fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n");
+ return;
+
+ case CXError_ASTReadError:
+ fprintf(stderr, "Failure: AST deserialization error occurred\n");
+ return;
+ }
+}
+
static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,
unsigned end_line, unsigned end_column) {
fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,
@@ -89,10 +114,11 @@ static void PrintExtent(FILE *out, unsig
static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,
CXTranslationUnit *TU) {
-
- *TU = clang_createTranslationUnit(Idx, file);
- if (!*TU) {
+ enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);
+ describeLibclangFailure(Err);
+ *TU = 0;
return 0;
}
return 1;
@@ -1420,8 +1446,9 @@ int perform_test_load_source(int argc, c
const char *CommentSchemaFile;
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
+ enum CXErrorCode Err;
int result;
-
+
Idx = clang_createIndex(/* excludeDeclsFromPCH */
(!strcmp(filter, "local") ||
!strcmp(filter, "local-display"))? 1 : 0,
@@ -1437,13 +1464,14 @@ int perform_test_load_source(int argc, c
return -1;
}
- TU = clang_parseTranslationUnit(Idx, 0,
- argv + num_unsaved_files,
- argc - num_unsaved_files,
- unsaved_files, num_unsaved_files,
- getDefaultParsingOptions());
- if (!TU) {
+ Err = clang_parseTranslationUnit2(Idx, 0,
+ argv + num_unsaved_files,
+ argc - num_unsaved_files,
+ unsaved_files, num_unsaved_files,
+ getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to load translation unit!\n");
+ describeLibclangFailure(Err);
free_remapped_files(unsaved_files, num_unsaved_files);
clang_disposeIndex(Idx);
return 1;
@@ -1464,6 +1492,7 @@ int perform_test_reparse_source(int argc
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
int compiler_arg_idx = 0;
+ enum CXErrorCode Err;
int result, i;
int trial;
int remap_after_trial = 0;
@@ -1489,12 +1518,13 @@ int perform_test_reparse_source(int argc
/* Load the initial translation unit -- we do this without honoring remapped
* files, so that we have a way to test results after changing the source. */
- TU = clang_parseTranslationUnit(Idx, 0,
- argv + compiler_arg_idx,
- argc - compiler_arg_idx,
- 0, 0, getDefaultParsingOptions());
- if (!TU) {
+ Err = clang_parseTranslationUnit2(Idx, 0,
+ argv + compiler_arg_idx,
+ argc - compiler_arg_idx,
+ 0, 0, getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to load translation unit!\n");
+ describeLibclangFailure(Err);
free_remapped_files(unsaved_files, num_unsaved_files);
clang_disposeIndex(Idx);
return 1;
@@ -1517,11 +1547,14 @@ int perform_test_reparse_source(int argc
return -1;
}
- if (clang_reparseTranslationUnit(TU,
- trial >= remap_after_trial ? num_unsaved_files : 0,
- trial >= remap_after_trial ? unsaved_files : 0,
- clang_defaultReparseOptions(TU))) {
+ Err = clang_reparseTranslationUnit(
+ TU,
+ trial >= remap_after_trial ? num_unsaved_files : 0,
+ trial >= remap_after_trial ? unsaved_files : 0,
+ clang_defaultReparseOptions(TU));
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to reparse translation unit!\n");
+ describeLibclangFailure(Err);
clang_disposeTranslationUnit(TU);
free_remapped_files(unsaved_files, num_unsaved_files);
clang_disposeIndex(Idx);
@@ -1943,7 +1976,8 @@ int perform_code_completion(int argc, co
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
CXCodeCompleteResults *results = 0;
- CXTranslationUnit TU = 0;
+ enum CXErrorCode Err;
+ CXTranslationUnit TU;
unsigned I, Repeats = 1;
unsigned completionOptions = clang_defaultCodeCompleteOptions();
@@ -1968,21 +2002,27 @@ int perform_code_completion(int argc, co
if (getenv("CINDEXTEST_EDITING"))
Repeats = 5;
-
- TU = clang_parseTranslationUnit(CIdx, 0,
- argv + num_unsaved_files + 2,
- argc - num_unsaved_files - 2,
- 0, 0, getDefaultParsingOptions());
- if (!TU) {
+
+ Err = clang_parseTranslationUnit2(CIdx, 0,
+ argv + num_unsaved_files + 2,
+ argc - num_unsaved_files - 2,
+ 0, 0, getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to load translation unit!\n");
+ describeLibclangFailure(Err);
return 1;
}
- if (clang_reparseTranslationUnit(TU, 0, 0, clang_defaultReparseOptions(TU))) {
+ Err = clang_reparseTranslationUnit(TU, 0, 0,
+ clang_defaultReparseOptions(TU));
+
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to reparse translation init!\n");
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
return 1;
}
-
+
for (I = 0; I != Repeats; ++I) {
results = clang_codeCompleteAt(TU, filename, line, column,
unsaved_files, num_unsaved_files,
@@ -2069,6 +2109,7 @@ static int inspect_cursor_at(int argc, c
int errorCode;
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
+ enum CXErrorCode Err;
CXTranslationUnit TU;
CXCursor Cursor;
CursorSourceLocation *Locations = 0;
@@ -2102,15 +2143,15 @@ static int inspect_cursor_at(int argc, c
/* Parse the translation unit. When we're testing clang_getCursor() after
reparsing, don't remap unsaved files until the second parse. */
CIdx = clang_createIndex(1, 1);
- TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumLocations,
- argc - num_unsaved_files - 2 - NumLocations,
- unsaved_files,
- Repeats > 1? 0 : num_unsaved_files,
- getDefaultParsingOptions());
-
- if (!TU) {
+ Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 1 + NumLocations,
+ argc - num_unsaved_files - 2 - NumLocations,
+ unsaved_files,
+ Repeats > 1? 0 : num_unsaved_files,
+ getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "unable to parse input\n");
+ describeLibclangFailure(Err);
return -1;
}
@@ -2118,11 +2159,14 @@ static int inspect_cursor_at(int argc, c
return -1;
for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1 &&
- clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU))) {
- clang_disposeTranslationUnit(TU);
- return 1;
+ if (Repeats > 1) {
+ Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU));
+ if (Err != CXError_Success) {
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
+ return 1;
+ }
}
if (checkForErrors(TU) != 0)
@@ -2235,6 +2279,7 @@ static int find_file_refs_at(int argc, c
int errorCode;
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
+ enum CXErrorCode Err;
CXTranslationUnit TU;
CXCursor Cursor;
CursorSourceLocation *Locations = 0;
@@ -2268,15 +2313,16 @@ static int find_file_refs_at(int argc, c
/* Parse the translation unit. When we're testing clang_getCursor() after
reparsing, don't remap unsaved files until the second parse. */
CIdx = clang_createIndex(1, 1);
- TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumLocations,
- argc - num_unsaved_files - 2 - NumLocations,
- unsaved_files,
- Repeats > 1? 0 : num_unsaved_files,
- getDefaultParsingOptions());
-
- if (!TU) {
+ Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 1 + NumLocations,
+ argc - num_unsaved_files - 2 - NumLocations,
+ unsaved_files,
+ Repeats > 1? 0 : num_unsaved_files,
+ getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "unable to parse input\n");
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
return -1;
}
@@ -2284,11 +2330,14 @@ static int find_file_refs_at(int argc, c
return -1;
for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1 &&
- clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU))) {
- clang_disposeTranslationUnit(TU);
- return 1;
+ if (Repeats > 1) {
+ Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU));
+ if (Err != CXError_Success) {
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
+ return 1;
+ }
}
if (checkForErrors(TU) != 0)
@@ -2339,6 +2388,7 @@ static int find_file_includes_in(int arg
CXIndex CIdx;
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
+ enum CXErrorCode Err;
CXTranslationUnit TU;
const char **Filenames = 0;
unsigned NumFilenames = 0;
@@ -2368,15 +2418,17 @@ static int find_file_includes_in(int arg
/* Parse the translation unit. When we're testing clang_getCursor() after
reparsing, don't remap unsaved files until the second parse. */
CIdx = clang_createIndex(1, 1);
- TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 1 + NumFilenames,
- argc - num_unsaved_files - 2 - NumFilenames,
- unsaved_files,
- Repeats > 1? 0 : num_unsaved_files,
- getDefaultParsingOptions());
+ Err = clang_parseTranslationUnit2(
+ CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 1 + NumFilenames,
+ argc - num_unsaved_files - 2 - NumFilenames,
+ unsaved_files,
+ Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU);
- if (!TU) {
+ if (Err != CXError_Success) {
fprintf(stderr, "unable to parse input\n");
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
return -1;
}
@@ -2384,11 +2436,14 @@ static int find_file_includes_in(int arg
return -1;
for (I = 0; I != Repeats; ++I) {
- if (Repeats > 1 &&
- clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU))) {
- clang_disposeTranslationUnit(TU);
- return 1;
+ if (Repeats > 1) {
+ Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU));
+ if (Err != CXError_Success) {
+ describeLibclangFailure(Err);
+ clang_disposeTranslationUnit(TU);
+ return 1;
+ }
}
if (checkForErrors(TU) != 0)
@@ -2933,6 +2988,9 @@ static int index_compile_args(int num_ar
&IndexCB,sizeof(IndexCB), index_opts,
0, args, num_args, 0, 0, 0,
getDefaultParsingOptions());
+ if (result != CXError_Success)
+ describeLibclangFailure(result);
+
if (index_data.fail_for_error)
result = -1;
@@ -3185,6 +3243,7 @@ int perform_token_annotation(int argc, c
CXFile file = 0;
CXCursor *cursors = 0;
CXSourceRangeList *skipped_ranges = 0;
+ enum CXErrorCode Err;
unsigned i;
input += strlen("-test-annotate-tokens=");
@@ -3198,14 +3257,15 @@ int perform_token_annotation(int argc, c
}
CIdx = clang_createIndex(0, 1);
- TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
- argv + num_unsaved_files + 2,
- argc - num_unsaved_files - 3,
- unsaved_files,
- num_unsaved_files,
- getDefaultParsingOptions());
- if (!TU) {
+ Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 2,
+ argc - num_unsaved_files - 3,
+ unsaved_files,
+ num_unsaved_files,
+ getDefaultParsingOptions(), &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "unable to parse input\n");
+ describeLibclangFailure(Err);
clang_disposeIndex(CIdx);
free(filename);
free_remapped_files(unsaved_files, num_unsaved_files);
@@ -3220,9 +3280,11 @@ int perform_token_annotation(int argc, c
if (getenv("CINDEXTEST_EDITING")) {
for (i = 0; i < 5; ++i) {
- if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
- clang_defaultReparseOptions(TU))) {
+ Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU));
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to reparse translation unit!\n");
+ describeLibclangFailure(Err);
errorCode = -1;
goto teardown;
}
@@ -3586,6 +3648,7 @@ int write_pch_file(const char *filename,
CXTranslationUnit TU;
struct CXUnsavedFile *unsaved_files = 0;
int num_unsaved_files = 0;
+ enum CXErrorCode Err;
int result = 0;
Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);
@@ -3594,18 +3657,19 @@ int write_pch_file(const char *filename,
clang_disposeIndex(Idx);
return -1;
}
-
- TU = clang_parseTranslationUnit(Idx, 0,
- argv + num_unsaved_files,
- argc - num_unsaved_files,
- unsaved_files,
- num_unsaved_files,
- CXTranslationUnit_Incomplete |
- CXTranslationUnit_DetailedPreprocessingRecord|
- CXTranslationUnit_ForSerialization);
- if (!TU) {
+
+ Err = clang_parseTranslationUnit2(
+ Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files,
+ unsaved_files, num_unsaved_files,
+ CXTranslationUnit_Incomplete |
+ CXTranslationUnit_DetailedPreprocessingRecord |
+ CXTranslationUnit_ForSerialization,
+ &TU);
+ if (Err != CXError_Success) {
fprintf(stderr, "Unable to load translation unit!\n");
+ describeLibclangFailure(Err);
free_remapped_files(unsaved_files, num_unsaved_files);
+ clang_disposeTranslationUnit(TU);
clang_disposeIndex(Idx);
return 1;
}
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Wed Feb 12 13:12:37 2014
@@ -25,6 +25,8 @@
#include "clang/AST/Attr.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticCategories.h"
+#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -34,6 +36,7 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
+#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -62,6 +65,7 @@ using namespace clang::cxindex;
CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *AU) {
if (!AU)
return 0;
+ assert(CIdx);
CXTranslationUnit D = new CXTranslationUnitImpl();
D->CIdx = CIdx;
D->TheASTUnit = AU;
@@ -72,6 +76,18 @@ CXTranslationUnit cxtu::MakeCXTranslatio
return D;
}
+bool cxtu::isASTReadError(ASTUnit *AU) {
+ for (ASTUnit::stored_diag_iterator D = AU->stored_diag_begin(),
+ DEnd = AU->stored_diag_end();
+ D != DEnd; ++D) {
+ if (D->getLevel() >= DiagnosticsEngine::Error &&
+ DiagnosticIDs::getCategoryNumberForDiag(D->getID()) ==
+ diag::DiagCat_AST_Deserialization_Issue)
+ return true;
+ }
+ return false;
+}
+
cxtu::CXTUOwner::~CXTUOwner() {
if (TU)
clang_disposeTranslationUnit(TU);
@@ -2589,11 +2605,22 @@ void clang_toggleCrashRecovery(unsigned
else
llvm::CrashRecoveryContext::Disable();
}
-
+
CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
const char *ast_filename) {
- if (!CIdx || !ast_filename)
- return 0;
+ CXTranslationUnit TU;
+ enum CXErrorCode Result =
+ clang_createTranslationUnit2(CIdx, ast_filename, &TU);
+ assert((TU && Result == CXError_Success) ||
+ (!TU && Result != CXError_Success));
+ return TU;
+}
+
+enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
+ const char *ast_filename,
+ CXTranslationUnit *out_TU) {
+ if (!CIdx || !ast_filename || !out_TU)
+ return CXError_InvalidArguments;
LOG_FUNC_SECTION {
*Log << ast_filename;
@@ -2603,19 +2630,20 @@ CXTranslationUnit clang_createTranslatio
FileSystemOptions FileSystemOpts;
IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
- ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
+ ASTUnit *AU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
CXXIdx->getOnlyLocalDecls(), None,
/*CaptureDiagnostics=*/true,
/*AllowPCHWithCompilerErrors=*/true,
/*UserFilesAreVolatile=*/true);
- return MakeCXTranslationUnit(CXXIdx, TU);
+ *out_TU = MakeCXTranslationUnit(CXXIdx, AU);
+ return *out_TU ? CXError_Success : CXError_Failure;
}
unsigned clang_defaultEditingTranslationUnitOptions() {
return CXTranslationUnit_PrecompiledPreamble |
CXTranslationUnit_CacheCompletionResults;
}
-
+
CXTranslationUnit
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char *source_filename,
@@ -2638,7 +2666,8 @@ struct ParseTranslationUnitInfo {
struct CXUnsavedFile *unsaved_files;
unsigned num_unsaved_files;
unsigned options;
- CXTranslationUnit result;
+ CXTranslationUnit *out_TU;
+ CXErrorCode result;
};
static void clang_parseTranslationUnit_Impl(void *UserData) {
ParseTranslationUnitInfo *PTUI =
@@ -2650,10 +2679,18 @@ static void clang_parseTranslationUnit_I
struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
unsigned num_unsaved_files = PTUI->num_unsaved_files;
unsigned options = PTUI->options;
- PTUI->result = 0;
+ CXTranslationUnit *out_TU = PTUI->out_TU;
- if (!CIdx)
+ // Check arguments.
+ if (!CIdx || !out_TU ||
+ (unsaved_files == NULL && num_unsaved_files != 0)) {
+ PTUI->result = CXError_InvalidArguments;
return;
+ }
+
+ // Set up the initial return values.
+ *out_TU = NULL;
+ PTUI->result = CXError_Failure;
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
@@ -2763,15 +2800,40 @@ static void clang_parseTranslationUnit_I
printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());
}
- PTUI->result = MakeCXTranslationUnit(CXXIdx, Unit.take());
+ if (isASTReadError(Unit ? Unit.get() : ErrUnit.get())) {
+ PTUI->result = CXError_ASTReadError;
+ } else {
+ *PTUI->out_TU = MakeCXTranslationUnit(CXXIdx, Unit.take());
+ PTUI->result = *PTUI->out_TU ? CXError_Success : CXError_Failure;
+ }
}
-CXTranslationUnit clang_parseTranslationUnit(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
+clang_parseTranslationUnit(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 TU;
+ enum CXErrorCode Result = clang_parseTranslationUnit2(
+ CIdx, source_filename, command_line_args, num_command_line_args,
+ unsaved_files, num_unsaved_files, options, &TU);
+ assert((TU && Result == CXError_Success) ||
+ (!TU && Result != CXError_Success));
+ return TU;
+}
+
+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) {
LOG_FUNC_SECTION {
*Log << source_filename << ": ";
for (int i = 0; i != num_command_line_args; ++i)
@@ -2780,7 +2842,8 @@ CXTranslationUnit clang_parseTranslation
ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
num_command_line_args, unsaved_files,
- num_unsaved_files, options, 0 };
+ num_unsaved_files, options, out_TU,
+ CXError_Failure };
llvm::CrashRecoveryContext CRC;
if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {
@@ -2803,10 +2866,11 @@ CXTranslationUnit clang_parseTranslation
fprintf(stderr, "],\n");
fprintf(stderr, " 'options' : %d,\n", options);
fprintf(stderr, "}\n");
-
- return 0;
+
+ return CXError_Crashed;
} else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
- PrintLibclangResourceUsage(PTUI.result);
+ if (CXTranslationUnit *TU = PTUI.out_TU)
+ PrintLibclangResourceUsage(*TU);
}
return PTUI.result;
@@ -2891,7 +2955,8 @@ void clang_disposeTranslationUnit(CXTran
if (CTUnit) {
// If the translation unit has been marked as unsafe to free, just discard
// it.
- if (cxtu::getASTUnit(CTUnit)->isUnsafeToFree())
+ ASTUnit *Unit = cxtu::getASTUnit(CTUnit);
+ if (Unit && Unit->isUnsafeToFree())
return;
delete cxtu::getASTUnit(CTUnit);
@@ -2918,11 +2983,22 @@ struct ReparseTranslationUnitInfo {
static void clang_reparseTranslationUnit_Impl(void *UserData) {
ReparseTranslationUnitInfo *RTUI =
static_cast<ReparseTranslationUnitInfo*>(UserData);
- RTUI->result = 1; // Error.
+ RTUI->result = CXError_Failure;
CXTranslationUnit TU = RTUI->TU;
+ unsigned num_unsaved_files = RTUI->num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
+ unsigned options = RTUI->options;
+ (void) options;
+
+ // Check arguments.
if (isNotUsableTU(TU)) {
LOG_BAD_TU(TU);
+ RTUI->result = CXError_InvalidArguments;
+ return;
+ }
+ if (unsaved_files == NULL && num_unsaved_files != 0) {
+ RTUI->result = CXError_InvalidArguments;
return;
}
@@ -2930,11 +3006,6 @@ static void clang_reparseTranslationUnit
delete static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);
TU->Diagnostics = 0;
- unsigned num_unsaved_files = RTUI->num_unsaved_files;
- struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
- unsigned options = RTUI->options;
- (void) options;
-
CIndexer *CXXIdx = TU->CIdx;
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
setThreadBackgroundPriority();
@@ -2956,9 +3027,11 @@ static void clang_reparseTranslationUnit
RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,
Buffer));
}
-
+
if (!CXXUnit->Reparse(*RemappedFiles.get()))
- RTUI->result = 0;
+ RTUI->result = CXError_Success;
+ else if (isASTReadError(CXXUnit))
+ RTUI->result = CXError_ASTReadError;
}
int clang_reparseTranslationUnit(CXTranslationUnit TU,
@@ -2970,7 +3043,7 @@ int clang_reparseTranslationUnit(CXTrans
}
ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
- options, 0 };
+ options, CXError_Failure };
if (getenv("LIBCLANG_NOTHREADS")) {
clang_reparseTranslationUnit_Impl(&RTUI);
@@ -2982,7 +3055,7 @@ int clang_reparseTranslationUnit(CXTrans
if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {
fprintf(stderr, "libclang: crash detected during reparsing\n");
cxtu::getASTUnit(TU)->setUnsafeToFree(true);
- return 1;
+ return CXError_Crashed;
} else if (getenv("LIBCLANG_RESOURCE_USAGE"))
PrintLibclangResourceUsage(TU);
@@ -6747,9 +6820,9 @@ Logger &cxindex::Logger::operator<<(CXTr
LogOS << " (" << Unit->getASTFileName() << ')';
return *this;
}
+ } else {
+ LogOS << "<NULL TU>";
}
-
- LogOS << "<NULL TU>";
return *this;
}
Modified: cfe/trunk/tools/libclang/CXTranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTranslationUnit.h?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXTranslationUnit.h (original)
+++ cfe/trunk/tools/libclang/CXTranslationUnit.h Wed Feb 12 13:12:37 2014
@@ -46,6 +46,10 @@ static inline ASTUnit *getASTUnit(CXTran
return TU->TheASTUnit;
}
+/// \returns true if the ASTUnit has a diagnostic about the AST file being
+/// corrupted.
+bool isASTReadError(ASTUnit *AU);
+
static inline bool isNotUsableTU(CXTranslationUnit TU) {
return !TU;
}
Modified: cfe/trunk/tools/libclang/Indexing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Indexing.cpp?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/Indexing.cpp (original)
+++ cfe/trunk/tools/libclang/Indexing.cpp Wed Feb 12 13:12:37 2014
@@ -514,16 +514,22 @@ static void clang_indexSourceFile_Impl(v
unsigned num_unsaved_files = ITUI->num_unsaved_files;
CXTranslationUnit *out_TU = ITUI->out_TU;
unsigned TU_options = ITUI->TU_options;
- ITUI->result = 1; // init as error.
-
+
+ // Set up the initial return value.
+ ITUI->result = CXError_Failure;
+
if (out_TU)
*out_TU = 0;
- bool requestedToGetTU = (out_TU != 0);
+ bool requestedToGetTU = (out_TU != 0);
- if (!cxIdxAction)
+ if (!cxIdxAction) {
+ ITUI->result = CXError_InvalidArguments;
return;
- if (!client_index_callbacks || index_callbacks_size == 0)
+ }
+ if (!client_index_callbacks || index_callbacks_size == 0) {
+ ITUI->result = CXError_InvalidArguments;
return;
+ }
IndexerCallbacks CB;
memset(&CB, 0, sizeof(CB));
@@ -671,13 +677,18 @@ static void clang_indexSourceFile_Impl(v
if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
printDiagsToStderr(Unit);
+ if (isASTReadError(Unit)) {
+ ITUI->result = CXError_ASTReadError;
+ return;
+ }
+
if (!Success)
return;
if (out_TU)
*out_TU = CXTU->takeTU();
- ITUI->result = 0; // success.
+ ITUI->result = CXError_Success;
}
//===----------------------------------------------------------------------===//
@@ -754,14 +765,20 @@ static void clang_indexTranslationUnit_I
IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
unsigned index_callbacks_size = ITUI->index_callbacks_size;
unsigned index_options = ITUI->index_options;
- ITUI->result = 1; // init as error.
+ // Set up the initial return value.
+ ITUI->result = CXError_Failure;
+
+ // Check arguments.
if (isNotUsableTU(TU)) {
LOG_BAD_TU(TU);
+ ITUI->result = CXError_InvalidArguments;
return;
}
- if (!client_index_callbacks || index_callbacks_size == 0)
+ if (!client_index_callbacks || index_callbacks_size == 0) {
+ ITUI->result = CXError_InvalidArguments;
return;
+ }
CIndexer *CXXIdx = TU->CIdx;
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
@@ -809,7 +826,7 @@ static void clang_indexTranslationUnit_I
indexTranslationUnit(*Unit, *IndexCtx);
indexDiagnostics(TU, *IndexCtx);
- ITUI->result = 0;
+ ITUI->result = CXError_Success;
}
//===----------------------------------------------------------------------===//
@@ -981,7 +998,8 @@ int clang_indexSourceFile(CXIndexAction
index_callbacks_size, index_options,
source_filename, command_line_args,
num_command_line_args, unsaved_files,
- num_unsaved_files, out_TU, TU_options, 0 };
+ num_unsaved_files, out_TU, TU_options,
+ CXError_Failure };
if (getenv("LIBCLANG_NOTHREADS")) {
clang_indexSourceFile_Impl(&ITUI);
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=201249&r1=201248&r2=201249&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Wed Feb 12 13:12:37 2014
@@ -87,6 +87,7 @@ clang_constructUSR_ObjCProtocol
clang_createCXCursorSet
clang_createIndex
clang_createTranslationUnit
+clang_createTranslationUnit2
clang_createTranslationUnitFromSourceFile
clang_defaultCodeCompleteOptions
clang_defaultDiagnosticDisplayOptions
@@ -262,6 +263,7 @@ clang_loadDiagnostics
clang_Location_isInSystemHeader
clang_Location_isFromMainFile
clang_parseTranslationUnit
+clang_parseTranslationUnit2
clang_remap_dispose
clang_remap_getFilenames
clang_remap_getNumFiles
More information about the cfe-commits
mailing list