forked from OSchip/llvm-project
Centralize error reporting of improper uses of incomplete types in the
new DiagnoseIncompleteType. It provides additional information about struct/class/union/enum types when possible, either by pointing to the forward declaration of that type or by pointing to the definition (if we're in the process of defining that type). Fixes <rdar://problem/6500531>. llvm-svn: 62521
This commit is contained in:
parent
ababe7d47d
commit
dd430f7ec9
|
@ -36,7 +36,10 @@ DIAG(note_previous_use, NOTE,
|
|||
"previous use is here")
|
||||
DIAG(note_duplicate_case_prev, NOTE,
|
||||
"previous case defined here")
|
||||
|
||||
DIAG(note_forward_declaration, NOTE,
|
||||
"forward declaration of %0")
|
||||
DIAG(note_type_being_defined, NOTE,
|
||||
"definition of %0 is not complete until the closing '}'")
|
||||
/// note_matching - this is used as a continuation of a previous diagnostic,
|
||||
/// e.g. to specify the '(' when we expected a ')'.
|
||||
DIAG(note_matching, NOTE,
|
||||
|
@ -1117,7 +1120,7 @@ DIAG(err_func_returning_array_function, ERROR,
|
|||
DIAG(err_field_declared_as_function, ERROR,
|
||||
"field %0 declared as a function")
|
||||
DIAG(err_field_incomplete, ERROR,
|
||||
"field %0 has incomplete type")
|
||||
"field has incomplete type %0")
|
||||
DIAG(err_variable_sized_type_in_struct, EXTENSION,
|
||||
"variable sized type %0 must be at end of struct or class")
|
||||
DIAG(err_flexible_array_empty_struct, ERROR,
|
||||
|
@ -1235,6 +1238,8 @@ DIAG(err_typecheck_illegal_increment_decrement, ERROR,
|
|||
"cannot modify value of type %0")
|
||||
DIAG(err_typecheck_arithmetic_incomplete_type, ERROR,
|
||||
"arithmetic on pointer to incomplete type %0")
|
||||
DIAG(err_typecheck_pointer_arith_function_type, ERROR,
|
||||
"arithmetic on pointer to function type %0")
|
||||
DIAG(err_typecheck_decl_incomplete_type, ERROR,
|
||||
"variable has incomplete type %0")
|
||||
// FIXME: Use %select
|
||||
|
@ -1341,8 +1346,12 @@ DIAG(err_decrement_bool, ERROR,
|
|||
"cannot decrement expression of type bool")
|
||||
DIAG(warn_increment_bool, WARNING,
|
||||
"incrementing expression of type bool is deprecated")
|
||||
DIAG(err_catch_incomplete_ptr, ERROR,
|
||||
"cannot catch pointer to incomplete type %0")
|
||||
DIAG(err_catch_incomplete_ref, ERROR,
|
||||
"cannot catch reference to incomplete type %0")
|
||||
DIAG(err_catch_incomplete, ERROR,
|
||||
"cannot catch%select{| pointer to| reference to}1 incomplete type %0")
|
||||
"cannot catch incomplete type %0")
|
||||
DIAG(err_qualified_catch_declarator, ERROR,
|
||||
"exception declarator cannot be qualified")
|
||||
DIAG(err_early_catch_all, ERROR,
|
||||
|
|
|
@ -270,6 +270,11 @@ public:
|
|||
|
||||
virtual TypeResult ActOnTypeName(Scope *S, Declarator &D);
|
||||
|
||||
bool DiagnoseIncompleteType(SourceLocation Loc, QualType T, unsigned diag,
|
||||
SourceRange Range1 = SourceRange(),
|
||||
SourceRange Range2 = SourceRange(),
|
||||
QualType PrintType = QualType());
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
|
||||
//
|
||||
|
|
|
@ -705,10 +705,9 @@ 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.
|
||||
if (Param->getType()->isIncompleteType() &&
|
||||
!Param->isInvalidDecl()) {
|
||||
Diag(Param->getLocation(), diag::err_typecheck_decl_incomplete_type)
|
||||
<< Param->getType();
|
||||
if (!Param->isInvalidDecl() &&
|
||||
DiagnoseIncompleteType(Param->getLocation(), Param->getType(),
|
||||
diag::err_typecheck_decl_incomplete_type)) {
|
||||
Param->setInvalidDecl();
|
||||
HasInvalidParm = true;
|
||||
}
|
||||
|
@ -2503,10 +2502,10 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
|
|||
// no linkage (C99 6.2.2p6), the type for the object shall be complete...
|
||||
if (IDecl->isBlockVarDecl() &&
|
||||
IDecl->getStorageClass() != VarDecl::Extern) {
|
||||
if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
|
||||
Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
|
||||
if (!IDecl->isInvalidDecl() &&
|
||||
DiagnoseIncompleteType(IDecl->getLocation(), T,
|
||||
diag::err_typecheck_decl_incomplete_type))
|
||||
IDecl->setInvalidDecl();
|
||||
}
|
||||
}
|
||||
// File scope. C99 6.9.2p2: A declaration of an identifier for and
|
||||
// object that has file scope without an initializer, and without a
|
||||
|
@ -2517,13 +2516,13 @@ Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
|
|||
if (T->isIncompleteArrayType()) {
|
||||
// C99 6.9.2 (p2, p5): Implicit initialization causes an incomplete
|
||||
// array to be completed. Don't issue a diagnostic.
|
||||
} else if (T->isIncompleteType() && !IDecl->isInvalidDecl()) {
|
||||
} else if (!IDecl->isInvalidDecl() &&
|
||||
DiagnoseIncompleteType(IDecl->getLocation(), T,
|
||||
diag::err_typecheck_decl_incomplete_type))
|
||||
// C99 6.9.2p3: If the declaration of an identifier for an object is
|
||||
// a tentative definition and has internal linkage (C99 6.2.2p3), the
|
||||
// declared type shall not be an incomplete type.
|
||||
Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type)<<T;
|
||||
IDecl->setInvalidDecl();
|
||||
}
|
||||
}
|
||||
if (IDecl->isFileVarDecl())
|
||||
CheckForFileScopedRedefinitions(S, IDecl);
|
||||
|
@ -3382,7 +3381,8 @@ void Sema::ActOnFields(Scope* S,
|
|||
// 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.
|
||||
Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
|
||||
DiagnoseIncompleteType(FD->getLocation(), FD->getType(),
|
||||
diag::err_field_incomplete);
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
|
@ -3390,7 +3390,8 @@ void Sema::ActOnFields(Scope* S,
|
|||
if (i != NumFields-1 || // ... that the last member ...
|
||||
!Record->isStruct() || // ... of a structure ...
|
||||
!FDTy->isArrayType()) { //... may have incomplete array type.
|
||||
Diag(FD->getLocation(), diag::err_field_incomplete) <<FD->getDeclName();
|
||||
DiagnoseIncompleteType(FD->getLocation(), FD->getType(),
|
||||
diag::err_field_incomplete);
|
||||
FD->setInvalidDecl();
|
||||
EnclosingDecl->setInvalidDecl();
|
||||
continue;
|
||||
|
|
|
@ -339,8 +339,9 @@ Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
|
|||
// C++ [class.derived]p2:
|
||||
// The class-name in a base-specifier shall not be an incompletely
|
||||
// defined class.
|
||||
if (BaseType->isIncompleteType())
|
||||
return Diag(BaseLoc, diag::err_incomplete_base_class) << SpecifierRange;
|
||||
if (DiagnoseIncompleteType(BaseLoc, BaseType, diag::err_incomplete_base_class,
|
||||
SpecifierRange))
|
||||
return true;
|
||||
|
||||
// If the base class is polymorphic, the new one is, too.
|
||||
RecordDecl *BaseDecl = BaseType->getAsRecordType()->getDecl();
|
||||
|
@ -2179,17 +2180,19 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
|
|||
// incomplete type, other than [cv] void*.
|
||||
QualType BaseType = ExDeclType;
|
||||
int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
|
||||
unsigned DK = diag::err_catch_incomplete;
|
||||
if (const PointerType *Ptr = BaseType->getAsPointerType()) {
|
||||
BaseType = Ptr->getPointeeType();
|
||||
Mode = 1;
|
||||
DK = diag::err_catch_incomplete_ptr;
|
||||
} else if(const ReferenceType *Ref = BaseType->getAsReferenceType()) {
|
||||
BaseType = Ref->getPointeeType();
|
||||
Mode = 2;
|
||||
DK = diag::err_catch_incomplete_ref;
|
||||
}
|
||||
if ((Mode == 0 || !BaseType->isVoidType()) && BaseType->isIncompleteType()) {
|
||||
if ((Mode == 0 || !BaseType->isVoidType()) &&
|
||||
DiagnoseIncompleteType(Begin, BaseType, DK))
|
||||
Invalid = true;
|
||||
Diag(Begin, diag::err_catch_incomplete) << BaseType << Mode;
|
||||
}
|
||||
|
||||
// FIXME: Need to test for ability to copy-construct and destroy the
|
||||
// exception variable.
|
||||
|
|
|
@ -1021,10 +1021,11 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType,
|
|||
else if (exprType->isVoidType())
|
||||
Diag(OpLoc, diag::ext_sizeof_void_type)
|
||||
<< (isSizeof ? "sizeof" : "__alignof") << ExprRange;
|
||||
else if (exprType->isIncompleteType())
|
||||
return Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
|
||||
diag::err_alignof_incomplete_type)
|
||||
<< exprType << ExprRange;
|
||||
else
|
||||
return DiagnoseIncompleteType(OpLoc, exprType,
|
||||
isSizeof ? diag::err_sizeof_incomplete_type :
|
||||
diag::err_alignof_incomplete_type,
|
||||
ExprRange);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1466,9 +1467,11 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
// of the ObjC 'id' struct.
|
||||
if (const RecordType *RTy = BaseType->getAsRecordType()) {
|
||||
RecordDecl *RDecl = RTy->getDecl();
|
||||
if (RTy->isIncompleteType())
|
||||
return ExprError(Diag(OpLoc, diag::err_typecheck_incomplete_tag)
|
||||
<< RDecl->getDeclName() << BaseExpr->getSourceRange());
|
||||
if (DiagnoseIncompleteType(OpLoc, BaseType,
|
||||
diag::err_typecheck_incomplete_tag,
|
||||
BaseExpr->getSourceRange()))
|
||||
return ExprError();
|
||||
|
||||
// The record definition is complete, now make sure the member is valid.
|
||||
// FIXME: Qualified name lookup for C++ is a bit more complicated
|
||||
// than this.
|
||||
|
@ -1906,11 +1909,10 @@ ActOnCompoundLiteral(SourceLocation LParenLoc, TypeTy *Ty,
|
|||
if (literalType->isVariableArrayType())
|
||||
return Diag(LParenLoc, diag::err_variable_object_no_init)
|
||||
<< SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
|
||||
} else if (literalType->isIncompleteType()) {
|
||||
return Diag(LParenLoc, diag::err_typecheck_decl_incomplete_type)
|
||||
<< literalType
|
||||
<< SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd());
|
||||
}
|
||||
} else if (DiagnoseIncompleteType(LParenLoc, literalType,
|
||||
diag::err_typecheck_decl_incomplete_type,
|
||||
SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd())))
|
||||
return true;
|
||||
|
||||
if (CheckInitializerTypes(literalExpr, literalType, LParenLoc,
|
||||
DeclarationName(), /*FIXME:DirectInit=*/false))
|
||||
|
@ -2643,10 +2645,16 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
|||
if (PTy->getPointeeType()->isVoidType()) {
|
||||
Diag(Loc, diag::ext_gnu_void_ptr)
|
||||
<< lex->getSourceRange() << rex->getSourceRange();
|
||||
} else {
|
||||
Diag(Loc, diag::err_typecheck_arithmetic_incomplete_type)
|
||||
} else if (PTy->getPointeeType()->isFunctionType()) {
|
||||
Diag(Loc, diag::err_typecheck_pointer_arith_function_type)
|
||||
<< lex->getType() << lex->getSourceRange();
|
||||
return QualType();
|
||||
} else {
|
||||
DiagnoseIncompleteType(Loc, PTy->getPointeeType(),
|
||||
diag::err_typecheck_arithmetic_incomplete_type,
|
||||
lex->getSourceRange(), SourceRange(),
|
||||
lex->getType());
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
return PExp->getType();
|
||||
|
@ -3038,9 +3046,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|||
break;
|
||||
case Expr::MLV_IncompleteType:
|
||||
case Expr::MLV_IncompleteVoidType:
|
||||
Diag = diag::err_typecheck_incomplete_type_not_modifiable_lvalue;
|
||||
NeedType = true;
|
||||
break;
|
||||
return S.DiagnoseIncompleteType(Loc, E->getType(),
|
||||
diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
|
||||
E->getSourceRange());
|
||||
case Expr::MLV_DuplicateVectorComponents:
|
||||
Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
|
||||
break;
|
||||
|
@ -3155,10 +3163,16 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
|
|||
} else if (PT->getPointeeType()->isVoidType()) {
|
||||
// Pointer to void is extension.
|
||||
Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
|
||||
} else {
|
||||
Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type)
|
||||
} else if (PT->getPointeeType()->isFunctionType()) {
|
||||
Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
|
||||
<< ResType << Op->getSourceRange();
|
||||
return QualType();
|
||||
} else {
|
||||
DiagnoseIncompleteType(OpLoc, PT->getPointeeType(),
|
||||
diag::err_typecheck_arithmetic_incomplete_type,
|
||||
Op->getSourceRange(), SourceRange(),
|
||||
ResType);
|
||||
return QualType();
|
||||
}
|
||||
} else if (ResType->isComplexType()) {
|
||||
// C99 does not support ++/-- on complex types, we allow as an extension.
|
||||
|
|
|
@ -172,9 +172,10 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
|
|||
//
|
||||
if (Ty->isArrayType())
|
||||
return Diag(TyBeginLoc, diag::err_value_init_for_array_type) << FullRange;
|
||||
if (!Ty->isDependentType() && Ty->isIncompleteType() && !Ty->isVoidType())
|
||||
return Diag(TyBeginLoc, diag::err_invalid_incomplete_type_use)
|
||||
<< Ty << FullRange;
|
||||
if (!Ty->isDependentType() && !Ty->isVoidType() &&
|
||||
DiagnoseIncompleteType(TyBeginLoc, Ty,
|
||||
diag::err_invalid_incomplete_type_use, FullRange))
|
||||
return true;
|
||||
|
||||
return new CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc);
|
||||
}
|
||||
|
@ -578,9 +579,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
|
|||
}
|
||||
|
||||
QualType Pointee = Type->getAsPointerType()->getPointeeType();
|
||||
if (Pointee->isIncompleteType() && !Pointee->isVoidType())
|
||||
Diag(StartLoc, diag::warn_delete_incomplete)
|
||||
<< Pointee << Ex->getSourceRange();
|
||||
if (!Pointee->isVoidType() &&
|
||||
DiagnoseIncompleteType(StartLoc, Pointee, diag::warn_delete_incomplete,
|
||||
Ex->getSourceRange()))
|
||||
return true;
|
||||
else if (!Pointee->isObjectType()) {
|
||||
Diag(StartLoc, diag::err_delete_operand)
|
||||
<< Type << Ex->getSourceRange();
|
||||
|
|
|
@ -685,11 +685,10 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
|||
if (DestPointee->isVoidType()) {
|
||||
assert(DestPointer && "Reference to void is not possible");
|
||||
} else if (DestRecord) {
|
||||
if (!DestRecord->getDecl()->isDefinition()) {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_incomplete)
|
||||
<< DestPointee.getUnqualifiedType() << DestRange;
|
||||
if (Self.DiagnoseIncompleteType(OpRange.getBegin(), DestPointee,
|
||||
diag::err_bad_dynamic_cast_incomplete,
|
||||
DestRange))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
|
||||
<< DestPointee.getUnqualifiedType() << DestRange;
|
||||
|
@ -720,11 +719,10 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
|||
|
||||
const RecordType *SrcRecord = SrcPointee->getAsRecordType();
|
||||
if (SrcRecord) {
|
||||
if (!SrcRecord->getDecl()->isDefinition()) {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_incomplete)
|
||||
<< SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
|
||||
if (Self.DiagnoseIncompleteType(OpRange.getBegin(), SrcPointee,
|
||||
diag::err_bad_dynamic_cast_incomplete,
|
||||
SrcExpr->getSourceRange()))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
|
||||
<< SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange();
|
||||
|
|
|
@ -352,9 +352,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
|
|||
|
||||
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
|
||||
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
|
||||
if (T->isIncompleteType()) {
|
||||
Diag(D.getIdentifierLoc(), diag::err_illegal_decl_array_incomplete_type)
|
||||
<< T;
|
||||
if (DiagnoseIncompleteType(D.getIdentifierLoc(), T,
|
||||
diag::err_illegal_decl_array_incomplete_type)) {
|
||||
T = Context.IntTy;
|
||||
D.setInvalidType(true);
|
||||
} else if (T->isFunctionType()) {
|
||||
|
@ -690,4 +689,67 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief If the type T is incomplete and cannot be completed,
|
||||
/// produce a suitable diagnostic.
|
||||
///
|
||||
/// This routine checks whether the type @p T is complete in any
|
||||
/// context where a complete type is required. If @p T is a complete
|
||||
/// type, returns false. If @p T is incomplete, issues the diagnostic
|
||||
/// @p diag (giving it the type @p T) and returns true.
|
||||
///
|
||||
/// @param Loc The location in the source that the incomplete type
|
||||
/// diagnostic should refer to.
|
||||
///
|
||||
/// @param T The type that this routine is examining for completeness.
|
||||
///
|
||||
/// @param diag The diagnostic value (e.g.,
|
||||
/// @c diag::err_typecheck_decl_incomplete_type) that will be used
|
||||
/// for the error message if @p T is incomplete.
|
||||
///
|
||||
/// @param Range1 An optional range in the source code that will be a
|
||||
/// part of the "incomplete type" error message.
|
||||
///
|
||||
/// @param Range2 An optional range in the source code that will be a
|
||||
/// part of the "incomplete type" error message.
|
||||
///
|
||||
/// @param PrintType If non-NULL, the type that should be printed
|
||||
/// instead of @p T. This parameter should be used when the type that
|
||||
/// we're checking for incompleteness isn't the type that should be
|
||||
/// displayed to the user, e.g., when T is a type and PrintType is a
|
||||
/// pointer to T.
|
||||
///
|
||||
/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
|
||||
/// @c false otherwise.
|
||||
///
|
||||
/// @todo When Clang gets proper support for C++ templates, this
|
||||
/// routine will also be able perform template instantiation when @p T
|
||||
/// is a class template specialization.
|
||||
bool Sema::DiagnoseIncompleteType(SourceLocation Loc, QualType T, unsigned diag,
|
||||
SourceRange Range1, SourceRange Range2,
|
||||
QualType PrintType) {
|
||||
// If we have a complete type, we're done.
|
||||
if (!T->isIncompleteType())
|
||||
return false;
|
||||
|
||||
if (PrintType.isNull())
|
||||
PrintType = T;
|
||||
|
||||
// We have an incomplete type. Produce a diagnostic.
|
||||
Diag(Loc, diag) << PrintType << Range1 << Range2;
|
||||
|
||||
// If the type was a forward declaration of a class/struct/union
|
||||
// type, produce
|
||||
const TagType *Tag = 0;
|
||||
if (const RecordType *Record = T->getAsRecordType())
|
||||
Tag = Record;
|
||||
else if (const EnumType *Enum = T->getAsEnumType())
|
||||
Tag = Enum;
|
||||
|
||||
if (Tag && !Tag->getDecl()->isInvalidDecl())
|
||||
Diag(Tag->getDecl()->getLocation(),
|
||||
Tag->isBeingDefined() ? diag::note_type_being_defined
|
||||
: diag::note_forward_declaration)
|
||||
<< QualType(Tag, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,6 @@ int test6248081() {
|
|||
[10] // expected-error {{expected expression}}
|
||||
}
|
||||
|
||||
struct forward;
|
||||
struct forward; // expected-note{{forward declaration of 'struct forward'}}
|
||||
void x(struct forward* x) {switch(x->a) {}} // expected-error {{incomplete definition of type}}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: clang -fsyntax-only -verify -pedantic %s
|
||||
|
||||
struct s;
|
||||
struct s; // expected-note {{forward declaration of 'struct s'}}
|
||||
struct s* t (struct s z[]) { // expected-error {{array has incomplete element type}}
|
||||
return z;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ int main(int argc, char **argv) {
|
|||
fooFunc(&(struct foo){ 1, 2 });
|
||||
}
|
||||
|
||||
struct Incomplete;
|
||||
struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}}
|
||||
struct Incomplete* I1 = &(struct Incomplete){1, 2, 3}; // -expected-error {{variable has incomplete type}}
|
||||
void IncompleteFunc(unsigned x) {
|
||||
struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // -expected-error {{variable-sized object may not be initialized}}
|
||||
|
|
|
@ -21,7 +21,9 @@ int test() {
|
|||
return sizeof(enum e) ;
|
||||
}
|
||||
|
||||
enum gccForwardEnumExtension ve; // expected-error {{variable has incomplete type 'enum gccForwardEnumExtension'}} expected-warning{{ISO C forbids forward references to 'enum' types}}
|
||||
enum gccForwardEnumExtension ve; // expected-error {{variable has incomplete type 'enum gccForwardEnumExtension'}} \
|
||||
// expected-warning{{ISO C forbids forward references to 'enum' types}} \
|
||||
// expected-note{{forward declaration of 'enum gccForwardEnumExtension'}}
|
||||
|
||||
int test2(int i)
|
||||
{
|
||||
|
@ -52,7 +54,7 @@ enum someenum {}; // expected-warning {{use of empty enum extension}}
|
|||
|
||||
// <rdar://problem/6093889>
|
||||
enum e0 { // expected-note {{previous definition is here}}
|
||||
E0 = sizeof(enum e0 { E1 }) // expected-error {{nested redefinition}}
|
||||
E0 = sizeof(enum e0 { E1 }), // expected-error {{nested redefinition}}
|
||||
};
|
||||
|
||||
// PR3173
|
||||
|
@ -66,3 +68,8 @@ void foo() {
|
|||
|
||||
// <rdar://problem/6503878>
|
||||
typedef enum { X = 0 }; // expected-warning{{typedef requires a name}}
|
||||
|
||||
|
||||
enum NotYetComplete { // expected-note{{definition of 'enum NotYetComplete' is not complete until the closing '}'}}
|
||||
NYC1 = sizeof(enum NotYetComplete) // expected-error{{invalid application of 'sizeof' to an incomplete type 'enum NotYetComplete'}}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
struct foo; // expected-note {{forward declaration of 'struct foo'}}
|
||||
|
||||
void b; // expected-error {{variable has incomplete type 'void'}}
|
||||
struct foo f; // expected-error {{variable has incomplete type 'struct foo'}}
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ int sym_fw1a_scr[] = {
|
|||
|
||||
// PR3001
|
||||
struct s1 s2 = {
|
||||
.a = sizeof(struct s3), // expected-error {{invalid application of 'sizeof'}}
|
||||
.a = sizeof(struct s3), // expected-error {{invalid application of 'sizeof'}} \
|
||||
// expected-note{{forward declaration of 'struct s3'}}
|
||||
.b = bogus // expected-error {{use of undeclared identifier 'bogus'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: clang %s -fsyntax-only -verify -pedantic
|
||||
|
||||
typedef struct S S;
|
||||
typedef struct S S; // expected-note{{forward declaration of 'struct S'}}
|
||||
void a(S* b, void* c) {
|
||||
b++; // expected-error {{arithmetic on pointer to incomplete type}}
|
||||
b += 1; // expected-error {{arithmetic on pointer to incomplete type}}
|
||||
|
@ -9,6 +9,6 @@ void a(S* b, void* c) {
|
|||
b = 1+b; // expected-error {{arithmetic on pointer to incomplete type}}
|
||||
/* The next couple tests are only pedantic warnings in gcc */
|
||||
void (*d)(S*,void*) = a;
|
||||
d += 1; // expected-error {{pointer to incomplete type}}
|
||||
d++; // expected-error {{pointer to incomplete type}}
|
||||
d += 1; // expected-error {{arithmetic on pointer to function type}}}
|
||||
d++; // expected-error {{arithmetic on pointer to function type}}}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ struct D : private A {};
|
|||
struct E : A {};
|
||||
struct F : B, E {};
|
||||
|
||||
struct Incomplete;
|
||||
struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}}
|
||||
|
||||
struct Poly
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ struct S // expected-note {{candidate}}
|
|||
S(double, int); // expected-note {{candidate}} expected-note {{candidate}}
|
||||
S(float, int); // expected-note {{candidate}} expected-note {{candidate}}
|
||||
};
|
||||
struct T;
|
||||
struct T; // expected-note{{forward declaration of 'struct T'}}
|
||||
struct U
|
||||
{
|
||||
// A special new, to verify that the global version isn't used.
|
||||
|
|
|
@ -96,7 +96,7 @@ void test_a() {
|
|||
a::a::a::i = 4;
|
||||
}
|
||||
|
||||
struct Undef {
|
||||
struct Undef { // expected-note{{definition of 'struct Undef' is not complete until the closing '}'}}
|
||||
typedef int type;
|
||||
|
||||
Undef::type member;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
struct A;
|
||||
struct A; // expected-note{{forward declaration of 'struct A'}}
|
||||
|
||||
void f()
|
||||
{
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
struct S;
|
||||
struct S; // expected-note{{forward declaration of 'struct S'}}
|
||||
typedef int FOO();
|
||||
|
||||
@interface INTF
|
||||
{
|
||||
struct F {} JJ;
|
||||
int arr[]; // expected-error {{field 'arr' has incomplete type}}
|
||||
struct S IC; // expected-error {{field 'IC' has incomplete type}}
|
||||
int arr[]; // expected-error {{field has incomplete type}}
|
||||
struct S IC; // expected-error {{field has incomplete type}}
|
||||
struct T { // expected-note {{previous definition is here}}
|
||||
struct T {} X; // expected-error {{nested redefinition of 'T'}}
|
||||
}YYY;
|
||||
FOO BADFUNC; // expected-error {{field 'BADFUNC' declared as a function}}
|
||||
int kaka; // expected-note {{previous declaration is here}}
|
||||
int kaka; // expected-error {{duplicate member 'kaka'}}
|
||||
char ch[]; // expected-error {{field 'ch' has incomplete type}}
|
||||
char ch[]; // expected-error {{field has incomplete type}}
|
||||
}
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue