From: Ronald Wampler Date: Sun, 19 Apr 2020 02:23:21 +0000 (-0400) Subject: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides X-Git-Tag: llvmorg-12-init~6181 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4b53495c4ba2ba410f6383f9c57593e838ec0d57;p=platform%2Fupstream%2Fllvm.git 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 --- diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index eba672d..74a4fd8 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(NewFD)) { - ActOnConversionDeclarator(Conversion); } else if (auto *Guide = dyn_cast(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(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 935ac93..3f1121c 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()) @@ -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 1486abe..fdd603c 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ public: 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 {