Index: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td @@ -58,8 +58,10 @@ BackendInfo, InGroup; def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo, InGroup, DefaultWarn; -def note_fe_backend_optimization_remark_invalid_loc : Note<"could " - "not determine the original source location for %0:%1:%2">; +def note_fe_backend_invalid_loc : Note<"could " + "not determine the original source location for %0:%1:%2">, BackendInfo; + +def err_fe_backend_unsupported : Error<"%0">, BackendInfo; def remark_sanitize_address_insert_extra_padding_accepted : Remark< "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader, Index: cfe/trunk/lib/CodeGen/CodeGenAction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenAction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp @@ -242,6 +242,13 @@ ((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI); } + /// Get the best possible source location to represent a diagnostic that + /// may have associated debug info. + const FullSourceLoc + getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithDebugLocBase &D, + bool &BadDebugInfo, StringRef &Filename, + unsigned &Line, unsigned &Column) const; + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, SourceLocation LocCookie); @@ -254,6 +261,8 @@ /// \return True if the diagnostic has been successfully reported, false /// otherwise. bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); + /// \brief Specialized handler for unsupported backend feature diagnostic. + void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); /// \brief Specialized handlers for optimization remarks. /// Note that these handlers only accept remarks and they always handle /// them. @@ -439,16 +448,11 @@ return false; } -void BackendConsumer::EmitOptimizationMessage( - const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { - // We only support warnings and remarks. - assert(D.getSeverity() == llvm::DS_Remark || - D.getSeverity() == llvm::DS_Warning); - +const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( + const llvm::DiagnosticInfoWithDebugLocBase &D, bool &BadDebugInfo, StringRef &Filename, + unsigned &Line, unsigned &Column) const { SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); - StringRef Filename; - unsigned Line, Column; SourceLocation DILoc; if (D.isLocationAvailable()) { @@ -459,6 +463,7 @@ // source manager, so pass 1 if Column is not set. DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); } + BadDebugInfo = DILoc.isInvalid(); } // If a location isn't available, try to approximate it using the associated @@ -467,18 +472,63 @@ FullSourceLoc Loc(DILoc, SourceMgr); if (Loc.isInvalid()) if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) - Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace()); + Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + + if (DILoc.isInvalid() && D.isLocationAvailable()) + // If we were not able to translate the file:line:col information + // back to a SourceLocation, at least emit a note stating that + // we could not translate this location. This can happen in the + // case of #line directives. + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) + << Filename << Line; + + return Loc; +} + +void BackendConsumer::UnsupportedDiagHandler( + const llvm::DiagnosticInfoUnsupported &D) { + // We only support errors. + assert(D.getSeverity() == llvm::DS_Error); + + StringRef Filename; + unsigned Line, Column; + bool BadDebugInfo; + FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, + Line, Column); + + Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); + + if (BadDebugInfo) + // If we were not able to translate the file:line:col information + // back to a SourceLocation, at least emit a note stating that + // we could not translate this location. This can happen in the + // case of #line directives. + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) + << Filename << Line << Column; +} + +void BackendConsumer::EmitOptimizationMessage( + const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { + // We only support warnings and remarks. + assert(D.getSeverity() == llvm::DS_Remark || + D.getSeverity() == llvm::DS_Warning); + + StringRef Filename; + unsigned Line, Column; + bool BadDebugInfo = false; + FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, + Line, Column); Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName() ? D.getPassName() : "") << D.getMsg().str(); - if (DILoc.isInvalid() && D.isLocationAvailable()) + if (BadDebugInfo) // If we were not able to translate the file:line:col information // back to a SourceLocation, at least emit a note stating that // we could not translate this location. This can happen in the // case of #line directives. - Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc) + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) << Filename << Line << Column; } @@ -603,6 +653,9 @@ // handler. OptimizationFailureHandler(cast(DI)); return; + case llvm::DK_Unsupported: + UnsupportedDiagHandler(cast(DI)); + return; default: // Plugin IDs are not bound to any value as they are set dynamically. ComputeDiagRemarkID(Severity, backend_plugin, DiagID); Index: cfe/trunk/test/CodeGen/backend-unsupported-error.ll =================================================================== --- cfe/trunk/test/CodeGen/backend-unsupported-error.ll +++ cfe/trunk/test/CodeGen/backend-unsupported-error.ll @@ -0,0 +1,45 @@ +; RUN: not %clang_cc1 -triple r600-unknown-unknown -S -o - %s 2>&1 | FileCheck %s +; REQUIRES: amdgpu-registered-target + +; This is to check that backend errors for unsupported features are formatted correctly + +; CHECK: error: test.c:2:20: in function bar i32 (): unsupported call to function foo.2 + +target triple = "r600-unknown-unknown" + +; Function Attrs: nounwind uwtable +define i32 @bar() #0 !dbg !4 { +entry: + %call = call i32 @foo(), !dbg !12 + ret i32 %call, !dbg !13 +} + +; Function Attrs: nounwind uwtable +define i32 @foo() #0 !dbg !8 { +entry: + %call = call i32 @bar(), !dbg !14 + ret i32 %call, !dbg !15 +} + +attributes #0 = { nounwind uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9, !10} +!llvm.ident = !{!11} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3) +!1 = !DIFile(filename: "test.c", directory: "") +!2 = !{} +!3 = !{!4, !8} +!4 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, variables: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{!7} +!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!8 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, variables: !2) +!9 = !{i32 2, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{!"clang version 3.9.0"} +!12 = !DILocation(line: 2, column: 20, scope: !4) +!13 = !DILocation(line: 2, column: 13, scope: !4) +!14 = !DILocation(line: 3, column: 20, scope: !8) +!15 = !DILocation(line: 3, column: 13, scope: !8) Index: cfe/trunk/test/Frontend/optimization-remark-analysis.c =================================================================== --- cfe/trunk/test/Frontend/optimization-remark-analysis.c +++ cfe/trunk/test/Frontend/optimization-remark-analysis.c @@ -1,8 +1,8 @@ // RUN: %clang -O1 -fvectorize -target x86_64-unknown-unknown -emit-llvm -Rpass-analysis -S %s -o - 2>&1 | FileCheck %s --check-prefix=RPASS // RUN: %clang -O1 -fvectorize -target x86_64-unknown-unknown -emit-llvm -S %s -o - 2>&1 | FileCheck %s -// RPASS: {{.*}}:21:1: remark: loop not vectorized: loop contains a switch statement -// CHECK-NOT: {{.*}}:21:1: remark: loop not vectorized: loop contains a switch statement +// RPASS: {{.*}}:7:8: remark: loop not vectorized: loop contains a switch statement +// CHECK-NOT: {{.*}}:7:8: remark: loop not vectorized: loop contains a switch statement double foo(int N, int *Array) { double v = 0.0; Index: cfe/trunk/test/Misc/backend-optimization-failure-nodbg.cpp =================================================================== --- cfe/trunk/test/Misc/backend-optimization-failure-nodbg.cpp +++ cfe/trunk/test/Misc/backend-optimization-failure-nodbg.cpp @@ -4,7 +4,7 @@ // Test verifies optimization failures generated by the backend are handled // correctly by clang. LLVM tests verify all of the failure conditions. -void test_switch(int *A, int *B, int Length) { +void test_switch(int *A, int *B, int Length) { /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */ #pragma clang loop vectorize(enable) unroll(disable) for (int i = 0; i < Length; i++) { switch (A[i]) { @@ -18,4 +18,4 @@ B[i] = 3; } } -/* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */ } +}