aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-12-03 18:33:45 +0000
committerDouglas Gregor <dgregor@apple.com>2009-12-03 18:33:45 +0000
commit1ab537be683c31afba3272a61ddd13811967d3be (patch)
treebc2ee9005c4aadf96ef310c9986a8a6841052932
parent9f303beca8a71368e34f53dd14eed7a3b51331ca (diff)
Unify the end-of-class code paths used by the parser and template
instantiation, to ensure that we mark class template specilizations as abstract when we need to and perform checking of abstract classes. Also, move the checking that determines whether we are creating a variable of abstract class type *after* we check whether the type is complete. Otherwise, we won't see when we have an abstract class template specialization that is implicitly instantiated by this declaration. This is the "something else" that Sebastian had noted earlier. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90467 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h1
-rw-r--r--lib/Sema/SemaDecl.cpp18
-rw-r--r--lib/Sema/SemaDeclCXX.cpp39
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp5
-rw-r--r--test/SemaCXX/virtual-override.cpp19
5 files changed, 55 insertions, 27 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 2ca639197e..616151efea 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2148,6 +2148,7 @@ public:
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits);
+ void CheckCompletedCXXClass(CXXRecordDecl *Record);
virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 5a7d006043..ea5e47a9a3 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2444,12 +2444,6 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
return NewVD->setInvalidDecl();
}
- // The variable can not have an abstract class type.
- if (RequireNonAbstractType(NewVD->getLocation(), T,
- diag::err_abstract_type_in_decl,
- AbstractVariableType))
- return NewVD->setInvalidDecl();
-
// Emit an error if an address space was applied to decl with local storage.
// This includes arrays of objects with address space qualifiers, but not
// automatic variables that point to other address spaces.
@@ -3431,6 +3425,12 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
return;
}
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(),
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ VDecl->setInvalidDecl();
+
const VarDecl *Def = 0;
if (VDecl->getDefinition(Def)) {
Diag(VDecl->getLocation(), diag::err_redefinition)
@@ -3663,6 +3663,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
Var->setInvalidDecl();
}
}
+
+ // The variable can not have an abstract class type.
+ if (RequireNonAbstractType(Var->getLocation(), Type,
+ diag::err_abstract_type_in_decl,
+ AbstractVariableType))
+ Var->setInvalidDecl();
}
#if 0
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 551ee92266..58b5633afa 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1957,6 +1957,28 @@ namespace {
};
}
+/// \brief Perform semantic checks on a class definition that has been
+/// completing, introducing implicitly-declared members, checking for
+/// abstract types, etc.
+void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
+ if (!Record || Record->isInvalidDecl())
+ return;
+
+ if (!Record->isAbstract()) {
+ // Collect all the pure virtual methods and see if this is an abstract
+ // class after all.
+ PureVirtualMethodCollector Collector(Context, Record);
+ if (!Collector.empty())
+ Record->setAbstract(true);
+ }
+
+ if (Record->isAbstract())
+ (void)AbstractClassUsageDiagnoser(*this, Record);
+
+ if (!Record->isDependentType() && !Record->isInvalidDecl())
+ AddImplicitlyDeclaredMembersToClass(Record);
+}
+
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
@@ -1965,24 +1987,13 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
return;
AdjustDeclIfTemplate(TagDecl);
+
ActOnFields(S, RLoc, TagDecl,
(DeclPtrTy*)FieldCollector->getCurFields(),
FieldCollector->getCurNumFields(), LBrac, RBrac, 0);
- CXXRecordDecl *RD = cast<CXXRecordDecl>(TagDecl.getAs<Decl>());
- if (!RD->isAbstract()) {
- // Collect all the pure virtual methods and see if this is an abstract
- // class after all.
- PureVirtualMethodCollector Collector(Context, RD);
- if (!Collector.empty())
- RD->setAbstract(true);
- }
-
- if (RD->isAbstract())
- (void)AbstractClassUsageDiagnoser(*this, RD);
-
- if (!RD->isDependentType() && !RD->isInvalidDecl())
- AddImplicitlyDeclaredMembersToClass(RD);
+ CheckCompletedCXXClass(
+ dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>()));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 250d14c865..122e85eaa5 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1077,13 +1077,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
0);
+ CheckCompletedCXXClass(Instantiation);
if (Instantiation->isInvalidDecl())
Invalid = true;
- // Add any implicitly-declared members that we might need.
- if (!Invalid)
- AddImplicitlyDeclaredMembersToClass(Instantiation);
-
// Exit the scope of this instantiation.
CurContext = PreviousContext;
diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp
index cee64568cd..c18a77f036 100644
--- a/test/SemaCXX/virtual-override.cpp
+++ b/test/SemaCXX/virtual-override.cpp
@@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -faccess-control -verify %s
-
namespace T1 {
class A {
@@ -122,8 +121,8 @@ struct Base1 { virtual void f(int); };
struct Base2 { };
void test() {
- Foo<Base1> f1;
- Foo<Base2> f2; // expected-note{{instantiation}}
+ (void)sizeof(Foo<Base1>);
+ (void)sizeof(Foo<Base2>); // expected-note{{instantiation}}
}
template<typename Base>
@@ -137,3 +136,17 @@ void test2() {
f1.f(17);
f2.f(17);
};
+
+struct Foo3 {
+ virtual void f(int) = 0; // expected-note{{pure virtual function}}
+};
+
+template<typename T>
+struct Bar3 : Foo3 {
+ void f(T);
+};
+
+void test3() {
+ Bar3<int> b3i; // okay
+ Bar3<float> b3f; // expected-error{{is an abstract class}}
+}