Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Flags implicit conversions; spell them out with a named cast or an explicit
# construction instead. Ported from misc-no-implicit-conversions in
# https://github.com/lefticus/llvm-project (add-implicit-conversion-checks).
#
# Value category adjustments, qualification changes, function decay, binding
# derived objects to base references or pointers, string literal decay,
# integer literal narrowing, nullptr and switch/case integral promotions are
# allowed.
set traversal AsIs

# Implicit conversions between built-in types, 0 to pointer and calls to
# conversion operators.
match implicitCastExpr(isExpansionInMainFile(),
unless(anyOf(hasCastKind("CK_LValueToRValue"),
hasCastKind("CK_FunctionToPointerDecay"),
hasCastKind("CK_NoOp"),
hasCastKind("CK_UncheckedDerivedToBase"),
hasCastKind("CK_DerivedToBase"),
allOf(hasCastKind("CK_ArrayToPointerDecay"), has(stringLiteral())),
allOf(hasCastKind("CK_IntegralCast"), has(integerLiteral())),
allOf(hasCastKind("CK_NullToPointer"), has(cxxNullPtrLiteralExpr())),
hasParent(cxxStaticCastExpr()),
allOf(hasCastKind("CK_IntegralCast"), hasParent(switchStmt())),
allOf(hasCastKind("CK_IntegralCast"),
hasParent(constantExpr(hasParent(caseStmt())))))))

# Temporaries with destructors created through a converting constructor.
match materializeTemporaryExpr(isExpansionInMainFile(),
has(cxxBindTemporaryExpr(has(cxxConstructExpr(has(implicitCastExpr()))))))

# Copies of a derived object into a base object.
match cxxConstructExpr(isExpansionInMainFile(),
hasDeclaration(cxxConstructorDecl(anyOf(isCopyConstructor(), isMoveConstructor()))),
has(implicitCastExpr(hasCastKind("CK_DerivedToBase"))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
void take_double(double);
void take_long_long(long long);

void promote_arguments(const float single, const int integer)
{
take_double(single);// expect-finding
take_double(integer);// expect-finding
take_long_long(integer);// expect-finding
take_double(1.3f);// expect-finding
take_double(1);// expect-finding
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
template<typename Char> struct basic_string_view
{
basic_string_view(const Char *);// NOLINT(google-explicit-constructor)
};

template<typename Char> struct basic_string
{
basic_string();
~basic_string();
operator basic_string_view<Char>() const;// NOLINT(google-explicit-constructor)
};

basic_string_view<char> dangling_view()
{
const basic_string<char> value;
return value;// expect-finding
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
struct Base
{
};
struct Derived : Base
{
};

template<typename T> struct Holder
{
template<typename Other> Holder(const Holder<Other> &);// NOLINT(google-explicit-constructor)

Holder() = default;
};

void take_holder(const Holder<Base> &);

void pass_converted_holders()
{
const auto derived = Holder<Derived>{};
take_holder(derived);// expect-finding
take_holder(Holder<Derived>());// expect-finding
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
struct string
{
};

struct istream
{
explicit operator bool() const;
~istream();
};

istream &getline(istream &input, string &output);

void read_lines()
{
istream input;
string output;

while (getline(input, output)) {// expect-finding
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
template<typename Char> struct basic_string
{
basic_string(const Char *);// NOLINT(google-explicit-constructor)
basic_string(const basic_string &);
~basic_string();
[[nodiscard]] const Char *c_str() const;
};

using string = basic_string<char>;

string copy_through_c_str(const string &value)
{
return value.c_str();// expect-finding
}
17 changes: 17 additions & 0 deletions checks/clang-query/no-implicit-conversions/tests/fail/slicing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
struct Base
{
};
struct Derived : Base
{
};

void take_by_value(Base);

void slice_derived()
{
const auto derived = Derived{};

take_by_value(derived);// expect-finding
[[maybe_unused]] const Base sliced = derived;// expect-finding
take_by_value(Derived{});// expect-finding
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
struct Base
{
};

void take_pointer(const Base *);

void pass_zero() { take_pointer(0); }// expect-finding
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
struct Base
{
};
struct Derived : Base
{
};

void take_base(const Base &);
void take_base(const Base *);

void bind_derived()
{
const auto derived = Derived{};
take_base(&derived);
take_base(Derived{});
take_base(derived);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
struct Base
{
};
struct Derived : Base
{
};

struct Observer
{
explicit Observer(const Base *);
};

void observe(const Derived &derived) { [[maybe_unused]] const Observer observer(&derived); }
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
struct Base
{
};

template<typename T> struct Holder
{
template<typename Other> Holder(const Holder<Other> &);// NOLINT(google-explicit-constructor)

Holder() = default;
};

void take_holder(const Holder<Base> &);
void take_by_value(Base);
void take_pointer(const Base *);
void take_double(double);

void pass_exact_types(const double value)
{
take_holder(Holder<Base>());
take_by_value(Base{});
take_pointer(nullptr);
take_double(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
struct istream
{
explicit operator bool() const;
[[nodiscard]] bool good() const;
};

void take_double(double);

void convert_explicitly(const istream &input, const int value)
{
while (input.good()) {}
take_double(static_cast<double>(value));
[[maybe_unused]] const bool valid = static_cast<bool>(input);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
void take_string(const char *);

[[nodiscard]] int classify(const char value)
{
take_string("literal");
[[maybe_unused]] const long widened = 1;

switch (value) {
case 'a':
return 1;
default:
return 0;
}
}
Loading