[cfe-commits] r69245 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/AST/ExprCXX.cpp lib/Parse/ParseExpr.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/trivial-constructor.cpp
Anders Carlsson
andersca at mac.com
Wed Apr 15 17:08:20 PDT 2009
Author: andersca
Date: Wed Apr 15 19:08:20 2009
New Revision: 69245
URL: http://llvm.org/viewvc/llvm-project?rev=69245&view=rev
Log:
Add support for the __has_trivial_constructor type trait.
Added:
cfe/trunk/test/SemaCXX/trivial-constructor.cpp
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/Parse/ParseExpr.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=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Apr 15 19:08:20 2009
@@ -225,6 +225,9 @@
/// pure virtual function, (that can come from a base class).
bool Abstract : 1;
+ /// HasTrivialConstructor - True when this class has a trivial constructor
+ bool HasTrivialConstructor : 1;
+
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
@@ -375,6 +378,14 @@
/// setAbstract - Set whether this class is abstract (C++ [class.abstract])
void setAbstract(bool Abs) { Abstract = Abs; }
+ // hasTrivialConstructor - Whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ bool hasTrivialConstructor() const { return HasTrivialConstructor; }
+
+ // setHasTrivialConstructor - Set whether this class has a trivial constructor
+ // (C++ [class.ctor]p5)
+ void setHasTrivialConstructor(bool TC) { HasTrivialConstructor = TC; }
+
/// \brief If this record is an instantiation of a member class,
/// retrieves the member class from which it was instantiated.
///
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Apr 15 19:08:20 2009
@@ -29,6 +29,7 @@
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false),
+ HasTrivialConstructor(true),
Bases(0), NumBases(0), Conversions(DC, DeclarationName()),
TemplateOrInstantiation() { }
@@ -138,6 +139,11 @@
// A POD-struct is an aggregate class [...]
PlainOldData = false;
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if it is an implicitly-declared default
+ // constructor.
+ HasTrivialConstructor = false;
+
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context))
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Apr 15 19:08:20 2009
@@ -170,6 +170,10 @@
if (const RecordType *RT = QueriedType->getAsRecordType())
return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
return false;
+ case UTT_HasTrivialConstructor:
+ if (const RecordType *RT = QueriedType->getAsRecordType())
+ return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
+ return false;
}
}
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Apr 15 19:08:20 2009
@@ -481,7 +481,7 @@
/// '__has_nothrow_constructor' [TODO]
/// '__has_trivial_assign' [TODO]
/// '__has_trivial_copy' [TODO]
-/// '__has_trivial_constructor' [TODO]
+/// '__has_trivial_constructor'
/// '__has_trivial_destructor' [TODO]
/// '__has_virtual_destructor' [TODO]
/// '__is_abstract' [TODO]
@@ -771,6 +771,7 @@
case tok::kw___is_union:
case tok::kw___is_polymorphic:
case tok::kw___is_abstract:
+ case tok::kw___has_trivial_constructor:
return ParseUnaryTypeTrait();
case tok::at: {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Apr 15 19:08:20 2009
@@ -2049,6 +2049,7 @@
CurClass->setAggregate(false);
CurClass->setPOD(false);
CurClass->setPolymorphic(true);
+ CurClass->setHasTrivialConstructor(false);
}
}
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=69245&r1=69244&r2=69245&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Apr 15 19:08:20 2009
@@ -369,6 +369,18 @@
Class->setAggregate(false);
Class->setPOD(false);
+ if (Virtual) {
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if its class has no virtual base classes.
+ Class->setHasTrivialConstructor(false);
+ } else {
+ // C++ [class.ctor]p5:
+ // A constructor is trivial if all the direct base classes of its
+ // class have trivial constructors.
+ Class->setHasTrivialConstructor(cast<CXXRecordDecl>(BaseDecl)->
+ hasTrivialConstructor());
+ }
+
// Create the base specifier.
// FIXME: Allocate via ASTContext?
return new CXXBaseSpecifier(SpecifierRange, Virtual,
@@ -940,6 +952,24 @@
if (RD->isAbstract())
AbstractClassUsageDiagnoser(*this, RD);
+ if (RD->hasTrivialConstructor()) {
+ for (RecordDecl::field_iterator i = RD->field_begin(Context),
+ e = RD->field_end(Context); i != e; ++i) {
+ // All the nonstatic data members must have trivial constructors.
+ QualType FTy = i->getType();
+ while (const ArrayType *AT = Context.getAsArrayType(FTy))
+ FTy = AT->getElementType();
+
+ if (const RecordType *RT = FTy->getAsRecordType()) {
+ CXXRecordDecl *FieldRD = cast<CXXRecordDecl>(RT->getDecl());
+ if (!FieldRD->hasTrivialConstructor()) {
+ RD->setHasTrivialConstructor(false);
+ break;
+ }
+ }
+ }
+ }
+
if (!Template)
AddImplicitlyDeclaredMembersToClass(RD);
}
Added: cfe/trunk/test/SemaCXX/trivial-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/trivial-constructor.cpp?rev=69245&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/trivial-constructor.cpp (added)
+++ cfe/trunk/test/SemaCXX/trivial-constructor.cpp Wed Apr 15 19:08:20 2009
@@ -0,0 +1,34 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+struct T1 {
+};
+static_assert(__has_trivial_constructor(T1), "T1 has trivial constructor!");
+
+struct T2 {
+ T2();
+};
+static_assert(!__has_trivial_constructor(T2), "T2 has a user-declared constructor!");
+
+struct T3 {
+ virtual void f();
+};
+static_assert(!__has_trivial_constructor(T3), "T3 has a virtual function!");
+
+struct T4 : virtual T3 {
+};
+static_assert(!__has_trivial_constructor(T4), "T4 has a virtual base class!");
+
+struct T5 : T1 {
+};
+static_assert(__has_trivial_constructor(T5), "All the direct base classes of T5 have trivial constructors!");
+
+struct T6 {
+ T5 t5;
+ T1 t1[2][2];
+ static T2 t2;
+};
+static_assert(__has_trivial_constructor(T6), "All nonstatic data members of T6 have trivial constructors!");
+
+struct T7 {
+ T4 t4;
+};
+static_assert(!__has_trivial_constructor(T7), "t4 does not have a trivial constructor!");
More information about the cfe-commits
mailing list