Rvalue references for *this: 

  - Add ref-qualifiers to the type system; they are part of the
  canonical type. Print & profile ref-qualifiers
  - Translate the ref-qualifier from the Declarator chunk for
    functions to the function type. 
  - Diagnose mis-uses of ref-qualifiers w.r.t. static member
  functions, free functions, constructors, destructors, etc.
  - Add serialization and deserialization of ref-qualifiers.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124281 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d5dea78..78d9a5b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3023,6 +3023,15 @@
     D.setInvalidType();
   }
 
+  // C++0x [class.ctor]p4:
+  //   A constructor shall not be declared with a ref-qualifier.
+  if (FTI.hasRefQualifier()) {
+    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
+      << FTI.RefQualifierIsLValueRef 
+      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+    D.setInvalidType();
+  }
+  
   // Rebuild the function type "R" without any type qualifiers (in
   // case any of the errors above fired) and with "void" as the
   // return type, since constructors don't have return types.
@@ -3032,7 +3041,8 @@
 
   FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
   EPI.TypeQuals = 0;
-
+  EPI.RefQualifier = RQ_None;
+  
   return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(),
                                  Proto->getNumArgs(), EPI);
 }
@@ -3173,6 +3183,15 @@
     D.setInvalidType();
   }
 
+  // C++0x [class.dtor]p2:
+  //   A destructor shall not be declared with a ref-qualifier.
+  if (FTI.hasRefQualifier()) {
+    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
+      << FTI.RefQualifierIsLValueRef
+      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
+    D.setInvalidType();
+  }
+  
   // Make sure we don't have any parameters.
   if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) {
     Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
@@ -3199,6 +3218,7 @@
   FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
   EPI.Variadic = false;
   EPI.TypeQuals = 0;
+  EPI.RefQualifier = RQ_None;
   return Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
 }
 
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 00d92bc..70e9973 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2106,6 +2106,7 @@
                                       ParamTypes.data(), ParamTypes.size(),
                                       Proto->isVariadic(),
                                       Proto->getTypeQuals(),
+                                      Proto->getRefQualifier(),
                                       Function->getLocation(),
                                       Function->getDeclName(),
                                       Proto->getExtInfo());
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index b663f58..64d5c42 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1269,6 +1269,7 @@
                                  QualType *ParamTypes,
                                  unsigned NumParamTypes,
                                  bool Variadic, unsigned Quals,
+                                 RefQualifierKind RefQualifier,
                                  SourceLocation Loc, DeclarationName Entity,
                                  FunctionType::ExtInfo Info) {
   if (T->isArrayType() || T->isFunctionType()) {
@@ -1294,6 +1295,7 @@
   FunctionProtoType::ExtProtoInfo EPI;
   EPI.Variadic = Variadic;
   EPI.TypeQuals = Quals;
+  EPI.RefQualifier = RefQualifier;
   EPI.ExtInfo = Info;
 
   return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
@@ -1722,7 +1724,10 @@
         FunctionProtoType::ExtProtoInfo EPI;
         EPI.Variadic = FTI.isVariadic;
         EPI.TypeQuals = FTI.TypeQuals;
-
+        EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
+                    : FTI.RefQualifierIsLValueRef? RQ_LValue
+                    : RQ_RValue;
+        
         // Otherwise, we have a function with an argument list that is
         // potentially variadic.
         llvm::SmallVector<QualType, 16> ArgTys;
@@ -1876,21 +1881,44 @@
       FreeFunction = (DC && !DC->isRecord());
     }
 
-    if (FnTy->getTypeQuals() != 0 &&
+    // C++0x [dcl.fct]p6:
+    //   A ref-qualifier shall only be part of the function type for a
+    //   non-static member function, the function type to which a pointer to
+    //   member refers, or the top-level function type of a function typedef 
+    //   declaration.
+    if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) &&
         D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
         (FreeFunction ||
          D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
-      if (D.isFunctionDeclarator())
-        Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
-      else
-        Diag(D.getIdentifierLoc(),
-             diag::err_invalid_qualified_typedef_function_type_use)
-          << FreeFunction;
-
-      // Strip the cv-quals from the type.
+      if (FnTy->getTypeQuals() != 0) {
+        if (D.isFunctionDeclarator())
+          Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
+        else
+          Diag(D.getIdentifierLoc(),
+               diag::err_invalid_qualified_typedef_function_type_use)
+            << FreeFunction;
+      }
+          
+      if (FnTy->getRefQualifier()) {
+        if (D.isFunctionDeclarator()) {
+          SourceLocation Loc
+            = D.getTypeObject(D.getNumTypeObjects()-1).Fun.getRefQualifierLoc();
+          Diag(Loc, diag::err_invalid_ref_qualifier_function_type)
+            << (FnTy->getRefQualifier() == RQ_LValue)
+            << FixItHint::CreateRemoval(Loc);
+        } else {
+          Diag(D.getIdentifierLoc(), 
+               diag::err_invalid_ref_qualifier_typedef_function_type_use)
+            << FreeFunction
+            << (FnTy->getRefQualifier() == RQ_LValue);
+        }
+      }
+          
+      // Strip the cv-quals and ref-qualifier from the type.
       FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
       EPI.TypeQuals = 0;
-
+      EPI.RefQualifier = RQ_None;
+          
       T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(),
                                   FnTy->getNumArgs(), EPI);
     }
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 04c45b8..3f8d3e5 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -633,6 +633,7 @@
                                     QualType *ParamTypes,
                                     unsigned NumParamTypes,
                                     bool Variadic, unsigned Quals,
+                                    RefQualifierKind RefQualifier,
                                     const FunctionType::ExtInfo &Info);
 
   /// \brief Build a new unprototyped function type.
@@ -3796,6 +3797,7 @@
                                                    ParamTypes.size(),
                                                    T->isVariadic(),
                                                    T->getTypeQuals(),
+                                                   T->getRefQualifier(),
                                                    T->getExtInfo());
     if (Result.isNull())
       return QualType();
@@ -7178,7 +7180,7 @@
                                                         ParamTypes.data(),
                                                         ParamTypes.size(),
                                                         BD->isVariadic(),
-                                                        0,
+                                                        0, RQ_None,
                                                BExprFunctionType->getExtInfo());
   CurBlock->FunctionType = FunctionType;
 
@@ -7373,9 +7375,10 @@
                                                         unsigned NumParamTypes,
                                                           bool Variadic,
                                                           unsigned Quals,
+                                                  RefQualifierKind RefQualifier,
                                             const FunctionType::ExtInfo &Info) {
   return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic,
-                                   Quals,
+                                   Quals, RefQualifier,
                                    getDerived().getBaseLocation(),
                                    getDerived().getBaseEntity(),
                                    Info);