зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
8b9fb3082b
Коммит
1efaa9594a
|
@ -690,6 +690,8 @@
|
|||
DEF168620F9549250098507F /* FixItRewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FixItRewriter.h; path = clang/Frontend/FixItRewriter.h; sourceTree = "<group>"; };
|
||||
DEF169220F9645960098507F /* FrontendDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FrontendDiagnostic.h; path = clang/Frontend/FrontendDiagnostic.h; sourceTree = "<group>"; };
|
||||
DEF1692C0F9645BF0098507F /* AnalysisDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AnalysisDiagnostic.h; path = clang/Analysis/AnalysisDiagnostic.h; sourceTree = "<group>"; };
|
||||
DEF16BE40FA13A5B0098507F /* TypeNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = TypeNodes.def; path = clang/AST/TypeNodes.def; sourceTree = "<group>"; };
|
||||
DEF16BE50FA13A650098507F /* TypeOrdering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeOrdering.h; path = clang/AST/TypeOrdering.h; sourceTree = "<group>"; };
|
||||
DEF2E95E0C5FBD74000C4259 /* InternalsManual.html */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.html; name = InternalsManual.html; path = docs/InternalsManual.html; sourceTree = "<group>"; };
|
||||
DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = StmtDumper.cpp; path = lib/AST/StmtDumper.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DEF2EFF20C6CDD74000C4259 /* CGExprAgg.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGExprAgg.cpp; path = lib/CodeGen/CGExprAgg.cpp; sourceTree = "<group>"; 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 */,
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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<ObjCInterfaceType>(this)->getDecl()->isForwardDecl();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1231,37 +1231,33 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
|
|||
|
||||
// C99 6.5.3.4p1:
|
||||
if (isa<FunctionType>(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<proto>)
|
||||
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<proto>) 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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче