summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/Parse/DeclSpec.cpp42
-rw-r--r--clang/Parse/Parser.cpp5
-rw-r--r--clang/include/clang/Parse/DeclSpec.h13
-rw-r--r--clang/test/Sema/declspec.c6
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 '}'}}
OpenPOWER on IntegriCloud