1 // RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-optional-value-conversion %t 2 3 namespace std { 4 template <typename T> struct optional { 5 constexpr optional() noexcept; 6 constexpr optional(T &&) noexcept; 7 constexpr optional(const T &) noexcept; 8 template <typename U> constexpr optional(U &&) noexcept; 9 const T &operator*() const; 10 T *operator->(); 11 const T *operator->() const; 12 T &operator*(); 13 const T &value() const; 14 T &value(); 15 const T &get() const; 16 T &get(); 17 T value_or(T) const; 18 }; 19 20 template <class T> T &&move(T &x) { return static_cast<T &&>(x); } 21 22 template <typename T> class default_delete {}; 23 24 template <typename type, typename Deleter = std::default_delete<type>> 25 class unique_ptr {}; 26 27 template <typename type> 28 class shared_ptr {}; 29 30 template <class T, class... Args> unique_ptr<T> make_unique(Args &&...args); 31 template <class T, class... Args> shared_ptr<T> make_shared(Args &&...args); 32 33 } // namespace std 34 35 struct A { 36 explicit A (int); 37 }; 38 std::optional<int> opt; 39 40 void invalid() { 41 std::make_unique<std::optional<int>>(opt.value()); 42 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion] 43 using A = std::optional<int>; 44 std::make_unique<A>(opt.value()); 45 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion] 46 std::make_shared<std::optional<int>>(opt.value()); 47 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: conversion from 'std::optional<int>' into 'int' and back into 'std::optional<int>', remove potentially error-prone optional dereference [bugprone-optional-value-conversion] 48 } 49 50 void valid() { 51 std::make_unique<A>(opt.value()); 52 std::make_shared<A>(opt.value()); 53 } 54