]> granicus.if.org Git - clang/commitdiff
When diagnosing an invalid out-of-line redeclaration, don't permit
authorDouglas Gregor <dgregor@apple.com>
Mon, 26 Mar 2012 16:54:18 +0000 (16:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 26 Mar 2012 16:54:18 +0000 (16:54 +0000)
typo correction to introduce a nested-name-specifier; we aren't
prepared to handle it here. Fixes PR12297 / <rdar://problem/11075219>.

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

include/clang/Sema/TypoCorrection.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaLookup.cpp
test/FixIt/typo-crash.cpp

index a8f6e1178b72e67d2613510e4ae366d337333a8f..a333c8182b0c8e66c63ff65ea12ef6ec19518580 100644 (file)
@@ -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
index e92b3e4acab7f2982f3425e594c7fef2b716d687..d4159bf1895e6340cad179655b0abbd9974027d2 100644 (file)
@@ -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)
index e47bc1c8b1254a0f7f41908ba4a035296040c5c6..ed5a8da61c3d44c635d0b5afdea8dbd80cca1086 100644 (file)
@@ -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<NamespaceDecl *, 4> 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<TypoCorrection,
                              16>::iterator QRI = QualifiedResults.begin(),
index 92d20377e88686a54f980289bba9a44b6f5e2ae1..2e6f34a2a0a2b72895b6d789b360ec9bc540a7b9 100644 (file)
@@ -10,3 +10,20 @@ template<typename T> 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'}}
+}