[clang-tools-extra] r360438 - Recommit r360345 with fixes (was reverted in r360348).
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri May 10 09:24:29 PDT 2019
Author: aaronballman
Date: Fri May 10 09:24:28 2019
New Revision: 360438
URL: http://llvm.org/viewvc/llvm-project?rev=360438&view=rev
Log:
Recommit r360345 with fixes (was reverted in r360348).
Add the modernize-use-trailing-return check to rewrite function signatures to use trailing return types.
Patch by Bernhard Manfred Gruber.
Added:
clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-trailing-return-type.rst
clang-tools-extra/trunk/test/clang-tidy/modernize-use-trailing-return-type.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt?rev=360438&r1=360437&r2=360438&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Fri May 10 09:24:28 2019
@@ -30,6 +30,7 @@ add_clang_library(clangTidyModernizeModu
UseNoexceptCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
+ UseTrailingReturnTypeCheck.cpp
UseTransparentFunctorsCheck.cpp
UseUncaughtExceptionsCheck.cpp
UseUsingCheck.cpp
Modified: clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp?rev=360438&r1=360437&r2=360438&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Fri May 10 09:24:28 2019
@@ -35,6 +35,7 @@
#include "UseNoexceptCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
+#include "UseTrailingReturnTypeCheck.h"
#include "UseTransparentFunctorsCheck.h"
#include "UseUncaughtExceptionsCheck.h"
#include "UseUsingCheck.h"
@@ -87,6 +88,8 @@ public:
CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
+ CheckFactories.registerCheck<UseTrailingReturnTypeCheck>(
+ "modernize-use-trailing-return-type");
CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
"modernize-use-transparent-functors");
CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
Added: clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp?rev=360438&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp Fri May 10 09:24:28 2019
@@ -0,0 +1,478 @@
+//===--- UseTrailingReturnTypeCheck.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 "UseTrailingReturnTypeCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+#include <cctype>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+namespace {
+struct UnqualNameVisitor : public RecursiveASTVisitor<UnqualNameVisitor> {
+public:
+ UnqualNameVisitor(const FunctionDecl &F, const SourceManager &SM)
+ : F(F), SM(SM) {}
+
+ bool Collision = false;
+
+ bool shouldWalkTypesOfTypeLocs() const { return false; }
+
+ bool VisitUnqualName(StringRef UnqualName) {
+ // Check for collisions with function arguments.
+ for (ParmVarDecl *Param : F.parameters())
+ if (const IdentifierInfo *Ident = Param->getIdentifier())
+ if (Ident->getName() == UnqualName) {
+ Collision = true;
+ return true;
+ }
+ return false;
+ }
+
+ bool TraverseTypeLoc(TypeLoc TL, bool Elaborated = false) {
+ if (TL.isNull())
+ return true;
+
+ if (!Elaborated) {
+ switch (TL.getTypeLocClass()) {
+ case TypeLoc::Record:
+ if (VisitUnqualName(
+ TL.getAs<RecordTypeLoc>().getTypePtr()->getDecl()->getName()))
+ return false;
+ break;
+ case TypeLoc::Enum:
+ if (VisitUnqualName(
+ TL.getAs<EnumTypeLoc>().getTypePtr()->getDecl()->getName()))
+ return false;
+ break;
+ case TypeLoc::TemplateSpecialization:
+ if (VisitUnqualName(TL.getAs<TemplateSpecializationTypeLoc>()
+ .getTypePtr()
+ ->getTemplateName()
+ .getAsTemplateDecl()
+ ->getName()))
+ return false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return RecursiveASTVisitor<UnqualNameVisitor>::TraverseTypeLoc(TL);
+ }
+
+ // Replace the base method in order to call ower own
+ // TraverseTypeLoc().
+ bool TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return TraverseTypeLoc(TL.getUnqualifiedLoc());
+ }
+
+ // Replace the base version to inform TraverseTypeLoc that the type is
+ // elaborated.
+ bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc TL) {
+ if (TL.getQualifierLoc() &&
+ !TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()))
+ return false;
+ return TraverseTypeLoc(TL.getNamedTypeLoc(), true);
+ }
+
+ bool VisitDeclRefExpr(DeclRefExpr *S) {
+ DeclarationName Name = S->getNameInfo().getName();
+ return S->getQualifierLoc() || !Name.isIdentifier() ||
+ !VisitUnqualName(Name.getAsIdentifierInfo()->getName());
+ }
+
+private:
+ const FunctionDecl &F;
+ const SourceManager &SM;
+};
+} // namespace
+
+constexpr llvm::StringLiteral Message =
+ "use a trailing return type for this function";
+
+static SourceLocation expandIfMacroId(SourceLocation Loc,
+ const SourceManager &SM) {
+ if (Loc.isMacroID())
+ Loc = expandIfMacroId(SM.getImmediateExpansionRange(Loc).getBegin(), SM);
+ assert(!Loc.isMacroID() &&
+ "SourceLocation must not be a macro ID after recursive expansion");
+ return Loc;
+}
+
+SourceLocation UseTrailingReturnTypeCheck::findTrailingReturnTypeSourceLocation(
+ const FunctionDecl &F, const FunctionTypeLoc &FTL, const ASTContext &Ctx,
+ const SourceManager &SM, const LangOptions &LangOpts) {
+ // We start with the location of the closing parenthesis.
+ SourceRange ExceptionSpecRange = F.getExceptionSpecSourceRange();
+ if (ExceptionSpecRange.isValid())
+ return Lexer::getLocForEndOfToken(ExceptionSpecRange.getEnd(), 0, SM,
+ LangOpts);
+
+ // If the function argument list ends inside of a macro, it is dangerous to
+ // start lexing from here - bail out.
+ SourceLocation ClosingParen = FTL.getRParenLoc();
+ if (ClosingParen.isMacroID())
+ return {};
+
+ SourceLocation Result =
+ Lexer::getLocForEndOfToken(ClosingParen, 0, SM, LangOpts);
+
+ // Skip subsequent CV and ref qualifiers.
+ std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(Result);
+ StringRef File = SM.getBufferData(Loc.first);
+ const char *TokenBegin = File.data() + Loc.second;
+ Lexer Lexer(SM.getLocForStartOfFile(Loc.first), LangOpts, File.begin(),
+ TokenBegin, File.end());
+ Token T;
+ while (!Lexer.LexFromRawLexer(T)) {
+ if (T.is(tok::raw_identifier)) {
+ IdentifierInfo &Info = Ctx.Idents.get(
+ StringRef(SM.getCharacterData(T.getLocation()), T.getLength()));
+ T.setIdentifierInfo(&Info);
+ T.setKind(Info.getTokenID());
+ }
+
+ if (T.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict)) {
+ Result = T.getEndLoc();
+ continue;
+ }
+ break;
+ }
+ return Result;
+}
+
+static bool IsCVR(Token T) {
+ return T.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict);
+}
+
+static bool IsSpecifier(Token T) {
+ return T.isOneOf(tok::kw_constexpr, tok::kw_inline, tok::kw_extern,
+ tok::kw_static, tok::kw_friend, tok::kw_virtual);
+}
+
+static llvm::Optional<ClassifiedToken>
+classifyToken(const FunctionDecl &F, Preprocessor &PP, Token Tok) {
+ ClassifiedToken CT;
+ CT.T = Tok;
+ CT.isQualifier = true;
+ CT.isSpecifier = true;
+ bool ContainsQualifiers = false;
+ bool ContainsSpecifiers = false;
+ bool ContainsSomethingElse = false;
+
+ Token End;
+ End.setKind(tok::eof);
+ SmallVector<Token, 2> Stream{Tok, End};
+ PP.EnterTokenStream(Stream, false);
+ while (true) {
+ Token T;
+ PP.Lex(T);
+ if (T.is(tok::eof))
+ break;
+
+ bool Qual = IsCVR(T);
+ bool Spec = IsSpecifier(T);
+ CT.isQualifier &= Qual;
+ CT.isSpecifier &= Spec;
+ ContainsQualifiers |= Qual;
+ ContainsSpecifiers |= Spec;
+ ContainsSomethingElse |= !Qual && !Spec;
+ }
+
+ // If the Token/Macro contains more than one type of tokens, we would need
+ // to split the macro in order to move parts to the trailing return type.
+ if (ContainsQualifiers + ContainsSpecifiers + ContainsSomethingElse > 1)
+ return llvm::None;
+
+ return CT;
+}
+
+llvm::Optional<SmallVector<ClassifiedToken, 8>>
+UseTrailingReturnTypeCheck::classifyTokensBeforeFunctionName(
+ const FunctionDecl &F, const ASTContext &Ctx, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ SourceLocation BeginF = expandIfMacroId(F.getBeginLoc(), SM);
+ SourceLocation BeginNameF = expandIfMacroId(F.getLocation(), SM);
+
+ // Create tokens for everything before the name of the function.
+ std::pair<FileID, unsigned> Loc = SM.getDecomposedLoc(BeginF);
+ StringRef File = SM.getBufferData(Loc.first);
+ const char *TokenBegin = File.data() + Loc.second;
+ Lexer Lexer(SM.getLocForStartOfFile(Loc.first), LangOpts, File.begin(),
+ TokenBegin, File.end());
+ Token T;
+ SmallVector<ClassifiedToken, 8> ClassifiedTokens;
+ while (!Lexer.LexFromRawLexer(T) &&
+ SM.isBeforeInTranslationUnit(T.getLocation(), BeginNameF)) {
+ if (T.is(tok::raw_identifier)) {
+ IdentifierInfo &Info = Ctx.Idents.get(
+ StringRef(SM.getCharacterData(T.getLocation()), T.getLength()));
+
+ if (Info.hasMacroDefinition()) {
+ const MacroInfo *MI = PP->getMacroInfo(&Info);
+ if (!MI || MI->isFunctionLike()) {
+ // Cannot handle function style macros.
+ diag(F.getLocation(), Message);
+ return llvm::None;
+ }
+ }
+
+ T.setIdentifierInfo(&Info);
+ T.setKind(Info.getTokenID());
+ }
+
+ if (llvm::Optional<ClassifiedToken> CT = classifyToken(F, *PP, T))
+ ClassifiedTokens.push_back(*CT);
+ else {
+ diag(F.getLocation(), Message);
+ return llvm::None;
+ }
+ }
+
+ return ClassifiedTokens;
+}
+
+static bool hasAnyNestedLocalQualifiers(QualType Type) {
+ bool Result = Type.hasLocalQualifiers();
+ if (Type->isPointerType())
+ Result = Result || hasAnyNestedLocalQualifiers(
+ Type->castAs<PointerType>()->getPointeeType());
+ if (Type->isReferenceType())
+ Result = Result || hasAnyNestedLocalQualifiers(
+ Type->castAs<ReferenceType>()->getPointeeType());
+ return Result;
+}
+
+SourceRange UseTrailingReturnTypeCheck::findReturnTypeAndCVSourceRange(
+ const FunctionDecl &F, const ASTContext &Ctx, const SourceManager &SM,
+ const LangOptions &LangOpts) {
+
+ // We start with the range of the return type and expand to neighboring
+ // qualifiers (const, volatile and restrict).
+ SourceRange ReturnTypeRange = F.getReturnTypeSourceRange();
+ if (ReturnTypeRange.isInvalid()) {
+ // Happens if e.g. clang cannot resolve all includes and the return type is
+ // unknown.
+ diag(F.getLocation(), Message);
+ return {};
+ }
+
+ // If the return type has no local qualifiers, it's source range is accurate.
+ if (!hasAnyNestedLocalQualifiers(F.getReturnType()))
+ return ReturnTypeRange;
+
+ // Include qualifiers to the left and right of the return type.
+ llvm::Optional<SmallVector<ClassifiedToken, 8>> MaybeTokens =
+ classifyTokensBeforeFunctionName(F, Ctx, SM, LangOpts);
+ if (!MaybeTokens)
+ return {};
+ const SmallVector<ClassifiedToken, 8> &Tokens = *MaybeTokens;
+
+ ReturnTypeRange.setBegin(expandIfMacroId(ReturnTypeRange.getBegin(), SM));
+ ReturnTypeRange.setEnd(expandIfMacroId(ReturnTypeRange.getEnd(), SM));
+
+ bool ExtendedLeft = false;
+ for (size_t I = 0; I < Tokens.size(); I++) {
+ // If we found the beginning of the return type, include left qualifiers.
+ if (!SM.isBeforeInTranslationUnit(Tokens[I].T.getLocation(),
+ ReturnTypeRange.getBegin()) &&
+ !ExtendedLeft) {
+ assert(I <= size_t(std::numeric_limits<int>::max()) &&
+ "Integer overflow detected");
+ for (int J = static_cast<int>(I) - 1; J >= 0 && Tokens[J].isQualifier;
+ J--)
+ ReturnTypeRange.setBegin(Tokens[J].T.getLocation());
+ ExtendedLeft = true;
+ }
+ // If we found the end of the return type, include right qualifiers.
+ if (SM.isBeforeInTranslationUnit(ReturnTypeRange.getEnd(),
+ Tokens[I].T.getLocation())) {
+ for (size_t J = I; J < Tokens.size() && Tokens[J].isQualifier; J++)
+ ReturnTypeRange.setEnd(Tokens[J].T.getLocation());
+ break;
+ }
+ }
+
+ assert(!ReturnTypeRange.getBegin().isMacroID() &&
+ "Return type source range begin must not be a macro");
+ assert(!ReturnTypeRange.getEnd().isMacroID() &&
+ "Return type source range end must not be a macro");
+ return ReturnTypeRange;
+}
+
+bool UseTrailingReturnTypeCheck::keepSpecifiers(
+ std::string &ReturnType, std::string &Auto, SourceRange ReturnTypeCVRange,
+ const FunctionDecl &F, const FriendDecl *Fr, const ASTContext &Ctx,
+ const SourceManager &SM, const LangOptions &LangOpts) {
+ // Check if there are specifiers inside the return type. E.g. unsigned
+ // inline int.
+ const auto *M = dyn_cast<CXXMethodDecl>(&F);
+ if (!F.isConstexpr() && !F.isInlineSpecified() &&
+ F.getStorageClass() != SC_Extern && F.getStorageClass() != SC_Static &&
+ !Fr && !(M && M->isVirtualAsWritten()))
+ return true;
+
+ // Tokenize return type. If it contains macros which contain a mix of
+ // qualifiers, specifiers and types, give up.
+ llvm::Optional<SmallVector<ClassifiedToken, 8>> MaybeTokens =
+ classifyTokensBeforeFunctionName(F, Ctx, SM, LangOpts);
+ if (!MaybeTokens)
+ return false;
+
+ // Find specifiers, remove them from the return type, add them to 'auto'.
+ unsigned int ReturnTypeBeginOffset =
+ SM.getDecomposedLoc(ReturnTypeCVRange.getBegin()).second;
+ size_t InitialAutoLength = Auto.size();
+ unsigned int DeletedChars = 0;
+ for (ClassifiedToken CT : *MaybeTokens) {
+ if (SM.isBeforeInTranslationUnit(CT.T.getLocation(),
+ ReturnTypeCVRange.getBegin()) ||
+ SM.isBeforeInTranslationUnit(ReturnTypeCVRange.getEnd(),
+ CT.T.getLocation()))
+ continue;
+ if (!CT.isSpecifier)
+ continue;
+
+ // Add the token to 'auto' and remove it from the return type, including
+ // any whitespace following the token.
+ unsigned int TOffset = SM.getDecomposedLoc(CT.T.getLocation()).second;
+ assert(TOffset >= ReturnTypeBeginOffset &&
+ "Token location must be after the beginning of the return type");
+ unsigned int TOffsetInRT = TOffset - ReturnTypeBeginOffset - DeletedChars;
+ unsigned int TLengthWithWS = CT.T.getLength();
+ while (TOffsetInRT + TLengthWithWS < ReturnType.size() &&
+ std::isspace(ReturnType[TOffsetInRT + TLengthWithWS]))
+ TLengthWithWS++;
+ std::string Specifier = ReturnType.substr(TOffsetInRT, TLengthWithWS);
+ if (!std::isspace(Specifier.back()))
+ Specifier.push_back(' ');
+ Auto.insert(Auto.size() - InitialAutoLength, Specifier);
+ ReturnType.erase(TOffsetInRT, TLengthWithWS);
+ DeletedChars += TLengthWithWS;
+ }
+
+ return true;
+}
+
+void UseTrailingReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ auto F = functionDecl(unless(anyOf(hasTrailingReturn(), returns(voidType()),
+ returns(autoType()), cxxConversionDecl(),
+ cxxMethodDecl(isImplicit()))))
+ .bind("Func");
+
+ Finder->addMatcher(F, this);
+ Finder->addMatcher(friendDecl(hasDescendant(F)).bind("Friend"), this);
+}
+
+void UseTrailingReturnTypeCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ this->PP = PP;
+}
+
+void UseTrailingReturnTypeCheck::check(const MatchFinder::MatchResult &Result) {
+ assert(PP && "Expected registerPPCallbacks() to have been called before so "
+ "preprocessor is available");
+
+ const auto *F = Result.Nodes.getNodeAs<FunctionDecl>("Func");
+ const auto *Fr = Result.Nodes.getNodeAs<FriendDecl>("Friend");
+ assert(F && "Matcher is expected to find only FunctionDecls");
+
+ if (F->getLocation().isInvalid())
+ return;
+
+ // TODO: implement those
+ if (F->getDeclaredReturnType()->isFunctionPointerType() ||
+ F->getDeclaredReturnType()->isMemberFunctionPointerType() ||
+ F->getDeclaredReturnType()->isMemberPointerType() ||
+ F->getDeclaredReturnType()->getAs<DecltypeType>() != nullptr) {
+ diag(F->getLocation(), Message);
+ return;
+ }
+
+ const ASTContext &Ctx = *Result.Context;
+ const SourceManager &SM = *Result.SourceManager;
+ const LangOptions &LangOpts = getLangOpts();
+
+ const TypeSourceInfo *TSI = F->getTypeSourceInfo();
+ if (!TSI)
+ return;
+
+ FunctionTypeLoc FTL =
+ TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
+ if (!FTL) {
+ // FIXME: This may happen if we have __attribute__((...)) on the function.
+ // We abort for now. Remove this when the function type location gets
+ // available in clang.
+ diag(F->getLocation(), Message);
+ return;
+ }
+
+ SourceLocation InsertionLoc =
+ findTrailingReturnTypeSourceLocation(*F, FTL, Ctx, SM, LangOpts);
+ if (InsertionLoc.isInvalid()) {
+ diag(F->getLocation(), Message);
+ return;
+ }
+
+ // Using the declared return type via F->getDeclaredReturnType().getAsString()
+ // discards user formatting and order of const, volatile, type, whitespace,
+ // space before & ... .
+ SourceRange ReturnTypeCVRange =
+ findReturnTypeAndCVSourceRange(*F, Ctx, SM, LangOpts);
+ if (ReturnTypeCVRange.isInvalid())
+ return;
+
+ // Check if unqualified names in the return type conflict with other entities
+ // after the rewrite.
+ // FIXME: this could be done better, by performing a lookup of all
+ // unqualified names in the return type in the scope of the function. If the
+ // lookup finds a different entity than the original entity identified by the
+ // name, then we can either not perform a rewrite or explicitely qualify the
+ // entity. Such entities could be function parameter names, (inherited) class
+ // members, template parameters, etc.
+ UnqualNameVisitor UNV{*F, SM};
+ UNV.TraverseTypeLoc(FTL.getReturnLoc());
+ if (UNV.Collision) {
+ diag(F->getLocation(), Message);
+ return;
+ }
+
+ SourceLocation ReturnTypeEnd =
+ Lexer::getLocForEndOfToken(ReturnTypeCVRange.getEnd(), 0, SM, LangOpts);
+ StringRef CharAfterReturnType = Lexer::getSourceText(
+ CharSourceRange::getCharRange(ReturnTypeEnd,
+ ReturnTypeEnd.getLocWithOffset(1)),
+ SM, LangOpts);
+ bool NeedSpaceAfterAuto =
+ CharAfterReturnType.empty() || !std::isspace(CharAfterReturnType[0]);
+
+ std::string Auto = NeedSpaceAfterAuto ? "auto " : "auto";
+ std::string ReturnType = tooling::fixit::getText(ReturnTypeCVRange, Ctx);
+ keepSpecifiers(ReturnType, Auto, ReturnTypeCVRange, *F, Fr, Ctx, SM,
+ LangOpts);
+
+ diag(F->getLocation(), Message)
+ << FixItHint::CreateReplacement(ReturnTypeCVRange, Auto)
+ << FixItHint::CreateInsertion(InsertionLoc, " -> " + ReturnType);
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.h?rev=360438&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseTrailingReturnTypeCheck.h Fri May 10 09:24:28 2019
@@ -0,0 +1,62 @@
+//===--- UseTrailingReturnTypeCheck.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_MODERNIZE_USETRAILINGRETURNTYPECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USETRAILINGRETURNTYPECHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+struct ClassifiedToken {
+ Token T;
+ bool isQualifier;
+ bool isSpecifier;
+};
+
+/// Rewrites function signatures to use a trailing return type.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-trailing-type-return.html
+class UseTrailingReturnTypeCheck : public ClangTidyCheck {
+public:
+ UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ Preprocessor *PP = nullptr;
+
+ SourceLocation findTrailingReturnTypeSourceLocation(
+ const FunctionDecl &F, const FunctionTypeLoc &FTL, const ASTContext &Ctx,
+ const SourceManager &SM, const LangOptions &LangOpts);
+ llvm::Optional<SmallVector<ClassifiedToken, 8>>
+ classifyTokensBeforeFunctionName(const FunctionDecl &F, const ASTContext &Ctx,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+ SourceRange findReturnTypeAndCVSourceRange(const FunctionDecl &F,
+ const ASTContext &Ctx,
+ const SourceManager &SM,
+ const LangOptions &LangOpts);
+ bool keepSpecifiers(std::string &ReturnType, std::string &Auto,
+ SourceRange ReturnTypeCVRange, const FunctionDecl &F,
+ const FriendDecl *Fr, const ASTContext &Ctx,
+ const SourceManager &SM, const LangOptions &LangOpts);
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USETRAILINGRETURNTYPECHECK_H
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=360438&r1=360437&r2=360438&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Fri May 10 09:24:28 2019
@@ -151,6 +151,14 @@ Improvements to clang-tidy
finds and replaces cases that match the pattern ``var &&
isa<X>(var)``, where ``var`` is evaluated twice.
+- New :doc:`modernize-use-trailing-return-type
+ <clang-tidy/checks/modernize-use-trailing-return-type>` check.
+
+ Rewrites function signatures to use a trailing return type.
+
+Improvements to include-fixer
+-----------------------------
+
- New :doc:`openmp-exception-escape
<clang-tidy/checks/openmp-exception-escape>` 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=360438&r1=360437&r2=360438&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Fri May 10 09:24:28 2019
@@ -219,6 +219,7 @@ Clang-Tidy Checks
modernize-use-noexcept
modernize-use-nullptr
modernize-use-override
+ modernize-use-trailing-return-type
modernize-use-transparent-functors
modernize-use-uncaught-exceptions
modernize-use-using
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-trailing-return-type.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-trailing-return-type.rst?rev=360438&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-trailing-return-type.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-trailing-return-type.rst Fri May 10 09:24:28 2019
@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-trailing-return-type
+
+modernize-use-trailing-return-type
+==================================
+
+Rewrites function signatures to use a trailing return type
+(introduced in C++11). This transformation is purely stylistic.
+The return type before the function name is replaced by ``auto``
+and inserted after the function parameter list (and qualifiers).
+
+Example
+-------
+
+.. code-block:: c++
+
+ int f1();
+ inline int f2(int arg) noexcept;
+ virtual float f3() const && = delete;
+
+transforms to:
+
+.. code-block:: c++
+
+ auto f1() -> int;
+ inline auto f2(int arg) -> int noexcept;
+ virtual auto f3() const && -> float = delete;
+
+Known Limitations
+-----------------
+
+The following categories of return types cannot be rewritten currently:
+* function pointers
+* member function pointers
+* member pointers
+* decltype, when it is the top level expression
+
+Unqualified names in the return type might erroneously refer to different entities after the rewrite.
+Preventing such errors requires a full lookup of all unqualified names present in the return type in the scope of the trailing return type location.
+This location includes e.g. function parameter names and members of the enclosing class (including all inherited classes).
+Such a lookup is currently not implemented.
+
+Given the following piece of code
+
+.. code-block:: c++
+
+ struct Object { long long value; };
+ Object f(unsigned Object) { return {Object * 2}; }
+ class CC {
+ int Object;
+ struct Object m();
+ };
+ Object CC::m() { return {0}; }
+
+a careless rewrite would produce the following output:
+
+.. code-block:: c++
+
+ struct Object { long long value; };
+ auto f(unsigned Object) -> Object { return {Object * 2}; } // error
+ class CC {
+ int Object;
+ auto m() -> struct Object;
+ };
+ auto CC::m() -> Object { return {0}; } // error
+
+This code fails to compile because the Object in the context of f refers to the equally named function parameter.
+Similarly, the Object in the context of m refers to the equally named class member.
+The check can currently only detect a clash with a function parameter name.
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-trailing-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-trailing-return-type.cpp?rev=360438&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-trailing-return-type.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-trailing-return-type.cpp Fri May 10 09:24:28 2019
@@ -0,0 +1,563 @@
+// RUN: %check_clang_tidy %s modernize-use-trailing-return-type %t -- -- --std=c++14 -fdeclspec -fexceptions
+
+namespace std {
+ template <typename T>
+ class vector;
+
+ template <typename T, int N>
+ class array;
+
+ class string;
+
+ template <typename T>
+ auto declval() -> T;
+}
+
+//
+// Functions
+//
+
+int f();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto f() -> int;{{$}}
+int ((f))();
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto ((f))() -> int;{{$}}
+int f(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto f(int) -> int;{{$}}
+int f(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto f(int arg) -> int;{{$}}
+int f(int arg1, int arg2, int arg3);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto f(int arg1, int arg2, int arg3) -> int;{{$}}
+int f(int arg1, int arg2, int arg3, ...);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto f(int arg1, int arg2, int arg3, ...) -> int;{{$}}
+template <typename T> int f(T t);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}template <typename T> auto f(T t) -> int;{{$}}
+
+//
+// Functions with formatting
+//
+
+int a1() { return 42; }
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a1() -> int { return 42; }{{$}}
+int a2() {
+ return 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a2() -> int {{{$}}
+int a3()
+{
+ return 42;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a3() -> int{{$}}
+int a4(int arg ) ;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a4(int arg ) -> int ;{{$}}
+int a5
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a5{{$}}
+(int arg);
+// CHECK-FIXES: {{^}}(int arg) -> int;{{$}}
+const
+int
+*
+a7
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+()
+// CHECK-FIXES: {{^}}() -> const{{$}}
+// CHECK-FIXES: {{^}}int{{$}}
+// CHECK-FIXES: {{^}}*{{$}}
+;
+
+int*a7(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a7(int arg) -> int*;{{$}}
+template<template <typename> class C>
+C<int>a8(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto a8(int arg) -> C<int>;{{$}}
+
+
+//
+// Functions with qualifiers and specifiers
+//
+
+inline int d1(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto d1(int arg) -> int;{{$}}
+extern "C" int d2(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}extern "C" auto d2(int arg) -> int;{{$}}
+inline int d3(int arg) noexcept(true);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto d3(int arg) noexcept(true) -> int;{{$}}
+inline int d4(int arg) try { } catch(...) { }
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto d4(int arg) -> int try { } catch(...) { }{{$}}
+int d5(int arg) throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto d5(int arg) throw() -> int;{{$}}
+static int d6(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto d6(int arg) -> int;{{$}}
+int static d6(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto static d6(int arg) -> int;{{$}}
+unsigned static int d7(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto d7(int arg) -> unsigned int;{{$}}
+const long static int volatile constexpr unsigned inline long d8(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:63: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static constexpr inline auto d8(int arg) -> const long int volatile unsigned long;{{$}}
+int constexpr d9();
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto constexpr d9() -> int;{{$}}
+inline int constexpr d10();
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto constexpr d10() -> int;{{$}}
+unsigned constexpr int d11();
+// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}constexpr auto d11() -> unsigned int;{{$}}
+unsigned extern int d13();
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}extern auto d13() -> unsigned int;{{$}}
+int static& d14();
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto d14() -> int &;{{$}}
+class DDD {
+ int friend unsigned m1();
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} friend auto m1() -> int unsigned;{{$}}
+ int friend unsigned m1() { return 0; }
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} friend auto m1() -> int unsigned { return 0; }{{$}}
+ const long int friend volatile constexpr unsigned inline long m2();
+// CHECK-MESSAGES: :[[@LINE-1]]:67: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} friend constexpr inline auto m2() -> const long int volatile unsigned long;{{$}}
+ int virtual unsigned m3();
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto m3() -> int unsigned;{{$}}
+ template <typename T>
+ int friend unsigned m4();
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} friend auto m4() -> int unsigned;{{$}}
+};
+
+//
+// Functions in namespaces
+//
+
+namespace N {
+ int e1();
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto e1() -> int;{{$}}
+int N::e1() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto N::e1() -> int {}{{$}}
+
+//
+// Functions with unsupported return types
+//
+int (*e3())(double);
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}int (*e3())(double);{{$}}
+struct A;
+int A::* e5();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}int A::* e5();{{$}}
+int std::vector<std::string>::* e6();
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}int std::vector<std::string>::* e6();{{$}}
+int (std::vector<std::string>::*e7())(double);
+// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}int (std::vector<std::string>::*e7())(double);{{$}}
+
+//
+// Functions with complex return types
+//
+
+inline volatile const std::vector<std::string> e2();
+// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto e2() -> volatile const std::vector<std::string>;{{$}}
+inline const std::vector<std::string> volatile e2();
+// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto e2() -> const std::vector<std::string> volatile;{{$}}
+inline std::vector<std::string> const volatile e2();
+// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}inline auto e2() -> std::vector<std::string> const volatile;{{$}}
+int* e8();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto e8() -> int*;{{$}}
+static const char* e9(void* user_data);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto e9(void* user_data) -> const char*;{{$}}
+static const char* const e10(void* user_data);
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto e10(void* user_data) -> const char* const;{{$}}
+static const char** volatile * const & e11(void* user_data);
+// CHECK-MESSAGES: :[[@LINE-1]]:40: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto e11(void* user_data) -> const char** volatile * const &;{{$}}
+static const char* const * const * const e12(void* user_data);
+// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}static auto e12(void* user_data) -> const char* const * const * const;{{$}}
+struct A e13();
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto e13() -> struct A;{{$}}
+
+//
+// decltype (unsupported if top level expression)
+//
+
+decltype(1 + 2) dec1() { return 1 + 2; }
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// TODO: source range of DecltypeTypeLoc not yet implemented
+// _HECK-FIXES: {{^}}auto dec1() -> decltype(1 + 2) { return 1 + 2; }{{$}}
+template <typename F, typename T>
+decltype(std::declval<F>(std::declval<T>)) dec2(F f, T t) { return f(t); }
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// TODO: source range of DecltypeTypeLoc not yet implemented
+// _HECK-FIXES: {{^}}auto dec2(F f, T t) -> decltype(std::declval<F>(std::declval<T>)) { return f(t); }{{$}}
+template <typename T>
+typename decltype(std::declval<T>())::value_type dec3();
+// CHECK-MESSAGES: :[[@LINE-1]]:50: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto dec3() -> typename decltype(std::declval<T>())::value_type;{{$}}
+template <typename T>
+decltype(std::declval<T>())* dec4();
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto dec4() -> decltype(std::declval<T>())*;{{$}}
+
+//
+// Methods
+//
+
+struct B {
+ B& operator=(const B&);
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto operator=(const B&) -> B&;{{$}}
+
+ double base1(int, bool b);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base1(int, bool b) -> double;{{$}}
+
+ virtual double base2(int, bool b) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base2(int, bool b) -> double {}{{$}}
+
+ virtual float base3() const = 0;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base3() const -> float = 0;{{$}}
+
+ virtual float base4() volatile = 0;
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base4() volatile -> float = 0;{{$}}
+
+ double base5(int, bool b) &&;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base5(int, bool b) && -> double;{{$}}
+
+ double base6(int, bool b) const &&;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base6(int, bool b) const && -> double;{{$}}
+
+ double base7(int, bool b) const & = delete;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base7(int, bool b) const & -> double = delete;{{$}}
+
+ double base8(int, bool b) const volatile & = delete;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base8(int, bool b) const volatile & -> double = delete;{{$}}
+
+ virtual const char * base9() const noexcept { return ""; }
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base9() const noexcept -> const char * { return ""; }{{$}}
+};
+
+double B::base1(int, bool b) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto B::base1(int, bool b) -> double {}{{$}}
+
+struct D : B {
+ virtual double f1(int, bool b) final;
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto f1(int, bool b) -> double final;{{$}}
+
+ virtual double base2(int, bool b) override;
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base2(int, bool b) -> double override;{{$}}
+
+ virtual float base3() const override final { }
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} virtual auto base3() const -> float override final { }{{$}}
+
+ const char * base9() const noexcept override { return ""; }
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto base9() const noexcept -> const char * override { return ""; }{{$}}
+
+ int f2() __restrict;
+// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto f2() __restrict -> int;{{$}}
+
+ volatile int* __restrict f3() const __restrict noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto f3() const __restrict noexcept -> volatile int* __restrict;{{$}}
+};
+
+//
+// Functions with attributes
+//
+
+int g1() [[asdf]];
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto g1() -> int {{[[][[]}}asdf{{[]][]]}};{{$}}
+[[noreturn]] int g2();
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}{{[[][[]}}noreturn{{[]][]]}} auto g2() -> int;{{$}}
+int g2 [[noreturn]] ();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto g2 {{[[][[]}}noreturn{{[]][]]}} () -> int;{{$}}
+int unsigned g3() __attribute__((cdecl)); // FunctionTypeLoc is null.
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+int unsigned __attribute__((cdecl)) g3() ; // FunctionTypeLoc is null.
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+__attribute__((cdecl)) int unsigned g3() ; // FunctionTypeLoc is null.
+// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+
+//
+// Templates
+//
+template <typename Container>
+[[maybe_unused]] typename Container::value_type const volatile&& t1(Container& C) noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:66: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}{{[[][[]}}maybe_unused{{[]][]]}} auto t1(Container& C) noexcept -> typename Container::value_type const volatile&&;{{$}}
+template <typename T>
+class BB {
+ using type = int;
+
+ template <typename U>
+ typename BB<U>::type m1();
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto m1() -> typename BB<U>::type;{{$}}
+};
+
+//
+// Macros
+//
+
+#define DWORD unsigned int
+DWORD h1();
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h1() -> DWORD;{{$}}
+#define INT int
+#define UNSIGNED unsigned
+UNSIGNED INT h2();
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h2() -> UNSIGNED INT;{{$}}
+#define CONST const
+CONST int h3();
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h3() -> CONST int;{{$}}
+#define ALWAYS_INLINE inline
+#define DLL_EXPORT __declspec(dllexport)
+ALWAYS_INLINE DLL_EXPORT int h4();
+// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}ALWAYS_INLINE DLL_EXPORT auto h4() -> int;{{$}}
+#define DEPRECATED __attribute__((deprecated))
+int h5() DEPRECATED;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h5() -> int DEPRECATED;{{$}}
+int DEPRECATED h5();
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto DEPRECATED h5() -> int;{{$}}
+DEPRECATED int h5();
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}DEPRECATED auto h5() -> int;{{$}}
+[[noreturn]] [[nodiscard]] DEPRECATED DLL_EXPORT int h6 [[deprecated]] ();
+// CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}{{[[][[]}}noreturn{{[]][]]}} {{[[][[]}}nodiscard{{[]][]]}} DEPRECATED DLL_EXPORT auto h6 {{[[][[]}}deprecated{{[]][]]}} () -> int;{{$}}
+#define FUNCTION_NAME(a, b) a##b
+int FUNCTION_NAME(foo, bar)();
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto FUNCTION_NAME(foo, bar)() -> int;{{$}}
+#define DEFINE_FUNCTION_1(a, b) int a##b()
+DEFINE_FUNCTION_1(foo, bar);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define DEFINE_FUNCTION_2 int foo(int arg);
+DEFINE_FUNCTION_2
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define DLL_EXPORT_const __declspec(dllexport) const
+DLL_EXPORT_const int h7();
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define DLL_EXPORT_CONST __declspec(dllexport) CONST
+DLL_EXPORT_CONST int h7();
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+
+template <typename T>
+using Real = T;
+#define PRECISION float
+Real<PRECISION> h8() { return 0.; }
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h8() -> Real<PRECISION> { return 0.; }{{$}}
+
+#define MAYBE_UNUSED_MACRO [[maybe_unused]]
+template <typename Container>
+MAYBE_UNUSED_MACRO typename Container::value_type const volatile** const h9(Container& C) noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:74: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}MAYBE_UNUSED_MACRO auto h9(Container& C) noexcept -> typename Container::value_type const volatile** const;{{$}}
+
+#define NOEXCEPT noexcept
+int h9(int arg) NOEXCEPT;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h9(int arg) NOEXCEPT -> int;{{$}}
+#define STATIC_INT static int
+STATIC_INT h10();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define UNSIGNED_STATIC_INT unsigned static int
+UNSIGNED_STATIC_INT h11();
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define STATIC static
+unsigned STATIC int h11();
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}STATIC auto h11() -> unsigned int;{{$}}
+#define STATIC_CONSTEXPR static constexpr
+unsigned STATIC_CONSTEXPR int h12();
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}STATIC_CONSTEXPR auto h12() -> unsigned int;{{$}}
+#define STATIC_CONSTEXPR_LONG static constexpr long
+unsigned STATIC_CONSTEXPR_LONG int h13();
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+DEPRECATED const int& h14();
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}DEPRECATED auto h14() -> const int&;{{$}}
+DEPRECATED const long static volatile unsigned& h15();
+// CHECK-MESSAGES: :[[@LINE-1]]:49: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}DEPRECATED static auto h15() -> const long volatile unsigned&;{{$}}
+#define WRAP(x) x
+WRAP(const) int& h16();
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+WRAP(CONST) int& h16();
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+#define CONCAT(a, b) a##b
+CONCAT(con, st) int& h16();
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+DEPRECATED const UNSIGNED& h17();
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}DEPRECATED auto h17() -> const UNSIGNED&;{{$}}
+DEPRECATED CONST UNSIGNED STATIC& h18();
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}DEPRECATED STATIC auto h18() -> CONST UNSIGNED &;{{$}}
+#define CONST_CAT con##st
+CONST_CAT int& h19();
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h19() -> CONST_CAT int&;{{$}}
+#define CONST_F_MACRO WRAP(CONST_CAT)
+CONST_F_MACRO int& h19();
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto h19() -> CONST_F_MACRO int&;{{$}}
+
+//
+// Name collisions
+//
+struct Object { long long value; };
+
+Object j1(unsigned Object) { return {Object * 2}; }
+// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}Object j1(unsigned Object) { return {Object * 2}; }{{$}}
+::Object j1(unsigned Object);
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j1(unsigned Object) -> ::Object;{{$}}
+const Object& j2(unsigned a, int b, char Object, long l);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}const Object& j2(unsigned a, int b, char Object, long l);{{$}}
+const struct Object& j2(unsigned a, int b, char Object, long l);
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j2(unsigned a, int b, char Object, long l) -> const struct Object&;{{$}}
+std::vector<Object> j3(unsigned Object);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}std::vector<Object> j3(unsigned Object);{{$}}
+std::vector<const Object> j7(unsigned Object);
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}std::vector<const Object> j7(unsigned Object);{{$}}
+std::vector<Object> j4(unsigned vector);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j4(unsigned vector) -> std::vector<Object>;{{$}}
+std::vector<::Object> j4(unsigned vector);
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j4(unsigned vector) -> std::vector<::Object>;{{$}}
+std::vector<struct Object> j4(unsigned vector);
+// CHECK-MESSAGES: :[[@LINE-1]]:28: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j4(unsigned vector) -> std::vector<struct Object>;{{$}}
+std::vector<Object> j4(unsigned Vector);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto j4(unsigned Vector) -> std::vector<Object>;{{$}}
+using std::vector;
+vector<Object> j5(unsigned vector);
+// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}vector<Object> j5(unsigned vector);{{$}}
+constexpr auto Size = 5;
+std::array<int, Size> j6(unsigned Size);
+// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}std::array<int, Size> j6(unsigned Size);{{$}}
+std::array<decltype(Size), (Size * 2) + 1> j8(unsigned Size);
+// CHECK-MESSAGES: :[[@LINE-1]]:44: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}std::array<decltype(Size), (Size * 2) + 1> j8(unsigned Size);{{$}}
+
+class CC {
+ int Object;
+ struct Object m();
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto m() -> struct Object;{{$}}
+};
+Object CC::m() { return {0}; }
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto CC::m() -> Object { return {0}; }{{$}}
+class DD : public CC {
+ ::Object g();
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}} auto g() -> ::Object;{{$}}
+};
+Object DD::g() {
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto DD::g() -> Object {{{$}}
+ return {0};
+}
+
+
+//
+// Samples which do not trigger the check
+//
+
+auto f() -> int;
+auto f(int) -> int;
+auto f(int arg) -> int;
+auto f(int arg1, int arg2, int arg3) -> int;
+auto f(int arg1, int arg2, int arg3, ...) -> int;
+template <typename T> auto f(T t) -> int;
+
+auto ff();
+decltype(auto) fff();
+
+void c();
+void c(int arg);
+void c(int arg) { return; }
+
+struct D2 : B {
+ D2();
+ virtual ~D2();
+
+ virtual auto f1(int, bool b) -> double final;
+ virtual auto base2(int, bool b) -> double override;
+ virtual auto base3() const -> float override final { }
+
+ operator double();
+};
+
+auto l1 = [](int arg) {};
+auto l2 = [](int arg) -> double {};
More information about the cfe-commits
mailing list