LCOV - code coverage report
Current view: top level - include/llvm/ADT - Optional.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 336 411 81.8 %
Date: 2018-10-16 05:50:02 Functions: 293 2063 14.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : //  This file provides Optional, a template class modeled in the spirit of
      11             : //  OCaml's 'opt' variant.  The idea is to strongly type whether or not
      12             : //  a value can be optional.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #ifndef LLVM_ADT_OPTIONAL_H
      17             : #define LLVM_ADT_OPTIONAL_H
      18             : 
      19             : #include "llvm/ADT/None.h"
      20             : #include "llvm/Support/AlignOf.h"
      21             : #include "llvm/Support/Compiler.h"
      22             : #include "llvm/Support/type_traits.h"
      23             : #include <algorithm>
      24             : #include <cassert>
      25             : #include <new>
      26             : #include <utility>
      27             : 
      28             : namespace llvm {
      29             : 
      30             : namespace optional_detail {
      31             : /// Storage for any type.
      32             : template <typename T, bool IsPodLike> struct OptionalStorage {
      33             :   AlignedCharArrayUnion<T> storage;
      34             :   bool hasVal = false;
      35             : 
      36   577489510 :   OptionalStorage() = default;
      37             : 
      38    48596306 :   OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
      39   114711596 :   OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
      40    70972009 :     if (hasVal)
      41    11707871 :       new (storage.buffer) T(*O.getPointer());
      42      313835 :   }
      43   270068667 :   OptionalStorage(T &&y) : hasVal(true) {
      44   217887248 :     new (storage.buffer) T(std::forward<T>(y));
      45         215 :   }
      46    42503486 :   OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
      47    26710417 :     if (O.hasVal) {
      48    30301280 :       new (storage.buffer) T(std::move(*O.getPointer()));
      49           2 :     }
      50        2377 :   }
      51           1 : 
      52     3358108 :   OptionalStorage &operator=(T &&y) {
      53    16995445 :     if (hasVal)
      54     3417036 :       *getPointer() = std::move(y);
      55          79 :     else {
      56     9726808 :       new (storage.buffer) T(std::move(y));
      57    22330116 :       hasVal = true;
      58             :     }
      59     3358107 :     return *this;
      60          11 :   }
      61      237535 :   OptionalStorage &operator=(OptionalStorage &&O) {
      62     5661082 :     if (!O.hasVal)
      63      165574 :       reset();
      64             :     else {
      65      124116 :       *this = std::move(*O.getPointer());
      66       36898 :     }
      67       35054 :     return *this;
      68      202476 :   }
      69           4 : 
      70        6395 :   // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
      71        6391 :   // could be made more efficient by passing by value, possibly unifying them
      72        1779 :   // with the rvalue versions above - but this could place a different set of
      73           4 :   // requirements (notably: the existence of a default ctor) when implemented
      74         114 :   // in that way. Careful SFINAE to avoid such pitfalls would be required.
      75       25213 :   OptionalStorage &operator=(const T &y) {
      76     2543669 :     if (hasVal)
      77     1006180 :       *getPointer() = y;
      78           0 :     else {
      79     3527141 :       new (storage.buffer) T(y);
      80     3609317 :       hasVal = true;
      81          12 :     }
      82       21134 :     return *this;
      83      267353 :   }
      84       25999 :   OptionalStorage &operator=(const OptionalStorage &O) {
      85     1671160 :     if (!O.hasVal)
      86         691 :       reset();
      87           0 :     else
      88       58338 :       *this = *O.getPointer();
      89       36754 :     return *this;
      90           0 :   }
      91           0 : 
      92       78174 :   ~OptionalStorage() { reset(); }
      93        1618 : 
      94     3149274 :   void reset() {
      95    14863247 :     if (hasVal) {
      96     2207698 :       (*getPointer()).~T();
      97      650004 :       hasVal = false;
      98      120034 :     }
      99     3113704 :   }
     100     2282098 : 
     101     2281850 :   T *getPointer() {
     102        3599 :     assert(hasVal);
     103     5825787 :     return reinterpret_cast<T *>(storage.buffer);
     104        8680 :   }
     105     2291273 :   const T *getPointer() const {
     106      322997 :     assert(hasVal);
     107       55356 :     return reinterpret_cast<const T *>(storage.buffer);
     108        4275 :   }
     109        1598 : };
     110       60650 : 
     111       57723 : #if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
     112       72739 : /// Storage for trivially copyable types only.
     113    17277280 : template <typename T> struct OptionalStorage<T, true> {
     114      119688 :   AlignedCharArrayUnion<T> storage;
     115     2244014 :   bool hasVal = false;
     116         131 : 
     117       71395 :   OptionalStorage() = default;
     118         498 : 
     119       84594 :   OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
     120        9325 :   OptionalStorage &operator=(const T &y) {
     121      345130 :     *reinterpret_cast<T *>(storage.buffer) = y;
     122        8996 :     hasVal = true;
     123        1451 :     return *this;
     124       72241 :   }
     125       80552 : 
     126           0 :   void reset() { hasVal = false; }
     127       29461 : };
     128           0 : #endif
     129       71253 : } // namespace optional_detail
     130          98 : 
     131     8289284 : template <typename T> class Optional {
     132           0 :   optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
     133        5062 : 
     134           0 : public:
     135       14072 :   using value_type = T;
     136       18366 : 
     137    32064572 :   constexpr Optional() {}
     138     7805864 :   constexpr Optional(NoneType) {}
     139       26255 : 
     140    22353222 :   Optional(const T &y) : Storage(y) {}
     141    51239617 :   Optional(const Optional &O) = default;
     142       14111 : 
     143    30820182 :   Optional(T &&y) : Storage(std::forward<T>(y)) {}
     144    10199552 :   Optional(Optional &&O) = default;
     145          54 : 
     146       20399 :   Optional &operator=(T &&y) {
     147     3133013 :     Storage = std::move(y);
     148       14353 :     return *this;
     149     1735995 :   }
     150     7100000 :   Optional &operator=(Optional &&O) = default;
     151        7175 : 
     152       18159 :   /// Create a new object by constructing it in place with the given arguments.
     153     3007644 :   template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
     154       12973 :     reset();
     155     7934046 :     Storage.hasVal = true;
     156     5745318 :     new (getPointer()) T(std::forward<ArgTypes>(Args)...);
     157      347162 :   }
     158      480031 : 
     159      169224 :   static inline Optional create(const T *y) {
     160       67029 :     return y ? Optional(*y) : Optional();
     161     4617455 :   }
     162      861299 : 
     163       53680 :   Optional &operator=(const T &y) {
     164       17011 :     Storage = y;
     165    13111700 :     return *this;
     166       53582 :   }
     167    22918803 :   Optional &operator=(const Optional &O) = default;
     168    10552937 : 
     169     2797627 :   void reset() { Storage.reset(); }
     170       27264 : 
     171      761159 :   const T *getPointer() const {
     172         144 :     assert(Storage.hasVal);
     173    37195843 :     return reinterpret_cast<const T *>(Storage.storage.buffer);
     174    27048296 :   }
     175     1398308 :   T *getPointer() {
     176       13421 :     assert(Storage.hasVal);
     177    25535320 :     return reinterpret_cast<T *>(Storage.storage.buffer);
     178     1398485 :   }
     179   150205974 :   const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
     180     2466195 :   T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
     181      880022 : 
     182     1599565 :   explicit operator bool() const { return Storage.hasVal; }
     183     1456837 :   bool hasValue() const { return Storage.hasVal; }
     184     1415443 :   const T *operator->() const { return getPointer(); }
     185      539943 :   T *operator->() { return getPointer(); }
     186     3677569 :   const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
     187     1054277 :   T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
     188     3377619 : 
     189      465594 :   template <typename U>
     190         997 :   constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
     191    60868964 :     return hasValue() ? getValue() : std::forward<U>(value);
     192     1555261 :   }
     193         160 : 
     194     2748157 : #if LLVM_HAS_RVALUE_REFERENCE_THIS
     195     2986920 :   T &&getValue() && { return std::move(*getPointer()); }
     196         967 :   T &&operator*() && { return std::move(*getPointer()); }
     197     2005505 : 
     198       15841 :   template <typename U>
     199       34453 :   T getValueOr(U &&value) && {
     200     1369494 :     return hasValue() ? std::move(getValue()) : std::forward<U>(value);
     201       64682 :   }
     202           3 : #endif
     203      446180 : };
     204     4492498 : 
     205      150209 : template <typename T> struct isPodLike<Optional<T>> {
     206      337071 :   // An Optional<T> is pod-like if T is.
     207      281480 :   static const bool value = isPodLike<T>::value;
     208      146771 : };
     209      860462 : 
     210       34758 : template <typename T, typename U>
     211         213 : bool operator==(const Optional<T> &X, const Optional<U> &Y) {
     212      506357 :   if (X && Y)
     213       24575 :     return *X == *Y;
     214      146751 :   return X.hasValue() == Y.hasValue();
     215      501132 : }
     216      150178 : 
     217       13453 : template <typename T, typename U>
     218       43433 : bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
     219          83 :   return !(X == Y);
     220      593546 : }
     221       46181 : 
     222       29752 : template <typename T, typename U>
     223          72 : bool operator<(const Optional<T> &X, const Optional<U> &Y) {
     224         994 :   if (X && Y)
     225     1022202 :     return *X < *Y;
     226          31 :   return X.hasValue() < Y.hasValue();
     227     7036186 : }
     228       26212 : 
     229         220 : template <typename T, typename U>
     230       44322 : bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
     231      298263 :   return !(Y < X);
     232       26378 : }
     233      485162 : 
     234        5785 : template <typename T, typename U>
     235          15 : bool operator>(const Optional<T> &X, const Optional<U> &Y) {
     236       17404 :   return Y < X;
     237        2243 : }
     238        1911 : 
     239     1234545 : template <typename T, typename U>
     240       73427 : bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
     241       15272 :   return !(X < Y);
     242       29241 : }
     243        2498 : 
     244       29569 : template<typename T>
     245          36 : bool operator==(const Optional<T> &X, NoneType) {
     246    27557928 :   return !X;
     247       15326 : }
     248        2527 : 
     249         284 : template<typename T>
     250      166968 : bool operator==(NoneType, const Optional<T> &X) {
     251      119067 :   return X == None;
     252       24269 : }
     253      197440 : 
     254        3741 : template<typename T>
     255           8 : bool operator!=(const Optional<T> &X, NoneType) {
     256         400 :   return !(X == None);
     257     2587697 : }
     258          62 : 
     259          46 : template<typename T>
     260           0 : bool operator!=(NoneType, const Optional<T> &X) {
     261       10148 :   return X != None;
     262      139006 : }
     263      390932 : 
     264     6962969 : template <typename T> bool operator<(const Optional<T> &X, NoneType) {
     265          20 :   return false;
     266         463 : }
     267         979 : 
     268         455 : template <typename T> bool operator<(NoneType, const Optional<T> &X) {
     269          37 :   return X.hasValue();
     270       14503 : }
     271         191 : 
     272      585336 : template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
     273           5 :   return !(None < X);
     274        1359 : }
     275         382 : 
     276      381845 : template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
     277         233 :   return !(X < None);
     278       12599 : }
     279           8 : 
     280       28994 : template <typename T> bool operator>(const Optional<T> &X, NoneType) {
     281        2440 :   return None < X;
     282         417 : }
     283       12472 : 
     284          21 : template <typename T> bool operator>(NoneType, const Optional<T> &X) {
     285          21 :   return X < None;
     286           0 : }
     287       34258 : 
     288           0 : template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
     289          21 :   return None <= X;
     290       44509 : }
     291     5123680 : 
     292           0 : template <typename T> bool operator>=(NoneType, const Optional<T> &X) {
     293           0 :   return X <= None;
     294           1 : }
     295         573 : 
     296           0 : template <typename T> bool operator==(const Optional<T> &X, const T &Y) {
     297       37727 :   return X && *X == Y;
     298           0 : }
     299          11 : 
     300           0 : template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
     301    10158235 :   return Y && X == *Y;
     302           4 : }
     303          34 : 
     304           0 : template <typename T> bool operator!=(const Optional<T> &X, const T &Y) {
     305           0 :   return !(X == Y);
     306           4 : }
     307           0 : 
     308             : template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
     309          50 :   return !(X == Y);
     310           0 : }
     311           0 : 
     312       57627 : template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
     313         471 :   return !X || *X < Y;
     314       57568 : }
     315         513 : 
     316           0 : template <typename T> bool operator<(const T &X, const Optional<T> &Y) {
     317         394 :   return Y && X < *Y;
     318           0 : }
     319           0 : 
     320         105 : template <typename T> bool operator<=(const Optional<T> &X, const T &Y) {
     321           0 :   return !(Y < X);
     322           0 : }
     323           0 : 
     324             : template <typename T> bool operator<=(const T &X, const Optional<T> &Y) {
     325           0 :   return !(Y < X);
     326           0 : }
     327         788 : 
     328           0 : template <typename T> bool operator>(const Optional<T> &X, const T &Y) {
     329      792545 :   return Y < X;
     330          45 : }
     331         222 : 
     332           2 : template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
     333           0 :   return Y < X;
     334           8 : }
     335         183 : 
     336             : template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
     337         369 :   return !(X < Y);
     338           3 : }
     339     1585076 : 
     340           0 : template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
     341          58 :   return !(X < Y);
     342           3 : }
     343           0 : 
     344          28 : } // end namespace llvm
     345      239536 : 
     346          40 : #endif // LLVM_ADT_OPTIONAL_H

Generated by: LCOV version 1.13