Hi,
The attached patch enables semantic checking of virtual functions. This
means:
1) Virtual fields and virtual static functions are rejected.
2) Classes with virtual functions are not considered aggregates.
3) Classes with virtual functions are polymorphic, as are classes
derived from polymorphic classes.
4) dynamic_cast checking is complete.
Sebastian
Index: test/SemaCXX/aggregate-initialization.cpp
===================================================================
--- test/SemaCXX/aggregate-initialization.cpp (revision 58767)
+++ test/SemaCXX/aggregate-initialization.cpp (working copy)
@@ -17,10 +17,12 @@
int m;
};
-// FIXME: virtual functions
struct NonAggr4 {
+ int m;
+ virtual void f();
};
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}}
+NonAggr4 na4 = { 17 }; // expected-error{{initialization of non-aggregate type
'struct NonAggr4' with an initializer list}}
Index: test/SemaCXX/class.cpp
===================================================================
--- test/SemaCXX/class.cpp (revision 58767)
+++ test/SemaCXX/class.cpp (working copy)
@@ -47,12 +47,16 @@
}
int f1(int p) {
- A z = 6;
- return p + x + this->y + z;
+ A z = 6;
+ return p + x + this->y + z;
}
typedef int A;
+ virtual int vi; // expected-error {{error: virtual can only appear on
non-static member functions}}
+ virtual static int vsif(); // expected-error {{error: virtual can only
appear on non-static member functions}}
+ virtual int vif();
+
private:
int x,y;
static int sx;
Index: test/SemaCXX/dynamic-cast.cpp
===================================================================
--- test/SemaCXX/dynamic-cast.cpp (revision 58767)
+++ test/SemaCXX/dynamic-cast.cpp (working copy)
@@ -10,6 +10,15 @@
struct Incomplete;
+struct Poly
+{
+ virtual void f();
+};
+
+struct PolyDerived : Poly
+{
+};
+
void basic_bad()
{
// ptr -> nonptr
@@ -52,4 +61,14 @@
(void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion
from derived class 'struct F' to base class 'struct A':\n struct F -> struct
B -> struct A\n struct F -> struct E -> struct A}}
}
-// FIXME: Other test cases require recognition of polymorphic classes.
+void poly()
+{
+ (void)dynamic_cast<A*>((Poly*)0);
+ (void)dynamic_cast<A&>(*((Poly*)0));
+ (void)dynamic_cast<A*>((PolyDerived*)0);
+ (void)dynamic_cast<A&>(*((PolyDerived*)0));
+
+ // Not polymorphic source
+ (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'struct A' is not
polymorphic}}
+ (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'struct A'
is not polymorphic}}
+}
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def (revision 58767)
+++ include/clang/Basic/DiagnosticKinds.def (working copy)
@@ -667,6 +667,8 @@
// C++ class members
DIAG(err_storageclass_invalid_for_member, ERROR,
"storage class specified for a member declaration")
+DIAG(err_virtual_non_function, ERROR,
+ "virtual can only appear on non-static member functions")
DIAG(err_not_bitfield_type, ERROR,
"cannot declare '%0' to be a bit-field type")
DIAG(err_static_not_bitfield, ERROR,
@@ -1142,6 +1144,8 @@
"'%0' is incomplete")
DIAG(err_bad_dynamic_cast_not_ptr, ERROR,
"'%0' is not a pointer")
+DIAG(err_bad_dynamic_cast_not_polymorphic, ERROR,
+ "'%0' is not polymorphic")
DIAG(err_invalid_use_of_function_type, ERROR,
"a function type is not allowed here")
Index: include/clang/AST/DeclCXX.h
===================================================================
--- include/clang/AST/DeclCXX.h (revision 58767)
+++ include/clang/AST/DeclCXX.h (working copy)
@@ -219,6 +219,10 @@
/// Aggregate - True when this class is an aggregate.
bool Aggregate : 1;
+ /// Polymorphic - True when this class is polymorphic, i.e. has at least one
+ /// virtual member or derives from a polymorphic class.
+ bool Polymorphic : 1;
+
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
@@ -238,8 +242,8 @@
SourceLocation L, IdentifierInfo *Id)
: RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
- Aggregate(true), Bases(0), NumBases(0), Constructors(DC, Id),
- Destructor(0) { }
+ Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
+ Constructors(DC, Id), Destructor(0) { }
~CXXRecordDecl();
@@ -327,6 +331,14 @@
/// [dcl.init.aggr]).
void setAggregate(bool Agg) { Aggregate = Agg; }
+ /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
+ /// which means that the class contains or inherits a virtual function.
+ bool isPolymorphic() const { return Polymorphic; }
+
+ /// setPolymorphic - Set whether this class is polymorphic (C++
+ /// [class.virtual]).
+ void setPolymorphic(bool Poly) { Polymorphic = Poly; }
+
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp (revision 58767)
+++ lib/Sema/SemaDeclCXX.cpp (working copy)
@@ -310,6 +310,15 @@
return true;
}
+ // If the base class is polymorphic, the new one is, too.
+ RecordDecl *BaseDecl = BaseType->getAsRecordType()->getDecl();
+ assert(BaseDecl && "Record type has no declaration");
+ BaseDecl = BaseDecl->getDefinition(Context);
+ assert(BaseDecl && "Base type is not incomplete, but has no definition");
+ if (cast<CXXRecordDecl>(BaseDecl)->isPolymorphic()) {
+ cast<CXXRecordDecl>(Decl)->setPolymorphic(true);
+ }
+
// Create the base specifier.
return new CXXBaseSpecifier(SpecifierRange, Virtual,
BaseType->isClassType(), Access, BaseType);
@@ -468,8 +477,16 @@
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 (DS.isVirtualSpecified()) {
+ if (!isFunc || DS.getStorageClassSpec() == DeclSpec::SCS_static) {
+ Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function);
+ InvalidDecl = true;
+ } else {
+ CXXRecordDecl *CurClass = cast<CXXRecordDecl>(CurContext);
+ CurClass->setAggregate(false);
+ CurClass->setPolymorphic(true);
+ }
+ }
if (BitWidth) {
// C++ 9.6p2: Only when declaring an unnamed bit-field may the
Index: lib/Sema/SemaNamedCast.cpp
===================================================================
--- lib/Sema/SemaNamedCast.cpp (revision 58770)
+++ lib/Sema/SemaNamedCast.cpp (working copy)
@@ -671,7 +671,12 @@
}
// C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
- // FIXME: Information not yet available.
+ const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(Context);
+ assert(SrcDecl && "Definition missing");
+ if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
+ Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic,
+ SrcPointee.getUnqualifiedType().getAsString(),
SrcExpr->getSourceRange());
+ }
// Done. Everything else is run-time checks.
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits