llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Aaron Ballman (AaronBallman)

<details>
<summary>Changes</summary>

The previous text was "implicitly declaring library function 'exp' with
type 'double (double)'" which helpfully mentioned the type. However, it
was also confusing because an implicit function declaration in C89 was
'int()', so when we'd implicitly declare a library function that isn't
present in the specified language mode, the type information was a bit
confusing.

The new message calls out the library functions which come from a
particular standard (C, C++, or POSIX) to mention that the type
selected is because the standard mandates that type. That makes it a
little more clear why the type is not 'int()'.

Fixes #<!-- -->146924

---
Full diff: https://github.com/llvm/llvm-project/pull/149314.diff


10 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+4) 
- (modified) clang/include/clang/Basic/Builtins.h (+27) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5-4) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+3-1) 
- (modified) clang/test/Analysis/exercise-ps.c (+1-1) 
- (modified) clang/test/Driver/implicit-function-as-error.c (+1-1) 
- (modified) clang/test/Sema/builtin-setjmp.c (+1-1) 
- (modified) clang/test/Sema/implicit-builtin-decl.c (+1-1) 
- (modified) clang/test/SemaObjC/builtin_objc_lib_functions.m (+7-7) 
- (modified) clang/test/SemaObjC/builtin_objc_nslog.m (+2-2) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fcd3887ec7a09..dbbe1ce4b3d09 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -716,6 +716,10 @@ Improvements to Clang's diagnostics
   Added a new warning in this group for the case where the attribute is 
missing/implicit on
   an override of a virtual method.
 
+ - Reworded the ``-Wimplicit-function-declaration`` diagnostic to make it more
+   clear that the type selected for the implicit declaration is based on the
+   signature of a standard (C, C++, POSIX) library function. (#GH146924)
+
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Basic/Builtins.h 
b/clang/include/clang/Basic/Builtins.h
index 3a5e31de2bc50..4bb860e537b8a 100644
--- a/clang/include/clang/Basic/Builtins.h
+++ b/clang/include/clang/Basic/Builtins.h
@@ -376,6 +376,33 @@ class Context {
     return getInfo(ID).Header.getName();
   }
 
+  /// Returns true if a library function is declared within a C or C++ standard
+  /// header (like stdio.h) or POSIX header (like malloc.h), false if the
+  /// function is not declared within a header or is declared in a non-standard
+  /// header (like Microsoft or Objective-C headers).
+  bool isDeclaredInStandardHeader(unsigned ID) const {
+    switch (getInfo(ID).Header.ID) {
+    default:
+      return false;
+    case HeaderDesc::COMPLEX_H: // C99
+    case HeaderDesc::CTYPE_H:   // C89
+    case HeaderDesc::MATH_H:    // C89
+    case HeaderDesc::MALLOC_H:  // POSIX
+    case HeaderDesc::MEMORY:    // C++98
+    case HeaderDesc::PTHREAD_H: // POSIX
+    case HeaderDesc::SETJMP_H:  // C89
+    case HeaderDesc::STDARG_H:  // C89
+    case HeaderDesc::STDIO_H:   // C89
+    case HeaderDesc::STDLIB_H:  // C89
+    case HeaderDesc::STRING_H:  // C89
+    case HeaderDesc::STRINGS_H: // POSIX
+    case HeaderDesc::UNISTD_H:  // POSIX
+    case HeaderDesc::UTILITY:   // C++98
+    case HeaderDesc::WCHAR_H:   // C99
+      return true;
+    }
+  }
+
   /// Determine whether this builtin is like printf in its
   /// formatting rules and, if so, set the index to the format string
   /// argument and whether this function as a va_list argument.
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b2ea65ae111be..abb916a66984c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -816,11 +816,12 @@ def warn_unreachable_association : Warning<
 
 /// Built-in functions.
 def ext_implicit_lib_function_decl : ExtWarn<
-  "implicitly declaring library function '%0' with type %1">,
-  InGroup<ImplicitFunctionDeclare>;
+  "implicitly declaring library function '%0' with%select{| 
standards-mandated}2 "
+  "type %1">, InGroup<ImplicitFunctionDeclare>;
 def ext_implicit_lib_function_decl_c99 : ExtWarn<
-  "call to undeclared library function '%0' with type %1; ISO C99 and later "
-  "do not support implicit function declarations">,
+  "call to undeclared library function '%0', will assume it exists with"
+  "%select{| standards-mandated}2 type %1; ISO C99 and later do not support "
+  "implicit function declarations">,
   InGroup<ImplicitFunctionDeclare>, DefaultError;
 def note_include_header_or_declare : Note<
   "include the header <%0> or explicitly provide a declaration for '%1'">;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14403e65e8f42..8824ce69c17cc 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -2380,9 +2380,11 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, 
unsigned ID,
   if (!ForRedeclaration &&
       (Context.BuiltinInfo.isPredefinedLibFunction(ID) ||
        Context.BuiltinInfo.isHeaderDependentFunction(ID))) {
+    bool IsStandardsMandated =
+        Context.BuiltinInfo.isDeclaredInStandardHeader(ID);
     Diag(Loc, LangOpts.C99 ? diag::ext_implicit_lib_function_decl_c99
                            : diag::ext_implicit_lib_function_decl)
-        << Context.BuiltinInfo.getName(ID) << R;
+        << Context.BuiltinInfo.getName(ID) << R << IsStandardsMandated;
     if (const char *Header = Context.BuiltinInfo.getHeaderName(ID))
       Diag(Loc, diag::note_include_header_or_declare)
           << Header << Context.BuiltinInfo.getName(ID);
diff --git a/clang/test/Analysis/exercise-ps.c 
b/clang/test/Analysis/exercise-ps.c
index 21d97a364e190..2de884b56ca7f 100644
--- a/clang/test/Analysis/exercise-ps.c
+++ b/clang/test/Analysis/exercise-ps.c
@@ -22,7 +22,7 @@ void_typedef f2_helper(void);
 static void f2(void *buf) {
   F12_typedef* x;
   x = f2_helper();
-  memcpy((&x[1]), (buf), 1); // expected-warning{{call to undeclared library 
function 'memcpy' with type 'void *(void *, const void *}} \
+  memcpy((&x[1]), (buf), 1); // expected-warning{{call to undeclared library 
function 'memcpy', will assume it exists with standards-mandated type 'void 
*(void *, const void *,}} \
   // expected-note{{include the header <string.h> or explicitly provide a 
declaration for 'memcpy'}}
 }
 
diff --git a/clang/test/Driver/implicit-function-as-error.c 
b/clang/test/Driver/implicit-function-as-error.c
index a7f815c8ed69b..f2db881a3eb2e 100644
--- a/clang/test/Driver/implicit-function-as-error.c
+++ b/clang/test/Driver/implicit-function-as-error.c
@@ -6,6 +6,6 @@
 // to an error.
 
 void radar_10894044(void) {
-  printf("Hi\n"); // expected-error {{call to undeclared library function 
'printf' with type 'int (const char *, ...)'}} expected-note {{include the 
header <stdio.h> or explicitly provide a declaration for 'printf'}}
+  printf("Hi\n"); // expected-error {{call to undeclared library function 
'printf', will assume it exists with standards-mandated type 'int (const char 
*, ...)'; ISO C99 and later do not support implicit function declarations}} 
expected-note {{include the header <stdio.h> or explicitly provide a 
declaration for 'printf'}}
   radar_10894044_not_declared(); // expected-error {{call to undeclared 
function 'radar_10894044_not_declared'; ISO C99 and later do not support 
implicit function declarations}}
 }
diff --git a/clang/test/Sema/builtin-setjmp.c b/clang/test/Sema/builtin-setjmp.c
index a71f87162612d..61ebf8012cdba 100644
--- a/clang/test/Sema/builtin-setjmp.c
+++ b/clang/test/Sema/builtin-setjmp.c
@@ -38,7 +38,7 @@ void use(void) {
   // c-error@-3 {{call to undeclared function 'setjmp'; ISO C99 and later do 
not support implicit function declarations}}
   #elif ONLY_JMP_BUF
   // cxx-error@-5 {{undeclared identifier 'setjmp'}}
-  // c-error@-6 {{call to undeclared library function 'setjmp' with type 'int 
(jmp_buf)' (aka 'int (int *)'); ISO C99 and later do not support implicit 
function declarations}}
+  // c-error@-6 {{call to undeclared library function 'setjmp', will assume it 
exists with standards-mandated type 'int (jmp_buf)' (aka 'int (int *)'); ISO 
C99 and later do not support implicit function declarations}}
   // c-note@-7 {{include the header <setjmp.h> or explicitly provide a 
declaration for 'setjmp'}}
   #else
   // cxx-no-diagnostics
diff --git a/clang/test/Sema/implicit-builtin-decl.c 
b/clang/test/Sema/implicit-builtin-decl.c
index 055ba7e70eb12..a36263a27d14c 100644
--- a/clang/test/Sema/implicit-builtin-decl.c
+++ b/clang/test/Sema/implicit-builtin-decl.c
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -verify %s
 
 void f() {
-  int *ptr = malloc(sizeof(int) * 10); // expected-error{{call to undeclared 
library function 'malloc' with type}} \
+  int *ptr = malloc(sizeof(int) * 10); // expected-error{{call to undeclared 
library function 'malloc'}} \
   // expected-note{{include the header <stdlib.h> or explicitly provide a 
declaration for 'malloc'}} \
   // expected-note{{'malloc' is a builtin with type 'void *}}
 }
diff --git a/clang/test/SemaObjC/builtin_objc_lib_functions.m 
b/clang/test/SemaObjC/builtin_objc_lib_functions.m
index a98abdf6039cb..449ae5edfb34e 100644
--- a/clang/test/SemaObjC/builtin_objc_lib_functions.m
+++ b/clang/test/SemaObjC/builtin_objc_lib_functions.m
@@ -1,27 +1,27 @@
 // RUN: %clang_cc1 -x objective-c %s -fsyntax-only -verify
-Class f0(void) { return objc_getClass("a"); } // expected-error {{call to 
undeclared library function 'objc_getClass' with type 'id (const char *)'}} \
+Class f0(void) { return objc_getClass("a"); } // expected-error {{call to 
undeclared library function 'objc_getClass', will assume it exists with type 
'id (const char *)'; ISO C99 and later do not support implicit function 
declarations}} \
                                          // expected-note {{include the header 
<objc/runtime.h> or explicitly provide a declaration for 'objc_getClass'}}
 
-Class f1(void) { return objc_getMetaClass("a"); } // expected-error {{call to 
undeclared library function 'objc_getMetaClass' with type 'id (const char *)'}} 
\
+Class f1(void) { return objc_getMetaClass("a"); } // expected-error {{call to 
undeclared library function 'objc_getMetaClass', will assume it exists with 
type 'id (const char *)'; ISO C99 and later do not support implicit function 
declarations}} \
                                          // expected-note {{include the header 
<objc/runtime.h> or explicitly provide a declaration for 'objc_getMetaClass'}}
 
-void f2(id val) { objc_enumerationMutation(val); } // expected-error {{call to 
undeclared library function 'objc_enumerationMutation' with type 'void (id)'}} \
+void f2(id val) { objc_enumerationMutation(val); } // expected-error {{call to 
undeclared library function 'objc_enumerationMutation', will assume it exists 
with type 'void (id)'; ISO C99 and later do not support implicit function 
declarations}} \
                                                   // expected-note {{include 
the header <objc/runtime.h> or explicitly provide a declaration for 
'objc_enumerationMutation'}}
 
-long double f3(id self, SEL op) { return objc_msgSend_fpret(self, op); } // 
expected-error {{call to undeclared library function 'objc_msgSend_fpret' with 
type 'long double (id, SEL, ...)'}} \
+long double f3(id self, SEL op) { return objc_msgSend_fpret(self, op); } // 
expected-error {{call to undeclared library function 'objc_msgSend_fpret', will 
assume it exists with type 'long double (id, SEL, ...)'; ISO C99 and later do 
not support implicit function declarations}} \
     // expected-note {{include the header <objc/message.h> or explicitly 
provide a declaration for 'objc_msgSend_fpret'}}
 
 id f4(struct objc_super *super, SEL op) { // expected-warning {{declaration of 
'struct objc_super' will not be visible outside of this function}}
-  return objc_msgSendSuper(super, op); // expected-error {{call to undeclared 
library function 'objc_msgSendSuper' with type 'id (struct objc_super *, SEL, 
...)'}} \
+  return objc_msgSendSuper(super, op); // expected-error {{call to undeclared 
library function 'objc_msgSendSuper', will assume it exists with type 'id 
(struct objc_super *, SEL, ...)'; ISO C99 and later do not support implicit 
function declarations}} \
                                        // expected-note {{include the header 
<objc/message.h> or explicitly provide a declaration for 'objc_msgSendSuper'}}
 }
 
 id f5(id val, id *dest) {
-  return objc_assign_strongCast(val, dest); // expected-error {{call to 
undeclared library function 'objc_assign_strongCast' with type 'id (id, id 
*)'}} \
+  return objc_assign_strongCast(val, dest); // expected-error {{call to 
undeclared library function 'objc_assign_strongCast', will assume it exists 
with type 'id (id, id *)'; ISO C99 and later do not support implicit function 
declarations}} \
                                            // expected-note {{include the 
header <objc/objc-auto.h> or explicitly provide a declaration for 
'objc_assign_strongCast'}}
 }
 
 int f6(Class exceptionClass, id exception) {
-  return objc_exception_match(exceptionClass, exception); // expected-error 
{{call to undeclared library function 'objc_exception_match' with type 'int 
(id, id)'}} \
+  return objc_exception_match(exceptionClass, exception); // expected-error 
{{call to undeclared library function 'objc_exception_match', will assume it 
exists with type 'int (id, id)'; ISO C99 and later do not support implicit 
function declarations}} \
                                                          // expected-note 
{{include the header <objc/objc-exception.h> or explicitly provide a 
declaration for 'objc_exception_match'}}
 }
diff --git a/clang/test/SemaObjC/builtin_objc_nslog.m 
b/clang/test/SemaObjC/builtin_objc_nslog.m
index 3c35a02d9b8a3..855d861516f72 100644
--- a/clang/test/SemaObjC/builtin_objc_nslog.m
+++ b/clang/test/SemaObjC/builtin_objc_nslog.m
@@ -3,11 +3,11 @@
 #include <stdarg.h>
 
 void f1(id arg) {
-  NSLog(@"%@", arg); // expected-error {{call to undeclared library function 
'NSLog' with type 'void (id, ...)'}} \
+  NSLog(@"%@", arg); // expected-error {{call to undeclared library function 
'NSLog', will assume it exists with type 'void (id, ...)'; ISO C99 and later do 
not support implicit function declaration}} \
   // expected-note {{include the header <Foundation/NSObjCRuntime.h> or 
explicitly provide a declaration for 'NSLog'}}
 }
 
 void f2(id str, va_list args) {
-  NSLogv(@"%@", args); // expected-error {{call to undeclared library function 
'NSLogv' with type }} \
+  NSLogv(@"%@", args); // expected-error {{call to undeclared library function 
'NSLogv', will assume it exists with type 'void (id, __builtin_va_list)'; ISO 
C99 and later do not support implicit function declarations}} \
   // expected-note {{include the header <Foundation/NSObjCRuntime.h> or 
explicitly provide a declaration for 'NSLogv'}}
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/149314
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to