]> granicus.if.org Git - clang/commitdiff
Suggest typo corrections for implicit function declarations.
authorHans Wennborg <hans@hanshq.net>
Tue, 6 Dec 2011 09:46:12 +0000 (09:46 +0000)
committerHans Wennborg <hans@hanshq.net>
Tue, 6 Dec 2011 09:46:12 +0000 (09:46 +0000)
A mistyped function call becomes an inmplicit function declaration in C.
Suggest typo correction when one can be found.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145930 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/Misc/warning-flags.c
test/Sema/builtins.c
test/Sema/c89.c
test/Sema/implicit-decl.c

index 76051f7b64908c3bd0ad85d84775763fd07f90f3..2031d068a3acc7708201813156c42c589c3310f1 100644 (file)
@@ -141,6 +141,7 @@ def warn_implicit_function_decl : Warning<
 def ext_implicit_function_decl : ExtWarn<
   "implicit declaration of function %0 is invalid in C99">,
   InGroup<ImplicitFunctionDeclare>;
+def note_function_suggestion : Note<"did you mean %0?">;
 
 def err_ellipsis_first_arg : Error<
   "ISO C requires a named argument before '...'">;
@@ -272,7 +273,7 @@ def warn_redecl_library_builtin : Warning<
 def err_builtin_definition : Error<"definition of builtin function %0">;
 def err_types_compatible_p_in_cplusplus : Error<
   "__builtin_types_compatible_p is not valid in C++">;
-def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
+def err_builtin_unknown : Error<"use of unknown builtin %0">;
 def warn_dyn_class_memaccess : Warning<
   "%select{destination for|source of|first operand of|second operand of}0 this "
   "%1 call is a pointer to dynamic class %2; vtable pointer will be "
index c90b7492a2fc0104bba366328ce40851c7b3d80a..cc8ec878ccb41a62a1281887cccf1ff5efc46b7f 100644 (file)
@@ -7262,14 +7262,38 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
     return Pos->second;
   }
 
+  // See if we can find a typo correction.
+  TypoCorrection Corrected;
+  FunctionDecl *Func = 0;
+  std::string CorrectedStr;
+  std::string CorrectedQuotedStr;
+  if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
+                                    LookupOrdinaryName, S, 0))) {
+    // Since this is an implicit function declaration, we are only
+    // interested in a potential typo for a function name.
+    if ((Func = dyn_cast_or_null<FunctionDecl>(
+            Corrected.getCorrectionDecl()))) {
+      CorrectedStr = Corrected.getAsString(getLangOptions());
+      CorrectedQuotedStr = Corrected.getQuoted(getLangOptions());
+    }
+  }
+
   // Extension in C99.  Legal in C90, but warn about it.
   if (II.getName().startswith("__builtin_"))
-    Diag(Loc, diag::warn_builtin_unknown) << &II;
+    Diag(Loc, diag::err_builtin_unknown) << &II;
   else if (getLangOptions().C99)
     Diag(Loc, diag::ext_implicit_function_decl) << &II;
   else
     Diag(Loc, diag::warn_implicit_function_decl) << &II;
 
+  if (Func) {
+    // If we found a typo correction, then suggest that.
+    Diag(Loc, diag::note_function_suggestion) << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(Loc, CorrectedStr);
+    if (Func->getLocation().isValid() && !II.getName().startswith("__builtin_"))
+      Diag(Func->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;
+  }
+
   // Set a Declarator for the implicit definition: int foo();
   const char *Dummy;
   AttributeFactory attrFactory;
index 04a2fde8604e4f79266f7a8c46c43c8166a7c524..d384bb5d539d17a04a5520dadfd4db9d5f38f9f3 100644 (file)
@@ -17,7 +17,7 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (272):
+CHECK: Warnings without flags (271):
 CHECK-NEXT:   ext_anon_param_requires_type_specifier
 CHECK-NEXT:   ext_anonymous_struct_union_qualified
 CHECK-NEXT:   ext_array_init_copy
@@ -128,7 +128,6 @@ CHECK-NEXT:   warn_bad_receiver_type
 CHECK-NEXT:   warn_bitfield_width_exceeds_type_size
 CHECK-NEXT:   warn_bool_switch_condition
 CHECK-NEXT:   warn_braces_around_scalar_init
-CHECK-NEXT:   warn_builtin_unknown
 CHECK-NEXT:   warn_c_kext
 CHECK-NEXT:   warn_call_to_pure_virtual_member_function_from_ctor_dtor
 CHECK-NEXT:   warn_call_wrong_number_of_arguments
index 64efefc7fdaddca6ecaf0e25865ee3a7954d1441..0850cc4ee4b922f1043f279b2cfe94a533fd2e6a 100644 (file)
@@ -78,7 +78,8 @@ void test12(void) {
 }
 
 void test_unknown_builtin(int a, int b) {
-  __builtin_foo(a, b); // expected-error{{use of unknown builtin}}
+  __builtin_isles(a, b); // expected-error{{use of unknown builtin}} \
+                         // expected-note{{did you mean '__builtin_isless'?}}
 }
 
 int test13() {
@@ -101,4 +102,3 @@ int test16() {
   return __builtin_constant_p() + // expected-error{{too few arguments}}
          __builtin_constant_p(1, 2); // expected-error {{too many arguments}}
 }
-
index 670dd15539f033551e46fee4973a98a1e66b2c9d..e4cdc11be1cd75339bb07dbd7bd1dd7b87e80c35 100644 (file)
@@ -1,4 +1,4 @@
-/* RUN: %clang_cc1 %s -std=c89 -pedantic -fsyntax-only -verify
+/* RUN: %clang_cc1 %s -std=c89 -pedantic -fsyntax-only -verify -Wimplicit-function-declaration
  */
 void test1() {
   {
@@ -82,3 +82,10 @@ void test13b() {
 int test14() { return (&*test14)(); }
 
 int test15[5] = { [2] = 1 }; /* expected-warning {{designated initializers are a C99 feature}} */
+
+extern int printf(__const char *__restrict __format, ...); /* expected-note{{'printf' declared here}} */
+
+void test16() {
+  printg("Hello, world!\n"); /* expected-warning {{implicit declaration of function 'printg'}}
+                                expected-note {{did you mean 'printf'?}} */
+}
index f455977536630b4a6a8dda70052184d41019526d..72e42e05bb654c5bfc98fb6abe4d68c4ad7c06e7 100644 (file)
@@ -3,6 +3,8 @@
 typedef int int32_t;
 typedef unsigned char Boolean;
 
+extern int printf(__const char *__restrict __format, ...); // expected-note{{'printf' declared here}}
+
 void func() {
    int32_t *vector[16];
    const char compDesc[16 + 1];
@@ -10,8 +12,13 @@ void func() {
    if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-note {{previous implicit declaration is here}} \
          expected-warning {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
    }
+
+   printg("Hello, World!\n"); // expected-warning{{implicit declaration of function 'printg' is invalid in C99}} \
+                              // expected-note{{did you mean 'printf'?}}
+
+  __builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}} \
+                          // expected-note{did you mean '__builtin_is_less'?}}
 }
 Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}}
  return 0;
 }
-