Add an initial cut at a datastructure for holding declspec's.

llvm-svn: 38805
This commit is contained in:
Chris Lattner 2006-08-04 04:39:53 +00:00
parent c0acd3d621
commit b9093cd1d0
8 changed files with 373 additions and 32 deletions

View File

@ -1,4 +1,4 @@
//===--- ParserActions.cpp - C Language Family Default Parser Actions -----===//
//===--- Actions.cpp - C Language Family Default Parser Actions -----------===//
//
// The LLVM Compiler Infrastructure
//

130
clang/Parse/DeclSpec.cpp Normal file
View File

@ -0,0 +1,130 @@
//===--- Declarations.cpp - Declaration Representation Implementation -----===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Declaration representation classes.
//
//===----------------------------------------------------------------------===//
#include "clang/Parse/Declarations.h"
using namespace llvm;
using namespace clang;
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
///
unsigned DeclSpec::getParsedSpecifiers() const {
unsigned Res = 0;
if (StorageClassSpec != SCS_unspecified)
Res |= PQ_StorageClassSpecifier;
if (TypeQualifiers != TQ_unspecified)
Res |= PQ_TypeQualifier;
if (TypeSpecWidth != TSW_unspecified ||
TypeSpecComplex != TSC_unspecified ||
TypeSpecSign != TSS_unspecified ||
TypeSpecType != TST_unspecified)
Res |= PQ_TypeSpecifier;
if (FuncSpec != FS_unspecified)
Res |= PQ_FunctionSpecifier;
return Res;
}
static bool BadSpecifier(DeclSpec::TSW W, const char *&PrevSpec) {
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;
}
return true;
}
static bool BadSpecifier(DeclSpec::TSC C, const char *&PrevSpec) {
switch (C) {
case DeclSpec::TSC_unspecified: PrevSpec = "unspecified"; break;
case DeclSpec::TSC_imaginary: PrevSpec = "imaginary"; break;
case DeclSpec::TSC_complex: PrevSpec = "complex"; break;
}
return true;
}
static bool BadSpecifier(DeclSpec::TSS S, const char *&PrevSpec) {
switch (S) {
case DeclSpec::TSS_unspecified: PrevSpec = "unspecified"; break;
case DeclSpec::TSS_signed: PrevSpec = "signed"; break;
case DeclSpec::TSS_unsigned: PrevSpec = "unsigned"; break;
}
return true;
}
static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) {
switch (T) {
case DeclSpec::TST_unspecified: PrevSpec = "unspecified"; break;
case DeclSpec::TST_void: PrevSpec = "void"; break;
case DeclSpec::TST_char: PrevSpec = "char"; break;
case DeclSpec::TST_int: PrevSpec = "int"; break;
case DeclSpec::TST_float: PrevSpec = "float"; break;
case DeclSpec::TST_double: PrevSpec = "double"; break;
case DeclSpec::TST_bool: PrevSpec = "_Bool"; break;
case DeclSpec::TST_decimal32: PrevSpec = "_Decimal32"; break;
case DeclSpec::TST_decimal64: PrevSpec = "_Decimal64"; break;
case DeclSpec::TST_decimal128: PrevSpec = "_Decimal128"; break;
}
return true;
}
/// 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).
bool DeclSpec::SetTypeSpecWidth(TSW W, const char *&PrevSpec) {
if (TypeSpecWidth != TSW_unspecified)
return BadSpecifier(TypeSpecWidth, PrevSpec);
TypeSpecWidth = W;
return false;
}
bool DeclSpec::SetTypeSpecComplex(TSC C, const char *&PrevSpec) {
if (TypeSpecComplex != TSC_unspecified)
return BadSpecifier(TypeSpecComplex, PrevSpec);
TypeSpecComplex = C;
return false;
}
bool DeclSpec::SetTypeSpecSign(TSS S, const char *&PrevSpec) {
if (TypeSpecSign != TSS_unspecified)
return BadSpecifier(TypeSpecSign, PrevSpec);
return false;
}
bool DeclSpec::SetTypeSpecType(TST T, const char *&PrevSpec) {
if (TypeSpecType != TST_unspecified)
return BadSpecifier(TypeSpecType, PrevSpec);
return false;
}
bool DeclSpec::SetFuncSpec(FS F, const char *&PrevSpec) {
// 'inline inline' is ok.
FuncSpec = F;
return false;
}
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
diag::kind DeclSpec::Finish() {
// FIXME: implement this.
return diag::NUM_DIAGNOSTICS;
}

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
#include "clang/Parse/Declarations.h"
using namespace llvm;
using namespace clang;
@ -22,6 +23,7 @@ using namespace clang;
/// ParseDeclarationSpecifiers
/// declaration-specifiers: [C99 6.7]
/// storage-class-specifier declaration-specifiers [opt] [TODO]
/// //__thread
/// type-specifier declaration-specifiers [opt]
/// type-qualifier declaration-specifiers [opt] [TODO]
/// [C99] function-specifier declaration-specifiers [opt] [TODO]
@ -42,35 +44,93 @@ using namespace clang;
/// struct-or-union-specifier [TODO]
/// enum-specifier [TODO]
/// typedef-name [TODO]
void Parser::ParseDeclarationSpecifiers() {
/// function-specifier: [C99 6.7.4]
/// [C99] inline
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
SourceLocation StartLoc = Tok.getLocation();
while (1) {
bool isInvalid = false;
const char *PrevSpec = 0;
switch (Tok.getKind()) {
default: return; // Not a declaration specifier token.
default:
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
diag::kind Res = DS.Finish();
if (Res != diag::NUM_DIAGNOSTICS)
Diag(StartLoc, Res);
return;
// type-specifiers
case tok::kw_void: // SetTypeSpecifier(); break;
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
break;
case tok::kw_long:
if (DS.TypeSpecWidth != DeclSpec::TSW_long) {
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, PrevSpec);
} else {
DS.TypeSpecWidth = DeclSpec::TSW_unspecified;
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, PrevSpec);
}
break;
case tok::kw_signed:
isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, PrevSpec);
break;
case tok::kw_unsigned:
isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, PrevSpec);
break;
case tok::kw__Complex:
isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, PrevSpec);
break;
case tok::kw__Imaginary:
isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, PrevSpec);
break;
case tok::kw_void:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, PrevSpec);
break;
case tok::kw_char:
case tok::kw_short: // Width
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, PrevSpec);
break;
case tok::kw_int:
case tok::kw_long: // Width
case tok::kw_float: // Type specifier
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, PrevSpec);
break;
case tok::kw_float:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, PrevSpec);
break;
case tok::kw_double:
case tok::kw_signed: // Signedness
case tok::kw_unsigned: // Signedness
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, PrevSpec);
break;
case tok::kw__Bool:
case tok::kw__Complex: // Complexity
case tok::kw__Imaginary: // Complexity
// FIXME: Read these, handle them!
ConsumeToken();
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, PrevSpec);
break;
case tok::kw__Decimal32:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, PrevSpec);
break;
case tok::kw__Decimal64:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, PrevSpec);
break;
case tok::kw__Decimal128:
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, PrevSpec);
break;
//case tok::kw_struct:
//case tok::kw_union:
//case tok::kw_enum:
// function-specifier
case tok::kw_inline:
isInvalid = DS.SetFuncSpec(DeclSpec::FS_inline, PrevSpec);
break;
}
// If the specifier combination wasn't legal, issue a diagnostic.
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
}
ConsumeToken();
}
}
/// ParseDeclarator
/// declarator: [C99 6.7.5]
/// pointer[opt] direct-declarator

View File

@ -1,4 +1,4 @@
//===--- Parser.cpp - C Language Family Parser ----------------------------===//
//===--- Parse.cpp - C Language Family Parser -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@ -12,16 +12,16 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/Parser.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Declarations.h"
using namespace llvm;
using namespace clang;
Parser::Parser(Preprocessor &pp, ParserActions &actions)
: PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {}
void Parser::Diag(const LexerToken &Tok, unsigned DiagID,
void Parser::Diag(SourceLocation Loc, unsigned DiagID,
const std::string &Msg) {
Diags.Report(Tok.getLocation(), DiagID, Msg);
Diags.Report(Loc, DiagID, Msg);
}
//===----------------------------------------------------------------------===//
@ -89,8 +89,9 @@ void Parser::ParseExternalDeclaration() {
///
void Parser::ParseDeclarationOrFunctionDefinition() {
// Parse the common declaration-specifiers piece.
// NOTE: this can not be missing for C99 declaration's.
ParseDeclarationSpecifiers();
// NOTE: this can not be missing for C99 'declaration's.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
// Parse the common declarator piece.
ParseDeclarator();

View File

@ -9,8 +9,11 @@
/* Begin PBXBuildFile section */
DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F22020A7D852A00FBF588 /* Parser.h */; };
DE1F22200A7D879000FBF588 /* ParserActions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F221F0A7D879000FBF588 /* ParserActions.h */; };
DE1F22730A7D8D5800FBF588 /* Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F22710A7D8D5800FBF588 /* Parser.cpp */; };
DE1F22740A7D8D5800FBF588 /* ParserActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F22720A7D8D5800FBF588 /* ParserActions.cpp */; };
DE1F24700A7DC99000FBF588 /* Actions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F246D0A7DC99000FBF588 /* Actions.cpp */; };
DE1F24710A7DC99000FBF588 /* Parse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F246E0A7DC99000FBF588 /* Parse.cpp */; };
DE1F24720A7DC99000FBF588 /* ParseDeclarations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F246F0A7DC99000FBF588 /* ParseDeclarations.cpp */; };
DE1F24820A7DCD3800FBF588 /* Declarations.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE1F24810A7DCD3800FBF588 /* Declarations.h */; };
DE1F257B0A7DD86800FBF588 /* Declarations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE1F257A0A7DD86800FBF588 /* Declarations.cpp */; };
DEAEE98B0A5A2B970045101B /* MultipleIncludeOpt.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */; };
DEAEECAD0A5AF0E30045101B /* clang.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEAEECAC0A5AF0E30045101B /* clang.h */; };
DEAEECD50A5AF1FE0045101B /* PrintPreprocessedOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEAEECD40A5AF1FE0045101B /* PrintPreprocessedOutput.cpp */; };
@ -92,6 +95,7 @@
DEAEED4B0A5AF89A0045101B /* NOTES.txt in CopyFiles */,
DE1F22030A7D852A00FBF588 /* Parser.h in CopyFiles */,
DE1F22200A7D879000FBF588 /* ParserActions.h in CopyFiles */,
DE1F24820A7DCD3800FBF588 /* Declarations.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
@ -101,8 +105,11 @@
8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
DE1F22020A7D852A00FBF588 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Parser.h; path = clang/Parse/Parser.h; sourceTree = "<group>"; };
DE1F221F0A7D879000FBF588 /* ParserActions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ParserActions.h; path = clang/Parse/ParserActions.h; sourceTree = "<group>"; };
DE1F22710A7D8D5800FBF588 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = Parse/Parser.cpp; sourceTree = "<group>"; };
DE1F22720A7D8D5800FBF588 /* ParserActions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParserActions.cpp; path = Parse/ParserActions.cpp; sourceTree = "<group>"; };
DE1F246D0A7DC99000FBF588 /* Actions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Actions.cpp; path = Parse/Actions.cpp; sourceTree = "<group>"; };
DE1F246E0A7DC99000FBF588 /* Parse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parse.cpp; path = Parse/Parse.cpp; sourceTree = "<group>"; };
DE1F246F0A7DC99000FBF588 /* ParseDeclarations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseDeclarations.cpp; path = Parse/ParseDeclarations.cpp; sourceTree = "<group>"; };
DE1F24810A7DCD3800FBF588 /* Declarations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Declarations.h; path = clang/Parse/Declarations.h; sourceTree = "<group>"; };
DE1F257A0A7DD86800FBF588 /* Declarations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Declarations.cpp; path = Parse/Declarations.cpp; sourceTree = "<group>"; };
DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = "<group>"; };
DEAEECAC0A5AF0E30045101B /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clang.h; sourceTree = "<group>"; };
DEAEECD40A5AF1FE0045101B /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PrintPreprocessedOutput.cpp; sourceTree = "<group>"; };
@ -193,6 +200,7 @@
DE1F21F20A7D84E800FBF588 /* Parse */ = {
isa = PBXGroup;
children = (
DE1F24810A7DCD3800FBF588 /* Declarations.h */,
DE1F22020A7D852A00FBF588 /* Parser.h */,
DE1F221F0A7D879000FBF588 /* ParserActions.h */,
);
@ -202,8 +210,10 @@
DE1F22600A7D8C9B00FBF588 /* Parse */ = {
isa = PBXGroup;
children = (
DE1F22710A7D8D5800FBF588 /* Parser.cpp */,
DE1F22720A7D8D5800FBF588 /* ParserActions.cpp */,
DE1F246D0A7DC99000FBF588 /* Actions.cpp */,
DE1F257A0A7DD86800FBF588 /* Declarations.cpp */,
DE1F246E0A7DC99000FBF588 /* Parse.cpp */,
DE1F246F0A7DC99000FBF588 /* ParseDeclarations.cpp */,
);
name = Parse;
sourceTree = "<group>";
@ -352,8 +362,10 @@
DED7D7C90A5242E6003AD0FB /* Preprocessor.cpp in Sources */,
DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */,
DEAEECD50A5AF1FE0045101B /* PrintPreprocessedOutput.cpp in Sources */,
DE1F22730A7D8D5800FBF588 /* Parser.cpp in Sources */,
DE1F22740A7D8D5800FBF588 /* ParserActions.cpp in Sources */,
DE1F24700A7DC99000FBF588 /* Actions.cpp in Sources */,
DE1F24710A7DC99000FBF588 /* Parse.cpp in Sources */,
DE1F24720A7DC99000FBF588 /* ParseDeclarations.cpp in Sources */,
DE1F257B0A7DD86800FBF588 /* Declarations.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -239,4 +239,8 @@ DIAG(ext_empty_source_file, EXTENSION,
DIAG(ext_top_level_semi, EXTENSION,
"ISO C does not allow extra ';' outside of a function")
DIAG(err_invalid_decl_spec_combination, ERROR,
"cannot combine declaration specifier with previous '%s' specifier")
#undef DIAG

View File

@ -0,0 +1,131 @@
//===--- Declarations.h - Declaration Representation ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines interfaces used for Declarations.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARSE_DECLARATIONS_H
#define LLVM_CLANG_PARSE_DECLARATIONS_H
#include "clang/Basic/Diagnostic.h"
namespace llvm {
namespace clang {
/// DeclSpec - This class captures information about "declaration specifiers",
/// which encompases storage-class-specifiers, type-specifiers, type-qualifiers,
/// and function-specifiers.
class DeclSpec {
public:
// storage-class-specifier
enum SCS {
SCS_unspecified,
SCS_typedef,
SCS_extern,
SCS_static,
SCS_auto,
SCS_register
} StorageClassSpec : 3;
// type-specifier
enum TSW {
TSW_unspecified,
TSW_short,
TSW_long,
TSW_longlong
} TypeSpecWidth : 2;
enum TSC {
TSC_unspecified,
TSC_imaginary,
TSC_complex
} TypeSpecComplex : 2;
enum TSS {
TSS_unspecified,
TSS_signed,
TSS_unsigned
} TypeSpecSign : 2;
enum TST {
TST_unspecified,
TST_void,
TST_char,
TST_int,
TST_float,
TST_double,
TST_bool, // _Bool
TST_decimal32, // _Decimal32
TST_decimal64, // _Decimal64
TST_decimal128 // _Decimal128
} TypeSpecType : 4;
// type-qualifiers
enum TQ {
TQ_unspecified = 0,
TQ_const = 1,
TQ_restrict = 2,
TQ_volatile = 4
};
unsigned TypeQualifiers : 3; // Bitwise OR of typequals.
// function-specifier
enum FS {
FS_unspecified,
FS_inline
} FuncSpec : 1;
// attributes.
// FIXME: implement declspec attributes.
// Flags to query which specifiers were applied.
enum ParsedSpecifiers {
PQ_None = 0,
PQ_StorageClassSpecifier = 1,
PQ_TypeSpecifier = 2,
PQ_TypeQualifier = 4,
PQ_FunctionSpecifier = 8
};
DeclSpec()
: StorageClassSpec(SCS_unspecified),
TypeSpecWidth(TSW_unspecified),
TypeSpecComplex(TSC_unspecified),
TypeSpecSign(TSS_unspecified),
TypeSpecType(TST_unspecified),
TypeQualifiers(TSS_unspecified),
FuncSpec(FS_unspecified) {
}
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
/// DeclSpec includes.
///
unsigned getParsedSpecifiers() const;
/// 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 SetTypeSpecWidth(TSW W, const char *&PrevSpec);
bool SetTypeSpecComplex(TSC C, const char *&PrevSpec);
bool SetTypeSpecSign(TSS S, const char *&PrevSpec);
bool SetTypeSpecType(TST T, const char *&PrevSpec);
bool SetFuncSpec(FS F, const char *&PrevSpec);
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
/// DeclSpec is guaranteed self-consistent, even if an error occurred.
diag::kind Finish();
};
} // end namespace clang
} // end namespace llvm
#endif

View File

@ -20,6 +20,7 @@
namespace llvm {
namespace clang {
class ParserActions;
class DeclSpec;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
@ -47,11 +48,13 @@ public:
// Diagnostics.
void Diag(const LexerToken &Tok, unsigned DiagID, const std::string &Msg="");
void Diag(unsigned DiagID, const std::string &Msg="") {
void Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg = "");
void Diag(const LexerToken &Tok, unsigned DiagID, const std::string &M = "") {
Diag(Tok.getLocation(), DiagID, M);
}
void Diag(unsigned DiagID, const std::string &Msg = "") {
Diag(Tok, DiagID, Msg);
}
/// ConsumeToken - Consume the current 'peek token', lexing a new one and
/// returning the token kind.
@ -69,7 +72,7 @@ private:
//===--------------------------------------------------------------------===//
// C99 6.7: Declarations.
void ParseDeclarationSpecifiers();
void ParseDeclarationSpecifiers(DeclSpec &DS);
void ParseDeclarator();
void ParseTypeQualifierListOpt();