brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.7 KiB · 5b256b0 Raw
386 lines · cpp
1// RUN: %clang %s -std=c++17 -Xclang -verify --analyze \2// RUN:   -Xclang -analyzer-checker=core \3// RUN:   -Xclang -analyzer-checker=debug.ExprInspection \4// RUN:   -Xclang -analyzer-checker=core,alpha.core.StdVariant5 6#include "Inputs/system-header-simulator-cxx.h"7 8class Foo{};9 10void clang_analyzer_warnIfReached();11void clang_analyzer_eval(int);12 13//helper functions14void changeVariantType(std::variant<int, char> &v) {15  v = 25;16}17 18void changesToInt(std::variant<int, char> &v);19void changesToInt(std::variant<int, char> *v);20 21void cannotChangePtr(const std::variant<int, char> &v);22void cannotChangePtr(const std::variant<int, char> *v);23 24char getUnknownChar();25 26void swap(std::variant<int, char> &v1, std::variant<int, char> &v2) {27  std::variant<int, char> tmp = v1;28  v1 = v2;29  v2 = tmp;30}31 32void cantDo(const std::variant<int, char>& v) {33  std::variant<int, char> vtmp = v;34  vtmp = 5;35  int a = std::get<int> (vtmp);36  (void) a;37}38 39void changeVariantPtr(std::variant<int, char> *v) {40  *v = 'c';41}42 43using var_t = std::variant<int, char>;44using var_tt = var_t;45using int_t = int;46using char_t = char;47 48// A quick sanity check to see that std::variant's std::get49// is not being confused with std::pairs std::get.50void wontConfuseStdGets() {51  std::pair<int, char> p{15, '1'};52  int a = std::get<int>(p);53  char c = std::get<char>(p);54  (void)a;55  (void)c;56}57 58//----------------------------------------------------------------------------//59// std::get60//----------------------------------------------------------------------------//61void stdGetType() {62  std::variant<int, char> v = 25;63  int a = std::get<int>(v);64  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}65  (void)a;66  (void)c;67}68 69void stdGetPointer() {70  int *p = new int;71  std::variant<int*, char> v = p;72  int *a = std::get<int*>(v);73  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int *', not a 'char'}}74  (void)a;75  (void)c;76  delete p;77}78 79void stdGetObject() {80  std::variant<int, char, Foo> v = Foo{};81  Foo f = std::get<Foo>(v);82  int i = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'Foo', not an 'int'}}83  (void)i;84}85 86void stdGetPointerAndPointee() {87  int a = 5;88  std::variant<int, int*> v = &a;89  int *b = std::get<int*>(v);90  int c = std::get<int>(v); // expected-warning {{std::variant 'v' held an 'int *', not an 'int'}}91  (void)c;92  (void)b;93}94 95void variantHoldingVariant() {96  std::variant<std::variant<int, char>, std::variant<char, int>> v = std::variant<int,char>(25);97  std::variant<int, char> v1 = std::get<std::variant<int,char>>(v);98  std::variant<char, int> v2 = std::get<std::variant<char,int>>(v); // expected-warning {{std::variant 'v' held a 'std::variant<int, char>', not a 'class std::variant<char, int>'}}99}100 101//----------------------------------------------------------------------------//102// Constructors and assignments103//----------------------------------------------------------------------------//104void copyConstructor() {105  std::variant<int, char> v = 25;106  std::variant<int, char> t(v);107  int a = std::get<int> (t);108  char c = std::get<char> (t); // expected-warning {{std::variant 't' held an 'int', not a 'char'}}109  (void)a;110  (void)c;111}112 113void copyAssignmentOperator() {114  std::variant<int, char> v = 25;115  std::variant<int, char> t = 'c';116  t = v;117  int a = std::get<int> (t);118  char c = std::get<char> (t); // expected-warning {{std::variant 't' held an 'int', not a 'char'}}119  (void)a;120  (void)c;121}122 123void assignmentOperator() {124  std::variant<int, char> v = 25;125  int a = std::get<int> (v);126  (void)a;127  v = 'c';128  char c = std::get<char>(v);129  a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}130  (void)a;131  (void)c;132}133 134void typeChangeThreeTimes() {135  std::variant<int, char, float> v = 25;136  int a = std::get<int> (v);137  (void)a;138  v = 'c';139  char c = std::get<char>(v);140  v = 25;141  a = std::get<int>(v);142  (void)a;143  v = 1.25f;144  float f = std::get<float>(v);145  a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'float', not an 'int'}}146  (void)a;147  (void)c;148  (void)f;149}150 151void defaultConstructor() {152  std::variant<int, char> v;153  int i = std::get<int>(v);154  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}155  (void)i;156  (void)c;157}158 159// Verify that we handle temporary objects correctly160void temporaryObjectsConstructor() {161  std::variant<int, char> v(std::variant<int, char>('c'));162  char c = std::get<char>(v);163  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}164  (void)a;165  (void)c;166}167 168void temporaryObjectsAssignment() {169  std::variant<int, char> v = std::variant<int, char>('c');170  char c = std::get<char>(v);171  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}172  (void)a;173  (void)c;174}175 176// Verify that we handle pointer types correctly177void pointerTypeHeld() {178  int *p = new int;179  std::variant<int*, char> v = p;180  int *a = std::get<int*>(v);181  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int *', not a 'char'}}182  (void)a;183  (void)c;184  delete p;185}186 187std::variant<int, char> get_unknown_variant();188// Verify that the copy constructor is handles properly when the std::variant189// has no previously activated type and we copy an object of unknown value in it.190void copyFromUnknownVariant() {191  std::variant<int, char> u = get_unknown_variant();192  std::variant<int, char> v(u);193  int a = std::get<int>(v); // no-waring194  char c = std::get<char>(v); // no-warning195  (void)a;196  (void)c;197}198 199// Verify that the copy constructor is handles properly when the std::variant200// has previously activated type and we copy an object of unknown value in it.201void copyFromUnknownVariantBef() {202  std::variant<int, char> v = 25;203  std::variant<int, char> u = get_unknown_variant();204  v = u;205  int a = std::get<int>(v); // no-waring206  char c = std::get<char>(v); // no-warning207  (void)a;208  (void)c;209}210 211//----------------------------------------------------------------------------//212// typedef213//----------------------------------------------------------------------------//214 215void typefdefedVariant() {216  var_t v = 25;217  int a = std::get<int>(v);218  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}219  (void)a;220  (void)c;221}222 223void typedefedTypedfefedVariant() {224  var_tt v = 25;225  int a = std::get<int>(v);226  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}227  (void)a;228  (void)c;229}230 231void typedefedGet() {232  std::variant<char, int> v = 25;233  int a = std::get<int_t>(v);234  char c = std::get<char_t>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}235  (void)a;236  (void)c;237}238 239void typedefedPack() {240  std::variant<int_t, char_t> v = 25;241  int a = std::get<int>(v);242  char c = std::get<char>(v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}243  (void)a;244  (void)c;245}246 247void fromVariable() {248  char o = 'c';249  std::variant<int, char> v(o);250  char c = std::get<char>(v);251  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}252  (void)a;253  (void)c;254}255 256void unknowValueButKnownType() {257  char o = getUnknownChar();258  std::variant<int, char> v(o);259  char c = std::get<char>(v);260  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}261  (void)a;262  (void)c;263}264 265void createPointer() {266  std::variant<int, char> *v = new std::variant<int, char>(15);267  int a = std::get<int>(*v);268  char c = std::get<char>(*v); // expected-warning {{std::variant  held an 'int', not a 'char'}}269  (void)a;270  (void)c;271  delete v;272}273 274//----------------------------------------------------------------------------//275// Passing std::variants to functions276//----------------------------------------------------------------------------//277 278// Verifying that we are not invalidating the memory region of a variant if279// a non inlined or inlined function takes it as a constant reference or pointer280void constNonInlineRef() {281  std::variant<int, char> v = 'c';282  cannotChangePtr(v);283  char c = std::get<char>(v);284  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}285  (void)a;286  (void)c;287}288 289void contNonInlinePtr() {290  std::variant<int, char> v = 'c';291  cannotChangePtr(&v);292  char c = std::get<char>(v);293  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}294  (void)a;295  (void)c;296}297 298void copyInAFunction() {299  std::variant<int, char> v = 'c';300  cantDo(v);301  char c = std::get<char>(v);302  int a = std::get<int>(v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}303  (void)a;304  (void)c;305 306}307 308// Verifying that we can keep track of the type stored in std::variant when309// it is passed to an inlined function as a reference or pointer310void changeThruPointers() {311  std::variant<int, char> v = 15;312  changeVariantPtr(&v);313  char c = std::get<char> (v);314  int a = std::get<int> (v); // expected-warning {{std::variant 'v' held a 'char', not an 'int'}}315  (void)a;316  (void)c;317}318 319void functionCallWithCopyAssignment() {320  var_t v1 = 15;321  var_t v2 = 'c';322  swap(v1, v2);323  int a = std::get<int> (v2);324  (void)a;325  char c = std::get<char> (v1);326  a = std::get<int> (v1); // expected-warning {{std::variant 'v1' held a 'char', not an 'int'}}327  (void)a;328  (void)c;329}330 331void inlineFunctionCall() {332  std::variant<int, char> v = 'c';333  changeVariantType(v);334  int a = std::get<int> (v);335  char c = std::get<char> (v); // expected-warning {{std::variant 'v' held an 'int', not a 'char'}}336  (void)a;337  (void)c;338}339 340// Verifying that we invalidate the mem region of std::variant when it is341// passed as a non const reference or a pointer to a non inlined function.342void nonInlineFunctionCall() {343  std::variant<int, char> v = 'c';344  changesToInt(v);345  int a = std::get<int> (v); // no-waring346  char c = std::get<char> (v); // no-warning347  (void)a;348  (void)c;349}350 351void nonInlineFunctionCallPtr() {352  std::variant<int, char> v = 'c';353  changesToInt(&v);354  int a = std::get<int> (v); // no-warning355  char c = std::get<char> (v); // no-warning356  (void)a;357  (void)c;358}359 360// ----------------------------------------------------------------------------//361// Misc362// ----------------------------------------------------------------------------//363 364void unknownVal() {365  // force the argument to be UnknownVal366  (void)std::get<int>(*(std::variant<int, float>*)(int)3.14f); // no crash367}368 369template <typename T>370using MyVariant = std::variant<int, float>;371 372void typeAlias() {373  MyVariant<bool> v;374 375  (void)std::get<int>(v); // no-warning376}377 378template <template<typename> typename Container>379using MySpecialVariant = std::variant<int, float>;380 381void complexTypeAlias() {382  MySpecialVariant<std::vector> v;383 384  (void)std::get<int>(v); // no crash385}386