diff --git a/clang/Parse/Actions.cpp b/clang/Parse/Actions.cpp index 6819c5373c38..19786e141f60 100644 --- a/clang/Parse/Actions.cpp +++ b/clang/Parse/Actions.cpp @@ -1,4 +1,4 @@ -//===--- ParserActions.cpp - C Language Family Default Parser Actions -----===// +//===--- Actions.cpp - C Language Family Default Parser Actions -----------===// // // The LLVM Compiler Infrastructure // diff --git a/clang/Parse/DeclSpec.cpp b/clang/Parse/DeclSpec.cpp new file mode 100644 index 000000000000..878ab11b84c9 --- /dev/null +++ b/clang/Parse/DeclSpec.cpp @@ -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; +} diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp index 6608ed35ac50..1065fd2483a7 100644 --- a/clang/Parse/ParseDecl.cpp +++ b/clang/Parse/ParseDecl.cpp @@ -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 diff --git a/clang/Parse/Parser.cpp b/clang/Parse/Parser.cpp index 835beae105d4..a3ca80157479 100644 --- a/clang/Parse/Parser.cpp +++ b/clang/Parse/Parser.cpp @@ -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(); diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index 17969eaef645..0cd0651e5a74 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -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 = ""; }; DE1F221F0A7D879000FBF588 /* ParserActions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ParserActions.h; path = clang/Parse/ParserActions.h; sourceTree = ""; }; - DE1F22710A7D8D5800FBF588 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = Parse/Parser.cpp; sourceTree = ""; }; - DE1F22720A7D8D5800FBF588 /* ParserActions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParserActions.cpp; path = Parse/ParserActions.cpp; sourceTree = ""; }; + DE1F246D0A7DC99000FBF588 /* Actions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Actions.cpp; path = Parse/Actions.cpp; sourceTree = ""; }; + DE1F246E0A7DC99000FBF588 /* Parse.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parse.cpp; path = Parse/Parse.cpp; sourceTree = ""; }; + DE1F246F0A7DC99000FBF588 /* ParseDeclarations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseDeclarations.cpp; path = Parse/ParseDeclarations.cpp; sourceTree = ""; }; + DE1F24810A7DCD3800FBF588 /* Declarations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Declarations.h; path = clang/Parse/Declarations.h; sourceTree = ""; }; + DE1F257A0A7DD86800FBF588 /* Declarations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Declarations.cpp; path = Parse/Declarations.cpp; sourceTree = ""; }; DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = ""; }; DEAEECAC0A5AF0E30045101B /* clang.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clang.h; sourceTree = ""; }; DEAEECD40A5AF1FE0045101B /* PrintPreprocessedOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PrintPreprocessedOutput.cpp; sourceTree = ""; }; @@ -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 = ""; @@ -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; }; diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 5b49224b80e8..d47b5cab89dc 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -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 diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h new file mode 100644 index 000000000000..c69a7caed206 --- /dev/null +++ b/clang/include/clang/Parse/DeclSpec.h @@ -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 diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 6ea7faa4f72a..efb052e9d491 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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();