dmaclach created this revision.
dmaclach added a project: clang.
Herald added a subscriber: cfe-commits.
Issue a warning when the Objective C runtime encoding generated for an iVar,
method, or block exceeds a user configurable value.
Off by default.
Note that handling iVars and methods will also get us properties.
Objective C runtime information can get very large (several K) and most of it
is unused. Having the warning allows us to diagnose where the problem exists in
our code.
Repository:
rC Clang
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,23 @@
}
}
+// Run through the ivars and see if any of their encodings are > 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 +4023,7 @@
if (IDecl->hasDesignatedInitializers())
DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
DiagnoseWeakIvars(*this, IC);
+ DiagnoseLargeIvarEncodings(IC);
DiagnoseRetainableFlexibleArrayMember(*this, IDecl);
bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
@@ -4768,6 +4786,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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits