diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 68 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 | 
5 files changed, 78 insertions, 6 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 9f9a1b98ce2..35bc993f73f 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1921,6 +1921,8 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,      ToData.HasMutableFields = FromData.HasMutableFields;      ToData.HasOnlyCMembers = FromData.HasOnlyCMembers;      ToData.HasInClassInitializer = FromData.HasInClassInitializer; +    ToData.HasUninitializedReferenceMember +      = FromData.HasUninitializedReferenceMember;      ToData.HasTrivialSpecialMembers = FromData.HasTrivialSpecialMembers;      ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;      ToData.HasConstexprNonCopyMoveConstructor diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 210dcb6d338..d3a0c1ad4c4 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -41,7 +41,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)      Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),      HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),      HasMutableFields(false), HasOnlyCMembers(true), -    HasInClassInitializer(false), +    HasInClassInitializer(false), HasUninitializedReferenceMember(false),      HasTrivialSpecialMembers(SMF_All),      HasIrrelevantDestructor(true),      HasConstexprNonCopyMoveConstructor(false), @@ -295,6 +295,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,      // Keep track of the presence of mutable fields.      if (BaseClassDecl->hasMutableFields())        data().HasMutableFields = true; + +    if (BaseClassDecl->hasUninitializedReferenceMember()) +      data().HasUninitializedReferenceMember = true;    }    if (VBases.empty()) @@ -727,7 +730,8 @@ void CXXRecordDecl::addedMember(Decl *D) {        data().PlainOldData = false;      if (T->isReferenceType()) { -      data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor; +      if (!Field->hasInClassInitializer()) +        data().HasUninitializedReferenceMember = true;        // C++0x [class]p7:        //   A standard-layout class is a class that: @@ -866,6 +870,10 @@ void CXXRecordDecl::addedMember(Decl *D) {          //   parameter is of type 'const M&', 'const volatile M&' or 'M'.          if (!FieldRec->hasCopyAssignmentWithConstParam())            data().ImplicitCopyAssignmentHasConstParam = false; + +        if (FieldRec->hasUninitializedReferenceMember() && +            !Field->hasInClassInitializer()) +          data().HasUninitializedReferenceMember = true;        }      } else {        // Base element type of field is a non-class type. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 48b0d1f8965..dcfd18b1223 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3623,6 +3623,22 @@ static void TryValueInitialization(Sema &S,        if (NeedZeroInitialization)          Sequence.AddZeroInitializationStep(Entity.getType()); +      // C++03: +      // -- if T is a non-union class type without a user-declared constructor, +      //    then every non-static data member and base class component of T is +      //    value-initialized; +      // [...] A program that calls for [...] value-initialization of an +      // entity of reference type is ill-formed. +      // +      // C++11 doesn't need this handling, because value-initialization does not +      // occur recursively there, and the implicit default constructor is +      // defined as deleted in the problematic cases. +      if (!S.getLangOpts().CPlusPlus0x && +          ClassDecl->hasUninitializedReferenceMember()) { +        Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); +        return; +      } +        // If this is list-value-initialization, pass the empty init list on when        // building the constructor call. This affects the semantics of a few        // things (such as whether an explicit default constructor can be called). @@ -5443,6 +5459,43 @@ InitializationSequence::Perform(Sema &S,    return CurInit;  } +/// Somewhere within T there is an uninitialized reference subobject. +/// Dig it out and diagnose it. +bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, QualType T) { +  if (T->isReferenceType()) { +    S.Diag(Loc, diag::err_reference_without_init) +      << T.getNonReferenceType(); +    return true; +  } + +  CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); +  if (!RD || !RD->hasUninitializedReferenceMember()) +    return false; + +  for (CXXRecordDecl::field_iterator FI = RD->field_begin(), +                                     FE = RD->field_end(); FI != FE; ++FI) { +    if (FI->isUnnamedBitfield()) +      continue; + +    if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) { +      S.Diag(Loc, diag::note_value_initialization_here) << RD; +      return true; +    } +  } + +  for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), +                                          BE = RD->bases_end(); +       BI != BE; ++BI) { +    if (DiagnoseUninitializedReference(S, BI->getLocStart(), BI->getType())) { +      S.Diag(Loc, diag::note_value_initialization_here) << RD; +      return true; +    } +  } + +  return false; +} + +  //===----------------------------------------------------------------------===//  // Diagnose initialization failures  //===----------------------------------------------------------------------===// @@ -5457,10 +5510,17 @@ bool InitializationSequence::Diagnose(Sema &S,    switch (Failure) {    case FK_TooManyInitsForReference:      // FIXME: Customize for the initialized entity? -    if (NumArgs == 0) -      S.Diag(Kind.getLocation(), diag::err_reference_without_init) -        << DestType.getNonReferenceType(); -    else  // FIXME: diagnostic below could be better! +    if (NumArgs == 0) { +      // Dig out the reference subobject which is uninitialized and diagnose it. +      // If this is value-initialization, this could be nested some way within +      // the target type. +      assert(Kind.getKind() == InitializationKind::IK_Value || +             DestType->isReferenceType()); +      bool Diagnosed = +        DiagnoseUninitializedReference(S, Kind.getLocation(), DestType); +      assert(Diagnosed && "couldn't find uninitialized reference to diagnose"); +      (void)Diagnosed; +    } else  // FIXME: diagnostic below could be better!        S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)          << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());      break; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d201f539fab..8c1058e396a 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1099,6 +1099,7 @@ void ASTDeclReader::ReadCXXDefinitionData(    Data.HasMutableFields = Record[Idx++];    Data.HasOnlyCMembers = Record[Idx++];    Data.HasInClassInitializer = Record[Idx++]; +  Data.HasUninitializedReferenceMember = Record[Idx++];    Data.HasTrivialSpecialMembers = Record[Idx++];    Data.HasIrrelevantDestructor = Record[Idx++];    Data.HasConstexprNonCopyMoveConstructor = Record[Idx++]; diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b6f798921d3..f89ae2ef128 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4588,6 +4588,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec    Record.push_back(Data.HasMutableFields);    Record.push_back(Data.HasOnlyCMembers);    Record.push_back(Data.HasInClassInitializer); +  Record.push_back(Data.HasUninitializedReferenceMember);    Record.push_back(Data.HasTrivialSpecialMembers);    Record.push_back(Data.HasIrrelevantDestructor);    Record.push_back(Data.HasConstexprNonCopyMoveConstructor);  | 

