Fix the bug that Eli noticed where we wouldn't look at function decls outside the class declaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67627 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f21a462..af71e71 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -785,13 +785,15 @@
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, AbstractDiagSelID SelID) {
+ unsigned DiagID, AbstractDiagSelID SelID,
+ const CXXRecordDecl *CurrentRD) {
if (!getLangOptions().CPlusPlus)
return false;
if (const ArrayType *AT = Context.getAsArrayType(T))
- return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID);
+ return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
+ CurrentRD);
if (const PointerType *PT = T->getAsPointerType()) {
// Find the innermost pointer type.
@@ -799,7 +801,8 @@
PT = T;
if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType()))
- return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID);
+ return RequireNonAbstractType(Loc, AT->getElementType(), DiagID, SelID,
+ CurrentRD);
}
const RecordType *RT = T->getAsRecordType();
@@ -810,6 +813,9 @@
if (!RD)
return false;
+ if (CurrentRD && CurrentRD != RD)
+ return false;
+
if (!RD->isAbstract())
return false;
@@ -843,40 +849,58 @@
Sema &SemaRef;
CXXRecordDecl *AbstractClass;
- public:
- AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
- : SemaRef(SemaRef), AbstractClass(ac) {}
-
- bool VisitCXXRecordDecl(const CXXRecordDecl *RD) {
+ bool VisitDeclContext(const DeclContext *DC) {
bool Invalid = false;
- for (CXXRecordDecl::decl_iterator I = RD->decls_begin(),
- E = RD->decls_end(); I != E; ++I)
+ for (CXXRecordDecl::decl_iterator I = DC->decls_begin(),
+ E = DC->decls_end(); I != E; ++I)
Invalid |= Visit(*I);
-
+
return Invalid;
}
-
- bool VisitCXXMethodDecl(const CXXMethodDecl *MD) {
- // Check the return type.
- QualType RTy = MD->getType()->getAsFunctionType()->getResultType();
- bool Invalid =
- SemaRef.RequireNonAbstractType(MD->getLocation(), RTy,
- diag::err_abstract_type_in_decl,
- Sema::AbstractReturnType);
+
+ public:
+ AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
+ : SemaRef(SemaRef), AbstractClass(ac) {
+ Visit(SemaRef.Context.getTranslationUnitDecl());
+ }
- for (CXXMethodDecl::param_const_iterator I = MD->param_begin(),
- E = MD->param_end(); I != E; ++I) {
+ bool VisitFunctionDecl(const FunctionDecl *FD) {
+ if (FD->isThisDeclarationADefinition()) {
+ // No need to do the check if we're in a definition, because it requires
+ // that the return/param types are complete.
+ // because that requires
+ return VisitDeclContext(FD);
+ }
+
+ // Check the return type.
+ QualType RTy = FD->getType()->getAsFunctionType()->getResultType();
+ bool Invalid =
+ SemaRef.RequireNonAbstractType(FD->getLocation(), RTy,
+ diag::err_abstract_type_in_decl,
+ Sema::AbstractReturnType,
+ AbstractClass);
+
+ for (FunctionDecl::param_const_iterator I = FD->param_begin(),
+ E = FD->param_end(); I != E; ++I) {
const ParmVarDecl *VD = *I;
Invalid |=
SemaRef.RequireNonAbstractType(VD->getLocation(),
VD->getOriginalType(),
diag::err_abstract_type_in_decl,
- Sema::AbstractParamType);
+ Sema::AbstractParamType,
+ AbstractClass);
}
return Invalid;
}
+
+ bool VisitDecl(const Decl* D) {
+ if (const DeclContext *DC = dyn_cast<DeclContext>(D))
+ return VisitDeclContext(DC);
+
+ return false;
+ }
};
}
@@ -898,8 +922,8 @@
RD->setAbstract(true);
}
- if (RD->isAbstract())
- AbstractClassUsageDiagnoser(*this, RD).Visit(RD);
+ if (RD->isAbstract())
+ AbstractClassUsageDiagnoser(*this, RD);
if (!Template)
AddImplicitlyDeclaredMembersToClass(RD);