// RUN: %check_clang_tidy %s llvm-prefer-isa-or-dyn-cast-in-conditionals %t struct X; struct Y; struct Z { int foo(); X *bar(); X *cast(Y*); bool baz(Y*); }; namespace llvm { template bool isa(Y *); template X *cast(Y *); template X *cast_or_null(Y *); template X *dyn_cast(Y *); template X *dyn_cast_or_null(Y *); } // namespace llvm using namespace llvm; bool foo(Y *y, Z *z) { if (auto x = cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (auto x = dyn_cast(y)) if (auto x = ::cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (auto x = ::dyn_cast(y)) if (auto x = llvm::cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (auto x = llvm::dyn_cast(y)) if (auto x = ::llvm::cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:24: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (auto x = ::llvm::dyn_cast(y)) for (; auto x = cast(y); ) break; // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: cast<> in conditional // CHECK-FIXES: for (; auto x = dyn_cast(y); ) while (auto x = cast(y)) break; // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: cast<> in conditional // CHECK-FIXES: while (auto x = dyn_cast(y)) if (cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: cast<> in conditional // CHECK-FIXES: if (isa(y)) if (auto x = cast(y); cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: cast<> in conditional will assert rather than return a null pointer [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (auto x = cast(y); isa(y)) for (; cast(y); ) break; // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: cast<> in conditional // CHECK-FIXES: for (; isa(y); ) while (cast(y)) break; // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: cast<> in conditional // CHECK-FIXES: while (isa(y)) do { break; } while (cast(y)); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: cast<> in conditional // CHECK-FIXES: } while (isa(y)); if (dyn_cast(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: return value from dyn_cast<> not used [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (isa(y)) for (; dyn_cast(y); ) break; // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: return value from dyn_cast<> not used // CHECK-FIXES: for (; isa(y); ) while (dyn_cast(y)) break; // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: return value from dyn_cast<> not used // CHECK-FIXES: while (isa(y)) do { break; } while (dyn_cast(y)); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: return value from dyn_cast<> not used // CHECK-FIXES: } while (isa(y)); if (y && isa(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (isa_and_nonnull(y)) if (y && ::isa(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (::isa_and_nonnull(y)) if (y && llvm::isa(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (llvm::isa_and_nonnull(y)) if (y && ::llvm::isa(y)) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred over an explicit test for null followed by calling isa<> [llvm-prefer-isa-or-dyn-cast-in-conditionals] // CHECK-FIXES: if (::llvm::isa_and_nonnull(y)) if (z->bar() && isa(z->bar())) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: if (isa_and_nonnull(z->bar())) if (z->bar() && cast(z->bar())) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: if (isa_and_nonnull(z->bar())) if (z->bar() && cast_or_null(z->bar())) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: if (isa_and_nonnull(z->bar())) if (z->bar() && dyn_cast(z->bar())) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: if (isa_and_nonnull(z->bar())) if (z->bar() && dyn_cast_or_null(z->bar())) return true; // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: if (isa_and_nonnull(z->bar())) bool b = z->bar() && cast(z->bar()); // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: isa_and_nonnull<> is preferred // CHECK-FIXES: bool b = isa_and_nonnull(z->bar()); // These don't trigger a warning. if (auto x = cast(y)->foo()) return true; if (auto x = z->cast(y)) return true; while (auto x = cast(y)->foo()) break; if (cast(y)->foo()) return true; if (z->cast(y)) return true; while (cast(y)->foo()) break; if (y && cast(z->bar())) return true; if (z && cast(y)->foo()) return true; bool b2 = y && cast(z); if(z->cast(y)) return true; if (z->baz(cast(z))) return true; #define CAST(T, Obj) cast(Obj) #define AUTO_VAR_CAST(X, Y, Z) auto X = cast(Z) #define ISA(T, Obj) isa(Obj) #define ISA_OR_NULL(T, Obj) Obj &&isa(Obj) // Macros don't trigger warning. if (auto x = CAST(X, y)) return true; if (AUTO_VAR_CAST(x, X, z)) return true; if (z->bar() && ISA(Y, z->bar())) return true; if (ISA_OR_NULL(Y, z->bar())) return true; return false; }