[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