[cfe-commits] r38811 - 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:51 PDT 2007


Author: sabre
Date: Wed Jul 11 11:24:50 2007
New Revision: 38811

URL: http://llvm.org/viewvc/llvm-project?rev=38811&view=rev
Log:
Emit diagnostics for things like 'signed _Bool' and 'short float'

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=38811&r1=38810&r2=38811&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/DeclSpec.cpp (original)
+++ cfe/cfe/trunk/Parse/DeclSpec.cpp Wed Jul 11 11:24:50 2007
@@ -13,6 +13,7 @@
 
 #include "clang/Parse/Declarations.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 using namespace llvm;
 using namespace clang;
 
@@ -67,19 +68,24 @@
   return true;
 }
 
-static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) {
+static const char *getSpecifierName(DeclSpec::TST T) {
   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;
+  default: assert(0 && "Unknown typespec!");
+  case DeclSpec::TST_unspecified: return "unspecified";
+  case DeclSpec::TST_void:        return "void";
+  case DeclSpec::TST_char:        return "char";
+  case DeclSpec::TST_int:         return "int";
+  case DeclSpec::TST_float:       return "float";
+  case DeclSpec::TST_double:      return "double";
+  case DeclSpec::TST_bool:        return "_Bool";
+  case DeclSpec::TST_decimal32:   return "_Decimal32";
+  case DeclSpec::TST_decimal64:   return "_Decimal64";
+  case DeclSpec::TST_decimal128:  return "_Decimal128";
   }
+}
+
+static bool BadSpecifier(DeclSpec::TST T, const char *&PrevSpec) {
+  PrevSpec = getSpecifierName(T);
   return true;
 }
 
@@ -143,8 +149,38 @@
 /// "_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(const LangOptions &Lang) {
-  // FIXME: implement this.
+void DeclSpec::Finish(SourceLocation Loc, Diagnostic &D,
+                      const LangOptions &Lang) {
+  // signed/unsigned are not valid with void,float,double,bool,decimal*.
+  if (TypeSpecSign != TSS_unspecified) {
+    if (TypeSpecType == TST_void      || TypeSpecType == TST_float     ||
+        TypeSpecType == TST_double    || TypeSpecType == TST_bool      ||
+        TypeSpecType == TST_decimal32 || TypeSpecType == TST_decimal64 ||
+        TypeSpecType == TST_decimal128) {
+      D.Report(Loc, diag::err_invalid_sign_spec,getSpecifierName(TypeSpecType));
+      TypeSpecSign = TSS_unspecified;
+    }
+  }
+  
+  // Validate the width of the type.
+  switch (TypeSpecWidth) {
+  case TSW_unspecified: break;
+  case TSW_short:    // short int
+  case TSW_longlong: // long long int
+    if (TypeSpecType != TST_unspecified && TypeSpecType != TST_int) {
+      D.Report(Loc, TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec :
+               diag::err_invalid_longlong_spec,
+               getSpecifierName(TypeSpecType));
+      TypeSpecType = TST_int;
+    }
+    break;
+  case TSW_long:  // long double, long int
+    if (TypeSpecType != TST_unspecified && TypeSpecType != TST_int &&
+        TypeSpecType != TST_double) {
+      D.Report(Loc, diag::err_invalid_long_spec,
+               getSpecifierName(TypeSpecType));
+      TypeSpecType = TST_int;
+    }
+  }
   
-  return diag::NUM_DIAGNOSTICS;
 }

Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=38811&r1=38810&r2=38811&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:24:50 2007
@@ -28,7 +28,7 @@
 /// [C99]   function-specifier declaration-specifiers [opt]
 /// [GNU]   attributes declaration-specifiers [opt]                [TODO]
 ///
-///       storage-class-specifier: [C99 6.7.1]
+///       storage-class-specifier: [C99 6.7.1]   [TODO]
 ///         'typedef'
 ///         'extern'
 ///         'static'
@@ -73,9 +73,7 @@
     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(getLang());
-      if (Res != diag::NUM_DIAGNOSTICS)
-        Diag(StartLoc, Res);
+      DS.Finish(StartLoc, Diags, getLang());
       return;
     // type-specifiers
     case tok::kw_short:

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=38811&r1=38810&r2=38811&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:24:50 2007
@@ -243,5 +243,13 @@
 
 DIAG(err_invalid_decl_spec_combination, ERROR,
      "cannot combine declaration specifier with previous '%s' specifier")
+DIAG(err_invalid_sign_spec, ERROR,
+     "'%s' cannot be signed or unsigned")
+DIAG(err_invalid_short_spec, ERROR,
+     "'short %s' is invalid")
+DIAG(err_invalid_long_spec, ERROR,
+     "'long %s' is invalid")
+DIAG(err_invalid_longlong_spec, ERROR,
+     "'long long %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=38811&r1=38810&r2=38811&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/DeclSpec.h Wed Jul 11 11:24:50 2007
@@ -19,6 +19,7 @@
 namespace llvm {
 namespace clang {
   class LangOptions;
+  class SourceLocation;
   
 /// DeclSpec - This class captures information about "declaration specifiers",
 /// which encompases storage-class-specifiers, type-specifiers, type-qualifiers,
@@ -121,11 +122,10 @@
   
   bool SetTypeQual(TQ T, const char *&PrevSpec, const LangOptions &Lang);
   
-  /// 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,
+  /// Finish - This does final analysis of the declspec, issuing diagnostics for
+  /// things like "_Imaginary" (lacking an FP type).  After calling this method,
   /// DeclSpec is guaranteed self-consistent, even if an error occurred.
-  diag::kind Finish(const LangOptions &Lang);
+  void Finish(SourceLocation Loc, Diagnostic &D,const LangOptions &Lang);
 };
   
 }  // end namespace clang





More information about the cfe-commits mailing list