// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-optional-value-conversion %t -- --fix-notes
// RUN: %check_clang_tidy -check-suffix=CUSTOM -std=c++17-or-later %s bugprone-optional-value-conversion %t -- \
// RUN: -config="{CheckOptions: {bugprone-optional-value-conversion.OptionalTypes: 'CustomOptional', \
// RUN: bugprone-optional-value-conversion.ValueMethods: '::Read$;::Ooo$'}}" --fix-notes
namespace std {
template<typename T>
struct optional
{
constexpr optional() noexcept;
constexpr optional(T&&) noexcept;
constexpr optional(const T&) noexcept;
template<typename U>
constexpr optional(U&&) noexcept;
const T& operator*() const;
T* operator->();
const T* operator->() const;
T& operator*();
const T& value() const;
T& value();
const T& get() const;
T& get();
T value_or(T) const;
};
template <class T>
T&& move(T &x) {
return static_cast<T&&>(x);
}
}
namespace boost {
template<typename T>
struct optional {
constexpr optional() noexcept;
constexpr optional(const T&) noexcept;
const T& operator*() const;
const T& get() const;
};
}
namespace absl {
template<typename T>
struct optional {
constexpr optional() noexcept;
constexpr optional(const T&) noexcept;
const T& operator*() const;
const T& value() const;
};
}
template<typename T>
struct CustomOptional {
CustomOptional();
CustomOptional(const T&);
const T& Read() const;
T& operator*();
T& Ooo();
};
void takeOptionalValue(std::optional<int>);
void takeOptionalRef(const std::optional<int>&);
void takeOptionalRRef(std::optional<int>&&);
void takeOtherOptional(std::optional<long>);
void takeBOptionalValue(boost::optional<int>);
void takeAOptionalValue(absl::optional<int>);
void incorrect(std::optional<int> param)
{
std::optional<int>* ptr = ¶m;
takeOptionalValue(**ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(*ptr);
takeOptionalValue(*param);
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(param);
takeOptionalValue(param.value());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(param);
takeOptionalValue(ptr->value());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(*ptr);
takeOptionalValue(param.operator*());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(param);
takeOptionalValue(ptr->operator*());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(*ptr);
takeOptionalRef(*param);
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(param);
takeOptionalRef(param.value());
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(param);
takeOptionalRef(ptr->value());
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(*ptr);
takeOptionalRef(param.operator*());
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(param);
takeOptionalRef(ptr->operator*());
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(*ptr);
std::optional<int> p = *param;
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: std::optional<int> p = param;
takeOptionalValue(std::move(**ptr));
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(std::move(*ptr));
takeOptionalValue(std::move(*param));
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(std::move(param));
takeOptionalValue(std::move(param.value()));
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(std::move(param));
takeOptionalValue(std::move(ptr->value()));
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(std::move(*ptr));
takeOptionalValue(std::move(param.operator*()));
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(std::move(param));
takeOptionalRef(std::move(*param));
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(std::move(param));
takeOptionalRef(std::move(param.value()));
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(std::move(param));
takeOptionalRef(std::move(ptr->value()));
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(std::move(*ptr));
takeOptionalRef(std::move(param.operator*()));
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRef(std::move(param));
takeOptionalRRef(std::move(*param));
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRRef(std::move(param));
takeOptionalRRef(std::move(param.value()));
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRRef(std::move(param));
takeOptionalRRef(std::move(ptr->value()));
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRRef(std::move(*ptr));
takeOptionalRRef(std::move(param.operator*()));
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRRef(std::move(param));
takeOptionalRRef(std::move(ptr->operator*()));
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalRRef(std::move(*ptr));
std::optional<int> p2 = std::move(*param);
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: std::optional<int> p2 = std::move(param);
std::optional<std::optional<int>> opt;
takeOptionalValue(opt->value());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(*opt);
takeOptionalValue(opt->operator*());
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeOptionalValue(*opt);
boost::optional<int> bopt;
takeBOptionalValue(*bopt);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'boost::optional<int>' into 'int' and back into 'boost::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeBOptionalValue(bopt);
takeBOptionalValue(bopt.get());
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'boost::optional<int>' into 'int' and back into 'boost::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeBOptionalValue(bopt);
absl::optional<int> aopt;
takeAOptionalValue(*aopt);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'absl::optional<int>' into 'int' and back into 'absl::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeAOptionalValue(aopt);
takeAOptionalValue(aopt.value());
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: conversion from 'absl::optional<int>' into 'int' and back into 'absl::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES: takeAOptionalValue(aopt);
}
void takeCustom(const CustomOptional<int>&);
void testCustom(CustomOptional<int> param) {
takeCustom(*param);
// CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES-CUSTOM: takeCustom(param);
takeCustom(param.Read());
// CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES-CUSTOM: takeCustom(param);
takeCustom(param.Ooo());
// CHECK-MESSAGES-CUSTOM: :[[@LINE-1]]:14: warning: conversion from 'CustomOptional<int>' into 'int' and back into 'CustomOptional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion]
// CHECK-FIXES-CUSTOM: takeCustom(param);
}
void correct(std::optional<int> param)
{
takeOtherOptional(*param);
takeOtherOptional(param.value());
takeOtherOptional(param.value_or(5U));
takeOtherOptional(param.operator*());
std::optional<long> p = *param;
takeOptionalValue(param.value_or(5U));
takeOptionalRef(param.value_or(5U));
std::optional<int>* ptr = ¶m;
takeOtherOptional(**ptr);
takeOtherOptional(ptr->value());
takeOtherOptional(ptr->value_or(5U));
takeOtherOptional(ptr->operator*());
std::optional<long>* p2 = &p;
takeOptionalValue(p2->value_or(5U));
takeOptionalRef(p2->value_or(5U));
using Type = decltype(takeOptionalValue(*param));
}