diff options
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/virtual-override.cpp | 19 |
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}} +} |