From: Douglas Gregor Date: Thu, 19 Mar 2009 04:25:59 +0000 (+0000) Subject: Print the context of tag types as part of pretty-printing, e.g., X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=24c46b3133b03e254877a680f92f035e56058a39;p=clang Print the context of tag types as part of pretty-printing, e.g., struct N::M::foo git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67284 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 1296c2fda9..d4d22060c8 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -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, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1fb1e999bd..77d006e644 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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(DC)) { + if (NS->getIdentifier()) + MyPart = NS->getNameAsString(); + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(DC)) { + std::string TemplateArgs + = ClassTemplateSpecializationType::PrintTemplateArgumentList( + Spec->getTemplateArgs(), + Spec->getNumTemplateArgs()); + MyPart = Spec->getIdentifier()->getName() + TemplateArgs; + } else if (TagDecl *Tag = dyn_cast(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; } diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp index b9ba508789..fe4e210814 100644 --- a/test/SemaCXX/elaborated-type-specifier.cpp +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -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 { diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp index c7748c31ba..156dfd6208 100644 --- a/test/SemaCXX/enum.cpp +++ b/test/SemaCXX/enum.cpp @@ -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}} diff --git a/test/SemaCXX/qualified-names-diag.cpp b/test/SemaCXX/qualified-names-diag.cpp index c3bd47f9e5..cb82f3189c 100644 --- a/test/SemaCXX/qualified-names-diag.cpp +++ b/test/SemaCXX/qualified-names-diag.cpp @@ -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; diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp index 5499c50a94..e77555f2f9 100644 --- a/test/SemaTemplate/class-template-id-2.cpp +++ b/test/SemaTemplate/class-template-id-2.cpp @@ -4,7 +4,7 @@ namespace N { template<> class A { }; - template<> class A; // expected-note{{forward declaration of 'class A'}} + template<> class A; // expected-note{{forward declaration of 'class N::A'}} class B : public A { }; } diff --git a/test/SemaTemplate/qualified-names-diag.cpp b/test/SemaTemplate/qualified-names-diag.cpp index 02bdf16b2b..74e61bbb27 100644 --- a/test/SemaTemplate/qualified-names-diag.cpp +++ b/test/SemaTemplate/qualified-names-diag.cpp @@ -12,5 +12,5 @@ void test() { std::vector v1; vector v2; - v1 = v2; // expected-error{{incompatible type assigning 'vector' (aka 'class vector'), expected 'std::vector' (aka 'class vector')}} + v1 = v2; // expected-error{{incompatible type assigning 'vector' (aka 'class std::vector'), expected 'std::vector' (aka 'class std::vector')}} }