From: Douglas Gregor Date: Mon, 19 Jan 2009 19:26:10 +0000 (+0000) Subject: Centralize error reporting of improper uses of incomplete types in the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4ec339f43c0cae2678334850c90926bea10999c7;p=clang 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62521 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 5db09e7f26..2436727ea1 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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, diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 40c9a99c7b..fa4301beb6 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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. // diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cff01c6530..fe604960f7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/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)<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)<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) <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) <getDeclName(); + DiagnoseIncompleteType(FD->getLocation(), FD->getType(), + diag::err_field_incomplete); FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 33a31c7500..95f920063d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index be87ee9c49..fb83cabd2d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 09db18ea54..8958221ef5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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(); diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp index 3d3572d00c..06fc9d83ba 100644 --- a/lib/Sema/SemaNamedCast.cpp +++ b/lib/Sema/SemaNamedCast.cpp @@ -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(); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8a459f4d3e..ecae79320d 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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; +} diff --git a/test/Parser/recovery.c b/test/Parser/recovery.c index 430d3c1caa..b6ba9e6294 100644 --- a/test/Parser/recovery.c +++ b/test/Parser/recovery.c @@ -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}} diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c index 596d19f77c..69475b76f6 100644 --- a/test/Sema/array-constraint.c +++ b/test/Sema/array-constraint.c @@ -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; } diff --git a/test/Sema/compound-literal.c b/test/Sema/compound-literal.c index c053a59fa7..e457c72bee 100644 --- a/test/Sema/compound-literal.c +++ b/test/Sema/compound-literal.c @@ -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}} diff --git a/test/Sema/enum.c b/test/Sema/enum.c index ea66c27aef..55ddb0ddd9 100644 --- a/test/Sema/enum.c +++ b/test/Sema/enum.c @@ -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}} // 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() { // 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'}} +}; diff --git a/test/Sema/incomplete-decl.c b/test/Sema/incomplete-decl.c index fedf2c69f7..bd603681d6 100644 --- a/test/Sema/incomplete-decl.c +++ b/test/Sema/incomplete-decl.c @@ -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'}} diff --git a/test/Sema/init.c b/test/Sema/init.c index 72586b13c4..abfab37b43 100644 --- a/test/Sema/init.c +++ b/test/Sema/init.c @@ -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'}} } diff --git a/test/Sema/pointer-addition.c b/test/Sema/pointer-addition.c index f2fb973d1b..95f364fc67 100644 --- a/test/Sema/pointer-addition.c +++ b/test/Sema/pointer-addition.c @@ -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}}} } diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp index 8b0b748801..654f2e41bc 100644 --- a/test/SemaCXX/dynamic-cast.cpp +++ b/test/SemaCXX/dynamic-cast.cpp @@ -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 { diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index fa19c6a055..ce96897e1f 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -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. diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp index cf86971f35..e5721e00ee 100644 --- a/test/SemaCXX/qualified-id-lookup.cpp +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -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; diff --git a/test/SemaCXX/try-catch.cpp b/test/SemaCXX/try-catch.cpp index 97dbaee10d..0d72f119df 100644 --- a/test/SemaCXX/try-catch.cpp +++ b/test/SemaCXX/try-catch.cpp @@ -1,6 +1,6 @@ // RUN: clang -fsyntax-only -verify %s -struct A; +struct A; // expected-note{{forward declaration of 'struct A'}} void f() { diff --git a/test/SemaObjC/ivar-sem-check-1.m b/test/SemaObjC/ivar-sem-check-1.m index a6d1a22a91..1ec4e57ce8 100644 --- a/test/SemaObjC/ivar-sem-check-1.m +++ b/test/SemaObjC/ivar-sem-check-1.m @@ -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