forked from OSchip/llvm-project
PR13293: Defer deduction of an auto type with a dependent declarator, such as "auto (*f)(T t)".
llvm-svn: 159908
This commit is contained in:
parent
8a874c93d9
commit
74801c8182
|
@ -6335,7 +6335,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(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.
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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<MemberPointerType>()){
|
||||
if (MPT->getClass()->isDependentType())
|
||||
return true;
|
||||
Ty = MPT->getPointeeType();
|
||||
} else if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()){
|
||||
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<DependentSizedExtVectorType>()) {
|
||||
return true;
|
||||
} else if (const VectorType *VT = Ty->getAs<VectorType>()) {
|
||||
Ty = VT->getElementType();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(Ty->getAs<AutoType>() && "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<InitListExpr>(Init);
|
||||
InitListExpr *InitList = dyn_cast<InitListExpr>(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;
|
||||
|
|
|
@ -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<typename T> struct S {
|
||||
static constexpr auto (*p)(T) = &f;
|
||||
};
|
||||
|
||||
constexpr int (*f1)(char) = &f;
|
||||
constexpr double (*f2)(short) = &f;
|
||||
static_assert(S<char>::p == f1, "");
|
||||
static_assert(S<short>::p == f2, "");
|
||||
|
||||
struct K { int n; };
|
||||
template<typename T> struct U {
|
||||
static constexpr auto (T::*p) = &K::n;
|
||||
};
|
||||
static_assert(U<K>::p == &K::n, "");
|
||||
|
||||
template<typename T>
|
||||
using X = auto(int) -> auto(*)(T) -> auto(*)(char) -> long;
|
||||
X<double> x;
|
||||
template<typename T> struct V {
|
||||
//static constexpr auto (*p)(int) -> auto(*)(T) -> auto(*)(char) = &x; // ill-formed
|
||||
static constexpr auto (*(*(*p)(int))(T))(char) = &x; // ok
|
||||
};
|
||||
V<double> v;
|
||||
|
||||
int *g(double);
|
||||
template<typename T> void h() {
|
||||
new (auto(*)(T)) (&g);
|
||||
}
|
||||
template void h<double>();
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue