[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