Author: klimek Date: Tue Mar 1 04:56:19 2016 New Revision: 262318 URL: http://llvm.org/viewvc/llvm-project?rev=262318&view=rev Log: Optionally demote fatal errors to non-fatal errors.
This behavior is enabled when the new CXTranslationUnit_KeepGoing option is passed to clang_parseTranslationUnit{,2}. It is geared towards use by IDEs and similar consumers of the clang-c API where fatal errors may arise when parsing incomplete code mid-edit, or when include paths are not properly configured yet. In such situations one still wants to get as much information as possible about a TU. Previously, the semantic analysis would not instantiate templates or report additional fatal errors after the first fatal error was encountered. Fixes PR24268. Patch by Milian Wolff. Added: cfe/trunk/test/Index/keep-going.cpp Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/include/clang/Basic/Diagnostic.h cfe/trunk/lib/Basic/Diagnostic.cpp cfe/trunk/lib/Basic/DiagnosticIDs.cpp cfe/trunk/tools/c-index-test/c-index-test.c cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/unittests/Basic/DiagnosticTest.cpp Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Tue Mar 1 04:56:19 2016 @@ -1208,7 +1208,18 @@ enum CXTranslationUnit_Flags { * trades runtime on the first parse (serializing the preamble takes time) for * reduced runtime on the second parse (can now reuse the preamble). */ - CXTranslationUnit_CreatePreambleOnFirstParse = 0x100 + CXTranslationUnit_CreatePreambleOnFirstParse = 0x100, + + /** + * \brief Do not stop processing when fatal errors are encountered. + * + * When fatal errors are encountered while parsing a translation unit, + * semantic analysis is typically stopped early when compiling code. A common + * source for fatal errors are unresolvable include files. For the + * purposes of an IDE, this is undesirable behavior and as much information + * as possible should be reported. Use this flag to enable this behavior. + */ + CXTranslationUnit_KeepGoing = 0x200 }; /** Modified: cfe/trunk/include/clang/Basic/Diagnostic.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Diagnostic.h (original) +++ cfe/trunk/include/clang/Basic/Diagnostic.h Tue Mar 1 04:56:19 2016 @@ -173,6 +173,7 @@ private: bool WarningsAsErrors; // Treat warnings like errors. bool EnableAllWarnings; // Enable all warnings. bool ErrorsAsFatal; // Treat errors like fatal errors. + bool FatalsAsError; // Treat fatal errors like errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. bool ElideType; // Elide common types of templates. @@ -455,6 +456,12 @@ public: void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; } bool getErrorsAsFatal() const { return ErrorsAsFatal; } + /// \brief When set to true, any fatal error reported is made an error. + /// + /// This setting takes precedence over the setErrorsAsFatal setting above. + void setFatalsAsError(bool Val) { FatalsAsError = Val; } + bool getFatalsAsError() const { return FatalsAsError; } + /// \brief When set to true mask warnings that come from system headers. void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; } bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; } Modified: cfe/trunk/lib/Basic/Diagnostic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/lib/Basic/Diagnostic.cpp (original) +++ cfe/trunk/lib/Basic/Diagnostic.cpp Tue Mar 1 04:56:19 2016 @@ -68,6 +68,7 @@ DiagnosticsEngine::DiagnosticsEngine( WarningsAsErrors = false; EnableAllWarnings = false; ErrorsAsFatal = false; + FatalsAsError = false; SuppressSystemWarnings = false; SuppressAllDiagnostics = false; ElideType = true; Modified: cfe/trunk/lib/Basic/DiagnosticIDs.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/DiagnosticIDs.cpp?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/lib/Basic/DiagnosticIDs.cpp (original) +++ cfe/trunk/lib/Basic/DiagnosticIDs.cpp Tue Mar 1 04:56:19 2016 @@ -462,6 +462,12 @@ DiagnosticIDs::getDiagnosticSeverity(uns Result = diag::Severity::Fatal; } + // If explicitly requested, map fatal errors to errors. + if (Result == diag::Severity::Fatal) { + if (Diag.FatalsAsError) + Result = diag::Severity::Error; + } + // Custom diagnostics always are emitted in system headers. bool ShowInSystemHeader = !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; Added: cfe/trunk/test/Index/keep-going.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/keep-going.cpp?rev=262318&view=auto ============================================================================== --- cfe/trunk/test/Index/keep-going.cpp (added) +++ cfe/trunk/test/Index/keep-going.cpp Tue Mar 1 04:56:19 2016 @@ -0,0 +1,29 @@ +#include "missing1.h" + +template<class T> +class A { T a; }; + +class B : public A<int> { }; + +#include "missing2.h" + +class C : public A<float> { }; + +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_KEEP_GOING=1 c-index-test -test-print-type %s 2> %t.stderr.txt | FileCheck %s +// RUN: FileCheck -check-prefix CHECK-DIAG %s < %t.stderr.txt + +// CHECK: inclusion directive=missing1.h ((null)) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: inclusion directive=missing2.h ((null)) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: ClassTemplate=A:4:7 (Definition) [type=] [typekind=Invalid] [isPOD=0] +// CHECK: TemplateTypeParameter=T:3:16 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: FieldDecl=a:4:13 (Definition) [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: TypeRef=T:3:16 [type=T] [typekind=Unexposed] [canonicaltype=type-parameter-0-0] [canonicaltypekind=Unexposed] [isPOD=0] +// CHECK: ClassDecl=B:6:7 (Definition) [type=B] [typekind=Record] [isPOD=0] +// CHECK: C++ base class specifier=A<int>:4:7 [access=public isVirtual=false] [type=A<int>] [typekind=Unexposed] [canonicaltype=A<int>] [canonicaltypekind=Record] [templateargs/1= [type=int] [typekind=Int]] [isPOD=0] [nbFields=1] +// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0] +// CHECK: ClassDecl=C:10:7 (Definition) [type=C] [typekind=Record] [isPOD=0] +// CHECK: C++ base class specifier=A<float>:4:7 [access=public isVirtual=false] [type=A<float>] [typekind=Unexposed] [canonicaltype=A<float>] [canonicaltypekind=Record] [templateargs/1= [type=float] [typekind=Float]] [isPOD=0] [nbFields=1] +// CHECK: TemplateRef=A:4:7 [type=] [typekind=Invalid] [isPOD=0] + +// CHECK-DIAG: keep-going.cpp:1:10: error: 'missing1.h' file not found +// CHECK-DIAG: keep-going.cpp:8:10: error: 'missing2.h' file not found 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=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/tools/c-index-test/c-index-test.c (original) +++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Mar 1 04:56:19 2016 @@ -80,6 +80,8 @@ static unsigned getDefaultParsingOptions options |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion; if (getenv("CINDEXTEST_CREATE_PREAMBLE_ON_FIRST_PARSE")) options |= CXTranslationUnit_CreatePreambleOnFirstParse; + if (getenv("CINDEXTEST_KEEP_GOING")) + options |= CXTranslationUnit_KeepGoing; return options; } Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Tue Mar 1 04:56:19 2016 @@ -3158,6 +3158,9 @@ clang_parseTranslationUnit_Impl(CXIndex IntrusiveRefCntPtr<DiagnosticsEngine> Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); + if (options & CXTranslationUnit_KeepGoing) + Diags->setFatalsAsError(true); + // Recover resources if we crash before exiting this function. llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > Modified: cfe/trunk/unittests/Basic/DiagnosticTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Basic/DiagnosticTest.cpp?rev=262318&r1=262317&r2=262318&view=diff ============================================================================== --- cfe/trunk/unittests/Basic/DiagnosticTest.cpp (original) +++ cfe/trunk/unittests/Basic/DiagnosticTest.cpp Tue Mar 1 04:56:19 2016 @@ -46,4 +46,27 @@ TEST(DiagnosticTest, suppressAndTrap) { EXPECT_FALSE(Diags.hasUnrecoverableErrorOccurred()); } +// Check that FatalsAsErrors works as intended +TEST(DiagnosticTest, fatalsAsErrors) { + DiagnosticsEngine Diags(new DiagnosticIDs(), + new DiagnosticOptions, + new IgnoringDiagConsumer()); + Diags.setFatalsAsError(true); + + // Diag that would set UncompilableErrorOccurred and ErrorOccurred. + Diags.Report(diag::err_target_unknown_triple) << "unknown"; + + // Diag that would set UnrecoverableErrorOccurred and ErrorOccurred. + Diags.Report(diag::err_cannot_open_file) << "file" << "error"; + + // Diag that would set FatalErrorOccurred + // (via non-note following a fatal error). + Diags.Report(diag::warn_mt_message) << "warning"; + + EXPECT_TRUE(Diags.hasErrorOccurred()); + EXPECT_FALSE(Diags.hasFatalErrorOccurred()); + EXPECT_TRUE(Diags.hasUncompilableErrorOccurred()); + EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred()); +} + } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits