Changes in preparation for nested-name-specifiers.

-When parsing declarators, don't depend on "CurScope->isCXXClassScope() == true" for constructors/destructors
-For C++ member declarations, don't depend on "Declarator.getContext() == Declarator::MemberContext"

llvm-svn: 58866
This commit is contained in:
Argyrios Kyrtzidis 2008-11-07 22:02:30 +00:00
parent cc0d2cfa01
commit e442635c37
5 changed files with 52 additions and 30 deletions

View File

@ -310,6 +310,10 @@ public:
}
}
bool isCXXRecord() const {
return DeclKind == Decl::CXXRecord;
}
const ScopedDecl *getDeclChain() const { return DeclChain; }
ScopedDecl *getDeclChain() { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }

View File

@ -691,6 +691,8 @@ DIAG(err_constructor_byvalue_arg, ERROR,
"copy constructor must pass its first argument by reference")
// C++ destructors
DIAG(err_destructor_not_member, ERROR,
"destructor must be a non-static member function")
DIAG(err_destructor_cannot_be, ERROR,
"destructor cannot be declared '%0'")
DIAG(err_invalid_qualified_destructor, ERROR,

View File

@ -1355,6 +1355,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, bool PtrOperator) {
/// conversion-function-id [TODO]
/// '~' class-name
/// template-id [TODO]
///
void Parser::ParseDirectDeclarator(Declarator &D) {
// Parse the first direct-declarator seen.
if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
@ -1362,31 +1363,35 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
// Determine whether this identifier is a C++ constructor name or
// a normal identifier.
if (getLang().CPlusPlus &&
CurScope->isCXXClassScope() &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
Tok.getIdentifierInfo(), Tok.getLocation());
else
D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken();
} else if (getLang().CPlusPlus && Tok.is(tok::tilde) &&
CurScope->isCXXClassScope() && D.mayHaveIdentifier()) {
} else if (getLang().CPlusPlus &&
Tok.is(tok::tilde) && D.mayHaveIdentifier()) {
// This should be a C++ destructor.
SourceLocation TildeLoc = ConsumeToken();
if (Tok.is(tok::identifier)) {
// Use the next identifier and "~" to form a name for the
// destructor. This is useful both for diagnostics and for
// correctness of the parser, since we use presence/absence of the
// identifier to determine what we parsed.
// FIXME: We could end up with a template-id here, once we parse
// templates, and will have to do something different to form the
// name of the destructor.
IdentifierInfo *II = Tok.getIdentifierInfo();
II = &PP.getIdentifierTable().get(std::string("~") + II->getName());
// Use the next identifier and "~" to form a name for the
// destructor. This is useful both for diagnostics and for
// correctness of the parser, since we use presence/absence of the
// identifier to determine what we parsed.
// FIXME: We could end up with a template-id here, once we parse
// templates, and will have to do something different to form the
// name of the destructor.
assert(Tok.is(tok::identifier) && "Expected identifier");
IdentifierInfo *II = Tok.getIdentifierInfo();
II = &PP.getIdentifierTable().get(std::string("~") + II->getName());
if (TypeTy *Type = ParseClassName())
D.SetDestructor(Type, II, TildeLoc);
if (TypeTy *Type = ParseClassName())
D.SetDestructor(Type, II, TildeLoc);
else
D.SetIdentifier(0, TildeLoc);
} else {
Diag(Tok, diag::err_expected_class_name);
D.SetIdentifier(0, TildeLoc);
}
} else if (Tok.is(tok::kw_operator)) {
SourceLocation OperatorLoc = Tok.getLocation();

View File

@ -811,7 +811,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
FunctionDecl *NewFD;
if (D.getKind() == Declarator::DK_Constructor) {
// This is a C++ constructor declaration.
assert(D.getContext() == Declarator::MemberContext &&
assert(CurContext->isCXXRecord() &&
"Constructors can only be declared in a member context");
bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);
@ -827,21 +827,29 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
NewFD->setInvalidDecl();
} else if (D.getKind() == Declarator::DK_Destructor) {
// This is a C++ destructor declaration.
assert(D.getContext() == Declarator::MemberContext &&
"Destructor can only be declared in a member context");
if (CurContext->isCXXRecord()) {
bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(CurContext),
D.getIdentifierLoc(), II, R,
isInline,
/*isImplicitlyDeclared=*/false);
NewFD = CXXDestructorDecl::Create(Context,
cast<CXXRecordDecl>(CurContext),
D.getIdentifierLoc(), II, R,
isInline,
/*isImplicitlyDeclared=*/false);
if (isInvalidDecl)
if (isInvalidDecl)
NewFD->setInvalidDecl();
} else {
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
// Create a FunctionDecl to satisfy the function definition parsing
// code path.
NewFD = FunctionDecl::Create(Context, CurContext, D.getIdentifierLoc(),
II, R, SC, isInline, LastDeclarator,
// FIXME: Move to DeclGroup...
D.getDeclSpec().getSourceRange().getBegin());
NewFD->setInvalidDecl();
}
} else if (D.getKind() == Declarator::DK_Conversion) {
if (D.getContext() != Declarator::MemberContext) {
if (!CurContext->isCXXRecord()) {
Diag(D.getIdentifierLoc(),
diag::err_conv_function_not_member);
return 0;
@ -856,7 +864,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
if (isInvalidDecl)
NewFD->setInvalidDecl();
}
} else if (D.getContext() == Declarator::MemberContext) {
} else if (CurContext->isCXXRecord()) {
// This is a C++ method declaration.
NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(CurContext),
D.getIdentifierLoc(), II, R,
@ -1037,7 +1045,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
case DeclSpec::SCS_register: SC = VarDecl::Register; break;
case DeclSpec::SCS_private_extern: SC = VarDecl::PrivateExtern; break;
}
if (D.getContext() == Declarator::MemberContext) {
if (CurContext->isCXXRecord()) {
assert(SC == VarDecl::Static && "Invalid storage class for member!");
// This is a static data member for a C++ class.
NewVD = CXXClassVarDecl::Create(Context, cast<CXXRecordDecl>(CurContext),

View File

@ -35,3 +35,6 @@ struct F {
~F(); // expected-error{{destructor cannot be redeclared}}
};
~; // expected-error {{expected class name}}
~undef(); // expected-error {{expected class name}}
~F(){} // expected-error {{destructor must be a non-static member function}}