[cfe-commits] r147962 - in /cfe/trunk: include/clang/Sema/Sema.h include/clang/Sema/TypoCorrection.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp test/SemaCXX/typo-correction.cpp

Kaelyn Uhrain rikka at google.com
Wed Jan 11 11:37:47 PST 2012


Author: rikka
Date: Wed Jan 11 13:37:46 2012
New Revision: 147962

URL: http://llvm.org/viewvc/llvm-project?rev=147962&view=rev
Log:
Add initial callback object support to Sema::CorrectTypo.

Also includes two examples of the callback: a wrapper/replacement for
the CorrectTypoContext enum, and a conversion of the two calls to
CorrectTypo in SemaDeclCXX.cpp (one of which provides verifiable
improvement to the typo correction, as demonstrated in the added test).

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/TypoCorrection.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/SemaCXX/typo-correction.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=147962&r1=147961&r2=147962&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan 11 13:37:46 2012
@@ -1835,10 +1835,18 @@
   TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
                              Sema::LookupNameKind LookupKind,
                              Scope *S, CXXScopeSpec *SS,
-                             DeclContext *MemberContext = NULL,
+                             DeclContext *MemberContext = 0,
                              bool EnteringContext = false,
                              CorrectTypoContext CTC = CTC_Unknown,
-                             const ObjCObjectPointerType *OPT = NULL);
+                             const ObjCObjectPointerType *OPT = 0);
+
+  TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+                             Sema::LookupNameKind LookupKind,
+                             Scope *S, CXXScopeSpec *SS,
+                             CorrectionCandidateCallback *CCC,
+                             DeclContext *MemberContext = 0,
+                             bool EnteringContext = false,
+                             const ObjCObjectPointerType *OPT = 0);
 
   void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
                                    AssociatedNamespaceSet &AssociatedNamespaces,

Modified: cfe/trunk/include/clang/Sema/TypoCorrection.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=147962&r1=147961&r2=147962&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/TypoCorrection.h (original)
+++ cfe/trunk/include/clang/Sema/TypoCorrection.h Wed Jan 11 13:37:46 2012
@@ -135,6 +135,32 @@
   unsigned EditDistance;
 };
 
+// @brief Base class for callback objects used by Sema::CorrectTypo to check the
+// validity of a potential typo correction.
+class CorrectionCandidateCallback {
+ public:
+  CorrectionCandidateCallback()
+      : WantTypeSpecifiers(true), WantExpressionKeywords(true),
+        WantCXXNamedCasts(true), WantRemainingKeywords(true),
+        WantObjCSuper(false),
+        IsObjCIvarLookup(false) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    return true;
+  }
+
+  // Flags for context-dependent keywords.
+  // TODO: Expand these to apply to non-keywords or possibly remove them.
+  bool WantTypeSpecifiers;
+  bool WantExpressionKeywords;
+  bool WantCXXNamedCasts;
+  bool WantRemainingKeywords;
+  bool WantObjCSuper;
+  // Temporary hack for the one case where a CorrectTypoContext enum is used
+  // when looking up results.
+  bool IsObjCIvarLookup;
+};
+
 }
 
 #endif

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=147962&r1=147961&r2=147962&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Jan 11 13:37:46 2012
@@ -1745,6 +1745,30 @@
                              EllipsisLoc);
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are namespaces.
+class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
+      : ClassDecl(ClassDecl) {}
+
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
+        return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
+      else
+        return isa<TypeDecl>(ND);
+    }
+    return false;
+  }
+
+ private:
+  CXXRecordDecl *ClassDecl;
+};
+
+}
+
 /// \brief Handle a C++ member initializer.
 MemInitResult
 Sema::BuildMemInitializer(Decl *ConstructorD,
@@ -1837,24 +1861,23 @@
 
       // If no results were found, try to correct typos.
       TypoCorrection Corr;
+      MemInitializerValidatorCCC Validator(ClassDecl);
       if (R.empty() && BaseType.isNull() &&
           (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
-                              ClassDecl, false, CTC_NoKeywords))) {
+                              &Validator, ClassDecl))) {
         std::string CorrectedStr(Corr.getAsString(getLangOptions()));
         std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions()));
         if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
-          if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {
-            // We have found a non-static data member with a similar
-            // name to what was typed; complain and initialize that
-            // member.
-            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
-              << MemberOrBase << true << CorrectedQuotedStr
-              << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
-            Diag(Member->getLocation(), diag::note_previous_decl)
-              << CorrectedQuotedStr;
+          // We have found a non-static data member with a similar
+          // name to what was typed; complain and initialize that
+          // member.
+          Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+            << MemberOrBase << true << CorrectedQuotedStr
+            << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
+          Diag(Member->getLocation(), diag::note_previous_decl)
+            << CorrectedQuotedStr;
 
-            return BuildMemberInitializer(Member, Args, IdLoc);
-          }
+          return BuildMemberInitializer(Member, Args, IdLoc);
         } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
           const CXXBaseSpecifier *DirectBaseSpec;
           const CXXBaseSpecifier *VirtualBaseSpec;
@@ -5750,35 +5773,47 @@
   }
 }
 
+namespace {
+
+// Callback to only accept typo corrections that are namespaces.
+class NamespaceValidatorCCC : public CorrectionCandidateCallback {
+ public:
+  virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
+      return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
+    }
+    return false;
+  }
+};
+
+}
+
 static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
                                        CXXScopeSpec &SS,
                                        SourceLocation IdentLoc,
                                        IdentifierInfo *Ident) {
+  NamespaceValidatorCCC Validator;
   R.clear();
   if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),
-                                               R.getLookupKind(), Sc, &SS, NULL,
-                                               false, S.CTC_NoKeywords, NULL)) {
-    if (Corrected.getCorrectionDeclAs<NamespaceDecl>() ||
-        Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) {
-      std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));
-      std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));
-      if (DeclContext *DC = S.computeDeclContext(SS, false))
-        S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
-          << Ident << DC << CorrectedQuotedStr << SS.getRange()
-          << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
-      else
-        S.Diag(IdentLoc, diag::err_using_directive_suggest)
-          << Ident << CorrectedQuotedStr
-          << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+                                               R.getLookupKind(), Sc, &SS,
+                                               &Validator)) {
+    std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));
+    std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));
+    if (DeclContext *DC = S.computeDeclContext(SS, false))
+      S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
+        << Ident << DC << CorrectedQuotedStr << SS.getRange()
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+    else
+      S.Diag(IdentLoc, diag::err_using_directive_suggest)
+        << Ident << CorrectedQuotedStr
+        << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
 
-      S.Diag(Corrected.getCorrectionDecl()->getLocation(),
-           diag::note_namespace_defined_here) << CorrectedQuotedStr;
+    S.Diag(Corrected.getCorrectionDecl()->getLocation(),
+         diag::note_namespace_defined_here) << CorrectedQuotedStr;
 
-      Ident = Corrected.getCorrectionAsIdentifierInfo();
-      R.addDecl(Corrected.getCorrectionDecl());
-      return true;
-    }
-    R.setLookupName(Ident);
+    Ident = Corrected.getCorrectionAsIdentifierInfo();
+    R.addDecl(Corrected.getCorrectionDecl());
+    return true;
   }
   return false;
 }

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=147962&r1=147961&r2=147962&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Jan 11 13:37:46 2012
@@ -3310,13 +3310,13 @@
                                       Scope *S, CXXScopeSpec *SS,
                                       DeclContext *MemberContext,
                                       bool EnteringContext,
-                                      Sema::CorrectTypoContext CTC) {
+                                      bool isObjCIvarLookup) {
   Res.suppressDiagnostics();
   Res.clear();
   Res.setLookupName(Name);
   if (MemberContext) {
     if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
-      if (CTC == Sema::CTC_ObjCIvarLookup) {
+      if (isObjCIvarLookup) {
         if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) {
           Res.addDecl(Ivar);
           Res.resolveKind();
@@ -3357,61 +3357,11 @@
 /// \brief Add keywords to the consumer as possible typo corrections.
 static void AddKeywordsToConsumer(Sema &SemaRef,
                                   TypoCorrectionConsumer &Consumer,
-                                  Scope *S, Sema::CorrectTypoContext CTC) {
-  // Add context-dependent keywords.
-  bool WantTypeSpecifiers = false;
-  bool WantExpressionKeywords = false;
-  bool WantCXXNamedCasts = false;
-  bool WantRemainingKeywords = false;
-  switch (CTC) {
-    case Sema::CTC_Unknown:
-      WantTypeSpecifiers = true;
-      WantExpressionKeywords = true;
-      WantCXXNamedCasts = true;
-      WantRemainingKeywords = true;
-
-      if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
-        if (Method->getClassInterface() &&
-            Method->getClassInterface()->getSuperClass())
-          Consumer.addKeywordResult("super");
+                                  Scope *S, CorrectionCandidateCallback &CCC) {
+  if (CCC.WantObjCSuper)
+    Consumer.addKeywordResult("super");
 
-      break;
-
-    case Sema::CTC_NoKeywords:
-      break;
-
-    case Sema::CTC_Type:
-      WantTypeSpecifiers = true;
-      break;
-
-    case Sema::CTC_ObjCMessageReceiver:
-      Consumer.addKeywordResult("super");
-      // Fall through to handle message receivers like expressions.
-
-    case Sema::CTC_Expression:
-      if (SemaRef.getLangOptions().CPlusPlus)
-        WantTypeSpecifiers = true;
-      WantExpressionKeywords = true;
-      // Fall through to get C++ named casts.
-
-    case Sema::CTC_CXXCasts:
-      WantCXXNamedCasts = true;
-      break;
-
-    case Sema::CTC_ObjCPropertyLookup:
-      // FIXME: Add "isa"?
-      break;
-
-    case Sema::CTC_MemberLookup:
-      if (SemaRef.getLangOptions().CPlusPlus)
-        Consumer.addKeywordResult("template");
-      break;
-
-    case Sema::CTC_ObjCIvarLookup:
-      break;
-  }
-
-  if (WantTypeSpecifiers) {
+  if (CCC.WantTypeSpecifiers) {
     // Add type-specifier keywords to the set of results.
     const char *CTypeSpecs[] = {
       "char", "const", "double", "enum", "float", "int", "long", "short",
@@ -3450,14 +3400,14 @@
       Consumer.addKeywordResult("typeof");
   }
 
-  if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
+  if (CCC.WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {
     Consumer.addKeywordResult("const_cast");
     Consumer.addKeywordResult("dynamic_cast");
     Consumer.addKeywordResult("reinterpret_cast");
     Consumer.addKeywordResult("static_cast");
   }
 
-  if (WantExpressionKeywords) {
+  if (CCC.WantExpressionKeywords) {
     Consumer.addKeywordResult("sizeof");
     if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) {
       Consumer.addKeywordResult("false");
@@ -3483,7 +3433,7 @@
     }
   }
 
-  if (WantRemainingKeywords) {
+  if (CCC.WantRemainingKeywords) {
     if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {
       // Statements.
       const char *CStmts[] = {
@@ -3533,6 +3483,77 @@
   }
 }
 
+namespace {
+
+// Simple CorrectionCandidateCallback class that sets the keyword flags based
+// on a given CorrectTypoContext, but does not perform any extra validation
+// of typo correction candidates.
+class CorrectTypoContextReplacementCCC : public CorrectionCandidateCallback {
+ public:
+  CorrectTypoContextReplacementCCC(
+      Sema &SemaRef, Sema::CorrectTypoContext CTC = Sema::CTC_Unknown) {
+    WantTypeSpecifiers = false;
+    WantExpressionKeywords = false;
+    WantCXXNamedCasts = false;
+    WantRemainingKeywords = false;
+    switch (CTC) {
+      case Sema::CTC_Unknown:
+        WantTypeSpecifiers = true;
+        WantExpressionKeywords = true;
+        WantCXXNamedCasts = true;
+        WantRemainingKeywords = true;
+        if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+          WantObjCSuper = Method->getClassInterface() &&
+                          Method->getClassInterface()->getSuperClass();
+        break;
+
+      case Sema::CTC_Type:
+        WantTypeSpecifiers = true;
+        break;
+
+      case Sema::CTC_ObjCMessageReceiver:
+        WantObjCSuper = true;
+        // Fall through to handle message receivers like expressions.
+
+      case Sema::CTC_Expression:
+        if (SemaRef.getLangOptions().CPlusPlus)
+          WantTypeSpecifiers = true;
+        WantExpressionKeywords = true;
+        // Fall through to get C++ named casts.
+
+      case Sema::CTC_CXXCasts:
+        WantCXXNamedCasts = true;
+        break;
+
+      case Sema::CTC_MemberLookup:
+      case Sema::CTC_NoKeywords:
+      case Sema::CTC_ObjCPropertyLookup:
+        break;
+
+      case Sema::CTC_ObjCIvarLookup:
+        IsObjCIvarLookup = true;
+        break;
+    }
+  }
+};
+
+}
+
+/// \brief Compatibility wrapper for call sites that pass a CorrectTypoContext
+/// value to CorrectTypo instead of providing a callback object.
+TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
+                                 Sema::LookupNameKind LookupKind,
+                                 Scope *S, CXXScopeSpec *SS,
+                                 DeclContext *MemberContext,
+                                 bool EnteringContext,
+                                 CorrectTypoContext CTC,
+                                 const ObjCObjectPointerType *OPT) {
+  CorrectTypoContextReplacementCCC CTCVerifier(*this, CTC);
+
+  return CorrectTypo(TypoName, LookupKind, S, SS, &CTCVerifier, MemberContext,
+                     EnteringContext, OPT);
+}
+
 /// \brief Try to "correct" a typo in the source code by finding
 /// visible declarations whose names are similar to the name that was
 /// present in the source code.
@@ -3547,15 +3568,16 @@
 /// \param SS the nested-name-specifier that precedes the name we're
 /// looking for, if present.
 ///
+/// \param CCC A CorrectionCandidateCallback object that provides further
+/// validation of typo correction candidates. It also provides flags for
+/// determining the set of keywords permitted.
+///
 /// \param MemberContext if non-NULL, the context in which to look for
 /// a member access expression.
 ///
 /// \param EnteringContext whether we're entering the context described by
 /// the nested-name-specifier SS.
 ///
-/// \param CTC The context in which typo correction occurs, which impacts the
-/// set of keywords permitted.
-///
 /// \param OPT when non-NULL, the search for visible declarations will
 /// also walk the protocols in the qualified interfaces of \p OPT.
 ///
@@ -3566,9 +3588,9 @@
 TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
                                  Sema::LookupNameKind LookupKind,
                                  Scope *S, CXXScopeSpec *SS,
+                                 CorrectionCandidateCallback *CCC,
                                  DeclContext *MemberContext,
                                  bool EnteringContext,
-                                 CorrectTypoContext CTC,
                                  const ObjCObjectPointerType *OPT) {
   if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)
     return TypoCorrection();
@@ -3665,7 +3687,8 @@
     }
   }
 
-  AddKeywordsToConsumer(*this, Consumer, S,  CTC);
+  CorrectTypoContextReplacementCCC DefaultCCC(*this);
+  AddKeywordsToConsumer(*this, Consumer, S, CCC ? *CCC : DefaultCCC);
 
   // If we haven't found anything, we're done.
   if (Consumer.empty()) {
@@ -3705,7 +3728,8 @@
       Namespaces.AddNamespace(KNI->first);
   }
 
-  // Weed out any names that could not be found by name lookup.
+  // Weed out any names that could not be found by name lookup or, if a
+  // CorrectionCandidateCallback object was provided, failed validation.
   llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults;
   LookupResult TmpRes(*this, TypoName, LookupKind);
   TmpRes.suppressDiagnostics();
@@ -3715,16 +3739,21 @@
     for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
                                               IEnd = DI->second->end();
          I != IEnd; /* Increment in loop. */) {
-      // If the item already has been looked up or is a keyword, keep it
+      // If the item already has been looked up or is a keyword, keep it.
+      // If a validator callback object was given, drop the correction
+      // unless it passes validation.
       if (I->second.isResolved()) {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         continue;
       }
 
       // Perform name lookup on this name.
       IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();
       LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
-                                EnteringContext, CTC);
+                                EnteringContext, CCC && CCC->IsObjCIvarLookup);
 
       switch (TmpRes.getResultKind()) {
       case LookupResult::NotFound:
@@ -3746,20 +3775,28 @@
         return TypoCorrection();
 
       case LookupResult::FoundOverloaded: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         // Store all of the Decls for overloaded symbols
         for (LookupResult::iterator TRD = TmpRes.begin(),
                                  TRDEnd = TmpRes.end();
              TRD != TRDEnd; ++TRD)
           I->second.addCorrectionDecl(*TRD);
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         break;
       }
 
-      case LookupResult::Found:
+      case LookupResult::Found: {
+        TypoCorrectionConsumer::result_iterator Prev = I;
         I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
         ++I;
+        if (CCC && !CCC->ValidateCandidate(Prev->second))
+          DI->second->erase(Prev);
         break;
       }
+
+      }
     }
 
     if (DI->second->empty())
@@ -3790,6 +3827,8 @@
           TmpRes.setLookupName(*QRI);
           if (!LookupQualifiedName(TmpRes, Ctx)) continue;
 
+          // Any corrections added below will be validated in subsequent
+          // iterations of the main while() loop over the Consumer's contents.
           switch (TmpRes.getResultKind()) {
           case LookupResult::Found:
             Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),
@@ -3863,7 +3902,12 @@
 
     return Result;
   }
-  else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver
+  else if (BestResults.size() > 1
+           // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver;
+           // WantObjCSuper is only true for CTC_ObjCMessageReceiver and for
+           // some instances of CTC_Unknown, while WantRemainingKeywords is true
+           // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
+           && CCC && CCC->WantObjCSuper && !CCC->WantRemainingKeywords
            && BestResults["super"].isKeyword()) {
     // Prefer 'super' when we're completing in a message-receiver
     // context.

Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=147962&r1=147961&r2=147962&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)
+++ cfe/trunk/test/SemaCXX/typo-correction.cpp Wed Jan 11 13:37:46 2012
@@ -29,3 +29,14 @@
 inline error_condition make_error_condition(errc _e) {
   return error_condition(static_cast<int>(_e));
 }
+
+
+// Prior to the introduction of a callback object to further filter possible
+// typo corrections, this example would not trigger a suggestion as "base_type"
+// is a closer match to "basetype" than is "BaseType" but "base_type" does not
+// refer to a base class or non-static data member.
+struct BaseType { };
+struct Derived : public BaseType { // expected-note {{base class 'BaseType' specified here}}
+  static int base_type;
+  Derived() : basetype() {} // expected-error{{initializer 'basetype' does not name a non-static data member or base class; did you mean the base class 'BaseType'?}}
+};





More information about the cfe-commits mailing list