[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