[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
This revision was automatically updated to reflect the committed changes. Closed by commit rG4b53495c4ba2: Perform ActOnConversionDeclarator after looking for any virtual functions it… (authored by rdwampler). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D78444/new/ https://reviews.llvm.org/D78444 Files: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/conversion-function.cpp Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -10486,15 +10486,12 @@ // 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 @@ 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) Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -10716,9 +10716,6 @@ 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 @@ checkThisInStaticMemberFunctionType(Method); } +if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) + ActOnConversionDeclarator(Conversion); + // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) { Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp
[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
rdwampler updated this revision to Diff 263466. rdwampler added a comment. Fixed indentation. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D78444/new/ https://reviews.llvm.org/D78444 Files: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/conversion-function.cpp Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -10486,15 +10486,12 @@ // 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 @@ 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) Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -10716,9 +10716,6 @@ 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 @@ checkThisInStaticMemberFunctionType(Method); } +if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) + ActOnConversionDeclarator(Conversion); + // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && CheckOverloadedOperatorDeclaration(NewFD)) { Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -10486,15 +1
[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
rjmccall added a comment. LGTM with a minor fix. Comment at: clang/lib/Sema/SemaDecl.cpp:10745 +if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) + ActOnConversionDeclarator(Conversion); Indentation is off. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D78444/new/ https://reviews.llvm.org/D78444 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
rdwampler added a comment. Ping. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D78444/new/ https://reviews.llvm.org/D78444 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
rdwampler updated this revision to Diff 258613. rdwampler added a comment. changed to check it overrides a virtual function in a base class and not just virtual. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D78444/new/ https://reviews.llvm.org/D78444 Files: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/conversion-function.cpp Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -10486,15 +10486,12 @@ // 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 @@ 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) Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -10713,9 +10713,6 @@ 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); @@ -10743,6 +10740,9 @@ if (Method->isStatic()) checkThisInStaticMemberFunctionType(Method); } + +if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) + ActOnConversionDeclarator(Conversion); // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,24 @@ 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 { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX
[PATCH] D78444: Perform ActOnConversionDeclarator after looking for any virtual functions it overrides
rdwampler created this revision. rdwampler added reviewers: saar.raz, aaron.ballman, doug.gregor, rsmith. rdwampler added a project: clang. Herald added subscribers: cfe-commits, dexonsmith. This allows for suppressing warnings about the conversion function never being called if it overrides a virtual function in a base class. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D78444 Files: clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/SemaCXX/conversion-function.cpp Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,27 @@ operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}} }; +class DerivedB; + +class BaseA { +public: + virtual operator BaseA&() = 0; //OK. Virtual function + virtual operator DerivedB&() = 0; //OK. Virtual function + virtual operator const void() = 0; //OK. Virtual function +}; + +class DerivedB : public BaseA { +#if __cplusplus >= 201103L +operator BaseA&() override; //OK. Overrides virtual function in BaseA +operator DerivedB&() override; //OK. Overrides virtual function BaseA +operator const void() override; //OK. Overrides virtual function BaseA +#else +virtual operator BaseA&(); //OK. Overrides virtual function in BaseA +virtual operator DerivedB&(); //OK. Overrides virtual function BaseA +virtual operator const void(); //OK. Overrides virtual function BaseA +#endif +}; + // This used to crash Clang. struct Flip; struct Flop { Index: clang/lib/Sema/SemaDeclCXX.cpp === --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -10486,15 +10486,12 @@ // 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 @@ if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) /* Suppress diagnostics for instantiations. */; + else if(Conversion->isVirtual()) +/*Suppress diagnostics if the function is virtual*/; else if (ConvType->isRecordType()) { ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); if (ConvType == ClassType) Index: clang/lib/Sema/SemaDecl.cpp === --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -10713,9 +10713,6 @@ 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); @@ -10743,6 +10740,9 @@ if (Method->isStatic()) checkThisInStaticMemberFunctionType(Method); } + +if (CXXConversionDecl *Conversion = dyn_cast(NewFD)) + ActOnConversionDeclarator(Conversion); // Extra checking for C++ overloaded operators (C++ [over.oper]). if (NewFD->isOverloadedOperator() && Index: clang/test/SemaCXX/conversion-function.cpp === --- clang/test/SemaCXX/conversion-function.cpp +++ clang/test/SemaCXX/conversion-function.cpp @@ -62,6 +62,27 @@ operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}} }; +class DerivedB; + +class BaseA { +public: + virtual operator BaseA&() = 0; //OK. Virtual function + virtual operator DerivedB&() = 0; //OK. Virtual function + virtual operator const void() = 0; //OK. Virtual function +}; + +class DerivedB : public BaseA { +#if __cplusplus >= 201103L +operator BaseA&() override; //OK. Overrides virtual function in BaseA +operator DerivedB&() override; //OK. Overrides virtual function BaseA +operator const void() override; //OK. Overrides virtual function BaseA +#else +virtual operator BaseA&(); //OK. Overrides virtual function in BaseA +virtual operator Derive