Add parsing and AST support for GNU "typeof".
Many small changes to lot's of files.
Still some FIXME's, however the basic support is in place.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40631 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp
index b05fd78..6b5215b 100644
--- a/Parse/ParseDecl.cpp
+++ b/Parse/ParseDecl.cpp
@@ -482,6 +482,11 @@
       ParseEnumSpecifier(DS);
       continue;
     
+    // GNU typeof support.
+    case tok::kw_typeof:
+      ParseTypeofSpecifier(DS);
+      continue;
+      
     // type-qualifier
     case tok::kw_const:
       isInvalid = DS.SetTypeQual(DeclSpec::TQ_const   , Loc, PrevSpec,
@@ -825,6 +830,9 @@
   default: return false;
     // GNU attributes support.
   case tok::kw___attribute:
+    // GNU typeof support.
+  case tok::kw_typeof:
+  
     // type-specifiers
   case tok::kw_short:
   case tok::kw_long:
@@ -902,6 +910,9 @@
   case tok::kw_const:
   case tok::kw_volatile:
   case tok::kw_restrict:
+
+    // GNU typeof support.
+  case tok::kw_typeof:
     
     // function-specifier
   case tok::kw_inline:
@@ -1397,3 +1408,40 @@
                                           NumElements.Val, StartLoc));
 }
 
+/// [GNU] typeof-specifier:
+///         typeof ( expressions )
+///         typeof ( type-name )
+///
+void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
+  assert(Tok.getKind() == tok::kw_typeof && "Not a typeof specifier");
+  SourceLocation StartLoc = ConsumeToken();
+
+  if (Tok.getKind() != tok::l_paren) {
+    // FIXME: handle error.
+  }
+  SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
+  
+  if (isTypeSpecifierQualifier()) {
+    TypeTy *Ty = ParseTypeName();
+
+    const char *PrevSpec = 0;
+    bool isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, 
+                                        PrevSpec, Ty);
+    // FIXME: what we have an invalid type? (or Ty is null)
+  } else { // we have an expression.
+    ExprResult Result = ParseExpression();
+    if (Result.isInvalid) {
+      SkipUntil(tok::r_paren);
+    }
+    const char *PrevSpec = 0;
+    bool isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, 
+                                        PrevSpec, Result.Val);
+    // FIXME: what we have an invalid type? (or Result.Val is null)
+  }
+  // Match the ')'.
+  if (Tok.getKind() == tok::r_paren)
+    RParenLoc = ConsumeParen();
+  else
+    MatchRHSPunctuation(tok::r_paren, LParenLoc);
+}
+