diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-12-08 02:01:17 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-12-08 02:01:17 +0000 |
| commit | 593f993a68550aff3b668c97a62447ee146d509b (patch) | |
| tree | cc5435f6ef285e7c6abcf4f9b3515346034980a1 /clang/lib/Sema | |
| parent | 1536e3b2c39a927337d4647ae2c3cd7103bb2772 (diff) | |
| download | bcm5719-llvm-593f993a68550aff3b668c97a62447ee146d509b.tar.gz bcm5719-llvm-593f993a68550aff3b668c97a62447ee146d509b.zip | |
Implement C++03 [dcl.init]p5's checking for value-initialization of references
properly, rather than faking it up by pretending that a reference member makes
the default constructor non-trivial. That leads to rejects-valids when putting
such types inside unions.
llvm-svn: 169662
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 68 |
1 files changed, 64 insertions, 4 deletions
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; |

