summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-12-08 02:01:17 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-12-08 02:01:17 +0000
commit593f993a68550aff3b668c97a62447ee146d509b (patch)
treecc5435f6ef285e7c6abcf4f9b3515346034980a1 /clang/lib/Sema
parent1536e3b2c39a927337d4647ae2c3cd7103bb2772 (diff)
downloadbcm5719-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.cpp68
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;
OpenPOWER on IntegriCloud