diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-03-08 02:45:10 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-03-08 02:45:10 +0000 |
commit | 589973b097996bffb4f7d56af189f93c9d37b60a (patch) | |
tree | 4aaccbd2faa6f170256f892ea303946d559ff84a | |
parent | 104ee00181f90735eaa945ac628d594e483edbcc (diff) | |
download | llvm-589973b097996bffb4f7d56af189f93c9d37b60a.tar.gz |
In C++98/03, an uninitialized variable that has POD class type will be
uninitialized. This seems not to be the case in C++0x, where we still
call the (trivial) default constructor for a POD class
(!). Previously, we had implemented only the C++0x rules; now we
implement both. Fixes PR6536.
llvm-svn: 97928
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 | ||||
-rw-r--r-- | clang/test/CXX/dcl.decl/dcl.init/p6.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/internal-linkage.cpp | 6 | ||||
-rw-r--r-- | clang/test/SemaCXX/statements.cpp | 5 |
4 files changed, 39 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 935adcf1b650..82dcd60aa069 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3809,24 +3809,38 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, return; } - InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); - InitializationKind Kind - = InitializationKind::CreateDefault(Var->getLocation()); + const RecordType *Record + = Context.getBaseElementType(Type)->getAs<RecordType>(); + if (Record && getLangOptions().CPlusPlus && !getLangOptions().CPlusPlus0x && + cast<CXXRecordDecl>(Record->getDecl())->isPOD()) { + // C++03 [dcl.init]p9: + // If no initializer is specified for an object, and the + // object is of (possibly cv-qualified) non-POD class type (or + // array thereof), the object shall be default-initialized; if + // the object is of const-qualified type, the underlying class + // type shall have a user-declared default + // constructor. Otherwise, if no initializer is specified for + // a non- static object, the object and its subobjects, if + // any, have an indeterminate initial value); if the object + // or any of its subobjects are of const-qualified type, the + // program is ill-formed. + // FIXME: DPG thinks it is very fishy that C++0x disables this. + } else { + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); - InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); - if (Init.isInvalid()) - Var->setInvalidDecl(); - else { - if (Init.get()) + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else if (Init.get()) Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - - if (getLangOptions().CPlusPlus) - if (const RecordType *Record - = Context.getBaseElementType(Type)->getAs<RecordType>()) - FinalizeVarWithDestructor(Var, Record); } + + if (!Var->isInvalidDecl() && getLangOptions().CPlusPlus && Record) + FinalizeVarWithDestructor(Var, Record); } } diff --git a/clang/test/CXX/dcl.decl/dcl.init/p6.cpp b/clang/test/CXX/dcl.decl/dcl.init/p6.cpp index f627a199eca6..df5dcfe97a74 100644 --- a/clang/test/CXX/dcl.decl/dcl.init/p6.cpp +++ b/clang/test/CXX/dcl.decl/dcl.init/p6.cpp @@ -5,7 +5,8 @@ // If a program calls for the default initialization of an object of a // const-qualified type T, T shall be a class type with a // user-provided default constructor. -struct NoUserDefault { }; +struct MakeNonPOD { MakeNonPOD(); }; +struct NoUserDefault : public MakeNonPOD { }; struct HasUserDefault { HasUserDefault(); }; void test_const_default_init() { diff --git a/clang/test/CodeGenCXX/internal-linkage.cpp b/clang/test/CodeGenCXX/internal-linkage.cpp index 1ae0f08f86ee..4263891e57f5 100644 --- a/clang/test/CodeGenCXX/internal-linkage.cpp +++ b/clang/test/CodeGenCXX/internal-linkage.cpp @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s -struct Global { }; -template<typename T> struct X { }; +struct Global { Global(); }; +template<typename T> struct X { X(); }; namespace { - struct Anon { }; + struct Anon { Anon(); }; // CHECK: @_ZN12_GLOBAL__N_15anon0E = internal global Global anon0; diff --git a/clang/test/SemaCXX/statements.cpp b/clang/test/SemaCXX/statements.cpp index 852086ed9a94..0e27f4645af4 100644 --- a/clang/test/SemaCXX/statements.cpp +++ b/clang/test/SemaCXX/statements.cpp @@ -15,3 +15,8 @@ void test2() { later: ; } + +namespace PR6536 { + struct A {}; + void a() { goto out; A x; out: return; } +} |