r331137 - Fix printing of reference-to-reference types.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sat Apr 28 22:33:38 PDT 2018


Author: rsmith
Date: Sat Apr 28 22:33:38 2018
New Revision: 331137

URL: http://llvm.org/viewvc/llvm-project?rev=331137&view=rev
Log:
Fix printing of reference-to-reference types.

Previously we would sometimes print these as 'T &&&' or even 'T &&&&'.

Modified:
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/test/SemaCXX/references.cpp

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=331137&r1=331136&r2=331137&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Sat Apr 28 22:33:38 2018
@@ -385,14 +385,23 @@ void TypePrinter::printBlockPointerAfter
   printAfter(T->getPointeeType(), OS);
 }
 
+// When printing a reference, the referenced type might also be a reference.
+// If so, we want to skip that before printing the inner type.
+static QualType skipTopLevelReferences(QualType T) {
+  if (auto *Ref = T->getAs<ReferenceType>())
+    return skipTopLevelReferences(Ref->getPointeeTypeAsWritten());
+  return T;
+}
+
 void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T,
                                              raw_ostream &OS) {
   IncludeStrongLifetimeRAII Strong(Policy);
   SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
-  printBefore(T->getPointeeTypeAsWritten(), OS);
+  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+  printBefore(Inner, OS);
   // Handle things like 'int (&A)[4];' correctly.
   // FIXME: this should include vectors, but vectors use attributes I guess.
-  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+  if (isa<ArrayType>(Inner))
     OS << '(';
   OS << '&';
 }
@@ -401,21 +410,23 @@ void TypePrinter::printLValueReferenceAf
                                             raw_ostream &OS) {
   IncludeStrongLifetimeRAII Strong(Policy);
   SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
   // Handle things like 'int (&A)[4];' correctly.
   // FIXME: this should include vectors, but vectors use attributes I guess.
-  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+  if (isa<ArrayType>(Inner))
     OS << ')';
-  printAfter(T->getPointeeTypeAsWritten(), OS);
+  printAfter(Inner, OS);
 }
 
 void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T,
                                              raw_ostream &OS) {
   IncludeStrongLifetimeRAII Strong(Policy);
   SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
-  printBefore(T->getPointeeTypeAsWritten(), OS);
+  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
+  printBefore(Inner, OS);
   // Handle things like 'int (&&A)[4];' correctly.
   // FIXME: this should include vectors, but vectors use attributes I guess.
-  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+  if (isa<ArrayType>(Inner))
     OS << '(';
   OS << "&&";
 }
@@ -424,11 +435,12 @@ void TypePrinter::printRValueReferenceAf
                                             raw_ostream &OS) {
   IncludeStrongLifetimeRAII Strong(Policy);
   SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+  QualType Inner = skipTopLevelReferences(T->getPointeeTypeAsWritten());
   // Handle things like 'int (&&A)[4];' correctly.
   // FIXME: this should include vectors, but vectors use attributes I guess.
-  if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
+  if (isa<ArrayType>(Inner))
     OS << ')';
-  printAfter(T->getPointeeTypeAsWritten(), OS);
+  printAfter(Inner, OS);
 }
 
 void TypePrinter::printMemberPointerBefore(const MemberPointerType *T, 

Modified: cfe/trunk/test/SemaCXX/references.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/references.cpp?rev=331137&r1=331136&r2=331137&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/references.cpp (original)
+++ cfe/trunk/test/SemaCXX/references.cpp Sat Apr 28 22:33:38 2018
@@ -154,3 +154,31 @@ namespace ExplicitRefInit {
   struct A { explicit A(int); };
   const A &a(0); // expected-error {{reference to type 'const ExplicitRefInit::A' could not bind to an rvalue of type 'int'}}
 }
+
+namespace RefCollapseTypePrinting {
+  template<typename T> void add_lref() {
+    using X = int(T); // expected-note 4{{previous}}
+    using X = const volatile T&;
+    // expected-error at -1 {{'int &' vs 'int (int &)'}}
+    // expected-error at -2 {{'int &' vs 'int (int &&)'}}
+    // expected-error at -3 {{'const int &' vs 'int (const int &)'}}
+    // expected-error at -4 {{'const int &' vs 'int (const int &&)'}}
+  }
+  template void add_lref<int&>(); // expected-note {{instantiation of}}
+  template void add_lref<int&&>(); // expected-note {{instantiation of}}
+  template void add_lref<const int&>(); // expected-note {{instantiation of}}
+  template void add_lref<const int&&>(); // expected-note {{instantiation of}}
+
+  template<typename T> void add_rref() {
+    using X = int(T); // expected-note 4{{previous}}
+    using X = const volatile T&&;
+    // expected-error at -1 {{'int &' vs 'int (int &)'}}
+    // expected-error at -2 {{'int &&' vs 'int (int &&)'}}
+    // expected-error at -3 {{'const int &' vs 'int (const int &)'}}
+    // expected-error at -4 {{'const int &&' vs 'int (const int &&)'}}
+  }
+  template void add_rref<int&>(); // expected-note {{instantiation of}}
+  template void add_rref<int&&>(); // expected-note {{instantiation of}}
+  template void add_rref<const int&>(); // expected-note {{instantiation of}}
+  template void add_rref<const int&&>(); // expected-note {{instantiation of}}
+}




More information about the cfe-commits mailing list