diff --git a/clang-tools-extra/clang-tidy/readability/ConstReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/readability/ConstReturnTypeCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/ConstReturnTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ConstReturnTypeCheck.cpp @@ -53,6 +53,18 @@ namespace { +AST_MATCHER(QualType, isLocalConstQualified) { + return Node.isLocalConstQualified(); +} + +AST_MATCHER(QualType, isTypeOfType) { + return isa(Node.getTypePtr()); +} + +AST_MATCHER(QualType, isTypeOfExprType) { + return isa(Node.getTypePtr()); +} + struct CheckResult { // Source range of the relevant `const` token in the definition being checked. CharSourceRange ConstRange; @@ -95,10 +107,14 @@ void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) { // Find all function definitions for which the return types are `const` - // qualified. + // qualified, ignoring decltype types. + auto NonLocalConstType = qualType( + unless(isLocalConstQualified()), + anyOf(decltypeType(), autoType(), isTypeOfType(), isTypeOfExprType())); Finder->addMatcher( - functionDecl(returns(isConstQualified()), - anyOf(isDefinition(), cxxMethodDecl(isPure()))) + functionDecl( + returns(allOf(isConstQualified(), unless(NonLocalConstType))), + anyOf(isDefinition(), cxxMethodDecl(isPure()))) .bind("func"), this); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-const-return-type.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-const-return-type.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/readability-const-return-type.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-const-return-type.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s readability-const-return-type %t +// RUN: %check_clang_tidy -std=c++14 %s readability-const-return-type %t // p# = positive test // n# = negative test @@ -285,3 +285,40 @@ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness // CHECK-NOT-FIXES: int getC() { return 1; } }; + +// Don't warn about const auto types, because it may be impossible to make them non-const +// without a significant semantics change. Since `auto` drops cv-qualifiers, +// tests check `decltype(auto)`. +decltype(auto) n16() { + static const int i = 42; + return i; +} + +// Don't warn about `decltype()` types +const int n17i = 1; +decltype(n17i) n17() { + return 17; +} + +// Do warn when on decltype types with the local const qualifier +// `const decltype(auto)` won't compile, so check only `const decltype()` +const decltype(n17i) n18() { + // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const decltype(n17i) + // CHECK-FIXES: decltype(n17i) n18() { + return 18; +} + +// `volatile` modifier doesn't affect the checker +volatile decltype(n17i) n19() { + return 19; +} + +// Don't warn about `__typeof__()` types +__typeof__(n17i) n20() { + return 20; +} + +// Don't warn about `__typeof__(type)` types +__typeof__(const int) n21() { + return 21; +}