diff options
| author | Douglas Gregor <dgregor@apple.com> | 2008-11-03 20:45:27 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2008-11-03 20:45:27 +0000 | 
| commit | c28b57d70346c1844ef8d7ba233c5c1f94ab6677 (patch) | |
| tree | 5a53a083d2ab170421f13d569c9728e911beddb4 /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | 6692dec2a0ff6ad5618d8aa49f0c6fab846d6ad1 (diff) | |
| download | bcm5719-llvm-c28b57d70346c1844ef8d7ba233c5c1f94ab6677.tar.gz bcm5719-llvm-c28b57d70346c1844ef8d7ba233c5c1f94ab6677.zip | |
Implicit support for direct initialization of objects of class type, e.g.,
  X x(5, 7);
llvm-svn: 58641
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 84 | 
1 files changed, 78 insertions, 6 deletions
| diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 1100e700c93..9c1e4a949fa 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -848,14 +848,21 @@ void Sema::AddCXXDirectInitializerToDecl(DeclTy *Dcl, SourceLocation LParenLoc,    // The form of initialization (using parentheses or '=') is generally    // insignificant, but does matter when the entity being initialized has a    // class type. +  QualType DeclInitType = VDecl->getType(); +  if (const ArrayType *Array = Context.getAsArrayType(DeclInitType)) +    DeclInitType = Array->getElementType();    if (VDecl->getType()->isRecordType()) { -    // FIXME: When constructors for class types are supported, determine how  -    // exactly semantic checking will be done for direct initializers. -    unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, -                           "initialization for class types is not handled yet"); -    Diag(VDecl->getLocation(), DiagID); -    RealDecl->setInvalidDecl(); +    CXXConstructorDecl *Constructor +      = PerformDirectInitForClassType(DeclInitType, (Expr **)ExprTys, NumExprs, +                                      VDecl->getLocation(), +                                      SourceRange(VDecl->getLocation(), +                                                  RParenLoc), +                                      VDecl->getName(), +                                      /*HasInitializer=*/true); +    if (!Constructor) { +      RealDecl->setInvalidDecl(); +    }      return;    } @@ -874,6 +881,71 @@ void Sema::AddCXXDirectInitializerToDecl(DeclTy *Dcl, SourceLocation LParenLoc,    AddInitializerToDecl(Dcl, ExprTys[0]);  } +/// PerformDirectInitForClassType - Perform direct-initialization (C++ +/// [dcl.init]) for a value of the given class type with the given set +/// of arguments (@p Args). @p Loc is the location in the source code +/// where the initializer occurs (e.g., a declaration, member +/// initializer, functional cast, etc.) while @p Range covers the +/// whole initialization. @p HasInitializer is true if the initializer +/// was actually written in the source code. When successful, returns +/// the constructor that will be used to perform the initialization; +/// when the initialization fails, emits a diagnostic and returns null. +CXXConstructorDecl * +Sema::PerformDirectInitForClassType(QualType ClassType, +                                    Expr **Args, unsigned NumArgs, +                                    SourceLocation Loc, SourceRange Range, +                                    std::string InitEntity, +                                    bool HasInitializer) { +  const RecordType *ClassRec = ClassType->getAsRecordType(); +  assert(ClassRec && "Can only initialize a class type here"); + +  // C++ [dcl.init]p14:  +  // +  //   If the initialization is direct-initialization, or if it is +  //   copy-initialization where the cv-unqualified version of the +  //   source type is the same class as, or a derived class of, the +  //   class of the destination, constructors are considered. The +  //   applicable constructors are enumerated (13.3.1.3), and the +  //   best one is chosen through overload resolution (13.3). The +  //   constructor so selected is called to initialize the object, +  //   with the initializer expression(s) as its argument(s). If no +  //   constructor applies, or the overload resolution is ambiguous, +  //   the initialization is ill-formed. +  // +  // FIXME: We don't check cv-qualifiers on the class type, because we +  // don't yet keep track of whether a class type is a POD class type +  // (or a "trivial" class type, as is used in C++0x). +  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl()); +  OverloadCandidateSet CandidateSet; +  OverloadCandidateSet::iterator Best; +  AddOverloadCandidates(ClassDecl->getConstructors(), Args, NumArgs, +                        CandidateSet); +  switch (BestViableFunction(CandidateSet, Best)) { +  case OR_Success: +    // We found a constructor. Return it. +    return cast<CXXConstructorDecl>(Best->Function); +     +  case OR_No_Viable_Function: +    if (CandidateSet.empty()) +      Diag(Loc, diag::err_ovl_no_viable_function_in_init,  +           InitEntity, Range); +    else { +      Diag(Loc, diag::err_ovl_no_viable_function_in_init_with_cands,  +           InitEntity, Range); +      PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); +    } +    return 0; +     +  case OR_Ambiguous: +    Diag(Loc, diag::err_ovl_ambiguous_init,  +         InitEntity, Range); +    PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); +    return 0; +  } +   +  return 0; +} +  /// CompareReferenceRelationship - Compare the two types T1 and T2 to  /// determine whether they are reference-related,  /// reference-compatible, reference-compatible with added | 

