From 99d724f6a31b5521ded95adf10ef7f3c62a0b18e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 10 Feb 2008 23:08:00 +0000 Subject: [PATCH] Fix PR1999, by emitting a hard error only if an argument declarator is completely missing. Otherwise, it is an implicit int case, which is valid in c90 and invalid elsewhere, but accepted as an extension. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46938 91177308-0d34-0410-b5e6-96231b3b80d8 --- Parse/ParseDecl.cpp | 19 ++++++++++++------- include/clang/Basic/DiagnosticKinds.def | 10 ++++++---- test/Parser/declarators.c | 4 ++-- test/Sema/c89.c | 3 +++ test/Sema/function.c | 10 +++++----- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp index 368887298e..d6b92119c7 100644 --- a/Parse/ParseDecl.cpp +++ b/Parse/ParseDecl.cpp @@ -1362,6 +1362,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { break; } + SourceLocation DSStart = Tok.getLocation(); + // Parse the declaration-specifiers. DeclSpec DS; ParseDeclarationSpecifiers(DS); @@ -1406,16 +1408,19 @@ void Parser::ParseParenDeclarator(Declarator &D) { // If no parameter was specified, verify that *something* was specified, // otherwise we have a missing type and identifier. - if (!DS.hasTypeSpecifier()) { + if (DS.getParsedSpecifiers() == DeclSpec::PQ_None && + ParmDecl.getIdentifier() == 0 && ParmDecl.getNumTypeObjects() == 0) { + Diag(DSStart, diag::err_missing_param); + } else if (!DS.hasTypeSpecifier() && + (getLang().C99 || getLang().CPlusPlus)) { + // Otherwise, if something was specified but a type specifier wasn't, + // (e.g. "x" or "restrict x" or "restrict"), this is a use of implicit + // int. This is valid in C90, but not in C99 or C++. if (ParmII) Diag(ParmDecl.getIdentifierLoc(), - diag::err_param_requires_type_specifier, ParmII->getName()); + diag::ext_param_requires_type_specifier, ParmII->getName()); else - Diag(Tok.getLocation(), diag::err_anon_param_requires_type_specifier); - - // Default the parameter to 'int'. - const char *PrevSpec = 0; - DS.SetTypeSpecType(DeclSpec::TST_int, Tok.getLocation(), PrevSpec); + Diag(DSStart, diag::ext_anon_param_requires_type_specifier); } ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 11d21775ed..7d0e684ce7 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -540,10 +540,12 @@ DIAG(ext_vla, EXTENSION, "variable length arrays are a C99 feature, accepted as an extension") DIAG(err_invalid_storage_class_in_func_decl, ERROR, "invalid storage class specifier in function declarator") -DIAG(err_anon_param_requires_type_specifier, ERROR, - "type specifier required for unnamed parameter") -DIAG(err_param_requires_type_specifier, ERROR, - "type specifier required for parameter '%0'") +DIAG(ext_anon_param_requires_type_specifier, EXTENSION, + "type specifier required for unnamed parameter, defaults to int") +DIAG(ext_param_requires_type_specifier, EXTENSION, + "type specifier required for parameter '%0', defaults to int") +DIAG(err_missing_param, ERROR, + "expected parameter declarator") DIAG(err_invalid_reference_qualifier_application, ERROR, "'%0' qualifier may not be applied to a reference") diff --git a/test/Parser/declarators.c b/test/Parser/declarators.c index e00035c8e0..aaea35c2cb 100644 --- a/test/Parser/declarators.c +++ b/test/Parser/declarators.c @@ -1,4 +1,4 @@ -// RUN: clang %s -fsyntax-only -verify +// RUN: clang %s -fsyntax-only -verify -pedantic extern int a1[]; @@ -6,7 +6,7 @@ void f0(); void f1(int [*]); void f2(int [const *]); void f3(int [volatile const*]); -int f4(*XX)(void); /* expected-error {{cannot return}} expected-error {{type specifier required}} */ +int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier required}} */ char ((((*X)))); diff --git a/test/Sema/c89.c b/test/Sema/c89.c index 7f26e99dfa..e7568bcb1b 100644 --- a/test/Sema/c89.c +++ b/test/Sema/c89.c @@ -27,3 +27,6 @@ void test3(int i) { int test4 = 0LL; /* expected-warning {{long long}} */ +/* PR1999 */ +void test5(register); + diff --git a/test/Sema/function.c b/test/Sema/function.c index 7e593d400c..a75814ee45 100644 --- a/test/Sema/function.c +++ b/test/Sema/function.c @@ -1,4 +1,4 @@ -// RUN: clang %s -fsyntax-only -verify +// RUN: clang %s -fsyntax-only -verify -pedantic // PR1892 void f(double a[restrict][5]); // should promote to restrict ptr. void f(double (* restrict a)[5]); @@ -16,10 +16,10 @@ void g(int (*compar)()) { // PR1965 int t5(b); // expected-error {{parameter list without types}} -int t6(int x, g); // expected-error {{type specifier required for parameter 'g'}} +int t6(int x, g); // expected-warning {{type specifier required for parameter 'g'}} -int t7(, ); // expected-error {{type specifier required}} expected-error {{type specifier required}} -int t8(, int a); // expected-error {{type specifier required}} -int t9(int a, ); // expected-error {{type specifier required}} +int t7(, ); // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}} +int t8(, int a); // expected-error {{expected parameter declarator}} +int t9(int a, ); // expected-error {{expected parameter declarator}} -- 2.40.0