summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-06-18 01:19:03 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-06-18 01:19:03 +0000
commit53e61b05cedec58ae85a4ac9f2ddd60ad00b479b (patch)
tree5f03438f632a95916f5d98e71a527be659681e23
parent831ae0105adb180585d356085482077c0ce4e259 (diff)
downloadbcm5719-llvm-53e61b05cedec58ae85a4ac9f2ddd60ad00b479b.tar.gz
bcm5719-llvm-53e61b05cedec58ae85a4ac9f2ddd60ad00b479b.zip
Accept no-return stripping conversions for pointer type arguments after
deducing template parameter types. Recently Clang began enforcing the more strict checking that the argument type and the deduced function parameter type (after substitution) match, but that only consideres qualification conversions. One problem with this patch is that we check noreturn conversions and qualification conversions independently. If a valid conversion would require *both*, perhaps interleaved with each other, it will be rejected. If this actually occurs (I'm not yet sure it does) and is in fact a problem (I'm not yet sure it is), there is a FIXME to implement more intelligent conversion checking. However, this step at least allows Clang to resume accepting valid code we're seeing in the wild. llvm-svn: 133327
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/Sema/SemaOverload.cpp12
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp9
-rw-r--r--clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp16
4 files changed, 31 insertions, 8 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 577c88c9270..06d7d58988c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/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/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 2995e2e6e07..eb1d661183a 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/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/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index b5e9c25d856..dcb4ff28606 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/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/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
index f5481c307d0..295f080a75d 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud