From 3c594beb0faf0bd43b1b4d2c5757747729234b5a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 17 Feb 2011 06:52:25 +0000 Subject: [PATCH] When printing a qualified type, look through a substituted template parameter type to see what's behind it, so that we don't end up printing silly things like "float const *" when "const float *" would make more sense. Also, replace the pile of "isa" tests with a simple switch enumerating all of the cases, making a few more obvious cases use prefix qualifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125729 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/TypePrinter.cpp | 60 ++++++++++++++++++++-- test/CXX/temp/temp.decls/temp.mem/p5.cpp | 2 +- .../temp.deduct/temp.deduct.call/p3-0x.cpp | 6 +-- test/Index/complete-exprs.cpp | 4 +- test/SemaCXX/type-formatting.cpp | 10 ++++ test/SemaTemplate/deduction.cpp | 2 +- test/SemaTemplate/instantiate-static-var.cpp | 2 +- 7 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 test/SemaCXX/type-formatting.cpp diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index c0ce1f25b..5e6046acd 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -77,11 +77,61 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { // the type is complex. For example if the type is "int*", we *must* print // "int * const", printing "const int *" is different. Only do this when the // type expands to a simple string. - bool CanPrefixQualifiers = - isa(T) || isa(T) || isa(T) || - isa(T) || isa(T) || - isa(T) || isa(T) || - T->isObjCIdType() || T->isObjCQualifiedIdType(); + bool CanPrefixQualifiers = false; + + Type::TypeClass TC = T->getTypeClass(); + if (const SubstTemplateTypeParmType *Subst + = dyn_cast(T)) + TC = Subst->getReplacementType()->getTypeClass(); + + switch (TC) { + case Type::Builtin: + case Type::Complex: + case Type::UnresolvedUsing: + case Type::Typedef: + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::Decltype: + case Type::Record: + case Type::Enum: + case Type::Elaborated: + case Type::TemplateTypeParm: + case Type::SubstTemplateTypeParmPack: + case Type::TemplateSpecialization: + case Type::InjectedClassName: + case Type::DependentName: + case Type::DependentTemplateSpecialization: + case Type::ObjCObject: + case Type::ObjCInterface: + CanPrefixQualifiers = true; + break; + + case Type::ObjCObjectPointer: + CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() || + T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType(); + break; + + case Type::Pointer: + case Type::BlockPointer: + case Type::LValueReference: + case Type::RValueReference: + case Type::MemberPointer: + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + case Type::FunctionProto: + case Type::FunctionNoProto: + case Type::Paren: + case Type::Attributed: + case Type::PackExpansion: + case Type::SubstTemplateTypeParm: + CanPrefixQualifiers = false; + break; + } if (!CanPrefixQualifiers && !Quals.empty()) { std::string qualsBuffer; diff --git a/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/test/CXX/temp/temp.decls/temp.mem/p5.cpp index 7adc6f06d..a188f05d5 100644 --- a/test/CXX/temp/temp.decls/temp.mem/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.mem/p5.cpp @@ -63,7 +63,7 @@ struct X0 { template operator const T*() const { T x = T(); - return x; // expected-error{{cannot initialize return object of type 'char const *' with an lvalue of type 'char'}} + return x; // expected-error{{cannot initialize return object of type 'const char *' with an lvalue of type 'char'}} } }; diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp index 05d9b328a..f18a74a1e 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -23,8 +23,8 @@ void test_f0() { X xy2 = f0(lvalue()); } -template X f1(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'int const &&' for 1st argument}} \ -// expected-note{{candidate function [with T = Y] not viable: no known conversion from 'Y' to 'Y const &&' for 1st argument}} +template X f1(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} \ +// expected-note{{candidate function [with T = Y] not viable: no known conversion from 'Y' to 'const Y &&' for 1st argument}} void test_f1() { X xi0 = f1(prvalue()); @@ -37,7 +37,7 @@ void test_f1() { namespace std_example { template int f(T&&); - template int g(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'int const &&' for 1st argument}} + template int g(const T&&); // expected-note{{candidate function [with T = int] not viable: no known conversion from 'int' to 'const int &&' for 1st argument}} int i; int n1 = f(i); diff --git a/test/Index/complete-exprs.cpp b/test/Index/complete-exprs.cpp index 016254e76..a8100653b 100644 --- a/test/Index/complete-exprs.cpp +++ b/test/Index/complete-exprs.cpp @@ -35,7 +35,7 @@ void g() { // CHECK-CC1: CXXConstructor:{TypedText string}{LeftParen (}{Placeholder const char *}{RightParen )} (50) // CHECK-CC1: CXXConstructor:{TypedText string}{LeftParen (}{Placeholder const char *}{Comma , }{Placeholder int n}{RightParen )} (50) // CHECK-CC1: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50) -// CHECK-CC1: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder T const &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50) +// CHECK-CC1: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder const T &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50) // CHECK-CC1: FunctionTemplate:{ResultType void}{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50) // RUN: c-index-test -code-completion-at=%s:19:1 %s | FileCheck -check-prefix=CHECK-CC2 %s @@ -49,5 +49,5 @@ void g() { // CHECK-CC3: FunctionDecl:{ResultType int}{TypedText foo}{LeftParen (}{RightParen )} (50) // CHECK-CC3: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{RightParen )} (50) // CHECK-CC3: ClassTemplate:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >} (50) -// CHECK-CC3: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder T const &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50) +// CHECK-CC3: CXXConstructor:{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder const T &}{Comma , }{Placeholder unsigned int n}{RightParen )} (50) // CHECK-CC3: FunctionTemplate:{ResultType void}{TypedText vector}{LeftAngle <}{Placeholder typename T}{RightAngle >}{LeftParen (}{Placeholder InputIterator first}{Comma , }{Placeholder InputIterator last}{RightParen )} (50) diff --git a/test/SemaCXX/type-formatting.cpp b/test/SemaCXX/type-formatting.cpp new file mode 100644 index 000000000..3fe9278c4 --- /dev/null +++ b/test/SemaCXX/type-formatting.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct X0 { }; +struct X1 { }; + +template +void f0() { + const T *t = (const X0*)0; // expected-error{{cannot initialize a variable of type 'const X1 *' with an rvalue of type 'const X0 *'}} +} +template void f0(); // expected-note{{instantiation of}} diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index cf98d6e0a..15c061c26 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -107,7 +107,7 @@ namespace PR7463 { } namespace test0 { - template void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'T const' equal 'char'}} + template void make(const T *(*fn)()); // expected-note {{candidate template ignored: can't deduce a type for 'T' which would make 'const T' equal 'char'}} char *char_maker(); void test() { make(char_maker); // expected-error {{no matching function for call to 'make'}} diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp index cd25ccb3d..0c0607524 100644 --- a/test/SemaTemplate/instantiate-static-var.cpp +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -11,7 +11,7 @@ X xi0; // expected-note{{in instantiation of template class 'X' template class Y { - static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'float const' is a C++0x extension}} + static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'const float' is a C++0x extension}} }; Y fy; // expected-note{{in instantiation of template class 'Y' requested here}} -- 2.11.4.GIT