diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -54,6 +54,7 @@ CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none +CODEGENOPT(ClearASTBeforeBackend , 1, 1) ///< Free the AST before running backend code generation. Only works with -disable-free. CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag) CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get 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/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5298,6 +5298,12 @@ def disable_free : Flag<["-"], "disable-free">, HelpText<"Disable freeing of memory on exit">, MarshallingInfoFlag>; +def clear_ast_before_backend : Flag<["-"], "clear-ast-before-backend">, + HelpText<"Clear the Clang AST before running backend code generation">, + MarshallingInfoFlag>; +def no_clear_ast_before_backend : Flag<["-"], "no-clear-ast-before-backend">, + HelpText<"Do not clear the Clang AST before running backend code generation">, + MarshallingInfoNegativeFlag>; def enable_noundef_analysis : Flag<["-"], "enable-noundef-analysis">, Group, HelpText<"Enable analyzing function argument and return types for mandatory definedness">, MarshallingInfoFlag>; 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 @@ -27,6 +27,7 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -124,6 +125,8 @@ std::unique_ptr Gen; SmallVector LinkModules; + llvm::StringMap + ManglingFullSourceLocs; // This is here so that the diagnostic printer knows the module a diagnostic // refers to. @@ -329,6 +332,18 @@ if (LinkInModules()) return; + for (auto &F : getModule()->functions()) { + if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { + auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + ManglingFullSourceLocs[F.getName()] = Loc; + } + } + + // FIXME: Fix cleanup issues with clearing the AST when we properly free + // things. + if (CodeGenOpts.DisableFree && CodeGenOpts.ClearASTBeforeBackend) + C.getAllocator().Reset(); + EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, @@ -568,17 +583,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 Find = ManglingFullSourceLocs.find(D.getFunction().getName()); + if (Find == ManglingFullSourceLocs.end()) + return false; - return false; + // FIXME: Shouldn't need to truncate to uint32_t + Diags.Report(Find->getValue(), 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( @@ -607,9 +621,11 @@ // 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()) { + auto Find = ManglingFullSourceLocs.find(D.getFunction().getName()); + if (Find != ManglingFullSourceLocs.end()) + Loc = Find->getValue(); + } if (DILoc.isInvalid() && D.isLocationAvailable()) // If we were not able to translate the file:line:col information diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -182,6 +182,7 @@ llvm::Expected> Interpreter::create(std::unique_ptr CI) { llvm::Error Err = llvm::Error::success(); + CI->getCodeGenOpts().ClearASTBeforeBackend = false; auto Interp = std::unique_ptr(new Interpreter(std::move(CI), Err)); if (Err) 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()()}} 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); };