From 1efaa9594a81709a17658fd80ae7e783e1026407 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 24 Apr 2009 00:30:45 +0000 Subject: [PATCH] Fix rdar://6821047 - clang crashes on subscript of interface in 64-bit mode Several changes here: 1. We change Type::isIncompleteType to realize that forward declared interfaces are incomplete. This eliminate special case code for this from the sizeof path, and starts us rejecting P[4] when P is a pointer to an incomplete interface. 2. Explicitly reject P[4] when P points to an interface in non-fragile ABI mode. 3. Switch the sizeof(interface) diagnostic back to an error instead of a warning in non-fragile abi mode. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69943 91177308-0d34-0410-b5e6-96231b3b80d8 --- clang.xcodeproj/project.pbxproj | 10 +++-- include/clang/Basic/DiagnosticSemaKinds.td | 8 ++-- lib/AST/Type.cpp | 4 ++ lib/Sema/SemaExpr.cpp | 45 ++++++++++++---------- lib/Sema/SemaType.cpp | 4 +- test/SemaObjC/sizeof-interface.m | 20 ++++++++-- 6 files changed, 58 insertions(+), 33 deletions(-) diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index 0aa9307572..6bacb1d98b 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -690,6 +690,8 @@ DEF168620F9549250098507F /* FixItRewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FixItRewriter.h; path = clang/Frontend/FixItRewriter.h; sourceTree = ""; }; DEF169220F9645960098507F /* FrontendDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendDiagnostic.h; path = clang/Frontend/FrontendDiagnostic.h; sourceTree = ""; }; DEF1692C0F9645BF0098507F /* AnalysisDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisDiagnostic.h; path = clang/Analysis/AnalysisDiagnostic.h; sourceTree = ""; }; + DEF16BE40FA13A5B0098507F /* TypeNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeNodes.def; path = clang/AST/TypeNodes.def; sourceTree = ""; }; + DEF16BE50FA13A650098507F /* TypeOrdering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeOrdering.h; path = clang/AST/TypeOrdering.h; sourceTree = ""; }; DEF2E95E0C5FBD74000C4259 /* InternalsManual.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html; name = InternalsManual.html; path = docs/InternalsManual.html; sourceTree = ""; }; DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtDumper.cpp; path = lib/AST/StmtDumper.cpp; sourceTree = ""; tabWidth = 2; }; DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprAgg.cpp; path = lib/CodeGen/CGExprAgg.cpp; sourceTree = ""; tabWidth = 2; }; @@ -1132,6 +1134,8 @@ 35CFFE010CA1CBDD00E6F2BE /* StmtGraphTraits.h */, 1A68BC120D0CADDD001A28C8 /* TargetBuiltins.h */, DEDFF87F0F848CE30035BD10 /* TemplateName.h */, + DEF16BE40FA13A5B0098507F /* TypeNodes.def */, + DEF16BE50FA13A650098507F /* TypeOrdering.h */, DE3464210B03040900DBC861 /* Type.h */, ); name = AST; @@ -1189,9 +1193,6 @@ DED7D7300A524295003AD0FB /* Basic */ = { isa = PBXGroup; children = ( - 9063F2280F9E911F002F7251 /* OnDiskHashTable.h */, - 9063F2290F9E911F002F7251 /* SourceManagerInternals.h */, - 9063F22A0F9E911F002F7251 /* TemplateKinds.h */, 906BF4AE0F83BA16001071FA /* ConvertUTF.h */, DED7D7310A524295003AD0FB /* Diagnostic.h */, DEDFFF070F959EE60035BD10 /* Diagnostic.td */, @@ -1207,12 +1208,15 @@ DED7D7330A524295003AD0FB /* FileManager.h */, DE3986EF0CB8D4B300223765 /* IdentifierTable.h */, DE06B73D0A8307640050E87E /* LangOptions.h */, + 9063F2280F9E911F002F7251 /* OnDiskHashTable.h */, DE8824560ED1244600CBC30A /* OperatorKinds.def */, DE8824530ED1243E00CBC30A /* OperatorKinds.h */, DEAABDF70F5F477C0098928A /* PrettyStackTrace.h */, DED7D7350A524295003AD0FB /* SourceLocation.h */, DED7D7360A524295003AD0FB /* SourceManager.h */, + 9063F2290F9E911F002F7251 /* SourceManagerInternals.h */, DE46BF270AE0A82D00CC047C /* TargetInfo.h */, + 9063F22A0F9E911F002F7251 /* TemplateKinds.h */, DED7D7370A524295003AD0FB /* TokenKinds.def */, DED7D7380A524295003AD0FB /* TokenKinds.h */, DEB089EE0F12F1D900522C07 /* TypeTraits.h */, diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index db4fa2a4fa..a5aa6bdb84 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -917,10 +917,7 @@ def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">; def ext_sizeof_void_type : Extension< "invalid application of '%0' to a void type">; -def err_sizeof_forward_interface : Error< - "invalid application of '%select{alignof|sizeof}1' to a forward declared" - " interface %0">; -def err_sizeof_nonfragile_interface : Warning< +def err_sizeof_nonfragile_interface : Error< "invalid application of '%select{alignof|sizeof}1' to interface %0 in " "non-fragile ABI">; def err_atdef_nonfragile_interface : Error< @@ -948,6 +945,9 @@ def err_subscript_function_type : Error< "subscript of pointer to function type %0">; def err_subscript_incomplete_type : Error< "subscript of pointer to incomplete type %0">; +def err_subscript_nonfragile_interface : Error< + "subscript requires size of interface %0, which is not constant in " + "non-fragile ABI">; def err_typecheck_member_reference_struct_union : Error< "member reference base type %0 is not a structure or union">; def err_typecheck_member_reference_ivar : Error< diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7daa20704b..a94310bbdf 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -825,6 +825,10 @@ bool Type::isIncompleteType() const { case IncompleteArray: // An array of unknown size is an incomplete type (C99 6.2.5p22). return true; + case ObjCInterface: + case ObjCQualifiedInterface: + // ObjC interfaces are incomplete if they are @class, not @interface. + return cast(this)->getDecl()->isForwardDecl(); } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 89f834cf5a..edf769b2fe 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1231,37 +1231,33 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, // C99 6.5.3.4p1: if (isa(exprType)) { - // alignof(function) is allowed. + // alignof(function) is allowed as an extension. if (isSizeof) Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange; return false; } + // Allow sizeof(void)/alignof(void) as an extension. if (exprType->isVoidType()) { Diag(OpLoc, diag::ext_sizeof_void_type) << (isSizeof ? "sizeof" : "__alignof") << ExprRange; return false; } - // sizeof(interface) and sizeof(interface) - if (const ObjCInterfaceType *IIT = exprType->getAsObjCInterfaceType()) { - if (IIT->getDecl()->isForwardDecl()) { - Diag(OpLoc, diag::err_sizeof_forward_interface) - << IIT->getDecl()->getDeclName() << isSizeof; - return true; - } - - if (LangOpts.ObjCNonFragileABI) { - Diag(OpLoc, diag::err_sizeof_nonfragile_interface) - << IIT->getDecl()->getDeclName() << isSizeof; - //return false; - } + if (RequireCompleteType(OpLoc, exprType, + isSizeof ? diag::err_sizeof_incomplete_type : + diag::err_alignof_incomplete_type, + ExprRange)) + return true; + + // Reject sizeof(interface) and sizeof(interface) in 64-bit mode. + if (exprType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + Diag(OpLoc, diag::err_sizeof_nonfragile_interface) + << exprType << isSizeof; + return true; } - return RequireCompleteType(OpLoc, exprType, - isSizeof ? diag::err_sizeof_incomplete_type : - diag::err_alignof_incomplete_type, - ExprRange); + return false; } bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, @@ -1651,12 +1647,19 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, << ResultType << BaseExpr->getSourceRange(); return ExprError(); } + if (!ResultType->isDependentType() && - RequireCompleteType(BaseExpr->getLocStart(), ResultType, - diag::err_subscript_incomplete_type, + RequireCompleteType(LLoc, ResultType, diag::err_subscript_incomplete_type, BaseExpr->getSourceRange())) return ExprError(); - + + // Diagnose bad cases where we step over interface counts. + if (ResultType->isObjCInterfaceType() && LangOpts.ObjCNonFragileABI) { + Diag(LLoc, diag::err_subscript_nonfragile_interface) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + Base.release(); Idx.release(); return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 50f5071306..62d2489b34 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1060,8 +1060,8 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { /// @returns @c true if @p T is incomplete and a diagnostic was emitted, /// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, unsigned diag, - SourceRange Range1, SourceRange Range2, - QualType PrintType) { + SourceRange Range1, SourceRange Range2, + QualType PrintType) { // If we have a complete type, we're done. if (!T->isIncompleteType()) return false; diff --git a/test/SemaObjC/sizeof-interface.m b/test/SemaObjC/sizeof-interface.m index ac029fddfc..1793167673 100644 --- a/test/SemaObjC/sizeof-interface.m +++ b/test/SemaObjC/sizeof-interface.m @@ -3,9 +3,17 @@ @class I0; // rdar://6811884 -int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to a forward declared interface 'I0'}} +int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an incomplete type 'I0'}} + +// rdar://6821047 +void *g3(I0 *P) { + return &P[4]; // expected-error{{subscript of pointer to incomplete type 'I0'}} +} + + @interface I0 { +@public char x[4]; } @@ -13,7 +21,7 @@ int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to a for @end // size == 4 -int g1[ sizeof(I0) // expected-warning {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} +int g1[ sizeof(I0) // expected-error {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} == 4 ? 1 : -1]; @implementation I0 @@ -22,7 +30,7 @@ int g1[ sizeof(I0) // expected-warning {{invalid application of 'sizeof' to // size == 4 (we do not include extended properties in the // sizeof). -int g2[ sizeof(I0) // expected-warning {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} +int g2[ sizeof(I0) // expected-error {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} == 4 ? 1 : -1]; @interface I1 @@ -38,3 +46,9 @@ typedef struct { @defs(I1) } I1_defs; // expected-error {{invalid application of // FIXME: This is currently broken due to the way the record layout we // create is tied to whether we have seen synthesized properties. Ugh. // int g3[ sizeof(I1) == 0 ? 1 : -1]; + +// rdar://6821047 +int bar(I0 *P) { + return P[4].x[2]; // expected-error {{subscript requires size of interface 'I0', which is not constant in non-fragile ABI}} +} +