[cfe-commits] r159908 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Sat Jul 7 21:13:08 PDT 2012
Author: rsmith
Date: Sat Jul 7 23:13:07 2012
New Revision: 159908
URL: http://llvm.org/viewvc/llvm-project?rev=159908&view=rev
Log:
PR13293: Defer deduction of an auto type with a dependent declarator, such as "auto (*f)(T t)".
Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=159908&r1=159907&r2=159908&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Jul 7 23:13:07 2012
@@ -6335,7 +6335,10 @@
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.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=159908&r1=159907&r2=159908&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Jul 7 23:13:07 2012
@@ -1093,8 +1093,10 @@
}
}
- // 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 @@
}
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());
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=159908&r1=159907&r2=159908&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Sat Jul 7 23:13:07 2012
@@ -3464,6 +3464,41 @@
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 @@
Init = result.take();
}
- if (Init->isTypeDependent()) {
+ if (Init->isTypeDependent() || isDependentAutoType(Type->getType())) {
Result = Type;
return DAR_Succeeded;
}
@@ -3517,10 +3552,10 @@
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 @@
FuncParam, InitType, Init,
TDF))
return DAR_Failed;
-
+
if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
InitType, Info, Deduced, TDF))
return DAR_Failed;
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=159908&r1=159907&r2=159908&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Sat Jul 7 23:13:07 2012
@@ -49,3 +49,40 @@
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
More information about the cfe-commits
mailing list