forked from OSchip/llvm-project
Make sure to use RequireCompleteType rather than testing for
incomplete types. RequireCompleteType is needed when the type may be completed by instantiating a template. llvm-svn: 67643
This commit is contained in:
parent
e7e5becdd2
commit
ac1fb65d0c
|
@ -817,7 +817,7 @@ def err_block_return_missing_expr : Error<
|
|||
def err_block_with_return_type_requires_args : Error<
|
||||
"block with explicit return type requires argument list">;
|
||||
def err_func_def_incomplete_result : Error<
|
||||
"result type for function definition cannot be incomplete">;
|
||||
"incomplete result type %0 in function definition">;
|
||||
|
||||
// Expressions.
|
||||
def ext_sizeof_function_type : Extension<
|
||||
|
@ -842,8 +842,10 @@ def warn_floatingpoint_eq : Warning<
|
|||
def err_typecheck_subscript_value : Error<
|
||||
"subscripted value is neither array nor pointer">;
|
||||
def err_typecheck_subscript : Error<"array subscript is not an integer">;
|
||||
def err_typecheck_subscript_not_object : Error<
|
||||
"illegal subscript of non-object type %0">;
|
||||
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_typecheck_member_reference_struct_union : Error<
|
||||
"member reference base type %0 is not a structure or union">;
|
||||
def err_typecheck_member_reference_ivar : Error<
|
||||
|
@ -1026,7 +1028,9 @@ def err_static_illegal_in_new : Error<
|
|||
def err_array_new_needs_size : Error<
|
||||
"array size must be specified in new expressions">;
|
||||
def err_bad_new_type : Error<
|
||||
"cannot allocate %select{function|incomplete|reference}1 type %0 with new">;
|
||||
"cannot allocate %select{function|reference}1 type %0 with new">;
|
||||
def err_new_incomplete_type : Error<
|
||||
"allocation of incomplete type %0">;
|
||||
def err_new_array_nonconst : Error<
|
||||
"only the first dimension of an allocated array may be non-const">;
|
||||
def err_array_size_not_integral : Error<
|
||||
|
@ -1049,8 +1053,9 @@ def err_qualified_catch_declarator : Error<
|
|||
"exception declarator cannot be qualified">;
|
||||
def err_early_catch_all : Error<"catch-all handler must come last">;
|
||||
def err_bad_memptr_rhs : Error<
|
||||
"right hand operand to %0 must be a pointer to member of a complete class "
|
||||
"but is %1">;
|
||||
"right hand operand to %0 has non pointer-to-member type %1">;
|
||||
def err_memptr_rhs_incomplete : Error<
|
||||
"right hand operand is a pointer to member of incomplete type %0">;
|
||||
|
||||
def err_bad_memptr_lhs : Error<
|
||||
"left hand operand to %0 must be a %select{|pointer to }1class "
|
||||
|
|
|
@ -881,6 +881,8 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
|
|||
// C99 6.7.5.3p4: the parameters in a parameter type list in a
|
||||
// function declarator that is part of a function definition of
|
||||
// that function shall not have incomplete type.
|
||||
//
|
||||
// This is also C++ [dcl.fct]p6.
|
||||
if (!Param->isInvalidDecl() &&
|
||||
RequireCompleteType(Param->getLocation(), Param->getType(),
|
||||
diag::err_typecheck_decl_incomplete_type)) {
|
||||
|
@ -2723,12 +2725,12 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
}
|
||||
|
||||
// The return type of a function definition must be complete
|
||||
// (C99 6.9.1p3)
|
||||
if (FD->getResultType()->isIncompleteType() &&
|
||||
!FD->getResultType()->isVoidType()) {
|
||||
Diag(FD->getLocation(), diag::err_func_def_incomplete_result) << FD;
|
||||
// (C99 6.9.1p3, C++ [dcl.fct]p6).
|
||||
QualType ResultType = FD->getResultType();
|
||||
if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
|
||||
RequireCompleteType(FD->getLocation(), ResultType,
|
||||
diag::err_func_def_incomplete_result))
|
||||
FD->setInvalidDecl();
|
||||
}
|
||||
|
||||
PushDeclContext(FnBodyScope, FD);
|
||||
|
||||
|
@ -3726,33 +3728,27 @@ void Sema::ActOnFields(Scope* S,
|
|||
if (FD->isInvalidDecl())
|
||||
continue;
|
||||
|
||||
// C99 6.7.2.1p2 - A field may not be a function type.
|
||||
// C99 6.7.2.1p2:
|
||||
// A structure or union shall not contain a member with
|
||||
// incomplete or function type (hence, a structure shall not
|
||||
// contain an instance of itself, but may contain a pointer to
|
||||
// an instance of itself), except that the last member of a
|
||||
// structure with more than one named member may have incomplete
|
||||
// array type; such a structure (and any union containing,
|
||||
// possibly recursively, a member that is such a structure)
|
||||
// shall not be a member of a structure or an element of an
|
||||
// array.
|
||||
if (FDTy->isFunctionType()) {
|
||||
// Field declared as a function.
|
||||
Diag(FD->getLocation(), diag::err_field_declared_as_function)
|
||||
<< FD->getDeclName();
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
}
|
||||
// C99 6.7.2.1p2 - A field may not be an incomplete type except...
|
||||
if (FDTy->isIncompleteType()) {
|
||||
if (!Record) { // Incomplete ivar type is always an error.
|
||||
RequireCompleteType(FD->getLocation(), FD->getType(),
|
||||
diag::err_field_incomplete);
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
}
|
||||
if (i != NumFields-1 || // ... that the last member ...
|
||||
!Record->isStruct() || // ... of a structure ...
|
||||
!FDTy->isArrayType()) { //... may have incomplete array type.
|
||||
RequireCompleteType(FD->getLocation(), FD->getType(),
|
||||
diag::err_field_incomplete);
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
}
|
||||
if (NumNamedMembers < 1) { //... must have more than named member ...
|
||||
} else if (FDTy->isIncompleteArrayType() && i == NumFields - 1 &&
|
||||
Record && Record->isStruct()) {
|
||||
// Flexible array member.
|
||||
if (NumNamedMembers < 1) {
|
||||
Diag(FD->getLocation(), diag::err_flexible_array_empty_struct)
|
||||
<< FD->getDeclName();
|
||||
FD->setInvalidDecl();
|
||||
|
@ -3762,10 +3758,14 @@ void Sema::ActOnFields(Scope* S,
|
|||
// Okay, we have a legal flexible array member at the end of the struct.
|
||||
if (Record)
|
||||
Record->setHasFlexibleArrayMember(true);
|
||||
}
|
||||
/// C99 6.7.2.1p2 - a struct ending in a flexible array member cannot be the
|
||||
/// field of another structure or the element of an array.
|
||||
if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
|
||||
} else if (!FDTy->isDependentType() &&
|
||||
RequireCompleteType(FD->getLocation(), FD->getType(),
|
||||
diag::err_field_incomplete)) {
|
||||
// Incomplete type
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
} else if (const RecordType *FDTTy = FDTy->getAsRecordType()) {
|
||||
if (FDTTy->getDecl()->hasFlexibleArrayMember()) {
|
||||
// If this is a member of a union, then entire union becomes "flexible".
|
||||
if (Record && Record->isUnion()) {
|
||||
|
@ -3787,9 +3787,8 @@ void Sema::ActOnFields(Scope* S,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (FDTy->isObjCInterfaceType()) {
|
||||
/// A field cannot be an Objective-c object
|
||||
if (FDTy->isObjCInterfaceType()) {
|
||||
Diag(FD->getLocation(), diag::err_statically_allocated_object);
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
|
|
|
@ -1593,14 +1593,20 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,
|
|||
return ExprError(Diag(IndexExpr->getLocStart(),
|
||||
diag::err_typecheck_subscript) << IndexExpr->getSourceRange());
|
||||
|
||||
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". In practice,
|
||||
// the following check catches trying to index a pointer to a function (e.g.
|
||||
// void (*)(int)) and pointers to incomplete types. Functions are not
|
||||
// objects in C99.
|
||||
if (!ResultType->isObjectType() && !ResultType->isDependentType())
|
||||
return ExprError(Diag(BaseExpr->getLocStart(),
|
||||
diag::err_typecheck_subscript_not_object)
|
||||
<< BaseExpr->getType() << BaseExpr->getSourceRange());
|
||||
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
|
||||
// C++ [expr.sub]p1: The type "T" shall be a completely-defined object
|
||||
// type. Note that Functions are not objects, and that (in C99 parlance)
|
||||
// incomplete types are not object types.
|
||||
if (ResultType->isFunctionType()) {
|
||||
Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type)
|
||||
<< ResultType << BaseExpr->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
if (!ResultType->isDependentType() &&
|
||||
RequireCompleteType(BaseExpr->getLocStart(), ResultType,
|
||||
diag::err_subscript_incomplete_type,
|
||||
BaseExpr->getSourceRange()))
|
||||
return ExprError();
|
||||
|
||||
Base.release();
|
||||
Idx.release();
|
||||
|
@ -3155,7 +3161,6 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
|||
if (const PointerType* PTy = PExp->getType()->getAsPointerType()) {
|
||||
if (IExp->getType()->isIntegerType()) {
|
||||
// Check for arithmetic on pointers to incomplete types
|
||||
if (!PTy->getPointeeType()->isObjectType()) {
|
||||
if (PTy->getPointeeType()->isVoidType()) {
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
|
||||
|
@ -3176,14 +3181,13 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
|||
// GNU extension: arithmetic on pointer to function
|
||||
Diag(Loc, diag::ext_gnu_ptr_func_arith)
|
||||
<< lex->getType() << lex->getSourceRange();
|
||||
} else {
|
||||
} else if (!PTy->isDependentType() &&
|
||||
RequireCompleteType(Loc, PTy->getPointeeType(),
|
||||
diag::err_typecheck_arithmetic_incomplete_type,
|
||||
lex->getSourceRange(), SourceRange(),
|
||||
lex->getType());
|
||||
lex->getType()))
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
|
||||
return PExp->getType();
|
||||
}
|
||||
}
|
||||
|
@ -3209,12 +3213,19 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
|
|||
if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
|
||||
QualType lpointee = LHSPTy->getPointeeType();
|
||||
|
||||
// The LHS must be an object type, not incomplete, function, etc.
|
||||
if (!lpointee->isObjectType()) {
|
||||
// Handle the GNU void* extension.
|
||||
// The LHS must be an completely-defined object type.
|
||||
|
||||
bool ComplainAboutVoid = false;
|
||||
Expr *ComplainAboutFunc = 0;
|
||||
if (lpointee->isVoidType()) {
|
||||
Diag(Loc, diag::ext_gnu_void_ptr)
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
|
||||
<< lex->getSourceRange() << rex->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// GNU C extension: arithmetic on pointer to void
|
||||
ComplainAboutVoid = true;
|
||||
} else if (lpointee->isFunctionType()) {
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
|
||||
|
@ -3222,31 +3233,43 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
|
|||
return QualType();
|
||||
}
|
||||
|
||||
// GNU extension: arithmetic on pointer to function
|
||||
Diag(Loc, diag::ext_gnu_ptr_func_arith)
|
||||
<< lex->getType() << lex->getSourceRange();
|
||||
} else {
|
||||
Diag(Loc, diag::err_typecheck_sub_ptr_object)
|
||||
<< lex->getType() << lex->getSourceRange();
|
||||
// GNU C extension: arithmetic on pointer to function
|
||||
ComplainAboutFunc = lex;
|
||||
} else if (!lpointee->isDependentType() &&
|
||||
RequireCompleteType(Loc, lpointee,
|
||||
diag::err_typecheck_sub_ptr_object,
|
||||
lex->getSourceRange(),
|
||||
SourceRange(),
|
||||
lex->getType()))
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
|
||||
// The result type of a pointer-int computation is the pointer type.
|
||||
if (rex->getType()->isIntegerType())
|
||||
if (rex->getType()->isIntegerType()) {
|
||||
if (ComplainAboutVoid)
|
||||
Diag(Loc, diag::ext_gnu_void_ptr)
|
||||
<< lex->getSourceRange() << rex->getSourceRange();
|
||||
if (ComplainAboutFunc)
|
||||
Diag(Loc, diag::ext_gnu_ptr_func_arith)
|
||||
<< ComplainAboutFunc->getType()
|
||||
<< ComplainAboutFunc->getSourceRange();
|
||||
|
||||
return lex->getType();
|
||||
}
|
||||
|
||||
// Handle pointer-pointer subtractions.
|
||||
if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) {
|
||||
QualType rpointee = RHSPTy->getPointeeType();
|
||||
|
||||
// RHS must be an object type, unless void (GNU).
|
||||
if (!rpointee->isObjectType()) {
|
||||
// RHS must be a completely-type object type.
|
||||
// Handle the GNU void* extension.
|
||||
if (rpointee->isVoidType()) {
|
||||
if (!lpointee->isVoidType())
|
||||
Diag(Loc, diag::ext_gnu_void_ptr)
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_void_type)
|
||||
<< lex->getSourceRange() << rex->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
ComplainAboutVoid = true;
|
||||
} else if (rpointee->isFunctionType()) {
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
|
||||
|
@ -3255,15 +3278,15 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
|
|||
}
|
||||
|
||||
// GNU extension: arithmetic on pointer to function
|
||||
if (!lpointee->isFunctionType())
|
||||
Diag(Loc, diag::ext_gnu_ptr_func_arith)
|
||||
<< lex->getType() << lex->getSourceRange();
|
||||
} else {
|
||||
Diag(Loc, diag::err_typecheck_sub_ptr_object)
|
||||
<< rex->getType() << rex->getSourceRange();
|
||||
if (!ComplainAboutFunc)
|
||||
ComplainAboutFunc = rex;
|
||||
} else if (!rpointee->isDependentType() &&
|
||||
RequireCompleteType(Loc, rpointee,
|
||||
diag::err_typecheck_sub_ptr_object,
|
||||
rex->getSourceRange(),
|
||||
SourceRange(),
|
||||
rex->getType()))
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
|
||||
// Pointee types must be compatible.
|
||||
if (!Context.typesAreCompatible(
|
||||
|
@ -3275,6 +3298,14 @@ QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
|
|||
return QualType();
|
||||
}
|
||||
|
||||
if (ComplainAboutVoid)
|
||||
Diag(Loc, diag::ext_gnu_void_ptr)
|
||||
<< lex->getSourceRange() << rex->getSourceRange();
|
||||
if (ComplainAboutFunc)
|
||||
Diag(Loc, diag::ext_gnu_ptr_func_arith)
|
||||
<< ComplainAboutFunc->getType()
|
||||
<< ComplainAboutFunc->getSourceRange();
|
||||
|
||||
return Context.getPointerDiffType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,10 +242,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
|||
if (CheckAllocatedType(AllocType, D))
|
||||
return ExprError();
|
||||
|
||||
if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
|
||||
diag::err_allocation_of_abstract_type))
|
||||
return ExprError();
|
||||
|
||||
QualType ResultType = AllocType->isDependentType()
|
||||
? Context.DependentTy
|
||||
: Context.getPointerType(AllocType);
|
||||
|
@ -364,23 +360,20 @@ bool Sema::CheckAllocatedType(QualType AllocType, const Declarator &D)
|
|||
{
|
||||
// C++ 5.3.4p1: "[The] type shall be a complete object type, but not an
|
||||
// abstract class type or array thereof.
|
||||
// FIXME: We don't have abstract types yet.
|
||||
// FIXME: Under C++ semantics, an incomplete object type is still an object
|
||||
// type. This code assumes the C semantics, where it's not.
|
||||
if (!AllocType->isObjectType()) {
|
||||
unsigned type; // For the select in the message.
|
||||
if (AllocType->isFunctionType()) {
|
||||
type = 0;
|
||||
} else if(AllocType->isIncompleteType()) {
|
||||
type = 1;
|
||||
} else {
|
||||
assert(AllocType->isReferenceType() && "Unhandled non-object type.");
|
||||
type = 2;
|
||||
}
|
||||
Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
|
||||
<< AllocType << type << D.getSourceRange();
|
||||
if (AllocType->isFunctionType())
|
||||
return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
|
||||
<< AllocType << 0 << D.getSourceRange();
|
||||
else if (AllocType->isReferenceType())
|
||||
return Diag(D.getSourceRange().getBegin(), diag::err_bad_new_type)
|
||||
<< AllocType << 1 << D.getSourceRange();
|
||||
else if (!AllocType->isDependentType() &&
|
||||
RequireCompleteType(D.getSourceRange().getBegin(), AllocType,
|
||||
diag::err_new_incomplete_type,
|
||||
D.getSourceRange()))
|
||||
return true;
|
||||
else if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
|
||||
diag::err_allocation_of_abstract_type))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Every dimension shall be of constant size.
|
||||
unsigned i = 1;
|
||||
|
@ -943,11 +936,15 @@ QualType Sema::CheckPointerToMemberOperands(
|
|||
// class type) [...]
|
||||
QualType RType = rex->getType();
|
||||
const MemberPointerType *MemPtr = RType->getAsMemberPointerType();
|
||||
if (!MemPtr || MemPtr->getClass()->isIncompleteType()) {
|
||||
if (!MemPtr) {
|
||||
Diag(Loc, diag::err_bad_memptr_rhs)
|
||||
<< OpSpelling << RType << rex->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
} else if (RequireCompleteType(Loc, QualType(MemPtr->getClass(), 0),
|
||||
diag::err_memptr_rhs_incomplete,
|
||||
rex->getSourceRange()))
|
||||
return QualType();
|
||||
|
||||
QualType Class(MemPtr->getClass(), 0);
|
||||
|
||||
// C++ 5.5p2
|
||||
|
|
|
@ -59,4 +59,5 @@ void f1static() {
|
|||
register void f2register(int); // expected-error{{illegal storage class on function}}
|
||||
}
|
||||
|
||||
struct incomplete_test a(void) {} // expected-error{{result type for function definition cannot be incomplete}}
|
||||
struct incomplete_test a(void) {} // expected-error{{incomplete result type 'struct incomplete_test' in function definition}} \
|
||||
// expected-note{{forward declaration of 'struct incomplete_test'}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* RUN: clang-cc %s -fsyntax-only -pedantic -verify
|
||||
*/
|
||||
struct incomplete;
|
||||
struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}}
|
||||
|
||||
int sub1(int *a, double *b) {
|
||||
return a - b; /* expected-error{{not pointers to compatible types}} */
|
||||
|
@ -18,6 +18,10 @@ int sub4(void *P, void *Q) {
|
|||
return P-Q; /* expected-warning{{GNU void* extension}} */
|
||||
}
|
||||
|
||||
int sub5(void *P, int *Q) {
|
||||
return P-Q; /* expected-error{{not pointers to compatible types}} */
|
||||
}
|
||||
|
||||
int logicaland1(int a) {
|
||||
return a && (void)a; /* expected-error{{invalid operands}} */
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ void g() {
|
|||
void (HasMembers::*pmd)() = &HasMembers::d;
|
||||
}
|
||||
|
||||
struct Incomplete;
|
||||
struct Incomplete; // expected-note{{forward declaration}}
|
||||
|
||||
void h() {
|
||||
HasMembers hm, *phm = &hm;
|
||||
|
@ -110,12 +110,12 @@ void h() {
|
|||
(void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}}
|
||||
(void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}}
|
||||
|
||||
(void)(hm.*i); // expected-error {{right hand operand to .* must be a pointer to member of a complete class but is 'int'}}
|
||||
(void)(phm->*i); // expected-error {{right hand operand to ->* must be a pointer to member of a complete class but is 'int'}}
|
||||
(void)(hm.*i); // expected-error {{pointer-to-member}}
|
||||
(void)(phm->*i); // expected-error {{pointer-to-member}}
|
||||
|
||||
Incomplete *inc;
|
||||
int Incomplete::*pii = 0;
|
||||
(void)inc->*pii; // expected-error {{right hand operand to ->* must be a pointer to member of a complete class but is 'int struct Incomplete::*'}}
|
||||
(void)inc->*pii; // expected-error {{right hand operand is a pointer to member of incomplete type 'struct Incomplete'}}
|
||||
}
|
||||
|
||||
struct OverloadsPtrMem
|
||||
|
|
|
@ -41,6 +41,10 @@ void good_news()
|
|||
//V *pv = new (ps) V;
|
||||
}
|
||||
|
||||
struct abstract {
|
||||
virtual ~abstract() = 0;
|
||||
};
|
||||
|
||||
void bad_news(int *ip)
|
||||
{
|
||||
int i = 1;
|
||||
|
@ -66,7 +70,6 @@ void bad_news(int *ip)
|
|||
(void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}}
|
||||
(void)new (int[]); // expected-error {{array size must be specified in new expressions}}
|
||||
(void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}}
|
||||
(void)new (void ()); // expected-error {{cannot allocate function type 'void (void)' with new}}
|
||||
// Some lacking cases due to lack of sema support.
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
// Tests various places where requiring a complete type involves
|
||||
// instantiation of that type.
|
||||
|
||||
template<typename T>
|
||||
struct X {
|
||||
X(T);
|
||||
|
||||
T f; // expected-error{{data member instantiated with function type 'float (int)'}} \
|
||||
// expected-error{{data member instantiated with function type 'int (int)'}} \
|
||||
// expected-error{{data member instantiated with function type 'char (char)'}} \
|
||||
// expected-error{{data member instantiated with function type 'short (short)'}} \
|
||||
// expected-error{{data member instantiated with function type 'float (float)'}} \
|
||||
// expected-error{{data member instantiated with function type 'long (long)'}}
|
||||
};
|
||||
|
||||
X<int> f() { return 0; }
|
||||
|
||||
struct XField {
|
||||
X<float(int)> xf; // expected-note{{in instantiation of template class 'struct X<float (int)>' requested here}}
|
||||
};
|
||||
|
||||
void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) {
|
||||
(void)ptr1[i];
|
||||
(void)ptr2[i]; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}}
|
||||
}
|
||||
|
||||
void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2,
|
||||
X<char(char)> *ptr3, X<short(short)> *ptr4) {
|
||||
(void)(ptr1 + 5);
|
||||
// FIXME: if I drop the ')' after void, below, it still parses (!)
|
||||
(void)(5 + ptr2);
|
||||
(void)(ptr3 + 5); // expected-note{{in instantiation of template class 'struct X<char (char)>' requested here}}
|
||||
(void)(5 + ptr4); // expected-note{{in instantiation of template class 'struct X<short (short)>' requested here}}
|
||||
}
|
||||
|
||||
void test_new() {
|
||||
(void)new X<float>(0);
|
||||
(void)new X<float(float)>; // expected-note{{in instantiation of template class 'struct X<float (float)>' requested here}}
|
||||
}
|
||||
|
||||
void test_memptr(X<long> *p1, long X<long>::*pm1,
|
||||
X<long(long)> *p2, long (X<long(long)>::*pm2)(long)) {
|
||||
(void)(p1->*pm1);
|
||||
(void)(p2->*pm2); // expected-note{{in instantiation of template class 'struct X<long (long)>' requested here}}
|
||||
}
|
Loading…
Reference in New Issue