<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Feb 12, 2014 at 8:12 PM, Dmitri Gribenko <span dir="ltr"><<a href="mailto:gribozavr@gmail.com" target="_blank" class="cremed">gribozavr@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: gribozavr<br>
Date: Wed Feb 12 13:12:37 2014<br>
New Revision: 201249<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=201249&view=rev" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project?rev=201249&view=rev</a><br>
Log:<br>
libclang: report error code for bad PCH files<br>
<br>
This commit improves libclang to report the error condition when<br>
CXTranslationUnit can not be created because of a stale PCH file.  This allows<br>
the caller, for example, to rebuild the PCH file and retry the request.<br>
<br>
There two are APIs in libclang that return a CXTranslationUnit and don't<br>
support reporting detailed errors (the only error condition is a NULL result).<br>
For these APIs, a second, superior, version is introduced --<br>
clang_createTranslationUnit2 and clang_parseTranslationUnit2.  These functions<br>
return a CXTranslationUnit indirectly and also return an error code.  Old<br>
functions are still supported and are nothing more than convenience wrappers<br>
that ignore extended error codes.<br>
<br>
As a cleanup, this commit also categorizes some libclang errors in the<br>
functions I had to modify anyway.<br>
<br>
Added:<br>
    cfe/trunk/test/Index/pch-depending-on-deleted-module.c<br>
Modified:<br>
    cfe/trunk/include/clang-c/Index.h<br>
    cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td<br>
    cfe/trunk/test/Modules/fatal-module-loader-error.m<br>
    cfe/trunk/tools/c-index-test/c-index-test.c<br>
    cfe/trunk/tools/libclang/CIndex.cpp<br>
    cfe/trunk/tools/libclang/CXTranslationUnit.h<br>
    cfe/trunk/tools/libclang/Indexing.cpp<br>
    cfe/trunk/tools/libclang/libclang.exports<br>
<br>
Modified: cfe/trunk/include/clang-c/Index.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang-c/Index.h (original)<br>
+++ cfe/trunk/include/clang-c/Index.h Wed Feb 12 13:12:37 2014<br>
@@ -30,7 +30,7 @@<br>
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.<br>
  */<br>
 #define CINDEX_VERSION_MAJOR 0<br>
-#define CINDEX_VERSION_MINOR 22<br>
+#define CINDEX_VERSION_MINOR 23<br>
<br>
 #define CINDEX_VERSION_ENCODE(major, minor) ( \<br>
       ((major) * 10000)                       \<br>
@@ -73,6 +73,43 @@ extern "C" {<br>
  */<br>
<br>
 /**<br>
+ * \brief Error codes returned by libclang routines.<br>
+ *<br>
+ * Zero (\c CXError_Success) is the only error code indicating success.  Other<br>
+ * error codes, including not yet assigned non-zero values, indicate errors.<br>
+ */<br>
+enum CXErrorCode {<br>
+  /**<br>
+   * \brief No error.<br>
+   */<br>
+  CXError_Success = 0,<br>
+<br>
+  /**<br>
+   * \brief A generic error code, no further details are available.<br>
+   *<br>
+   * Errors of this kind can get their own specific error codes in future<br>
+   * libclang versions.<br>
+   */<br>
+  CXError_Failure = 1,<br>
+<br>
+  /**<br>
+   * \brief libclang crashed while performing the requested operation.<br>
+   */<br>
+  CXError_Crashed = 2,<br>
+<br>
+  /**<br>
+   * \brief The function detected that the arguments violate the function<br>
+   * contract.<br>
+   */<br>
+  CXError_InvalidArguments = 3,<br>
+<br>
+  /**<br>
+   * \brief An AST deserialization error has occurred.<br>
+   */<br>
+  CXError_ASTReadError = 4<br>
+};<br>
+<br>
+/**<br>
  * \brief An "index" that consists of a set of translation units that would<br>
  * typically be linked together into an executable or library.<br>
  */<br>
@@ -1076,10 +1113,27 @@ CINDEX_LINKAGE CXTranslationUnit clang_c<br>
                                          struct CXUnsavedFile *unsaved_files);<br>
<br>
 /**<br>
- * \brief Create a translation unit from an AST file (-emit-ast).<br>
+ * \brief Same as \c clang_createTranslationUnit2, but returns<br>
+ * the \c CXTranslationUnit instead of an error code.  In case of an error this<br>
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed<br>
+ * error codes.<br>
+ */<br>
+CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(<br>
+    CXIndex CIdx,<br>
+    const char *ast_filename);<br>
+<br>
+/**<br>
+ * \brief Create a translation unit from an AST file (\c -emit-ast).<br>
+ *<br>
+ * \param[out] out_TU A non-NULL pointer to store the created<br>
+ * \c CXTranslationUnit.<br>
+ *<br>
+ * \returns Zero on success, otherwise returns an error code.<br>
  */<br>
-CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,<br>
-                                             const char *ast_filename);<br>
+CINDEX_LINKAGE enum CXErrorCode clang_createTranslationUnit2(<br>
+    CXIndex CIdx,<br>
+    const char *ast_filename,<br>
+    CXTranslationUnit *out_TU);<br>
<br>
 /**<br>
  * \brief Flags that control the creation of translation units.<br>
@@ -1193,7 +1247,22 @@ enum CXTranslationUnit_Flags {<br>
  * set of optimizations enabled may change from one version to the next.<br>
  */<br>
 CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);<br>
-<br>
+<br>
+/**<br>
+ * \brief Same as \c clang_parseTranslationUnit2, but returns<br>
+ * the \c CXTranslationUnit instead of an error code.  In case of an error this<br>
+ * routine returns a \c NULL \c CXTranslationUnit, without further detailed<br>
+ * error codes.<br>
+ */<br>
+CINDEX_LINKAGE CXTranslationUnit<br>
+clang_parseTranslationUnit(CXIndex CIdx,<br>
+                           const char *source_filename,<br>
+                           const char *const *command_line_args,<br>
+                           int num_command_line_args,<br>
+                           struct CXUnsavedFile *unsaved_files,<br>
+                           unsigned num_unsaved_files,<br>
+                           unsigned options);<br>
+<br>
 /**<br>
  * \brief Parse the given source file and the translation unit corresponding<br>
  * to that file.<br>
@@ -1208,7 +1277,7 @@ CINDEX_LINKAGE unsigned clang_defaultEdi<br>
  * associated.<br>
  *<br>
  * \param source_filename The name of the source file to load, or NULL if the<br>
- * source file is included in \p command_line_args.<br>
+ * source file is included in \c command_line_args.<br>
  *<br>
  * \param command_line_args The command-line arguments that would be<br>
  * passed to the \c clang executable if it were being invoked out-of-process.<br>
@@ -1217,7 +1286,7 @@ CINDEX_LINKAGE unsigned clang_defaultEdi<br>
  * '-emit-ast', '-fsyntax-only' (which is the default), and '-o \<output file>'.<br>
  *<br>
  * \param num_command_line_args The number of command-line arguments in<br>
- * \p command_line_args.<br>
+ * \c command_line_args.<br>
  *<br>
  * \param unsaved_files the files that have not yet been saved to disk<br>
  * but may be required for parsing, including the contents of<br>
@@ -1232,18 +1301,22 @@ CINDEX_LINKAGE unsigned clang_defaultEdi<br>
  * is managed but not its compilation. This should be a bitwise OR of the<br>
  * CXTranslationUnit_XXX flags.<br>
  *<br>
- * \returns A new translation unit describing the parsed code and containing<br>
- * any diagnostics produced by the compiler. If there is a failure from which<br>
- * the compiler cannot recover, returns NULL.<br>
- */<br>
-CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,<br>
-                                                    const char *source_filename,<br>
-                                         const char * const *command_line_args,<br>
-                                                      int num_command_line_args,<br>
-                                            struct CXUnsavedFile *unsaved_files,<br>
-                                                     unsigned num_unsaved_files,<br>
-                                                            unsigned options);<br>
-<br>
+ * \param[out] out_TU A non-NULL pointer to store the created<br>
+ * \c CXTranslationUnit, describing the parsed code and containing any<br>
+ * diagnostics produced by the compiler.<br>
+ *<br>
+ * \returns Zero on success, otherwise returns an error code.<br>
+ */<br>
+CINDEX_LINKAGE enum CXErrorCode<br>
+clang_parseTranslationUnit2(CXIndex CIdx,<br>
+                            const char *source_filename,<br>
+                            const char *const *command_line_args,<br>
+                            int num_command_line_args,<br>
+                            struct CXUnsavedFile *unsaved_files,<br>
+                            unsigned num_unsaved_files,<br>
+                            unsigned options,<br>
+                            CXTranslationUnit *out_TU);<br>
+<br>
 /**<br>
  * \brief Flags that control how translation units are saved.<br>
  *<br>
@@ -1395,10 +1468,11 @@ CINDEX_LINKAGE unsigned clang_defaultRep<br>
  * The function \c clang_defaultReparseOptions() produces a default set of<br>
  * options recommended for most uses, based on the translation unit.<br>
  *<br>
- * \returns 0 if the sources could be reparsed. A non-zero value will be<br>
+ * \returns 0 if the sources could be reparsed.  A non-zero error code will be<br>
  * returned if reparsing was impossible, such that the translation unit is<br>
- * invalid. In such cases, the only valid call for \p TU is<br>
- * \c clang_disposeTranslationUnit(TU).<br>
+ * invalid. In such cases, the only valid call for \c TU is<br>
+ * \c clang_disposeTranslationUnit(TU).  The error codes returned by this<br>
+ * routine are described by the \c CXErrorCode enum.<br>
  */<br>
 CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,<br>
                                                 unsigned num_unsaved_files,<br>
@@ -5789,11 +5863,12 @@ typedef enum {<br>
  * \param index_options A bitmask of options that affects how indexing is<br>
  * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags.<br>
  *<br>
- * \param out_TU [out] pointer to store a CXTranslationUnit that can be reused<br>
- * after indexing is finished. Set to NULL if you do not require it.<br>
+ * \param[out] out_TU pointer to store a \c CXTranslationUnit that can be<br>
+ * reused after indexing is finished. Set to \c NULL if you do not require it.<br>
  *<br>
- * \returns If there is a failure from which the there is no recovery, returns<br>
- * non-zero, otherwise returns 0.<br>
+ * \returns 0 on success or if there were errors from which the compiler could<br>
+ * recover.  If there is a failure from which the there is no recovery, returns<br>
+ * a non-zero \c CXErrorCode.<br>
  *<br>
  * The rest of the parameters are the same as #clang_parseTranslationUnit.<br>
  */<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Wed Feb 12 13:12:37 2014<br>
@@ -8,6 +8,7 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 let Component = "Serialization" in {<br>
+let CategoryName = "AST Deserialization Issue" in {<br>
<br>
 def err_fe_unable_to_read_pch_file : Error<<br>
     "unable to read PCH file %0: '%1'">;<br>
@@ -78,4 +79,6 @@ def note_module_odr_violation_no_possibl<br>
 def note_module_odr_violation_possible_decl : Note<<br>
   "declaration of %0 does not match">;<br>
<br>
-}<br>
+} // let CategoryName<br>
+} // let Component<br>
+<br>
<br>
Added: cfe/trunk/test/Index/pch-depending-on-deleted-module.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/pch-depending-on-deleted-module.c?rev=201249&view=auto" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/pch-depending-on-deleted-module.c?rev=201249&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/Index/pch-depending-on-deleted-module.c (added)<br>
+++ cfe/trunk/test/Index/pch-depending-on-deleted-module.c Wed Feb 12 13:12:37 2014<br>
@@ -0,0 +1,14 @@<br>
+#include "a.h"<br>
+<br>
+// RUN: rm -rf %t<br>
+// RUN: mkdir %t<br>
+<br>
+// 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<br>
+// RUN: %clang_cc1 -fmodules -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -verify-pch %t/use_LibA.pch<br>
+// RUN: rm -f %t/modules-cache/LibA.pcm<br>
+// 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<br>
+// 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<br>
+<br>
+// VERIFY: fatal error: malformed or corrupted AST file: 'Unable to load module<br>
+// INDEX: {{^}}Failure: AST deserialization error occurred{{$}}<br>
+<br>
<br>
Modified: cfe/trunk/test/Modules/fatal-module-loader-error.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/fatal-module-loader-error.m?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/fatal-module-loader-error.m?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/Modules/fatal-module-loader-error.m (original)<br>
+++ cfe/trunk/test/Modules/fatal-module-loader-error.m Wed Feb 12 13:12:37 2014<br>
@@ -23,4 +23,4 @@<br>
 // Also check that libclang does not create a PCH with such an error.<br>
 // RUN: not c-index-test -write-pch %t.pch -fmodules -fmodules-cache-path=%t \<br>
 // RUN: %s -Xclang -fdisable-module-hash -F %S/Inputs 2>&1 | FileCheck %s<br>
-// CHECK: Unable to write PCH file<br>
+// CHECK: {{^}}Failure: AST deserialization error occurred{{$}}<br>
<br>
Modified: cfe/trunk/tools/c-index-test/c-index-test.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)<br>
+++ cfe/trunk/tools/c-index-test/c-index-test.c Wed Feb 12 13:12:37 2014<br>
@@ -79,8 +79,33 @@ static unsigned getDefaultParsingOptions<br>
   return options;<br>
 }<br>
<br>
+/// \brief Returns 0 in case of success, non-zero in case of a failure.<br>
 static int checkForErrors(CXTranslationUnit TU);<br>
<br>
+static void describeLibclangFailure(enum CXErrorCode Err) {<br>
+  switch (Err) {<br>
+  case CXError_Success:<br>
+    fprintf(stderr, "Success\n");<br>
+    return;<br>
+<br>
+  case CXError_Failure:<br>
+    fprintf(stderr, "Failure (no details available)\n");<br>
+    return;<br>
+<br>
+  case CXError_Crashed:<br>
+    fprintf(stderr, "Failure: libclang crashed\n");<br>
+    return;<br>
+<br>
+  case CXError_InvalidArguments:<br>
+    fprintf(stderr, "Failure: invalid arguments passed to a libclang routine\n");<br>
+    return;<br>
+<br>
+  case CXError_ASTReadError:<br>
+    fprintf(stderr, "Failure: AST deserialization error occurred\n");<br>
+    return;<br>
+  }<br>
+}<br>
+<br>
 static void PrintExtent(FILE *out, unsigned begin_line, unsigned begin_column,<br>
                         unsigned end_line, unsigned end_column) {<br>
   fprintf(out, "[%d:%d - %d:%d]", begin_line, begin_column,<br>
@@ -89,10 +114,11 @@ static void PrintExtent(FILE *out, unsig<br>
<br>
 static unsigned CreateTranslationUnit(CXIndex Idx, const char *file,<br>
                                       CXTranslationUnit *TU) {<br>
-<br>
-  *TU = clang_createTranslationUnit(Idx, file);<br>
-  if (!*TU) {<br>
+  enum CXErrorCode Err = clang_createTranslationUnit2(Idx, file, TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to load translation unit from '%s'!\n", file);<br>
+    describeLibclangFailure(Err);<br>
+    *TU = 0;<br>
     return 0;<br>
   }<br>
   return 1;<br>
@@ -1420,8 +1446,9 @@ int perform_test_load_source(int argc, c<br>
   const char *CommentSchemaFile;<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
+  enum CXErrorCode Err;<br>
   int result;<br>
-<br>
+<br>
   Idx = clang_createIndex(/* excludeDeclsFromPCH */<br>
                           (!strcmp(filter, "local") ||<br>
                            !strcmp(filter, "local-display"))? 1 : 0,<br>
@@ -1437,13 +1464,14 @@ int perform_test_load_source(int argc, c<br>
     return -1;<br>
   }<br>
<br>
-  TU = clang_parseTranslationUnit(Idx, 0,<br>
-                                  argv + num_unsaved_files,<br>
-                                  argc - num_unsaved_files,<br>
-                                  unsaved_files, num_unsaved_files,<br>
-                                  getDefaultParsingOptions());<br>
-  if (!TU) {<br>
+  Err = clang_parseTranslationUnit2(Idx, 0,<br>
+                                    argv + num_unsaved_files,<br>
+                                    argc - num_unsaved_files,<br>
+                                    unsaved_files, num_unsaved_files,<br>
+                                    getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to load translation unit!\n");<br>
+    describeLibclangFailure(Err);<br>
     free_remapped_files(unsaved_files, num_unsaved_files);<br>
     clang_disposeIndex(Idx);<br>
     return 1;<br>
@@ -1464,6 +1492,7 @@ int perform_test_reparse_source(int argc<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
   int compiler_arg_idx = 0;<br>
+  enum CXErrorCode Err;<br>
   int result, i;<br>
   int trial;<br>
   int remap_after_trial = 0;<br>
@@ -1489,12 +1518,13 @@ int perform_test_reparse_source(int argc<br>
<br>
   /* Load the initial translation unit -- we do this without honoring remapped<br>
    * files, so that we have a way to test results after changing the source. */<br>
-  TU = clang_parseTranslationUnit(Idx, 0,<br>
-                                  argv + compiler_arg_idx,<br>
-                                  argc - compiler_arg_idx,<br>
-                                  0, 0, getDefaultParsingOptions());<br>
-  if (!TU) {<br>
+  Err = clang_parseTranslationUnit2(Idx, 0,<br>
+                                    argv + compiler_arg_idx,<br>
+                                    argc - compiler_arg_idx,<br>
+                                    0, 0, getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to load translation unit!\n");<br>
+    describeLibclangFailure(Err);<br>
     free_remapped_files(unsaved_files, num_unsaved_files);<br>
     clang_disposeIndex(Idx);<br>
     return 1;<br>
@@ -1517,11 +1547,14 @@ int perform_test_reparse_source(int argc<br>
       return -1;<br>
     }<br>
<br>
-    if (clang_reparseTranslationUnit(TU,<br>
-                             trial >= remap_after_trial ? num_unsaved_files : 0,<br>
-                             trial >= remap_after_trial ? unsaved_files : 0,<br>
-                                     clang_defaultReparseOptions(TU))) {<br>
+    Err = clang_reparseTranslationUnit(<br>
+        TU,<br>
+        trial >= remap_after_trial ? num_unsaved_files : 0,<br>
+        trial >= remap_after_trial ? unsaved_files : 0,<br>
+        clang_defaultReparseOptions(TU));<br>
+    if (Err != CXError_Success) {<br>
       fprintf(stderr, "Unable to reparse translation unit!\n");<br>
+      describeLibclangFailure(Err);<br>
       clang_disposeTranslationUnit(TU);<br>
       free_remapped_files(unsaved_files, num_unsaved_files);<br>
       clang_disposeIndex(Idx);<br>
@@ -1943,7 +1976,8 @@ int perform_code_completion(int argc, co<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
   CXCodeCompleteResults *results = 0;<br>
-  CXTranslationUnit TU = 0;<br>
+  enum CXErrorCode Err;<br>
+  CXTranslationUnit TU;<br>
   unsigned I, Repeats = 1;<br>
   unsigned completionOptions = clang_defaultCodeCompleteOptions();<br>
<br>
@@ -1968,21 +2002,27 @@ int perform_code_completion(int argc, co<br>
<br>
   if (getenv("CINDEXTEST_EDITING"))<br>
     Repeats = 5;<br>
-<br>
-  TU = clang_parseTranslationUnit(CIdx, 0,<br>
-                                  argv + num_unsaved_files + 2,<br>
-                                  argc - num_unsaved_files - 2,<br>
-                                  0, 0, getDefaultParsingOptions());<br>
-  if (!TU) {<br>
+<br>
+  Err = clang_parseTranslationUnit2(CIdx, 0,<br>
+                                    argv + num_unsaved_files + 2,<br>
+                                    argc - num_unsaved_files - 2,<br>
+                                    0, 0, getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to load translation unit!\n");<br>
+    describeLibclangFailure(Err);<br>
     return 1;<br>
   }<br>
<br>
-  if (clang_reparseTranslationUnit(TU, 0, 0, clang_defaultReparseOptions(TU))) {<br>
+  Err = clang_reparseTranslationUnit(TU, 0, 0,<br>
+                                     clang_defaultReparseOptions(TU));<br>
+<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to reparse translation init!\n");<br>
+    describeLibclangFailure(Err);<br>
+    clang_disposeTranslationUnit(TU);<br>
     return 1;<br>
   }<br>
-<br>
+<br>
   for (I = 0; I != Repeats; ++I) {<br>
     results = clang_codeCompleteAt(TU, filename, line, column,<br>
                                    unsaved_files, num_unsaved_files,<br>
@@ -2069,6 +2109,7 @@ static int inspect_cursor_at(int argc, c<br>
   int errorCode;<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
+  enum CXErrorCode Err;<br>
   CXTranslationUnit TU;<br>
   CXCursor Cursor;<br>
   CursorSourceLocation *Locations = 0;<br>
@@ -2102,15 +2143,15 @@ static int inspect_cursor_at(int argc, c<br>
   /* Parse the translation unit. When we're testing clang_getCursor() after<br>
      reparsing, don't remap unsaved files until the second parse. */<br>
   CIdx = clang_createIndex(1, 1);<br>
-  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],<br>
-                                  argv + num_unsaved_files + 1 + NumLocations,<br>
-                                  argc - num_unsaved_files - 2 - NumLocations,<br>
-                                  unsaved_files,<br>
-                                  Repeats > 1? 0 : num_unsaved_files,<br>
-                                  getDefaultParsingOptions());<br>
-<br>
-  if (!TU) {<br>
+  Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],<br>
+                                   argv + num_unsaved_files + 1 + NumLocations,<br>
+                                   argc - num_unsaved_files - 2 - NumLocations,<br>
+                                   unsaved_files,<br>
+                                   Repeats > 1? 0 : num_unsaved_files,<br>
+                                   getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "unable to parse input\n");<br>
+    describeLibclangFailure(Err);<br>
     return -1;<br>
   }<br>
<br>
@@ -2118,11 +2159,14 @@ static int inspect_cursor_at(int argc, c<br>
     return -1;<br>
<br>
   for (I = 0; I != Repeats; ++I) {<br>
-    if (Repeats > 1 &&<br>
-        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
-                                     clang_defaultReparseOptions(TU))) {<br>
-      clang_disposeTranslationUnit(TU);<br>
-      return 1;<br>
+    if (Repeats > 1) {<br>
+      Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
+                                         clang_defaultReparseOptions(TU));<br>
+      if (Err != CXError_Success) {<br>
+        describeLibclangFailure(Err);<br>
+        clang_disposeTranslationUnit(TU);<br>
+        return 1;<br>
+      }<br>
     }<br>
<br>
     if (checkForErrors(TU) != 0)<br>
@@ -2235,6 +2279,7 @@ static int find_file_refs_at(int argc, c<br>
   int errorCode;<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
+  enum CXErrorCode Err;<br>
   CXTranslationUnit TU;<br>
   CXCursor Cursor;<br>
   CursorSourceLocation *Locations = 0;<br>
@@ -2268,15 +2313,16 @@ static int find_file_refs_at(int argc, c<br>
   /* Parse the translation unit. When we're testing clang_getCursor() after<br>
      reparsing, don't remap unsaved files until the second parse. */<br>
   CIdx = clang_createIndex(1, 1);<br>
-  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],<br>
-                                  argv + num_unsaved_files + 1 + NumLocations,<br>
-                                  argc - num_unsaved_files - 2 - NumLocations,<br>
-                                  unsaved_files,<br>
-                                  Repeats > 1? 0 : num_unsaved_files,<br>
-                                  getDefaultParsingOptions());<br>
-<br>
-  if (!TU) {<br>
+  Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],<br>
+                                    argv + num_unsaved_files + 1 + NumLocations,<br>
+                                    argc - num_unsaved_files - 2 - NumLocations,<br>
+                                    unsaved_files,<br>
+                                    Repeats > 1? 0 : num_unsaved_files,<br>
+                                    getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "unable to parse input\n");<br>
+    describeLibclangFailure(Err);<br>
+    clang_disposeTranslationUnit(TU);<br>
     return -1;<br>
   }<br>
<br>
@@ -2284,11 +2330,14 @@ static int find_file_refs_at(int argc, c<br>
     return -1;<br>
<br>
   for (I = 0; I != Repeats; ++I) {<br>
-    if (Repeats > 1 &&<br>
-        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
-                                     clang_defaultReparseOptions(TU))) {<br>
-      clang_disposeTranslationUnit(TU);<br>
-      return 1;<br>
+    if (Repeats > 1) {<br>
+      Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
+                                         clang_defaultReparseOptions(TU));<br>
+      if (Err != CXError_Success) {<br>
+        describeLibclangFailure(Err);<br>
+        clang_disposeTranslationUnit(TU);<br>
+        return 1;<br>
+      }<br>
     }<br>
<br>
     if (checkForErrors(TU) != 0)<br>
@@ -2339,6 +2388,7 @@ static int find_file_includes_in(int arg<br>
   CXIndex CIdx;<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
+  enum CXErrorCode Err;<br>
   CXTranslationUnit TU;<br>
   const char **Filenames = 0;<br>
   unsigned NumFilenames = 0;<br>
@@ -2368,15 +2418,17 @@ static int find_file_includes_in(int arg<br>
   /* Parse the translation unit. When we're testing clang_getCursor() after<br>
      reparsing, don't remap unsaved files until the second parse. */<br>
   CIdx = clang_createIndex(1, 1);<br>
-  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],<br>
-                                  argv + num_unsaved_files + 1 + NumFilenames,<br>
-                                  argc - num_unsaved_files - 2 - NumFilenames,<br>
-                                  unsaved_files,<br>
-                                  Repeats > 1? 0 : num_unsaved_files,<br>
-                                  getDefaultParsingOptions());<br>
+  Err = clang_parseTranslationUnit2(<br>
+      CIdx, argv[argc - 1],<br>
+      argv + num_unsaved_files + 1 + NumFilenames,<br>
+      argc - num_unsaved_files - 2 - NumFilenames,<br>
+      unsaved_files,<br>
+      Repeats > 1 ? 0 : num_unsaved_files, getDefaultParsingOptions(), &TU);<br>
<br>
-  if (!TU) {<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "unable to parse input\n");<br>
+    describeLibclangFailure(Err);<br>
+    clang_disposeTranslationUnit(TU);<br>
     return -1;<br>
   }<br>
<br>
@@ -2384,11 +2436,14 @@ static int find_file_includes_in(int arg<br>
     return -1;<br>
<br>
   for (I = 0; I != Repeats; ++I) {<br>
-    if (Repeats > 1 &&<br>
-        clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
-                                     clang_defaultReparseOptions(TU))) {<br>
-      clang_disposeTranslationUnit(TU);<br>
-      return 1;<br>
+    if (Repeats > 1) {<br>
+      Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
+                                         clang_defaultReparseOptions(TU));<br>
+      if (Err != CXError_Success) {<br>
+        describeLibclangFailure(Err);<br>
+        clang_disposeTranslationUnit(TU);<br>
+        return 1;<br>
+      }<br>
     }<br>
<br>
     if (checkForErrors(TU) != 0)<br>
@@ -2933,6 +2988,9 @@ static int index_compile_args(int num_ar<br>
                                  &IndexCB,sizeof(IndexCB), index_opts,<br>
                                  0, args, num_args, 0, 0, 0,<br>
                                  getDefaultParsingOptions());<br>
+  if (result != CXError_Success)<br>
+    describeLibclangFailure(result);<br>
+<br>
   if (index_data.fail_for_error)<br>
     result = -1;<br>
<br>
@@ -3185,6 +3243,7 @@ int perform_token_annotation(int argc, c<br>
   CXFile file = 0;<br>
   CXCursor *cursors = 0;<br>
   CXSourceRangeList *skipped_ranges = 0;<br>
+  enum CXErrorCode Err;<br>
   unsigned i;<br>
<br>
   input += strlen("-test-annotate-tokens=");<br>
@@ -3198,14 +3257,15 @@ int perform_token_annotation(int argc, c<br>
   }<br>
<br>
   CIdx = clang_createIndex(0, 1);<br>
-  TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],<br>
-                                  argv + num_unsaved_files + 2,<br>
-                                  argc - num_unsaved_files - 3,<br>
-                                  unsaved_files,<br>
-                                  num_unsaved_files,<br>
-                                  getDefaultParsingOptions());<br>
-  if (!TU) {<br>
+  Err = clang_parseTranslationUnit2(CIdx, argv[argc - 1],<br>
+                                    argv + num_unsaved_files + 2,<br>
+                                    argc - num_unsaved_files - 3,<br>
+                                    unsaved_files,<br>
+                                    num_unsaved_files,<br>
+                                    getDefaultParsingOptions(), &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "unable to parse input\n");<br>
+    describeLibclangFailure(Err);<br>
     clang_disposeIndex(CIdx);<br>
     free(filename);<br>
     free_remapped_files(unsaved_files, num_unsaved_files);<br>
@@ -3220,9 +3280,11 @@ int perform_token_annotation(int argc, c<br>
<br>
   if (getenv("CINDEXTEST_EDITING")) {<br>
     for (i = 0; i < 5; ++i) {<br>
-      if (clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
-                                       clang_defaultReparseOptions(TU))) {<br>
+      Err = clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,<br>
+                                         clang_defaultReparseOptions(TU));<br>
+      if (Err != CXError_Success) {<br>
         fprintf(stderr, "Unable to reparse translation unit!\n");<br>
+        describeLibclangFailure(Err);<br>
         errorCode = -1;<br>
         goto teardown;<br>
       }<br>
@@ -3586,6 +3648,7 @@ int write_pch_file(const char *filename,<br>
   CXTranslationUnit TU;<br>
   struct CXUnsavedFile *unsaved_files = 0;<br>
   int num_unsaved_files = 0;<br>
+  enum CXErrorCode Err;<br>
   int result = 0;<br>
<br>
   Idx = clang_createIndex(/* excludeDeclsFromPCH */1, /* displayDiagnostics=*/1);<br>
@@ -3594,18 +3657,19 @@ int write_pch_file(const char *filename,<br>
     clang_disposeIndex(Idx);<br>
     return -1;<br>
   }<br>
-<br>
-  TU = clang_parseTranslationUnit(Idx, 0,<br>
-                                  argv + num_unsaved_files,<br>
-                                  argc - num_unsaved_files,<br>
-                                  unsaved_files,<br>
-                                  num_unsaved_files,<br>
-                                  CXTranslationUnit_Incomplete |<br>
-                                  CXTranslationUnit_DetailedPreprocessingRecord|<br>
-                                    CXTranslationUnit_ForSerialization);<br>
-  if (!TU) {<br>
+<br>
+  Err = clang_parseTranslationUnit2(<br>
+      Idx, 0, argv + num_unsaved_files, argc - num_unsaved_files,<br>
+      unsaved_files, num_unsaved_files,<br>
+      CXTranslationUnit_Incomplete |<br>
+          CXTranslationUnit_DetailedPreprocessingRecord |<br>
+          CXTranslationUnit_ForSerialization,<br>
+      &TU);<br>
+  if (Err != CXError_Success) {<br>
     fprintf(stderr, "Unable to load translation unit!\n");<br>
+    describeLibclangFailure(Err);<br>
     free_remapped_files(unsaved_files, num_unsaved_files);<br>
+    clang_disposeTranslationUnit(TU);<br>
     clang_disposeIndex(Idx);<br>
     return 1;<br>
   }<br>
<br>
Modified: cfe/trunk/tools/libclang/CIndex.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/CIndex.cpp (original)<br>
+++ cfe/trunk/tools/libclang/CIndex.cpp Wed Feb 12 13:12:37 2014<br>
@@ -25,6 +25,8 @@<br>
 #include "clang/AST/Attr.h"<br>
 #include "clang/AST/StmtVisitor.h"<br>
 #include "clang/Basic/Diagnostic.h"<br>
+#include "clang/Basic/DiagnosticCategories.h"<br>
+#include "clang/Basic/DiagnosticIDs.h"<br>
 #include "clang/Basic/Version.h"<br>
 #include "clang/Frontend/ASTUnit.h"<br>
 #include "clang/Frontend/CompilerInstance.h"<br>
@@ -34,6 +36,7 @@<br>
 #include "clang/Lex/Lexer.h"<br>
 #include "clang/Lex/PreprocessingRecord.h"<br>
 #include "clang/Lex/Preprocessor.h"<br>
+#include "clang/Serialization/SerializationDiagnostic.h"<br>
 #include "llvm/ADT/Optional.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
@@ -62,6 +65,7 @@ using namespace clang::cxindex;<br>
 CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *AU) {<br>
   if (!AU)<br>
     return 0;<br>
+  assert(CIdx);<br>
   CXTranslationUnit D = new CXTranslationUnitImpl();<br>
   D->CIdx = CIdx;<br>
   D->TheASTUnit = AU;<br>
@@ -72,6 +76,18 @@ CXTranslationUnit cxtu::MakeCXTranslatio<br>
   return D;<br>
 }<br>
<br>
+bool cxtu::isASTReadError(ASTUnit *AU) {<br>
+  for (ASTUnit::stored_diag_iterator D = AU->stored_diag_begin(),<br>
+                                     DEnd = AU->stored_diag_end();<br>
+       D != DEnd; ++D) {<br>
+    if (D->getLevel() >= DiagnosticsEngine::Error &&<br>
+        DiagnosticIDs::getCategoryNumberForDiag(D->getID()) ==<br>
+            diag::DiagCat_AST_Deserialization_Issue)<br>
+      return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
 cxtu::CXTUOwner::~CXTUOwner() {<br>
   if (TU)<br>
     clang_disposeTranslationUnit(TU);<br>
@@ -2589,11 +2605,22 @@ void clang_toggleCrashRecovery(unsigned<br>
   else<br>
     llvm::CrashRecoveryContext::Disable();<br>
 }<br>
-<br>
+<br>
 CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,<br>
                                               const char *ast_filename) {<br>
-  if (!CIdx || !ast_filename)<br>
-    return 0;<br>
+  CXTranslationUnit TU;<br>
+  enum CXErrorCode Result =<br>
+      clang_createTranslationUnit2(CIdx, ast_filename, &TU);<br>
+  assert((TU && Result == CXError_Success) ||<br>
+         (!TU && Result != CXError_Success));<br></blockquote><div><br></div><div>This triggers on one of our internal tests. I have submitted r201329, which kind of papers over the underlying cause. Can you take a look? If the fix is not obvious, I am happy to look into this further.</div>
<div><br></div><div>Cheers,</div><div>Daniel</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

+  return TU;<br>
+}<br>
+<br>
+enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,<br>
+                                              const char *ast_filename,<br>
+                                              CXTranslationUnit *out_TU) {<br>
+  if (!CIdx || !ast_filename || !out_TU)<br>
+    return CXError_InvalidArguments;<br>
<br>
   LOG_FUNC_SECTION {<br>
     *Log << ast_filename;<br>
@@ -2603,19 +2630,20 @@ CXTranslationUnit clang_createTranslatio<br>
   FileSystemOptions FileSystemOpts;<br>
<br>
   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;<br>
-  ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,<br>
+  ASTUnit *AU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,<br>
                                          CXXIdx->getOnlyLocalDecls(), None,<br>
                                          /*CaptureDiagnostics=*/true,<br>
                                          /*AllowPCHWithCompilerErrors=*/true,<br>
                                          /*UserFilesAreVolatile=*/true);<br>
-  return MakeCXTranslationUnit(CXXIdx, TU);<br>
+  *out_TU = MakeCXTranslationUnit(CXXIdx, AU);<br>
+  return *out_TU ? CXError_Success : CXError_Failure;<br>
 }<br>
<br>
 unsigned clang_defaultEditingTranslationUnitOptions() {<br>
   return CXTranslationUnit_PrecompiledPreamble |<br>
          CXTranslationUnit_CacheCompletionResults;<br>
 }<br>
-<br>
+<br>
 CXTranslationUnit<br>
 clang_createTranslationUnitFromSourceFile(CXIndex CIdx,<br>
                                           const char *source_filename,<br>
@@ -2638,7 +2666,8 @@ struct ParseTranslationUnitInfo {<br>
   struct CXUnsavedFile *unsaved_files;<br>
   unsigned num_unsaved_files;<br>
   unsigned options;<br>
-  CXTranslationUnit result;<br>
+  CXTranslationUnit *out_TU;<br>
+  CXErrorCode result;<br>
 };<br>
 static void clang_parseTranslationUnit_Impl(void *UserData) {<br>
   ParseTranslationUnitInfo *PTUI =<br>
@@ -2650,10 +2679,18 @@ static void clang_parseTranslationUnit_I<br>
   struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;<br>
   unsigned num_unsaved_files = PTUI->num_unsaved_files;<br>
   unsigned options = PTUI->options;<br>
-  PTUI->result = 0;<br>
+  CXTranslationUnit *out_TU = PTUI->out_TU;<br>
<br>
-  if (!CIdx)<br>
+  // Check arguments.<br>
+  if (!CIdx || !out_TU ||<br>
+      (unsaved_files == NULL && num_unsaved_files != 0)) {<br>
+    PTUI->result = CXError_InvalidArguments;<br>
     return;<br>
+  }<br>
+<br>
+  // Set up the initial return values.<br>
+  *out_TU = NULL;<br>
+  PTUI->result = CXError_Failure;<br>
<br>
   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);<br>
<br>
@@ -2763,15 +2800,40 @@ static void clang_parseTranslationUnit_I<br>
       printDiagsToStderr(Unit ? Unit.get() : ErrUnit.get());<br>
   }<br>
<br>
-  PTUI->result = MakeCXTranslationUnit(CXXIdx, Unit.take());<br>
+  if (isASTReadError(Unit ? Unit.get() : ErrUnit.get())) {<br>
+    PTUI->result = CXError_ASTReadError;<br>
+  } else {<br>
+    *PTUI->out_TU = MakeCXTranslationUnit(CXXIdx, Unit.take());<br>
+    PTUI->result = *PTUI->out_TU ? CXError_Success : CXError_Failure;<br>
+  }<br>
 }<br>
-CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,<br>
-                                             const char *source_filename,<br>
-                                         const char * const *command_line_args,<br>
-                                             int num_command_line_args,<br>
-                                            struct CXUnsavedFile *unsaved_files,<br>
-                                             unsigned num_unsaved_files,<br>
-                                             unsigned options) {<br>
+<br>
+CXTranslationUnit<br>
+clang_parseTranslationUnit(CXIndex CIdx,<br>
+                           const char *source_filename,<br>
+                           const char *const *command_line_args,<br>
+                           int num_command_line_args,<br>
+                           struct CXUnsavedFile *unsaved_files,<br>
+                           unsigned num_unsaved_files,<br>
+                           unsigned options) {<br>
+  CXTranslationUnit TU;<br>
+  enum CXErrorCode Result = clang_parseTranslationUnit2(<br>
+      CIdx, source_filename, command_line_args, num_command_line_args,<br>
+      unsaved_files, num_unsaved_files, options, &TU);<br>
+  assert((TU && Result == CXError_Success) ||<br>
+         (!TU && Result != CXError_Success));<br>
+  return TU;<br>
+}<br>
+<br>
+enum CXErrorCode clang_parseTranslationUnit2(<br>
+    CXIndex CIdx,<br>
+    const char *source_filename,<br>
+    const char *const *command_line_args,<br>
+    int num_command_line_args,<br>
+    struct CXUnsavedFile *unsaved_files,<br>
+    unsigned num_unsaved_files,<br>
+    unsigned options,<br>
+    CXTranslationUnit *out_TU) {<br>
   LOG_FUNC_SECTION {<br>
     *Log << source_filename << ": ";<br>
     for (int i = 0; i != num_command_line_args; ++i)<br>
@@ -2780,7 +2842,8 @@ CXTranslationUnit clang_parseTranslation<br>
<br>
   ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,<br>
                                     num_command_line_args, unsaved_files,<br>
-                                    num_unsaved_files, options, 0 };<br>
+                                    num_unsaved_files, options, out_TU,<br>
+                                    CXError_Failure };<br>
   llvm::CrashRecoveryContext CRC;<br>
<br>
   if (!RunSafely(CRC, clang_parseTranslationUnit_Impl, &PTUI)) {<br>
@@ -2803,10 +2866,11 @@ CXTranslationUnit clang_parseTranslation<br>
     fprintf(stderr, "],\n");<br>
     fprintf(stderr, "  'options' : %d,\n", options);<br>
     fprintf(stderr, "}\n");<br>
-<br>
-    return 0;<br>
+<br>
+    return CXError_Crashed;<br>
   } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {<br>
-    PrintLibclangResourceUsage(PTUI.result);<br>
+    if (CXTranslationUnit *TU = PTUI.out_TU)<br>
+      PrintLibclangResourceUsage(*TU);<br>
   }<br>
<br>
   return PTUI.result;<br>
@@ -2891,7 +2955,8 @@ void clang_disposeTranslationUnit(CXTran<br>
   if (CTUnit) {<br>
     // If the translation unit has been marked as unsafe to free, just discard<br>
     // it.<br>
-    if (cxtu::getASTUnit(CTUnit)->isUnsafeToFree())<br>
+    ASTUnit *Unit = cxtu::getASTUnit(CTUnit);<br>
+    if (Unit && Unit->isUnsafeToFree())<br>
       return;<br>
<br>
     delete cxtu::getASTUnit(CTUnit);<br>
@@ -2918,11 +2983,22 @@ struct ReparseTranslationUnitInfo {<br>
 static void clang_reparseTranslationUnit_Impl(void *UserData) {<br>
   ReparseTranslationUnitInfo *RTUI =<br>
     static_cast<ReparseTranslationUnitInfo*>(UserData);<br>
-  RTUI->result = 1; // Error.<br>
+  RTUI->result = CXError_Failure;<br>
<br>
   CXTranslationUnit TU = RTUI->TU;<br>
+  unsigned num_unsaved_files = RTUI->num_unsaved_files;<br>
+  struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;<br>
+  unsigned options = RTUI->options;<br>
+  (void) options;<br>
+<br>
+  // Check arguments.<br>
   if (isNotUsableTU(TU)) {<br>
     LOG_BAD_TU(TU);<br>
+    RTUI->result = CXError_InvalidArguments;<br>
+    return;<br>
+  }<br>
+  if (unsaved_files == NULL && num_unsaved_files != 0) {<br>
+    RTUI->result = CXError_InvalidArguments;<br>
     return;<br>
   }<br>
<br>
@@ -2930,11 +3006,6 @@ static void clang_reparseTranslationUnit<br>
   delete static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics);<br>
   TU->Diagnostics = 0;<br>
<br>
-  unsigned num_unsaved_files = RTUI->num_unsaved_files;<br>
-  struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;<br>
-  unsigned options = RTUI->options;<br>
-  (void) options;<br>
-<br>
   CIndexer *CXXIdx = TU->CIdx;<br>
   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))<br>
     setThreadBackgroundPriority();<br>
@@ -2956,9 +3027,11 @@ static void clang_reparseTranslationUnit<br>
     RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename,<br>
                                             Buffer));<br>
   }<br>
-<br>
+<br>
   if (!CXXUnit->Reparse(*RemappedFiles.get()))<br>
-    RTUI->result = 0;<br>
+    RTUI->result = CXError_Success;<br>
+  else if (isASTReadError(CXXUnit))<br>
+    RTUI->result = CXError_ASTReadError;<br>
 }<br>
<br>
 int clang_reparseTranslationUnit(CXTranslationUnit TU,<br>
@@ -2970,7 +3043,7 @@ int clang_reparseTranslationUnit(CXTrans<br>
   }<br>
<br>
   ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,<br>
-                                      options, 0 };<br>
+                                      options, CXError_Failure };<br>
<br>
   if (getenv("LIBCLANG_NOTHREADS")) {<br>
     clang_reparseTranslationUnit_Impl(&RTUI);<br>
@@ -2982,7 +3055,7 @@ int clang_reparseTranslationUnit(CXTrans<br>
   if (!RunSafely(CRC, clang_reparseTranslationUnit_Impl, &RTUI)) {<br>
     fprintf(stderr, "libclang: crash detected during reparsing\n");<br>
     cxtu::getASTUnit(TU)->setUnsafeToFree(true);<br>
-    return 1;<br>
+    return CXError_Crashed;<br>
   } else if (getenv("LIBCLANG_RESOURCE_USAGE"))<br>
     PrintLibclangResourceUsage(TU);<br>
<br>
@@ -6747,9 +6820,9 @@ Logger &cxindex::Logger::operator<<(CXTr<br>
         LogOS << " (" << Unit->getASTFileName() << ')';<br>
       return *this;<br>
     }<br>
+  } else {<br>
+    LogOS << "<NULL TU>";<br>
   }<br>
-<br>
-  LogOS << "<NULL TU>";<br>
   return *this;<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/tools/libclang/CXTranslationUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTranslationUnit.h?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTranslationUnit.h?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/CXTranslationUnit.h (original)<br>
+++ cfe/trunk/tools/libclang/CXTranslationUnit.h Wed Feb 12 13:12:37 2014<br>
@@ -46,6 +46,10 @@ static inline ASTUnit *getASTUnit(CXTran<br>
   return TU->TheASTUnit;<br>
 }<br>
<br>
+/// \returns true if the ASTUnit has a diagnostic about the AST file being<br>
+/// corrupted.<br>
+bool isASTReadError(ASTUnit *AU);<br>
+<br>
 static inline bool isNotUsableTU(CXTranslationUnit TU) {<br>
   return !TU;<br>
 }<br>
<br>
Modified: cfe/trunk/tools/libclang/Indexing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Indexing.cpp?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Indexing.cpp?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/Indexing.cpp (original)<br>
+++ cfe/trunk/tools/libclang/Indexing.cpp Wed Feb 12 13:12:37 2014<br>
@@ -514,16 +514,22 @@ static void clang_indexSourceFile_Impl(v<br>
   unsigned num_unsaved_files = ITUI->num_unsaved_files;<br>
   CXTranslationUnit *out_TU  = ITUI->out_TU;<br>
   unsigned TU_options = ITUI->TU_options;<br>
-  ITUI->result = 1; // init as error.<br>
-<br>
+<br>
+  // Set up the initial return value.<br>
+  ITUI->result = CXError_Failure;<br>
+<br>
   if (out_TU)<br>
     *out_TU = 0;<br>
-  bool requestedToGetTU = (out_TU != 0);<br>
+  bool requestedToGetTU = (out_TU != 0);<br>
<br>
-  if (!cxIdxAction)<br>
+  if (!cxIdxAction) {<br>
+    ITUI->result = CXError_InvalidArguments;<br>
     return;<br>
-  if (!client_index_callbacks || index_callbacks_size == 0)<br>
+  }<br>
+  if (!client_index_callbacks || index_callbacks_size == 0) {<br>
+    ITUI->result = CXError_InvalidArguments;<br>
     return;<br>
+  }<br>
<br>
   IndexerCallbacks CB;<br>
   memset(&CB, 0, sizeof(CB));<br>
@@ -671,13 +677,18 @@ static void clang_indexSourceFile_Impl(v<br>
   if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())<br>
     printDiagsToStderr(Unit);<br>
<br>
+  if (isASTReadError(Unit)) {<br>
+    ITUI->result = CXError_ASTReadError;<br>
+    return;<br>
+  }<br>
+<br>
   if (!Success)<br>
     return;<br>
<br>
   if (out_TU)<br>
     *out_TU = CXTU->takeTU();<br>
<br>
-  ITUI->result = 0; // success.<br>
+  ITUI->result = CXError_Success;<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
@@ -754,14 +765,20 @@ static void clang_indexTranslationUnit_I<br>
   IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;<br>
   unsigned index_callbacks_size = ITUI->index_callbacks_size;<br>
   unsigned index_options = ITUI->index_options;<br>
-  ITUI->result = 1; // init as error.<br>
<br>
+  // Set up the initial return value.<br>
+  ITUI->result = CXError_Failure;<br>
+<br>
+  // Check arguments.<br>
   if (isNotUsableTU(TU)) {<br>
     LOG_BAD_TU(TU);<br>
+    ITUI->result = CXError_InvalidArguments;<br>
     return;<br>
   }<br>
-  if (!client_index_callbacks || index_callbacks_size == 0)<br>
+  if (!client_index_callbacks || index_callbacks_size == 0) {<br>
+    ITUI->result = CXError_InvalidArguments;<br>
     return;<br>
+  }<br>
<br>
   CIndexer *CXXIdx = TU->CIdx;<br>
   if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))<br>
@@ -809,7 +826,7 @@ static void clang_indexTranslationUnit_I<br>
   indexTranslationUnit(*Unit, *IndexCtx);<br>
   indexDiagnostics(TU, *IndexCtx);<br>
<br>
-  ITUI->result = 0;<br>
+  ITUI->result = CXError_Success;<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
@@ -981,7 +998,8 @@ int clang_indexSourceFile(CXIndexAction<br>
                                index_callbacks_size, index_options,<br>
                                source_filename, command_line_args,<br>
                                num_command_line_args, unsaved_files,<br>
-                               num_unsaved_files, out_TU, TU_options, 0 };<br>
+                               num_unsaved_files, out_TU, TU_options,<br>
+                               CXError_Failure };<br>
<br>
   if (getenv("LIBCLANG_NOTHREADS")) {<br>
     clang_indexSourceFile_Impl(&ITUI);<br>
<br>
Modified: cfe/trunk/tools/libclang/libclang.exports<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=201249&r1=201248&r2=201249&view=diff" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=201249&r1=201248&r2=201249&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/tools/libclang/libclang.exports (original)<br>
+++ cfe/trunk/tools/libclang/libclang.exports Wed Feb 12 13:12:37 2014<br>
@@ -87,6 +87,7 @@ clang_constructUSR_ObjCProtocol<br>
 clang_createCXCursorSet<br>
 clang_createIndex<br>
 clang_createTranslationUnit<br>
+clang_createTranslationUnit2<br>
 clang_createTranslationUnitFromSourceFile<br>
 clang_defaultCodeCompleteOptions<br>
 clang_defaultDiagnosticDisplayOptions<br>
@@ -262,6 +263,7 @@ clang_loadDiagnostics<br>
 clang_Location_isInSystemHeader<br>
 clang_Location_isFromMainFile<br>
 clang_parseTranslationUnit<br>
+clang_parseTranslationUnit2<br>
 clang_remap_dispose<br>
 clang_remap_getFilenames<br>
 clang_remap_getNumFiles<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu" class="cremed">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank" class="cremed">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>