Add support for parsing and representing C++ constructor declarations.

Notes:
  - Constructors are never found by name lookup, so they'll never get
    pushed into any scope. Instead, they are stored as an 
    OverloadedFunctionDecl in CXXRecordDecl for easy overloading.
  - There's a new action isCurrentClassName that determines whether an
    identifier is the name of the innermost class currently being defined;
    we use this to identify the declarator-id grammar rule that refers to 
    a type-name. 
  - MinimalAction does *not* support parsing constructors.
  - We now handle virtual and explicit function specifiers.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58499 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 243a15f..7a84171 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -383,7 +383,12 @@
   
   // Issue diagnostic and remove function specfier if present.
   if (Specs & DeclSpec::PQ_FunctionSpecifier) {
-    Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+    if (DS.isInlineSpecified())
+      Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
+    if (DS.isVirtualSpecified())
+      Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
+    if (DS.isExplicitSpecified())
+      Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
     DS.ClearFunctionSpecs();
   }
 }
@@ -433,6 +438,8 @@
 /// [C99]   'restrict'
 ///       function-specifier: [C99 6.7.4]
 /// [C99]   'inline'
+/// [C++]   'virtual'
+/// [C++]   'explicit'
 ///
 void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) {
   DS.SetRangeStart(Tok.getLocation());
@@ -462,6 +469,16 @@
       if (TypeRep == 0)
         goto DoneWithDeclSpec;
       
+      // C++: If the identifier is actually the name of the class type
+      // being defined and the next token is a '(', then this is a
+      // constructor declaration. We're done with the decl-specifiers
+      // and will treat this token as an identifier.
+      if (getLang().CPlusPlus && 
+          CurScope->isCXXClassScope() &&
+          Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) && 
+          NextToken().getKind() == tok::l_paren)
+        goto DoneWithDeclSpec;
+
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef, Loc, PrevSpec,
                                      TypeRep);
       if (isInvalid)
@@ -607,6 +624,14 @@
     case tok::kw_inline:
       isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec);
       break;
+
+    case tok::kw_virtual:
+      isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec);
+      break;
+
+    case tok::kw_explicit:
+      isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec);
+      break;
       
     case tok::less:
       // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
@@ -1056,6 +1081,8 @@
 
     // function-specifier
   case tok::kw_inline:
+  case tok::kw_virtual:
+  case tok::kw_explicit:
 
     // GNU typeof support.
   case tok::kw_typeof:
@@ -1217,7 +1244,11 @@
 ///                    parameter-type-list[opt] ')'
 /// [C++]   direct-declarator '(' parameter-declaration-clause ')'
 ///                    cv-qualifier-seq[opt] exception-specification[opt]
-///
+/// [C++]   declarator-id
+//
+//        declarator-id: [C++ 8]
+//          id-expression
+//          '::'[opt] nested-name-specifier[opt] type-name
 void Parser::ParseDirectDeclarator(Declarator &D) {
   // Parse the first direct-declarator seen.
   if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {