216 lines · cpp
1// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-optional-value-conversion %t -- --fix-notes2// RUN: %check_clang_tidy -check-suffix=CUSTOM -std=c++17-or-later %s bugprone-optional-value-conversion %t -- \3// RUN: -config="{CheckOptions: {bugprone-optional-value-conversion.OptionalTypes: 'CustomOptional', \4// RUN: bugprone-optional-value-conversion.ValueMethods: '::Read$;::Ooo$'}}" --fix-notes5 6namespace std {7 template<typename T>8 struct optional9 {10 constexpr optional() noexcept;11 constexpr optional(T&&) noexcept;12 constexpr optional(const T&) noexcept;13 template<typename U>14 constexpr optional(U&&) noexcept;15 const T& operator*() const;16 T* operator->();17 const T* operator->() const;18 T& operator*();19 const T& value() const;20 T& value();21 const T& get() const;22 T& get();23 T value_or(T) const;24 };25 26 template <class T>27 T&& move(T &x) {28 return static_cast<T&&>(x);29 }30}31 32namespace boost {33 template<typename T>34 struct optional {35 constexpr optional() noexcept;36 constexpr optional(const T&) noexcept;37 const T& operator*() const;38 const T& get() const;39 };40}41 42namespace absl {43 template<typename T>44 struct optional {45 constexpr optional() noexcept;46 constexpr optional(const T&) noexcept;47 const T& operator*() const;48 const T& value() const;49 };50}51 52template<typename T>53struct CustomOptional {54 CustomOptional();55 CustomOptional(const T&);56 const T& Read() const;57 T& operator*();58 T& Ooo();59};60 61void takeOptionalValue(std::optional<int>);62void takeOptionalRef(const std::optional<int>&);63void takeOptionalRRef(std::optional<int>&&);64void takeOtherOptional(std::optional<long>);65void takeBOptionalValue(boost::optional<int>);66void takeAOptionalValue(absl::optional<int>);67 68void incorrect(std::optional<int> param)69{70 std::optional<int>* ptr = ¶m;71 takeOptionalValue(**ptr);72 // 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]73 // CHECK-FIXES: takeOptionalValue(*ptr);74 takeOptionalValue(*param);75 // 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]76 // CHECK-FIXES: takeOptionalValue(param);77 takeOptionalValue(param.value());78 // 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]79 // CHECK-FIXES: takeOptionalValue(param);80 takeOptionalValue(ptr->value());81 // 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]82 // CHECK-FIXES: takeOptionalValue(*ptr);83 takeOptionalValue(param.operator*());84 // 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]85 // CHECK-FIXES: takeOptionalValue(param);86 takeOptionalValue(ptr->operator*());87 // 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]88 // CHECK-FIXES: takeOptionalValue(*ptr);89 takeOptionalRef(*param);90 // 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]91 // CHECK-FIXES: takeOptionalRef(param);92 takeOptionalRef(param.value());93 // 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]94 // CHECK-FIXES: takeOptionalRef(param);95 takeOptionalRef(ptr->value());96 // 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]97 // CHECK-FIXES: takeOptionalRef(*ptr);98 takeOptionalRef(param.operator*());99 // 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]100 // CHECK-FIXES: takeOptionalRef(param);101 takeOptionalRef(ptr->operator*());102 // 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]103 // CHECK-FIXES: takeOptionalRef(*ptr);104 std::optional<int> p = *param;105 // 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]106 // CHECK-FIXES: std::optional<int> p = param;107 108 takeOptionalValue(std::move(**ptr));109 // 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]110 // CHECK-FIXES: takeOptionalValue(std::move(*ptr));111 takeOptionalValue(std::move(*param));112 // 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]113 // CHECK-FIXES: takeOptionalValue(std::move(param));114 takeOptionalValue(std::move(param.value()));115 // 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]116 // CHECK-FIXES: takeOptionalValue(std::move(param));117 takeOptionalValue(std::move(ptr->value()));118 // 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]119 // CHECK-FIXES: takeOptionalValue(std::move(*ptr));120 takeOptionalValue(std::move(param.operator*()));121 // 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]122 // CHECK-FIXES: takeOptionalValue(std::move(param));123 takeOptionalRef(std::move(*param));124 // 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]125 // CHECK-FIXES: takeOptionalRef(std::move(param));126 takeOptionalRef(std::move(param.value()));127 // 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]128 // CHECK-FIXES: takeOptionalRef(std::move(param));129 takeOptionalRef(std::move(ptr->value()));130 // 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]131 // CHECK-FIXES: takeOptionalRef(std::move(*ptr));132 takeOptionalRef(std::move(param.operator*()));133 // 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]134 // CHECK-FIXES: takeOptionalRef(std::move(param));135 takeOptionalRRef(std::move(*param));136 // 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]137 // CHECK-FIXES: takeOptionalRRef(std::move(param));138 takeOptionalRRef(std::move(param.value()));139 // 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]140 // CHECK-FIXES: takeOptionalRRef(std::move(param));141 takeOptionalRRef(std::move(ptr->value()));142 // 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]143 // CHECK-FIXES: takeOptionalRRef(std::move(*ptr));144 takeOptionalRRef(std::move(param.operator*()));145 // 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]146 // CHECK-FIXES: takeOptionalRRef(std::move(param));147 takeOptionalRRef(std::move(ptr->operator*()));148 // 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]149 // CHECK-FIXES: takeOptionalRRef(std::move(*ptr));150 std::optional<int> p2 = std::move(*param);151 // 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]152 // CHECK-FIXES: std::optional<int> p2 = std::move(param);153 154 std::optional<std::optional<int>> opt;155 takeOptionalValue(opt->value());156 // 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]157 // CHECK-FIXES: takeOptionalValue(*opt);158 takeOptionalValue(opt->operator*());159 // 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]160 // CHECK-FIXES: takeOptionalValue(*opt);161 162 boost::optional<int> bopt;163 takeBOptionalValue(*bopt);164 // 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]165 // CHECK-FIXES: takeBOptionalValue(bopt);166 takeBOptionalValue(bopt.get());167 // 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]168 // CHECK-FIXES: takeBOptionalValue(bopt);169 170 absl::optional<int> aopt;171 takeAOptionalValue(*aopt);172 // 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]173 // CHECK-FIXES: takeAOptionalValue(aopt);174 takeAOptionalValue(aopt.value());175 // 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]176 // CHECK-FIXES: takeAOptionalValue(aopt);177}178 179void takeCustom(const CustomOptional<int>&);180 181void testCustom(CustomOptional<int> param) {182 takeCustom(*param);183 // 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]184 // CHECK-FIXES-CUSTOM: takeCustom(param);185 takeCustom(param.Read());186 // 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]187 // CHECK-FIXES-CUSTOM: takeCustom(param);188 takeCustom(param.Ooo());189 // 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]190 // CHECK-FIXES-CUSTOM: takeCustom(param);191}192 193void correct(std::optional<int> param)194{195 takeOtherOptional(*param);196 takeOtherOptional(param.value());197 takeOtherOptional(param.value_or(5U));198 takeOtherOptional(param.operator*());199 200 std::optional<long> p = *param;201 takeOptionalValue(param.value_or(5U));202 takeOptionalRef(param.value_or(5U));203 204 std::optional<int>* ptr = ¶m;205 takeOtherOptional(**ptr);206 takeOtherOptional(ptr->value());207 takeOtherOptional(ptr->value_or(5U));208 takeOtherOptional(ptr->operator*());209 210 std::optional<long>* p2 = &p;211 takeOptionalValue(p2->value_or(5U));212 takeOptionalRef(p2->value_or(5U));213 214 using Type = decltype(takeOptionalValue(*param));215}216