-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Sema] Refactor IsFunctionConversion #139172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
A bunch of uses of IsFunctionConversion don't use the third argument and just make a dummy QualType to pass. This splits IsFunctionConversion into 2 functions, one that just takes 2 arguments and does the check, and one that does the actual conversion using the 3rd argument. Both functions can be const and replace current uses appropriately.
@llvm/pr-subscribers-clang Author: None (PiJoules) ChangesA bunch of uses of IsFunctionConversion don't use the third argument and just make a dummy QualType to pass. This splits IsFunctionConversion into 2 functions, one that just takes 2 arguments and does the check, and one that does the actual conversion using the 3rd argument. Both functions can be const and replace current uses appropriately. Full diff: https://github.com/llvm/llvm-project/pull/139172.diff 6 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c02e827773341..6ea7ee281e14d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10240,8 +10240,13 @@ class Sema final : public SemaBase {
/// Determine whether the conversion from FromType to ToType is a valid
/// conversion that strips "noexcept" or "noreturn" off the nested function
/// type.
- bool IsFunctionConversion(QualType FromType, QualType ToType,
- QualType &ResultTy);
+ bool IsFunctionConversion(QualType FromType, QualType ToType) const;
+
+ /// Same as `IsFunctionConversion`, but if this would return true, it sets
+ /// `ResultTy` to `ToType`.
+ bool TryFunctionConversion(QualType FromType, QualType ToType,
+ QualType &ResultTy) const;
+
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
void DiagnoseUseOfDeletedFunction(SourceLocation Loc, SourceRange Range,
DeclarationName Name,
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index aaa2bb22565e4..c83eab53891ca 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -700,12 +700,11 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
// -- a qualification conversion
// -- a function pointer conversion
bool LifetimeConv;
- QualType Result;
// FIXME: Should we treat the exception as catchable if a lifetime
// conversion is required?
if (IsQualificationConversion(ExceptionType, HandlerType, false,
LifetimeConv) ||
- IsFunctionConversion(ExceptionType, HandlerType, Result))
+ IsFunctionConversion(ExceptionType, HandlerType))
return true;
// -- a standard pointer conversion [...]
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 57135adf714ce..b0e4e3e1c0aa3 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9124,7 +9124,7 @@ static AssignConvertType checkPointerTypesForAssignment(Sema &S,
diag::warn_typecheck_convert_incompatible_function_pointer_strict,
Loc) &&
RHSType->isFunctionPointerType() && LHSType->isFunctionPointerType() &&
- !S.IsFunctionConversion(RHSType, LHSType, RHSType))
+ !S.TryFunctionConversion(RHSType, LHSType, RHSType))
return AssignConvertType::IncompatibleFunctionPointerStrict;
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
@@ -9188,8 +9188,7 @@ static AssignConvertType checkPointerTypesForAssignment(Sema &S,
return AssignConvertType::IncompatibleFunctionPointer;
return AssignConvertType::IncompatiblePointer;
}
- if (!S.getLangOpts().CPlusPlus &&
- S.IsFunctionConversion(ltrans, rtrans, ltrans))
+ if (!S.getLangOpts().CPlusPlus && S.IsFunctionConversion(ltrans, rtrans))
return AssignConvertType::IncompatibleFunctionPointer;
if (IsInvalidCmseNSCallConversion(S, ltrans, rtrans))
return AssignConvertType::IncompatibleFunctionPointer;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d3ee9989c73ed..e20a41c10ccaa 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1881,8 +1881,15 @@ ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return PerformImplicitConversion(From, ToType, ICS, Action);
}
-bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
- QualType &ResultTy) {
+bool Sema::TryFunctionConversion(QualType FromType, QualType ToType,
+ QualType &ResultTy) const {
+ bool Changed = IsFunctionConversion(FromType, ToType);
+ if (Changed)
+ ResultTy = ToType;
+ return Changed;
+}
+
+bool Sema::IsFunctionConversion(QualType FromType, QualType ToType) const {
if (Context.hasSameUnqualifiedType(FromType, ToType))
return false;
@@ -1993,7 +2000,6 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
assert(QualType(FromFn, 0).isCanonical());
if (QualType(FromFn, 0) != CanTo) return false;
- ResultTy = ToType;
return true;
}
@@ -2232,11 +2238,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// we can sometimes resolve &foo<int> regardless of ToType, so check
// if the type matches (identity) or we are converting to bool
if (!S.Context.hasSameUnqualifiedType(
- S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
- QualType resultTy;
+ S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
// if the function type matches except for [[noreturn]], it's ok
if (!S.IsFunctionConversion(FromType,
- S.ExtractUnqualifiedFunctionType(ToType), resultTy))
+ S.ExtractUnqualifiedFunctionType(ToType)))
// otherwise, only a boolean conversion is standard
if (!ToType->isBooleanType())
return false;
@@ -2476,7 +2481,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// The third conversion can be a function pointer conversion or a
// qualification conversion (C++ [conv.fctptr], [conv.qual]).
bool ObjCLifetimeConversion;
- if (S.IsFunctionConversion(FromType, ToType, FromType)) {
+ if (S.TryFunctionConversion(FromType, ToType, FromType)) {
// Function pointer conversions (removing 'noexcept') including removal of
// 'noreturn' (Clang extension).
SCS.Third = ICK_Function_Conversion;
@@ -5033,7 +5038,6 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// Check for standard conversions we can apply to pointers: derived-to-base
// conversions, ObjC pointer conversions, and function pointer conversions.
// (Qualification conversions are checked last.)
- QualType ConvertedT2;
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (isCompleteType(Loc, OrigT2) &&
@@ -5044,7 +5048,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
Conv |= ReferenceConversions::ObjC;
else if (UnqualT2->isFunctionType() &&
- IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
+ IsFunctionConversion(UnqualT2, UnqualT1)) {
Conv |= ReferenceConversions::Function;
// No need to check qualifiers; function types don't have them.
return Ref_Compatible;
@@ -13426,9 +13430,8 @@ class AddressOfFunctionResolver {
private:
bool candidateHasExactlyCorrectType(const FunctionDecl *FD) {
- QualType Discard;
return Context.hasSameUnqualifiedType(TargetFunctionType, FD->getType()) ||
- S.IsFunctionConversion(FD->getType(), TargetFunctionType, Discard);
+ S.IsFunctionConversion(FD->getType(), TargetFunctionType);
}
/// \return true if A is considered a better overload candidate for the
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 94f4c1c46c1fb..2ba69c87d95e3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -7665,9 +7665,8 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(
QualType DestExprType = ParamType.getNonLValueExprType(Context);
if (!Context.hasSameType(RefExpr.get()->getType(), DestExprType)) {
CastKind CK;
- QualType Ignored;
if (Context.hasSimilarType(RefExpr.get()->getType(), DestExprType) ||
- IsFunctionConversion(RefExpr.get()->getType(), DestExprType, Ignored)) {
+ IsFunctionConversion(RefExpr.get()->getType(), DestExprType)) {
CK = CK_NoOp;
} else if (ParamType->isVoidPointerType() &&
RefExpr.get()->getType()->isPointerType()) {
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index ee1ef84fa4fbd..5dc06ebc2a235 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1333,7 +1333,7 @@ bool Sema::isSameOrCompatibleFunctionType(QualType P, QualType A) {
return Context.hasSameType(P, A);
// Noreturn and noexcept adjustment.
- if (QualType AdjustedParam; IsFunctionConversion(P, A, AdjustedParam))
+ if (QualType AdjustedParam; TryFunctionConversion(P, A, AdjustedParam))
P = AdjustedParam;
// FIXME: Compatible calling conventions.
@@ -3732,8 +3732,7 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
// FIXME: Resolve core issue (no number yet): if the original P is a
// reference type and the transformed A is function type "noexcept F",
// the deduced A can be F.
- QualType Tmp;
- if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA, Tmp))
+ if (A->isFunctionType() && S.IsFunctionConversion(A, DeducedA))
return TemplateDeductionResult::Success;
Qualifiers AQuals = A.getQualifiers();
@@ -3770,11 +3769,10 @@ CheckOriginalCallArgDeduction(Sema &S, TemplateDeductionInfo &Info,
// Also allow conversions which merely strip __attribute__((noreturn)) from
// function types (recursively).
bool ObjCLifetimeConversion = false;
- QualType ResultTy;
if ((A->isAnyPointerType() || A->isMemberPointerType()) &&
(S.IsQualificationConversion(A, DeducedA, false,
ObjCLifetimeConversion) ||
- S.IsFunctionConversion(A, DeducedA, ResultTy)))
+ S.IsFunctionConversion(A, DeducedA)))
return TemplateDeductionResult::Success;
// - If P is a class and P has the form simple-template-id, then the
|
A bunch of uses of IsFunctionConversion don't use the third argument and just make a dummy QualType to pass. This splits IsFunctionConversion into 2 functions, one that just takes 2 arguments and does the check, and one that does the actual conversion using the 3rd argument. Both functions can be const and replace current uses appropriately.