129 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -triple x86_64-gnu-linux2// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -triple x86_64-gnu-linux -fexperimental-new-constant-interpreter3 4template <bool Leak>5struct RAIIBase {6 constexpr RAIIBase(const char* in) {7 s = __builtin_strlen(in);8 d = new char[s + 1]; // expected-note 4{{allocation performed here was not deallocated}}9 for(int i = 0 ; i < s; i++)10 d[i] = in[i];11 }12 int s;13 char* d;14 constexpr unsigned long size() const {15 return s;16 }17 constexpr const char* data() const {18 return d;19 }20 constexpr ~RAIIBase() {21 if constexpr(!Leak)22 delete[] d;23 }24};25 26using RAII = RAIIBase<false>;27using RAIILeak = RAIIBase<true>;28 29void test_leaks(int i) {30 asm((RAII("nop")) : (RAII("+ir")) (i) : (RAII("g")) (i) : (RAII("memory")));31 asm((RAIILeak("nop"))); // expected-error {{the expression in this asm operand must be produced by a constant expression}}32 asm((RAII("nop"))33 : (RAIILeak("+ir")) (i) // expected-error {{the expression in this asm operand must be produced by a constant expression}}34 ::35 );36 asm((RAII("nop"))37 : (RAII("+ir")) (i)38 : (RAIILeak("g")) (i) // expected-error {{the expression in this asm operand must be produced by a constant expression}}39 :40 );41 asm((RAII("nop"))42 : (RAII("+ir")) (i)43 : (RAII("g")) (i)44 : (RAIILeak("memory")) // expected-error {{the expression in this asm operand must be produced by a constant expression}}45 );46}47 48struct NotAString{};49struct MessageInvalidSize {50 constexpr unsigned long size(int) const; // expected-note {{'size' declared here}}51 constexpr const char* data() const;52};53struct MessageInvalidData {54 constexpr unsigned long size() const;55 constexpr const char* data(int) const; // expected-note {{'data' declared here}}56};57 58 59struct WMessage {60 constexpr unsigned long long size() const {return 0;};61 constexpr const wchar_t* data() const {return L"";}62};63 64struct string_view {65 int S;66 const char* D;67 constexpr string_view() : S(0), D(0){}68 constexpr string_view(const char* Str) : S(__builtin_strlen(Str)), D(Str) {}69 constexpr string_view(int Size, const char* Str) : S(Size), D(Str) {}70 constexpr int size() const {71 return S;72 }73 constexpr const char* data() const {74 return D;75 }76};77 78 79void f() {80 asm(("")); // expected-error {{the expression in this asm operand must be a string literal or an object with 'data()' and 'size()' member functions}}81 asm((NotAString{})); // expected-error {{the string object in this asm operand is missing 'data()' and 'size()' member functions}}82 asm((MessageInvalidData{})); // expected-error {{the expression in this asm operand must have a 'data()' member function returning an object convertible to 'const char *'}} \83 // expected-error {{too few arguments to function call, expected 1, have 0}}84 asm((MessageInvalidSize{})); // expected-error {{the expression in this asm operand must have a 'size()' member function returning an object convertible to 'std::size_t'}} \85 // expected-error {{too few arguments to function call, expected 1, have 0}}86 87 asm((WMessage{})); // expected-error {{value of type 'const wchar_t *' is not implicitly convertible to 'const char *'}} \88 // expected-error {{the expression in this asm operand must have a 'data()' member function returning an object convertible to 'const char *'}}89}90 91template <typename... U>92void test_packs() {93 asm((U{})); // expected-error {{expression contains unexpanded parameter pack 'U'}}94 asm("" : (U{})); // expected-error {{expression contains unexpanded parameter pack 'U'}}95 asm("" :: (U{})); // expected-error {{expression contains unexpanded parameter pack 'U'}}96 asm("" ::: (U{})); // expected-error {{expression contains unexpanded parameter pack 'U'}}97}98 99template <typename T>100void test_dependent1(int i) {101 asm((T{})); // #err-int102 asm("" : (T{"+g"})(i)); // #err-int2103 asm("" :: (T{"g"})(i)); // #err-int3104 asm("" ::: (T{"memory"})); // #err-int4105}106 107template void test_dependent1<int>(int);108// expected-note@-1 {{in instantiation of function template specialization}}109// expected-error@#err-int {{the expression in this asm operand must be a string literal or an object with 'data()' and 'size()' member functions}}110// expected-error@#err-int2 {{cannot initialize a value of type 'int' with an lvalue of type 'const char[3]'}}111// expected-error@#err-int3 {{cannot initialize a value of type 'int' with an lvalue of type 'const char[2]'}}112// expected-error@#err-int4 {{cannot initialize a value of type 'int' with an lvalue of type 'const char[7]'}}113 114template void test_dependent1<string_view>(int);115 116 117template <typename T>118void test_dependent2(int i) {119 asm("" : (T{"g"})(i)); // #err-invalid1120 asm("" :: (T{"+g"})(i)); // #err-invalid2121 asm("" ::: (T{"foo"})); // #err-invalid3122}123template void test_dependent2<string_view>(int);124// expected-note@-1 {{in instantiation of function template specialization}}125// expected-error@#err-invalid1 {{invalid output constraint 'g' in asm}}126// expected-error@#err-invalid2 {{invalid input constraint '+g' in asm}}127// expected-error@#err-invalid3 {{unknown register name 'foo' in asm}}128 129