[clang] 4b53495 - Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
Ronald Wampler via cfe-commits
cfe-commits at lists.llvm.org
Wed May 13 07:35:21 PDT 2020
Author: Ronald Wampler
Date: 2020-05-13T10:34:19-04:00
New Revision: 4b53495c4ba2ba410f6383f9c57593e838ec0d57
URL: https://github.com/llvm/llvm-project/commit/4b53495c4ba2ba410f6383f9c57593e838ec0d57
DIFF: https://github.com/llvm/llvm-project/commit/4b53495c4ba2ba410f6383f9c57593e838ec0d57.diff
LOG: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
Summary: This allows for suppressing warnings about the conversion function never being called if it overrides a virtual function in a base class.
Differential Revision: https://reviews.llvm.org/D78444
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/conversion-function.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index eba672d54cf8..74a4fd8a06de 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10716,9 +10716,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
return Redeclaration;
}
}
- } else if (CXXConversionDecl *Conversion
- = dyn_cast<CXXConversionDecl>(NewFD)) {
- ActOnConversionDeclarator(Conversion);
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) {
if (auto *TD = Guide->getDescribedFunctionTemplate())
CheckDeductionGuideTemplate(TD);
@@ -10747,6 +10744,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
checkThisInStaticMemberFunctionType(Method);
}
+ if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+ ActOnConversionDeclarator(Conversion);
+
// Extra checking for C++ overloaded operators (C++ [over.oper]).
if (NewFD->isOverloadedOperator() &&
CheckOverloadedOperatorDeclaration(NewFD)) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 935ac93e9922..3f1121c0e9b2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10486,15 +10486,12 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
// Make sure we aren't redeclaring the conversion function.
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
-
// C++ [class.conv.fct]p1:
// [...] A conversion function is never used to convert a
// (possibly cv-qualified) object to the (possibly cv-qualified)
// same object type (or a reference to it), to a (possibly
// cv-qualified) base class of that type (or a reference to it),
// or to (possibly cv-qualified) void.
- // FIXME: Suppress this warning if the conversion function ends up being a
- // virtual function that overrides a virtual function in a base class.
QualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
@@ -10502,6 +10499,8 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
/* Suppress diagnostics for instantiations. */;
+ else if (Conversion->size_overridden_methods() != 0)
+ /* Suppress diagnostics for overriding virtual function in a base class. */;
else if (ConvType->isRecordType()) {
ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
if (ConvType == ClassType)
diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp
index 1486abea8c60..fdd603c98f43 100644
--- a/clang/test/SemaCXX/conversion-function.cpp
+++ b/clang/test/SemaCXX/conversion-function.cpp
@@ -62,6 +62,24 @@ class B : public A {
operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}}
};
+class BaseA {};
+class DerivedA;
+
+class BaseB {
+ virtual operator BaseA &() = 0;
+ virtual operator DerivedA &() = 0;
+};
+
+class DerivedA : public BaseA, BaseB {
+ virtual operator BaseA &(); // OK. Overrides BaseB::operatorBaseA&()
+ virtual operator DerivedA &(); // OK. Overrides BaseB::operatorDerivedA&()
+};
+
+class DerivedB : public BaseA {
+ virtual operator DerivedB &(); // expected-warning{{conversion function converting 'DerivedB' to itself will never be used}}
+ virtual operator BaseA &(); // expected-warning{{conversion function converting 'DerivedB' to its base class 'BaseA' will never be used}}
+};
+
// This used to crash Clang.
struct Flip;
struct Flop {
More information about the cfe-commits
mailing list