summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-10-16 17:54:23 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-10-16 17:54:23 +0000
commit3c4f8d2e96c4b83108bfc48bfdaf2b6d5ebbd6bf (patch)
treeab5b37c2e879b528275ff0b16a71a710d4acd949 /clang/lib/Sema/SemaOverload.cpp
parente3a9a676f9e3000662c05ff35a3b4312e04b5ee2 (diff)
downloadbcm5719-llvm-3c4f8d2e96c4b83108bfc48bfdaf2b6d5ebbd6bf.tar.gz
bcm5719-llvm-3c4f8d2e96c4b83108bfc48bfdaf2b6d5ebbd6bf.zip
P0012R1: Make exception specifications be part of the type system. This
implements the bulk of the change (modifying the type system to include exception specifications), but not all the details just yet. llvm-svn: 284337
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp68
1 files changed, 54 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 082a6f98ef2..460e53fc261 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -150,7 +150,7 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
"Lvalue-to-rvalue",
"Array-to-pointer",
"Function-to-pointer",
- "Noreturn adjustment",
+ "Function pointer conversion",
"Qualification",
"Integral promotion",
"Floating point promotion",
@@ -1390,13 +1390,15 @@ 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.
-bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
+/// conversion that strips "noexcept" or "noreturn" off the nested function
+/// type.
+bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
QualType &ResultTy) {
if (Context.hasSameUnqualifiedType(FromType, ToType))
return false;
// Permit the conversion F(t __attribute__((noreturn))) -> F(t)
+ // or F(t noexcept) -> F(t)
// where F adds one of the following at most once:
// - a pointer
// - a member pointer
@@ -1425,11 +1427,37 @@ bool Sema::IsNoReturnConversion(QualType FromType, QualType ToType,
return false;
}
- const FunctionType *FromFn = cast<FunctionType>(CanFrom);
- FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
- if (!EInfo.getNoReturn()) return false;
+ const auto *FromFn = cast<FunctionType>(CanFrom);
+ FunctionType::ExtInfo FromEInfo = FromFn->getExtInfo();
+
+ const auto *ToFn = dyn_cast<FunctionProtoType>(CanTo);
+ FunctionType::ExtInfo ToEInfo = ToFn->getExtInfo();
+
+ bool Changed = false;
+
+ // Drop 'noreturn' if not present in target type.
+ if (FromEInfo.getNoReturn() && !ToEInfo.getNoReturn()) {
+ FromFn = Context.adjustFunctionType(FromFn, FromEInfo.withNoReturn(false));
+ Changed = true;
+ }
+
+ // Drop 'noexcept' if not present in target type.
+ if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) {
+ const auto *ToFPT = dyn_cast<FunctionProtoType>(ToFn);
+ if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) {
+ FromFn = cast<FunctionType>(
+ Context.getFunctionType(FromFPT->getReturnType(),
+ FromFPT->getParamTypes(),
+ FromFPT->getExtProtoInfo().withExceptionSpec(
+ FunctionProtoType::ExceptionSpecInfo()))
+ .getTypePtr());
+ Changed = true;
+ }
+ }
+
+ if (!Changed)
+ return false;
- FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false));
assert(QualType(FromFn, 0).isCanonical());
if (QualType(FromFn, 0) != CanTo) return false;
@@ -1534,7 +1562,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 (!S.IsNoReturnConversion(FromType,
+ if (!S.IsFunctionConversion(FromType,
S.ExtractUnqualifiedFunctionType(ToType), resultTy))
// otherwise, only a boolean conversion is standard
if (!ToType->isBooleanType())
@@ -1727,9 +1755,10 @@ 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 (S.IsNoReturnConversion(FromType, ToType, FromType)) {
- // Treat a conversion that strips "noreturn" as an identity conversion.
- SCS.Second = ICK_NoReturn_Adjustment;
+ } else if (S.IsFunctionConversion(FromType, ToType, FromType)) {
+ // Function pointer conversions (removing 'noexcept') including removal of
+ // 'noreturn' (Clang extension).
+ SCS.Second = ICK_Function_Conversion;
} else if (IsTransparentUnionStandardConversion(S, From, ToType,
InOverloadResolution,
SCS, CStyle)) {
@@ -2615,7 +2644,8 @@ enum {
ft_parameter_arity,
ft_parameter_mismatch,
ft_return_type,
- ft_qualifer_mismatch
+ ft_qualifer_mismatch,
+ ft_noexcept
};
/// Attempts to get the FunctionProtoType from a Type. Handles
@@ -2715,6 +2745,16 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
return;
}
+ // Handle exception specification differences on canonical type (in C++17
+ // onwards).
+ if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
+ ->isNothrow(Context) !=
+ cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
+ ->isNothrow(Context)) {
+ PDiag << ft_noexcept;
+ return;
+ }
+
// Unable to find a difference, so add no extra info.
PDiag << ft_default;
}
@@ -5096,7 +5136,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
// conversions are fine.
switch (SCS.Second) {
case ICK_Identity:
- case ICK_NoReturn_Adjustment:
+ case ICK_Function_Conversion:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
return true;
@@ -10428,7 +10468,7 @@ private:
bool candidateHasExactlyCorrectType(const FunctionDecl *FD) {
QualType Discard;
return Context.hasSameUnqualifiedType(TargetFunctionType, FD->getType()) ||
- S.IsNoReturnConversion(FD->getType(), TargetFunctionType, Discard);
+ S.IsFunctionConversion(FD->getType(), TargetFunctionType, Discard);
}
/// \return true if A is considered a better overload candidate for the
OpenPOWER on IntegriCloud