1
- // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
1
+ // RUN: %clang_cc1 --std=c++20 - fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
2
2
struct [[gsl::Owner(int )]] MyIntOwner {
3
3
MyIntOwner ();
4
4
int &operator *();
@@ -252,6 +252,19 @@ struct reference_wrapper {
252
252
253
253
template <typename T>
254
254
reference_wrapper<T> ref (T& t) noexcept ;
255
+
256
+ struct false_type {
257
+ static constexpr bool value = false ;
258
+ constexpr operator bool () const noexcept { return value; }
259
+ };
260
+ struct true_type {
261
+ static constexpr bool value = true ;
262
+ constexpr operator bool () const noexcept { return value; }
263
+ };
264
+
265
+ template <class T > struct is_pointer : false_type {};
266
+ template <class T > struct is_pointer <T*> : true_type {};
267
+ template <class T > struct is_pointer <T* const > : true_type {};
255
268
}
256
269
257
270
struct Unannotated {
@@ -806,95 +819,189 @@ struct S {
806
819
void captureInt (const int &x [[clang::lifetime_capture_by(s)]], S&s);
807
820
void captureRValInt (int &&x [[clang::lifetime_capture_by(s)]], S&s);
808
821
void noCaptureInt (int x [[clang::lifetime_capture_by(s)]], S&s);
822
+
809
823
std::string_view substr (const std::string& s [[clang::lifetimebound]]);
810
824
std::string_view strcopy (const std::string& s);
825
+
811
826
void captureSV (std::string_view x [[clang::lifetime_capture_by(s)]], S&s);
812
827
void captureRValSV (std::string_view&& x [[clang::lifetime_capture_by(s)]], S&s);
813
828
void noCaptureSV (std::string_view x, S&s);
814
829
void captureS (const std::string& x [[clang::lifetime_capture_by(s)]], S&s);
815
830
void captureRValS (std::string&& x [[clang::lifetime_capture_by(s)]], S&s);
831
+
832
+ const std::string& getLB (const std::string& s[[clang::lifetimebound]]);
833
+ const std::string& getLB (std::string_view sv[[clang::lifetimebound]]);
816
834
const std::string* getPointerLB (const std::string& s[[clang::lifetimebound]]);
817
835
const std::string* getPointerNoLB (const std::string& s);
836
+
818
837
void capturePointer (const std::string* x [[clang::lifetime_capture_by(s)]], S&s);
838
+
819
839
struct ThisIsCaptured {
820
840
void capture (S& s) [[clang::lifetime_capture_by(s)]];
821
841
void bar (S& s) [[clang::lifetime_capture_by(abcd)]]; // expected-error {{'lifetime_capture_by' attribute argument 'abcd' is not a known function parameter}}
822
842
void baz (S& s) [[clang::lifetime_capture_by(this )]]; // expected-error {{'lifetime_capture_by' argument references itself}}
823
843
};
844
+
845
+ void captureByGlobal (std::string_view s [[clang::lifetime_capture_by(global)]]);
846
+ void captureByUnknown (std::string_view s [[clang::lifetime_capture_by(unknown)]]);
847
+
824
848
void use () {
825
849
std::string_view local_sv;
826
850
std::string local_s;
827
851
S s;
828
852
// Capture an 'int'.
829
853
int local;
830
- captureInt (1 , // expected-warning {{object captured by 's' will be destroyed at the end of the full-expression}}
854
+ captureInt (1 , // expected-warning {{object whose reference is captured by 's' will be destroyed at the end of the full-expression}}
831
855
s);
832
- captureRValInt (1 , s); // expected-warning {{object captured by 's'}}
856
+ captureRValInt (1 , s); // expected-warning {{object whose reference is captured by 's'}}
833
857
captureInt (local, s);
834
858
noCaptureInt (1 , s);
835
859
noCaptureInt (local, s);
836
860
837
- // Capture lifetimebound pointer.
838
- capturePointer (getPointerLB (std::string ()), s); // expected-warning {{object captured by 's'}}
839
- capturePointer (getPointerLB (*getPointerLB (std::string ())), s); // expected-warning {{object captured by 's'}}
840
- capturePointer (getPointerNoLB (std::string ()), s);
841
-
842
861
// Capture using std::string_view.
843
862
captureSV (local_sv, s);
844
- captureSV (std::string (), // expected-warning {{object captured by 's'}}
863
+ captureSV (std::string (), // expected-warning {{object whose reference is captured by 's'}}
845
864
s);
846
865
captureSV (substr (
847
- std::string () // expected-warning {{object captured by 's'}}
866
+ std::string () // expected-warning {{object whose reference is captured by 's'}}
848
867
), s);
849
868
captureSV (substr (local_s), s);
850
869
captureSV (strcopy (std::string ()), s);
851
870
captureRValSV (std::move (local_sv), s);
852
- captureRValSV (std::string (), s); // expected-warning {{object captured by 's'}}
871
+ captureRValSV (std::string (), s); // expected-warning {{object whose reference is captured by 's'}}
853
872
captureRValSV (std::string_view{" abcd" }, s);
854
873
captureRValSV (substr (local_s), s);
855
- captureRValSV (substr (std::string ()), s); // expected-warning {{object captured by 's'}}
874
+ captureRValSV (substr (std::string ()), s); // expected-warning {{object whose reference is captured by 's'}}
856
875
captureRValSV (strcopy (std::string ()), s);
857
876
noCaptureSV (local_sv, s);
858
877
noCaptureSV (std::string (), s);
859
878
noCaptureSV (substr (std::string ()), s);
860
879
861
880
// Capture using std::string.
862
- captureS (std::string (), s); // expected-warning {{object captured by 's'}}
881
+ captureS (std::string (), s); // expected-warning {{object whose reference is captured by 's'}}
863
882
captureS (local_s, s);
864
883
captureRValS (std::move (local_s), s);
865
- captureRValS (std::string (), s); // expected-warning {{object captured by 's'}}
884
+ captureRValS (std::string (), s); // expected-warning {{object whose reference is captured by 's'}}
885
+
886
+ // Capture with lifetimebound.
887
+ captureSV (getLB (std::string ()), s); // expected-warning {{object whose reference is captured by 's'}}
888
+ captureSV (getLB (substr (std::string ())), s); // expected-warning {{object whose reference is captured by 's'}}
889
+ captureSV (getLB (getLB (
890
+ std::string () // expected-warning {{object whose reference is captured by 's'}}
891
+ )), s);
892
+ capturePointer (getPointerLB (std::string ()), s); // expected-warning {{object whose reference is captured by 's'}}
893
+ capturePointer (getPointerLB (*getPointerLB (
894
+ std::string () // expected-warning {{object whose reference is captured by 's'}}
895
+ )), s);
896
+ capturePointer (getPointerNoLB (std::string ()), s);
866
897
867
898
// Member functions.
868
- s.captureInt (1 ); // expected-warning {{object captured by 's'}}
869
- s.captureSV (std::string ()); // expected-warning {{object captured by 's'}}
870
- s.captureSV (substr (std::string ())); // expected-warning {{object captured by 's'}}
899
+ s.captureInt (1 ); // expected-warning {{object whose reference is captured by 's'}}
900
+ s.captureSV (std::string ()); // expected-warning {{object whose reference is captured by 's'}}
901
+ s.captureSV (substr (std::string ())); // expected-warning {{object whose reference is captured by 's'}}
871
902
s.captureSV (strcopy (std::string ()));
872
903
873
904
// 'this' is captured.
874
- ThisIsCaptured{}.capture (s); // expected-warning {{object captured by 's'}}
905
+ ThisIsCaptured{}.capture (s); // expected-warning {{object whose reference is captured by 's'}}
875
906
ThisIsCaptured TIS;
876
907
TIS.capture (s);
908
+
909
+ // capture by global.
910
+ captureByGlobal (std::string ()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}}
911
+ captureByGlobal (substr (std::string ())); // expected-warning {{captured}}
912
+ captureByGlobal (local_s);
913
+ captureByGlobal (local_sv);
914
+
915
+ // // capture by unknown.
916
+ captureByGlobal (std::string ()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}}
917
+ captureByGlobal (substr (std::string ())); // expected-warning {{captured}}
918
+ captureByGlobal (local_s);
919
+ captureByGlobal (local_sv);
877
920
}
878
- class [[gsl::Pointer()]] my_string_view : public std::string_view {};
879
- class my_string_view_not_pointer : public std ::string_view {};
880
- std::optional<std::string_view> getOptionalSV ();
881
- std::optional<std::string> getOptionalS ();
882
- std::optional<my_string_view> getOptionalMySV ();
883
- std::optional<my_string_view_not_pointer> getOptionalMySVNotP ();
884
- my_string_view getMySV ();
885
- my_string_view_not_pointer getMySVNotP ();
886
921
922
+ template <typename T> struct IsPointerLikeTypeImpl : std::false_type {};
923
+ template <> struct IsPointerLikeTypeImpl <std::string_view> : std::true_type {};
924
+ template <typename T> concept IsPointerLikeType = std::is_pointer<T>::value || IsPointerLikeTypeImpl<T>::value;
925
+
926
+ // Templated containers having no distinction between pointer-like and other element type.
887
927
template <class T >
888
928
struct MySet {
889
- void insert (T&& t [[clang::lifetime_capture_by(this )]]);
890
- void insert (const T& t [[clang::lifetime_capture_by(this )]]);
929
+ void insert (T&& t [[clang::lifetime_capture_by(this )]]);
930
+ void insert (const T& t [[clang::lifetime_capture_by(this )]]);
891
931
};
892
932
void user_defined_containers () {
893
933
MySet<int > set_of_int;
894
- set_of_int.insert (1 ); // expected-warning {{object captured by 'set_of_int' will be destroyed}}
934
+ set_of_int.insert (1 ); // expected-warning {{object whose reference is captured by 'set_of_int' will be destroyed}}
895
935
MySet<std::string_view> set_of_sv;
896
- set_of_sv.insert (std::string ()); // expected-warning {{object captured by 'set_of_sv' will be destroyed}}
936
+ set_of_sv.insert (std::string ()); // expected-warning {{object whose reference is captured by 'set_of_sv' will be destroyed}}
937
+ }
938
+
939
+ // Templated containers having **which distinguishes** between pointer-like and other element type.
940
+ template <class T >
941
+ struct MyVector {
942
+ void push_back (T&& t [[clang::lifetime_capture_by(this )]]) requires IsPointerLikeType<T>;
943
+ void push_back (const T& t [[clang::lifetime_capture_by(this )]]) requires IsPointerLikeType<T>;
944
+
945
+ void push_back (T&& t) requires (!IsPointerLikeType<T>);
946
+ void push_back (const T& t) requires (!IsPointerLikeType<T>);
947
+ };
948
+
949
+ // Container of pointers.
950
+ struct [[gsl::Pointer()]] MyStringView : public std::string_view {
951
+ MyStringView ();
952
+ MyStringView (std::string_view&&);
953
+ MyStringView (const MyStringView&);
954
+ MyStringView (const std::string&);
955
+ };
956
+ template <> struct IsPointerLikeTypeImpl <MyStringView> : std::true_type {};
957
+
958
+ std::optional<std::string_view> getOptionalSV ();
959
+ std::optional<std::string> getOptionalS ();
960
+ std::optional<MyStringView> getOptionalMySV ();
961
+ MyStringView getMySV ();
962
+
963
+ class MyStringViewNotPointer : public std ::string_view {};
964
+ std::optional<MyStringViewNotPointer> getOptionalMySVNotP ();
965
+ MyStringViewNotPointer getMySVNotP ();
966
+
967
+ void container_of_pointers () {
968
+ std::string local;
969
+ MyVector<std::string> vs;
970
+ vs.push_back (std::string ()); // Ok.
971
+
972
+ MyVector<std::string_view> vsv;
973
+ vsv.push_back (std::string ()); // expected-warning {{object whose reference is captured by 'vsv'}}
974
+ vsv.push_back (substr (std::string ())); // expected-warning {{object whose reference is captured by 'vsv'}}
975
+
976
+ MyVector<const std::string*> vp;
977
+ vp.push_back (getPointerLB (std::string ())); // expected-warning {{object whose reference is captured by 'vp'}}
978
+ vp.push_back (getPointerLB (*getPointerLB (std::string ()))); // expected-warning {{object whose reference is captured by 'vp'}}
979
+ vp.push_back (getPointerLB (local));
980
+ vp.push_back (getPointerNoLB (std::string ()));
981
+
982
+ // User-defined [[gsl::Pointer]]
983
+ vsv.push_back (getMySV ());
984
+ vsv.push_back (getMySVNotP ());
985
+
986
+ // Vector of user defined gsl::Pointer.
987
+ MyVector<MyStringView> vmysv;
988
+ vmysv.push_back (getMySV ());
989
+ vmysv.push_back (MyStringView{});
990
+ vmysv.push_back (std::string_view{});
991
+ vmysv.push_back (std::string{}); // expected-warning {{object whose reference is captured by 'vmysv'}}
992
+ vmysv.push_back (substr (std::string{})); // expected-warning {{object whose reference is captured by 'vmysv'}}
993
+ vmysv.push_back (getLB (substr (std::string{}))); // expected-warning {{object whose reference is captured by 'vmysv'}}
994
+ vmysv.push_back (strcopy (getLB (substr (std::string{}))));
995
+
996
+ // With std::optional container.
997
+ std::optional<std::string_view> optional;
998
+ vsv.push_back (optional.value ());
999
+ vsv.push_back (getOptionalS ().value ()); // expected-warning {{object whose reference is captured by 'vsv'}}
1000
+ vsv.push_back (getOptionalSV ().value ());
1001
+ vsv.push_back (getOptionalMySV ().value ());
1002
+
1003
+ // (maybe) FIXME: We may choose to diagnose the following case.
1004
+ // This happens because 'MyStringViewNotPointer' is not marked as a [[gsl::Pointer]] but is derived from one.
1005
+ vsv.push_back (getOptionalMySVNotP ().value ()); // expected-warning {{object whose reference is captured by 'vsv'}}
897
1006
}
898
1007
} // namespace lifetime_capture_by
899
- // Test for templated code.
900
- // 2 nested function calls foo(sv, bar(sv, setsv));
0 commit comments