diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 9 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp | 16 |
4 files changed, 31 insertions, 8 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 577c88c927..06d7d58988 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1351,6 +1351,8 @@ public: bool IgnoreBaseAccess); bool IsQualificationConversion(QualType FromType, QualType ToType, bool CStyle, bool &ObjCLifetimeConversion); + bool IsNoReturnConversion(QualType FromType, QualType ToType, + QualType &ResultTy); bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2995e2e6e0..eb1d661183 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -924,8 +924,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, /// \brief Determine whether the conversion from FromType to ToType is a valid /// conversion that strips "noreturn" off the nested function type. -static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, - QualType ToType, QualType &ResultTy) { +bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType, + QualType &ResultTy) { if (Context.hasSameUnqualifiedType(FromType, ToType)) return false; @@ -1066,7 +1066,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, S.ExtractUnqualifiedFunctionType(ToType), FromType)) { QualType resultTy; // if the function type matches except for [[noreturn]], it's ok - if (!IsNoReturnConversion(S.Context, FromType, + if (!S.IsNoReturnConversion(FromType, S.ExtractUnqualifiedFunctionType(ToType), resultTy)) // otherwise, only a boolean conversion is standard if (!ToType->isBooleanType()) @@ -1234,7 +1234,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) { + } else if (S.IsNoReturnConversion(FromType, ToType, FromType)) { // Treat a conversion that strips "noreturn" as an identity conversion. SCS.Second = ICK_NoReturn_Adjustment; } else if (IsTransparentUnionStandardConversion(S, From, ToType, @@ -7597,8 +7597,8 @@ private: QualType ResultTy; if (Context.hasSameUnqualifiedType(TargetFunctionType, FunDecl->getType()) || - IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType, - ResultTy)) { + S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType, + ResultTy)) { Matches.push_back(std::make_pair(CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); FoundNonTemplateFunction = true; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index b5e9c25d85..dcb4ff2860 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2371,9 +2371,16 @@ CheckOriginalCallArgDeduction(Sema &S, Sema::OriginalCallArg OriginalArg, // - The transformed A can be another pointer or pointer to member // type that can be converted to the deduced A via a qualification // conversion. + // + // Also allow conversions which merely strip [[noreturn]] from function types + // (recursively) as an extension. + // FIXME: Currently, this doesn't place nicely with qualfication conversions. bool ObjCLifetimeConversion = false; + QualType ResultTy; if ((A->isAnyPointerType() || A->isMemberPointerType()) && - S.IsQualificationConversion(A, DeducedA, false, ObjCLifetimeConversion)) + (S.IsQualificationConversion(A, DeducedA, false, + ObjCLifetimeConversion) || + S.IsNoReturnConversion(A, DeducedA, ResultTy))) return false; diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp index f5481c307d..295f080a75 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp @@ -71,7 +71,21 @@ void test_f3(int ***ip, volatile int ***vip) { A<int> a0 = f3(ip); A<volatile int> a1 = f3(vip); } - + +// Also accept conversions for pointer types which require removing +// [[noreturn]]. +namespace noreturn_stripping { + template <class R> + void f(R (*function)()); + + void g() __attribute__ ((__noreturn__)); + void h(); + void test() { + f(g); + f(h); + } +} + // - If P is a class, and P has the form template-id, then A can be a // derived class of the deduced A. Likewise, if P is a pointer to a class // of the form template-id, A can be a pointer to a derived class pointed |