[cfe-commits] RFC: C++ References Patch

Bill Wendling isanbard at gmail.com
Tue Nov 27 02:12:51 PST 2007

Hi all,

This is a long awaited patch for the failure in cxx-references.cpp.  
The idea is that during the typesAreCompatible method, it should  
ignore any references, according to the section [expr] in the C++  
standard (quoted in the comment below). At this point, we basically  
have a "pointer to a reference" coming into this method. This is  
because of how the code is parsed -- the variable is a reference, and  
its address is taken. Note, however, that a pointer to a reference is  
invalid C++ code. I suppose that we'd ideally like to have it never  
be a pointer to a reference. That is to have the reference part of  
the type removed before the pointer type to that type is created. I'm  
not sure how much information this would lose doing that though.

Because it removes the reference, there's no longer a need to have  
the Type::Reference in the switch statement.



Index: test/Sema/cxx-references.cpp
--- test/Sema/cxx-references.cpp        (revision 44358)
+++ test/Sema/cxx-references.cpp        (working copy)
@@ -5,9 +5,7 @@
    int i;
    int &r = i;
    r = 1;
-#if 0  // FIXME: &ref not right yet
    int *p = &r;
    int &rr = r;
    int (&rg)(int) = g;
Index: AST/ASTContext.cpp
--- AST/ASTContext.cpp  (revision 44358)
+++ AST/ASTContext.cpp  (working copy)
@@ -1217,7 +1217,7 @@
    return typesAreCompatible(ltype, rtype);

-// C++ 5.17p6: When the left opperand of an assignment operator  
denotes a
+// C++ 5.17p6: When the left operand of an assignment operator  
denotes a
  // reference to T, the operation assigns to the object of type T  
denoted by the
  // reference.
  bool ASTContext::referenceTypesAreCompatible(QualType lhs, QualType  
rhs) {
@@ -1299,6 +1299,15 @@
    // If two types are identical, they are are compatible
    if (lcanon == rcanon)
      return true;
+  // C++ [expr]: If an expression initially has the type "reference  
to T", the
+  // type is adjusted to "T" prior to any further analysis, the  
+  // designates the object or function denoted by the reference, and  
+  // expression is an lvalue.
+  if (lcanon->getTypeClass() == Type::Reference)
+    lcanon = cast<ReferenceType>(lcanon)->getReferenceeType();
+  if (rcanon->getTypeClass() == Type::Reference)
+    rcanon = cast<ReferenceType>(rcanon)->getReferenceeType();

    // If the canonical type classes don't match, they can't be  
    if (lcanon->getTypeClass() != rcanon->getTypeClass()) {
@@ -1312,8 +1321,6 @@
    switch (lcanon->getTypeClass()) {
      case Type::Pointer:
        return pointerTypesAreCompatible(lcanon, rcanon);
-    case Type::Reference:
-      return referenceTypesAreCompatible(lcanon, rcanon);
      case Type::ConstantArray:
      case Type::VariableArray:
        return arrayTypesAreCompatible(lcanon, rcanon);

More information about the cfe-commits mailing list