[cfe-commits] r38807 - in /cfe/cfe/trunk: Parse/DeclSpec.cpp Parse/ParseDecl.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:24:49 PDT 2007


Author: sabre
Date: Wed Jul 11 11:24:48 2007
New Revision: 38807

URL: http://llvm.org/viewvc/llvm-project?rev=38807&view=rev
Log:
Parse and validate cvr type-qualifiers

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
    cfe/cfe/trunk/include/clang/Parse/Parser.h

Modified: cfe/cfe/trunk/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/DeclSpec.cpp?rev=38807&r1=38806&r2=38807&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/DeclSpec.cpp (original)
+++ cfe/cfe/trunk/Parse/DeclSpec.cpp Wed Jul 11 11:24:48 2007
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Parse/Declarations.h"
+#include "clang/Basic/LangOptions.h"
 using namespace llvm;
 using namespace clang;
 
@@ -82,6 +83,15 @@
   return true;
 }
 
+static bool BadSpecifier(DeclSpec::TQ T, const char *&PrevSpec) {
+  switch (T) {
+  case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
+  case DeclSpec::TQ_const:       PrevSpec = "const"; break;
+  case DeclSpec::TQ_restrict:    PrevSpec = "restrict"; break;
+  case DeclSpec::TQ_volatile:    PrevSpec = "volatile"; 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
@@ -112,6 +122,14 @@
   return false;
 }
 
+bool DeclSpec::SetTypeQual(TQ T, const char *&PrevSpec,
+                           const LangOptions &Lang) {
+  // Duplicates turn into warnings pre-C99.
+  if ((TypeQualifiers & T) && !Lang.C99)
+    return BadSpecifier(T, PrevSpec);
+  TypeQualifiers |= T;
+  return false;
+}
 
 bool DeclSpec::SetFuncSpec(FS F, const char *&PrevSpec) {
   // 'inline inline' is ok.
@@ -123,7 +141,7 @@
 /// "_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() {
+diag::kind DeclSpec::Finish(const LangOptions &Lang) {
   // FIXME: implement this.
   
   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=38807&r1=38806&r2=38807&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:24:48 2007
@@ -22,12 +22,19 @@
 
 /// ParseDeclarationSpecifiers
 ///       declaration-specifiers: [C99 6.7]
-///         storage-class-specifier declaration-specifiers [opt] [TODO]
-///             //__thread
+///         storage-class-specifier declaration-specifiers [opt]
 ///         type-specifier declaration-specifiers [opt]
-///         type-qualifier declaration-specifiers [opt]          [TODO]
-/// [C99]   function-specifier declaration-specifiers [opt]      [TODO]
-///
+///         type-qualifier declaration-specifiers [opt]
+/// [C99]   function-specifier declaration-specifiers [opt]
+/// [GNU]   attributes declaration-specifiers [opt]                [TODO]
+///
+///       storage-class-specifier: [C99 6.7.1]
+///         'typedef'
+///         'extern'
+///         'static'
+///         'auto'
+///         'register'
+/// [GNU]   '__thread'
 ///       type-specifier: [C99 6.7.2]
 ///         'void'
 ///         'char'
@@ -40,23 +47,33 @@
 ///         'unsigned'
 /// [C99]   '_Bool'
 /// [C99]   '_Complex'
-/// [C99]   '_Imaginary'
-///         struct-or-union-specifier [TODO]
-///         enum-specifier [TODO]
-///         typedef-name [TODO]
+/// [C99]   '_Imaginary'  // Removed in TC2?
+/// [GNU]   '_Decimal32'
+/// [GNU]   '_Decimal64'
+/// [GNU]   '_Decimal128'
+/// [OBJC]  class-name objc-protocol-refs [opt]   [TODO]
+/// [OBJC]  typedef-name objc-protocol-refs       [TODO]
+/// [OBJC]  objc-protocol-refs                    [TODO]
+///         struct-or-union-specifier             [TODO]
+///         enum-specifier                        [TODO]
+///         typedef-name                          [TODO]
+///       type-qualifier:
+///         const
+///         volatile
+/// [C99]   restrict
 ///       function-specifier: [C99 6.7.4]
 /// [C99]   inline
 ///
 void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
   SourceLocation StartLoc = Tok.getLocation();
   while (1) {
-    bool isInvalid = false;
+    int isInvalid = false;
     const char *PrevSpec = 0;
     switch (Tok.getKind()) {
     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();
+      diag::kind Res = DS.Finish(getLang());
       if (Res != diag::NUM_DIAGNOSTICS)
         Diag(StartLoc, Res);
       return;
@@ -115,6 +132,17 @@
     //case tok::kw_struct:
     //case tok::kw_union:
     //case tok::kw_enum:
+    
+    // type-qualifier
+    case tok::kw_const:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , PrevSpec, getLang())*2;
+      break;
+    case tok::kw_volatile:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, PrevSpec, getLang())*2;
+      break;
+    case tok::kw_restrict:
+      isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, PrevSpec, getLang())*2;
+      break;
       
     // function-specifier
     case tok::kw_inline:
@@ -124,7 +152,10 @@
     // 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);
+      if (isInvalid == 1)  // Error.
+        Diag(Tok, diag::err_invalid_decl_spec_combination, PrevSpec);
+      else                 // extwarn.
+        Diag(Tok, diag::ext_duplicate_declspec, PrevSpec);
     }
     ConsumeToken();
   }

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=38807&r1=38806&r2=38807&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:24:48 2007
@@ -238,7 +238,8 @@
      "ISO C forbids an empty source file")
 DIAG(ext_top_level_semi, EXTENSION,
      "ISO C does not allow extra ';' outside of a function")
-
+DIAG(ext_duplicate_declspec, EXTENSION,
+     "duplicate '%s' declaration specifier")
 
 DIAG(err_invalid_decl_spec_combination, ERROR,
      "cannot combine declaration specifier with previous '%s' specifier")

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=38807&r1=38806&r2=38807&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/DeclSpec.h Wed Jul 11 11:24:48 2007
@@ -18,6 +18,7 @@
 
 namespace llvm {
 namespace clang {
+  class LangOptions;
   
 /// DeclSpec - This class captures information about "declaration specifiers",
 /// which encompases storage-class-specifiers, type-specifiers, type-qualifiers,
@@ -118,11 +119,13 @@
   bool SetTypeSpecType(TST T, const char *&PrevSpec);
   bool SetFuncSpec(FS F, const char *&PrevSpec);
   
+  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,
   /// DeclSpec is guaranteed self-consistent, even if an error occurred.
-  diag::kind Finish();
+  diag::kind Finish(const LangOptions &Lang);
 };
   
 }  // end namespace clang

Modified: cfe/cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Parser.h?rev=38807&r1=38806&r2=38807&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:24:48 2007
@@ -38,6 +38,8 @@
 public:
   Parser(Preprocessor &PP, ParserActions &Actions);
 
+  const LangOptions &getLang() const { return PP.getLangOptions(); }
+  
   // Type forwarding.  All of these are statically 'void*', but they may all be
   // different actual classes based on the actions in place.
   typedef ParserActions::ExprTy ExprTy;





More information about the cfe-commits mailing list