Initial step toward supporting qualification conversions (C++ 4.4).

Changes:
  - Sema::IsQualificationConversion determines whether we have a qualification
    conversion.
  - Sema::CheckSingleAssignment constraints now follows the C++ rules in C++,
    performing an implicit conversion from the right-hand side to the type of
    the left-hand side rather than checking based on the C notion of 
    "compatibility". We now rely on the implicit-conversion code to
    determine whether the conversion can happen or
    not. Sema::TryCopyInitialization has an ugly reference-related
    hack to cope with the initialization of references, for now.
  - When building DeclRefExprs, strip away the reference type, since
    there are no expressions whose type is a reference. We'll need to
    do this throughout Sema.
  - Expr::isLvalue now permits functions to be lvalues in C++ (but not
  in C).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57935 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 88c209b..2696c98 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -318,6 +318,32 @@
   ICS.Standard.Deprecated = false;
   ICS.Standard.FromTypePtr = FromType.getAsOpaquePtr();
 
+  if (const ReferenceType *ToTypeRef = ToType->getAsReferenceType()) {
+    // FIXME: This is a hack to deal with the initialization of
+    // references the way that the C-centric code elsewhere deals with
+    // references, by only allowing them if the referred-to type is
+    // exactly the same. This means that we're only handling the
+    // direct-binding case. The code will be replaced by an
+    // implementation of C++ 13.3.3.1.4 once we have the
+    // initialization of references implemented.
+    QualType ToPointee = Context.getCanonicalType(ToTypeRef->getPointeeType());
+
+    // Get down to the canonical type that we're converting from.
+    if (const ReferenceType *FromTypeRef = FromType->getAsReferenceType())
+      FromType = FromTypeRef->getPointeeType();
+    FromType = Context.getCanonicalType(FromType);
+
+    ICS.Standard.First = ICK_Identity;
+    ICS.Standard.Second = ICK_Identity;
+    ICS.Standard.Third = ICK_Identity;
+    ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr();
+
+    if (FromType != ToPointee)
+      ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+
+    return ICS;
+  }
+
   // The first conversion can be an lvalue-to-rvalue conversion,
   // array-to-pointer conversion, or function-to-pointer conversion
   // (C++ 4p1).
@@ -432,10 +458,7 @@
   }
 
   // The third conversion can be a qualification conversion (C++ 4p1).
-  // FIXME: CheckPointerTypesForAssignment isn't the right way to
-  // determine whether we have a qualification conversion.
-  if (Context.getCanonicalType(FromType) != Context.getCanonicalType(ToType)
-      && CheckPointerTypesForAssignment(ToType, FromType) == Compatible) {
+  if (IsQualificationConversion(FromType, ToType)) {
     ICS.Standard.Third = ICK_Qualification;
     FromType = ToType;
   } else {
@@ -618,6 +641,74 @@
   return false;
 }
 
+/// IsQualificationConversion - Determines whether the conversion from
+/// an rvalue of type FromType to ToType is a qualification conversion
+/// (C++ 4.4).
+bool 
+Sema::IsQualificationConversion(QualType FromType, QualType ToType)
+{
+  FromType = Context.getCanonicalType(FromType);
+  ToType = Context.getCanonicalType(ToType);
+
+  // If FromType and ToType are the same type, this is not a
+  // qualification conversion.
+  if (FromType == ToType)
+    return false;
+    
+  // (C++ 4.4p4):
+  //   A conversion can add cv-qualifiers at levels other than the first
+  //   in multi-level pointers, subject to the following rules: [...]
+  bool PreviousToQualsIncludeConst = true;
+  bool UnwrappedPointer;
+  bool UnwrappedAnyPointer = false;
+  do {
+    // Within each iteration of the loop, we check the qualifiers to
+    // determine if this still looks like a qualification
+    // conversion. Then, if all is well, we unwrap one more level of
+    // pointers (FIXME: or pointers-to-members) and do it all again
+    // until there are no more pointers or pointers-to-members left to
+    // unwrap.
+    UnwrappedPointer = false;
+
+    //   -- the pointer types are similar.
+    const PointerType *FromPtrType = FromType->getAsPointerType(),
+                      *ToPtrType   = ToType->getAsPointerType();
+    if (FromPtrType && ToPtrType) {
+      // The pointer types appear similar. Look at their pointee types.
+      FromType = FromPtrType->getPointeeType();
+      ToType = ToPtrType->getPointeeType();
+      UnwrappedPointer = true;
+      UnwrappedAnyPointer = true;
+    } 
+
+    // FIXME: Cope with pointer-to-member types.
+
+    //   -- for every j > 0, if const is in cv 1,j then const is in cv
+    //      2,j, and similarly for volatile.
+    if (FromType.isMoreQualifiedThan(ToType))
+      return false;
+
+    //   -- if the cv 1,j and cv 2,j are different, then const is in
+    //      every cv for 0 < k < j.
+    if (FromType.getCVRQualifiers() != ToType.getCVRQualifiers()
+	&& !PreviousToQualsIncludeConst)
+      return false;
+
+    // Keep track of whether all prior cv-qualifiers in the "to" type
+    // include const.
+    PreviousToQualsIncludeConst 
+      = PreviousToQualsIncludeConst && ToType.isConstQualified();
+  } while (UnwrappedPointer);
+
+  // We are left with FromType and ToType being the pointee types
+  // after unwrapping the original FromType and ToType the same number
+  // of types. If we unwrapped any pointers, and if FromType and
+  // ToType have the same unqualified type (since we checked
+  // qualifiers above), then this is a qualification conversion.
+  return UnwrappedAnyPointer &&
+    FromType.getUnqualifiedType() == ToType.getUnqualifiedType();
+}
+
 /// CompareImplicitConversionSequences - Compare two implicit
 /// conversion sequences to determine whether one is better than the
 /// other or if they are indistinguishable (C++ 13.3.3.2).