[cfe-commits] r38816 - in /cfe/cfe/trunk: Parse/DeclSpec.cpp Parse/ParseDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/DeclSpec.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:24:53 PDT 2007
Author: sabre
Date: Wed Jul 11 11:24:53 2007
New Revision: 38816
URL: http://llvm.org/viewvc/llvm-project?rev=38816&view=rev
Log:
Handle __thread and storage-class-specifiers
Modified:
cfe/cfe/trunk/Parse/DeclSpec.cpp
cfe/cfe/trunk/Parse/ParseDecl.cpp
cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/cfe/trunk/include/clang/Parse/DeclSpec.h
Modified: cfe/cfe/trunk/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/DeclSpec.cpp?rev=38816&r1=38815&r2=38816&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/DeclSpec.cpp (original)
+++ cfe/cfe/trunk/Parse/DeclSpec.cpp Wed Jul 11 11:24:53 2007
@@ -21,7 +21,8 @@
///
unsigned DeclSpec::getParsedSpecifiers() const {
unsigned Res = 0;
- if (StorageClassSpec != SCS_unspecified)
+ if (StorageClassSpec != SCS_unspecified ||
+ SCS_thread_specified)
Res |= PQ_StorageClassSpecifier;
if (TypeQualifiers != TQ_unspecified)
@@ -33,11 +34,27 @@
TypeSpecType != TST_unspecified)
Res |= PQ_TypeSpecifier;
- if (FuncSpec != FS_unspecified)
+ if (FS_inline_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
+static const char *getSpecifierName(DeclSpec::SCS S) {
+ switch (S) {
+ default: assert(0 && "Unknown typespec!");
+ case DeclSpec::SCS_unspecified: return "unspecified";
+ case DeclSpec::SCS_typedef: return "typedef";
+ case DeclSpec::SCS_extern: return "extern";
+ case DeclSpec::SCS_static: return "static";
+ case DeclSpec::SCS_auto: return "auto";
+ case DeclSpec::SCS_register: return "register";
+ }
+}
+
+static bool BadSpecifier(DeclSpec::SCS S, const char *&PrevSpec) {
+ PrevSpec = getSpecifierName(S);
+ return true;
+}
static bool BadSpecifier(DeclSpec::TSW W, const char *&PrevSpec) {
switch (W) {
@@ -99,6 +116,14 @@
return true;
}
+bool DeclSpec::SetStorageClassSpec(SCS S, const char *&PrevSpec) {
+ if (StorageClassSpec != SCS_unspecified)
+ return BadSpecifier(StorageClassSpec, PrevSpec);
+ StorageClassSpec = S;
+ return false;
+}
+
+
/// 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).
@@ -139,12 +164,6 @@
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,
@@ -196,7 +215,7 @@
D.Report(Loc, diag::ext_plain_complex);
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
- // Note that GCC doesn't support _Complex _Bool.
+ // Note that this intentionally doesn't include _Complex _Bool.
D.Report(Loc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
D.Report(Loc, diag::err_invalid_complex_spec,
@@ -213,5 +232,18 @@
// Okay, now we can infer the real type.
+
+ // Verify __thread.
+ if (SCS_thread_specified) {
+ if (StorageClassSpec == SCS_unspecified) {
+ StorageClassSpec = SCS_extern; // '__thread int' -> 'extern __thread int'
+ } else if (StorageClassSpec != SCS_extern &&
+ StorageClassSpec != SCS_static) {
+ D.Report(Loc, diag::err_invalid_thread_spec,
+ getSpecifierName(StorageClassSpec));
+ SCS_thread_specified = false;
+ }
+ }
+
// 'data definition has no type or storage class'?
}
Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=38816&r1=38815&r2=38816&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:24:53 2007
@@ -28,7 +28,7 @@
/// [C99] function-specifier declaration-specifiers [opt]
/// [GNU] attributes declaration-specifiers [opt] [TODO]
///
-/// storage-class-specifier: [C99 6.7.1] [TODO]
+/// storage-class-specifier: [C99 6.7.1]
/// 'typedef'
/// 'extern'
/// 'static'
@@ -51,6 +51,7 @@
/// [GNU] '_Decimal32'
/// [GNU] '_Decimal64'
/// [GNU] '_Decimal128'
+/// [GNU] typeof-specifier [TODO]
/// [OBJC] class-name objc-protocol-refs [opt] [TODO]
/// [OBJC] typedef-name objc-protocol-refs [TODO]
/// [OBJC] objc-protocol-refs [TODO]
@@ -75,6 +76,34 @@
// specifiers. First verify that DeclSpec's are consistent.
DS.Finish(StartLoc, Diags, getLang());
return;
+
+ // storage-class-specifier
+ case tok::kw_typedef:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, PrevSpec);
+ break;
+ case tok::kw_extern:
+ if (DS.SCS_thread_specified)
+ Diag(Tok, diag::ext_thread_before, "extern");
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, PrevSpec);
+ break;
+ case tok::kw_static:
+ if (DS.SCS_thread_specified)
+ Diag(Tok, diag::ext_thread_before, "static");
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, PrevSpec);
+ break;
+ case tok::kw_auto:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, PrevSpec);
+ break;
+ case tok::kw_register:
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, PrevSpec);
+ break;
+ case tok::kw___thread:
+ if (DS.SCS_thread_specified)
+ isInvalid = 2, PrevSpec = "__thread";
+ else
+ DS.SCS_thread_specified = true;
+ break;
+
// type-specifiers
case tok::kw_short:
isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, PrevSpec);
@@ -144,7 +173,8 @@
// function-specifier
case tok::kw_inline:
- isInvalid = DS.SetFuncSpec(DeclSpec::FS_inline, PrevSpec);
+ // 'inline inline' is ok.
+ DS.FS_inline_specified = true;
break;
}
// If the specifier combination wasn't legal, issue a diagnostic.
Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38816&r1=38815&r2=38816&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:24:53 2007
@@ -247,6 +247,8 @@
"ISO C does not support plain '_Complex' meaning '_Complex double'")
DIAG(ext_integer_complex, EXTENSION,
"ISO C does not support complex integer types")
+DIAG(ext_thread_before, EXTENSION,
+ "'__thread' before 'static'")
DIAG(err_invalid_decl_spec_combination, ERROR,
"cannot combine with previous '%s' declaration specifier")
@@ -260,5 +262,7 @@
"'long long %s' is invalid")
DIAG(err_invalid_complex_spec, ERROR,
"'_Complex %s' is invalid")
+DIAG(err_invalid_thread_spec, ERROR,
+ "'__thread %s' is invalid")
#undef DIAG
Modified: cfe/cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=38816&r1=38815&r2=38816&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/DeclSpec.h Wed Jul 11 11:24:53 2007
@@ -36,6 +36,9 @@
SCS_register
} StorageClassSpec : 3;
+ // storage-class-specifier
+ bool SCS_thread_specified : 1;
+
// type-specifier
enum TSW {
TSW_unspecified,
@@ -79,10 +82,7 @@
unsigned TypeQualifiers : 3; // Bitwise OR of typequals.
// function-specifier
- enum FS {
- FS_unspecified,
- FS_inline
- } FuncSpec : 1;
+ bool FS_inline_specified : 1;
// attributes.
// FIXME: implement declspec attributes.
@@ -98,12 +98,13 @@
DeclSpec()
: StorageClassSpec(SCS_unspecified),
+ SCS_thread_specified(false),
TypeSpecWidth(TSW_unspecified),
TypeSpecComplex(TSC_unspecified),
TypeSpecSign(TSS_unspecified),
TypeSpecType(TST_unspecified),
TypeQualifiers(TSS_unspecified),
- FuncSpec(FS_unspecified) {
+ FS_inline_specified(false) {
}
/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this
@@ -114,11 +115,11 @@
/// 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 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);
bool SetTypeQual(TQ T, const char *&PrevSpec, const LangOptions &Lang);
More information about the cfe-commits
mailing list