diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-12-31 09:10:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-12-31 09:10:24 +0000 |
commit | fe0241e31dd2d1af60116adf6f71dedc88cd1f68 (patch) | |
tree | 201d63613f158ed755de0c7a76ae0c4351b00775 /lib | |
parent | 6c409a031946c069b7f8c33e7d71175563028afb (diff) |
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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92355 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 120 |
1 files changed, 88 insertions, 32 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f1474cd979..f8321132ff 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -948,6 +948,51 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, 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 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, 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 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // 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 |