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@-1 {{'int &' vs 'int (int &)'}} + // expected-error@-2 {{'int &' vs 'int (int &&)'}} + // expected-error@-3 {{'const int &' vs 'int (const int &)'}} + // expected-error@-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@-1 {{'int &' vs 'int (int &)'}} + // expected-error@-2 {{'int &&' vs 'int (int &&)'}} + // expected-error@-3 {{'const int &' vs 'int (const int &)'}} + // expected-error@-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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits