[cfe-commits] r148420 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/Sema/implicit-decl.c test/SemaCXX/typo-correction.cpp

Kaelyn Uhrain rikka at google.com
Wed Jan 18 13:41:41 PST 2012


Author: rikka
Date: Wed Jan 18 15:41:41 2012
New Revision: 148420

URL: http://llvm.org/viewvc/llvm-project?rev=148420&view=rev
Log:
Convert SemaDecl.cpp to pass callback objects to CorrectTypo.

Includes tests highlighting the cases where accuracy has improved
(there is one call that does no filtering beyond selecting the set
of allowed keywords, and one call that only triggers for ObjC code
for which a test by someone who knows ObjC would be welcome). Also
fixes a small typo in one of the suggestion messages, and drops a
malformed "expected-note" for a suggestion that did not occur even
when the malformed note was committed as r145930.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/implicit-decl.c
    cfe/trunk/test/SemaCXX/typo-correction.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=148420&r1=148419&r2=148420&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jan 18 15:41:41 2012
@@ -3480,7 +3480,7 @@
   "out-of-line definition of %0 does not match any declaration in %1">;
 def err_member_def_does_not_match_suggest : Error<
   "out-of-line definition of %0 does not match any declaration in %1; "
-  "did you mean %2">;
+  "did you mean %2?">;
 def err_member_def_does_not_match_ret_type : Error<
   "out-of-line definition of %q0 differs from the declaration in the return type">;
 def err_nonstatic_member_out_of_line : Error<

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=148420&r1=148419&r2=148420&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan 18 15:41:41 2012
@@ -55,6 +55,30 @@
   return DeclGroupPtrTy::make(DeclGroupRef(Ptr));
 }
 
+namespace {
+
+class TypeNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  TypeNameValidatorCCC(bool AllowInvalid) : AllowInvalidDecl(AllowInvalid) {
+    WantExpressionKeywords = false;
+    WantCXXNamedCasts = false;
+    WantRemainingKeywords = false;
+  }
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl())
+      return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
+          (AllowInvalidDecl || !ND->isInvalidDecl());
+    else
+      return candidate.isKeyword();
+  }
+
+ private:
+  bool AllowInvalidDecl;
+};
+
+}
+
 /// \brief If the identifier refers to a type name within this scope,
 /// return the declaration of that type.
 ///
@@ -147,9 +171,9 @@
   case LookupResult::NotFound:
   case LookupResult::NotFoundInCurrentInstantiation:
     if (CorrectedII) {
+      TypeNameValidatorCCC Validator(true);
       TypoCorrection Correction = CorrectTypo(Result.getLookupNameInfo(),
-                                              Kind, S, SS, 0, false,
-                                              Sema::CTC_Type);
+                                              Kind, S, SS, &Validator);
       IdentifierInfo *NewII = Correction.getCorrectionAsIdentifierInfo();
       TemplateTy Template;
       bool MemberOfUnknownSpecialization;
@@ -339,9 +363,10 @@
   
   // There may have been a typo in the name of the type. Look up typo
   // results, in case we have something that we can suggest.
+  TypeNameValidatorCCC Validator(false);
   if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc),
-                                             LookupOrdinaryName, S, SS, NULL,
-                                             false, CTC_Type)) {
+                                             LookupOrdinaryName, S, SS,
+                                             &Validator)) {
     std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
     std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));
 
@@ -350,32 +375,28 @@
       // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.
       Diag(IILoc, diag::err_unknown_typename_suggest)
         << &II << CorrectedQuotedStr;
-      return true;      
     } else {
       NamedDecl *Result = Corrected.getCorrectionDecl();
-      if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&
-          !Result->isInvalidDecl()) {
-        // We found a similarly-named type or interface; suggest that.
-        if (!SS || !SS->isSet())
-          Diag(IILoc, diag::err_unknown_typename_suggest)
-            << &II << CorrectedQuotedStr
-            << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
-        else if (DeclContext *DC = computeDeclContext(*SS, false))
-          Diag(IILoc, diag::err_unknown_nested_typename_suggest) 
-            << &II << DC << CorrectedQuotedStr << SS->getRange()
-            << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
-        else
-          llvm_unreachable("could not have corrected a typo here");
+      // We found a similarly-named type or interface; suggest that.
+      if (!SS || !SS->isSet())
+        Diag(IILoc, diag::err_unknown_typename_suggest)
+          << &II << CorrectedQuotedStr
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else if (DeclContext *DC = computeDeclContext(*SS, false))
+        Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+          << &II << DC << CorrectedQuotedStr << SS->getRange()
+          << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+      else
+        llvm_unreachable("could not have corrected a typo here");
 
-        Diag(Result->getLocation(), diag::note_previous_decl)
-          << CorrectedQuotedStr;
-        
-        SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
-                                    false, false, ParsedType(),
-                                    /*NonTrivialTypeSourceInfo=*/true);
-        return true;
-      }
+      Diag(Result->getLocation(), diag::note_previous_decl)
+        << CorrectedQuotedStr;
+
+      SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,
+                                  false, false, ParsedType(),
+                                  /*NonTrivialTypeSourceInfo=*/true);
     }
+    return true;
   }
 
   if (getLangOptions().CPlusPlus) {
@@ -546,9 +567,10 @@
     // close to this name.
     if (!SecondTry) {
       SecondTry = true;
+      CorrectionCandidateCallback DefaultValidator;
       if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),
                                                  Result.getLookupKind(), S, 
-                                                 &SS)) {
+                                                 &SS, &DefaultValidator)) {
         unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;
         unsigned QualifiedDiag = diag::err_no_member_suggest;
         std::string CorrectedStr(Corrected.getAsString(getLangOptions()));
@@ -1241,10 +1263,11 @@
   if (!IDecl && DoTypoCorrection) {
     // Perform typo correction at the given location, but only if we
     // find an Objective-C class name.
-    TypoCorrection C;
-    if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName,
-                         TUScope, NULL, NULL, false, CTC_NoKeywords)) &&
-        (IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) {
+    DeclFilterCCC<ObjCInterfaceDecl> Validator;
+    if (TypoCorrection C = CorrectTypo(DeclarationNameInfo(Id, IdLoc),
+                                       LookupOrdinaryName, TUScope, NULL,
+                                       &Validator)) {
+      IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
       Diag(IdLoc, diag::err_undef_interface_suggest)
         << Id << IDecl->getDeclName() 
         << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());
@@ -4409,6 +4432,18 @@
   };
 }
 
+namespace {
+
+// Callback to only accept typo corrections that have a non-zero edit distance.
+class DifferentNameValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return candidate.getEditDistance() > 0;
+  }
+};
+
+}
+
 /// \brief Generate diagnostics for an invalid function redeclaration.
 ///
 /// This routine handles generating the diagnostic messages for an invalid
@@ -4438,6 +4473,7 @@
   SemaRef.LookupQualifiedName(Prev, NewDC);
   assert(!Prev.isAmbiguous() &&
          "Cannot have an ambiguity in previous-declaration lookup");
+  DifferentNameValidatorCCC Validator;
   if (!Prev.empty()) {
     for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
          Func != FuncEnd; ++Func) {
@@ -4453,8 +4489,8 @@
     }
   // If the qualified name lookup yielded nothing, try typo correction
   } else if ((Correction = SemaRef.CorrectTypo(Prev.getLookupNameInfo(),
-                                         Prev.getLookupKind(), 0, 0, NewDC)) &&
-             Correction.getCorrection() != Name) {
+                                         Prev.getLookupKind(), 0, 0,
+                                         &Validator, NewDC))) {
     // Trap errors.
     Sema::SFINAETrap Trap(SemaRef);
 
@@ -7309,21 +7345,20 @@
   // function declaration is going to be treated as an error.
   if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) {
     TypoCorrection Corrected;
+    DeclFilterCCC<FunctionDecl> Validator;
     if (S && (Corrected = CorrectTypo(DeclarationNameInfo(&II, Loc),
-                                      LookupOrdinaryName, S, 0))) {
-      NamedDecl *Decl = Corrected.getCorrectionDecl();
-      if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Decl)) {
-        std::string CorrectedStr = Corrected.getAsString(getLangOptions());
-        std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOptions());
-
-        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;
-      }
+                                      LookupOrdinaryName, S, 0, &Validator))) {
+      std::string CorrectedStr = Corrected.getAsString(getLangOptions());
+      std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOptions());
+      FunctionDecl *Func = Corrected.getCorrectionDeclAs<FunctionDecl>();
+
+      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;
     }
   }
 

Modified: cfe/trunk/test/Sema/implicit-decl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/implicit-decl.c?rev=148420&r1=148419&r2=148420&view=diff
==============================================================================
--- cfe/trunk/test/Sema/implicit-decl.c (original)
+++ cfe/trunk/test/Sema/implicit-decl.c Wed Jan 18 15:41:41 2012
@@ -16,9 +16,17 @@
    printg("Hello, World!\n"); // expected-error{{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'?}}
+  __builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}}
 }
 Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}}
  return 0;
 }
+
+
+// Test the typo-correction callback in Sema::ImplicitlyDefineFunction
+extern int sformatf(char *str, __const char *__restrict __format, ...); // expected-note{{'sformatf' declared here}}
+void test_implicit() {
+  int formats = 0;
+  formatd("Hello, World!\n"); // expected-error{{implicit declaration of function 'formatd' is invalid in C99}} \
+                              // expected-note{{did you mean 'sformatf'?}}
+}

Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=148420&r1=148419&r2=148420&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction.cpp Wed Jan 18 15:41:41 2012
@@ -67,12 +67,14 @@
 st var = { .fielda = 0.0 }; // expected-error{{field designator 'fielda' does not refer to any field in type 'st'; did you mean 'FieldA'?}}
 
 // Test the improvement from passing a callback object to CorrectTypo in
-// Sema::BuildCXXNestedNameSpecifier.
-typedef char* another_str;
+// Sema::BuildCXXNestedNameSpecifier. And also for the improvement by doing
+// so in Sema::getTypeName.
+typedef char* another_str; // expected-note{{'another_str' declared here}}
 namespace AnotherStd { // expected-note{{'AnotherStd' declared here}}
   class string {};
 }
 another_std::string str; // expected-error{{use of undeclared identifier 'another_std'; did you mean 'AnotherStd'?}}
+another_str *cstr = new AnotherStr; // expected-error{{unknown type name 'AnotherStr'; did you mean 'another_str'?}}
 
 // Test the improvement from passing a callback object to CorrectTypo in
 // Sema::ActOnSizeofParameterPackExpr.
@@ -80,3 +82,19 @@
 template<typename ...TypeNames> struct count { // expected-note{{parameter pack 'TypeNames' declared here}}
   static const unsigned value = sizeof...(TyreNames); // expected-error{{'TyreNames' does not refer to the name of a parameter pack; did you mean 'TypeNames'?}}
 };
+
+// Test the typo-correction callback in Sema::DiagnoseUnknownTypeName.
+namespace unknown_type_test {
+  class StreamOut {}; // expected-note{{'StreamOut' declared here}}
+  long stream_count;
+};
+unknown_type_test::stream_out out; // expected-error{{no type named 'stream_out' in namespace 'unknown_type_test'; did you mean 'StreamOut'?}}
+
+// Test the typo-correction callback in Sema::DiagnoseInvalidRedeclaration.
+struct BaseDecl {
+  void add_in(int i);
+};
+struct TestRedecl : public BaseDecl {
+  void add_it(int i); // expected-note{{'add_it' declared here}}
+};
+void TestRedecl::add_in(int i) {} // expected-error{{out-of-line definition of 'add_in' does not match any declaration in 'TestRedecl'; did you mean 'add_it'?}}





More information about the cfe-commits mailing list