[cfe-commits] r58757 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/aggregate-initialization.cpp
Douglas Gregor
doug.gregor at gmail.com
Wed Nov 5 08:20:42 PST 2008
Author: dgregor
Date: Wed Nov 5 10:20:31 2008
New Revision: 58757
URL: http://llvm.org/viewvc/llvm-project?rev=58757&view=rev
Log:
Keep track of whether a C++ class is an aggregate. Don't allow initialization of non-aggregates with initializer lists.
Added:
cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=58757&r1=58756&r2=58757&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Nov 5 10:20:31 2008
@@ -215,6 +215,9 @@
/// user-defined copy constructor.
bool UserDeclaredCopyConstructor : 1;
+ /// Aggregate - True when this class is an aggregate.
+ bool Aggregate : 1;
+
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
@@ -230,8 +233,8 @@
CXXRecordDecl(TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id)
: RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
- UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
- Bases(0), NumBases(0), Constructors(DC, Id) { }
+ UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+ Aggregate(true), Bases(0), NumBases(0), Constructors(DC, Id) { }
~CXXRecordDecl();
@@ -300,6 +303,16 @@
return UserDeclaredCopyConstructor;
}
+ /// isAggregate - Whether this class is an aggregate (C++
+ /// [dcl.init.aggr]), which is a class with no user-declared
+ /// constructors, no private or protected non-static data members,
+ /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
+ bool isAggregate() const { return Aggregate; }
+
+ /// setAggregate - Set whether this class is an aggregate (C++
+ /// [dcl.init.aggr]).
+ void setAggregate(bool Agg) { Aggregate = Agg; }
+
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=58757&r1=58756&r2=58757&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Nov 5 10:20:31 2008
@@ -697,6 +697,8 @@
"declaration of reference variable '%0' requires an initializer")
DIAG(err_const_var_requires_init, ERROR,
"declaration of const variable '%0' requires an initializer")
+DIAG(err_init_non_aggr_init_list, ERROR,
+ "initialization of non-aggregate type '%0' with an initializer list")
// Objective-C++
DIAG(err_objc_decls_may_only_appear_in_global_scope, ERROR,
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=58757&r1=58756&r2=58757&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Nov 5 10:20:31 2008
@@ -50,6 +50,11 @@
void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
unsigned NumBases) {
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with [...]
+ // no base classes [...].
+ Aggregate = false;
+
if (this->Bases)
delete [] this->Bases;
@@ -78,6 +83,11 @@
// Note that we have a user-declared constructor.
UserDeclaredConstructor = true;
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with no
+ // user-declared constructors (12.1) [...].
+ Aggregate = false;
+
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context))
@@ -154,9 +164,8 @@
bool CXXConstructorDecl::isDefaultConstructor() const {
// C++ [class.ctor]p5:
- //
- // A default constructor for a class X is a constructor of class
- // X that can be called without an argument.
+ // A default constructor for a class X is a constructor of class
+ // X that can be called without an argument.
return (getNumParams() == 0) ||
(getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
}
@@ -165,10 +174,10 @@
CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
unsigned &TypeQuals) const {
// C++ [class.copy]p2:
- // A non-template constructor for class X is a copy constructor
- // if its first parameter is of type X&, const X&, volatile X& or
- // const volatile X&, and either there are no other parameters
- // or else all other parameters have default arguments (8.3.6).
+ // A non-template constructor for class X is a copy constructor
+ // if its first parameter is of type X&, const X&, volatile X& or
+ // const volatile X&, and either there are no other parameters
+ // or else all other parameters have default arguments (8.3.6).
if ((getNumParams() < 1) ||
(getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
return false;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=58757&r1=58756&r2=58757&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov 5 10:20:31 2008
@@ -701,6 +701,23 @@
Init->getSourceRange());
return CheckSingleInitializer(Init, DeclType);
+ } else if (getLangOptions().CPlusPlus) {
+ // C++ [dcl.init]p14:
+ // [...] If the class is an aggregate (8.5.1), and the initializer
+ // is a brace-enclosed list, see 8.5.1.
+ //
+ // Note: 8.5.1 is handled below; here, we diagnose the case where
+ // we have an initializer list and a destination type that is not
+ // an aggregate.
+ // FIXME: In C++0x, this is yet another form of initialization.
+ if (const RecordType *ClassRec = DeclType->getAsRecordType()) {
+ const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
+ if (!ClassDecl->isAggregate())
+ return Diag(InitLoc,
+ diag::err_init_non_aggr_init_list,
+ DeclType.getAsString(),
+ Init->getSourceRange());
+ }
}
InitListChecker CheckInitList(this, InitList, DeclType);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58757&r1=58756&r2=58757&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Nov 5 10:20:31 2008
@@ -461,6 +461,15 @@
// member decls.
CXXClassMemberWrapper(Member).setAccess(AS);
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is an array or a class (clause 9) with [...] no
+ // private or protected non-static data members (clause 11).
+ if (isInstField && (AS == AS_private || AS == AS_protected))
+ cast<CXXRecordDecl>(CurContext)->setAggregate(false);
+
+ // FIXME: If the member is a virtual function, mark it its class as
+ // a non-aggregate.
+
if (BitWidth) {
// C++ 9.6p2: Only when declaring an unnamed bit-field may the
// constant-expression be a value equal to zero.
Added: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=58757&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (added)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Wed Nov 5 10:20:31 2008
@@ -0,0 +1,26 @@
+// RUN: clang -fsyntax-only -verify -std=c++98 %s
+
+// Verify that we can't initialize non-aggregates with an initializer
+// list.
+struct NonAggr1 {
+ NonAggr1(int) { }
+
+ int m;
+};
+
+struct Base { };
+struct NonAggr2 : public Base {
+ int m;
+};
+
+class NonAggr3 {
+ int m;
+};
+
+// FIXME: virtual functions
+struct NonAggr4 {
+};
+
+NonAggr1 na1 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr1' with an initializer list}}
+NonAggr2 na2 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr2' with an initializer list}}
+NonAggr3 na3 = { 17 }; // expected-error{{initialization of non-aggregate type 'class NonAggr3' with an initializer list}}
Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list