diff options
| -rw-r--r-- | clang/Parse/DeclSpec.cpp | 42 | ||||
| -rw-r--r-- | clang/Parse/Parser.cpp | 5 | ||||
| -rw-r--r-- | clang/include/clang/Parse/DeclSpec.h | 13 | ||||
| -rw-r--r-- | clang/test/Sema/declspec.c | 6 |
4 files changed, 45 insertions, 21 deletions
diff --git a/clang/Parse/DeclSpec.cpp b/clang/Parse/DeclSpec.cpp index 15e291f46c3..8f9a5fd7919 100644 --- a/clang/Parse/DeclSpec.cpp +++ b/clang/Parse/DeclSpec.cpp @@ -47,36 +47,40 @@ const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) { } } -static bool BadSpecifier(DeclSpec::SCS S, const char *&PrevSpec) { - PrevSpec = DeclSpec::getSpecifierName(S); +bool DeclSpec::BadSpecifier(SCS S, const char *&PrevSpec) { + Invalid = true; + PrevSpec = getSpecifierName(S); return true; } -static bool BadSpecifier(DeclSpec::TSW W, const char *&PrevSpec) { +bool DeclSpec::BadSpecifier(TSW W, const char *&PrevSpec) { + Invalid = true; switch (W) { - case DeclSpec::TSW_unspecified: PrevSpec = "unspecified"; break; - case DeclSpec::TSW_short: PrevSpec = "short"; break; - case DeclSpec::TSW_long: PrevSpec = "long"; break; - case DeclSpec::TSW_longlong: PrevSpec = "long long"; break; + case TSW_unspecified: PrevSpec = "unspecified"; break; + case TSW_short: PrevSpec = "short"; break; + case TSW_long: PrevSpec = "long"; break; + case TSW_longlong: PrevSpec = "long long"; break; } return true; } -static bool BadSpecifier(DeclSpec::TSC C, const char *&PrevSpec) { +bool DeclSpec::BadSpecifier(TSC C, const char *&PrevSpec) { + Invalid = true; switch (C) { - case DeclSpec::TSC_unspecified: PrevSpec = "unspecified"; break; - case DeclSpec::TSC_imaginary: PrevSpec = "imaginary"; break; - case DeclSpec::TSC_complex: PrevSpec = "complex"; break; + case TSC_unspecified: PrevSpec = "unspecified"; break; + case TSC_imaginary: PrevSpec = "imaginary"; break; + case TSC_complex: PrevSpec = "complex"; break; } return true; } -static bool BadSpecifier(DeclSpec::TSS S, const char *&PrevSpec) { +bool DeclSpec::BadSpecifier(TSS S, const char *&PrevSpec) { + Invalid = true; switch (S) { - case DeclSpec::TSS_unspecified: PrevSpec = "unspecified"; break; - case DeclSpec::TSS_signed: PrevSpec = "signed"; break; - case DeclSpec::TSS_unsigned: PrevSpec = "unsigned"; break; + case TSS_unspecified: PrevSpec = "unspecified"; break; + case TSS_signed: PrevSpec = "signed"; break; + case TSS_unsigned: PrevSpec = "unsigned"; break; } return true; } @@ -103,12 +107,14 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { } } -static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) { - PrevSpec = DeclSpec::getSpecifierName(T); +bool DeclSpec::BadSpecifier(TST T, const char *&PrevSpec) { + Invalid = true; + PrevSpec = getSpecifierName(T); return true; } -static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) { +bool DeclSpec::BadSpecifier(TQ T, const char *&PrevSpec) { + Invalid = true; switch (T) { case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break; case DeclSpec::TQ_const: PrevSpec = "const"; break; diff --git a/clang/Parse/Parser.cpp b/clang/Parse/Parser.cpp index e3208a0b3e9..860a44f9e94 100644 --- a/clang/Parse/Parser.cpp +++ b/clang/Parse/Parser.cpp @@ -367,7 +367,10 @@ Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS); - + // If the decl specs are invalid, there is no need to continue. + if (DS.isInvalid()) + return 0; + // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h index bb2773217e2..e38f764af6a 100644 --- a/clang/include/clang/Parse/DeclSpec.h +++ b/clang/include/clang/Parse/DeclSpec.h @@ -134,6 +134,15 @@ private: SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc; + + bool Invalid; + + bool BadSpecifier(TST T, const char *&PrevSpec); + bool BadSpecifier(TQ T, const char *&PrevSpec); + bool BadSpecifier(TSS T, const char *&PrevSpec); + bool BadSpecifier(TSC T, const char *&PrevSpec); + bool BadSpecifier(TSW T, const char *&PrevSpec); + bool BadSpecifier(SCS T, const char *&PrevSpec); public: DeclSpec() @@ -147,7 +156,8 @@ public: FS_inline_specified(false), TypeRep(0), AttrList(0), - ProtocolQualifiers(0) { + ProtocolQualifiers(0), + Invalid(false) { } ~DeclSpec() { delete AttrList; @@ -160,6 +170,7 @@ public: SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; } + bool isInvalid() { return Invalid; } void ClearStorageClassSpecs() { StorageClassSpec = DeclSpec::SCS_unspecified; diff --git a/clang/test/Sema/declspec.c b/clang/test/Sema/declspec.c index 05f492d67ac..fd575406812 100644 --- a/clang/test/Sema/declspec.c +++ b/clang/test/Sema/declspec.c @@ -5,4 +5,8 @@ T foo(int n, int m) { } // expected-error {{cannot return array or function}} void foof(const char *, ...) __attribute__((__format__(__printf__, 1, 2))), barf (void); - +struct _zend_module_entry { } +typedef struct _zend_function_entry { } // expected-error {{cannot combine with previous 'struct' declaration specifier}} +static void buggy(int *x) { // expected-error {{cannot combine with previous 'typedef' declaration specifier}} \ + // expected-error {{cannot combine with previous 'struct' declaration specifier}} + // expected-error {{expected '}'}} |

