diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -26,7 +26,7 @@ def warn_fe_linking_module : Warning<"linking module '%0': %1">, InGroup; def note_fe_linking_module : Note<"linking module '%0': %1">; -def warn_fe_frame_larger_than : Warning<"stack frame size (%0) exceeds limit (%1) in %q2">, +def warn_fe_frame_larger_than : Warning<"stack frame size (%0) exceeds limit (%1) in '%2'">, BackendInfo, InGroup; def warn_fe_backend_frame_larger_than: Warning<"%0">, BackendInfo, InGroup; diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -25,6 +25,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/Hashing.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/Demangle/Demangle.h" @@ -125,6 +126,8 @@ std::unique_ptr Gen; SmallVector LinkModules; + std::vector> + ManglingFullSourceLocs; // This is here so that the diagnostic printer knows the module a diagnostic // refers to. @@ -330,6 +333,14 @@ if (LinkInModules()) return; + for (auto &F : getModule()->functions()) { + if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { + auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + auto NameHash = llvm::hash_value(F.getName()); + ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); + } + } + EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, @@ -376,6 +387,8 @@ bool &BadDebugInfo, StringRef &Filename, unsigned &Line, unsigned &Column) const; + Optional getFunctionSourceLocation(const Function &F) const; + void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); /// Specialized handler for InlineAsm diagnostic. /// \return True if the diagnostic has been successfully reported, false @@ -569,17 +582,16 @@ // We do not know how to format other severities. return false; - if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { - // FIXME: Shouldn't need to truncate to uint32_t - Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), - diag::warn_fe_frame_larger_than) - << static_cast(D.getStackSize()) - << static_cast(D.getStackLimit()) - << Decl::castToDeclContext(ND); - return true; - } + auto Loc = getFunctionSourceLocation(D.getFunction()); + if (!Loc) + return false; - return false; + // FIXME: Shouldn't need to truncate to uint32_t + Diags.Report(*Loc, diag::warn_fe_frame_larger_than) + << static_cast(D.getStackSize()) + << static_cast(D.getStackLimit()) + << llvm::demangle(D.getFunction().getName().str()); + return true; } const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( @@ -608,9 +620,10 @@ // function definition. We use the definition's right brace to differentiate // from diagnostics that genuinely relate to the function itself. FullSourceLoc Loc(DILoc, SourceMgr); - if (Loc.isInvalid()) - if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) - Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + if (Loc.isInvalid()) { + if (auto MaybeLoc = getFunctionSourceLocation(D.getFunction())) + Loc = *MaybeLoc; + } if (DILoc.isInvalid() && D.isLocationAvailable()) // If we were not able to translate the file:line:col information @@ -623,6 +636,16 @@ return Loc; } +Optional +BackendConsumer::getFunctionSourceLocation(const Function &F) const { + auto Hash = llvm::hash_value(F.getName()); + for (const auto &Pair : ManglingFullSourceLocs) { + if (Pair.first == Hash) + return Pair.second; + } + return Optional(); +} + void BackendConsumer::UnsupportedDiagHandler( const llvm::DiagnosticInfoUnsupported &D) { // We only support warnings or errors. diff --git a/clang/test/Frontend/backend-diagnostic.c b/clang/test/Frontend/backend-diagnostic.c --- a/clang/test/Frontend/backend-diagnostic.c +++ b/clang/test/Frontend/backend-diagnostic.c @@ -15,9 +15,9 @@ extern void doIt(char *); -// REGULAR: warning: stack frame size ([[#]]) exceeds limit ([[#]]) in function 'stackSizeWarning' -// PROMOTE: error: stack frame size ([[#]]) exceeds limit ([[#]]) in function 'stackSizeWarning' -// IGNORE-NOT: stack frame size ([[#]]) exceeds limit ([[#]]) in function 'stackSizeWarning' +// REGULAR: warning: stack frame size ([[#]]) exceeds limit ([[#]]) in 'stackSizeWarning' +// PROMOTE: error: stack frame size ([[#]]) exceeds limit ([[#]]) in 'stackSizeWarning' +// IGNORE-NOT: stack frame size ([[#]]) exceeds limit ([[#]]) in 'stackSizeWarning' void stackSizeWarning() { char buffer[80]; doIt(buffer); diff --git a/clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp b/clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp --- a/clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp +++ b/clang/test/Misc/backend-stack-frame-diagnostics-fallback.cpp @@ -12,7 +12,7 @@ virtual void f(); }; - // CHECK: warning: stack frame size ([[#]]) exceeds limit ([[#]]) in function 'frameSizeThunkWarning::B::f' + // CHECK: warning: stack frame size ([[#]]) exceeds limit ([[#]]) in 'frameSizeThunkWarning::B::f()' // CHECK: warning: stack frame size ([[#]]) exceeds limit ([[#]]) in function '_ZTv0_n12_N21frameSizeThunkWarning1B1fEv' void B::f() { volatile int x = 0; // Ensure there is stack usage. diff --git a/clang/test/Misc/backend-stack-frame-diagnostics.cpp b/clang/test/Misc/backend-stack-frame-diagnostics.cpp --- a/clang/test/Misc/backend-stack-frame-diagnostics.cpp +++ b/clang/test/Misc/backend-stack-frame-diagnostics.cpp @@ -26,7 +26,7 @@ void frameSizeWarning(); -void frameSizeWarning() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in function 'frameSizeWarning'}} +void frameSizeWarning() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in 'frameSizeWarning()'}} char buffer[80]; doIt(buffer); } @@ -45,7 +45,7 @@ void frameSizeLocalClassWarning() { struct S { - S() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in function 'frameSizeLocalClassWarning()::S::S'}} + S() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in 'frameSizeLocalClassWarning()::S::S()'}} char buffer[80]; doIt(buffer); } @@ -55,7 +55,7 @@ void frameSizeLambdaWarning() { auto fn = - []() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in lambda expression}} + []() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in 'frameSizeLambdaWarning()::$_0::operator()() const'}} char buffer[80]; doIt(buffer); }; @@ -64,7 +64,7 @@ void frameSizeBlocksWarning() { auto fn = - ^() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in block literal}} + ^() { // expected-warning-re {{stack frame size ({{[0-9]+}}) exceeds limit ({{[0-9]+}}) in 'invocation function for block in frameSizeBlocksWarning()'}} char buffer[80]; doIt(buffer); };