aaron.ballman created this revision. aaron.ballman added reviewers: congliu, alexfh. aaron.ballman added a subscriber: cfe-commits.
Special member functions don't always have names, and so calling FunctionDecl::getName() can cause assertions. This patch addresses the issue by assuming any such function needs to have the rest of its signature checked, regardless of the function name. The test case was pulled from MSVC's STL headers, where this check is causing failed assertions. http://reviews.llvm.org/D16377 Files: clang-tidy/misc/VirtualNearMissCheck.cpp test/clang-tidy/misc-virtual-near-miss.cpp Index: test/clang-tidy/misc-virtual-near-miss.cpp =================================================================== --- test/clang-tidy/misc-virtual-near-miss.cpp +++ test/clang-tidy/misc-virtual-near-miss.cpp @@ -63,3 +63,20 @@ private: void funk(); // Should not warn: access qualifers don't match. }; + +namespace { +// Ensure this code does not crash due to special member functions. +class _Facet_base { +public: + virtual ~_Facet_base() noexcept {} +}; + +class facet : public _Facet_base { +protected: + virtual ~facet() noexcept {} + +public: + facet(const facet&) = delete; + facet& operator=(const facet&) = delete; +}; +} Index: clang-tidy/misc/VirtualNearMissCheck.cpp =================================================================== --- clang-tidy/misc/VirtualNearMissCheck.cpp +++ clang-tidy/misc/VirtualNearMissCheck.cpp @@ -244,8 +244,15 @@ if (isOverriddenByDerivedClass(BaseMD, DerivedRD)) continue; + // If the function has an identifier for a name, then use that + // identifier to determine the edit distance. If the function is a + // special member function without an identifier, assume the edit + // distance is nonzero to determine whether the signature is a near + // miss or not. unsigned EditDistance = - BaseMD->getName().edit_distance(DerivedMD->getName()); + BaseMD->getDeclName().isIdentifier() + ? BaseMD->getName().edit_distance(DerivedMD->getName()) + : 1; if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) { if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) { // A "virtual near miss" is found.
Index: test/clang-tidy/misc-virtual-near-miss.cpp =================================================================== --- test/clang-tidy/misc-virtual-near-miss.cpp +++ test/clang-tidy/misc-virtual-near-miss.cpp @@ -63,3 +63,20 @@ private: void funk(); // Should not warn: access qualifers don't match. }; + +namespace { +// Ensure this code does not crash due to special member functions. +class _Facet_base { +public: + virtual ~_Facet_base() noexcept {} +}; + +class facet : public _Facet_base { +protected: + virtual ~facet() noexcept {} + +public: + facet(const facet&) = delete; + facet& operator=(const facet&) = delete; +}; +} Index: clang-tidy/misc/VirtualNearMissCheck.cpp =================================================================== --- clang-tidy/misc/VirtualNearMissCheck.cpp +++ clang-tidy/misc/VirtualNearMissCheck.cpp @@ -244,8 +244,15 @@ if (isOverriddenByDerivedClass(BaseMD, DerivedRD)) continue; + // If the function has an identifier for a name, then use that + // identifier to determine the edit distance. If the function is a + // special member function without an identifier, assume the edit + // distance is nonzero to determine whether the signature is a near + // miss or not. unsigned EditDistance = - BaseMD->getName().edit_distance(DerivedMD->getName()); + BaseMD->getDeclName().isIdentifier() + ? BaseMD->getName().edit_distance(DerivedMD->getName()) + : 1; if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) { if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) { // A "virtual near miss" is found.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits