MoveConstArgCheck.cpp
MoveConstructorInitCheck.cpp
NoAutomaticMoveCheck.cpp
+ NoIntToPtrCheck.cpp
NoexceptMoveConstructorCheck.cpp
PerformanceTidyModule.cpp
TriviallyDestructibleCheck.cpp
--- /dev/null
+//===--- NoIntToPtrCheck.cpp - clang-tidy ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "NoIntToPtrCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+void NoIntToPtrCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(castExpr(hasCastKind(CK_IntegralToPointer),
+ unless(hasSourceExpression(integerLiteral())))
+ .bind("x"),
+ this);
+}
+
+void NoIntToPtrCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedCast = Result.Nodes.getNodeAs<CastExpr>("x");
+ diag(MatchedCast->getBeginLoc(),
+ "integer to pointer cast pessimizes optimization opportunities");
+}
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
--- /dev/null
+//===--- NoIntToPtrCheck.h - clang-tidy -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace performance {
+
+/// Diagnoses every integer to pointer cast.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/performance-no-int-to-ptr.html
+class NoIntToPtrCheck : public ClangTidyCheck {
+public:
+ NoIntToPtrCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace performance
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_NOINTTOPTRCHECK_H
#include "MoveConstArgCheck.h"
#include "MoveConstructorInitCheck.h"
#include "NoAutomaticMoveCheck.h"
+#include "NoIntToPtrCheck.h"
#include "NoexceptMoveConstructorCheck.h"
#include "TriviallyDestructibleCheck.h"
#include "TypePromotionInMathFnCheck.h"
"performance-move-constructor-init");
CheckFactories.registerCheck<NoAutomaticMoveCheck>(
"performance-no-automatic-move");
+ CheckFactories.registerCheck<NoIntToPtrCheck>("performance-no-int-to-ptr");
CheckFactories.registerCheck<NoexceptMoveConstructorCheck>(
"performance-noexcept-move-constructor");
CheckFactories.registerCheck<TriviallyDestructibleCheck>(
Alias to the :doc:`bugprone-signal-handler
<clang-tidy/checks/bugprone-signal-handler>` check.
+- New :doc:`performance-no-int-to-ptr
+ <clang-tidy/checks/performance-no-int-to-ptr>` check.
+
+ Diagnoses every integer to pointer cast.
+
- New :doc:`readability-function-cognitive-complexity
<clang-tidy/checks/readability-function-cognitive-complexity>` check.
`performance-move-const-arg <performance-move-const-arg.html>`_, "Yes"
`performance-move-constructor-init <performance-move-constructor-init.html>`_, "Yes"
`performance-no-automatic-move <performance-no-automatic-move.html>`_,
+ `performance-no-int-to-ptr <performance-no-int-to-ptr.html>`_,
`performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_, "Yes"
`performance-trivially-destructible <performance-trivially-destructible.html>`_, "Yes"
`performance-type-promotion-in-math-fn <performance-type-promotion-in-math-fn.html>`_, "Yes"
--- /dev/null
+.. title:: clang-tidy - performance-no-int-to-ptr
+
+performance-no-int-to-ptr
+=========================
+
+Diagnoses every integer to pointer cast.
+
+While casting an (integral) pointer to an integer is obvious - you just get
+the integral value of the pointer, casting an integer to an (integral) pointer
+is deceivingly different. While you will get a pointer with that integral value,
+if you got that integral value via a pointer-to-integer cast originally,
+the new pointer will lack the provenance information from the original pointer.
+
+So while (integral) pointer to integer casts are effectively no-ops,
+and are transparent to the optimizer, integer to (integral) pointer casts
+are *NOT* transparent, and may conceal information from optimizer.
+
+While that may be the intention, it is not always so. For example,
+let's take a look at a routine to align the pointer up to the multiple of 16:
+The obvious, naive implementation for that is:
+
+.. code-block:: c++
+
+ char* src(char* maybe_underbiased_ptr) {
+ uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
+ uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
+ uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
+ return (char*)aligned_intptr; // warning: avoid integer to pointer casts [performance-no-int-to-ptr]
+ }
+
+The check will rightfully diagnose that cast.
+
+But when provenance concealment is not the goal of the code, but an accident,
+this example can be rewritten as follows, without using integer to pointer cast:
+
+.. code-block:: c++
+
+ char*
+ tgt(char* maybe_underbiased_ptr) {
+ uintptr_t maybe_underbiased_intptr = (uintptr_t)maybe_underbiased_ptr;
+ uintptr_t aligned_biased_intptr = maybe_underbiased_intptr + 15;
+ uintptr_t aligned_intptr = aligned_biased_intptr & (~15);
+ uintptr_t bias = aligned_intptr - maybe_underbiased_intptr;
+ return maybe_underbiased_ptr + bias;
+ }
--- /dev/null
+// RUN: %check_clang_tidy %s performance-no-int-to-ptr %t
+
+void *t0(char x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t1(signed char x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t2(unsigned char x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+void *t3(short x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t4(unsigned short x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t5(signed short x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+void *t6(int x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t7(unsigned int x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t8(signed int x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+void *t9(long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t10(unsigned long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t11(signed long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+void *t12(long long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t13(unsigned long long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+void *t14(signed long long x) {
+ return x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
--- /dev/null
+// RUN: %check_clang_tidy %s performance-no-int-to-ptr %t
+
+// can't implicitly cast int to a pointer.
+// can't use static_cast<>() to cast integer to a pointer.
+// can't use dynamic_cast<>() to cast integer to a pointer.
+// can't use const_cast<>() to cast integer to a pointer.
+
+void *t0(long long int x) {
+ return (void *)x;
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+void *t1(int x) {
+ return reinterpret_cast<void *>(x);
+ // CHECK-MESSAGES: [[@LINE-1]]:10: warning: integer to pointer cast pessimizes optimization opportunities [performance-no-int-to-ptr]
+}
+
+// Don't diagnose casts from integer literals.
+// It's a widely-used technique in embedded/microcontroller/hardware interfacing.
+void *t3(long long int x) {
+ return (void *)0xFEEDFACE;
+}