From b1402ae94eb7ca0f52b358aaf8eae13247114bf7 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 18 Mar 2013 22:52:47 +0000 Subject: [PATCH] Add missing diagnostic for a nested-name-specifier on a free-standing type definition. Bump some related diagnostics from warning to extension in C++, since they're errors there. Add some missing checks for function specifiers on non-function declarations. llvm-svn: 177335 --- clang/include/clang/Basic/DiagnosticCommonKinds.td | 2 - clang/include/clang/Basic/DiagnosticSemaKinds.td | 10 +- clang/include/clang/Sema/Sema.h | 5 +- clang/lib/Parse/ParseTemplate.cpp | 8 +- clang/lib/Sema/SemaDecl.cpp | 163 ++++++++++++--------- clang/lib/Sema/SemaDeclObjC.cpp | 2 +- .../test/CodeGenCXX/debug-info-use-after-free.cpp | 3 +- clang/test/Misc/warning-flags.c | 3 +- clang/test/Parser/c11-noreturn.c | 6 +- clang/test/Parser/cxx-class.cpp | 11 ++ clang/test/Sema/anonymous-struct-union.c | 2 +- clang/test/Sema/decl-invalid.c | 4 +- clang/test/Sema/declspec.c | 2 +- clang/test/Sema/struct-decl.c | 2 +- clang/test/SemaCXX/anonymous-union.cpp | 2 +- clang/test/SemaCXX/storage-class.cpp | 2 +- 16 files changed, 140 insertions(+), 87 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 7dccb73..14fbe39 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -52,8 +52,6 @@ def err_invalid_numeric_udl : Error< "numeric literal with user-defined suffix cannot be used here">; // Parse && Sema -def ext_no_declarators : ExtWarn<"declaration does not declare anything">, - InGroup; def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6556c12..d23df6c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -411,6 +411,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " "platform-specific data}0) must be of type %1">; /// parser diagnostics +def ext_no_declarators : ExtWarn<"declaration does not declare anything">, + InGroup; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">, InGroup; def err_typedef_not_identifier : Error<"typedef name must be an identifier">; @@ -4180,7 +4182,13 @@ def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; def err_unsupported_global_register : Error< "global register variables are not supported">; -def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">; +def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">, + InGroup; +def ext_standalone_specifier : ExtWarn<"'%0' is not permitted on a declaration " + "of a type">, InGroup; +def err_standalone_class_nested_name_specifier : Error< + "forward declaration of %select{class|struct|interface|union|enum}0 cannot " + "have a nested name specifier">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e8b4f55..9205e2a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1357,7 +1357,7 @@ public: bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc); - void DiagnoseFunctionSpecifiers(Declarator& D); + void DiagnoseFunctionSpecifiers(const DeclSpec &DS); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); @@ -1516,7 +1516,8 @@ public: DeclSpec &DS); Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - MultiTemplateParamsArg TemplateParams); + MultiTemplateParamsArg TemplateParams, + bool IsExplicitInstantiation = false); Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 32a78a7..1327dd5 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -214,7 +214,11 @@ Parser::ParseSingleDeclarationAfterTemplate( if (Tok.is(tok::semi)) { ProhibitAttributes(prefixAttrs); DeclEnd = ConsumeToken(); - Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); + Decl *Decl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS, DS, + TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams + : MultiTemplateParamsArg(), + TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation); DS.complete(Decl); return Decl; } @@ -1196,7 +1200,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { /// explicit-instantiation: /// 'extern' [opt] 'template' declaration /// -/// Note that the 'extern' is a GNU extension and C++0x feature. +/// Note that the 'extern' is a GNU extension and C++11 feature. Decl *Parser::ParseExplicitInstantiation(unsigned Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 245bc2c..b3edc5e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2984,11 +2984,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with -/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - MultiTemplateParamsArg TemplateParams) { + MultiTemplateParamsArg TemplateParams, + bool IsExplicitInstantiation) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -3041,6 +3042,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return TagD; } + DiagnoseFunctionSpecifiers(DS); + if (DS.isFriendSpecified()) { // If we're dealing with a decl but not a TagDecl, assume that // whatever routines created it handled the friendship aspect. @@ -3049,10 +3052,28 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ActOnFriendTypeDecl(S, DS, TemplateParams); } - // Track whether we warned about the fact that there aren't any - // declarators. - bool emittedWarning = false; - + CXXScopeSpec &SS = DS.getTypeSpecScope(); + bool IsExplicitSpecialization = + !TemplateParams.empty() && TemplateParams.back()->size() == 0; + if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && + !IsExplicitInstantiation && !IsExplicitSpecialization) { + // Per C++ [dcl.type.elab]p1, a class declaration cannot have a + // nested-name-specifier unless it is an explicit instantiation + // or an explicit specialization. + // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. + Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) + << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : + DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : + DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4) + << SS.getRange(); + return 0; + } + + // Track whether this decl-specifier declares anything. + bool DeclaresAnything = true; + + // Handle anonymous struct definitions. if (RecordDecl *Record = dyn_cast_or_null(Tag)) { if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { @@ -3060,13 +3081,11 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Record->getDeclContext()->isRecord()) return BuildAnonymousStructOrUnion(S, DS, AS, Record); - Diag(DS.getLocStart(), diag::ext_no_declarators) - << DS.getSourceRange(); - emittedWarning = true; + DeclaresAnything = false; } } - // Check for Microsoft C extension: anonymous struct. + // Check for Microsoft C extension: anonymous struct member. if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { @@ -3083,70 +3102,80 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return BuildMicrosoftCAnonymousStruct(S, DS, Record); } } - - if (getLangOpts().CPlusPlus && + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error || + (TagD && TagD->isInvalidDecl())) + return TagD; + + if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) if (EnumDecl *Enum = dyn_cast_or_null(Tag)) if (Enum->enumerator_begin() == Enum->enumerator_end() && - !Enum->getIdentifier() && !Enum->isInvalidDecl()) { - Diag(Enum->getLocation(), diag::ext_no_declarators) - << DS.getSourceRange(); - emittedWarning = true; - } + !Enum->getIdentifier() && !Enum->isInvalidDecl()) + DeclaresAnything = false; - // Skip all the checks below if we have a type error. - if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD; - if (!DS.isMissingDeclaratorOk()) { - // Warn about typedefs of enums without names, since this is an - // extension in both Microsoft and GNU. - if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && - Tag && isa(Tag)) { + // Customize diagnostic for a typedef missing a name. + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) << DS.getSourceRange(); - return Tag; - } - - Diag(DS.getLocStart(), diag::ext_no_declarators) - << DS.getSourceRange(); - emittedWarning = true; + else + DeclaresAnything = false; } - // We're going to complain about a bunch of spurious specifiers; - // only do this if we're declaring a tag, because otherwise we - // should be getting diag::ext_no_declarators. - if (emittedWarning || (TagD && TagD->isInvalidDecl())) + if (DS.isModulePrivateSpecified() && + Tag && Tag->getDeclContext()->isFunctionOrMethod()) + Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) + << Tag->getTagKind() + << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); + + ActOnDocumentableDecl(TagD); + + // C 6.7/2: + // A declaration [...] shall declare at least a declarator [...], a tag, + // or the members of an enumeration. + // C++ [dcl.dcl]p3: + // [If there are no declarators], and except for the declaration of an + // unnamed bit-field, the decl-specifier-seq shall introduce one or more + // names into the program, or shall redeclare a name introduced by a + // previous declaration. + if (!DeclaresAnything) { + // In C, we allow this as a (popular) extension / bug. Don't bother + // producing further diagnostics for redundant qualifiers after this. + Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); return TagD; + } + + // C++ [dcl.stc]p1: + // If a storage-class-specifier appears in a decl-specifier-seq, [...] the + // init-declarator-list of the declaration shall not be empty. + // C++ [dcl.fct.spec]p1: + // If a cv-qualifier appears in a decl-specifier-seq, the + // init-declarator-list of the declaration shall not be empty. + // + // Spurious qualifiers here appear to be valid in C. + unsigned DiagID = diag::warn_standalone_specifier; + if (getLangOpts().CPlusPlus) + DiagID = diag::ext_standalone_specifier; // Note that a linkage-specification sets a storage class, but // 'extern "C" struct foo;' is actually valid and not theoretically // useless. - if (DeclSpec::SCS scs = DS.getStorageClassSpec()) - if (!DS.isExternInLinkageSpec()) - Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier) - << DeclSpec::getSpecifierName(scs); + if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef) + Diag(DS.getStorageClassSpecLoc(), DiagID) + << DeclSpec::getSpecifierName(SCS); if (DS.isThreadSpecified()) - Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + Diag(DS.getThreadSpecLoc(), DiagID) << "__thread"; if (DS.getTypeQualifiers()) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) - Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + Diag(DS.getConstSpecLoc(), DiagID) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) - Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + Diag(DS.getConstSpecLoc(), DiagID) << "volatile"; // Restrict is covered above. } - if (DS.isInlineSpecified()) - Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline"; - if (DS.isVirtualSpecified()) - Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual"; - if (DS.isExplicitSpecified()) - Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; - - if (DS.isModulePrivateSpecified() && - Tag && Tag->getDeclContext()->isFunctionOrMethod()) - Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) - << Tag->getTagKind() - << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); // Warn about ignored type attributes, for example: // __attribute__((aligned)) struct A; @@ -3171,8 +3200,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } } - ActOnDocumentableDecl(TagD); - return TagD; } @@ -4349,23 +4376,23 @@ Sema::findLocallyScopedExternCDecl(DeclarationName Name) { /// \brief Diagnose function specifiers on a declaration of an identifier that /// does not identify a function. -void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { +void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { // FIXME: We should probably indicate the identifier in question to avoid // confusion for constructs like "inline int a(), b;" - if (D.getDeclSpec().isInlineSpecified()) - Diag(D.getDeclSpec().getInlineSpecLoc(), + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function); - if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); - if (D.getDeclSpec().isExplicitSpecified()) - Diag(D.getDeclSpec().getExplicitSpecLoc(), + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::err_explicit_non_function); - if (D.getDeclSpec().isNoreturnSpecified()) - Diag(D.getDeclSpec().getNoreturnSpecLoc(), + if (DS.isNoreturnSpecified()) + Diag(DS.getNoreturnSpecLoc(), diag::err_noreturn_non_function); } @@ -4382,7 +4409,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous.clear(); } - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); @@ -4665,7 +4692,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, return 0; } - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (!DC->isRecord() && S->getFnParent() == 0) { // C99 6.9p2: The storage-class specifiers auto and register shall not @@ -8144,7 +8171,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType parmDeclType = TInfo->getType(); @@ -10235,7 +10262,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, D.setInvalidType(); } - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 66fdc67..759f6c9 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3187,7 +3187,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); D.getMutableDeclSpec().ClearStorageClassSpecs(); - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); // Check that there are no default arguments inside the type of this // exception object (C++ only). diff --git a/clang/test/CodeGenCXX/debug-info-use-after-free.cpp b/clang/test/CodeGenCXX/debug-info-use-after-free.cpp index 9757ca4..852e148 100644 --- a/clang/test/CodeGenCXX/debug-info-use-after-free.cpp +++ b/clang/test/CodeGenCXX/debug-info-use-after-free.cpp @@ -192,6 +192,7 @@ __gnu_cxx { public: typedef _EqualKey key_equal; + typedef void key_type; }; using std::equal_to; @@ -217,7 +218,7 @@ __gnu_cxx { _Alloc > _Ht; public: - typename _Ht::key_type; + typedef typename _Ht::key_type key_type; typedef typename _Ht::key_equal key_equal; diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c index 931de83..a6dc8f1 100644 --- a/clang/test/Misc/warning-flags.c +++ b/clang/test/Misc/warning-flags.c @@ -18,7 +18,7 @@ This test serves two purposes: The list of warnings below should NEVER grow. It should gradually shrink to 0. -CHECK: Warnings without flags (144): +CHECK: Warnings without flags (143): CHECK-NEXT: ext_delete_void_ptr_operand CHECK-NEXT: ext_enum_friend CHECK-NEXT: ext_expected_semi_decl_list @@ -148,7 +148,6 @@ CHECK-NEXT: warn_related_result_type_compatibility_class CHECK-NEXT: warn_related_result_type_compatibility_protocol CHECK-NEXT: warn_second_parameter_of_va_start_not_last_named_argument CHECK-NEXT: warn_second_parameter_to_va_arg_never_compatible -CHECK-NEXT: warn_standalone_specifier CHECK-NEXT: warn_static_inline_explicit_inst_ignored CHECK-NEXT: warn_static_non_static CHECK-NEXT: warn_template_export_unsupported diff --git a/clang/test/Parser/c11-noreturn.c b/clang/test/Parser/c11-noreturn.c index 7a2fe50..e61901d 100644 --- a/clang/test/Parser/c11-noreturn.c +++ b/clang/test/Parser/c11-noreturn.c @@ -4,11 +4,15 @@ _Noreturn int f(); int _Noreturn f(); // expected-note {{previous}} int f _Noreturn(); // expected-error {{expected ';'}} expected-error 2{{}} -int f() _Noreturn; // expected-error {{expected ';'}} expected-warning {{does not declare anything}} +int f() _Noreturn; // expected-error {{expected ';'}} expected-warning {{does not declare anything}} expected-error {{'_Noreturn' can only appear on functions}} _Noreturn char c1; // expected-error {{'_Noreturn' can only appear on functions}} char _Noreturn c2; // expected-error {{'_Noreturn' can only appear on functions}} typedef _Noreturn int g(); // expected-error {{'_Noreturn' can only appear on functions}} +_Noreturn int; // expected-error {{'_Noreturn' can only appear on functions}} expected-warning {{does not declare anything}} +_Noreturn struct S; // expected-error {{'_Noreturn' can only appear on functions}} +_Noreturn enum E { e }; // expected-error {{'_Noreturn' can only appear on functions}} + // CHECK-EXT: _Noreturn functions are a C11-specific feature diff --git a/clang/test/Parser/cxx-class.cpp b/clang/test/Parser/cxx-class.cpp index 8ed5882..5fac797 100644 --- a/clang/test/Parser/cxx-class.cpp +++ b/clang/test/Parser/cxx-class.cpp @@ -88,6 +88,17 @@ namespace ctor_error { // expected-error{{unknown type name 'UnknownType'}} } +namespace nns_decl { + struct A { + struct B; + }; + namespace N { + union C; + } + struct A::B; // expected-error {{forward declaration of struct cannot have a nested name specifier}} + union N::C; // expected-error {{forward declaration of union cannot have a nested name specifier}} +} + // PR13775: Don't assert here. namespace PR13775 { class bar diff --git a/clang/test/Sema/anonymous-struct-union.c b/clang/test/Sema/anonymous-struct-union.c index e082290..35d3175 100644 --- a/clang/test/Sema/anonymous-struct-union.c +++ b/clang/test/Sema/anonymous-struct-union.c @@ -78,7 +78,7 @@ void g() { struct s0 { union { int f0; }; }; // -typedef struct { }; // expected-warning{{declaration does not declare anything}} +typedef struct { }; // expected-warning{{typedef requires a name}} // PR3675 struct s1 { diff --git a/clang/test/Sema/decl-invalid.c b/clang/test/Sema/decl-invalid.c index f6fed3c..0544304 100644 --- a/clang/test/Sema/decl-invalid.c +++ b/clang/test/Sema/decl-invalid.c @@ -1,7 +1,7 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify // See Sema::ParsedFreeStandingDeclSpec about the double diagnostic -typedef union __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} expected-warning {{declaration does not declare anything}} +typedef union __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} expected-warning {{typedef requires a name}} // PR2017 @@ -14,7 +14,7 @@ int a() { } int; // expected-warning {{declaration does not declare anything}} -typedef int; // expected-warning {{declaration does not declare anything}} +typedef int; // expected-warning {{typedef requires a name}} const int; // expected-warning {{declaration does not declare anything}} struct; // expected-error {{declaration of anonymous struct must be a definition}} // expected-warning {{declaration does not declare anything}} typedef int I; diff --git a/clang/test/Sema/declspec.c b/clang/test/Sema/declspec.c index 7354028..30c0092 100644 --- a/clang/test/Sema/declspec.c +++ b/clang/test/Sema/declspec.c @@ -10,7 +10,7 @@ int typedef validTypeDecl() { } // expected-error {{function definition declared struct _zend_module_entry { } // expected-error {{expected ';' after struct}} int gv1; typedef struct _zend_function_entry { } // expected-error {{expected ';' after struct}} \ - // expected-warning {{declaration does not declare anything}} + // expected-warning {{typedef requires a name}} int gv2; static void buggy(int *x) { } diff --git a/clang/test/Sema/struct-decl.c b/clang/test/Sema/struct-decl.c index 6070e87..819e856 100644 --- a/clang/test/Sema/struct-decl.c +++ b/clang/test/Sema/struct-decl.c @@ -54,6 +54,6 @@ static struct test1 { // expected-warning {{'static' ignored on this declaration const struct test2 { // expected-warning {{'const' ignored on this declaration}} int x; }; -inline struct test3 { // expected-warning {{'inline' ignored on this declaration}} +inline struct test3 { // expected-error {{'inline' can only appear on functions}} int x; }; diff --git a/clang/test/SemaCXX/anonymous-union.cpp b/clang/test/SemaCXX/anonymous-union.cpp index 93b5b0a..9c2cf24 100644 --- a/clang/test/SemaCXX/anonymous-union.cpp +++ b/clang/test/SemaCXX/anonymous-union.cpp @@ -110,7 +110,7 @@ struct BadMembers { }; // -typedef union { }; // expected-warning{{declaration does not declare anything}} +typedef union { }; // expected-warning{{typedef requires a name}} // typedef struct objc_module *Foo ; diff --git a/clang/test/SemaCXX/storage-class.cpp b/clang/test/SemaCXX/storage-class.cpp index 01cfbfc..7412184 100644 --- a/clang/test/SemaCXX/storage-class.cpp +++ b/clang/test/SemaCXX/storage-class.cpp @@ -3,5 +3,5 @@ extern const int PR6495a = 42; extern int PR6495b = 42; // expected-warning{{'extern' variable has an initializer}} extern const int PR6495c[] = {42,43,44}; -extern struct Test1 {}; // expected-warning {{'extern' ignored on this declaration}} +extern struct Test1 {}; // expected-warning {{'extern' is not permitted on a declaration of a type}} extern "C" struct Test0 {}; // no warning -- 2.7.4