]> granicus.if.org Git - clang/commitdiff
When printing a qualified type, look through a substituted template
authorDouglas Gregor <dgregor@apple.com>
Thu, 17 Feb 2011 06:52:25 +0000 (06:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 17 Feb 2011 06:52:25 +0000 (06:52 +0000)
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
test/CXX/temp/temp.decls/temp.mem/p5.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp
test/Index/complete-exprs.cpp
test/SemaCXX/type-formatting.cpp [new file with mode: 0644]
test/SemaTemplate/deduction.cpp
test/SemaTemplate/instantiate-static-var.cpp

index c0ce1f25bf578489e9d77fcd270241407000842a..5e6046acdc578313b6cbbcc3aa8bc2fdadd03591 100644 (file)
@@ -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<BuiltinType>(T) || isa<TypedefType>(T) || isa<TagType>(T) || 
-    isa<ComplexType>(T) || isa<TemplateSpecializationType>(T) ||
-    isa<ObjCObjectType>(T) || isa<ObjCInterfaceType>(T) ||
-    T->isObjCIdType() || T->isObjCQualifiedIdType();
+  bool CanPrefixQualifiers = false;
+  
+  Type::TypeClass TC = T->getTypeClass();
+  if (const SubstTemplateTypeParmType *Subst
+                                      = dyn_cast<SubstTemplateTypeParmType>(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;
index 7adc6f06da375b6d8ddd9a3cd88e0eaeff3cf103..a188f05d535e3dc2a5aebcf93aa9c2c7391ee1ad 100644 (file)
@@ -63,7 +63,7 @@ struct X0 {
   
   template<typename T> 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'}}
   }
 };
 
index 05d9b328a36339c276c4d0db024c7c9df6df7e2a..f18a74a1e4ef21d9254e277c7e779372a5b0a149 100644 (file)
@@ -23,8 +23,8 @@ void test_f0() {
   X<Y&> xy2 = f0(lvalue<Y>());
 }
 
-template<typename T> X<T> 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<typename T> X<T> 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<int> xi0 = f1(prvalue<int>());
@@ -37,7 +37,7 @@ void test_f1() {
 
 namespace std_example {
   template <class T> int f(T&&); 
-  template <class T> 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 <class T> 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);
index 016254e763dbb1f9071eebc3fbbfcb1b565985d0..a8100653b2aaa3e43021799e0c21c5afe45e2fbd 100644 (file)
@@ -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 (file)
index 0000000..3fe9278
--- /dev/null
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct X0 { };
+struct X1 { };
+
+template<typename T>
+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<X1>(); // expected-note{{instantiation of}}
index cf98d6e0ac473a3ce1e89c89f6027eb8aed0e1be..15c061c26198fdd0d6634ecef3701f7f54a161bd 100644 (file)
@@ -107,7 +107,7 @@ namespace PR7463 {
 }
 
 namespace test0 {
-  template <class T> 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 <class T> 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'}}
index cd25ccb3d3111425115e7dbe3daf8bbea151c0f0..0c06075248345cad3b29983398b72936ef9a061f 100644 (file)
@@ -11,7 +11,7 @@ X<int, 0> xi0; // expected-note{{in instantiation of template class 'X<int, 0>'
 
 template<typename T>
 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<float> fy; // expected-note{{in instantiation of template class 'Y<float>' requested here}}