forked from OSchip/llvm-project
Fix a couple of bugs, add some new cool stuff.
1. Fix a todo in Parser::ParseTag, to recover better. On code like that in test/Sema/decl-invalid.c it causes us to return a single error instead of multiple. 2. Fix an error in Sema::ParseDeclarator, where it would crash if the declarator didn't have an identifier. Instead, diagnose the problem. 3. Start adding infrastructure to track the range of locations covered by a declspec or declarator. This is mostly implemented for declspec, but could be improved, it is missing for declarator. Thanks to Neil for pointing out this crash. llvm-svn: 40482
This commit is contained in:
parent
64b64ae591
commit
02c0439a44
|
@ -277,7 +277,6 @@ void DeclSpec::Finish(Diagnostic &D, const LangOptions &Lang) {
|
|||
}
|
||||
|
||||
// Okay, now we can infer the real type.
|
||||
// TODO: infer real type.
|
||||
|
||||
// TODO: return "auto function" and other bad things based on the real type.
|
||||
|
||||
|
|
|
@ -296,7 +296,6 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
|||
void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
|
||||
/// specifier-qualifier-list is a subset of declaration-specifiers. Just
|
||||
/// parse declaration-specifiers and complain about extra stuff.
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
// Validate declspec for type-name.
|
||||
|
@ -367,6 +366,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
|
|||
/// [C99] 'inline'
|
||||
///
|
||||
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
||||
DS.Range.setBegin(Tok.getLocation());
|
||||
while (1) {
|
||||
int isInvalid = false;
|
||||
const char *PrevSpec = 0;
|
||||
|
@ -509,6 +509,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
|
|||
else // extwarn.
|
||||
Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
|
||||
}
|
||||
DS.Range.setEnd(Tok.getLocation());
|
||||
ConsumeToken();
|
||||
}
|
||||
}
|
||||
|
@ -527,7 +528,9 @@ bool Parser::ParseTag(DeclTy *&Decl, unsigned TagType, SourceLocation StartLoc){
|
|||
if (Tok.getKind() != tok::identifier &&
|
||||
Tok.getKind() != tok::l_brace) {
|
||||
Diag(Tok, diag::err_expected_ident_lbrace);
|
||||
// TODO: better error recovery here.
|
||||
|
||||
// Skip the rest of this declarator, up until the comma or semicolon.
|
||||
SkipUntil(tok::comma, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,6 +278,14 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *init,
|
|||
Expr *Init = static_cast<Expr*>(init);
|
||||
IdentifierInfo *II = D.getIdentifier();
|
||||
|
||||
// All of these full declarators require an identifier. If it doesn't have
|
||||
// one, the ParsedFreeStandingDeclSpec action should be used.
|
||||
if (II == 0) {
|
||||
Diag(D.getDeclSpec().getSourceRange().Begin(), diag::err_declarator_need_ident,
|
||||
D.getDeclSpec().getSourceRange(), D.getSourceRange());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// See if this is a redefinition of a variable in the same scope.
|
||||
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
|
||||
D.getIdentifierLoc(), S);
|
||||
|
|
|
@ -427,6 +427,8 @@ DIAG(err_invalid_storage_class_in_func_decl, ERROR,
|
|||
"invalid storage class specifier in function declarator")
|
||||
DIAG(err_invalid_reference_qualifier_application, ERROR,
|
||||
"'%0' qualifier may not be applied to a reference")
|
||||
DIAG(err_declarator_need_ident, ERROR,
|
||||
"declarator requires an identifier")
|
||||
|
||||
// Attributes
|
||||
DIAG(err_attribute_wrong_number_arguments, ERROR,
|
||||
|
|
|
@ -161,6 +161,9 @@ public:
|
|||
SourceLocation Begin() const { return B; }
|
||||
SourceLocation End() const { return E; }
|
||||
|
||||
void setBegin(SourceLocation b) { B = b; }
|
||||
void setEnd(SourceLocation e) { E = e; }
|
||||
|
||||
bool isValid() const { return B.isValid() && E.isValid(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ namespace clang {
|
|||
/// and function-specifiers.
|
||||
class DeclSpec {
|
||||
public:
|
||||
SourceRange Range;
|
||||
const SourceRange &getSourceRange() const { return Range; }
|
||||
|
||||
// storage-class-specifier
|
||||
enum SCS {
|
||||
SCS_unspecified,
|
||||
|
@ -414,8 +417,8 @@ struct DeclaratorChunk {
|
|||
/// Abstract declarators are used when parsing types, and don't have an
|
||||
/// identifier. Normal declarators do have ID's.
|
||||
///
|
||||
/// This is NOT intended to be a small value object: this should be a transient
|
||||
/// object that lives on the stack.
|
||||
/// Instances of this class should be a transient object that lives on the
|
||||
/// stack, not objects that are allocated in large quantities on the heap.
|
||||
class Declarator {
|
||||
const DeclSpec &DS;
|
||||
IdentifierInfo *Identifier;
|
||||
|
@ -459,6 +462,9 @@ public:
|
|||
|
||||
TheContext getContext() const { return Context; }
|
||||
|
||||
// getSourceRange - FIXME: This should be implemented.
|
||||
const SourceRange getSourceRange() const { return SourceRange(); }
|
||||
|
||||
/// clear - Reset the contents of this Declarator.
|
||||
void clear() {
|
||||
Identifier = 0;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// RUN: clang %s -parse-ast-check
|
||||
|
||||
typedef union <anonymous> __mbstate_t; // expected-error: {{expected identifier or}}
|
Loading…
Reference in New Issue