[clang-tools-extra] r348633 - [clang-tidy]: Abseil: new check 'abseil-upgrade-duration-conversions'
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 7 12:03:03 PST 2018
Author: ericwf
Date: Fri Dec 7 12:03:03 2018
New Revision: 348633
URL: http://llvm.org/viewvc/llvm-project?rev=348633&view=rev
Log:
[clang-tidy]: Abseil: new check 'abseil-upgrade-duration-conversions'
Patch by Alex Strelnikov.
Reviewed as D53830
Introduce a new check to upgrade user code based on upcoming API breaking changes to absl::Duration.
The check finds calls to arithmetic operators and factory functions for absl::Duration that rely on
an implicit user defined conversion to int64_t. These cases will no longer compile after proposed
changes are released. Suggested fixes explicitly cast the argument int64_t.
Added:
clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-upgrade-duration-conversions.rst
clang-tools-extra/trunk/test/clang-tidy/abseil-upgrade-duration-conversions.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp?rev=348633&r1=348632&r2=348633&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/AbseilTidyModule.cpp Fri Dec 7 12:03:03 2018
@@ -20,6 +20,7 @@
#include "RedundantStrcatCallsCheck.h"
#include "StringFindStartswithCheck.h"
#include "StrCatAppendCheck.h"
+#include "UpgradeDurationConversionsCheck.h"
namespace clang {
namespace tidy {
@@ -47,6 +48,8 @@ public:
"abseil-str-cat-append");
CheckFactories.registerCheck<StringFindStartswithCheck>(
"abseil-string-find-startswith");
+ CheckFactories.registerCheck<UpgradeDurationConversionsCheck>(
+ "abseil-upgrade-duration-conversions");
}
};
Modified: clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt?rev=348633&r1=348632&r2=348633&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/abseil/CMakeLists.txt Fri Dec 7 12:03:03 2018
@@ -13,6 +13,7 @@ add_clang_library(clangTidyAbseilModule
RedundantStrcatCallsCheck.cpp
StrCatAppendCheck.cpp
StringFindStartswithCheck.cpp
+ UpgradeDurationConversionsCheck.cpp
LINK_LIBS
clangAST
Added: clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp?rev=348633&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp Fri Dec 7 12:03:03 2018
@@ -0,0 +1,158 @@
+//===--- UpgradeDurationConversionsCheck.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 "UpgradeDurationConversionsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+void UpgradeDurationConversionsCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ // For the arithmetic calls, we match only the uses of the templated operators
+ // where the template parameter is not a built-in type. This means the
+ // instantiation makes use of an available user defined conversion to
+ // `int64_t`.
+ //
+ // The implementation of these templates will be updated to fail SFINAE for
+ // non-integral types. We match them to suggest an explicit cast.
+
+ // Match expressions like `a *= b` and `a /= b` where `a` has type
+ // `absl::Duration` and `b` is not of a built-in type.
+ Finder->addMatcher(
+ cxxOperatorCallExpr(
+ argumentCountIs(2),
+ hasArgument(
+ 0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
+ hasArgument(1, expr().bind("arg")),
+ callee(functionDecl(
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("operator*=", "operator/=")))),
+ this);
+
+ // Match expressions like `a.operator*=(b)` and `a.operator/=(b)` where `a`
+ // has type `absl::Duration` and `b` is not of a built-in type.
+ Finder->addMatcher(
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(
+ ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("operator*=", "operator/="))),
+ argumentCountIs(1), hasArgument(0, expr().bind("arg"))),
+ this);
+
+ // Match expressions like `a * b`, `a / b`, `operator*(a, b)`, and
+ // `operator/(a, b)` where `a` has type `absl::Duration` and `b` is not of a
+ // built-in type.
+ Finder->addMatcher(
+ callExpr(callee(functionDecl(
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("::absl::operator*", "::absl::operator/"))),
+ argumentCountIs(2),
+ hasArgument(0, expr(hasType(
+ cxxRecordDecl(hasName("::absl::Duration"))))),
+ hasArgument(1, expr().bind("arg"))),
+ this);
+
+ // Match expressions like `a * b` and `operator*(a, b)` where `a` is not of a
+ // built-in type and `b` has type `absl::Duration`.
+ Finder->addMatcher(
+ callExpr(callee(functionDecl(
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasName("::absl::operator*"))),
+ argumentCountIs(2), hasArgument(0, expr().bind("arg")),
+ hasArgument(1, expr(hasType(cxxRecordDecl(
+ hasName("::absl::Duration")))))),
+ this);
+
+ // For the factory functions, we match only the non-templated overloads that
+ // take an `int64_t` parameter. Within these calls, we care about implicit
+ // casts through a user defined conversion to `int64_t`.
+ //
+ // The factory functions will be updated to be templated and SFINAE on whether
+ // the template parameter is an integral type. This complements the already
+ // existing templated overloads that only accept floating point types.
+
+ // Match calls like:
+ // `absl::Nanoseconds(x)`
+ // `absl::Microseconds(x)`
+ // `absl::Milliseconds(x)`
+ // `absl::Seconds(x)`
+ // `absl::Minutes(x)`
+ // `absl::Hours(x)`
+ // where `x` is not of a built-in type.
+ Finder->addMatcher(
+ implicitCastExpr(
+ anyOf(hasCastKind(CK_UserDefinedConversion),
+ has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))),
+ hasParent(callExpr(
+ callee(functionDecl(
+ hasAnyName("::absl::Nanoseconds", "::absl::Microseconds",
+ "::absl::Milliseconds", "::absl::Seconds",
+ "::absl::Minutes", "::absl::Hours"),
+ unless(hasParent(functionTemplateDecl())))),
+ hasArgument(0, expr().bind("arg"))))),
+ this);
+}
+
+void UpgradeDurationConversionsCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const llvm::StringRef Message =
+ "implicit conversion to 'int64_t' is deprecated in this context; use an "
+ "explicit cast instead";
+
+ const auto *ArgExpr = Result.Nodes.getNodeAs<Expr>("arg");
+ SourceLocation Loc = ArgExpr->getBeginLoc();
+
+ if (!match(isInTemplateInstantiation(), *ArgExpr, *Result.Context).empty()) {
+ if (MatchedTemplateLocations.count(Loc.getRawEncoding()) == 0) {
+ // For each location matched in a template instantiation, we check if the
+ // location can also be found in `MatchedTemplateLocations`. If it is not
+ // found, that means the expression did not create a match without the
+ // instantiation and depends on template parameters. A manual fix is
+ // probably required so we provide only a warning.
+ diag(Loc, Message);
+ }
+ return;
+ }
+
+ // We gather source locations from template matches not in template
+ // instantiations for future matches.
+ internal::Matcher<Stmt> IsInsideTemplate =
+ hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl())));
+ if (!match(IsInsideTemplate, *ArgExpr, *Result.Context).empty())
+ MatchedTemplateLocations.insert(Loc.getRawEncoding());
+
+ DiagnosticBuilder Diag = diag(Loc, Message);
+ CharSourceRange SourceRange = Lexer::makeFileCharRange(
+ CharSourceRange::getTokenRange(ArgExpr->getSourceRange()),
+ *Result.SourceManager, Result.Context->getLangOpts());
+ if (SourceRange.isInvalid())
+ // An invalid source range likely means we are inside a macro body. A manual
+ // fix is likely needed so we do not create a fix-it hint.
+ return;
+
+ Diag << FixItHint::CreateInsertion(SourceRange.getBegin(),
+ "static_cast<int64_t>(")
+ << FixItHint::CreateInsertion(SourceRange.getEnd(), ")");
+}
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.h?rev=348633&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/abseil/UpgradeDurationConversionsCheck.h Fri Dec 7 12:03:03 2018
@@ -0,0 +1,40 @@
+//===--- UpgradeDurationConversionsCheck.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_ABSEIL_UPGRADEDURATIONCONVERSIONSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_UPGRADEDURATIONCONVERSIONSCHECK_H
+
+#include "../ClangTidy.h"
+
+#include <unordered_set>
+
+namespace clang {
+namespace tidy {
+namespace abseil {
+
+/// Finds deprecated uses of `absl::Duration` arithmetic operators and factories.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/abseil-upgrade-duration-conversions.html
+class UpgradeDurationConversionsCheck : public ClangTidyCheck {
+public:
+ UpgradeDurationConversionsCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::unordered_set<unsigned> MatchedTemplateLocations;
+};
+
+} // namespace abseil
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ABSEIL_UPGRADEDURATIONCONVERSIONSCHECK_H
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=348633&r1=348632&r2=348633&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Fri Dec 7 12:03:03 2018
@@ -129,6 +129,13 @@ Improvements to clang-tidy
which means this type can't represent all values which are part of the
iteration range.
+- New :doc:`abseil-upgrade-duration-conversions
+ <clang-tidy/checks/abseil-upgrade-duration-conversions>` check.
+
+ Finds calls to ``absl::Duration`` arithmetic operators and factories whose
+ argument needs an explicit cast to continue compiling after upcoming API
+ changes.
+
- New :doc:`cppcoreguidelines-macro-usage
<clang-tidy/checks/cppcoreguidelines-macro-usage>` check.
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-upgrade-duration-conversions.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-upgrade-duration-conversions.rst?rev=348633&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-upgrade-duration-conversions.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/abseil-upgrade-duration-conversions.rst Fri Dec 7 12:03:03 2018
@@ -0,0 +1,43 @@
+.. title:: clang-tidy - abseil-upgrade-duration-conversions
+
+abseil-upgrade-duration-conversions
+===================================
+
+Finds calls to ``absl::Duration`` arithmetic operators and factories whose
+argument needs an explicit cast to continue compiling after upcoming API
+changes.
+
+The operators ``*=``, ``/=``, ``*``, and ``/`` for ``absl::Duration`` currently
+accept an argument of class type that is convertible to an arithmetic type. Such
+a call currently converts the value to an ``int64_t``, even in a case such as
+``std::atomic<float>`` that would result in lossy conversion.
+
+Additionally, the ``absl::Duration`` factory functions (``absl::Hours``,
+``absl::Minutes``, etc) currently accept an ``int64_t`` or a floating-point
+type. Similar to the arithmetic operators, calls with an argument of class type
+that is convertible to an arithmetic type go through the ``int64_t`` path.
+
+These operators and factories will be changed to only accept arithmetic types to
+prevent unintended behavior. After these changes are released, passing an
+argument of class type will no longer compile, even if the type is implicitly
+convertible to an arithmetic type.
+
+Here are example fixes created by this check:
+
+.. code-block:: c++
+
+ std::atomic<int> a;
+ absl::Duration d = absl::Milliseconds(a);
+ d *= a;
+
+becomes
+
+.. code-block:: c++
+
+ std::atomic<int> a;
+ absl::Duration d = absl::Milliseconds(static_cast<int64_t>(a));
+ d *= static_cast<int64_t>(a);
+
+Note that this check always adds a cast to ``int64_t`` in order to preserve the
+current behavior of user code. It is possible that this uncovers unintended
+behavior due to types implicitly convertible to a floating-point type.
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=348633&r1=348632&r2=348633&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Fri Dec 7 12:03:03 2018
@@ -14,6 +14,7 @@ Clang-Tidy Checks
abseil-redundant-strcat-calls
abseil-string-find-startswith
abseil-str-cat-append
+ abseil-upgrade-duration-conversions
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
Added: clang-tools-extra/trunk/test/clang-tidy/abseil-upgrade-duration-conversions.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/abseil-upgrade-duration-conversions.cpp?rev=348633&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/abseil-upgrade-duration-conversions.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/abseil-upgrade-duration-conversions.cpp Fri Dec 7 12:03:03 2018
@@ -0,0 +1,473 @@
+// RUN: %check_clang_tidy %s abseil-upgrade-duration-conversions %t
+
+using int64_t = long long;
+
+// Partial implementation of relevant APIs from
+// https://github.com/abseil/abseil-cpp/blob/master/absl/time/time.h
+namespace absl {
+
+class Duration {
+public:
+ Duration &operator*=(int64_t r);
+ Duration &operator*=(float r);
+ Duration &operator*=(double r);
+ template <typename T> Duration &operator*=(T r);
+
+ Duration &operator/=(int64_t r);
+ Duration &operator/=(float r);
+ Duration &operator/=(double r);
+ template <typename T> Duration &operator/=(T r);
+};
+
+template <typename T> Duration operator*(Duration lhs, T rhs);
+template <typename T> Duration operator*(T lhs, Duration rhs);
+template <typename T> Duration operator/(Duration lhs, T rhs);
+
+constexpr Duration Nanoseconds(int64_t n);
+constexpr Duration Microseconds(int64_t n);
+constexpr Duration Milliseconds(int64_t n);
+constexpr Duration Seconds(int64_t n);
+constexpr Duration Minutes(int64_t n);
+constexpr Duration Hours(int64_t n);
+
+template <typename T> struct EnableIfFloatImpl {};
+template <> struct EnableIfFloatImpl<float> { typedef int Type; };
+template <> struct EnableIfFloatImpl<double> { typedef int Type; };
+template <> struct EnableIfFloatImpl<long double> { typedef int Type; };
+template <typename T> using EnableIfFloat = typename EnableIfFloatImpl<T>::Type;
+
+template <typename T, EnableIfFloat<T> = 0> Duration Nanoseconds(T n);
+template <typename T, EnableIfFloat<T> = 0> Duration Microseconds(T n);
+template <typename T, EnableIfFloat<T> = 0> Duration Milliseconds(T n);
+template <typename T, EnableIfFloat<T> = 0> Duration Seconds(T n);
+template <typename T, EnableIfFloat<T> = 0> Duration Minutes(T n);
+template <typename T, EnableIfFloat<T> = 0> Duration Hours(T n);
+
+} // namespace absl
+
+template <typename T> struct ConvertibleTo {
+ operator T() const;
+};
+
+template <typename T>
+ConvertibleTo<T> operator+(ConvertibleTo<T>, ConvertibleTo<T>);
+
+template <typename T>
+ConvertibleTo<T> operator*(ConvertibleTo<T>, ConvertibleTo<T>);
+
+void arithmeticOperatorBasicPositive() {
+ absl::Duration d;
+ d *= ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
+ d /= ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d /= static_cast<int64_t>(ConvertibleTo<int64_t>());
+ d = ConvertibleTo<int64_t>() * d;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = static_cast<int64_t>(ConvertibleTo<int64_t>()) * d;
+ d = d * ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = d * static_cast<int64_t>(ConvertibleTo<int64_t>());
+ d = d / ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = d / static_cast<int64_t>(ConvertibleTo<int64_t>());
+ d.operator*=(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d.operator*=(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ d.operator/=(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:16: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d.operator/=(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ d = operator*(ConvertibleTo<int64_t>(), d);
+ // CHECK-MESSAGES: [[@LINE-1]]:17: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = operator*(static_cast<int64_t>(ConvertibleTo<int64_t>()), d);
+ d = operator*(d, ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = operator*(d, static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ d = operator/(d, ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:20: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = operator/(d, static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ ConvertibleTo<int64_t> c;
+ d *= (c + c) * c + c;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>((c + c) * c + c)
+ d /= (c + c) * c + c;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d /= static_cast<int64_t>((c + c) * c + c)
+ d = d * c * c;
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = d * static_cast<int64_t>(c) * static_cast<int64_t>(c)
+ d = c * d * c;
+ // CHECK-MESSAGES: [[@LINE-1]]:7: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = static_cast<int64_t>(c) * d * static_cast<int64_t>(c)
+ d = d / c * c;
+ // CHECK-MESSAGES: [[@LINE-1]]:11: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-MESSAGES: [[@LINE-2]]:15: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = d / static_cast<int64_t>(c) * static_cast<int64_t>(c)
+}
+
+void arithmeticOperatorBasicNegative() {
+ absl::Duration d;
+ d *= char{1};
+ d *= 1;
+ d *= int64_t{1};
+ d *= 1.0f;
+ d *= 1.0;
+ d *= 1.0l;
+ d /= char{1};
+ d /= 1;
+ d /= int64_t{1};
+ d /= 1.0f;
+ d /= 1.0;
+ d /= 1.0l;
+ d = d * char{1};
+ d = d * 1;
+ d = d * int64_t{1};
+ d = d * 1.0f;
+ d = d * 1.0;
+ d = d * 1.0l;
+ d = char{1} * d;
+ d = 1 * d;
+ d = int64_t{1} * d;
+ d = 1.0f * d;
+ d = 1.0 * d;
+ d = 1.0l * d;
+ d = d / char{1};
+ d = d / 1;
+ d = d / int64_t{1};
+ d = d / 1.0f;
+ d = d / 1.0;
+ d = d / 1.0l;
+
+ d *= static_cast<int>(ConvertibleTo<int>());
+ d *= (int)ConvertibleTo<int>();
+ d *= int(ConvertibleTo<int>());
+ d /= static_cast<int>(ConvertibleTo<int>());
+ d /= (int)ConvertibleTo<int>();
+ d /= int(ConvertibleTo<int>());
+ d = static_cast<int>(ConvertibleTo<int>()) * d;
+ d = (int)ConvertibleTo<int>() * d;
+ d = int(ConvertibleTo<int>()) * d;
+ d = d * static_cast<int>(ConvertibleTo<int>());
+ d = d * (int)ConvertibleTo<int>();
+ d = d * int(ConvertibleTo<int>());
+ d = d / static_cast<int>(ConvertibleTo<int>());
+ d = d / (int)ConvertibleTo<int>();
+ d = d / int(ConvertibleTo<int>());
+
+ d *= 1 + ConvertibleTo<int>();
+ d /= 1 + ConvertibleTo<int>();
+ d = (1 + ConvertibleTo<int>()) * d;
+ d = d * (1 + ConvertibleTo<int>());
+ d = d / (1 + ConvertibleTo<int>());
+}
+
+template <typename T> void templateForOpsSpecialization(T) {}
+template <>
+void templateForOpsSpecialization<absl::Duration>(absl::Duration d) {
+ d *= ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
+}
+
+template <int N> void arithmeticNonTypeTemplateParamSpecialization() {
+ absl::Duration d;
+ d *= N;
+}
+
+template <> void arithmeticNonTypeTemplateParamSpecialization<5>() {
+ absl::Duration d;
+ d *= ConvertibleTo<int>();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int>());
+}
+
+template <typename T> void templateOpsFix() {
+ absl::Duration d;
+ d *= ConvertibleTo<int64_t>();
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(ConvertibleTo<int64_t>());
+}
+
+template <typename T, typename U> void templateOpsWarnOnly(T t, U u) {
+ t *= u;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ absl::Duration d;
+ d *= u;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+template <typename T> struct TemplateTypeOpsWarnOnly {
+ void memberA(T t) {
+ d *= t;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ }
+ template <typename U, typename V> void memberB(U u, V v) {
+ u *= v;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ d *= v;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ }
+
+ absl::Duration d;
+};
+
+template <typename T, typename U>
+void templateOpsInstantiationBeforeDefinition(T t, U u);
+
+void arithmeticOperatorsInTemplates() {
+ templateForOpsSpecialization(5);
+ templateForOpsSpecialization(absl::Duration());
+ arithmeticNonTypeTemplateParamSpecialization<1>();
+ arithmeticNonTypeTemplateParamSpecialization<5>();
+ templateOpsFix<int>();
+ templateOpsWarnOnly(absl::Duration(), ConvertibleTo<int>());
+ templateOpsInstantiationBeforeDefinition(absl::Duration(),
+ ConvertibleTo<int>());
+ TemplateTypeOpsWarnOnly<ConvertibleTo<int>> t;
+ t.memberA(ConvertibleTo<int>());
+ t.memberB(absl::Duration(), ConvertibleTo<int>());
+}
+
+template <typename T, typename U>
+void templateOpsInstantiationBeforeDefinition(T t, U u) {
+ t *= u;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ absl::Duration d;
+ d *= u;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+#define FUNCTION_MACRO(x) x
+#define CONVERTIBLE_TMP ConvertibleTo<int>()
+#define ONLY_WARN_INSIDE_MACRO_ARITHMETIC_OP d *= ConvertibleTo<int>()
+
+#define T_OBJECT T()
+#define T_CALL_EXPR d *= T()
+
+template <typename T> void arithmeticTemplateAndMacro() {
+ absl::Duration d;
+ d *= T_OBJECT;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ d *= CONVERTIBLE_TMP;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(CONVERTIBLE_TMP);
+ T_CALL_EXPR;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+#define TEMPLATE_MACRO(type) \
+ template <typename T> void TemplateInMacro(T t) { \
+ type d; \
+ d *= t; \
+ }
+
+TEMPLATE_MACRO(absl::Duration)
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+
+void arithmeticOperatorsInMacros() {
+ absl::Duration d;
+ d = FUNCTION_MACRO(d * ConvertibleTo<int>());
+ // CHECK-MESSAGES: [[@LINE-1]]:26: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d = FUNCTION_MACRO(d * static_cast<int64_t>(ConvertibleTo<int>()));
+ d *= FUNCTION_MACRO(ConvertibleTo<int>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(FUNCTION_MACRO(ConvertibleTo<int>()));
+ d *= CONVERTIBLE_TMP;
+ // CHECK-MESSAGES: [[@LINE-1]]:8: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: d *= static_cast<int64_t>(CONVERTIBLE_TMP);
+ ONLY_WARN_INSIDE_MACRO_ARITHMETIC_OP;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ arithmeticTemplateAndMacro<ConvertibleTo<int>>();
+ TemplateInMacro(ConvertibleTo<int>());
+}
+
+void factoryFunctionPositive() {
+ // User defined conversion:
+ (void)absl::Nanoseconds(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ (void)absl::Microseconds(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ (void)absl::Milliseconds(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ (void)absl::Seconds(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ (void)absl::Minutes(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+ (void)absl::Hours(ConvertibleTo<int64_t>());
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<int64_t>()));
+
+ // User defined conversion to integral type, followed by built-in conversion:
+ (void)absl::Nanoseconds(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<char>()));
+ (void)absl::Microseconds(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<char>()));
+ (void)absl::Milliseconds(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<char>()));
+ (void)absl::Seconds(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<char>()));
+ (void)absl::Minutes(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<char>()));
+ (void)absl::Hours(ConvertibleTo<char>());
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<char>()));
+
+ // User defined conversion to floating point type, followed by built-in conversion:
+ (void)absl::Nanoseconds(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<float>()));
+ (void)absl::Microseconds(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Microseconds(static_cast<int64_t>(ConvertibleTo<float>()));
+ (void)absl::Milliseconds(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:28: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Milliseconds(static_cast<int64_t>(ConvertibleTo<float>()));
+ (void)absl::Seconds(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Seconds(static_cast<int64_t>(ConvertibleTo<float>()));
+ (void)absl::Minutes(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:23: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Minutes(static_cast<int64_t>(ConvertibleTo<float>()));
+ (void)absl::Hours(ConvertibleTo<float>());
+ // CHECK-MESSAGES: [[@LINE-1]]:21: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Hours(static_cast<int64_t>(ConvertibleTo<float>()));
+}
+
+void factoryFunctionNegative() {
+ (void)absl::Nanoseconds(char{1});
+ (void)absl::Nanoseconds(1);
+ (void)absl::Nanoseconds(int64_t{1});
+ (void)absl::Nanoseconds(1.0f);
+ (void)absl::Microseconds(char{1});
+ (void)absl::Microseconds(1);
+ (void)absl::Microseconds(int64_t{1});
+ (void)absl::Microseconds(1.0f);
+ (void)absl::Milliseconds(char{1});
+ (void)absl::Milliseconds(1);
+ (void)absl::Milliseconds(int64_t{1});
+ (void)absl::Milliseconds(1.0f);
+ (void)absl::Seconds(char{1});
+ (void)absl::Seconds(1);
+ (void)absl::Seconds(int64_t{1});
+ (void)absl::Seconds(1.0f);
+ (void)absl::Minutes(char{1});
+ (void)absl::Minutes(1);
+ (void)absl::Minutes(int64_t{1});
+ (void)absl::Minutes(1.0f);
+ (void)absl::Hours(char{1});
+ (void)absl::Hours(1);
+ (void)absl::Hours(int64_t{1});
+ (void)absl::Hours(1.0f);
+
+ (void)absl::Nanoseconds(static_cast<int>(ConvertibleTo<int>()));
+ (void)absl::Microseconds(static_cast<int>(ConvertibleTo<int>()));
+ (void)absl::Milliseconds(static_cast<int>(ConvertibleTo<int>()));
+ (void)absl::Seconds(static_cast<int>(ConvertibleTo<int>()));
+ (void)absl::Minutes(static_cast<int>(ConvertibleTo<int>()));
+ (void)absl::Hours(static_cast<int>(ConvertibleTo<int>()));
+}
+
+template <typename T> void templateForFactorySpecialization(T) {}
+template <> void templateForFactorySpecialization<ConvertibleTo<int>>(ConvertibleTo<int> c) {
+ (void)absl::Nanoseconds(c);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(c));
+}
+
+template <int N> void factoryNonTypeTemplateParamSpecialization() {
+ (void)absl::Nanoseconds(N);
+}
+
+template <> void factoryNonTypeTemplateParamSpecialization<5>() {
+ (void)absl::Nanoseconds(ConvertibleTo<int>());
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int>()));
+}
+
+template <typename T> void templateFactoryFix() {
+ (void)absl::Nanoseconds(ConvertibleTo<int>());
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(ConvertibleTo<int>()));
+}
+
+template <typename T> void templateFactoryWarnOnly(T t) {
+ (void)absl::Nanoseconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+template <typename T> void templateFactoryInstantiationBeforeDefinition(T t);
+
+template <typename T> struct TemplateTypeFactoryWarnOnly {
+ void memberA(T t) {
+ (void)absl::Nanoseconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ }
+ template <typename U> void memberB(U u) {
+ (void)absl::Nanoseconds(u);
+ // CHECK-MESSAGES: [[@LINE-1]]:29: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ }
+};
+
+void factoryInTemplates() {
+ templateForFactorySpecialization(5);
+ templateForFactorySpecialization(ConvertibleTo<int>());
+ factoryNonTypeTemplateParamSpecialization<1>();
+ factoryNonTypeTemplateParamSpecialization<5>();
+ templateFactoryFix<int>();
+ templateFactoryWarnOnly(ConvertibleTo<int>());
+ templateFactoryInstantiationBeforeDefinition(ConvertibleTo<int>());
+ TemplateTypeFactoryWarnOnly<ConvertibleTo<int>> t;
+ t.memberA(ConvertibleTo<int>());
+ t.memberB(ConvertibleTo<int>());
+}
+
+template <typename T> void templateFactoryInstantiationBeforeDefinition(T t) {
+ (void)absl::Nanoseconds(t);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+#define ONLY_WARN_INSIDE_MACRO_FACTORY \
+ (void)absl::Nanoseconds(ConvertibleTo<int>())
+#define T_CALL_FACTORTY_INSIDE_MACRO (void)absl::Nanoseconds(T())
+
+template <typename T> void factoryTemplateAndMacro() {
+ (void)absl::Nanoseconds(T_OBJECT);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ (void)absl::Nanoseconds(CONVERTIBLE_TMP);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(CONVERTIBLE_TMP))
+ T_CALL_FACTORTY_INSIDE_MACRO;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+}
+
+#define TEMPLATE_FACTORY_MACRO(factory) \
+ template <typename T> void TemplateFactoryInMacro(T t) { (void)factory(t); }
+
+TEMPLATE_FACTORY_MACRO(absl::Nanoseconds)
+// CHECK-MESSAGES: [[@LINE-1]]:1: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+
+void factoryInMacros() {
+ (void)absl::Nanoseconds(FUNCTION_MACRO(ConvertibleTo<int>()));
+ // CHECK-MESSAGES: [[@LINE-1]]:42: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(FUNCTION_MACRO(ConvertibleTo<int>())));
+ (void)absl::Nanoseconds(CONVERTIBLE_TMP);
+ // CHECK-MESSAGES: [[@LINE-1]]:27: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ // CHECK-FIXES: (void)absl::Nanoseconds(static_cast<int64_t>(CONVERTIBLE_TMP))
+ ONLY_WARN_INSIDE_MACRO_FACTORY;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: implicit conversion to 'int64_t' is deprecated in this context; use an explicit cast instead
+ factoryTemplateAndMacro<ConvertibleTo<int>>();
+ TemplateFactoryInMacro(ConvertibleTo<int>());
+}
More information about the cfe-commits
mailing list