diff options
| author | Douglas Gregor <dgregor@apple.com> | 2008-11-05 04:29:56 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2008-11-05 04:29:56 +0000 | 
| commit | e8381c00eb6c753c6100b968d16c829933e743e2 (patch) | |
| tree | 1fed91840bcb8c2d5cb5083c5f01a945c6536145 /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | f14b77ebf12ee2e1bc21145c3947dd30c9d2b988 (diff) | |
| download | bcm5719-llvm-e8381c00eb6c753c6100b968d16c829933e743e2.tar.gz bcm5719-llvm-e8381c00eb6c753c6100b968d16c829933e743e2.zip | |
Initial implementation of parsing, semantic analysis, and AST-building
for constructor initializations, e.g.,
  class A { };
  class B : public A { 
    int m;
  public:
    B() : A(), m(17) { };
  };
llvm-svn: 58749
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 106 | 
1 files changed, 106 insertions, 0 deletions
| diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e4321f53ff0..95d17fa327b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -12,6 +12,7 @@  //===----------------------------------------------------------------------===//  #include "Sema.h" +#include "SemaInherit.h"  #include "clang/AST/ASTConsumer.h"  #include "clang/AST/ASTContext.h"  #include "clang/AST/TypeOrdering.h" @@ -543,6 +544,111 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,    return Member;  } +/// ActOnMemInitializer - Handle a C++ member initializer. +Sema::MemInitResult  +Sema::ActOnMemInitializer(DeclTy *ConstructorD, +                          Scope *S, +                          IdentifierInfo *MemberOrBase, +                          SourceLocation IdLoc, +                          SourceLocation LParenLoc, +                          ExprTy **Args, unsigned NumArgs, +                          SourceLocation *CommaLocs, +                          SourceLocation RParenLoc) { +  CXXConstructorDecl *Constructor  +    = dyn_cast<CXXConstructorDecl>((Decl*)ConstructorD); +  if (!Constructor) { +    // The user wrote a constructor initializer on a function that is +    // not a C++ constructor. Ignore the error for now, because we may +    // have more member initializers coming; we'll diagnose it just +    // once in ActOnMemInitializers. +    return true; +  } + +  CXXRecordDecl *ClassDecl = Constructor->getParent(); + +  // C++ [class.base.init]p2: +  //   Names in a mem-initializer-id are looked up in the scope of the +  //   constructor’s class and, if not found in that scope, are looked +  //   up in the scope containing the constructor’s +  //   definition. [Note: if the constructor’s class contains a member +  //   with the same name as a direct or virtual base class of the +  //   class, a mem-initializer-id naming the member or base class and +  //   composed of a single identifier refers to the class member. A +  //   mem-initializer-id for the hidden base class may be specified +  //   using a qualified name. ] +  // Look for a member, first. +  CXXFieldDecl *Member = ClassDecl->getMember(MemberOrBase); + +  // FIXME: Handle members of an anonymous union. + +  if (Member) { +    // FIXME: Perform direct initialization of the member. +    return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs); +  } + +  // It didn't name a member, so see if it names a class. +  TypeTy *BaseTy = isTypeName(*MemberOrBase, S); +  if (!BaseTy) +    return Diag(IdLoc, diag::err_mem_init_not_member_or_class, +                MemberOrBase->getName(), SourceRange(IdLoc, RParenLoc)); +   +  QualType BaseType = Context.getTypeDeclType((TypeDecl *)BaseTy); +  if (!BaseType->isRecordType()) +    return Diag(IdLoc, diag::err_base_init_does_not_name_class, +                BaseType.getAsString(), SourceRange(IdLoc, RParenLoc)); + +  // C++ [class.base.init]p2: +  //   [...] Unless the mem-initializer-id names a nonstatic data +  //   member of the constructor’s class or a direct or virtual base +  //   of that class, the mem-initializer is ill-formed. A +  //   mem-initializer-list can initialize a base class using any +  //   name that denotes that base class type. +   +  // First, check for a direct base class. +  const CXXBaseSpecifier *DirectBaseSpec = 0; +  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); +       Base != ClassDecl->bases_end(); ++Base) { +    if (Context.getCanonicalType(BaseType).getUnqualifiedType() ==  +        Context.getCanonicalType(Base->getType()).getUnqualifiedType()) { +      // 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. +    BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, +                    /*DetectVirtual=*/false); +    if (IsDerivedFrom(Context.getTypeDeclType(ClassDecl), BaseType, Paths)) { +      for (BasePaths::paths_iterator Path = Paths.begin();  +           Path != Paths.end(); ++Path) { +        if (Path->back().Base->isVirtual()) { +          VirtualBaseSpec = Path->back().Base; +          break; +        } +      } +    } +  } + +  // C++ [base.class.init]p2: +  //   If a mem-initializer-id is ambiguous because it designates both +  //   a direct non-virtual base class and an inherited virtual base +  //   class, the mem-initializer is ill-formed. +  if (DirectBaseSpec && VirtualBaseSpec) +    return Diag(IdLoc, diag::err_base_init_direct_and_virtual, +                MemberOrBase->getName(), SourceRange(IdLoc, RParenLoc)); + +  return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs); +} + +  void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,                                               DeclTy *TagDecl,                                               SourceLocation LBrac, | 

