From 9916cf22ac559501eeb360f98b47333948013667 Mon Sep 17 00:00:00 2001 From: John Bytheway Date: Mon, 4 May 2020 20:49:51 -0400 Subject: [PATCH] Expand localized sorting to cover pair, tuple Warn about comparison or sorting of pairs or tuples where one of the elements is a string. --- .../UseLocalizedSortingCheck.cpp | 48 +++++++++++++++++-- .../test/use-localized-sorting.cpp | 41 ++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp index e72a15d672cbc..1bdaff7b534d8 100644 --- a/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp +++ b/tools/clang-tidy-plugin/UseLocalizedSortingCheck.cpp @@ -33,14 +33,54 @@ namespace tidy namespace cata { -inline bool IsString( QualType T ) +static bool IsStringish( QualType T ); + +static bool IsStringish( const TemplateArgument &Arg ) +{ + switch( Arg.getKind() ) { + case TemplateArgument::Type: + if( IsStringish( Arg.getAsType() ) ) { + return true; + } + break; + case TemplateArgument::Pack: + for( const TemplateArgument &PackArg : Arg.getPackAsArray() ) { + if( IsStringish( PackArg ) ) { + return true; + } + } + break; + default: + break; + } + return false; +} + +static bool IsStringish( QualType T ) { const TagDecl *TTag = T.getTypePtr()->getAsTagDecl(); if( !TTag ) { return false; } StringRef Name = TTag->getName(); - return Name == "basic_string"; + if( Name == "basic_string" ) { + return true; + } + if( Name == "pair" || Name == "tuple" ) { + const ClassTemplateSpecializationDecl *SpecDecl = + dyn_cast( TTag ); + if( !SpecDecl ) { + fprintf( stderr, "Not a spec: %s\n", TTag->getKindName().str().c_str() ); + return false; + } + const TemplateArgumentList &Args = SpecDecl->getTemplateArgs(); + for( const TemplateArgument &Arg : Args.asArray() ) { + if( IsStringish( Arg ) ) { + return true; + } + } + } + return false; } void UseLocalizedSortingCheck::registerMatchers( MatchFinder *Finder ) @@ -81,7 +121,7 @@ static void CheckOpCall( UseLocalizedSortingCheck &Check, const MatchFinder::Mat return; } - if( !IsString( *Arg0Type ) ) { + if( !IsStringish( *Arg0Type ) ) { return; } @@ -123,7 +163,7 @@ static void CheckSortCall( UseLocalizedSortingCheck &Check, const MatchFinder::M ValueType = *BoundValueType; } - if( !IsString( ValueType ) ) { + if( !IsStringish( ValueType ) ) { return; } diff --git a/tools/clang-tidy-plugin/test/use-localized-sorting.cpp b/tools/clang-tidy-plugin/test/use-localized-sorting.cpp index 1ecea6e77c218..5914548437b96 100644 --- a/tools/clang-tidy-plugin/test/use-localized-sorting.cpp +++ b/tools/clang-tidy-plugin/test/use-localized-sorting.cpp @@ -24,6 +24,18 @@ bool operator<( const std::basic_string &lhs, template void sort( RandomIt first, RandomIt last ); +template +struct pair; + +template< class T1, class T2 > +bool operator<( const std::pair &lhs, const std::pair &rhs ); + +template< class... Types > +class tuple; + +template +bool operator<( const tuple &lhs, + const tuple &rhs ); } template @@ -48,6 +60,35 @@ bool f1( const NonString &l, const NonString &r ) return l < r; } +bool f2( const std::pair &l, const std::pair &r ) +{ + return l < r; + // CHECK-MESSAGES: warning: Raw comparison of 'const std::pair' (aka 'const pair >'). For UI purposes please use localized_compare from translations.h. [cata-use-localized-sorting] +} + +bool f3( const std::pair &l, const std::pair &r ) +{ + return l < r; +} + +bool f4( const std::tuple &l, const std::tuple &r ) +{ + return l < r; + // CHECK-MESSAGES: warning: Raw comparison of 'const std::tuple' (aka 'const tuple >'). For UI purposes please use localized_compare from translations.h. [cata-use-localized-sorting] +} + +bool f5( const std::tuple &l, const std::tuple &r ) +{ + return l < r; +} + +bool f4( const std::tuple> &l, + const std::tuple> &r ) +{ + return l < r; + // CHECK-MESSAGES: warning: Raw comparison of 'const std::tuple >' (aka 'const tuple > >'). For UI purposes please use localized_compare from translations.h. [cata-use-localized-sorting] +} + bool sort0( const std::string *start, const std::string *end ) { std::sort( start, end );