forked from OSchip/llvm-project
Allow the parser to detect invalid DeclSpec's. This fixes http://llvm.org/bugs/show_bug.cgi?id=1987.
This commit only "guards" the call to ParseDeclarationSpecifiers() in ParseDeclarationOrFunctionDefinition(). We could consider guarding all calls, however this is a bit radical (since it effectively stops parsing the declaration once we have a bad declspec). Will discuss with Chris tomorrow. llvm-svn: 46984
This commit is contained in:
parent
779593cd9d
commit
ab468cb14b
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 '}'}}
|
||||
|
|
Loading…
Reference in New Issue