From 8ad6c8696a23f410398fc126929b107404c59a95 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sun, 8 Jul 2012 04:13:07 +0000 Subject: [PATCH] PR13293: Defer deduction of an auto type with a dependent declarator, such as "auto (*f)(T t)". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159908 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 5 ++- lib/Sema/SemaExprCXX.cpp | 9 ++-- lib/Sema/SemaTemplateDeduction.cpp | 43 +++++++++++++++++-- .../dcl.spec/dcl.type/dcl.spec.auto/p3.cpp | 37 ++++++++++++++++ 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 99814911e0..f9a487270b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6335,7 +6335,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, ParenListExpr *CXXDirectInit = dyn_cast(Init); // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + AutoType *Auto = 0; + if (TypeMayContainAuto && + (Auto = VDecl->getType()->getContainedAutoType()) && + !Auto->isDeduced()) { Expr *DeduceInit = Init; // Initializer could be a C++ direct-initializer. Deduction only works if it // contains exactly one expression. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 8efd465580..9657661a03 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1093,8 +1093,10 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (TypeMayContainAuto && AllocType->getContainedAutoType()) { + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + AutoType *AT = 0; + if (TypeMayContainAuto && + (AT = AllocType->getContainedAutoType()) && !AT->isDeduced()) { if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); @@ -1110,8 +1112,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } Expr *Deduce = Inits[0]; TypeSourceInfo *DeducedType = 0; - if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == - DAR_Failed) + if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed) return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) << AllocType << Deduce->getType() << TypeRange << Deduce->getSourceRange()); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index f4618e2e7e..310d9b36cb 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -3464,6 +3464,41 @@ namespace { return E; } }; + + /// Determine whether the specified type (which contains an 'auto' type + /// specifier) is dependent. This is not trivial, because the 'auto' specifier + /// itself claims to be type-dependent. + bool isDependentAutoType(QualType Ty) { + while (1) { + QualType Pointee = Ty->getPointeeType(); + if (!Pointee.isNull()) { + Ty = Pointee; + } else if (const MemberPointerType *MPT = Ty->getAs()){ + if (MPT->getClass()->isDependentType()) + return true; + Ty = MPT->getPointeeType(); + } else if (const FunctionProtoType *FPT = Ty->getAs()){ + for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(), + E = FPT->arg_type_end(); + I != E; ++I) + if ((*I)->isDependentType()) + return true; + Ty = FPT->getResultType(); + } else if (Ty->isDependentSizedArrayType()) { + return true; + } else if (const ArrayType *AT = Ty->getAsArrayTypeUnsafe()) { + Ty = AT->getElementType(); + } else if (Ty->getAs()) { + return true; + } else if (const VectorType *VT = Ty->getAs()) { + Ty = VT->getElementType(); + } else { + break; + } + } + assert(Ty->getAs() && "didn't find 'auto' in auto type"); + return false; + } } /// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6) @@ -3486,7 +3521,7 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, Init = result.take(); } - if (Init->isTypeDependent()) { + if (Init->isTypeDependent() || isDependentAutoType(Type->getType())) { Result = Type; return DAR_Succeeded; } @@ -3517,10 +3552,10 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, TemplateDeductionInfo Info(Context, Loc); - InitListExpr * InitList = dyn_cast(Init); + InitListExpr *InitList = dyn_cast(Init); if (InitList) { for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) { - if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, + if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, TemplArg, InitList->getInit(i), Info, Deduced, TDF)) @@ -3531,7 +3566,7 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, FuncParam, InitType, Init, TDF)) return DAR_Failed; - + if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam, InitType, Info, Deduced, TDF)) return DAR_Failed; diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp index 1daf02f6ea..f732255a8a 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp @@ -49,3 +49,40 @@ void p3example() { same<__typeof(u), const int> uHasTypeConstInt; same<__typeof(y), double> yHasTypeDouble; } + +#if __cplusplus >= 201103L +namespace PR13293 { + // Ensure that dependent declarators have their deduction delayed. + int f(char); + double f(short); + template struct S { + static constexpr auto (*p)(T) = &f; + }; + + constexpr int (*f1)(char) = &f; + constexpr double (*f2)(short) = &f; + static_assert(S::p == f1, ""); + static_assert(S::p == f2, ""); + + struct K { int n; }; + template struct U { + static constexpr auto (T::*p) = &K::n; + }; + static_assert(U::p == &K::n, ""); + + template + using X = auto(int) -> auto(*)(T) -> auto(*)(char) -> long; + X x; + template struct V { + //static constexpr auto (*p)(int) -> auto(*)(T) -> auto(*)(char) = &x; // ill-formed + static constexpr auto (*(*(*p)(int))(T))(char) = &x; // ok + }; + V v; + + int *g(double); + template void h() { + new (auto(*)(T)) (&g); + } + template void h(); +} +#endif -- 2.50.1