[cfe-commits] r90913 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/attr-noreturn.cpp

Douglas Gregor dgregor at apple.com
Tue Dec 8 16:47:38 PST 2009


Author: dgregor
Date: Tue Dec  8 18:47:37 2009
New Revision: 90913

URL: http://llvm.org/viewvc/llvm-project?rev=90913&view=rev
Log:
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.


Added:
    cfe/trunk/test/SemaCXX/attr-noreturn.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=90913&r1=90912&r2=90913&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Dec  8 18:47:37 2009
@@ -394,9 +394,10 @@
   /// equivalent to calling T.withConst().
   QualType getConstType(QualType T) { return T.withConst(); }
 
-  /// getNoReturnType - Add the noreturn attribute to the given type which must
-  /// be a FunctionType or a pointer to an allowable type or a BlockPointer.
-  QualType getNoReturnType(QualType T);
+  /// getNoReturnType - Add or remove the noreturn attribute to the given type 
+  /// which must be a FunctionType or a pointer to an allowable type or a 
+  /// BlockPointer.
+  QualType getNoReturnType(QualType T, bool AddNoReturn = true);
 
   /// getComplexType - Return the uniqued reference to the type for a complex
   /// number with the specified element type.

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=90913&r1=90912&r2=90913&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Dec  8 18:47:37 2009
@@ -1200,32 +1200,42 @@
   return getExtQualType(TypeNode, Quals);
 }
 
-QualType ASTContext::getNoReturnType(QualType T) {
+QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
   QualType ResultType;
-  if (T->isPointerType()) {
-    QualType Pointee = T->getAs<PointerType>()->getPointeeType();
-    ResultType = getNoReturnType(Pointee);
+  if (const PointerType *Pointer = T->getAs<PointerType>()) {
+    QualType Pointee = Pointer->getPointeeType();
+    ResultType = getNoReturnType(Pointee, AddNoReturn);
+    if (ResultType == Pointee)
+      return T;
+    
     ResultType = getPointerType(ResultType);
-  } else if (T->isBlockPointerType()) {
-    QualType Pointee = T->getAs<BlockPointerType>()->getPointeeType();
-    ResultType = getNoReturnType(Pointee);
+  } else if (const BlockPointerType *BlockPointer
+                                              = T->getAs<BlockPointerType>()) {
+    QualType Pointee = BlockPointer->getPointeeType();
+    ResultType = getNoReturnType(Pointee, AddNoReturn);
+    if (ResultType == Pointee)
+      return T;
+    
     ResultType = getBlockPointerType(ResultType);
-  } else {
-    assert (T->isFunctionType()
-            && "can't noreturn qualify non-pointer to function or block type");
-
-    if (const FunctionNoProtoType *FNPT = T->getAs<FunctionNoProtoType>()) {
-      ResultType = getFunctionNoProtoType(FNPT->getResultType(), true);
+  } else if (const FunctionType *F = T->getAs<FunctionType>()) {
+    if (F->getNoReturnAttr() == AddNoReturn)
+      return T;
+    
+    if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
+      ResultType = getFunctionNoProtoType(FNPT->getResultType(), AddNoReturn);
     } else {
-      const FunctionProtoType *F = T->getAs<FunctionProtoType>();
+      const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
       ResultType
-        = getFunctionType(F->getResultType(), F->arg_type_begin(),
-                          F->getNumArgs(), F->isVariadic(), F->getTypeQuals(),
-                          F->hasExceptionSpec(), F->hasAnyExceptionSpec(),
-                          F->getNumExceptions(), F->exception_begin(), true);
+        = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
+                          FPT->getNumArgs(), FPT->isVariadic(), 
+                          FPT->getTypeQuals(),
+                          FPT->hasExceptionSpec(), FPT->hasAnyExceptionSpec(),
+                          FPT->getNumExceptions(), FPT->exception_begin(), 
+                          AddNoReturn);
     }
-  }
-
+  } else
+    return T;
+  
   return getQualifiedType(ResultType, T.getLocalQualifiers());
 }
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=90913&r1=90912&r2=90913&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Dec  8 18:47:37 2009
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=90913&r1=90912&r2=90913&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Dec  8 18:47:37 2009
@@ -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;
       }

Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=90913&r1=90912&r2=90913&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Tue Dec  8 18:47:37 2009
@@ -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)

Added: cfe/trunk/test/SemaCXX/attr-noreturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-noreturn.cpp?rev=90913&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/attr-noreturn.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-noreturn.cpp Tue Dec  8 18:47:37 2009
@@ -0,0 +1,30 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// PR5620
+void f0() __attribute__((__noreturn__));
+void f1(void (*)()); 
+void f2() { f1(f0); }
+
+// Taking the address of a noreturn function
+void test_f0a() {
+  void (*fp)() = f0;
+  void (*fp1)() __attribute__((noreturn)) = f0;
+}
+
+// Taking the address of an overloaded noreturn function 
+void f0(int) __attribute__((__noreturn__));
+
+void test_f0b() {
+  void (*fp)() = f0;
+  void (*fp1)() __attribute__((noreturn)) = f0;
+}
+
+// No-returned function pointers
+typedef void (* noreturn_fp)() __attribute__((noreturn));
+
+void f3(noreturn_fp); // expected-note{{candidate function}}
+
+void test_f3() {
+  f3(f0); // okay
+  f3(f2); // expected-error{{no matching function for call}}
+}





More information about the cfe-commits mailing list