Add an initial cut at a datastructure for holding declspec's.
llvm-svn: 38805
This commit is contained in:
parent
c0acd3d621
commit
b9093cd1d0
|
@ -1,4 +1,4 @@
|
|||
//===--- ParserActions.cpp - C Language Family Default Parser Actions -----===//
|
||||
//===--- Actions.cpp - C Language Family Default Parser Actions -----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue