diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-04-10 20:14:15 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-04-10 20:14:15 +0000 |
commit | abf65ce5ddfb8db0d34280d30a91253930732f4f (patch) | |
tree | 2687bd2efa30489ee73de0d6a9ff60ccf64aef9f | |
parent | 316551f079a182d15c0e9b930c361428c968b5ee (diff) |
Improve the printing of __PRETTY_FUNCTION__ more provide more
information and more closely match GCC's, from Nikola Smiljanic!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154430 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/Expr.cpp | 78 | ||||
-rw-r--r-- | test/CodeGenCXX/predefined-expr-sizeof.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/predefined-expr.cpp | 180 |
3 files changed, 247 insertions, 19 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index ffc8fea894..1947e61d12 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -399,21 +399,23 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { } 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; + if (const FunctionDecl* Pattern = FD->getTemplateInstantiationPattern()) + Decl = Pattern; + 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 +424,74 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { 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"; + RefQualifierKind Ref = MD->getRefQualifier(); + if (Ref == RQ_LValue) + POut << " &"; + else if (Ref == RQ_RValue) + POut << " &&"; + } + + 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) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + 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) { + StringRef Param = Params->getParam(i)->getName(); + if (Param.empty()) continue; + TOut << Param << " = "; + 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); diff --git a/test/CodeGenCXX/predefined-expr-sizeof.cpp b/test/CodeGenCXX/predefined-expr-sizeof.cpp index f74cfb38fd..b4712ad15b 100644 --- a/test/CodeGenCXX/predefined-expr-sizeof.cpp +++ b/test/CodeGenCXX/predefined-expr-sizeof.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s -// CHECK: store i32 49, i32* %size -// CHECK: store i32 52, i32* %size +// CHECK: store i32 59, i32* %size +// CHECK: store i32 65, i32* %size template<typename T> class TemplateClass { public: @@ -10,8 +10,8 @@ public: } }; -// CHECK: store i32 27, i32* %size -// CHECK: store i32 30, i32* %size +// CHECK: store i32 35, i32* %size +// CHECK: store i32 38, i32* %size template<typename T> void functionTemplate(T t) { int size = sizeof(__PRETTY_FUNCTION__); diff --git a/test/CodeGenCXX/predefined-expr.cpp b/test/CodeGenCXX/predefined-expr.cpp index 56270b5f69..1795ec8b46 100644 --- a/test/CodeGenCXX/predefined-expr.cpp +++ b/test/CodeGenCXX/predefined-expr.cpp @@ -1,15 +1,29 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - | FileCheck %s // 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 [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = 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" @@ -31,6 +45,10 @@ // CHECK: private unnamed_addr constant [16 x i8] c"virtualFunction\00" // CHECK: private unnamed_addr constant [44 x i8] c"virtual void NS::Derived::virtualFunction()\00" +// CHECK: private unnamed_addr constant [21 x i8] c"refQualifiedFunction\00" +// CHECK: private unnamed_addr constant [41 x i8] c"void NS::Base::refQualifiedFunction() &&\00" +// CHECK: private unnamed_addr constant [40 x i8] c"void NS::Base::refQualifiedFunction() &\00" + // CHECK: private unnamed_addr constant [22 x i8] c"constVolatileFunction\00" // CHECK: private unnamed_addr constant [54 x i8] c"void NS::Base::constVolatileFunction() const volatile\00" @@ -78,6 +96,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 { @@ -203,11 +223,23 @@ public: printf("__FUNCTION__ %s\n", __FUNCTION__); printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); } + + void refQualifiedFunction() & { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + void refQualifiedFunction() && { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } }; 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 +326,116 @@ extern void externFunction() { } // 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, typename T> +void functionTemplateWithUnnamedTemplateParameter(T t) +{ + 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(); @@ -319,6 +461,8 @@ int main() { b.constFunction(); b.volatileFunction(); b.constVolatileFunction(); + b.refQualifiedFunction(); + NS::Base().refQualifiedFunction(); NS::Derived d; d.virtualFunction(); @@ -345,5 +489,29 @@ int main() { 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); + functionTemplateWithUnnamedTemplateParameter<int, float>(0.0f); + + 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; } |