dmaclach updated this revision to Diff 177732.
dmaclach added a comment.

Added some spacing around early exit as requested by theraven.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55544/new/

https://reviews.llvm.org/D55544

Files:
  docs/ReleaseNotes.rst
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Driver/Options.td
  include/clang/Sema/Sema.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Sema/SemaDeclObjC.cpp
  lib/Sema/SemaExpr.cpp
  test/SemaObjC/objc-large-encoding-warn.m

Index: test/SemaObjC/objc-large-encoding-warn.m
===================================================================
--- test/SemaObjC/objc-large-encoding-warn.m
+++ test/SemaObjC/objc-large-encoding-warn.m
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -Wobjc-encoding-larger-than=10 -Wno-objc-root-class %s
+
+struct MyStruct {
+  int a;
+  int b;
+  struct MyStruct *c;
+};
+
+@interface MyClass {
+  struct MyStruct iVarThatWarns; // expected-warning {{instance variable encoding of size 24 is larger than 10 bytes}}
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wobjc-encoding-larger-than="
+  struct MyStruct iVarThatDoesntWarn;
+#pragma clang diagnostic pop
+  id idThatDoesntWarn;
+}
+@end
+
+@implementation MyClass
+- (void)methodThatWarns:(struct MyStruct)aStruct {} // expected-warning {{instance method 'methodThatWarns:' encoding of size 33 is larger than 10 bytes}}
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wobjc-encoding-larger-than="
+- (void)methodThatDoesntWarn:(struct MyStruct)aStruct {}
+#pragma clang diagnostic pop
+- (void)methodThatAlsoDoesntWarn {}
+@end
+
+void BlockFunc() {
+  void(^aBlockThatWarns)(struct MyStruct) = ^(struct MyStruct a) {}; // expected-warning {{block argument encoding of size 31 is larger than 10 bytes}}
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wobjc-encoding-larger-than="
+  void(^aBlockThatDoesntWarn)(struct MyStruct) = ^(struct MyStruct a) {};
+#pragma clang diagnostic pop
+  void(^aBlockThatAlsoDoesntWarn)() = ^() {};
+}
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13777,6 +13777,16 @@
   if (getCurFunction())
     getCurFunction()->addBlock(BD);
 
+  /// Check for block objective C encoding size
+  if (getLangOpts().ObjC) {
+    std::string encoding = Context.getObjCEncodingForBlock(Result);
+    unsigned long encodingSize = LangOpts.ObjCLargeEncodingSize;
+    if (encodingSize && encoding.length() > encodingSize) {
+      Diag(BD->getLocation(), diag::warn_objc_block_encoding_too_large)
+        << (unsigned)encoding.length() << (unsigned)encodingSize;
+    }
+  }
+
   return Result;
 }
 
Index: lib/Sema/SemaDeclObjC.cpp
===================================================================
--- lib/Sema/SemaDeclObjC.cpp
+++ lib/Sema/SemaDeclObjC.cpp
@@ -3875,6 +3875,25 @@
   }
 }
 
+// Run through the ivars and see if any of their encodings are larger than
+// ObjCLargeEncodingSize.
+void Sema::DiagnoseLargeIvarEncodings(ObjCImplementationDecl *ID) {
+  unsigned long encodingSize = LangOpts.ObjCLargeEncodingSize;
+  if (encodingSize == 0) return;
+
+  for (ObjCIvarDecl *ivar = ID->getClassInterface()->all_declared_ivar_begin();
+       ivar; ivar = ivar->getNextIvar()) {
+    QualType QT = Context.getBaseElementType(ivar->getType());
+    std::string encoding;
+    QualType NotEncodedT;
+    Context.getObjCEncodingForType(QT, encoding, nullptr, &NotEncodedT);
+    if (encoding.length() > encodingSize) {
+      Diag(ivar->getLocation(), diag::warn_objc_ivar_encoding_too_large)
+        << (unsigned)encoding.length() << (unsigned)encodingSize;
+    }
+  }
+}
+
 // Note: For class/category implementations, allMethods is always null.
 Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
                        ArrayRef<DeclGroupPtrTy> allTUVars) {
@@ -4006,6 +4025,7 @@
       if (IDecl->hasDesignatedInitializers())
         DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
       DiagnoseWeakIvars(*this, IC);
+      DiagnoseLargeIvarEncodings(IC);
       DiagnoseRetainableFlexibleArrayMember(*this, IDecl);
 
       bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
@@ -4768,6 +4788,15 @@
     }
   }
 
+  /// Check for method encoding size.
+  std::string encoding = Context.getObjCEncodingForMethodDecl(ObjCMethod);
+  unsigned long encodingSize = LangOpts.ObjCLargeEncodingSize;
+  if (encodingSize && encoding.length() > encodingSize) {
+    Diag(ObjCMethod->getLocation(), diag::warn_objc_method_encoding_too_large)
+      << (ObjCMethod->isInstanceMethod() ? "instance" : "class")
+      << ObjCMethod->getDeclName() << (unsigned)encoding.length()
+      << (unsigned)encodingSize;
+  }
   ActOnDocumentableDecl(ObjCMethod);
 
   return ObjCMethod;
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -2656,6 +2656,8 @@
     Args.getLastArgValue(OPT_fconstant_string_class);
   Opts.ObjCDefaultSynthProperties =
     !Args.hasArg(OPT_disable_objc_default_synthesize_properties);
+  Opts.ObjCLargeEncodingSize =
+    getLastArgIntValue(Args, OPT_Wobjc_encoding_larger_than_EQ, 0, Diags);
   Opts.EncodeExtendedBlockSig =
     Args.hasArg(OPT_fencode_extended_block_signature);
   Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -4232,6 +4232,14 @@
     CmdArgs.push_back(A->getValue());
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_Wobjc_encoding_larger_than_EQ)) {
+    if (A->getNumValues()) {
+      StringRef bytes = A->getValue();
+      CmdArgs.push_back(
+          Args.MakeArgString("-Wobjc-encoding-larger-than=" + bytes));
+    }
+  }
+  
   if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
                                options::OPT_Wlarge_by_value_copy_def)) {
     if (A->getNumValues()) {
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1711,6 +1711,7 @@
   DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
 
   void DiagnoseUseOfUnimplementedSelectors();
+  void DiagnoseLargeIvarEncodings(ObjCImplementationDecl *ID);
 
   bool isSimpleTypeSpecifier(tok::TokenKind Kind) const;
 
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1698,6 +1698,8 @@
 def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than_EQ>;
 def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>, Flags<[DriverOption]>;
 
+def Wobjc_encoding_larger_than_EQ : Joined<["-"], "Wobjc-encoding-larger-than=">, Flags<[CC1Option]>;
+
 def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
 def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group<f_Group>;
 def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
Index: include/clang/Basic/LangOptions.def
===================================================================
--- include/clang/Basic/LangOptions.def
+++ include/clang/Basic/LangOptions.def
@@ -99,6 +99,8 @@
                "Encoding extended block type signature")
 BENIGN_LANGOPT(ObjCInferRelatedResultType , 1, 1,
                "Objective-C related result type inference")
+BENIGN_LANGOPT(ObjCLargeEncodingSize, 32, 0,
+              "if non-zero, warn about Objective C encodings larger in bytes than this setting. 0 is no check.")
 LANGOPT(AppExt , 1, 0, "Objective-C App Extension")
 LANGOPT(Trigraphs         , 1, 0,"trigraphs")
 LANGOPT(LineComment       , 1, 0, "'//' comments")
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6203,6 +6203,15 @@
   InGroup<DiagGroup<"objc-unsafe-perform-selector">>;
 def note_objc_unsafe_perform_selector_method_declared_here :  Note<
   "method %0 that returns %1 declared here">;
+def warn_objc_method_encoding_too_large : Warning<
+  "%0 method %1 encoding of size %2 is larger than %3 bytes">,
+  InGroup<ObjCEncodingLargerThan>;
+def warn_objc_block_encoding_too_large : Warning<
+  "block argument encoding of size %0 is larger than %1 bytes">,
+  InGroup<ObjCEncodingLargerThan>;
+def warn_objc_ivar_encoding_too_large : Warning<
+  "instance variable encoding of size %0 is larger than %1 bytes">,
+  InGroup<ObjCEncodingLargerThan>;
 
 def warn_setter_getter_impl_required : Warning<
   "property %0 requires method %1 to be defined - "
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -397,6 +397,8 @@
 def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
 def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
 def ObjCFlexibleArray : DiagGroup<"objc-flexible-array">;
+def ObjCEncodingLargerThan : DiagGroup<"objc-encoding-larger-than=">;
+
 def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
 def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
 def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -112,6 +112,10 @@
           ;
       }
 
+- ``-Wobjc-encodings-larger-than=`` is a new diagnostic that diagnoses when the Objective
+  C runtime is generating large Objective C runtime information. This often happens
+  when passing C++ classes in Objective C messages/blocks. This information can get very
+  large. A good starting value is 1024 (1K).
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to