record accurate sourceloc info for storage class specs, so we can report

things like:

t.c:4:10: error: invalid storage class specifier in function declarator
int foo2(auto int Aaslfkasdflkj, register B);
         ^

instead of:

t.c:4:19: error: invalid storage class specifier in function declarator
int foo2(auto int Aaslfkasdflkj, register B);
                  ^

llvm-svn: 39224
This commit is contained in:
Chris Lattner 2006-11-28 05:05:08 +00:00
parent 353f5740b1
commit 4d8f873b5b
4 changed files with 39 additions and 15 deletions

View File

@ -25,7 +25,7 @@ unsigned DeclSpec::getParsedSpecifiers() const {
SCS_thread_specified)
Res |= PQ_StorageClassSpecifier;
if (TypeQualifiers != TQ_unspecified)
if (TypeQualifiers != TQ_unspecified)
Res |= PQ_TypeQualifier;
if (hasTypeSpecifier())
@ -117,19 +117,23 @@ static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) {
return true;
}
bool DeclSpec::SetStorageClassSpec(SCS S, const char *&PrevSpec) {
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
const char *&PrevSpec) {
if (StorageClassSpec != SCS_unspecified)
return BadSpecifier(StorageClassSpec, PrevSpec);
StorageClassSpec = S;
StorageClassSpecLoc = Loc;
return false;
}
bool DeclSpec::SetStorageClassSpecThread(const char *&PrevSpec) {
bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
const char *&PrevSpec) {
if (SCS_thread_specified) {
PrevSpec = "__thread";
return true;
}
SCS_thread_specified = true;
SCS_threadLoc = Loc;
return false;
}
@ -250,7 +254,7 @@ void DeclSpec::Finish(SourceLocation Loc, Diagnostic &D,
StorageClassSpec = SCS_extern; // '__thread int' -> 'extern __thread int'
} else if (StorageClassSpec != SCS_extern &&
StorageClassSpec != SCS_static) {
D.Report(Loc, diag::err_invalid_thread_spec,
D.Report(getStorageClassSpecLoc(), diag::err_invalid_thread_spec,
getSpecifierName(StorageClassSpec));
SCS_thread_specified = false;
}

View File

@ -244,10 +244,13 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
/// [C99] 'inline'
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
// FIXME: Remove this.
SourceLocation StartLoc = Tok.getLocation();
while (1) {
int isInvalid = false;
const char *PrevSpec = 0;
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
// typedef-name
case tok::identifier:
@ -267,6 +270,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
default:
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
// FIXME: Remove StartLoc.
DS.Finish(StartLoc, Diags, getLang());
return;
@ -277,26 +281,26 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
// storage-class-specifier
case tok::kw_typedef:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, PrevSpec);
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
break;
case tok::kw_extern:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before, "extern");
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, PrevSpec);
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec);
break;
case tok::kw_static:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before, "static");
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, PrevSpec);
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec);
break;
case tok::kw_auto:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, PrevSpec);
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec);
break;
case tok::kw_register:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, PrevSpec);
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec);
break;
case tok::kw___thread:
isInvalid = DS.SetStorageClassSpecThread(PrevSpec)*2;
isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec)*2;
break;
// type-specifiers
@ -989,12 +993,16 @@ void Parser::ParseParenDeclarator(Declarator &D) {
case DeclSpec::SCS_auto:
// NOTE: we could trivially allow 'int foo(auto int X)' if we wanted.
default:
// FIXME: Get better loc info from declspecs!
Diag(DeclaratorInfo.getIdentifierLoc(),
Diag(DS.getStorageClassSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
DS.ClearStorageClassSpecs();
break;
}
if (DS.isThreadSpecified()) {
Diag(DS.getThreadSpecLoc(),
diag::err_invalid_storage_class_in_func_decl);
DS.ClearStorageClassSpecs();
}
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.

View File

@ -236,7 +236,8 @@ void Parser::Initialize() {
//__builtin_va_list
DeclSpec DS;
bool Error = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Dummy);
bool Error = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, SourceLocation(),
Dummy);
// TODO: add a 'TST_builtin' type?
Error |= DS.SetTypeSpecType(DeclSpec::TST_int, Dummy);

View File

@ -117,6 +117,11 @@ private:
// attributes.
// FIXME: implement declspec attributes.
// SourceLocation info. These are null if the item wasn't specified or if
// the setting was synthesized.
SourceLocation StorageClassSpecLoc, SCS_threadLoc;
public:
DeclSpec()
@ -135,9 +140,15 @@ public:
SCS getStorageClassSpec() const { return StorageClassSpec; }
bool isThreadSpecified() const { return SCS_thread_specified; }
SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
void ClearStorageClassSpecs() {
StorageClassSpec = DeclSpec::SCS_unspecified;
SCS_thread_specified = false;
StorageClassSpecLoc = SourceLocation();
SCS_threadLoc = SourceLocation();
}
// type-specifier
@ -175,8 +186,8 @@ public:
/// These methods set the specified attribute of the DeclSpec, but return true
/// and ignore the request if invalid (e.g. "extern" then "auto" is
/// specified). The name of the previous specifier is returned in prevspec.
bool SetStorageClassSpec(SCS S, const char *&PrevSpec);
bool SetStorageClassSpecThread(const char *&PrevSpec);
bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec);
bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec);
bool SetTypeSpecWidth(TSW W, const char *&PrevSpec);
bool SetTypeSpecComplex(TSC C, const char *&PrevSpec);
bool SetTypeSpecSign(TSS S, const char *&PrevSpec);