// RUN: %check_clang_tidy %s llvmlibc-callee-namespace %t #define OTHER_MACRO_NAMESPACE custom_namespace namespace OTHER_MACRO_NAMESPACE { void wrong_name_macro_func() {} } namespace __llvm_libc { void right_name_no_macro_func() {} } #define LIBC_NAMESPACE __llvm_libc_xyz namespace LIBC_NAMESPACE { namespace nested { void nested_func() {} } // namespace nested void libc_api_func() {} struct libc_api_struct { int operator()() const { return 0; } }; } // namespace __llvm_libc // Emulate a function from the public headers like string.h void libc_api_func() {} // Emulate a function specifically allowed by the exception list. void malloc() {} // Emulate a non-trivially named symbol. struct global_struct { int operator()() const { return 0; } }; namespace LIBC_NAMESPACE { void Test() { // Allow calls with the fully qualified name. LIBC_NAMESPACE::libc_api_func(); LIBC_NAMESPACE::nested::nested_func(); void (*qualifiedPtr)(void) = LIBC_NAMESPACE::libc_api_func; qualifiedPtr(); // Should not trigger on compiler provided function calls. (void)__builtin_abs(-1); // Bare calls are allowed as long as they resolve to the correct namespace. libc_api_func(); nested::nested_func(); void (*barePtr)(void) = LIBC_NAMESPACE::libc_api_func; barePtr(); // Allow calling entities defined in the namespace. LIBC_NAMESPACE::libc_api_struct{}(); // Disallow calling into global namespace for implemented entrypoints. ::libc_api_func(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro // CHECK-MESSAGES: :25:6: note: resolves to this declaration // Disallow indirect references to functions in global namespace. void (*badPtr)(void) = ::libc_api_func; badPtr(); // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 'libc_api_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro // CHECK-MESSAGES: :25:6: note: resolves to this declaration // Allow calling into global namespace for specific functions. ::malloc(); // Disallow calling on entities that are not in the namespace, but make sure // no crashes happen. global_struct{}(); // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 'operator()' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro // CHECK-MESSAGES: :32:7: note: resolves to this declaration OTHER_MACRO_NAMESPACE::wrong_name_macro_func(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'wrong_name_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro // CHECK-MESSAGES: :3:31: note: expanded from macro 'OTHER_MACRO_NAMESPACE' // CHECK-MESSAGES: :5:8: note: resolves to this declaration __llvm_libc::right_name_no_macro_func(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'right_name_no_macro_func' must resolve to a function declared within the namespace defined by the 'LIBC_NAMESPACE' macro // CHECK-MESSAGES: :9:8: note: resolves to this declaration } } // namespace __llvm_libc