]> granicus.if.org Git - clang/commitdiff
Fix the noreturn conversion to only strip off a single level of indirection.
authorJohn McCall <rjmccall@apple.com>
Tue, 21 Dec 2010 00:44:39 +0000 (00:44 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 21 Dec 2010 00:44:39 +0000 (00:44 +0000)
Apply the noreturn attribute while creating a builtin function's type.
Remove the getNoReturnType() API.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122295 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaOverload.cpp

index aee1612948b6909cb56318f6d40f4b5f4ac3d83f..757cddbfd2b30fa5d6028fbc90d315fb41839f37 100644 (file)
@@ -484,11 +484,6 @@ public:
   const FunctionType *adjustFunctionType(const FunctionType *Fn,
                                          FunctionType::ExtInfo EInfo);
 
-  /// 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.
   QualType getComplexType(QualType T);
index 8e2ef1a95e4a0afb1efb4d9c2e736f3448751e93..90279d8db1a5488fdef1e1dbf56ba1fa1a19cf9c 100644 (file)
@@ -1159,53 +1159,6 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
   return cast<FunctionType>(Result.getTypePtr());
 }
 
-static QualType getExtFunctionType(ASTContext& Context, QualType T,
-                                   FunctionType::ExtInfo Info) {
-  QualType ResultType;
-  if (const PointerType *Pointer = T->getAs<PointerType>()) {
-    QualType Pointee = Pointer->getPointeeType();
-    ResultType = getExtFunctionType(Context, Pointee, Info);
-    if (ResultType == Pointee)
-      return T;
-
-    ResultType = Context.getPointerType(ResultType);
-  } else if (const ParenType *Paren = T->getAs<ParenType>()) {
-    QualType Inner = Paren->getInnerType();
-    ResultType = getExtFunctionType(Context, Inner, Info);
-    if (ResultType == Inner)
-      return T;
-
-    ResultType = Context.getParenType(ResultType);
-  } else if (const BlockPointerType *BlockPointer
-                                              = T->getAs<BlockPointerType>()) {
-    QualType Pointee = BlockPointer->getPointeeType();
-    ResultType = getExtFunctionType(Context, Pointee, Info);
-    if (ResultType == Pointee)
-      return T;
-
-    ResultType = Context.getBlockPointerType(ResultType);
-  } else if (const MemberPointerType *MemberPointer 
-                                            = T->getAs<MemberPointerType>()) {
-    QualType Pointee = MemberPointer->getPointeeType();
-    ResultType = getExtFunctionType(Context, Pointee, Info);
-    if (ResultType == Pointee)
-      return T;
-    
-    ResultType = Context.getMemberPointerType(ResultType, 
-                                              MemberPointer->getClass());
-   } else if (const FunctionType *F = T->getAs<FunctionType>()) {
-    ResultType = QualType(Context.adjustFunctionType(F, Info), 0);
-  } else
-    return T;
-
-  return Context.getQualifiedType(ResultType, T.getLocalQualifiers());
-}
-
-QualType ASTContext::getNoReturnType(QualType T, bool AddNoReturn) {
-  FunctionType::ExtInfo Info = getFunctionExtInfo(T);
-  return getExtFunctionType(*this, T, Info.withNoReturn(AddNoReturn));
-}
-
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
 QualType ASTContext::getComplexType(QualType T) {
@@ -5595,13 +5548,18 @@ QualType ASTContext::GetBuiltinType(unsigned Id,
   assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
          "'.' should only occur at end of builtin type list!");
 
-  // handle untyped/variadic arguments "T c99Style();" or "T cppStyle(...);".
-  if (ArgTypes.size() == 0 && TypeStr[0] == '.')
-    return getFunctionNoProtoType(ResType);
+  FunctionType::ExtInfo EI;
+  if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
+
+  bool Variadic = (TypeStr[0] == '.');
+
+  // We really shouldn't be making a no-proto type here, especially in C++.
+  if (ArgTypes.empty() && Variadic)
+    return getFunctionNoProtoType(ResType, EI);
 
   FunctionProtoType::ExtProtoInfo EPI;
-  EPI.Variadic = (TypeStr[0] == '.');
-  // FIXME: Should we create noreturn types?
+  EPI.ExtInfo = EI;
+  EPI.Variadic = Variadic;
 
   return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI);
 }
index 665689ef269ed18e735892e2e65218037874b592..ad0c077aad4e2a893f9d8f3147c8904f132b7df8 100644 (file)
@@ -5594,8 +5594,6 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) {
         FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context));
     }
 
-    if (Context.BuiltinInfo.isNoReturn(BuiltinID))
-      FD->setType(Context.getNoReturnType(FD->getType()));
     if (Context.BuiltinInfo.isNoThrow(BuiltinID))
       FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context));
     if (Context.BuiltinInfo.isConst(BuiltinID))
index 5a2150664cab3a5abc4065a3e3362b480a407146..6b370fd36aebcb17043e391f72396208b4cfb2be 100644 (file)
@@ -882,13 +882,44 @@ static bool IsNoReturnConversion(ASTContext &Context, QualType FromType,
   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;
+  // Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+  // where F adds one of the following at most once:
+  //   - a pointer
+  //   - a member pointer
+  //   - a block pointer
+  CanQualType CanTo = Context.getCanonicalType(ToType);
+  CanQualType CanFrom = Context.getCanonicalType(FromType);
+  Type::TypeClass TyClass = CanTo->getTypeClass();
+  if (TyClass != CanFrom->getTypeClass()) return false;
+  if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) {
+    if (TyClass == Type::Pointer) {
+      CanTo = CanTo.getAs<PointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<PointerType>()->getPointeeType();
+    } else if (TyClass == Type::BlockPointer) {
+      CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
+    } else if (TyClass == Type::MemberPointer) {
+      CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
+      CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
+    } else {
+      return false;
+    }
+
+    TyClass = CanTo->getTypeClass();
+    if (TyClass != CanFrom->getTypeClass()) return false;
+    if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
+      return false;
+  }
+
+  const FunctionType *FromFn = cast<FunctionType>(CanFrom);
+  FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
+  if (!EInfo.getNoReturn()) return false;
+
+  FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
+  assert(QualType(FromFn, 0).isCanonical());
+  if (QualType(FromFn, 0) != CanTo) return false;
 
-  ResultTy = FromType;
+  ResultTy = ToType;
   return true;
 }