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);
|
ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init);
|
||||||
|
|
||||||
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
// 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;
|
Expr *DeduceInit = Init;
|
||||||
// Initializer could be a C++ direct-initializer. Deduction only works if it
|
// Initializer could be a C++ direct-initializer. Deduction only works if it
|
||||||
// contains exactly one expression.
|
// 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.
|
// C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for.
|
||||||
if (TypeMayContainAuto && AllocType->getContainedAutoType()) {
|
AutoType *AT = 0;
|
||||||
|
if (TypeMayContainAuto &&
|
||||||
|
(AT = AllocType->getContainedAutoType()) && !AT->isDeduced()) {
|
||||||
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
|
if (initStyle == CXXNewExpr::NoInit || NumInits == 0)
|
||||||
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
|
return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg)
|
||||||
<< AllocType << TypeRange);
|
<< AllocType << TypeRange);
|
||||||
|
@ -1110,8 +1112,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
|
||||||
}
|
}
|
||||||
Expr *Deduce = Inits[0];
|
Expr *Deduce = Inits[0];
|
||||||
TypeSourceInfo *DeducedType = 0;
|
TypeSourceInfo *DeducedType = 0;
|
||||||
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
|
if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed)
|
||||||
DAR_Failed)
|
|
||||||
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
|
||||||
<< AllocType << Deduce->getType()
|
<< AllocType << Deduce->getType()
|
||||||
<< TypeRange << Deduce->getSourceRange());
|
<< TypeRange << Deduce->getSourceRange());
|
||||||
|
|
|
@ -3464,6 +3464,41 @@ namespace {
|
||||||
return E;
|
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)
|
/// \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();
|
Init = result.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Init->isTypeDependent()) {
|
if (Init->isTypeDependent() || isDependentAutoType(Type->getType())) {
|
||||||
Result = Type;
|
Result = Type;
|
||||||
return DAR_Succeeded;
|
return DAR_Succeeded;
|
||||||
}
|
}
|
||||||
|
@ -3517,7 +3552,7 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init,
|
||||||
|
|
||||||
TemplateDeductionInfo Info(Context, Loc);
|
TemplateDeductionInfo Info(Context, Loc);
|
||||||
|
|
||||||
InitListExpr * InitList = dyn_cast<InitListExpr>(Init);
|
InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
|
||||||
if (InitList) {
|
if (InitList) {
|
||||||
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
|
for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
|
||||||
if (DeduceTemplateArgumentByListElement(*this, &TemplateParams,
|
if (DeduceTemplateArgumentByListElement(*this, &TemplateParams,
|
||||||
|
|
|
@ -49,3 +49,40 @@ void p3example() {
|
||||||
same<__typeof(u), const int> uHasTypeConstInt;
|
same<__typeof(u), const int> uHasTypeConstInt;
|
||||||
same<__typeof(y), double> yHasTypeDouble;
|
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