Implemented an implicit conversion from "noreturn" function types (and
pointers thereof) to their corresponding non-noreturn function
types. This conversion is considered an exact match for
overload-resolution purposes. Note that we are a little more strict
that GCC is, because we encode noreturn in the type system, but that's
a Good Thing (TM) because it does not allow us to pretend that
potentially-returning function pointers are non-returning function
pointers.

Fxies PR5620.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90913 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index be33c06..d83148c 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1269,6 +1269,16 @@
     // Nothing else to do.
     break;
 
+  case ICK_NoReturn_Adjustment:
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;      
+      
+    ImpCastExprToType(From, Context.getNoReturnType(From->getType(), false),
+                      CastExpr::CK_NoOp);
+    break;
+      
   case ICK_Integral_Promotion:
   case ICK_Integral_Conversion:
     ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 769adb5..47393f7 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -38,6 +38,7 @@
     ICC_Lvalue_Transformation,
     ICC_Lvalue_Transformation,
     ICC_Lvalue_Transformation,
+    ICC_Identity,
     ICC_Qualification_Adjustment,
     ICC_Promotion,
     ICC_Promotion,
@@ -66,6 +67,7 @@
     ICR_Exact_Match,
     ICR_Exact_Match,
     ICR_Exact_Match,
+    ICR_Exact_Match,
     ICR_Promotion,
     ICR_Promotion,
     ICR_Promotion,
@@ -91,6 +93,7 @@
     "Lvalue-to-rvalue",
     "Array-to-pointer",
     "Function-to-pointer",
+    "Noreturn adjustment",
     "Qualification",
     "Integral promotion",
     "Floating point promotion",
@@ -475,6 +478,23 @@
   return ICS;
 }
 
+/// \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) {
+  if (Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+  
+  // Strip the noreturn off the type we're converting from; noreturn can
+  // safely be removed.
+  FromType = Context.getNoReturnType(FromType, false);
+  if (!Context.hasSameUnqualifiedType(FromType, ToType))
+    return false;
+
+  ResultTy = FromType;
+  return true;
+}
+  
 /// IsStandardConversion - Determines whether there is a standard
 /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
 /// expression From to the type ToType. Standard conversion sequences
@@ -554,7 +574,7 @@
     // function. (C++ 4.3p1).
     FromType = Context.getPointerType(FromType);
   } else if (FunctionDecl *Fn
-             = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
+               = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
     // Address of overloaded function (C++ [over.over]).
     SCS.First = ICK_Function_To_Pointer;
 
@@ -656,6 +676,9 @@
              Context.typesAreCompatible(ToType, FromType)) {
     // Compatible conversions (Clang extension for C function overloading)
     SCS.Second = ICK_Compatible_Conversion;
+  } else if (IsNoReturnConversion(Context, FromType, ToType, FromType)) {
+    // Treat a conversion that strips "noreturn" as an identity conversion.
+    SCS.Second = ICK_NoReturn_Adjustment;
   } else {
     // No second conversion required.
     SCS.Second = ICK_Identity;
@@ -1234,7 +1257,7 @@
 
   return false;
 }
-
+  
 /// CheckMemberPointerConversion - Check the member pointer conversion from the
 /// expression From to the type ToType. This routine checks for ambiguous or
 /// virtual (FIXME: or inaccessible) base-to-derived member pointer conversions
@@ -4455,7 +4478,10 @@
       continue;
 
     if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*I)) {
-      if (FunctionType == Context.getCanonicalType(FunDecl->getType())) {
+      QualType ResultTy;
+      if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
+          IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, 
+                               ResultTy)) {
         Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl()));
         FoundNonTemplateFunction = true;
       }
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index 0d1f37a..5eef3ce 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -30,6 +30,7 @@
     ICK_Lvalue_To_Rvalue,      ///< Lvalue-to-rvalue conversion (C++ 4.1)
     ICK_Array_To_Pointer,      ///< Array-to-pointer conversion (C++ 4.2)
     ICK_Function_To_Pointer,   ///< Function-to-pointer (C++ 4.3)
+    ICK_NoReturn_Adjustment,   ///< Removal of noreturn from a type (Clang)
     ICK_Qualification,         ///< Qualification conversions (C++ 4.4)
     ICK_Integral_Promotion,    ///< Integral promotions (C++ 4.5)
     ICK_Floating_Promotion,    ///< Floating point promotions (C++ 4.6)