[cfe-commits] r137966 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaCXX/function-redecl.cpp
Eli Friedman
eli.friedman at gmail.com
Thu Aug 18 13:38:55 PDT 2011
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:
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
More information about the cfe-commits
mailing list