forked from OSchip/llvm-project
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:
parent
cc0d2cfa01
commit
e442635c37
|
@ -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; }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue