19
19
#include " swift/AST/DebuggerClient.h"
20
20
#include " swift/AST/Decl.h"
21
21
#include " swift/AST/DiagnosticEngine.h"
22
+ #include " swift/AST/DiagnosticsClangImporter.h"
22
23
#include " swift/AST/DiagnosticsSema.h"
23
24
#include " swift/AST/ExistentialLayout.h"
24
25
#include " swift/AST/GenericParamList.h"
@@ -2307,7 +2308,7 @@ Status SwiftASTContext::GetAllErrors() const {
2307
2308
if (error.Success ()) {
2308
2309
// Retrieve the error message from the DiagnosticConsumer.
2309
2310
DiagnosticManager diagnostic_manager;
2310
- PrintDiagnostics (diagnostic_manager);
2311
+ PrintDiagnostics (diagnostic_manager, true );
2311
2312
error.SetErrorString (diagnostic_manager.GetString ());
2312
2313
}
2313
2314
return error;
@@ -2731,6 +2732,7 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2731
2732
m_ast_context.GetDiagnosticEngine ().takeConsumers ();
2732
2733
}
2733
2734
2735
+ // / Consume a Diagnostic from the Swift compiler.
2734
2736
void handleDiagnostic (swift::SourceManager &source_mgr,
2735
2737
const swift::DiagnosticInfo &info) override {
2736
2738
llvm::StringRef bufferName = " <anonymous>" ;
@@ -2786,9 +2788,9 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2786
2788
// related to the same error, but we only copy the first one as the fixits
2787
2789
// are mutually exclusive (for example, one may suggest inserting a '?'
2788
2790
// and the next may suggest inserting '!')
2789
- if (!m_raw_diagnostics. empty () &&
2790
- info. Kind == swift::DiagnosticKind::Note ) {
2791
- auto &last_diagnostic = m_raw_diagnostics .back ();
2791
+ if (info. Kind == swift::DiagnosticKind::Note &&
2792
+ !m_raw_swift_diagnostics. empty () ) {
2793
+ auto &last_diagnostic = m_raw_swift_diagnostics .back ();
2792
2794
if (last_diagnostic.kind == swift::DiagnosticKind::Error &&
2793
2795
last_diagnostic.fixits .empty () &&
2794
2796
last_diagnostic.bufferID == bufferID &&
@@ -2817,32 +2819,40 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2817
2819
std::string &s = os.str ();
2818
2820
formatted_text = !s.empty () ? std::move (s) : std::string (text);
2819
2821
}
2820
- m_raw_diagnostics.push_back (
2821
- {formatted_text, info.Kind , bufferName, bufferID, line_col.first ,
2822
- line_col.second ,
2823
- use_fixits ? info.FixIts
2824
- : llvm::ArrayRef<swift::Diagnostic::FixIt>()});
2825
-
2826
- if (info.Kind == swift::DiagnosticKind::Error)
2827
- m_num_errors++;
2822
+ RawDiagnostic diagnostic (
2823
+ formatted_text, info.Kind , bufferName, bufferID, line_col.first ,
2824
+ line_col.second ,
2825
+ use_fixits ? info.FixIts : llvm::ArrayRef<swift::Diagnostic::FixIt>());
2826
+ if (info.ID == swift::diag::error_from_clang.ID ) {
2827
+ if (m_raw_clang_diagnostics.empty () ||
2828
+ m_raw_clang_diagnostics.back () != diagnostic) {
2829
+ m_raw_clang_diagnostics.push_back (std::move (diagnostic));
2830
+ if (info.Kind == swift::DiagnosticKind::Error)
2831
+ m_num_clang_errors++;
2832
+ }
2833
+ } else {
2834
+ m_raw_swift_diagnostics.push_back (std::move (diagnostic));
2835
+ if (info.Kind == swift::DiagnosticKind::Error)
2836
+ m_num_swift_errors++;
2837
+ }
2828
2838
}
2829
2839
2830
2840
void Clear () {
2831
2841
m_ast_context.GetDiagnosticEngine ().resetHadAnyError ();
2832
- m_raw_diagnostics .clear ();
2842
+ m_raw_swift_diagnostics .clear ();
2833
2843
m_diagnostics.clear ();
2834
- m_num_errors = 0 ;
2844
+ m_num_swift_errors = 0 ;
2845
+ // Don't reset Clang errors. ClangImporter's DiagnosticEngine doesn't either.
2835
2846
}
2836
2847
2837
2848
unsigned NumErrors () {
2838
- if (m_num_errors)
2839
- return m_num_errors;
2840
- else if (m_ast_context.GetASTContext ()->hadError ())
2841
- return 1 ;
2842
- else
2843
- return 0 ;
2849
+ if (m_num_swift_errors)
2850
+ return m_num_swift_errors;
2851
+ return m_ast_context.GetASTContext ()->hadError ();
2844
2852
}
2845
2853
2854
+ unsigned NumClangErrors () { return m_num_clang_errors; }
2855
+
2846
2856
static DiagnosticSeverity SeverityForKind (swift::DiagnosticKind kind) {
2847
2857
switch (kind) {
2848
2858
case swift::DiagnosticKind::Error:
@@ -2857,93 +2867,101 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2857
2867
llvm_unreachable (" Unhandled DiagnosticKind in switch." );
2858
2868
}
2859
2869
2870
+ // Forward the stored diagnostics to \c diagnostic_manager.
2860
2871
void PrintDiagnostics (DiagnosticManager &diagnostic_manager,
2861
2872
uint32_t bufferID = UINT32_MAX, uint32_t first_line = 0 ,
2862
2873
uint32_t last_line = UINT32_MAX) {
2863
2874
bool added_one_diagnostic = !m_diagnostics.empty ();
2864
2875
2865
- for (std::unique_ptr<Diagnostic> &diagnostic : m_diagnostics) {
2876
+ for (std::unique_ptr<Diagnostic> &diagnostic : m_diagnostics)
2866
2877
diagnostic_manager.AddDiagnostic (std::move (diagnostic));
2867
- }
2868
2878
2869
- for (const RawDiagnostic &diagnostic : m_raw_diagnostics) {
2870
- // We often make expressions and wrap them in some code. When
2871
- // we see errors we want the line numbers to be correct so we
2872
- // correct them below. LLVM stores in SourceLoc objects as
2873
- // character offsets so there is no way to get LLVM to move its
2874
- // error line numbers around by adjusting the source location,
2875
- // we must do it manually. We also want to use the same error
2876
- // formatting as LLVM and Clang, so we must muck with the
2877
- // string.
2879
+ // We often make expressions and wrap them in some code. When we
2880
+ // see errors we want the line numbers to be correct so we correct
2881
+ // them below. LLVM stores in SourceLoc objects as character
2882
+ // offsets so there is no way to get LLVM to move its error line
2883
+ // numbers around by adjusting the source location, we must do it
2884
+ // manually. We also want to use the same error formatting as LLVM
2885
+ // and Clang, so we must muck with the string.
2878
2886
2887
+ auto format_diagnostic = [&](const RawDiagnostic &diagnostic) {
2879
2888
const DiagnosticSeverity severity = SeverityForKind (diagnostic.kind );
2880
2889
const DiagnosticOrigin origin = eDiagnosticOriginSwift;
2881
2890
2882
- if (first_line > 0 && bufferID != UINT32_MAX) {
2883
- // Make sure the error line is in range or in another file.
2884
- if (diagnostic.bufferID == bufferID && !diagnostic.bufferName .empty () &&
2885
- (diagnostic.line < first_line || diagnostic.line > last_line))
2886
- continue ;
2887
- // Need to remap the error/warning to a different line.
2888
- StreamString match;
2889
- match.Printf (" %s:%u:" , diagnostic.bufferName .str ().c_str (),
2890
- diagnostic.line );
2891
- const size_t match_len = match.GetString ().size ();
2892
- size_t match_pos = diagnostic.description .find (match.GetString ().str ());
2893
- if (match_pos != std::string::npos) {
2894
- // We have some <file>:<line>:" instances that need to be updated.
2895
- StreamString fixed_description;
2896
- size_t start_pos = 0 ;
2897
- do {
2898
- if (match_pos > start_pos)
2899
- fixed_description.Printf (
2900
- " %s" ,
2901
- diagnostic.description .substr (start_pos, match_pos).c_str ());
2902
- fixed_description.Printf (
2903
- " %s:%u:" , diagnostic.bufferName .str ().c_str (),
2904
- diagnostic.line - first_line + 1 );
2905
- start_pos = match_pos + match_len;
2906
- match_pos =
2907
- diagnostic.description .find (match.GetString ().str (), start_pos);
2908
- } while (match_pos != std::string::npos);
2909
-
2910
- // Append any last remaining text.
2911
- if (start_pos < diagnostic.description .size ())
2912
- fixed_description.Printf (
2913
- " %s" , diagnostic.description
2914
- .substr (start_pos,
2915
- diagnostic.description .size () - start_pos)
2916
- .c_str ());
2917
-
2918
- auto new_diagnostic = std::make_unique<SwiftDiagnostic>(
2919
- fixed_description.GetData (), severity, origin, bufferID);
2920
- for (auto fixit : diagnostic.fixits )
2921
- new_diagnostic->AddFixIt (fixit);
2922
-
2923
- diagnostic_manager.AddDiagnostic (std::move (new_diagnostic));
2924
- if (diagnostic.kind == swift::DiagnosticKind::Error)
2925
- added_one_diagnostic = true ;
2891
+ if ((first_line <= 0 ) || (bufferID == UINT32_MAX))
2892
+ return ;
2893
+
2894
+ // Make sure the error line is in range or in another file.
2895
+ if (diagnostic.bufferID == bufferID && !diagnostic.bufferName .empty () &&
2896
+ (diagnostic.line < first_line || diagnostic.line > last_line))
2897
+ return ;
2926
2898
2927
- }
2928
- }
2929
- }
2899
+ // Need to remap the error/warning to a different line.
2900
+ StreamString match;
2901
+ match.Printf (" %s:%u:" , diagnostic.bufferName .str ().c_str (),
2902
+ diagnostic.line );
2903
+ const size_t match_len = match.GetString ().size ();
2904
+ size_t match_pos = diagnostic.description .find (match.GetString ().str ());
2905
+ if (match_pos == std::string::npos)
2906
+ return ;
2907
+
2908
+ // We have some <file>:<line>:" instances that need to be updated.
2909
+ StreamString fixed_description;
2910
+ size_t start_pos = 0 ;
2911
+ do {
2912
+ if (match_pos > start_pos)
2913
+ fixed_description.Printf (
2914
+ " %s" ,
2915
+ diagnostic.description .substr (start_pos, match_pos).c_str ());
2916
+ fixed_description.Printf (" %s:%u:" , diagnostic.bufferName .str ().c_str (),
2917
+ diagnostic.line - first_line + 1 );
2918
+ start_pos = match_pos + match_len;
2919
+ match_pos =
2920
+ diagnostic.description .find (match.GetString ().str (), start_pos);
2921
+ } while (match_pos != std::string::npos);
2922
+
2923
+ // Append any last remaining text.
2924
+ if (start_pos < diagnostic.description .size ())
2925
+ fixed_description.Printf (
2926
+ " %s" ,
2927
+ diagnostic.description
2928
+ .substr (start_pos, diagnostic.description .size () - start_pos)
2929
+ .c_str ());
2930
+
2931
+ auto new_diagnostic = std::make_unique<SwiftDiagnostic>(
2932
+ fixed_description.GetData (), severity, origin, bufferID);
2933
+ for (auto fixit : diagnostic.fixits )
2934
+ new_diagnostic->AddFixIt (fixit);
2935
+
2936
+ diagnostic_manager.AddDiagnostic (std::move (new_diagnostic));
2937
+ if (diagnostic.kind == swift::DiagnosticKind::Error)
2938
+ added_one_diagnostic = true ;
2939
+ };
2940
+
2941
+ for (auto &diag : m_raw_clang_diagnostics)
2942
+ format_diagnostic (diag);
2943
+ for (auto &diag : m_raw_swift_diagnostics)
2944
+ format_diagnostic (diag);
2930
2945
2931
2946
// In general, we don't want to see diagnostics from outside of
2932
- // the source text range of the actual user expression. But if we
2933
- // didn't find any diagnostics in the text range, it's probably
2934
- // because the source range was not specified correctly, and we
2935
- // don't want to lose legit errors because of that. So in that
2936
- // case we'll add them all here:
2947
+ // the source text range of the actual user expression. This
2948
+ // either indicates a bug in LLDB or that there is only a
2949
+ // ClangImporter diagnostic.
2937
2950
if (!added_one_diagnostic) {
2938
2951
// This will report diagnostic errors from outside the
2939
2952
// expression's source range. Those are not interesting to
2940
2953
// users, so we only emit them in debug builds.
2941
- for (const RawDiagnostic &diagnostic : m_raw_diagnostics) {
2942
- const DiagnosticSeverity severity = SeverityForKind (diagnostic.kind );
2943
- const DiagnosticOrigin origin = eDiagnosticOriginSwift;
2954
+ for (const RawDiagnostic &diagnostic : m_raw_clang_diagnostics)
2944
2955
diagnostic_manager.AddDiagnostic (diagnostic.description .c_str (),
2945
- severity, origin);
2946
- }
2956
+ SeverityForKind (diagnostic.kind ),
2957
+ eDiagnosticOriginClang);
2958
+
2959
+ // If we printed a clang error, ignore Swift warnings, which are expected.
2960
+ if (!m_num_clang_errors || m_num_swift_errors)
2961
+ for (const RawDiagnostic &diagnostic : m_raw_swift_diagnostics)
2962
+ diagnostic_manager.AddDiagnostic (diagnostic.description .c_str (),
2963
+ SeverityForKind (diagnostic.kind ),
2964
+ eDiagnosticOriginSwift);
2947
2965
}
2948
2966
}
2949
2967
@@ -2955,6 +2973,7 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2955
2973
return old;
2956
2974
}
2957
2975
2976
+ // / This is only used by ReconstructTypes.
2958
2977
void AddDiagnostic (std::unique_ptr<Diagnostic> diagnostic) {
2959
2978
if (diagnostic)
2960
2979
m_diagnostics.push_back (std::move (diagnostic));
@@ -2973,6 +2992,13 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2973
2992
: description(in_desc), kind(in_kind), bufferName(in_bufferName),
2974
2993
bufferID (in_bufferID), line(in_line), column(in_column),
2975
2994
fixits(in_fixits) {}
2995
+ bool operator ==(const RawDiagnostic& other) {
2996
+ return kind == other.kind && bufferID == other.bufferID &&
2997
+ line == other.line && column == other.column &&
2998
+ description == other.description ;
2999
+ }
3000
+ bool operator !=(const RawDiagnostic &other) { return !(*this == other); }
3001
+
2976
3002
std::string description;
2977
3003
swift::DiagnosticKind kind;
2978
3004
const llvm::StringRef bufferName;
@@ -2981,14 +3007,16 @@ class StoringDiagnosticConsumer : public swift::DiagnosticConsumer {
2981
3007
uint32_t column;
2982
3008
std::vector<swift::DiagnosticInfo::FixIt> fixits;
2983
3009
};
2984
- typedef std::vector<RawDiagnostic> RawDiagnosticBuffer;
2985
- typedef std::vector<std::unique_ptr<Diagnostic>> DiagnosticList;
2986
3010
2987
3011
SwiftASTContext &m_ast_context;
2988
- RawDiagnosticBuffer m_raw_diagnostics;
2989
- DiagnosticList m_diagnostics;
2990
-
2991
- unsigned m_num_errors = 0 ;
3012
+ // / Stores all diagnostics coming from the Swift compiler.
3013
+ std::vector<RawDiagnostic> m_raw_swift_diagnostics;
3014
+ std::vector<RawDiagnostic> m_raw_clang_diagnostics;
3015
+ // / Stores diagnostics coming from LLDB.
3016
+ std::vector<std::unique_ptr<Diagnostic>> m_diagnostics;
3017
+
3018
+ unsigned m_num_swift_errors = 0 ;
3019
+ unsigned m_num_clang_errors = 0 ;
2992
3020
bool m_colorize = false ;
2993
3021
};
2994
3022
@@ -3040,7 +3068,7 @@ swift::ASTContext *SwiftASTContext::GetASTContext() {
3040
3068
m_module_import_warnings.push_back (message);
3041
3069
} else {
3042
3070
DiagnosticManager diagnostic_manager;
3043
- PrintDiagnostics (diagnostic_manager);
3071
+ PrintDiagnostics (diagnostic_manager, true );
3044
3072
std::string underlying_error = diagnostic_manager.GetString ();
3045
3073
message = " failed to initialize ClangImporter: " ;
3046
3074
message += underlying_error;
@@ -3353,7 +3381,7 @@ swift::ModuleDecl *SwiftASTContext::GetModule(const SourceModule &module,
3353
3381
swift::ModuleDecl *module_decl = ast->getModuleByName (module_basename_sref);
3354
3382
if (HasErrors ()) {
3355
3383
DiagnosticManager diagnostic_manager;
3356
- PrintDiagnostics (diagnostic_manager);
3384
+ PrintDiagnostics (diagnostic_manager, true );
3357
3385
std::string diagnostic = diagnostic_manager.GetString ();
3358
3386
error.SetErrorStringWithFormat (
3359
3387
" failed to get module \" %s\" from AST context:\n %s" ,
@@ -4738,8 +4766,14 @@ bool SwiftASTContext::HasErrors() {
4738
4766
return (
4739
4767
static_cast <StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get ())
4740
4768
->NumErrors () != 0 );
4741
- else
4742
- return false ;
4769
+ return false ;
4770
+ }
4771
+ bool SwiftASTContext::HasClangImporterErrors () {
4772
+ if (m_diagnostic_consumer_ap.get ())
4773
+ return (
4774
+ static_cast <StoringDiagnosticConsumer *>(m_diagnostic_consumer_ap.get ())
4775
+ ->NumClangErrors () != 0 );
4776
+ return false ;
4743
4777
}
4744
4778
4745
4779
bool SwiftASTContext::HasFatalErrors (swift::ASTContext *ast_context) {
0 commit comments