Index: include/clang/AST/PrettyPrinter.h =================================================================== --- include/clang/AST/PrettyPrinter.h +++ include/clang/AST/PrettyPrinter.h @@ -42,7 +42,7 @@ SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), - IncludeNewlines(true) { } + IncludeNewlines(true), KeepAutoType(false) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -163,6 +163,9 @@ /// \brief When true, include newlines after statements like "break", etc. unsigned IncludeNewlines : 1; + + /// \brief When true, output "auto" instead of the actually deduced type. + unsigned KeepAutoType : 1; }; } // end namespace clang Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -600,6 +600,7 @@ // type deduction and lambdas. For trailing return types resolve the // decltype expression. Otherwise print the real type when this is // not a constructor or destructor. + Policy.KeepAutoType = true; if ((isa(FD) && cast(FD)->getParent()->isLambda()) || (FT && FT->getReturnType()->getAs())) Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -824,7 +824,7 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { // If the type has been deduced, do not print 'auto'. - if (!T->getDeducedType().isNull()) { + if (!Policy.KeepAutoType && !T->getDeducedType().isNull()) { printBefore(T->getDeducedType(), OS); } else { OS << (T->isDecltypeAuto() ? "decltype(auto)" : "auto"); @@ -833,7 +833,7 @@ } void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) { // If the type has been deduced, do not print 'auto'. - if (!T->getDeducedType().isNull()) + if (!Policy.KeepAutoType && !T->getDeducedType().isNull()) printAfter(T->getDeducedType(), OS); } Index: test/CodeGenCXX/predefined-expr-cxx14.cpp =================================================================== --- test/CodeGenCXX/predefined-expr-cxx14.cpp +++ test/CodeGenCXX/predefined-expr-cxx14.cpp @@ -0,0 +1,518 @@ +// RUN: %clang_cc1 -std=c++14 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s + +// CHECK-DAG: private unnamed_addr constant [15 x i8] c"externFunction\00" +// CHECK-DAG: private unnamed_addr constant [26 x i8] c"auto NS::externFunction()\00" +// CHECK-DAG: private unnamed_addr constant [49 x i8] c"auto functionTemplateExplicitSpecialization(int)\00" +// CHECK-DAG: private unnamed_addr constant [52 x i8] c"T *functionTemplateWithCompoundTypes(T *) [T = int]\00" +// CHECK-DAG: private unnamed_addr constant [54 x i8] c"T functionTemplateWithTemplateReturnType() [T = char]\00" + +// CHECK-DAG: private unnamed_addr constant [95 x i8] c"auto SpecializedClassTemplate::memberFunctionTemplate(T, U) const [T = char, U = double]\00" +// CHECK-DAG: private unnamed_addr constant [85 x i8] c"auto SpecializedClassTemplate::memberFunctionTemplate(int, U) const [U = float]\00" +// CHECK-DAG: private unnamed_addr constant [57 x i8] c"auto NonTypeTemplateParam<42>::size() const [Count = 42]\00" +// CHECK-DAG: private unnamed_addr constant [122 x i8] c"static auto ClassWithTemplateTemplateParam::staticMember() [T = char, Param = NS::ClassTemplate]\00" +// CHECK-DAG: private unnamed_addr constant [106 x i8] c"auto OuterClass::MiddleClass::InnerClass::memberFunction(T, U) const [T = int *, U = float]\00" +// CHECK-DAG: private unnamed_addr constant [51 x i8] c"auto functionTemplateWithCapturedStmt(T) [T = int]\00" +// CHECK-DAG: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::(anonymous class)::operator()() const\00" +// CHECK-DAG: private unnamed_addr constant [65 x i8] c"auto functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00" + +// CHECK-DAG: private unnamed_addr constant [60 x i8] c"auto functionTemplateExplicitSpecialization(T) [T = double]\00" +// CHECK-DAG: private unnamed_addr constant [57 x i8] c"auto functionTemplateWithoutParameterList() [T = double]\00" +// CHECK-DAG: private unnamed_addr constant [62 x i8] c"auto functionTemplateWithTwoParams(T, U) [T = int, U = float]\00" + +// CHECK-DAG: private unnamed_addr constant [22 x i8] c"classTemplateFunction\00" +// CHECK-DAG: private unnamed_addr constant [77 x i8] c"auto NS::ClassTemplate::classTemplateFunction() [T = NS::Base *]\00" +// CHECK-DAG: private unnamed_addr constant [63 x i8] c"auto NS::ClassTemplate::classTemplateFunction() [T = int]\00" + +// CHECK-DAG: private unnamed_addr constant [18 x i8] c"functionTemplate1\00" +// CHECK-DAG: private unnamed_addr constant [53 x i8] c"auto NS::Base::functionTemplate1(T) [T = NS::Base *]\00" +// CHECK-DAG: private unnamed_addr constant [46 x i8] c"auto NS::Base::functionTemplate1(T) [T = int]\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00" +// CHECK-DAG: private unnamed_addr constant [83 x i8] c"auto NS::ContainerForAnonymousRecords::(anonymous union)::anonymousUnionFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [24 x i8] c"anonymousStructFunction\00" +// CHECK-DAG: private unnamed_addr constant [85 x i8] c"auto NS::ContainerForAnonymousRecords::(anonymous struct)::anonymousStructFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"anonymousClassFunction\00" +// CHECK-DAG: private unnamed_addr constant [83 x i8] c"auto NS::ContainerForAnonymousRecords::(anonymous class)::anonymousClassFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [12 x i8] c"~Destructor\00" +// CHECK-DAG: private unnamed_addr constant [30 x i8] c"NS::Destructor::~Destructor()\00" + +// CHECK-DAG: private unnamed_addr constant [12 x i8] c"Constructor\00" +// CHECK-DAG: private unnamed_addr constant [41 x i8] c"NS::Constructor::Constructor(NS::Base *)\00" +// CHECK-DAG: private unnamed_addr constant [34 x i8] c"NS::Constructor::Constructor(int)\00" +// CHECK-DAG: private unnamed_addr constant [31 x i8] c"NS::Constructor::Constructor()\00" + +// CHECK-DAG: private unnamed_addr constant [21 x i8] c"refQualifiedFunction\00" +// CHECK-DAG: private unnamed_addr constant [41 x i8] c"auto NS::Base::refQualifiedFunction() &&\00" +// CHECK-DAG: private unnamed_addr constant [40 x i8] c"auto NS::Base::refQualifiedFunction() &\00" + +// CHECK-DAG: private unnamed_addr constant [22 x i8] c"constVolatileFunction\00" +// CHECK-DAG: private unnamed_addr constant [54 x i8] c"auto NS::Base::constVolatileFunction() const volatile\00" + +// CHECK-DAG: private unnamed_addr constant [17 x i8] c"volatileFunction\00" +// CHECK-DAG: private unnamed_addr constant [43 x i8] c"auto NS::Base::volatileFunction() volatile\00" + +// CHECK-DAG: private unnamed_addr constant [14 x i8] c"constFunction\00" +// CHECK-DAG: private unnamed_addr constant [37 x i8] c"auto NS::Base::constFunction() const\00" + +// CHECK-DAG: private unnamed_addr constant [26 x i8] c"functionReturingTemplate2\00" +// CHECK-DAG: private unnamed_addr constant [64 x i8] c"ClassTemplate NS::Base::functionReturingTemplate2()\00" + +// CHECK-DAG: private unnamed_addr constant [26 x i8] c"functionReturingTemplate1\00" +// CHECK-DAG: private unnamed_addr constant [57 x i8] c"ClassTemplate NS::Base::functionReturingTemplate1()\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"withTemplateParameter2\00" +// CHECK-DAG: private unnamed_addr constant [65 x i8] c"auto NS::Base::withTemplateParameter2(ClassTemplate)\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"withTemplateParameter1\00" +// CHECK-DAG: private unnamed_addr constant [58 x i8] c"auto NS::Base::withTemplateParameter1(ClassTemplate)\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"functionReturningClass\00" +// CHECK-DAG: private unnamed_addr constant [45 x i8] c"NS::Base *NS::Base::functionReturningClass()\00" + +// CHECK-DAG: private unnamed_addr constant [23 x i8] c"functionWithParameters\00" +// CHECK-DAG: private unnamed_addr constant [67 x i8] c"auto &NS::Base::functionWithParameters(int &, float *, NS::Base *)\00" + +// CHECK-DAG: private unnamed_addr constant [17 x i8] c"variadicFunction\00" +// CHECK-DAG: private unnamed_addr constant [51 x i8] c"const auto *NS::Base::variadicFunction(int *, ...)\00" + +// CHECK-DAG: private unnamed_addr constant [15 x i8] c"inlineFunction\00" +// CHECK-DAG: private unnamed_addr constant [32 x i8] c"auto NS::Base::inlineFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [15 x i8] c"staticFunction\00" +// CHECK-DAG: private unnamed_addr constant [39 x i8] c"static auto NS::Base::staticFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [26 x i8] c"topLevelNamespaceFunction\00" +// CHECK-DAG: private unnamed_addr constant [60 x i8] c"auto *ClassInTopLevelNamespace::topLevelNamespaceFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [27 x i8] c"anonymousNamespaceFunction\00" +// CHECK-DAG: private unnamed_addr constant [84 x i8] c"auto (anonymous namespace)::ClassInAnonymousNamespace::anonymousNamespaceFunction()\00" + +// CHECK-DAG: private unnamed_addr constant [19 x i8] c"localClassFunction\00" +// CHECK-DAG: private unnamed_addr constant [59 x i8] c"auto NS::localClass(int)::LocalClass::localClassFunction()\00" + + + +int printf(const char * _Format, ...); + +class ClassInTopLevelNamespace { +public: + auto *topLevelNamespaceFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return static_cast(nullptr); + } +}; + +namespace { + + class ClassInAnonymousNamespace { + public: + auto anonymousNamespaceFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + }; + +} // end anonymous namespace + +namespace NS { + +template +class ClassTemplate { +public: + auto classTemplateFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +class Base { +public: + static auto staticFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + inline auto (inlineFunction)() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto &functionWithParameters(int &a, float*, Base* base) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return a; + } + + Base *functionReturningClass() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return 0; + } + + const auto *variadicFunction(int *a, ...) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return a; + } + + auto withTemplateParameter1(ClassTemplate) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto withTemplateParameter2(ClassTemplate) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + ClassTemplate functionReturingTemplate1() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return ClassTemplate(); + } + + ClassTemplate functionReturingTemplate2() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + return ClassTemplate(); + } + + template + auto functionTemplate1(T t) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto constFunction() const { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto volatileFunction() volatile { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto constVolatileFunction() const volatile { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto refQualifiedFunction() & { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + auto refQualifiedFunction() && { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +class Constructor { +public: + Constructor() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + Constructor(int) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + + Constructor(Base *) { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +class Destructor { +public: + ~Destructor() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +class ContainerForAnonymousRecords { +public: + class { + public: + auto anonymousClassFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + } anonymousClass; + + struct { + auto anonymousStructFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + } anonymousStruct; + + union { + auto anonymousUnionFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + } anonymousUnion; +}; + +auto localClass(int) { + class LocalClass { + public: + auto localClassFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + }; + LocalClass lc; + lc.localClassFunction(); +} + +extern auto externFunction() { + printf("__func__ %s\n", __func__); + printf("__FUNCTION__ %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +} // end NS namespace + +// additional tests for __PRETTY_FUNCTION__ +template +auto functionTemplateWithTwoParams(T, U) +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +template +auto functionTemplateWithoutParameterList() +{ + T t = T(); + + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +template +T functionTemplateWithTemplateReturnType() +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + + return T(); +} + +template +T * functionTemplateWithCompoundTypes(T a[]) +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + + return 0; +} + +template +auto functionTemplateExplicitSpecialization(T t) +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +template <> +auto functionTemplateExplicitSpecialization(int i) +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +template +auto functionTemplateWithUnnamedTemplateParameter(T t) +{ + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); +} + +template +auto functionTemplateWithLambda(T t) +{ + []() { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } (); +} + +template +auto functionTemplateWithCapturedStmt(T t) +{ + #pragma clang __debug captured + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +} + +template +class OuterClass +{ +public: + class MiddleClass + { + public: + template + class InnerClass + { + public: + auto memberFunction(T x, U y) const + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } + }; + }; +}; + +template class Param = NS::ClassTemplate> +class ClassWithTemplateTemplateParam +{ +public: + static auto staticMember() + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +template +class NonTypeTemplateParam +{ +public: + auto size() const + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +template +class SpecializedClassTemplate +{ +public: + template + auto memberFunctionTemplate(T t, U u) const + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +template <> +class SpecializedClassTemplate +{ +public: + template + auto memberFunctionTemplate(int i, U u) const + { + printf("__PRETTY_FUNCTION__ %s\n\n", __PRETTY_FUNCTION__); + } +}; + +int main() { + ClassInAnonymousNamespace anonymousNamespace; + anonymousNamespace.anonymousNamespaceFunction(); + + ClassInTopLevelNamespace topLevelNamespace; + topLevelNamespace.topLevelNamespaceFunction(); + + NS::Base::staticFunction(); + + NS::Base b; + b.inlineFunction(); + b.variadicFunction(nullptr); + int a; + b.functionWithParameters(a, 0, 0); + b.functionReturningClass(); + + b.withTemplateParameter1(NS::ClassTemplate()); + b.withTemplateParameter2(NS::ClassTemplate()); + b.functionReturingTemplate1(); + b.functionReturingTemplate2(); + b.functionTemplate1(0); + b.functionTemplate1(0); + b.constFunction(); + b.volatileFunction(); + b.constVolatileFunction(); + b.refQualifiedFunction(); + NS::Base().refQualifiedFunction(); + + NS::ClassTemplate t1; + t1.classTemplateFunction(); + NS::ClassTemplate t2; + t2.classTemplateFunction(); + + NS::Constructor c1; + NS::Constructor c2(0); + NS::Constructor c3((NS::Base *)0); + + { + NS::Destructor destructor; + } + + NS::ContainerForAnonymousRecords anonymous; + anonymous.anonymousClass.anonymousClassFunction(); + anonymous.anonymousStruct.anonymousStructFunction(); + anonymous.anonymousUnion.anonymousUnionFunction(); + + NS::localClass(0); + + NS::externFunction(); + + // additional tests for __PRETTY_FUNCTION__ + + functionTemplateWithTwoParams(0, 0.0f); + functionTemplateWithoutParameterList(); + functionTemplateWithTemplateReturnType(); + int array[] = { 1, 2, 3 }; + functionTemplateWithCompoundTypes(array); + functionTemplateExplicitSpecialization(0); + functionTemplateExplicitSpecialization(0.0); + functionTemplateWithUnnamedTemplateParameter(0.0f); + + functionTemplateWithLambda(0); + functionTemplateWithCapturedStmt(0); + + OuterClass::MiddleClass::InnerClass omi; + omi.memberFunction(0, 0.0f); + + ClassWithTemplateTemplateParam::staticMember(); + + NonTypeTemplateParam<42> ntt; + ntt.size(); + + SpecializedClassTemplate sct1; + sct1.memberFunctionTemplate(0, 0.0f); + SpecializedClassTemplate sct2; + sct2.memberFunctionTemplate('0', 0.0); + + return 0; +}