[cfe-commits] r137966 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaCXX/function-redecl.cpp

Chandler Carruth chandlerc at google.com
Thu Aug 18 14:16:50 PDT 2011


On Thu, Aug 18, 2011 at 1:38 PM, Eli Friedman <eli.friedman at gmail.com>wrote:

> On Thu, Aug 18, 2011 at 11:19 AM, Kaelyn Uhrain <rikka at google.com> wrote:
> > Author: rikka
> > Date: Thu Aug 18 13:19:12 2011
> > New Revision: 137966
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=137966&view=rev
> > Log:
> > Rework DiagnoseInvalidRedeclaration to add the ability to correct typos
> when
> > diagnosing invalid function redeclarations.
> >
> > Modified:
> >    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> >    cfe/trunk/lib/Sema/SemaDecl.cpp
> >    cfe/trunk/test/SemaCXX/function-redecl.cpp
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=137966&r1=137965&r2=137966&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Aug 18
> 13:19:12 2011
> > @@ -610,6 +610,8 @@
> >   "friend type templates must use an elaborated type">;
> >  def err_no_matching_local_friend : Error<
> >   "no matching function found in local scope">;
> > +def err_no_matching_local_friend_suggest : Error<
> > +  "no matching function %0 found in local scope; did you mean %2">;
> >  def err_partial_specialization_friend : Error<
> >   "partial specialization cannot be declared as a friend">;
> >
> > @@ -3038,6 +3040,9 @@
> >   "out-of-line definition of %0 from class %1 without definition">;
> >  def err_member_def_does_not_match : Error<
> >   "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">;
> >  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=137966&r1=137965&r2=137966&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Aug 18 13:19:12 2011
> > @@ -4204,28 +4204,79 @@
> >   return AddedAny;
> >  }
> >
> > -static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD) {
> > -  LookupResult Prev(S, NewFD->getDeclName(), NewFD->getLocation(),
> > +static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD,
> > +                                         bool isFriendDecl) {
> > +  DeclarationName Name = NewFD->getDeclName();
> > +  DeclContext *DC = NewFD->getDeclContext();
> > +  LookupResult Prev(S, Name, NewFD->getLocation(),
> >                     Sema::LookupOrdinaryName, Sema::ForRedeclaration);
> >   llvm::SmallVector<unsigned, 1> MismatchedParams;
> > -  S.LookupQualifiedName(Prev, NewFD->getDeclContext());
> > +  llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches;
> > +  TypoCorrection Correction;
> > +  unsigned DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend
> > +                                  : diag::err_member_def_does_not_match;
> > +
> > +  NewFD->setInvalidDecl();
> > +  S.LookupQualifiedName(Prev, DC);
> >   assert(!Prev.isAmbiguous() &&
> >          "Cannot have an ambiguity in previous-declaration lookup");
> > -  for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
> > -       Func != FuncEnd; ++Func) {
> > -    FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func);
> > -    if (FD && isNearlyMatchingFunction(S.Context, FD, NewFD,
> > -                                       MismatchedParams)) {
> > -      if (MismatchedParams.size() > 0) {
> > -        unsigned Idx = MismatchedParams.front();
> > -        ParmVarDecl *FDParam = FD->getParamDecl(Idx);
> > -        S.Diag(FDParam->getTypeSpecStartLoc(),
> > -               diag::note_member_def_close_param_match)
> > -            << Idx+1 << FDParam->getType() <<
> NewFD->getParamDecl(Idx)->getType();
> > -      } else
> > -        S.Diag(FD->getLocation(), diag::note_member_def_close_match);
> > +  if (!Prev.empty()) {
> > +    for (LookupResult::iterator Func = Prev.begin(), FuncEnd =
> Prev.end();
> > +         Func != FuncEnd; ++Func) {
> > +      FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func);
> > +      if (FD && isNearlyMatchingFunction(S.Context, FD, NewFD,
> > +                                         MismatchedParams)) {
> > +        // Add 1 to the index so that 0 can mean the mismatch didn't
> > +        // involve a parameter
> > +        unsigned ParamNum =
> > +            MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1;
> > +        NearMatches.push_back(std::make_pair(FD, ParamNum));
> > +      }
> > +    }
> > +  // If the qualified name lookup yielded nothing, try typo correction
> > +  } else if ((Correction = S.CorrectTypo(Prev.getLookupNameInfo(),
> > +                                         Prev.getLookupKind(), 0, 0,
> DC))) {
> > +    DiagMsg = isFriendDecl ? diag::err_no_matching_local_friend_suggest
> > +                           :
> diag::err_member_def_does_not_match_suggest;
> > +    for (TypoCorrection::decl_iterator CDecl = Correction.begin(),
> > +                                    CDeclEnd = Correction.end();
> > +         CDecl != CDeclEnd; ++CDecl) {
> > +      FunctionDecl *FD = dyn_cast<FunctionDecl>(*CDecl);
> > +      if (FD && isNearlyMatchingFunction(S.Context, FD, NewFD,
> > +                                         MismatchedParams)) {
> > +        // Add 1 to the index so that 0 can mean the mismatch didn't
> > +        // involve a parameter
> > +        unsigned ParamNum =
> > +            MismatchedParams.empty() ? 0 : MismatchedParams.front() + 1;
> > +        NearMatches.push_back(std::make_pair(FD, ParamNum));
> > +      }
> >     }
> >   }
> > +
> > +  if (Correction)
> > +    S.Diag(NewFD->getLocation(), DiagMsg)
> > +        << Name << DC << Correction.getQuoted(S.getLangOptions())
> > +        << FixItHint::CreateReplacement(
> > +            NewFD->getLocation(),
> Correction.getAsString(S.getLangOptions()));
> > +  else
> > +    S.Diag(NewFD->getLocation(), DiagMsg) << Name << DC <<
> NewFD->getLocation();
> > +
> > +  for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>,
> 1>::iterator
> > +       NearMatch = NearMatches.begin(), NearMatchEnd =
> NearMatches.end();
> > +       NearMatch != NearMatchEnd; ++NearMatch) {
> > +    FunctionDecl *FD = NearMatch->first;
> > +
> > +    if (unsigned Idx = NearMatch->second) {
> > +      ParmVarDecl *FDParam = FD->getParamDecl(Idx-1);
> > +      S.Diag(FDParam->getTypeSpecStartLoc(),
> > +             diag::note_member_def_close_param_match)
> > +          << Idx << FDParam->getType() <<
> NewFD->getParamDecl(Idx-1)->getType();
> > +    } else if (Correction) {
> > +      S.Diag(FD->getLocation(), diag::note_previous_decl)
> > +        << Correction.getQuoted(S.getLangOptions());
> > +    } else
> > +      S.Diag(FD->getLocation(), diag::note_member_def_close_match);
> > +  }
> >  }
> >
> >  NamedDecl*
> > @@ -4939,19 +4990,14 @@
> >               // Complain about this problem, and attempt to suggest
> close
> >               // matches (e.g., those that differ only in cv-qualifiers
> and
> >               // whether the parameter types are references).
> > -              Diag(D.getIdentifierLoc(),
> diag::err_member_def_does_not_match)
> > -              << Name << DC << D.getCXXScopeSpec().getRange();
> > -              NewFD->setInvalidDecl();
> >
> > -              DiagnoseInvalidRedeclaration(*this, NewFD);
> > +              DiagnoseInvalidRedeclaration(*this, NewFD, false);
> >             }
> >
> >         // Unqualified local friend declarations are required to resolve
> >         // to something.
> >         } else if (isFriend &&
> cast<CXXRecordDecl>(CurContext)->isLocalClass()) {
> > -          Diag(D.getIdentifierLoc(),
> diag::err_no_matching_local_friend);
> > -          NewFD->setInvalidDecl();
> > -          DiagnoseInvalidRedeclaration(*this, NewFD);
> > +          DiagnoseInvalidRedeclaration(*this, NewFD, true);
> >         }
> >
> >     } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() &&
> >
> > Modified: cfe/trunk/test/SemaCXX/function-redecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-redecl.cpp?rev=137966&r1=137965&r2=137966&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/function-redecl.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/function-redecl.cpp Thu Aug 18 13:19:12 2011
> > @@ -24,3 +24,29 @@
> >     }
> >   }
> >  }
> > +
> > +class A {
> > + void typocorrection(); // expected-note {{'typocorrection' declared
> here}}
> > +};
> > +
> > +void A::Notypocorrection() { // expected-error {{out-of-line definition
> of 'Notypocorrection' does not match any declaration in 'A'; did you mean
> 'typocorrection'}}
> > +}
> > +
> > +
> > +namespace test0 {
> > +  void dummy() {
> > +    void Bar(); // expected-note {{'Bar' declared here}}
> > +    class A {
> > +      friend void bar(); // expected-error {{no matching function 'bar'
> found in local scope; did you mean 'Bar'}}
> > +    };
> > +  }
> > +}
> > +
> > +
> > +class B {
> > + void typocorrection(const int); // expected-note {{type of 1st
> parameter of member declaration does not match definition}}
> > + void typocorrection(double);
> > +};
> > +
> > +void B::Notypocorrection(int) { // expected-error {{out-of-line
> definition of 'Notypocorrection' does not match any declaration in 'B'; did
> you mean 'typocorrection'}}
> > +}
>
> This is giving an extremely strange-looking error for the following:
>

Looks like its doing really nice qualifier-based typo correction, but
failing to mention those qualified names in the diagnostic, or suggest the
fixit hint for the qualifier itself... This works for other contexts though
so hopefully it doesn't require a huge change to fix.


>
> struct A { int f(); };
> struct B : public A {};
> int B::f() { return 3; }
>
> <stdin>:3:8: error: out-of-line definition of 'f' does not match any
> declaration in 'B'; did you mean 'f'
> int B::f() { return 3; }
>       ^
>       f
> <stdin>:1:16: note: 'f' declared here
> struct A { int f(); };
>               ^
> 1 error generated.
>
> -Eli
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110818/c523572f/attachment.html>


More information about the cfe-commits mailing list