From 0179868cce096101236261ff64eca30224b1f233 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 26 Mar 2012 16:54:18 +0000 Subject: [PATCH] When diagnosing an invalid out-of-line redeclaration, don't permit typo correction to introduce a nested-name-specifier; we aren't prepared to handle it here. Fixes PR12297 / . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153445 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/TypoCorrection.h | 6 +++++- lib/Sema/SemaDecl.cpp | 9 ++++++++- lib/Sema/SemaLookup.cpp | 15 +++++++++++---- test/FixIt/typo-crash.cpp | 17 +++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index a8f6e1178b..a333c8182b 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -205,7 +205,7 @@ class CorrectionCandidateCallback { : WantTypeSpecifiers(true), WantExpressionKeywords(true), WantCXXNamedCasts(true), WantRemainingKeywords(true), WantObjCSuper(false), - IsObjCIvarLookup(false) {} + IsObjCIvarLookup(false), AllowAddedQualifier(true) {} virtual ~CorrectionCandidateCallback() {} @@ -239,6 +239,10 @@ class CorrectionCandidateCallback { // Temporary hack for the one case where a CorrectTypoContext enum is used // when looking up results. bool IsObjCIvarLookup; + + /// \brief Whether to allow this typo correction to add a + /// nested-name-specifier. + bool AllowAddedQualifier; }; /// @brief Simple template class for restricting typo correction candidates diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index e92b3e4aca..d4159bf189 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4478,7 +4478,14 @@ namespace { class DifferentNameValidatorCCC : public CorrectionCandidateCallback { public: DifferentNameValidatorCCC(CXXRecordDecl *Parent) - : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) {} + : ExpectedParent(Parent ? Parent->getCanonicalDecl() : 0) { + // Don't allow any additional qualification. + // FIXME: It would be nice to perform this additional qualification. + // However, DiagnoseInvalidRedeclaration is unable to handle the + // qualification, because it doesn't know how to pass the corrected + // nested-name-specifier through to ActOnFunctionDeclarator. + AllowAddedQualifier = false; + } virtual bool ValidateCandidate(const TypoCorrection &candidate) { if (candidate.getEditDistance() == 0) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index e47bc1c8b1..ed5a8da61c 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -3806,7 +3806,13 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, } } - if (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())) { + // Determine whether we are going to search in the various namespaces for + // corrections. + bool SearchNamespaces + = getLangOpts().CPlusPlus && CCC.AllowAddedQualifier && + (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace())); + + if (IsUnqualifiedLookup || SearchNamespaces) { // For unqualified lookup, look through all of the names that we have // seen in this translation unit. // FIXME: Re-add the ability to skip very unlikely potential corrections. @@ -3852,8 +3858,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return TypoCorrection(); } - // Build the NestedNameSpecifiers for the KnownNamespaces - if (getLangOpts().CPlusPlus) { + // Build the NestedNameSpecifiers for the KnownNamespaces, if we're going + // to search those namespaces. + if (SearchNamespaces) { // Load any externally-known namespaces. if (ExternalSource && !LoadedExternalKnownNamespaces) { SmallVector ExternalKnownNamespaces; @@ -3948,7 +3955,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, break; // Only perform the qualified lookups for C++ - if (getLangOpts().CPlusPlus) { + if (SearchNamespaces) { TmpRes.suppressDiagnostics(); for (llvm::SmallVector::iterator QRI = QualifiedResults.begin(), diff --git a/test/FixIt/typo-crash.cpp b/test/FixIt/typo-crash.cpp index 92d20377e8..2e6f34a2a0 100644 --- a/test/FixIt/typo-crash.cpp +++ b/test/FixIt/typo-crash.cpp @@ -10,3 +10,20 @@ template void template_id1() { // expected-note {{'template_id1' dec // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} \ // expected-error {{use of undeclared identifier 't'}} } + +// FIXME: It would be nice if we could get this correction right. +namespace PR12297 { + namespace A { + typedef short T; + + namespace B { + typedef short T; + + T global(); + } + } + + using namespace A::B; + + T A::global(); // expected-error{{out-of-line definition of 'global' does not match any declaration in namespace 'PR12297::A'}} +} -- 2.40.0