r210293 - Implement -Wframe-larger-than backend diagnostic

Alp Toker alp at nuanti.com
Thu Jun 5 15:10:59 PDT 2014


Author: alp
Date: Thu Jun  5 17:10:59 2014
New Revision: 210293

URL: http://llvm.org/viewvc/llvm-project?rev=210293&view=rev
Log:
Implement -Wframe-larger-than backend diagnostic

Add driver and frontend support for the GCC -Wframe-larger-than=bytes warning.
This is the first GCC-compatible backend diagnostic built around LLVM's
reporting feature.

This commit adds infrastructure to perform reverse lookup from mangled names
emitted after LLVM IR generation. We use that to resolve precise locations and
originating AST functions, lambdas or block declarations to produce seamless
codegen-guided diagnostics.

An associated change, StringMap now maintains unique mangled name strings
instead of allocating copies. This is a net memory saving in C++ and a small
hit for C where we no longer reuse IdentifierInfo storage, pending further
optimisation.

Added:
    cfe/trunk/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
    cfe/trunk/test/Misc/backend-stack-frame-diagnostics.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CodeGenAction.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Frontend/backend-diagnostic.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Thu Jun  5 17:10:59 2014
@@ -22,8 +22,9 @@ def note_fe_inline_asm_here : Note<"inst
 def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">,
   DefaultFatal;
 
-def warn_fe_backend_frame_larger_than: Warning<"stack size exceeded (%0) in %1">,
+def warn_fe_frame_larger_than : Warning<"stack frame size of %0 bytes in %q1">,
     CatBackend, InGroup<BackendFrameLargerThan>;
+def warn_fe_backend_frame_larger_than: Warning<"%0">, CatBackend, InGroup<BackendFrameLargerThan>;
 def err_fe_backend_frame_larger_than: Error<"%0">, CatBackend;
 def note_fe_backend_frame_larger_than: Note<"%0">, CatBackend;
 

Modified: cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/ModuleBuilder.h?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/ModuleBuilder.h (original)
+++ cfe/trunk/include/clang/CodeGen/ModuleBuilder.h Thu Jun  5 17:10:59 2014
@@ -27,12 +27,14 @@ namespace clang {
   class LangOptions;
   class CodeGenOptions;
   class TargetOptions;
+  class Decl;
 
   class CodeGenerator : public ASTConsumer {
     virtual void anchor();
   public:
     virtual llvm::Module* GetModule() = 0;
     virtual llvm::Module* ReleaseModule() = 0;
+    virtual const Decl *GetDeclForMangledName(llvm::StringRef MangledName) = 0;
   };
 
   /// CreateLLVMCodeGen - Create a CodeGenerator instance.

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Thu Jun  5 17:10:59 2014
@@ -854,12 +854,12 @@ def Wlarge_by_value_copy_def : Flag<["-"
            "in bytes than a given value">, Flags<[HelpHidden]>;
 def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>;
 
-// Just silence warnings about -Wlarger-than,  -Wframe-larger-than for now.
+// Just silence warnings about -Wlarger-than for now.
 def Wlarger_than : Separate<["-"], "Wlarger-than">, Group<clang_ignored_f_Group>;
 def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Alias<Wlarger_than>;
 def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than>;
-def Wframe_larger_than : Separate<["-"], "Wframe-larger-than">, Group<clang_ignored_f_Group>;
-def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Alias<Wframe_larger_than>;
+def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Flags<[DriverOption]>;
+def Wstack_usage_EQ : Joined<["-"], "Wstack-usage=">, Group<clang_ignored_f_Group>;
 
 def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
 def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group<f_Group>;

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Thu Jun  5 17:10:59 2014
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
@@ -345,7 +346,8 @@ void clang::FormatASTNodeDiagnosticArgum
     case DiagnosticsEngine::ak_declcontext: {
       DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
       assert(DC && "Should never have a null declaration context");
-      
+      NeedQuotes = false;
+
       if (DC->isTranslationUnit()) {
         // FIXME: Get these strings from some localized place
         if (Context.getLangOpts().CPlusPlus)
@@ -359,6 +361,14 @@ void clang::FormatASTNodeDiagnosticArgum
                                             QualTypeVals);
       } else {
         // FIXME: Get these strings from some localized place
+        if (isa<BlockDecl>(DC)) {
+          OS << "block literal";
+          break;
+        }
+        if (isLambdaCallOperator(DC)) {
+          OS << "lambda expression";
+          break;
+        }
         NamedDecl *ND = cast<NamedDecl>(DC);
         if (isa<NamespaceDecl>(ND))
           OS << "namespace ";
@@ -371,7 +381,6 @@ void clang::FormatASTNodeDiagnosticArgum
         ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
         OS << '\'';
       }
-      NeedQuotes = false;
       break;
     }
     case DiagnosticsEngine::ak_attr: {

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Jun  5 17:10:59 2014
@@ -1127,7 +1127,7 @@ CodeGenFunction::GenerateBlockFunction(G
 
   llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
 
-  std::string name = CGM.getBlockMangledName(GD, blockDecl);
+  StringRef name = CGM.getBlockMangledName(GD, blockDecl);
   llvm::Function *fn = llvm::Function::Create(
       fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
   CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Jun  5 17:10:59 2014
@@ -149,12 +149,11 @@ void CodeGenFunction::EmitVarDecl(const
 static std::string GetStaticDeclName(CodeGenFunction &CGF, const VarDecl &D,
                                      const char *Separator) {
   CodeGenModule &CGM = CGF.CGM;
-  if (CGF.getLangOpts().CPlusPlus) {
-    StringRef Name = CGM.getMangledName(&D);
-    return Name.str();
-  }
 
-  std::string ContextName;
+  if (CGF.getLangOpts().CPlusPlus)
+    return CGM.getMangledName(&D).str();
+
+  StringRef ContextName;
   if (!CGF.CurFuncDecl) {
     // Better be in a block declared in global scope.
     const NamedDecl *ND = cast<NamedDecl>(&D);
@@ -163,15 +162,14 @@ static std::string GetStaticDeclName(Cod
       ContextName = CGM.getBlockMangledName(GlobalDecl(), BD);
     else
       llvm_unreachable("Unknown context for block static var decl");
-  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl)) {
-    StringRef Name = CGM.getMangledName(FD);
-    ContextName = Name.str();
-  } else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
+  } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CGF.CurFuncDecl))
+    ContextName = CGM.getMangledName(FD);
+  else if (isa<ObjCMethodDecl>(CGF.CurFuncDecl))
     ContextName = CGF.CurFn->getName();
   else
     llvm_unreachable("Unknown context for static var decl");
 
-  return ContextName + Separator + D.getNameAsString();
+  return ContextName.str() + Separator + D.getNameAsString();
 }
 
 llvm::Constant *

Modified: cfe/trunk/lib/CodeGen/CodeGenAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenAction.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenAction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenAction.cpp Thu Jun  5 17:10:59 2014
@@ -404,12 +404,14 @@ BackendConsumer::StackSizeDiagHandler(co
     // We do not know how to format other severities.
     return false;
 
-  // FIXME: We should demangle the function name.
-  // FIXME: Is there a way to get a location for that function?
-  FullSourceLoc Loc;
-  Diags.Report(Loc, diag::warn_fe_backend_frame_larger_than)
-      << D.getStackSize() << D.getFunction().getName();
-  return true;
+  if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
+    Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
+                 diag::warn_fe_frame_larger_than)
+        << D.getStackSize() << Decl::castToDeclContext(ND);
+    return true;
+  }
+
+  return false;
 }
 
 void BackendConsumer::EmitOptimizationRemark(

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Jun  5 17:10:59 2014
@@ -498,47 +498,40 @@ void CodeGenModule::setTLSMode(llvm::Glo
 }
 
 StringRef CodeGenModule::getMangledName(GlobalDecl GD) {
-  const auto *ND = cast<NamedDecl>(GD.getDecl());
-
-  StringRef &Str = MangledDeclNames[GD.getCanonicalDecl()];
-  if (!Str.empty())
-    return Str;
+  StringRef &FoundStr = MangledDeclNames[GD.getCanonicalDecl()];
+  if (!FoundStr.empty())
+    return FoundStr;
 
-  if (!getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+  const auto *ND = cast<NamedDecl>(GD.getDecl());
+  SmallString<256> Buffer;
+  StringRef Str;
+  if (getCXXABI().getMangleContext().shouldMangleDeclName(ND)) {
+    llvm::raw_svector_ostream Out(Buffer);
+    if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
+      getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
+    else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
+      getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
+    else
+      getCXXABI().getMangleContext().mangleName(ND, Out);
+    Str = Out.str();
+  } else {
     IdentifierInfo *II = ND->getIdentifier();
     assert(II && "Attempt to mangle unnamed decl.");
-
     Str = II->getName();
-    return Str;
   }
-  
-  SmallString<256> Buffer;
-  llvm::raw_svector_ostream Out(Buffer);
-  if (const auto *D = dyn_cast<CXXConstructorDecl>(ND))
-    getCXXABI().getMangleContext().mangleCXXCtor(D, GD.getCtorType(), Out);
-  else if (const auto *D = dyn_cast<CXXDestructorDecl>(ND))
-    getCXXABI().getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Out);
-  else
-    getCXXABI().getMangleContext().mangleName(ND, Out);
 
-  // Allocate space for the mangled name.
-  Out.flush();
-  size_t Length = Buffer.size();
-  char *Name = MangledNamesAllocator.Allocate<char>(Length);
-  std::copy(Buffer.begin(), Buffer.end(), Name);
-  
-  Str = StringRef(Name, Length);
-  
-  return Str;
+  auto &Mangled = Manglings.GetOrCreateValue(Str);
+  Mangled.second = GD;
+  return FoundStr = Mangled.first();
 }
 
-std::string CodeGenModule::getBlockMangledName(GlobalDecl GD,
-                                               const BlockDecl *BD) {
+StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD,
+                                             const BlockDecl *BD) {
   MangleContext &MangleCtx = getCXXABI().getMangleContext();
   const Decl *D = GD.getDecl();
 
-  std::string Buffer;
-  llvm::raw_string_ostream Out(Buffer);
+  SmallString<256> Buffer;
+  llvm::raw_svector_ostream Out(Buffer);
   if (!D)
     MangleCtx.mangleGlobalBlock(BD, 
       dyn_cast_or_null<VarDecl>(initializedGlobalDecl.getDecl()), Out);
@@ -549,7 +542,9 @@ std::string CodeGenModule::getBlockMangl
   else
     MangleCtx.mangleBlock(cast<DeclContext>(D), BD, Out);
 
-  return Out.str();
+  auto &Mangled = Manglings.GetOrCreateValue(Out.str());
+  Mangled.second = BD;
+  return Mangled.first();
 }
 
 llvm::GlobalValue *CodeGenModule::GetGlobalValue(StringRef Name) {
@@ -1462,7 +1457,7 @@ CodeGenModule::GetOrCreateLLVMFunction(S
     // This is the first use or definition of a mangled name.  If there is a
     // deferred decl with this name, remember that we need to emit it at the end
     // of the file.
-    llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+    auto DDI = DeferredDecls.find(MangledName);
     if (DDI != DeferredDecls.end()) {
       // Move the potentially referenced deferred decl to the
       // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
@@ -1622,7 +1617,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(Str
   // This is the first use or definition of a mangled name.  If there is a
   // deferred decl with this name, remember that we need to emit it at the end
   // of the file.
-  llvm::StringMap<GlobalDecl>::iterator DDI = DeferredDecls.find(MangledName);
+  auto DDI = DeferredDecls.find(MangledName);
   if (DDI != DeferredDecls.end()) {
     // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
     // list, and remove it from DeferredDecls (since we don't need it anymore).
@@ -3205,6 +3200,15 @@ void CodeGenModule::EmitStaticExternCAli
   }
 }
 
+bool CodeGenModule::lookupRepresentativeDecl(StringRef MangledName,
+                                             GlobalDecl &Result) const {
+  auto Res = Manglings.find(MangledName);
+  if (Res == Manglings.end())
+    return false;
+  Result = Res->getValue();
+  return true;
+}
+
 /// Emits metadata nodes associating all the global values in the
 /// current module with the Decls they came from.  This is useful for
 /// projects using IR gen as a subroutine.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Jun  5 17:10:59 2014
@@ -287,7 +287,7 @@ class CodeGenModule : public CodeGenType
   /// for emission and therefore should only be output if they are actually
   /// used. If a decl is in this, then it is known to have not been referenced
   /// yet.
-  llvm::StringMap<GlobalDecl> DeferredDecls;
+  std::map<StringRef, GlobalDecl> DeferredDecls;
 
   /// This is a list of deferred decls which we have seen that *are* actually
   /// referenced. These get code generated when the module is done.
@@ -327,8 +327,8 @@ class CodeGenModule : public CodeGenType
 
   /// A map of canonical GlobalDecls to their mangled names.
   llvm::DenseMap<GlobalDecl, StringRef> MangledDeclNames;
-  llvm::BumpPtrAllocator MangledNamesAllocator;
-  
+  llvm::StringMap<GlobalDecl, llvm::BumpPtrAllocator> Manglings;
+
   /// Global annotations.
   std::vector<llvm::Constant*> Annotations;
 
@@ -522,6 +522,9 @@ public:
     StaticLocalDeclGuardMap[D] = C;
   }
 
+  bool lookupRepresentativeDecl(StringRef MangledName,
+                                GlobalDecl &Result) const;
+
   llvm::Constant *getAtomicSetterHelperFnMap(QualType Ty) {
     return AtomicSetterHelperFnMap[Ty];
   }
@@ -922,7 +925,7 @@ public:
                               bool AttrOnCallSite);
 
   StringRef getMangledName(GlobalDecl GD);
-  std::string getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
+  StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD);
 
   void EmitTentativeDefinition(const VarDecl *D);
 

Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Thu Jun  5 17:10:59 2014
@@ -49,6 +49,21 @@ namespace {
       return M.get();
     }
 
+    const Decl *GetDeclForMangledName(StringRef MangledName) override {
+      GlobalDecl Result;
+      if (!Builder->lookupRepresentativeDecl(MangledName, Result))
+        return nullptr;
+      const Decl *D = Result.getCanonicalDecl().getDecl();
+      if (auto FD = dyn_cast<FunctionDecl>(D)) {
+        if (FD->hasBody(FD))
+          return FD;
+      } else if (auto TD = dyn_cast<TagDecl>(D)) {
+        if (auto Def = TD->getDefinition())
+          return Def;
+      }
+      return D;
+    }
+
     llvm::Module *ReleaseModule() override { return M.release(); }
 
     void Initialize(ASTContext &Context) override {

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Thu Jun  5 17:10:59 2014
@@ -2517,6 +2517,13 @@ void Clang::ConstructJob(Compilation &C,
 
   // LLVM Code Generator Options.
 
+  if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
+    StringRef v = A->getValue();
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
+    A->claim();
+  }
+
   if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
     CmdArgs.push_back("-mregparm");
     CmdArgs.push_back(A->getValue());

Modified: cfe/trunk/test/Frontend/backend-diagnostic.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/backend-diagnostic.c?rev=210293&r1=210292&r2=210293&view=diff
==============================================================================
--- cfe/trunk/test/Frontend/backend-diagnostic.c (original)
+++ cfe/trunk/test/Frontend/backend-diagnostic.c Thu Jun  5 17:10:59 2014
@@ -11,16 +11,13 @@
 // RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -no-integrated-as -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than 2> %t.err
 // RUN: FileCheck < %t.err %s --check-prefix=IGNORE --check-prefix=ASM
 //
-// Currently the stack size reporting cannot be checked with -verify because
-//  no source location is attached to the diagnostic. Therefore do not emit
-// them for the -verify test for now.
 // RUN: %clang_cc1 %s -S -o - -triple=i386-apple-darwin -verify -no-integrated-as
 
 extern void doIt(char *);
 
-// REGULAR: warning: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
-// PROMOTE: error: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
-// IGNORE-NOT: stack size exceeded ({{[0-9]+}}) in stackSizeWarning
+// REGULAR: warning: stack frame size of {{[0-9]+}} bytes in function 'stackSizeWarning'
+// PROMOTE: error: stack frame size of {{[0-9]+}} bytes in function 'stackSizeWarning'
+// IGNORE-NOT: stack frame size of {{[0-9]+}} bytes in function 'stackSizeWarning'
 void stackSizeWarning() {
   char buffer[80];
   doIt(buffer);

Added: cfe/trunk/test/Misc/backend-stack-frame-diagnostics-fallback.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/backend-stack-frame-diagnostics-fallback.cpp?rev=210293&view=auto
==============================================================================
--- cfe/trunk/test/Misc/backend-stack-frame-diagnostics-fallback.cpp (added)
+++ cfe/trunk/test/Misc/backend-stack-frame-diagnostics-fallback.cpp Thu Jun  5 17:10:59 2014
@@ -0,0 +1,18 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang_cc1 %s -mllvm -warn-stack-size=0 -emit-codegen-only -triple=i386-apple-darwin 2>&1 | FileCheck %s
+
+// TODO: Emit rich diagnostics for thunks and move this into the appropriate test file.
+// Until then, test that we fall back and display the LLVM backend diagnostic.
+namespace frameSizeThunkWarning {
+  struct A {
+    virtual void f();
+  };
+
+  struct B : virtual A {
+    virtual void f();
+  };
+
+  // CHECK: warning: stack frame size of {{[0-9]+}} bytes in function 'frameSizeThunkWarning::B::f'
+  // CHECK: warning: stack size limit exceeded ({{[0-9]+}}) in {{[^ ]+}}
+  void B::f() { }
+}

Added: cfe/trunk/test/Misc/backend-stack-frame-diagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/backend-stack-frame-diagnostics.cpp?rev=210293&view=auto
==============================================================================
--- cfe/trunk/test/Misc/backend-stack-frame-diagnostics.cpp (added)
+++ cfe/trunk/test/Misc/backend-stack-frame-diagnostics.cpp Thu Jun  5 17:10:59 2014
@@ -0,0 +1,51 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang -target i386-apple-darwin -std=c++11 -fblocks -Wframe-larger-than=70 -Xclang -verify -o /dev/null -c %s
+
+// Test that:
+//  * The driver passes the option through to the backend.
+//  * The frontend diagnostic handler 'demangles' and resolves the correct function definition.
+
+// TODO: Support rich backend diagnostics for Objective-C methods.
+
+extern void doIt(char *);
+
+void frameSizeWarning(int, int) {}
+
+void frameSizeWarning();
+
+void frameSizeWarning() { // expected-warning-re {{stack frame size of {{[0-9]+}} bytes in function 'frameSizeWarning'}}
+  char buffer[80];
+  doIt(buffer);
+}
+
+void frameSizeWarning();
+
+void frameSizeWarning(int) {}
+
+void frameSizeLocalClassWarning() {
+  struct S {
+    S() { // expected-warning-re {{stack frame size of {{[0-9]+}} bytes in function 'frameSizeLocalClassWarning()::S::S'}}
+      char buffer[80];
+      doIt(buffer);
+    }
+  };
+  S();
+}
+
+void frameSizeLambdaWarning() {
+  auto fn =
+      []() { // expected-warning-re {{stack frame size of {{[0-9]+}} bytes in lambda expression}}
+    char buffer[80];
+    doIt(buffer);
+  };
+  fn();
+}
+
+void frameSizeBlocksWarning() {
+  auto fn =
+      ^() { // expected-warning-re {{stack frame size of {{[0-9]+}} bytes in block literal}}
+    char buffer[80];
+    doIt(buffer);
+  };
+  fn();
+}





More information about the cfe-commits mailing list