зеркало из https://github.com/microsoft/clang.git
Very basic support for pure virtual functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62003 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6037fcba34
Коммит
9ba73ad654
|
@ -648,6 +648,8 @@ private:
|
|||
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
|
||||
unsigned SClass : 2;
|
||||
bool IsInline : 1;
|
||||
bool IsVirtual : 1;
|
||||
bool IsPure : 1;
|
||||
|
||||
// Move to DeclGroup when it is implemented.
|
||||
SourceLocation TypeSpecStartLoc;
|
||||
|
@ -659,7 +661,8 @@ protected:
|
|||
: ValueDecl(DK, DC, L, N, T, PrevDecl),
|
||||
DeclContext(DK),
|
||||
ParamInfo(0), Body(0), PreviousDeclaration(0),
|
||||
SClass(S), IsInline(isInline), TypeSpecStartLoc(TSSL) {}
|
||||
SClass(S), IsInline(isInline), IsVirtual(false), IsPure(false),
|
||||
TypeSpecStartLoc(TSSL) {}
|
||||
|
||||
virtual ~FunctionDecl();
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
@ -692,7 +695,13 @@ public:
|
|||
bool isThisDeclarationADefinition() const { return Body != 0; }
|
||||
|
||||
void setBody(Stmt *B) { Body = B; }
|
||||
|
||||
|
||||
bool isVirtual() { return IsVirtual; }
|
||||
void setVirtual() { IsVirtual = true; }
|
||||
|
||||
bool isPure() { return IsPure; }
|
||||
void setPure() { IsPure = true; }
|
||||
|
||||
/// getPreviousDeclaration - Return the previous declaration of this
|
||||
/// function.
|
||||
const FunctionDecl *getPreviousDeclaration() const {
|
||||
|
|
|
@ -753,6 +753,10 @@ DIAG(err_not_integral_type_bitfield, ERROR,
|
|||
"bit-field %0 with non-integral type")
|
||||
DIAG(err_member_initialization, ERROR,
|
||||
"%0 can only be initialized if it is a static const integral data member")
|
||||
DIAG(err_member_function_initialization, ERROR,
|
||||
"initializer on function does not look like a pure-specifier")
|
||||
DIAG(err_non_virtual_pure, ERROR,
|
||||
"%0 is not virtual and cannot be declared pure")
|
||||
DIAG(err_implicit_object_parameter_init, ERROR,
|
||||
"cannot initialize object parameter of type %0 with an expression of type %1")
|
||||
|
||||
|
|
|
@ -535,6 +535,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function);
|
||||
InvalidDecl = true;
|
||||
} else {
|
||||
cast<CXXMethodDecl>(Member)->setVirtual();
|
||||
CXXRecordDecl *CurClass = cast<CXXRecordDecl>(CurContext);
|
||||
CurClass->setAggregate(false);
|
||||
CurClass->setPOD(false);
|
||||
|
@ -542,6 +543,10 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME: The above definition of virtual is not sufficient. A function is
|
||||
// also virtual if it overrides an already virtual function. This is important
|
||||
// to do here because it decides the validity of a pure specifier.
|
||||
|
||||
if (BitWidth) {
|
||||
// C++ 9.6p2: Only when declaring an unnamed bit-field may the
|
||||
// constant-expression be a value equal to zero.
|
||||
|
@ -608,10 +613,28 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
|||
}
|
||||
|
||||
} else {
|
||||
// not static member.
|
||||
Diag(Loc, diag::err_member_initialization)
|
||||
<< Name << Init->getSourceRange();
|
||||
InvalidDecl = true;
|
||||
// not static member. perhaps virtual function?
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member)) {
|
||||
IntegerLiteral *IL;
|
||||
if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 &&
|
||||
Context.getCanonicalType(IL->getType()) == Context.IntTy) {
|
||||
if (MD->isVirtual())
|
||||
MD->setPure();
|
||||
else {
|
||||
Diag(Loc, diag::err_non_virtual_pure)
|
||||
<< Name << Init->getSourceRange();
|
||||
InvalidDecl = true;
|
||||
}
|
||||
} else {
|
||||
Diag(Loc, diag::err_member_function_initialization)
|
||||
<< Name << Init->getSourceRange();
|
||||
InvalidDecl = true;
|
||||
}
|
||||
} else {
|
||||
Diag(Loc, diag::err_member_initialization)
|
||||
<< Name << Init->getSourceRange();
|
||||
InvalidDecl = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// RUN: clang -fsyntax-only -verify %s
|
||||
|
||||
class A {
|
||||
virtual void f();
|
||||
virtual void g() = 0;
|
||||
|
||||
void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}}
|
||||
void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}}
|
||||
void j() = 0u; // expected-error {{initializer on function does not look like a pure-specifier}}
|
||||
|
||||
public:
|
||||
A(int);
|
||||
};
|
||||
|
||||
class B : public A {
|
||||
// Needs to recognize that overridden function is virtual.
|
||||
//void g() = 0;
|
||||
|
||||
// Needs to recognize that function does not override.
|
||||
//void g(int) = 0;
|
||||
};
|
||||
|
||||
// Needs to recognize invalid uses of abstract classes.
|
||||
/*
|
||||
A fn(A)
|
||||
{
|
||||
A a;
|
||||
static_cast<A>(0);
|
||||
try {
|
||||
} catch(A) {
|
||||
}
|
||||
}
|
||||
*/
|
Загрузка…
Ссылка в новой задаче