]> granicus.if.org Git - clang/commitdiff
Print the context of tag types as part of pretty-printing, e.g.,
authorDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 04:25:59 +0000 (04:25 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 04:25:59 +0000 (04:25 +0000)
  struct N::M::foo

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67284 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
lib/AST/Type.cpp
test/SemaCXX/elaborated-type-specifier.cpp
test/SemaCXX/enum.cpp
test/SemaCXX/qualified-names-diag.cpp
test/SemaTemplate/class-template-id-2.cpp
test/SemaTemplate/qualified-names-diag.cpp

index 1296c2fda9e7e0faf4808a908b0fa172f72d025a..d4d22060c83cf13b529b28db33158e2285e4c586 100644 (file)
@@ -860,6 +860,7 @@ class TypeDecl : public NamedDecl {
   friend class TagDecl;
   friend class TemplateTypeParmDecl;
   friend class ClassTemplateSpecializationDecl;
+  friend class TagType;
 
 protected:
   TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,
index 1fb1e999bd543cedff24c666eabf52be75cf8370..77d006e644980ffd027ac1df277a3bf847f27149 100644 (file)
@@ -1526,8 +1526,35 @@ void TagType::getAsStringInternal(std::string &InnerString,
     InnerString = TemplateArgs + InnerString;
   }
 
-  if (Kind)
-    InnerString = std::string(Kind) + " " + ID + InnerString;
-  else
+  if (Kind) {
+    // Compute the full nested-name-specifier for this type. In C,
+    // this will always be empty.
+    std::string ContextStr;
+    for (DeclContext *DC = getDecl()->getDeclContext(); 
+         !DC->isTranslationUnit(); DC = DC->getParent()) {
+      std::string MyPart;
+      if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
+        if (NS->getIdentifier())
+          MyPart = NS->getNameAsString();
+      } else if (ClassTemplateSpecializationDecl *Spec 
+                   = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+        std::string TemplateArgs 
+          = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+                                                  Spec->getTemplateArgs(),
+                                                  Spec->getNumTemplateArgs());
+        MyPart = Spec->getIdentifier()->getName() + TemplateArgs;
+      } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
+        if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())
+          MyPart = Typedef->getIdentifier()->getName();
+        else if (Tag->getIdentifier())
+          MyPart = Tag->getIdentifier()->getName();
+      }
+
+      if (!MyPart.empty())
+        ContextStr = MyPart + "::" + ContextStr;
+    }
+
+    InnerString = std::string(Kind) + " " + ContextStr + ID + InnerString;
+  } else
     InnerString = ID + InnerString;
 }
index b9ba5087896e0337f53e96d0ef912f1e27f8450f..fe4e210814c72c88f7db0eceec2b4649af6ae7bb 100644 (file)
@@ -27,7 +27,7 @@ namespace NS {
 
 void test_X_elab(NS::X x) {
   struct S4 *s4 = 0;
-  x.test_elab2(s4); // expected-error{{incompatible type passing 'struct S4 *', expected 'struct S4 *'}}
+  x.test_elab2(s4); // expected-error{{incompatible type passing 'struct S4 *', expected 'struct NS::S4 *'}}
 }
 
 namespace NS {
index c7748c31ba0cf92290ebb0789535da870119a7b2..156dfd62088462068ad8f224a4d8597547e689f3 100644 (file)
@@ -32,9 +32,7 @@ struct s1 {
 enum e1 { YES, NO };
 
 static enum e1 badfunc(struct s1 *q) {
-  // FIXME: the message below should probably give context information
-  // in those types.
-  return q->bar(); // expected-error{{incompatible type returning 'enum e1', expected 'enum e1'}}
+  return q->bar(); // expected-error{{incompatible type returning 'enum s1::e1', expected 'enum e1'}}
 }
 
 enum e2; // expected-error{{ISO C++ forbids forward references to 'enum' types}}
index c3bd47f9e5c2ce4fe308d91abfcee018fce3970b..cb82f3189c7749b2e576dc8a1cfe42a3bed5d14b 100644 (file)
@@ -16,17 +16,17 @@ namespace foo {
 namespace bar {
   typedef int y;
 
-  struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}}
+  struct incomplete; // expected-note{{forward declaration of 'struct bar::incomplete'}}
 }
 void test() {
   foo::wibble::x a;
   ::bar::y b;
-  a + b; // expected-error{{invalid operands to binary expression ('foo::wibble::x' (aka 'struct x') and '::bar::y' (aka 'int'))}}
+  a + b; // expected-error{{invalid operands to binary expression ('foo::wibble::x' (aka 'struct foo::wibble::x') and '::bar::y' (aka 'int'))}}
 
   ::foo::wibble::bar::wonka::x::y c;
-  c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' (aka 'struct y') and '::bar::y' (aka 'int'))}}
+  c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' (aka 'struct foo::wibble::bar::wonka::x::y') and '::bar::y' (aka 'int'))}}
 
-  (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete' (aka 'struct incomplete')}}
+  (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete' (aka 'struct bar::incomplete')}}
 }
 
 int ::foo::wibble::bar::wonka::x::y::* ptrmem;
index 5499c50a949f930b5762542442fba396b0e52c71..e77555f2f976355a34839f978083949f3680a78c 100644 (file)
@@ -4,7 +4,7 @@ namespace N {
 
   template<> class A<int> { };
 
-  template<> class A<float>; // expected-note{{forward declaration of 'class A<float>'}}
+  template<> class A<float>; // expected-note{{forward declaration of 'class N::A<float>'}}
 
   class B : public A<int> { };
 }
index 02bdf16b2ba4b46d99dedb347c51ba565e145466..74e61bbb2749f9f227354f8473fab411a60ea544 100644 (file)
@@ -12,5 +12,5 @@ void test() {
 
   std::vector<INT> v1;
   vector<Real> v2;
-  v1 = v2; // expected-error{{incompatible type assigning 'vector<Real>' (aka 'class vector<float>'), expected 'std::vector<INT>' (aka 'class vector<int>')}}
+  v1 = v2; // expected-error{{incompatible type assigning 'vector<Real>' (aka 'class std::vector<float>'), expected 'std::vector<INT>' (aka 'class std::vector<int>')}}
 }