================
@@ -0,0 +1,270 @@
+// C/C++ behavior of -mloadtime-comment-vars= :
+//   codegen.cpp - mangled-name matching and what gets preserved
+//   storage.cpp - storage-duration and scope diagnostics
+//   diag.c      - volatile / non-string-literal diagnostics (C)
+//   init.cpp    - constant-initialization / string-literal diagnostics (C++)
+//   list.c      - list parsing: whitespace after a comma, repeated names
+
+// RUN: rm -rf %t && split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++17 -O2 -triple powerpc64-ibm-aix \
+// RUN:   
-mloadtime-comment-vars=x,_ZN1N1xE,_ZN1N1qE,_ZN1NL3ptrE,_ZN1A1xE,_ZN1B3verE,_ZN1C4infoE
 \
+// RUN:   -emit-llvm -disable-llvm-passes -o - %t/codegen.cpp | FileCheck 
%t/codegen.cpp
+//
+// RUN: %clang_cc1 -std=c++17 -triple powerpc64-ibm-aix \
+// RUN:   -mloadtime-comment-vars=keep,_ZN1N2tlE,_ZL3stl,_ZN1A2tmE,_ZZ1fvE2fn \
+// RUN:   -emit-llvm -verify -o - %t/storage.cpp | FileCheck %t/storage.cpp
+//
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix \
+// RUN:   
-mloadtime-comment-vars=vol_ptr,vol_char,vol_arr,tls_ptr,ind_ptr,const_arr \
+// RUN:   -emit-llvm -verify -o - %t/diag.c | FileCheck %t/diag.c
+//
+// RUN: %clang_cc1 -std=c++17 -triple powerpc64-ibm-aix \
+// RUN:   -mloadtime-comment-vars=p_ok,arr_ok,p_dyn,p_ind \
+// RUN:   -emit-llvm -verify -o - %t/init.cpp | FileCheck %t/init.cpp
+//
+// The diagnostics are produced by Sema, so they are emitted even when no code
+// is generated.
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix \
+// RUN:   
-mloadtime-comment-vars=vol_ptr,vol_char,vol_arr,tls_ptr,ind_ptr,const_arr \
+// RUN:   -fsyntax-only -verify %t/diag.c
+// RUN: %clang_cc1 -std=c++17 -triple powerpc64-ibm-aix \
+// RUN:   -mloadtime-comment-vars=p_ok,arr_ok,p_dyn,p_ind \
+// RUN:   -fsyntax-only -verify %t/init.cpp
+//
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix \
+// RUN:   "-mloadtime-comment-vars=foo, bar" \
+// RUN:   -emit-llvm -o - %t/list.c | FileCheck %t/list.c --check-prefix=SPACE
+//
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix \
+// RUN:   -mloadtime-comment-vars=foo,foo \
+// RUN:   -emit-llvm -o - %t/list.c | FileCheck %t/list.c --check-prefix=DUP
+
+//--- codegen.cpp
+// Names are matched against mangled IR symbol names.
+// C++ variables use Itanium ABI mangling; C/file-scope statics keep their
+// source name.
+//
+// Mangled names used here:
+//   x            -> x             (file-scope, no mangling)
+//   N::x         -> _ZN1N1xE
+//   N::q         -> _ZN1N1qE
+//   N::ptr       -> _ZN1NL3ptrE   (static, internal linkage)
+//   A::x         -> _ZN1A1xE
+//   B::ver       -> _ZN1B3verE
+//   C::info      -> _ZN1C4infoE   (declared only, no definition — skipped)
+
+// 1. File-scope array "x" — no mangling in C++, IR name == source name.
+char x[] = "@(#) global x";
+
+namespace N {
+char x[] = "@(#) ns x";
+
+// 2. Namespace member "N::x" — mangled as _ZN1N1xE.
+char q[] = "@(#) ns q";
+
+// 3. Namespace-scope pointer initialized with a string literal.
+//    _ZN1NL3ptrE (N::ptr) is internal (it is a const variable at namespace
+//    scope). MustBeEmitted forces it through EmitGlobalVarDefinition.
+static const char *ptr = "@(#) ns ptr";
+} // namespace N
+
+// 4. Class static member "A::x" — mangled as _ZN1A1xE.
+struct A {
+  static const char *x;
+};
+const char *A::x = "@(#) class x";
+
+// 5. Class static member pointer initialized with a string literal.
+//    _ZN1B3verE (B::ver).
+struct B {
+  static const char *ver;
+};
+const char *B::ver = "@(#) class ver";
+
+// 6. _ZN1C4infoE is in the list but C::info has no definition in this TU —
+//    must be silently skipped.
+struct C { static const char *info; };
+
+// 7. Invalid type — int must not be tagged regardless of its IR name.
+int not_string = 7;
+
+void f() {}
+
+// File-scope x and namespace N::x both matched.
+// CHECK-DAG: @x = global [14 x i8] c"@(#) global x\00", align {{[0-9]+}}, 
!loadtime_comment ![[MD:[0-9]+]]
+// CHECK-DAG: @_ZN1N1xE = global [10 x i8] c"@(#) ns x\00", align {{[0-9]+}}, 
!loadtime_comment ![[MD]]
+
+// N::q matched by mangled name _ZN1N1qE.
+// CHECK-DAG: @_ZN1N1qE = global [10 x i8] c"@(#) ns q\00", align {{[0-9]+}}, 
!loadtime_comment ![[MD]]
+
+// A::x matched by mangled name _ZN1A1xE.
+// CHECK-DAG: @[[AX:_ZN1A1xE]] = {{.*}}global ptr @[[AXSTR:.*]], align 
{{[0-9]+}}, !loadtime_comment ![[MD]]
+// CHECK-DAG: @[[AXSTR]] = private unnamed_addr constant [13 x i8] c"@(#) 
class x\00", align {{[0-9]+}}
+
+// N::ptr (_ZN1NL3ptrE) points to a string literal.
+// CHECK-DAG: @_ZN1NL3ptrE = internal global ptr @[[NPTR_STR:.*]], align 
{{[0-9]+}}, !loadtime_comment ![[MD]]
+// CHECK-DAG: @[[NPTR_STR]] = private unnamed_addr constant [{{[0-9]+}} x i8] 
c"@(#) ns ptr\00", align {{[0-9]+}}
+
+// B::ver (_ZN1B3verE) points to a string literal.
+// CHECK-DAG: @_ZN1B3verE = global ptr @[[BVER_STR:.*]], align {{[0-9]+}}, 
!loadtime_comment ![[MD]]
+// CHECK-DAG: @[[BVER_STR]] = private unnamed_addr constant [{{[0-9]+}} x i8] 
c"@(#) class ver\00", align {{[0-9]+}}
+
+// Invalid type must not be tagged.
+// CHECK-NOT: @not_string{{.*}}!loadtime_comment
+
+// C::info has no definition — must not appear.
+// CHECK-NOT: @_ZN1C4infoE
+
+// All six selected globals are preserved in llvm.compiler.used.
+// CHECK: @llvm.compiler.used = appending global [6 x ptr]
+// CHECK-SAME: @x
+// CHECK-SAME: @_ZN1N1xE
+// CHECK-SAME: @_ZN1N1qE
+// CHECK-SAME: @_ZN1NL3ptrE
+// CHECK-SAME: @[[AX]]
+// CHECK-SAME: @_ZN1B3verE
+// CHECK-SAME: section "llvm.metadata"
+
+//--- storage.cpp
+// Storage-duration and scope handling for -mloadtime-comment-vars=.
+//
+// To be preserved a variable must have static storage duration and be defined
+// at file, namespace, or class scope. A thread_local variable (thread storage
+// duration) is diagnosed. A function-local static has static storage duration
+// but is emitted through a different path, so it is silently ignored.
+//
+// Mangled names used here:
+//   keep    -> keep         (namespace-scope, external linkage) -- preserved
+//   N::tl   -> _ZN1N2tlE    (thread_local)                      -- diagnosed
+//   stl     -> _ZL3stl      (static thread_local, internal)     -- diagnosed
+//   A::tm   -> _ZN1A2tmE    (thread_local static member)        -- diagnosed
+//   f()::fn -> _ZZ1fvE2fn   (function-local static)             -- ignored
+
+// Supported: namespace scope, static storage duration -> preserved.
+const char *keep = "@(#) keep";
+
+namespace N {
+// Thread storage duration -> diagnosed.
+thread_local const char *tl = "@(#) tl"; // expected-warning {{'tl' named in 
'-mloadtime-comment-vars=' does not have static storage duration and will not 
be preserved}}
+} // namespace N
+
+// 'static' here only changes linkage; the storage duration is still thread.
+static thread_local const char *stl = "@(#) stl"; // expected-warning {{'stl' 
named in '-mloadtime-comment-vars=' does not have static storage duration and 
will not be preserved}}
+
+struct A {
+  static thread_local const char *tm;
+};
+thread_local const char *A::tm = "@(#) tm"; // expected-warning {{'tm' named 
in '-mloadtime-comment-vars=' does not have static storage duration and will 
not be preserved}}
----------------
tonykuttai wrote:

Done. Sema diagnostics now live in dedicated `-fsyntax-only -verify` tests: 
`clang/test/Sema/loadtime-comment-vars.c` and 
`clang/test/Sema/loadtime-comment-vars.cpp`.

https://github.com/llvm/llvm-project/pull/187986
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to