]> granicus.if.org Git - clang/commitdiff
Give the default CorrectionCandidateCallback::ValidateCandidate some
authorKaelyn Uhrain <rikka@google.com>
Wed, 3 Apr 2013 16:59:49 +0000 (16:59 +0000)
committerKaelyn Uhrain <rikka@google.com>
Wed, 3 Apr 2013 16:59:49 +0000 (16:59 +0000)
smarts so that it doesn't approve of keywords and/or type names when it
knows (based on its flags) that those kinds of corrections are not
wanted.

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

include/clang/Sema/TypoCorrection.h
lib/Parse/ParseTentative.cpp
lib/Sema/SemaLookup.cpp
test/SemaCXX/typo-correction.cpp

index 0b897b55ccaa909b5233b9b1d60b0f3b0cc1370b..cdd71c8fa9aabf0e580ad3c5dbb1c72d5776f07d 100644 (file)
@@ -228,9 +228,11 @@ class CorrectionCandidateCallback {
   /// candidate is viable, without ranking potentially viable candidates.
   /// Only ValidateCandidate or RankCandidate need to be overriden by a
   /// callback wishing to check the viability of correction candidates.
-  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
-    return true;
-  }
+  /// The default predicate always returns true if the candidate is not a type
+  /// name or keyword, true for types if WantTypeSpecifiers is true, and true
+  /// for keywords if WantTypeSpecifiers, WantExpressionKeywords,
+  /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true.
+  virtual bool ValidateCandidate(const TypoCorrection &candidate);
 
   /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank
   /// to a candidate (where a lower value represents a better candidate), or
index fe602f6b658cfec3a07ba88f1ed65fc5291e3b9c..5e0ef2b83f67ed87b4a18f4776741aca54dbe451 100644 (file)
@@ -999,6 +999,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
       // to types and identifiers, in order to try to recover from errors.
       CorrectionCandidateCallback TypoCorrection;
       TypoCorrection.WantRemainingKeywords = false;
+      TypoCorrection.WantTypeSpecifiers = Next.isNot(tok::arrow);
       switch (TryAnnotateName(false /* no nested name specifier */,
                               &TypoCorrection)) {
       case ANK_Error:
index 0fe3db1901fdebfaaf04c3b30d43c6219e22ec69..2b3ca3f0ef786085cf0c0367df5095317cadf8de 100644 (file)
@@ -4139,3 +4139,21 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
 
   return CorrectionName.getAsString();
 }
+
+bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candidate) {
+  if (!candidate.isResolved())
+    return true;
+
+  if (candidate.isKeyword())
+    return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts ||
+           WantRemainingKeywords || WantObjCSuper;
+
+  for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
+                                           CDeclEnd = candidate.end();
+       CDecl != CDeclEnd; ++CDecl) {
+    if (!isa<TypeDecl>(*CDecl))
+      return true;
+  }
+
+  return WantTypeSpecifiers;
+}
index 4a3f0f6b2949907261a0eadf10b2231d63691ba8..caa6355fe958d7299dce08423c83ab831c7f213c 100644 (file)
@@ -250,3 +250,13 @@ void f(B &x) {
   x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
 }
 }
+
+struct DataStruct {void foo();};
+struct T {
+ DataStruct data_struct;
+ void f();
+};
+// should be void T::f();
+void f() {
+ data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}}
+}