Diagnose declarations that don't declare anything, and fix PR3020.

Examples:
int;
typedef int;

llvm-svn: 61454
This commit is contained in:
Sebastian Redl 2008-12-28 15:28:59 +00:00
parent 85cd7bac29
commit a2b5e31cb1
7 changed files with 42 additions and 10 deletions

View File

@ -318,6 +318,10 @@ public:
/// things like "_Imaginary" (lacking an FP type). After calling this method, /// things like "_Imaginary" (lacking an FP type). After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred. /// DeclSpec is guaranteed self-consistent, even if an error occurred.
void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang); void Finish(Diagnostic &D, SourceManager& SrcMgr, const LangOptions &Lang);
/// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
/// without a Declarator. Only tag declspecs can stand alone.
bool isMissingDeclaratorOk();
}; };
/// ObjCDeclSpec - This class captures information about /// ObjCDeclSpec - This class captures information about

View File

@ -313,3 +313,11 @@ void DeclSpec::Finish(Diagnostic &D, SourceManager& SrcMgr,
// 'data definition has no type or storage class'? // 'data definition has no type or storage class'?
} }
bool DeclSpec::isMissingDeclaratorOk() {
TST tst = getTypeSpecType();
return (tst == TST_union
|| tst == TST_struct
|| tst == TST_class
|| tst == TST_enum
) && getTypeRep() != 0;
}

View File

@ -773,9 +773,16 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed. /// no declarator (e.g. "struct foo;") is parsed.
Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
// TODO: emit error on 'int;' or 'const enum foo;'. // FIXME: Isn't that more of a parser diagnostic than a sema diagnostic?
// TODO: emit error on 'typedef int;' if (!DS.isMissingDeclaratorOk()) {
// if (!DS.isMissingDeclaratorOk()) Diag(...); // FIXME: This diagnostic is emitted even when various previous
// errors occurred (see e.g. test/Sema/decl-invalid.c). However,
// DeclSpec has no means of communicating this information, and the
// responsible parser functions are quite far apart.
Diag(DS.getSourceRange().getBegin(), diag::err_no_declarators)
<< DS.getSourceRange();
return 0;
}
return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep())); return dyn_cast_or_null<TagDecl>(static_cast<Decl *>(DS.getTypeRep()));
} }

View File

@ -5,10 +5,12 @@ export class foo { }; // expected-error {{expected template}}
template x; // expected-error {{expected '<' after 'template'}} template x; // expected-error {{expected '<' after 'template'}}
export template x; // expected-error {{expected '<' after 'template'}} \ export template x; // expected-error {{expected '<' after 'template'}} \
// expected-note {{exported templates are unsupported}} // expected-note {{exported templates are unsupported}}
template < ; // expected-error {{parse error}} // See Sema::ParsedFreeStandingDeclSpec about the double diagnostic. This is
template <template X> ; // expected-error {{expected '<' after 'template'}} // because ParseNonTypeTemplateParameter starts parsing a DeclSpec.
template <template <typename> > ; // expected-error {{expected 'class' before '>'}} template < ; // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
template <template <typename> Foo> ; // expected-error {{expected 'class' before 'Foo'}} template <template X> struct Err1; // expected-error {{expected '<' after 'template'}}
template <template <typename> > struct Err2; // expected-error {{expected 'class' before '>'}}
template <template <typename> Foo> struct Err3; // expected-error {{expected 'class' before 'Foo'}}
// Template function declarations // Template function declarations
template <typename T> void foo(); template <typename T> void foo();

View File

@ -1,6 +1,7 @@
// RUN: clang %s -fsyntax-only -verify // RUN: clang %s -fsyntax-only -verify
typedef union <anonymous> __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} // See Sema::ParsedFreeStandingDeclSpec about the double diagnostic
typedef union <anonymous> __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} expected-error {{declaration does not declare anything}}
// PR2017 // PR2017
@ -9,3 +10,9 @@ int a() {
int r[x()]; // expected-error {{size of array has non-integer type 'void'}} int r[x()]; // expected-error {{size of array has non-integer type 'void'}}
} }
int; // expected-error {{declaration does not declare anything}}
typedef int; // expected-error {{declaration does not declare anything}}
const int; // expected-error {{declaration does not declare anything}}
struct; // expected-error {{declaration of anonymous struct must be a definition}} // expected-error {{declaration does not declare anything}}
typedef int I;
I; // expected-error {{declaration does not declare anything}}

View File

@ -100,4 +100,8 @@ mutable void gfn(); // expected-error {{illegal storage class on function}}
void ogfn() void ogfn()
{ {
mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}} mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}}
// PR3020: This used to crash due to double ownership of C4.
struct C4;
C4; // expected-error {{declaration does not declare anything}}
} }