]> granicus.if.org Git - clang/commitdiff
When typo correction produces an overloaded result when looking up a member,
authorNick Lewycky <nicholas@mxc.ca>
Tue, 7 May 2013 22:14:37 +0000 (22:14 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Tue, 7 May 2013 22:14:37 +0000 (22:14 +0000)
return all the overloads instead of just picking the first possible declaration.
This removes an invalid note (and on occasion other invalid diagnostics) and
also makes clang's parsing recovery behave as if the text from its fixit were
applied.

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

include/clang/Sema/TypoCorrection.h
lib/Sema/SemaExprMember.cpp
test/SemaCXX/typo-correction.cpp

index cdd71c8fa9aabf0e580ad3c5dbb1c72d5776f07d..5fbfba2d5d0e88af13ec23cbda3739485801aae3 100644 (file)
@@ -116,7 +116,7 @@ public:
   }
 
   /// \brief Gets the pointer to the declaration of the typo correction
-  NamedDeclgetCorrectionDecl() const {
+  NamedDecl *getCorrectionDecl() const {
     return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : 0;
   }
   template <class DeclClass>
index 545ac2746d6d83ec2602c09915b731006ce38920..0f65d3f50510cce7baa6bf4ab8b85d6e8c5985d9 100644 (file)
@@ -605,19 +605,33 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
                                                  R.getLookupKind(), NULL,
                                                  &SS, Validator, DC);
   R.clear();
-  if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+  if (Corrected.isResolved() && !Corrected.isKeyword()) {
     std::string CorrectedStr(
         Corrected.getAsString(SemaRef.getLangOpts()));
     std::string CorrectedQuotedStr(
         Corrected.getQuoted(SemaRef.getLangOpts()));
+
     R.setLookupName(Corrected.getCorrection());
-    R.addDecl(ND);
+    for (TypoCorrection::decl_iterator DI = Corrected.begin(),
+                                       DIEnd = Corrected.end();
+         DI != DIEnd; ++DI) {
+      R.addDecl(*DI);
+    }
+    R.resolveKind();
+
     SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
       << Name << DC << CorrectedQuotedStr << SS.getRange()
       << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
                                       CorrectedStr);
-    SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
-      << ND->getDeclName();
+
+    // If we're typo-correcting to an overloaded name, we don't yet have enough
+    // information to do overload resolution, so we don't know which previous
+    // declaration to point to.
+    if (!Corrected.isOverloaded()) {
+      NamedDecl *ND = Corrected.getCorrectionDecl();
+      SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)
+        << ND->getDeclName();
+    }
   }
 
   return false;
index caa6355fe958d7299dce08423c83ab831c7f213c..3d40d842f0e9ad9579c372f6bbd15a2896263c97 100644 (file)
@@ -239,7 +239,7 @@ void test() {
 
 namespace PR13387 {
 struct A {
-  void CreateFoo(float, float); // expected-note {{'CreateFoo' declared here}}
+  void CreateFoo(float, float);
   void CreateBar(float, float);
 };
 struct B : A {
@@ -260,3 +260,45 @@ struct T {
 void f() {
  data_struct->foo(); // expected-error-re{{use of undeclared identifier 'data_struct'$}}
 }
+
+namespace b6956809_test1 {
+  struct A {};
+  struct B {};
+
+  struct S1 {
+    void method(A*);  // no note here
+    void method(B*);
+  };
+
+  void test1() {
+    B b;
+    S1 s;
+    s.methodd(&b);  // expected-error{{no member named 'methodd' in 'b6956809_test1::S1'; did you mean 'method'}}
+  }
+
+  struct S2 {
+    S2();
+    void method(A*) const;  // expected-note{{candidate function not viable}}
+   private:
+    void method(B*);  // expected-note{{candidate function not viable}}
+  };
+
+  void test2() {
+    B b;
+    const S2 s;
+    s.methodd(&b);  // expected-error{{no member named 'methodd' in 'b6956809_test1::S2'; did you mean 'method'}}  expected-error{{no matching member function for call to 'method'}}
+  }
+}
+
+namespace b6956809_test2 {
+  template<typename T> struct Err { typename T::error n; };  // expected-error{{type 'void *' cannot be used prior to '::' because it has no members}}
+  struct S {
+    template<typename T> typename Err<T>::type method(T);  // expected-note{{in instantiation of template class 'b6956809_test2::Err<void *>' requested here}}  expected-note{{while substituting deduced template arguments into function template 'method' [with T = void *]}}
+    template<typename T> int method(T *);
+  };
+
+  void test() {
+    S s;
+    int k = s.methodd((void*)0);  // expected-error{{no member named 'methodd' in 'b6956809_test2::S'; did you mean 'method'?}}
+  }
+}