From: Bill Wendling Date: Mon, 3 Dec 2007 07:33:35 +0000 (+0000) Subject: Fix for testcase that assigns a dereferenced reference to a pointer. The X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=43d69750e7f7b26076e7474dec8839bb777b260f;p=clang Fix for testcase that assigns a dereferenced reference to a pointer. The standard says that we should adjust the "reference to T" type to "T" before analysis. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44530 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp index 899dfdecb6..3f5a7fbc58 100644 --- a/AST/ASTContext.cpp +++ b/AST/ASTContext.cpp @@ -1217,7 +1217,7 @@ bool ASTContext::pointerTypesAreCompatible(QualType lhs, QualType rhs) { 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 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) { // 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 expression + // designates the object or function denoted by the reference, and the + // expression is an lvalue. + if (lcanon->getTypeClass() == Type::Reference) + lcanon = cast(lcanon)->getReferenceeType(); + if (rcanon->getTypeClass() == Type::Reference) + rcanon = cast(rcanon)->getReferenceeType(); // If the canonical type classes don't match, they can't be compatible if (lcanon->getTypeClass() != rcanon->getTypeClass()) { @@ -1312,8 +1321,6 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) { 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); diff --git a/test/Sema/cxx-references.cpp b/test/Sema/cxx-references.cpp index a1c3eb5518..3637573b44 100644 --- a/test/Sema/cxx-references.cpp +++ b/test/Sema/cxx-references.cpp @@ -5,9 +5,7 @@ void f() { int i; int &r = i; r = 1; -#if 0 // FIXME: &ref not right yet int *p = &r; -#endif int &rr = r; int (&rg)(int) = g; rg(i);