[cfe-commits] r92355 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/FixIt/typo.cpp

Douglas Gregor dgregor at apple.com
Thu Dec 31 01:10:25 PST 2009


Author: dgregor
Date: Thu Dec 31 03:10:24 2009
New Revision: 92355

URL: http://llvm.org/viewvc/llvm-project?rev=92355&view=rev
Log:
Typo correction for C++ base and member initializers, e.g.,

test/FixIt/typo.cpp:41:15: error: initializer 'base' does not name a non-static
      data member or base class; did you mean the base class 'Base'?
  Derived() : base(),
              ^~~~
              Base
test/FixIt/typo.cpp:42:15: error: initializer 'ember' does not name a non-static
      data member or base class; did you mean the member 'member'?
              ember() { }
              ^~~~~
              member


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/FixIt/typo.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=92355&r1=92354&r2=92355&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Dec 31 03:10:24 2009
@@ -2560,6 +2560,9 @@
 def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
 def err_no_member_template_suggest : Error<
   "no template named %0 in %1; did you mean %2?">;
+def err_mem_init_not_member_or_class_suggest : Error<
+  "initializer %0 does not name a non-static data member or base "
+  "class; did you mean the %select{base class|member}1 %2?">;
 
 }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=92355&r1=92354&r2=92355&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Dec 31 03:10:24 2009
@@ -948,6 +948,51 @@
   return DeclPtrTy::make(Member);
 }
 
+/// \brief Find the direct and/or virtual base specifiers that
+/// correspond to the given base type, for use in base initialization
+/// within a constructor.
+static bool FindBaseInitializer(Sema &SemaRef, 
+                                CXXRecordDecl *ClassDecl,
+                                QualType BaseType,
+                                const CXXBaseSpecifier *&DirectBaseSpec,
+                                const CXXBaseSpecifier *&VirtualBaseSpec) {
+  // First, check for a direct base class.
+  DirectBaseSpec = 0;
+  for (CXXRecordDecl::base_class_const_iterator Base
+         = ClassDecl->bases_begin(); 
+       Base != ClassDecl->bases_end(); ++Base) {
+    if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
+      // We found a direct base of this type. That's what we're
+      // initializing.
+      DirectBaseSpec = &*Base;
+      break;
+    }
+  }
+
+  // Check for a virtual base class.
+  // FIXME: We might be able to short-circuit this if we know in advance that
+  // there are no virtual bases.
+  VirtualBaseSpec = 0;
+  if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
+    // We haven't found a base yet; search the class hierarchy for a
+    // virtual base class.
+    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                       /*DetectVirtual=*/false);
+    if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), 
+                              BaseType, Paths)) {
+      for (CXXBasePaths::paths_iterator Path = Paths.begin();
+           Path != Paths.end(); ++Path) {
+        if (Path->back().Base->isVirtual()) {
+          VirtualBaseSpec = Path->back().Base;
+          break;
+        }
+      }
+    }
+  }
+
+  return DirectBaseSpec || VirtualBaseSpec;
+}
+
 /// ActOnMemInitializer - Handle a C++ member initializer.
 Sema::MemInitResult
 Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
@@ -1015,9 +1060,46 @@
     if (!TyD) {
       if (R.isAmbiguous()) return true;
 
-      Diag(IdLoc, diag::err_mem_init_not_member_or_class)
-        << MemberOrBase << SourceRange(IdLoc, RParenLoc);
-      return true;
+      // If no results were found, try to correct typos.
+      if (R.empty() && 
+          CorrectTypo(R, S, &SS, ClassDecl) && R.isSingleResult()) {
+        if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {
+          if (Member->getDeclContext()->getLookupContext()->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 << R.getLookupName()
+              << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                               R.getLookupName().getAsString());
+
+            return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,
+                                          LParenLoc, RParenLoc);
+          }
+        } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {
+          const CXXBaseSpecifier *DirectBaseSpec;
+          const CXXBaseSpecifier *VirtualBaseSpec;
+          if (FindBaseInitializer(*this, ClassDecl, 
+                                  Context.getTypeDeclType(Type),
+                                  DirectBaseSpec, VirtualBaseSpec)) {
+            // We have found a direct or virtual base class with a
+            // similar name to what was typed; complain and initialize
+            // that base class.
+            Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)
+              << MemberOrBase << false << R.getLookupName()
+              << CodeModificationHint::CreateReplacement(R.getNameLoc(),
+                                               R.getLookupName().getAsString());
+            
+            TyD = Type;
+          }
+        }
+      }
+
+      if (!TyD) {
+        Diag(IdLoc, diag::err_mem_init_not_member_or_class)
+          << MemberOrBase << SourceRange(IdLoc, RParenLoc);
+        return true;
+      }
     }
 
     BaseType = Context.getTypeDeclType(TyD);
@@ -1193,37 +1275,11 @@
     //   mem-initializer-list can initialize a base class using any
     //   name that denotes that base class type.
 
-    // First, check for a direct base class.
+    // Check for direct and virtual base classes.
     const CXXBaseSpecifier *DirectBaseSpec = 0;
-    for (CXXRecordDecl::base_class_const_iterator Base =
-         ClassDecl->bases_begin(); Base != ClassDecl->bases_end(); ++Base) {
-      if (Context.hasSameUnqualifiedType(BaseType, Base->getType())) {
-        // We found a direct base of this type. That's what we're
-        // initializing.
-        DirectBaseSpec = &*Base;
-        break;
-      }
-    }
-
-    // Check for a virtual base class.
-    // FIXME: We might be able to short-circuit this if we know in advance that
-    // there are no virtual bases.
     const CXXBaseSpecifier *VirtualBaseSpec = 0;
-    if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
-      // We haven't found a base yet; search the class hierarchy for a
-      // virtual base class.
-      CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
-                         /*DetectVirtual=*/false);
-      if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) {
-        for (CXXBasePaths::paths_iterator Path = Paths.begin();
-             Path != Paths.end(); ++Path) {
-          if (Path->back().Base->isVirtual()) {
-            VirtualBaseSpec = Path->back().Base;
-            break;
-          }
-        }
-      }
-    }
+    FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, 
+                        VirtualBaseSpec);
 
     // C++ [base.class.init]p2:
     //   If a mem-initializer-id is ambiguous because it designates both

Modified: cfe/trunk/test/FixIt/typo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=92355&r1=92354&r2=92355&view=diff

==============================================================================
--- cfe/trunk/test/FixIt/typo.cpp (original)
+++ cfe/trunk/test/FixIt/typo.cpp Thu Dec 31 03:10:24 2009
@@ -33,3 +33,11 @@
   return s.fnd("hello") // expected-error{{no member named 'fnd' in 'class std::basic_string<char>'; did you mean 'find'?}}
     == std::string::pos; // expected-error{{no member named 'pos' in 'class std::basic_string<char>'; did you mean 'npos'?}}
 }
+
+struct Base { };
+struct Derived : public Base {
+  int member;
+
+  Derived() : base(), // expected-error{{initializer 'base' does not name a non-static data member or base class; did you mean the base class 'Base'?}}
+              ember() { } // expected-error{{initializer 'ember' does not name a non-static data member or base class; did you mean the member 'member'?}}
+};





More information about the cfe-commits mailing list