diff options
-rw-r--r-- | lib/Sema/TreeTransform.h | 19 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp | 27 |
2 files changed, 39 insertions, 7 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 08cfd68d66..db5c67a2e0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2903,18 +2903,25 @@ QualType 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() || diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp index f6121b373e..6481485b2a 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp @@ -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 @@ struct X { }; 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'); + } +} |