[cfe-dev] clang and gcc implement __PRETTY_FUNCTION__ differently
Nikola Smiljanic
popizdeh at gmail.com
Sun Apr 1 06:00:21 PDT 2012
This should be it. Additional tests for explicit specializations (both
function and class template) in which case specialized template
parameters are not mentioned. I'm still interested in adding a test
case where getInstantiatedFromMemberTemplate needs to be called more
than once, I just couldn't figure this one out.
-------------- next part --------------
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp (revision 153829)
+++ lib/AST/Expr.cpp (working copy)
@@ -399,21 +399,22 @@
}
PrintingPolicy Policy(Context.getLangOpts());
-
std::string Proto = FD->getQualifiedNameAsString(Policy);
+ llvm::raw_string_ostream POut(Proto);
- const FunctionType *AFT = FD->getType()->getAs<FunctionType>();
+ const FunctionDecl *Decl = FD->getTemplateInstantiationPattern();
+ if (Decl == 0) Decl = FD;
+ const FunctionType *AFT = Decl->getType()->getAs<FunctionType>();
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(AFT);
- Proto += "(";
+ POut << "(";
if (FT) {
- llvm::raw_string_ostream POut(Proto);
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+ for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) {
if (i) POut << ", ";
std::string Param;
- FD->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
+ Decl->getParamDecl(i)->getType().getAsStringInternal(Param, Policy);
POut << Param;
}
@@ -422,16 +423,65 @@
POut << "...";
}
}
- Proto += ")";
+ POut << ")";
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
if (ThisQuals.hasConst())
- Proto += " const";
+ POut << " const";
if (ThisQuals.hasVolatile())
- Proto += " volatile";
+ POut << " volatile";
}
+ typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
+ SpecsTy Specs;
+ const DeclContext *Ctx = FD->getDeclContext();
+ while (Ctx && isa<NamedDecl>(Ctx)) {
+ const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
+ if (Spec && !Spec->isExplicitSpecialization())
+ Specs.push_back(Spec);
+ Ctx = Ctx->getParent();
+ }
+
+ std::string TemplateParams;
+ llvm::raw_string_ostream TOut(TemplateParams);
+ for (SpecsTy::reverse_iterator I = Specs.rbegin(), E = Specs.rend();
+ I != E; ++I) {
+ const TemplateParameterList *Params
+ = (*I)->getSpecializedTemplate()->getTemplateParameters();
+ const TemplateArgumentList &Args = (*I)->getTemplateArgs();
+ assert(Params->size() == Args.size());
+ for (unsigned i = 0, numParams = Params->size(); i != numParams; ++i) {
+ TOut << Params->getParam(i)->getNameAsString() << " = ";
+ Args.get(i).print(Policy, TOut);
+ TOut << ", ";
+ }
+ }
+
+ FunctionTemplateSpecializationInfo *FSI
+ = FD->getTemplateSpecializationInfo();
+ if (FSI && !FSI->isExplicitSpecialization()) {
+ const TemplateParameterList* Params
+ = FSI->getTemplate()->getTemplateParameters();
+ const TemplateArgumentList* Args = FSI->TemplateArguments;
+ assert(Params->size() == Args->size());
+ for (unsigned i = 0, e = Params->size(); i != e; ++i) {
+ TOut << Params->getParam(i)->getName() << " = ";
+ Args->get(i).print(Policy, TOut);
+ TOut << ", ";
+ }
+ }
+
+ TOut.flush();
+ if (!TemplateParams.empty()) {
+ // remove the trailing comma and space
+ TemplateParams.resize(TemplateParams.size() - 2);
+ POut << " [" << TemplateParams << "]";
+ }
+
+ POut.flush();
+
if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
AFT->getResultType().getAsStringInternal(Proto, Policy);
Index: test/CodeGenCXX/predefined-expr.cpp
===================================================================
--- test/CodeGenCXX/predefined-expr.cpp (revision 153829)
+++ test/CodeGenCXX/predefined-expr.cpp (working copy)
@@ -2,14 +2,27 @@
// CHECK: private unnamed_addr constant [15 x i8] c"externFunction\00"
// CHECK: private unnamed_addr constant [26 x i8] c"void NS::externFunction()\00"
+// CHECK: private unnamed_addr constant [49 x i8] c"void functionTemplateExplicitSpecialization(int)\00"
+// CHECK: private unnamed_addr constant [95 x i8] c"void SpecializedClassTemplate<char>::memberFunctionTemplate(T, U) const [T = char, U = double]\00"
+// CHECK: private unnamed_addr constant [85 x i8] c"void SpecializedClassTemplate<int>::memberFunctionTemplate(int, U) const [U = float]\00"
+// CHECK: private unnamed_addr constant [57 x i8] c"void NonTypeTemplateParam<42>::size() const [Count = 42]\00"
+// CHECK: private unnamed_addr constant [122 x i8] c"static void ClassWithTemplateTemplateParam<char, NS::ClassTemplate>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
+// CHECK: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00"
+
+// CHECK: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00"
+// CHECK: private unnamed_addr constant [52 x i8] c"T *functionTemplateWithCompoundTypes(T *) [T = int]\00"
+// CHECK: private unnamed_addr constant [54 x i8] c"T functionTemplateWithTemplateReturnType() [T = char]\00"
+// CHECK: private unnamed_addr constant [57 x i8] c"void functionTemplateWithoutParameterList() [T = double]\00"
+// CHECK: private unnamed_addr constant [62 x i8] c"void functionTemplateWithTwoParams(T, U) [T = int, U = float]\00"
+
// CHECK: private unnamed_addr constant [22 x i8] c"classTemplateFunction\00"
-// CHECK: private unnamed_addr constant [60 x i8] c"void NS::ClassTemplate<NS::Base *>::classTemplateFunction()\00"
-// CHECK: private unnamed_addr constant [53 x i8] c"void NS::ClassTemplate<int>::classTemplateFunction()\00"
+// CHECK: private unnamed_addr constant [77 x i8] c"void NS::ClassTemplate<NS::Base *>::classTemplateFunction() [T = NS::Base *]\00"
+// CHECK: private unnamed_addr constant [63 x i8] c"void NS::ClassTemplate<int>::classTemplateFunction() [T = int]\00"
// CHECK: private unnamed_addr constant [18 x i8] c"functionTemplate1\00"
-// CHECK: private unnamed_addr constant [45 x i8] c"void NS::Base::functionTemplate1(NS::Base *)\00"
-// CHECK: private unnamed_addr constant [38 x i8] c"void NS::Base::functionTemplate1(int)\00"
+// CHECK: private unnamed_addr constant [53 x i8] c"void NS::Base::functionTemplate1(T) [T = NS::Base *]\00"
+// CHECK: private unnamed_addr constant [46 x i8] c"void NS::Base::functionTemplate1(T) [T = int]\00"
// CHECK: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00"
// CHECK: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::<anonymous union>::anonymousUnionFunction()\00"
@@ -78,6 +91,8 @@
// CHECK: private unnamed_addr constant [19 x i8] c"localClassFunction\00"
// CHECK: private unnamed_addr constant [59 x i8] c"void NS::localClass(int)::LocalClass::localClassFunction()\00"
+
+
int printf(const char * _Format, ...);
class ClassInTopLevelNamespace {
@@ -207,7 +222,7 @@
class Derived : public Base {
public:
- // Virtual function without being explicitally written.
+ // Virtual function without being explicitly written.
void virtualFunction() {
printf("__func__ %s\n", __func__);
printf("__FUNCTION__ %s\n", __FUNCTION__);
@@ -294,6 +309,110 @@
} // end NS namespace
+// additional tests for __PRETTY_FUNCTION__
+template <typename T, typename U>
+void functionTemplateWithTwoParams(T, U)
+{
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+}
+
+template <typename T>
+void functionTemplateWithoutParameterList()
+{
+ T t = T();
+
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+}
+
+template <typename T>
+T functionTemplateWithTemplateReturnType()
+{
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+
+ return T();
+}
+
+template <typename T>
+T * functionTemplateWithCompoundTypes(T a[])
+{
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+
+ return 0;
+}
+
+template <typename T>
+void functionTemplateExplicitSpecialization(T t)
+{
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+}
+
+template <>
+void functionTemplateExplicitSpecialization<int>(int i)
+{
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+}
+
+template <typename T>
+class OuterClass
+{
+public:
+ class MiddleClass
+ {
+ public:
+ template <typename U>
+ class InnerClass
+ {
+ public:
+ void memberFunction(T x, U y) const
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+ };
+ };
+};
+
+template <typename T, template <typename> class Param = NS::ClassTemplate>
+class ClassWithTemplateTemplateParam
+{
+public:
+ static void staticMember()
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+};
+
+template <int Count>
+class NonTypeTemplateParam
+{
+public:
+ void size() const
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+};
+
+template <typename T>
+class SpecializedClassTemplate
+{
+public:
+ template <typename U>
+ void memberFunctionTemplate(T t, U u) const
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+};
+
+template <>
+class SpecializedClassTemplate<int>
+{
+public:
+ template <typename U>
+ void memberFunctionTemplate(int i, U u) const
+ {
+ printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__);
+ }
+};
+
int main() {
ClassInAnonymousNamespace anonymousNamespace;
anonymousNamespace.anonymousNamespaceFunction();
@@ -345,5 +464,28 @@
NS::externFunction();
+ // additional tests for __PRETTY_FUNCTION__
+
+ functionTemplateWithTwoParams(0, 0.0f);
+ functionTemplateWithoutParameterList<double>();
+ functionTemplateWithTemplateReturnType<char>();
+ int array[] = { 1, 2, 3 };
+ functionTemplateWithCompoundTypes(array);
+ functionTemplateExplicitSpecialization(0);
+ functionTemplateExplicitSpecialization(0.0);
+
+ OuterClass<int *>::MiddleClass::InnerClass<float> omi;
+ omi.memberFunction(0, 0.0f);
+
+ ClassWithTemplateTemplateParam<char>::staticMember();
+
+ NonTypeTemplateParam<42> ntt;
+ ntt.size();
+
+ SpecializedClassTemplate<int> sct1;
+ sct1.memberFunctionTemplate(0, 0.0f);
+ SpecializedClassTemplate<char> sct2;
+ sct2.memberFunctionTemplate('0', 0.0);
+
return 0;
}
More information about the cfe-dev
mailing list