[cfe-commits] r112561 - in /cfe/trunk: lib/Sema/TreeTransform.h test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp

Douglas Gregor dgregor at apple.com
Mon Aug 30 17:26:14 PDT 2010


Author: dgregor
Date: Mon Aug 30 19:26:14 2010
New Revision: 112561

URL: http://llvm.org/viewvc/llvm-project?rev=112561&view=rev
Log:
When instantiating a function type, instantiate the return type before
instantiating the parameters. In a perfect world, this wouldn't
matter, and compilers are free to instantiate in any order they
want. However, every other compiler seems to instantiate the return
type first, and some code (in this case, Boost.Polygon) depends on
this and SFINAE to avoid instantiating something that shouldn't be
instantiated.

We could fight this battle, and insist that Clang is allowed to do
what it does, but it's not beneficial: it's more predictable to
instantiate this way, in source order. When we implement
late-specified return types, we'll need to instantiate the return type
last when it was late-specified, hence the FIXME.

We now compile Boost.Polygon properly.

Modified:
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=112561&r1=112560&r2=112561&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Aug 30 19:26:14 2010
@@ -2903,18 +2903,25 @@
 TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
                                                    FunctionProtoTypeLoc TL,
                                                    QualType ObjectType) {
-  // Transform the parameters. We do this first for the benefit of template
-  // instantiations, so that the ParmVarDecls get/ placed into the template
-  // instantiation scope before we transform the function type.
+  // Transform the parameters and return type.
+  //
+  // We instantiate in source order, with the return type first followed by
+  // the parameters, because users tend to expect this (even if they shouldn't
+  // rely on it!).
+  //
+  // FIXME: When we implement late-specified return types, we'll need to
+  // instantiate the return tpe *after* the parameter types in that case,
+  // since the return type can then refer to the parameters themselves (via
+  // decltype, sizeof, etc.).
   llvm::SmallVector<QualType, 4> ParamTypes;
   llvm::SmallVector<ParmVarDecl*, 4> ParamDecls;
-  if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
-    return QualType();
-  
   FunctionProtoType *T = TL.getTypePtr();
   QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
   if (ResultType.isNull())
     return QualType();
+
+  if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls))
+    return QualType();  
   
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp?rev=112561&r1=112560&r2=112561&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp Mon Aug 30 19:26:14 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s
+// RUN: %clang_cc1 -verify %s
 
 typedef char one_byte;
 struct two_bytes { char data[2]; };
@@ -15,3 +15,28 @@
 int array0[is_class<X>::value? 1 : -1];
 int array1[is_class<int>::value? -1 : 1];
 int array2[is_class<char[3]>::value? -1 : 1];
+
+namespace instantiation_order1 {
+  template<typename T>
+  struct it_is_a_trap { 
+    typedef typename T::trap type;
+  };
+
+  template<bool, typename T = void>
+  struct enable_if {
+    typedef T type;
+  };
+
+  template<typename T>
+  struct enable_if<false, T> { };
+
+  template<typename T>
+  typename enable_if<sizeof(T) == 17>::type 
+  f(const T&, typename it_is_a_trap<T>::type* = 0);
+
+  void f(...);
+
+  void test_f() {
+    f('a');
+  }
+}





More information about the cfe-commits mailing list