[cfe-commits] r67594 - in /cfe/trunk: include/clang/AST/DeclVisitor.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/abstract.cpp
Anders Carlsson
andersca at mac.com
Mon Mar 23 18:19:16 PDT 2009
Author: andersca
Date: Mon Mar 23 20:19:16 2009
New Revision: 67594
URL: http://llvm.org/viewvc/llvm-project?rev=67594&view=rev
Log:
More work on diagnosing abstract classes. We can now handle cases like
class C {
void g(C c);
virtual void f() = 0;
};
In this case, C is not known to be abstract when doing semantic analysis on g. This is done by recursively traversing the abstract class and checking the types of member functions.
Modified:
cfe/trunk/include/clang/AST/DeclVisitor.h
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/abstract.cpp
Modified: cfe/trunk/include/clang/AST/DeclVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclVisitor.h?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DeclVisitor.h Mon Mar 23 20:19:16 2009
@@ -13,6 +13,8 @@
#ifndef LLVM_CLANG_AST_DECLVISITOR_H
#define LLVM_CLANG_AST_DECLVISITOR_H
+#include "clang/AST/DeclTemplate.h"
+
namespace clang {
#define DISPATCH(NAME, CLASS) \
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Mar 23 20:19:16 2009
@@ -1638,8 +1638,16 @@
SourceLocation Loc, SourceRange Range);
std::string getAmbiguousPathsDisplayString(BasePaths &Paths);
- bool RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, unsigned SelID);
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType
+ };
+
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+ AbstractDiagSelID SelID = AbstractNone);
//===--------------------------------------------------------------------===//
// C++ Overloaded Operators [C++ 13.5]
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Mar 23 20:19:16 2009
@@ -1643,7 +1643,7 @@
// The variable can not have an abstract class type.
if (RequireNonAbstractType(D.getIdentifierLoc(), R,
diag::err_abstract_type_in_decl,
- 2 /* variable type */))
+ AbstractVariableType))
InvalidDecl = true;
// The variable can not
@@ -1815,11 +1815,14 @@
bool isExplicit = D.getDeclSpec().isExplicitSpecified();
// Check that the return type is not an abstract class type.
- if (RequireNonAbstractType(D.getIdentifierLoc(),
+ // For record types, this is done by the AbstractClassUsageDiagnoser once
+ // the class has been completely parsed.
+ if (!DC->isRecord() &&
+ RequireNonAbstractType(D.getIdentifierLoc(),
R->getAsFunctionType()->getResultType(),
diag::err_abstract_type_in_decl,
- 0 /* return type */))
- InvalidDecl = true;
+ AbstractReturnType))
+ InvalidDecl = true;
bool isVirtualOkay = false;
FunctionDecl *NewFD;
@@ -2609,9 +2612,12 @@
}
// Parameters can not be abstract class types.
- if (RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType,
+ // For record types, this is done by the AbstractClassUsageDiagnoser once
+ // the class has been completely parsed.
+ if (!CurContext->isRecord() &&
+ RequireNonAbstractType(D.getIdentifierLoc(), parmDeclType,
diag::err_abstract_type_in_decl,
- 1 /* parameter type */))
+ AbstractParamType))
D.setInvalidType(true);
QualType T = adjustParameterType(parmDeclType);
@@ -3544,7 +3550,7 @@
// Fields can not have abstract class types
if (RequireNonAbstractType(Loc, T, diag::err_abstract_type_in_decl,
- 3 /* field type */))
+ AbstractFieldType))
InvalidDecl = true;
// If this is declared as a bit-field, check the bit-field.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Mar 23 20:19:16 2009
@@ -15,6 +15,7 @@
#include "SemaInherit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclVisitor.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Preprocessor.h"
@@ -784,7 +785,7 @@
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
- unsigned DiagID, unsigned SelID) {
+ unsigned DiagID, AbstractDiagSelID SelID) {
if (!getLangOptions().CPlusPlus)
return false;
@@ -827,6 +828,49 @@
return true;
}
+namespace {
+ class VISIBILITY_HIDDEN AbstractClassUsageDiagnoser
+ : public DeclVisitor<AbstractClassUsageDiagnoser, bool> {
+ Sema &SemaRef;
+ CXXRecordDecl *AbstractClass;
+
+ public:
+ AbstractClassUsageDiagnoser(Sema& SemaRef, CXXRecordDecl *ac)
+ : SemaRef(SemaRef), AbstractClass(ac) {}
+
+ bool VisitCXXRecordDecl(const CXXRecordDecl *RD) {
+ bool Invalid = false;
+
+ for (CXXRecordDecl::decl_iterator I = RD->decls_begin(),
+ E = RD->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);
+
+ for (CXXMethodDecl::param_const_iterator I = MD->param_begin(),
+ E = MD->param_end(); I != E; ++I) {
+ const ParmVarDecl *VD = *I;
+ Invalid |=
+ SemaRef.RequireNonAbstractType(VD->getLocation(),
+ VD->getOriginalType(),
+ diag::err_abstract_type_in_decl,
+ Sema::AbstractParamType);
+ }
+
+ return Invalid;
+ }
+ };
+}
+
void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclTy *TagDecl,
SourceLocation LBrac,
@@ -845,6 +889,9 @@
RD->setAbstract(true);
}
+ if (RD->isAbstract())
+ AbstractClassUsageDiagnoser(*this, RD).Visit(RD);
+
if (!Template)
AddImplicitlyDeclaredMembersToClass(RD);
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Mar 23 20:19:16 2009
@@ -197,8 +197,8 @@
diag::err_invalid_incomplete_type_use, FullRange))
return ExprError();
- if (RequireNonAbstractType(TyBeginLoc, Ty,
- diag::err_allocation_of_abstract_type, 0))
+ if (RequireNonAbstractType(TyBeginLoc, Ty,
+ diag::err_allocation_of_abstract_type))
return ExprError();
exprs.release();
@@ -243,7 +243,7 @@
return ExprError();
if (RequireNonAbstractType(D.getSourceRange().getBegin(), AllocType,
- diag::err_allocation_of_abstract_type, 0))
+ diag::err_allocation_of_abstract_type))
return ExprError();
QualType ResultType = AllocType->isDependentType()
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Mar 23 20:19:16 2009
@@ -357,7 +357,7 @@
else if (SemaRef.RequireNonAbstractType(PInst->getLocation(),
PInst->getType(),
diag::err_abstract_type_in_decl,
- 1 /* parameter type */))
+ Sema::AbstractParamType))
PInst->setInvalidDecl();
Params.push_back(PInst);
Modified: cfe/trunk/test/SemaCXX/abstract.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/abstract.cpp?rev=67594&r1=67593&r2=67594&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/abstract.cpp (original)
+++ cfe/trunk/test/SemaCXX/abstract.cpp Mon Mar 23 20:19:16 2009
@@ -51,4 +51,16 @@
typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}}
void t6(Func);
+class F {
+ F a() { } // expected-error {{return type 'F' is an abstract class}}
+
+ class D {
+ void f(F c); // expected-error {{parameter type 'F' is an abstract class}}
+ };
+ union U {
+ void u(F c); // expected-error {{parameter type 'F' is an abstract class}}
+ };
+
+ virtual void f() = 0; // expected-note {{pure virtual function 'f'}}
+};
More information about the cfe-commits
mailing list