[clang-tools-extra] r345764 - Implement the readability-const-return-type check.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 31 12:11:38 PDT 2018


Author: aaronballman
Date: Wed Oct 31 12:11:38 2018
New Revision: 345764

URL: http://llvm.org/viewvc/llvm-project?rev=345764&view=rev
Log:
Implement the readability-const-return-type check.

This check flags function top-level const-qualified return types and suggests removing the mostly-superfluous const qualifier where possible.

Patch by Yitzhak Mandelbaum.

Added:
    clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.cpp
    clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/readability-const-return-type.rst
    clang-tools-extra/trunk/test/clang-tidy/readability-const-return-type.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
    clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.cpp
    clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.h
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Wed Oct 31 12:11:38 2018
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
 add_clang_library(clangTidyReadabilityModule
   AvoidConstParamsInDecls.cpp
   BracesAroundStatementsCheck.cpp
+  ConstReturnTypeCheck.cpp
   ContainerSizeEmptyCheck.cpp
   DeleteNullPointerCheck.cpp
   DeletedDefaultCheck.cpp

Added: clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.cpp?rev=345764&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.cpp Wed Oct 31 12:11:38 2018
@@ -0,0 +1,128 @@
+//===--- ConstReturnTypeCheck.cpp - clang-tidy ---------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ConstReturnTypeCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/Optional.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+// Finds the location of the qualifying `const` token in the `FunctionDecl`'s
+// return type. Returns `None` when the return type is not `const`-qualified or
+// `const` does not appear in `Def`'s source like when the type is an alias or a
+// macro.
+static llvm::Optional<Token>
+findConstToRemove(const FunctionDecl *Def,
+                  const MatchFinder::MatchResult &Result) {
+  if (!Def->getReturnType().isLocalConstQualified())
+    return None;
+
+  // Get the begin location for the function name, including any qualifiers
+  // written in the source (for out-of-line declarations). A FunctionDecl's
+  // "location" is the start of its name, so, when the name is unqualified, we
+  // use `getLocation()`.
+  SourceLocation NameBeginLoc = Def->getQualifier()
+                                    ? Def->getQualifierLoc().getBeginLoc()
+                                    : Def->getLocation();
+  // Since either of the locs can be in a macro, use `makeFileCharRange` to be
+  // sure that we have a consistent `CharSourceRange`, located entirely in the
+  // source file.
+  CharSourceRange FileRange = Lexer::makeFileCharRange(
+      CharSourceRange::getCharRange(Def->getBeginLoc(), NameBeginLoc),
+      *Result.SourceManager, Result.Context->getLangOpts());
+
+  if (FileRange.isInvalid())
+    return None;
+
+  return utils::lexer::getConstQualifyingToken(FileRange, *Result.Context,
+                                               *Result.SourceManager);
+}
+
+namespace {
+
+struct CheckResult {
+  // Source range of the relevant `const` token in the definition being checked.
+  CharSourceRange ConstRange;
+
+  // FixItHints associated with the definition being checked.
+  llvm::SmallVector<clang::FixItHint, 4> Hints;
+
+  // Locations of any declarations that could not be fixed.
+  llvm::SmallVector<clang::SourceLocation, 4> DeclLocs;
+};
+
+} // namespace
+
+// Does the actual work of the check.
+static CheckResult checkDef(const clang::FunctionDecl *Def,
+                            const MatchFinder::MatchResult &MatchResult) {
+  CheckResult Result;
+  llvm::Optional<Token> Tok = findConstToRemove(Def, MatchResult);
+  if (!Tok)
+    return Result;
+
+  Result.ConstRange =
+      CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc());
+  Result.Hints.push_back(FixItHint::CreateRemoval(Result.ConstRange));
+
+  // Fix the definition and any visible declarations, but don't warn
+  // seperately for each declaration. Instead, associate all fixes with the
+  // single warning at the definition.
+  for (const FunctionDecl *Decl = Def->getPreviousDecl(); Decl != nullptr;
+       Decl = Decl->getPreviousDecl()) {
+    if (llvm::Optional<Token> T = findConstToRemove(Decl, MatchResult))
+      Result.Hints.push_back(FixItHint::CreateRemoval(
+          CharSourceRange::getCharRange(T->getLocation(), T->getEndLoc())));
+    else
+      // `getInnerLocStart` gives the start of the return type.
+      Result.DeclLocs.push_back(Decl->getInnerLocStart());
+  }
+  return Result;
+}
+
+void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
+  // Find all function definitions for which the return types are `const`
+  // qualified.
+  Finder->addMatcher(
+      functionDecl(returns(isConstQualified()), isDefinition()).bind("func"),
+      this);
+}
+
+void ConstReturnTypeCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Def = Result.Nodes.getNodeAs<FunctionDecl>("func");
+  CheckResult CR = checkDef(Def, Result);
+  {
+    // Clang only supports one in-flight diagnostic at a time. So, delimit the
+    // scope of `Diagnostic` to allow further diagnostics after the scope.  We
+    // use `getInnerLocStart` to get the start of the return type.
+    DiagnosticBuilder Diagnostic =
+        diag(Def->getInnerLocStart(),
+             "return type %0 is 'const'-qualified at the top level, which may "
+             "reduce code readability without improving const correctness")
+        << Def->getReturnType();
+    if (CR.ConstRange.isValid())
+      Diagnostic << CR.ConstRange;
+    for (auto &Hint : CR.Hints)
+      Diagnostic << Hint;
+  }
+  for (auto Loc : CR.DeclLocs)
+    diag(Loc, "could not transform this declaration", DiagnosticIDs::Note);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang

Added: clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.h?rev=345764&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/ConstReturnTypeCheck.h Wed Oct 31 12:11:38 2018
@@ -0,0 +1,35 @@
+//===--- ConstReturnTypeCheck.h - clang-tidy --------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONSTRETURNTYPECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONSTRETURNTYPECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// For any function whose return type is const-qualified, suggests removal of
+/// the `const` qualifier from that return type.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-const-return-type.html
+class ConstReturnTypeCheck : public ClangTidyCheck {
+ public:
+  using ClangTidyCheck::ClangTidyCheck;
+  void registerMatchers(ast_matchers::MatchFinder* finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult& result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONSTRETURNTYPECHECK_H

Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Wed Oct 31 12:11:38 2018
@@ -12,6 +12,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "AvoidConstParamsInDecls.h"
 #include "BracesAroundStatementsCheck.h"
+#include "ConstReturnTypeCheck.h"
 #include "ContainerSizeEmptyCheck.h"
 #include "DeleteNullPointerCheck.h"
 #include "DeletedDefaultCheck.h"
@@ -52,6 +53,8 @@ public:
         "readability-avoid-const-params-in-decls");
     CheckFactories.registerCheck<BracesAroundStatementsCheck>(
         "readability-braces-around-statements");
+    CheckFactories.registerCheck<ConstReturnTypeCheck>(
+        "readability-const-return-type");
     CheckFactories.registerCheck<ContainerSizeEmptyCheck>(
         "readability-container-size-empty");
     CheckFactories.registerCheck<DeleteNullPointerCheck>(

Modified: clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.cpp?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.cpp Wed Oct 31 12:11:38 2018
@@ -92,6 +92,34 @@ bool rangeContainsExpansionsOrDirectives
 
   return false;
 }
+
+llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
+                                              const ASTContext &Context,
+                                              const SourceManager &SM) {
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
+  StringRef File = SM.getBufferData(LocInfo.first);
+  Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
+                 File.begin(), File.data() + LocInfo.second, File.end());
+  llvm::Optional<Token> FirstConstTok;
+  Token LastTokInRange;
+  Token Tok;
+  while (!RawLexer.LexFromRawLexer(Tok) &&
+         Range.getEnd() != Tok.getLocation() &&
+         !SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
+    if (Tok.is(tok::raw_identifier)) {
+      IdentifierInfo &Info = Context.Idents.get(
+          StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
+      Tok.setIdentifierInfo(&Info);
+      Tok.setKind(Info.getTokenID());
+    }
+    if (Tok.is(tok::kw_const) && !FirstConstTok)
+      FirstConstTok = Tok;
+    LastTokInRange = Tok;
+  }
+  // If the last token in the range is a `const`, then it const qualifies the
+  // type.  Otherwise, the first `const` token, if any, is the qualifier.
+  return LastTokInRange.is(tok::kw_const) ? LastTokInRange : FirstConstTok;
+}
 } // namespace lexer
 } // namespace utils
 } // namespace tidy

Modified: clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.h?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.h (original)
+++ clang-tools-extra/trunk/clang-tidy/utils/LexerUtils.h Wed Oct 31 12:11:38 2018
@@ -82,6 +82,14 @@ bool rangeContainsExpansionsOrDirectives
                                          const SourceManager &SM,
                                          const LangOptions &LangOpts);
 
+/// Assuming that ``Range`` spans a const-qualified type, returns the ``const``
+/// token in ``Range`` that is responsible for const qualification. ``Range``
+/// must be valid with respect to ``SM``.  Returns ``None`` if no ``const``
+/// tokens are found.
+llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
+                                              const ASTContext &Context,
+                                              const SourceManager &SM);
+
 } // namespace lexer
 } // namespace utils
 } // namespace tidy

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Oct 31 12:11:38 2018
@@ -142,6 +142,12 @@ Improvements to clang-tidy
   Detects local variable declarations declaring more than one variable and
   tries to refactor the code to one statement per declaration.
 
+- New :doc:`readability-const-return-type
+  <clang-tidy/checks/readability-const-return-type>` check.
+
+  Checks for functions with a ``const``-qualified return type and recommends
+  removal of the ``const`` keyword.
+
 - New :doc:`readability-magic-numbers
   <clang-tidy/checks/readability-magic-numbers>` check.
 

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=345764&r1=345763&r2=345764&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Oct 31 12:11:38 2018
@@ -225,6 +225,7 @@ Clang-Tidy Checks
    portability-simd-intrinsics
    readability-avoid-const-params-in-decls
    readability-braces-around-statements
+   readability-const-return-type
    readability-container-size-empty
    readability-delete-null-pointer
    readability-deleted-default

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/readability-const-return-type.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/readability-const-return-type.rst?rev=345764&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/readability-const-return-type.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/readability-const-return-type.rst Wed Oct 31 12:11:38 2018
@@ -0,0 +1,26 @@
+.. title:: clang-tidy - readability-const-return-type
+
+readability-const-return-type
+=============================
+
+Checks for functions with a ``const``-qualified return type and recommends
+removal of the ``const`` keyword. Such use of `const` is usually superfluous,
+and can prevent valuable compiler optimizations.  Does not (yet) fix trailing
+return types.
+
+Examples:
+
+.. code-block:: c++
+		
+  const int foo();
+  const Clazz foo();
+  Clazz *const foo();
+
+Note that this applies strictly to top-level qualification, which excludes
+pointers or references to const values. For example, these are fine:
+
+.. code-block:: c++
+
+   const int* foo();
+   const int& foo();
+   const Clazz* foo();

Added: clang-tools-extra/trunk/test/clang-tidy/readability-const-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-const-return-type.cpp?rev=345764&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-const-return-type.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-const-return-type.cpp Wed Oct 31 12:11:38 2018
@@ -0,0 +1,227 @@
+// RUN: %check_clang_tidy %s readability-const-return-type %t -- -- -isystem
+
+//  p# = positive test
+//  n# = negative test
+
+#include <type_traits>
+
+const int p1() {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qualified at the top level, which may reduce code readability without improving const correctness
+// CHECK-FIXES: int p1() {
+  return 1;
+}
+
+const int p15();
+// CHECK-FIXES: int p15();
+
+template <typename T>
+const int p31(T v) { return 2; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+// CHECK-FIXES: int p31(T v) { return 2; }
+
+// We detect const-ness even without instantiating T.
+template <typename T>
+const T p32(T t) { return t; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const T' is 'const'-qual
+// CHECK-FIXES: T p32(T t) { return t; }
+
+// However, if the return type is itself a template instantiation, Clang does
+// not consider it const-qualified without knowing `T`.
+template <typename T>
+typename std::add_const<T>::type n15(T v) { return v; }
+
+template <typename A>
+class Klazz {
+public:
+  Klazz(A) {}
+};
+
+class Clazz {
+ public:
+  Clazz *const p2() {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'Clazz *const' is 'co
+    // CHECK-FIXES: Clazz *p2() {
+    return this;
+  }
+
+  Clazz *const p3();
+  // CHECK-FIXES: Clazz *p3();
+
+  const int p4() const {
+    // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const
+    // CHECK-FIXES: int p4() const {
+    return 4;
+  }
+
+  const Klazz<const int>* const p5() const;
+  // CHECK-FIXES: const Klazz<const int>* p5() const;
+
+  const Clazz operator++(int x) {  //  p12
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz' is 'const
+  // CHECK-FIXES: Clazz operator++(int x) {
+  }
+
+  struct Strukt {
+    int i;
+  };
+
+  const Strukt p6() {}
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
+  // CHECK-FIXES: Strukt p6() {}
+
+  // No warning is emitted here, because this is only the declaration.  The
+  // warning will be associated with the definition, below.
+  const Strukt* const p7();
+  // CHECK-FIXES: const Strukt* p7();
+
+  // const-qualifier is the first `const` token, but not the first token.
+  static const int p8() {}
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const int' is 'const'-
+  // CHECK-FIXES: static int p8() {}
+
+  static const Strukt p9() {}
+  // CHECK-MESSAGES: [[@LINE-1]]:3: warning: return type 'const Clazz::Strukt' i
+  // CHECK-FIXES: static Strukt p9() {}
+
+  int n0() const { return 0; }
+  const Klazz<const int>& n11(const Klazz<const int>) const;
+};
+
+Clazz *const Clazz::p3() {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
+  // CHECK-FIXES: Clazz *Clazz::p3() {
+  return this;
+}
+
+const Klazz<const int>* const Clazz::p5() const {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
+// CHECK-FIXES: const Klazz<const int>* Clazz::p5() const {}
+
+const Clazz::Strukt* const Clazz::p7() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz::Strukt *con
+// CHECK-FIXES: const Clazz::Strukt* Clazz::p7() {}
+
+Clazz *const p10();
+// CHECK-FIXES: Clazz *p10();
+
+Clazz *const p10() {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'Clazz *const' is 'cons
+  // CHECK-FIXES: Clazz *p10() {
+  return new Clazz();
+}
+
+const Clazz bar;
+const Clazz *const p11() {
+  // CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Clazz *const' is
+  // CHECK-FIXES: const Clazz *p11() {
+  return &bar;
+}
+
+const Klazz<const int> p12() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int>'
+// CHECK-FIXES: Klazz<const int> p12() {}
+
+const Klazz<const int>* const p13() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const int> *
+// CHECK-FIXES: const Klazz<const int>* p13() {}
+
+// re-declaration of p15.
+const int p15();
+// CHECK-FIXES: int p15();
+
+const int p15() {
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
+// CHECK-FIXES: int p15() {
+  return 0;
+}
+
+// Exercise the lexer.
+
+const /* comment */ /* another comment*/ int p16() { return 0; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning:
+// CHECK-FIXES: /* comment */ /* another comment*/ int p16() { return 0; }
+
+/* comment */ const
+// CHECK-MESSAGES: [[@LINE-1]]:15: warning:
+// CHECK-FIXES: /* comment */
+// more
+/* another comment*/ int p17() { return 0; }
+
+// Test cases where the `const` token lexically is hidden behind some form of
+// indirection.
+
+#define CONSTINT const int
+CONSTINT p18() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+
+#define CONST const
+CONST int p19() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+
+using ty = const int;
+ty p21() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty' (aka 'const int') is
+
+typedef const int ty2;
+ty2 p22() {}
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'ty2' (aka 'const int') i
+
+// Declaration uses a macro, while definition doesn't.  In this case, we won't
+// fix the declaration, and will instead issue a warning.
+CONST int p23();
+// CHECK-NOTE: [[@LINE-1]]:1: note: could not transform this declaration
+
+const int p23();
+// CHECK-FIXES: int p23();
+
+const int p23() { return 3; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+// CHECK-FIXES: int p23() { return 3; }
+
+int const p24() { return 3; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+// CHECK-FIXES: int p24() { return 3; }
+
+int const * const p25(const int* p) { return p; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int *const' is 'co
+// CHECK-FIXES: int const * p25(const int* p) { return p; }
+
+// We cannot (yet) fix instances that use trailing return types, but we can
+// warn.
+auto p26() -> const int { return 3; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+auto p27() -> int const { return 3; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const int' is 'const'-qu
+
+std::add_const<int>::type p28() { return 3; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'std::add_const<int>::typ
+
+// p29, p30 are based on
+// llvm/projects/test-suite/SingleSource/Benchmarks/Misc-C++-EH/spirit.cpp:
+template <class T>
+Klazz<T const> const p29(T const &t) { return {}; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const T>' is
+// CHECK-FIXES: Klazz<T const> p29(T const &t) { return {}; }
+
+Klazz<char const *> const p30(char const *s) { return s; }
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: return type 'const Klazz<const char *
+// CHECK-FIXES: Klazz<char const *> p30(char const *s) { return s; }
+
+const int n1 = 1;
+const Clazz n2 = Clazz();
+const Clazz* n3 = new Clazz();
+Clazz *const n4 = new Clazz();
+const Clazz *const n5 = new Clazz();
+constexpr int n6 = 6;
+constexpr int n7() { return 8; }
+const int eight = 8;
+constexpr const int* n8() { return &eight; }
+Klazz<const int> n9();
+const Klazz<const int>* n10();
+const Klazz<const int>& Clazz::n11(const Klazz<const int>) const {}
+
+// Declaration only.
+const int n14();
+
+int **const * n_multiple_ptr();
+int *const & n_pointer_ref();




More information about the cfe-commits mailing list