mirror of
https://github.com/intel/llvm.git
synced 2026-02-08 08:57:43 +08:00
Generalize the checking for qualification of (non-friend) class
members. Provide a hard error when the qualification doesn't match the current class type, or a warning + Fix-it if it does match the current class type. Fixes PR8159. llvm-svn: 116445
This commit is contained in:
@@ -2167,6 +2167,8 @@ def ext_out_of_line_declaration : ExtWarn<
|
||||
InGroup<OutOfLineDeclaration>, DefaultError;
|
||||
def warn_member_extra_qualification : Warning<
|
||||
"extra qualification on member %0">;
|
||||
def err_member_qualification : Error<
|
||||
"non-friend class member %0 cannot have a qualified name">;
|
||||
def note_member_def_close_match : Note<"member declaration nearly matches">;
|
||||
def err_typecheck_ivar_variable_size : Error<
|
||||
"instance variables must have a constant size">;
|
||||
|
||||
@@ -2265,11 +2265,30 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D,
|
||||
RequireCompleteDeclContext(D.getCXXScopeSpec(), DC))
|
||||
return 0;
|
||||
|
||||
if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) {
|
||||
Diag(D.getIdentifierLoc(),
|
||||
diag::err_member_def_undefined_record)
|
||||
<< Name << DC << D.getCXXScopeSpec().getRange();
|
||||
D.setInvalidType();
|
||||
if (isa<CXXRecordDecl>(DC)) {
|
||||
if (!cast<CXXRecordDecl>(DC)->hasDefinition()) {
|
||||
Diag(D.getIdentifierLoc(),
|
||||
diag::err_member_def_undefined_record)
|
||||
<< Name << DC << D.getCXXScopeSpec().getRange();
|
||||
D.setInvalidType();
|
||||
} else if (isa<CXXRecordDecl>(CurContext) &&
|
||||
!D.getDeclSpec().isFriendSpecified()) {
|
||||
// The user provided a superfluous scope specifier inside a class
|
||||
// definition:
|
||||
//
|
||||
// class X {
|
||||
// void X::f();
|
||||
// };
|
||||
if (CurContext->Equals(DC))
|
||||
Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
|
||||
<< Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
|
||||
else
|
||||
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
|
||||
<< Name << D.getCXXScopeSpec().getRange();
|
||||
|
||||
// Pretend that this qualifier was not here.
|
||||
D.getCXXScopeSpec().clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether we need to rebuild the type of the given
|
||||
@@ -3684,18 +3703,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
|
||||
if (NewFD->isInvalidDecl()) {
|
||||
// Ignore all the rest of this.
|
||||
|
||||
} else if (CurContext->isRecord() && D.getCXXScopeSpec().isSet() &&
|
||||
!isFriend) {
|
||||
// The user provided a superfluous scope specifier inside a class
|
||||
// definition:
|
||||
//
|
||||
// class X {
|
||||
// void X::f();
|
||||
// };
|
||||
Diag(NewFD->getLocation(), diag::warn_member_extra_qualification)
|
||||
<< Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange());
|
||||
|
||||
} else if (!Redeclaration) {
|
||||
// Fake up an access specifier if it's supposed to be a class member.
|
||||
if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
|
||||
|
||||
@@ -896,6 +896,27 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
|
||||
|
||||
Decl *Member;
|
||||
if (isInstField) {
|
||||
CXXScopeSpec &SS = D.getCXXScopeSpec();
|
||||
|
||||
|
||||
if (SS.isSet() && !SS.isInvalid()) {
|
||||
// The user provided a superfluous scope specifier inside a class
|
||||
// definition:
|
||||
//
|
||||
// class X {
|
||||
// int X::member;
|
||||
// };
|
||||
DeclContext *DC = 0;
|
||||
if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext))
|
||||
Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification)
|
||||
<< Name << FixItHint::CreateRemoval(SS.getRange());
|
||||
else
|
||||
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
|
||||
<< Name << SS.getRange();
|
||||
|
||||
SS.clear();
|
||||
}
|
||||
|
||||
// FIXME: Check for template parameters!
|
||||
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth,
|
||||
AS);
|
||||
|
||||
@@ -248,3 +248,13 @@ namespace PR7133 {
|
||||
class CLASS {
|
||||
void CLASS::foo2(); // expected-warning {{extra qualification on member 'foo2'}}
|
||||
};
|
||||
|
||||
namespace PR8159 {
|
||||
class B { };
|
||||
|
||||
class A {
|
||||
int A::a; // expected-warning{{extra qualification on member 'a'}}
|
||||
static int A::b; // expected-warning{{extra qualification on member 'b'}}
|
||||
int ::c; // expected-error{{non-friend class member 'c' cannot have a qualified name}}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user