aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}}
+}