LCOV - code coverage report
Current view: top level - include/llvm/ADT - Optional.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 341 403 84.6 %
Date: 2018-10-20 13:21:21 Functions: 290 2065 14.0 %
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   591711245 :   OptionalStorage() = default;
      37             : 
      38    48973487 :   OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
      39   115306275 :   OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) {
      40    71166497 :     if (hasVal)
      41    11666273 :       new (storage.buffer) T(*O.getPointer());
      42      333885 :   }
      43   269332764 :   OptionalStorage(T &&y) : hasVal(true) {
      44   216515018 :     new (storage.buffer) T(std::forward<T>(y));
      45         215 :   }
      46    42847886 :   OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) {
      47    26882652 :     if (O.hasVal) {
      48    30624264 :       new (storage.buffer) T(std::move(*O.getPointer()));
      49           5 :     }
      50        1996 :   }
      51           5 : 
      52     3383022 :   OptionalStorage &operator=(T &&y) {
      53    17176048 :     if (hasVal)
      54     3443209 :       *getPointer() = std::move(y);
      55          10 :     else {
      56     9734140 :       new (storage.buffer) T(std::move(y));
      57    22500704 :       hasVal = true;
      58           8 :     }
      59     3383017 :     return *this;
      60          19 :   }
      61      250327 :   OptionalStorage &operator=(OptionalStorage &&O) {
      62     5747650 :     if (!O.hasVal)
      63      176730 :       reset();
      64             :     else {
      65      124029 :       *this = std::move(*O.getPointer());
      66       38662 :     }
      67       34925 :     return *this;
      68      215396 :   }
      69           6 : 
      70        6634 :   // FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
      71        6628 :   // could be made more efficient by passing by value, possibly unifying them
      72        1835 :   // with the rvalue versions above - but this could place a different set of
      73             :   // requirements (notably: the existence of a default ctor) when implemented
      74         117 :   // in that way. Careful SFINAE to avoid such pitfalls would be required.
      75       25244 :   OptionalStorage &operator=(const T &y) {
      76     2550530 :     if (hasVal)
      77     1015723 :       *getPointer() = y;
      78           6 :     else {
      79     3609036 :       new (storage.buffer) T(y);
      80     3691206 :       hasVal = true;
      81          12 :     }
      82       21000 :     return *this;
      83      278700 :   }
      84       26348 :   OptionalStorage &operator=(const OptionalStorage &O) {
      85     1687779 :     if (!O.hasVal)
      86         691 :       reset();
      87           6 :     else
      88       58756 :       *this = *O.getPointer();
      89       37512 :     return *this;
      90           0 :   }
      91           0 : 
      92       79256 :   ~OptionalStorage() { reset(); }
      93        1707 : 
      94     3154235 :   void reset() {
      95    14945906 :     if (hasVal) {
      96     2208870 :       (*getPointer()).~T();
      97      656310 :       hasVal = false;
      98      125936 :     }
      99     3118155 :   }
     100     2284636 : 
     101     2284314 :   T *getPointer() {
     102        3765 :     assert(hasVal);
     103     5850562 :     return reinterpret_cast<T *>(storage.buffer);
     104        8932 :   }
     105     2294157 :   const T *getPointer() const {
     106      326956 :     assert(hasVal);
     107       55299 :     return reinterpret_cast<const T *>(storage.buffer);
     108        4443 :   }
     109        1612 : };
     110       61035 : 
     111       57869 : #if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this.
     112       72935 : /// Storage for trivially copyable types only.
     113    17440761 : template <typename T> struct OptionalStorage<T, true> {
     114      125303 :   AlignedCharArrayUnion<T> storage;
     115     2236969 :   bool hasVal = false;
     116         131 : 
     117       71595 :   OptionalStorage() = default;
     118         463 : 
     119       90160 :   OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); }
     120        9345 :   OptionalStorage &operator=(const T &y) {
     121      367672 :     *reinterpret_cast<T *>(storage.buffer) = y;
     122        9009 :     hasVal = true;
     123        1440 :     return *this;
     124       72426 :   }
     125       80769 : 
     126           0 :   void reset() { hasVal = false; }
     127       29505 : };
     128           4 : #endif
     129       71450 : } // namespace optional_detail
     130          89 : 
     131     8916207 : template <typename T> class Optional {
     132           0 :   optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage;
     133        5113 : 
     134          37 : public:
     135       14989 :   using value_type = T;
     136       19566 : 
     137    32714490 :   constexpr Optional() {}
     138     7830938 :   constexpr Optional(NoneType) {}
     139       26991 : 
     140    22284809 :   Optional(const T &y) : Storage(y) {}
     141    51297314 :   Optional(const Optional &O) = default;
     142       14991 : 
     143    30818859 :   Optional(T &&y) : Storage(std::forward<T>(y)) {}
     144    10213951 :   Optional(Optional &&O) = default;
     145          54 : 
     146       20662 :   Optional &operator=(T &&y) {
     147     3144779 :     Storage = std::move(y);
     148       14392 :     return *this;
     149     1677800 :   }
     150     7112314 :   Optional &operator=(Optional &&O) = default;
     151        7146 : 
     152       12030 :   /// Create a new object by constructing it in place with the given arguments.
     153     3015604 :   template <typename... ArgTypes> void emplace(ArgTypes &&... Args) {
     154       13811 :     reset();
     155     7949772 :     Storage.hasVal = true;
     156     5751303 :     new (getPointer()) T(std::forward<ArgTypes>(Args)...);
     157      347661 :   }
     158      480707 : 
     159      169233 :   static inline Optional create(const T *y) {
     160       68001 :     return y ? Optional(*y) : Optional();
     161     4623512 :   }
     162      871900 : 
     163       53760 :   Optional &operator=(const T &y) {
     164       17055 :     Storage = y;
     165    13218498 :     return *this;
     166       53773 :   }
     167    23636757 :   Optional &operator=(const Optional &O) = default;
     168    10579249 : 
     169     2799100 :   void reset() { Storage.reset(); }
     170       27075 : 
     171      763754 :   const T *getPointer() const {
     172          16 :     assert(Storage.hasVal);
     173    37833667 :     return reinterpret_cast<const T *>(Storage.storage.buffer);
     174    28148377 :   }
     175     1399008 :   T *getPointer() {
     176       13422 :     assert(Storage.hasVal);
     177    26021362 :     return reinterpret_cast<T *>(Storage.storage.buffer);
     178     1399053 :   }
     179   154261374 :   const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
     180     2482589 :   T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); }
     181      883301 : 
     182     1600487 :   explicit operator bool() const { return Storage.hasVal; }
     183     1469500 :   bool hasValue() const { return Storage.hasVal; }
     184     1417399 :   const T *operator->() const { return getPointer(); }
     185      533873 :   T *operator->() { return getPointer(); }
     186     3679156 :   const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); }
     187     1086427 :   T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); }
     188     3302153 : 
     189      463903 :   template <typename U>
     190         996 :   constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION {
     191    60655763 :     return hasValue() ? getValue() : std::forward<U>(value);
     192     1557470 :   }
     193         187 : 
     194     2751038 : #if LLVM_HAS_RVALUE_REFERENCE_THIS
     195     2990625 :   T &&getValue() && { return std::move(*getPointer()); }
     196         965 :   T &&operator*() && { return std::move(*getPointer()); }
     197     2012442 : 
     198       16728 :   template <typename U>
     199       36014 :   T getValueOr(U &&value) && {
     200     1371529 :     return hasValue() ? std::move(getValue()) : std::forward<U>(value);
     201       64758 :   }
     202           0 : #endif
     203      446674 : };
     204     4495095 : 
     205      158236 : template <typename T> struct isPodLike<Optional<T>> {
     206      337414 :   // An Optional<T> is pod-like if T is.
     207      282361 :   static const bool value = isPodLike<T>::value;
     208      147099 : };
     209      873820 : 
     210       34796 : template <typename T, typename U>
     211          76 : bool operator==(const Optional<T> &X, const Optional<U> &Y) {
     212      507610 :   if (X && Y)
     213       24997 :     return *X == *Y;
     214      147075 :   return X.hasValue() == Y.hasValue();
     215      512749 : }
     216      150709 : 
     217       14328 : template <typename T, typename U>
     218      116813 : bool operator!=(const Optional<T> &X, const Optional<U> &Y) {
     219       24319 :   return !(X == Y);
     220      593548 : }
     221       69329 : 
     222       30194 : template <typename T, typename U>
     223       24312 : bool operator<(const Optional<T> &X, const Optional<U> &Y) {
     224         994 :   if (X && Y)
     225     1045356 :     return *X < *Y;
     226          31 :   return X.hasValue() < Y.hasValue();
     227     7013466 : }
     228        2633 : 
     229         428 : template <typename T, typename U>
     230       20947 : bool operator<=(const Optional<T> &X, const Optional<U> &Y) {
     231      299490 :   return !(Y < X);
     232        2773 : }
     233      561664 : 
     234        5596 : template <typename T, typename U>
     235          15 : bool operator>(const Optional<T> &X, const Optional<U> &Y) {
     236       17405 :   return Y < X;
     237        2243 : }
     238        1913 : 
     239     1234607 : template <typename T, typename U>
     240       73429 : bool operator>=(const Optional<T> &X, const Optional<U> &Y) {
     241       40260 :   return !(X < Y);
     242       29274 : }
     243       26738 : 
     244       29602 : template<typename T>
     245           8 : bool operator==(const Optional<T> &X, NoneType) {
     246    27343750 :   return !X;
     247       16220 : }
     248        2660 : 
     249         284 : template<typename T>
     250      143485 : bool operator==(NoneType, const Optional<T> &X) {
     251      119039 :   return X == None;
     252         710 : }
     253      197815 : 
     254        3707 : template<typename T>
     255           8 : bool operator!=(const Optional<T> &X, NoneType) {
     256         410 :   return !(X == None);
     257     2593448 : }
     258          62 : 
     259         100 : template<typename T>
     260           0 : bool operator!=(NoneType, const Optional<T> &X) {
     261       10142 :   return X != None;
     262      139017 : }
     263      391750 : 
     264     6966904 : template <typename T> bool operator<(const Optional<T> &X, NoneType) {
     265          20 :   return false;
     266         463 : }
     267         973 : 
     268         499 : template <typename T> bool operator<(NoneType, const Optional<T> &X) {
     269           4 :   return X.hasValue();
     270       14724 : }
     271         267 : 
     272      585380 : template <typename T> bool operator<=(const Optional<T> &X, NoneType) {
     273          11 :   return !(None < X);
     274        1434 : }
     275         355 : 
     276      381845 : template <typename T> bool operator<=(NoneType, const Optional<T> &X) {
     277         207 :   return !(X < None);
     278       12605 : }
     279           8 : 
     280       29440 : template <typename T> bool operator>(const Optional<T> &X, NoneType) {
     281        2490 :   return None < X;
     282         455 : }
     283       13264 : 
     284          21 : template <typename T> bool operator>(NoneType, const Optional<T> &X) {
     285          21 :   return X < None;
     286           0 : }
     287       34568 : 
     288           0 : template <typename T> bool operator>=(const Optional<T> &X, NoneType) {
     289          25 :   return None <= X;
     290       44532 : }
     291     5163224 : 
     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       37849 :   return X && *X == Y;
     298           4 : }
     299          11 : 
     300           0 : template <typename T> bool operator==(const T &X, const Optional<T> &Y) {
     301    10237421 :   return Y && X == *Y;
     302         158 : }
     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           0 : template <typename T> bool operator!=(const T &X, const Optional<T> &Y) {
     309          50 :   return !(X == Y);
     310           0 : }
     311           0 : 
     312       57658 : template <typename T> bool operator<(const Optional<T> &X, const T &Y) {
     313         471 :   return !X || *X < Y;
     314       57599 : }
     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         337 : 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      793530 :   return Y < X;
     330          45 : }
     331         222 : 
     332             : template <typename T> bool operator>(const T &X, const Optional<T> &Y) {
     333           0 :   return Y < X;
     334           6 : }
     335          21 : 
     336             : template <typename T> bool operator>=(const Optional<T> &X, const T &Y) {
     337         367 :   return !(X < Y);
     338           3 : }
     339     1587044 : 
     340           0 : template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
     341          58 :   return !(X < Y);
     342           3 : }
     343           0 : 
     344          42 : } // end namespace llvm
     345      238037 : 
     346          54 : #endif // LLVM_ADT_OPTIONAL_H

Generated by: LCOV version 1.13