[cfe-dev] clang and gcc implement __PRETTY_FUNCTION__ differently

Douglas Gregor dgregor at apple.com
Thu Mar 15 12:43:02 PDT 2012


On Mar 15, 2012, at 3:46 AM, Nikola Smiljanic wrote:

> That did the trick, but I don't understand why, what is the difference
> between getTemplatedDecl (underlying template declaration) and
> getInstantiatedFromMemberTemplate (previous declaration of this
> template). And then there is also getPreviousDecl (previous
> declaration of this function template). Doxygen comments aren't very
> revealing here, and I'm sure that knowing the terminology from the
> standard would help, but can somebody please explain.
> 
> Anyway this is the new patch. Two things to note here:

Much improved!

> 1. Since I don't really understand this special case I'm not sure if
> my logic for handling it is OK (the tests that I have all pass). I'm
> talking about the part inside (TK ==
> TK_FunctionTemplateSpecialization) branch.

+    if (TK == FunctionDecl::TK_FunctionTemplateSpecialization) {
+      FunctionTemplateDecl *Primary = FD->getPrimaryTemplate();
+      FunctionTemplateDecl *TemplatedDecl 
+                                 = Primary->getInstantiatedFromMemberTemplate();
+      Decl = TemplatedDecl ? TemplatedDecl->getTemplatedDecl() 
+                           : Primary->getTemplatedDecl();
+    }
+    else if (TK == FunctionDecl::TK_MemberSpecialization)
+      Decl = FD->getInstantiatedFromMemberFunction();
+

As John noted, if you want to get back to the original source, you'll need to make this a loop. Plus, you'll probably want to check if it was an explicit specialization and stop iterating at that point, since explicit specializations were written by the user (rather than instantiated).

+    typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
+    SpecsTy Specs;
+    const DeclContext *Ctx = FD->getDeclContext();
+    while (Ctx && isa<NamedDecl>(Ctx)) {
+      if (const ClassTemplateSpecializationDecl *Spec
+            = dyn_cast<ClassTemplateSpecializationDecl>(Ctx))
+        Specs.push_back(Spec);
+      Ctx = Ctx->getParent();
+    }

There are a few cases here, too. For example, you could have a CXXRecordDecl that's an instantiation of a member class, e.g.,

template<typename T>
struct X {
	struct Inner {
		void f();
	};
};

and you don't want to skip "Inner" in the printing.

> 2. I added the test for compound types and I noticed that pointer
> return type is printed like "T *func". I know that we prefer printing
> the asterisk like this when it comes to variables, but is this OK for
> function return type?

Yes.

	- Doug



More information about the cfe-dev mailing list