Almost complete implementation of rvalue references. One bug, and a few unclear areas. Maybe Doug can shed some light on some of the fixmes.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67059 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 29d0796..13c3e87 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -272,7 +272,7 @@
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
   QualType BuildPointerType(QualType T, unsigned Quals, 
                             SourceLocation Loc, DeclarationName Entity);
-  QualType BuildReferenceType(QualType T, unsigned Quals, 
+  QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
                               SourceLocation Loc, DeclarationName Entity);
   QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
                           Expr *ArraySize, unsigned Quals,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index fa84c7d..acf8224 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -802,7 +802,7 @@
     QualType ArgType = ClassType;
     if (HasConstCopyConstructor)
       ArgType = ArgType.withConst();
-    ArgType = Context.getReferenceType(ArgType);
+    ArgType = Context.getLValueReferenceType(ArgType);
 
     //   An implicitly-declared copy constructor is an inline public
     //   member of its class.
@@ -880,10 +880,10 @@
     //
     //       X& X::operator=(X&)
     QualType ArgType = ClassType;
-    QualType RetType = Context.getReferenceType(ArgType);
+    QualType RetType = Context.getLValueReferenceType(ArgType);
     if (HasConstCopyAssignment)
       ArgType = ArgType.withConst();
-    ArgType = Context.getReferenceType(ArgType);
+    ArgType = Context.getLValueReferenceType(ArgType);
 
     //   An implicitly-declared copy assignment operator is an inline public
     //   member of its class.
@@ -1630,7 +1630,8 @@
 Sema::ReferenceCompareResult 
 Sema::CompareReferenceRelationship(QualType T1, QualType T2, 
                                    bool& DerivedToBase) {
-  assert(!T1->isReferenceType() && "T1 must be the pointee type of the reference type");
+  assert(!T1->isReferenceType() &&
+    "T1 must be the pointee type of the reference type");
   assert(!T2->isReferenceType() && "T2 cannot be a reference type");
 
   T1 = Context.getCanonicalType(T1);
@@ -1713,6 +1714,7 @@
   }
 
   // Compute some basic properties of the types and the initializer.
+  bool isRValRef = DeclType->isRValueReferenceType();
   bool DerivedToBase = false;
   Expr::isLvalueResult InitLvalue = Init->isLvalue(Context);
   ReferenceCompareResult RefRelationship 
@@ -1738,6 +1740,15 @@
       RefRelationship >= Ref_Compatible_With_Added_Qualification) {
     BindsDirectly = true;
 
+    // Rvalue references cannot bind to lvalues (N2812).
+    // FIXME: This part of rvalue references is still in flux. Revisit later.
+    if (isRValRef) {
+      if (!ICS)
+        Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref)
+          << Init->getSourceRange();
+      return true;
+    }
+
     if (ICS) {
       // C++ [over.ics.ref]p1:
       //   When a parameter of reference type binds directly (8.5.3)
@@ -1774,7 +1785,9 @@
   //          92) (this conversion is selected by enumerating the
   //          applicable conversion functions (13.3.1.6) and choosing
   //          the best one through overload resolution (13.3)),
-  if (!SuppressUserConversions && T2->isRecordType()) {
+  // FIXME: Without standard language for N2812, the rvalue reference treatment
+  // here is pretty much a guess.
+  if (!isRValRef && !SuppressUserConversions && T2->isRecordType()) {
     // FIXME: Look for conversions in base classes!
     CXXRecordDecl *T2RecordDecl 
       = dyn_cast<CXXRecordDecl>(T2->getAsRecordType()->getDecl());
@@ -1790,7 +1803,7 @@
       // If the conversion function doesn't return a reference type,
       // it can't be considered for this conversion.
       // FIXME: This will change when we support rvalue references.
-      if (Conv->getConversionType()->isReferenceType() &&
+      if (Conv->getConversionType()->isLValueReferenceType() &&
           (AllowExplicit || !Conv->isExplicit()))
         AddConversionCandidate(Conv, Init, DeclType, CandidateSet);
     }
@@ -1862,8 +1875,8 @@
   }
 
   //     -- Otherwise, the reference shall be to a non-volatile const
-  //        type (i.e., cv1 shall be const).
-  if (T1.getCVRQualifiers() != QualType::Const) {
+  //        type (i.e., cv1 shall be const), or shall be an rvalue reference.
+  if (!isRValRef && T1.getCVRQualifiers() != QualType::Const) {
     if (!ICS)
       Diag(Init->getSourceRange().getBegin(),
            diag::err_not_reference_to_const_init)
@@ -2200,6 +2213,8 @@
       RequireCompleteType(Begin, BaseType, DK))
     Invalid = true;
 
+  // FIXME: C++0x [except.handle] names the handler as cv T or cv T&, i.e.
+  // rvalue references aren't there. Oversight or intentional?
   // FIXME: Need to test for ability to copy-construct and destroy the
   // exception variable.
   // FIXME: Need to check for abstract classes.
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 5450d19..b3d94c3 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -764,7 +764,7 @@
     // the constructor or conversion operator, and then cope with the
     // standard conversions.
     ImpCastExprToType(From, ToType.getNonReferenceType(), 
-                      ToType->isReferenceType());
+                      ToType->isLValueReferenceType());
     return false;
 
   case ImplicitConversionSequence::EllipsisConversion:
@@ -800,7 +800,7 @@
     // FIXME: Create a temporary object by calling the copy
     // constructor.
     ImpCastExprToType(From, ToType.getNonReferenceType(), 
-                      ToType->isReferenceType());
+                      ToType->isLValueReferenceType());
     return false;
   }
 
@@ -893,8 +893,10 @@
     break;
 
   case ICK_Qualification:
+    // FIXME: Not sure about lvalue vs rvalue here in the presence of
+    // rvalue references.
     ImpCastExprToType(From, ToType.getNonReferenceType(), 
-                      ToType->isReferenceType());
+                      ToType->isLValueReferenceType());
     break;
 
   default:
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 02df9b3..e0d3b7e 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -121,7 +121,7 @@
     return false;
   
   // C++ [dcl.init.ref]p1:
-  //   A variable declared to be a T&, that is "reference to type T"
+  //   A variable declared to be a T& or T&&, that is "reference to type T"
   //   (8.3.2), shall be initialized by an object, or function, of
   //   type T or by an object that can be converted into a T.
   if (DeclType->isReferenceType())
diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp
index a8ad10d..9f5c5e5 100644
--- a/lib/Sema/SemaNamedCast.cpp
+++ b/lib/Sema/SemaNamedCast.cpp
@@ -115,9 +115,10 @@
 
   DestType = Self.Context.getCanonicalType(DestType);
   QualType SrcType = SrcExpr->getType();
-  if (const ReferenceType *DestTypeTmp = DestType->getAsReferenceType()) {
+  if (const LValueReferenceType *DestTypeTmp =
+        DestType->getAsLValueReferenceType()) {
     if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
-      // Cannot cast non-lvalue to reference type.
+      // Cannot cast non-lvalue to lvalue reference type.
       Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
         << "const_cast" << OrigDestType << SrcExpr->getSourceRange();
       return;
@@ -141,6 +142,8 @@
   if (!DestType->isPointerType() && !DestType->isMemberPointerType()) {
     // Cannot cast to non-pointer, non-reference type. Note that, if DestType
     // was a reference type, we converted it to a pointer above.
+    // The status of rvalue references isn't entirely clear, but it looks like
+    // conversion to them is simply invalid.
     // C++ 5.2.11p3: For two pointer types [...]
     Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest)
       << OrigDestType << DestRange;
@@ -214,7 +217,8 @@
 
   DestType = Self.Context.getCanonicalType(DestType);
   QualType SrcType = SrcExpr->getType();
-  if (const ReferenceType *DestTypeTmp = DestType->getAsReferenceType()) {
+  if (const LValueReferenceType *DestTypeTmp =
+        DestType->getAsLValueReferenceType()) {
     if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
       // Cannot cast non-lvalue to reference type.
       Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
@@ -228,6 +232,14 @@
     // This code does this transformation for the checked types.
     DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
     SrcType = Self.Context.getPointerType(SrcType);
+  } else if (const RValueReferenceType *DestTypeTmp =
+               DestType->getAsRValueReferenceType()) {
+    // Both the reference conversion and the rvalue rules apply.
+    Self.DefaultFunctionArrayConversion(SrcExpr);
+    SrcType = SrcExpr->getType();
+
+    DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
+    SrcType = Self.Context.getPointerType(SrcType);
   } else {
     // C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and
     //   function-to-pointer standard conversions are performed on the
@@ -425,6 +437,8 @@
   // conversion using B's conversion constructor.
   // DR 427 specifies that the downcast is to be applied here.
 
+  // FIXME: With N2812, casts to rvalue refs will change.
+
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
   if (DestType->isVoidType()) {
     return;
@@ -787,9 +801,11 @@
     return;
   }
 
-  // C++ 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
-  //   complete class type, [...]. If T is a reference type, v shall be an
-  //   lvalue of a complete class type, [...].
+  // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
+  //   complete class type, [...]. If T is an lvalue reference type, v shall be
+  //   an lvalue of a complete class type, [...]. If T is an rvalue reference
+  //   type, v shall be an expression having a complete effective class type,
+  //   [...]
 
   QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
   QualType SrcPointee;
@@ -801,12 +817,14 @@
         << OrigSrcType << SrcExpr->getSourceRange();
       return;
     }
-  } else {
+  } else if (DestReference->isLValueReferenceType()) {
     if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
       Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
         << "dynamic_cast" << OrigDestType << OpRange;
     }
     SrcPointee = SrcType;
+  } else {
+    SrcPointee = SrcType;
   }
 
   const RecordType *SrcRecord = SrcPointee->getAsRecordType();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 8943aa6..5321935 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -519,8 +519,10 @@
     // We were able to resolve the address of the overloaded function,
     // so we can convert to the type of that function.
     FromType = Fn->getType();
-    if (ToType->isReferenceType())
-      FromType = Context.getReferenceType(FromType);
+    if (ToType->isLValueReferenceType())
+      FromType = Context.getLValueReferenceType(FromType);
+    else if (ToType->isRValueReferenceType())
+      FromType = Context.getRValueReferenceType(FromType);
     else if (ToType->isMemberPointerType()) {
       // Resolve address only succeeds if both sides are member pointers,
       // but it doesn't have to be the same class. See DR 247.
@@ -2734,7 +2736,7 @@
          Arith < NumArithmeticTypes; ++Arith) {
       QualType ArithTy = ArithmeticTypes[Arith];
       QualType ParamTypes[2] 
-        = { Context.getReferenceType(ArithTy), Context.IntTy };
+        = { Context.getLValueReferenceType(ArithTy), Context.IntTy };
 
       // Non-volatile version.
       if (NumArgs == 1)
@@ -2743,7 +2745,7 @@
         AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet);
 
       // Volatile version
-      ParamTypes[0] = Context.getReferenceType(ArithTy.withVolatile());
+      ParamTypes[0] = Context.getLValueReferenceType(ArithTy.withVolatile());
       if (NumArgs == 1)
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
       else
@@ -2767,7 +2769,7 @@
         continue;
 
       QualType ParamTypes[2] = { 
-        Context.getReferenceType(*Ptr), Context.IntTy 
+        Context.getLValueReferenceType(*Ptr), Context.IntTy 
       };
       
       // Without volatile
@@ -2778,7 +2780,7 @@
 
       if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
         // With volatile
-        ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
+        ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
         if (NumArgs == 1)
           AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);
         else
@@ -2802,7 +2804,7 @@
          Ptr != CandidateTypes.pointer_end(); ++Ptr) {
       QualType ParamTy = *Ptr;
       QualType PointeeTy = ParamTy->getAsPointerType()->getPointeeType();
-      AddBuiltinCandidate(Context.getReferenceType(PointeeTy), 
+      AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy), 
                           &ParamTy, Args, 1, CandidateSet);
     }
     break;
@@ -3021,14 +3023,14 @@
       QualType ParamTypes[2];
 
       // T& operator=(T&, T)
-      ParamTypes[0] = Context.getReferenceType(*Enum);
+      ParamTypes[0] = Context.getLValueReferenceType(*Enum);
       ParamTypes[1] = *Enum;
       AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                           /*IsAssignmentOperator=*/false);
 
       if (!Context.getCanonicalType(*Enum).isVolatileQualified()) {
         // volatile T& operator=(volatile T&, T)
-        ParamTypes[0] = Context.getReferenceType((*Enum).withVolatile());
+        ParamTypes[0] = Context.getLValueReferenceType((*Enum).withVolatile());
         ParamTypes[1] = *Enum;
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssignmentOperator=*/false);
@@ -3060,13 +3062,13 @@
       ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType();
 
       // non-volatile version
-      ParamTypes[0] = Context.getReferenceType(*Ptr);
+      ParamTypes[0] = Context.getLValueReferenceType(*Ptr);
       AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                           /*IsAssigmentOperator=*/Op == OO_Equal);
 
       if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) {
         // volatile version
-        ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
+        ParamTypes[0] = Context.getLValueReferenceType((*Ptr).withVolatile());
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssigmentOperator=*/Op == OO_Equal);
       }
@@ -3094,13 +3096,13 @@
         ParamTypes[1] = ArithmeticTypes[Right];
 
         // Add this built-in operator as a candidate (VQ is empty).
-        ParamTypes[0] = Context.getReferenceType(ArithmeticTypes[Left]);
+        ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssigmentOperator=*/Op == OO_Equal);
 
         // Add this built-in operator as a candidate (VQ is 'volatile').
         ParamTypes[0] = ArithmeticTypes[Left].withVolatile();
-        ParamTypes[0] = Context.getReferenceType(ParamTypes[0]);
+        ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
                             /*IsAssigmentOperator=*/Op == OO_Equal);
       }
@@ -3132,13 +3134,13 @@
         ParamTypes[1] = ArithmeticTypes[Right];
 
         // Add this built-in operator as a candidate (VQ is empty).
-        ParamTypes[0] = Context.getReferenceType(ArithmeticTypes[Left]);
+        ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
 
         // Add this built-in operator as a candidate (VQ is 'volatile').
         ParamTypes[0] = ArithmeticTypes[Left];
         ParamTypes[0].addVolatile();
-        ParamTypes[0] = Context.getReferenceType(ParamTypes[0]);
+        ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]);
         AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
       }
     }
@@ -3190,7 +3192,7 @@
          Ptr != CandidateTypes.pointer_end(); ++Ptr) {
       QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
       QualType PointeeType = (*Ptr)->getAsPointerType()->getPointeeType();
-      QualType ResultTy = Context.getReferenceType(PointeeType);
+      QualType ResultTy = Context.getLValueReferenceType(PointeeType);
 
       // T& operator[](T*, ptrdiff_t)
       AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
@@ -3407,11 +3409,17 @@
         // retaining as many typedefs as possible while still showing
         // the function type (and, therefore, its parameter types).
         QualType FnType = Cand->Surrogate->getConversionType();
-        bool isReference = false;
+        bool isLValueReference = false;
+        bool isRValueReference = false;
         bool isPointer = false;
-        if (const ReferenceType *FnTypeRef = FnType->getAsReferenceType()) {
+        if (const LValueReferenceType *FnTypeRef =
+              FnType->getAsLValueReferenceType()) {
           FnType = FnTypeRef->getPointeeType();
-          isReference = true;
+          isLValueReference = true;
+        } else if (const RValueReferenceType *FnTypeRef =
+                     FnType->getAsRValueReferenceType()) {
+          FnType = FnTypeRef->getPointeeType();
+          isRValueReference = true;
         }
         if (const PointerType *FnTypePtr = FnType->getAsPointerType()) {
           FnType = FnTypePtr->getPointeeType();
@@ -3421,7 +3429,8 @@
         FnType = QualType(FnType->getAsFunctionType(), 0);
         // Reconstruct the pointer/reference as appropriate.
         if (isPointer) FnType = Context.getPointerType(FnType);
-        if (isReference) FnType = Context.getReferenceType(FnType);
+        if (isRValueReference) FnType = Context.getRValueReferenceType(FnType);
+        if (isLValueReference) FnType = Context.getLValueReferenceType(FnType);
 
         Diag(Cand->Surrogate->getLocation(), diag::err_ovl_surrogate_cand)
           << FnType;
@@ -4144,7 +4153,7 @@
     // FIXME: Represent the user-defined conversion in the AST!
     ImpCastExprToType(Object,
                       Conv->getConversionType().getNonReferenceType(),
-                      Conv->getConversionType()->isReferenceType());
+                      Conv->getConversionType()->isLValueReferenceType());
     return ActOnCallExpr(S, ExprArg(*this, Object), LParenLoc,
                          MultiExprArg(*this, (ExprTy**)Args, NumArgs),
                          CommaLocs, RParenLoc).release();
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index dbdc5a8..fd541f3 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -218,14 +218,24 @@
   return QualType();
 }
 
-QualType 
-TemplateTypeInstantiator::InstantiateReferenceType(const ReferenceType *T, 
-                                                   unsigned Quals) const {
+QualType
+TemplateTypeInstantiator::InstantiateLValueReferenceType(
+    const LValueReferenceType *T, unsigned Quals) const {
   QualType ReferentType = Instantiate(T->getPointeeType());
   if (ReferentType.isNull())
     return QualType();
 
-  return SemaRef.BuildReferenceType(ReferentType, Quals, Loc, Entity);
+  return SemaRef.BuildReferenceType(ReferentType, true, Quals, Loc, Entity);
+}
+
+QualType
+TemplateTypeInstantiator::InstantiateRValueReferenceType(
+    const RValueReferenceType *T, unsigned Quals) const {
+  QualType ReferentType = Instantiate(T->getPointeeType());
+  if (ReferentType.isNull())
+    return QualType();
+
+  return SemaRef.BuildReferenceType(ReferentType, false, Quals, Loc, Entity);
 }
 
 QualType 
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index bfbc6c3..ac0e1e1 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -319,8 +319,16 @@
 ///
 /// \returns A suitable reference type, if there are no
 /// errors. Otherwise, returns a NULL type.
-QualType Sema::BuildReferenceType(QualType T, unsigned Quals, 
+QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned Quals,
                                   SourceLocation Loc, DeclarationName Entity) {
+  if (LValueRef) {
+    if (const RValueReferenceType *R = T->getAsRValueReferenceType()) {
+      // FIXME: Find the C++0x reference for reference collapsing.
+      // In reference collapsing, lvalue refs win over rvalue refs.
+      return Context.getLValueReferenceType(R->getPointeeType()).
+               getQualifiedType(Quals);
+    }
+  }
   if (T->isReferenceType()) {
     // C++ [dcl.ref]p4: There shall be no references to references.
     // 
@@ -367,7 +375,9 @@
   Quals &= ~QualType::Volatile;
 
   // Handle restrict on references.
-  return Context.getReferenceType(T).getQualifiedType(Quals);
+  if (LValueRef)
+    return Context.getLValueReferenceType(T).getQualifiedType(Quals);
+  return Context.getRValueReferenceType(T).getQualifiedType(Quals);
 }
 
 /// \brief Build an array type.
@@ -603,8 +613,8 @@
       T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
       break;
     case DeclaratorChunk::Reference:
-      T = BuildReferenceType(T, 
-                             DeclType.Ref.HasRestrict? QualType::Restrict : 0,
+      T = BuildReferenceType(T, DeclType.Ref.LValueRef,
+                             DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
                              DeclType.Loc, Name);
       break;
     case DeclaratorChunk::Array: {