summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-03-08 02:45:10 +0000
committerDouglas Gregor <dgregor@apple.com>2010-03-08 02:45:10 +0000
commit516a6bc399f1f4595423e80c9d4bc687f870acd1 (patch)
tree848ac6a7240e4b597359ca5c0bdf8f5736a8ff31
parenta2762918ecc636c9af207ce2a9ce705edad2a444 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97928 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp44
-rw-r--r--test/CXX/dcl.decl/dcl.init/p6.cpp3
-rw-r--r--test/CodeGenCXX/internal-linkage.cpp6
-rw-r--r--test/SemaCXX/statements.cpp5
4 files changed, 39 insertions, 19 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 935adcf1b6..82dcd60aa0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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/test/CXX/dcl.decl/dcl.init/p6.cpp b/test/CXX/dcl.decl/dcl.init/p6.cpp
index f627a199ec..df5dcfe97a 100644
--- a/test/CXX/dcl.decl/dcl.init/p6.cpp
+++ b/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/test/CodeGenCXX/internal-linkage.cpp b/test/CodeGenCXX/internal-linkage.cpp
index 1ae0f08f86..4263891e57 100644
--- a/test/CodeGenCXX/internal-linkage.cpp
+++ b/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/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp
index 852086ed9a..0e27f4645a 100644
--- a/test/SemaCXX/statements.cpp
+++ b/test/SemaCXX/statements.cpp
@@ -15,3 +15,8 @@ void test2() {
later:
;
}
+
+namespace PR6536 {
+ struct A {};
+ void a() { goto out; A x; out: return; }
+}