forked from OSchip/llvm-project
Improve diagnostics for missing members. This renames the err_typecheck_no_member to err_typecheck_no_member_deprecated. The idea is that err_typecheck_no_member_deprecated should be phased out and any call sites that reference it should call DiagnoseMissingMember instead.
llvm-svn: 80469
This commit is contained in:
parent
744a249493
commit
896c230a19
|
@ -1296,7 +1296,14 @@ def note_member_reference_needs_call : Note<
|
|||
"perhaps you meant to call this function with '()'?">;
|
||||
|
||||
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
||||
def err_typecheck_no_member : Error<"no member named %0">;
|
||||
def err_typecheck_no_member_deprecated : Error<"no member named %0">;
|
||||
def err_typecheck_record_no_member : Error<
|
||||
"%select{struct|union|class}0 %q1 has no member named %2">;
|
||||
def err_typecheck_namespace_no_member : Error<
|
||||
"namespace %q0 has no member named %1">;
|
||||
def err_typecheck_global_scope_no_member : Error<
|
||||
"the global scope has no member named %0">;
|
||||
|
||||
def err_member_redeclared : Error<"class member cannot be redeclared">;
|
||||
def err_member_def_does_not_match : Error<
|
||||
"out-of-line definition does not match any declaration in %0">;
|
||||
|
|
|
@ -345,6 +345,31 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void Sema::DiagnoseMissingMember(SourceLocation MemberLoc,
|
||||
DeclarationName Member,
|
||||
NestedNameSpecifier *NNS, SourceRange Range) {
|
||||
switch (NNS->getKind()) {
|
||||
default: assert(0 && "Unexpected nested name specifier kind!");
|
||||
case NestedNameSpecifier::TypeSpec: {
|
||||
const Type *Ty = Context.getCanonicalType(NNS->getAsType());
|
||||
RecordDecl *RD = cast<RecordType>(Ty)->getDecl();
|
||||
Diag(MemberLoc, diag::err_typecheck_record_no_member)
|
||||
<< RD->getTagKind() << RD << Member << Range;
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::Namespace: {
|
||||
Diag(MemberLoc, diag::err_typecheck_namespace_no_member)
|
||||
<< NNS->getAsNamespace() << Member << Range;
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::Global: {
|
||||
Diag(MemberLoc, diag::err_typecheck_global_scope_no_member)
|
||||
<< Member << Range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
|
||||
if (!this->Emit())
|
||||
return;
|
||||
|
|
|
@ -3461,6 +3461,9 @@ public:
|
|||
QualType FieldTy, const Expr *BitWidth,
|
||||
bool *ZeroWidth = 0);
|
||||
|
||||
void DiagnoseMissingMember(SourceLocation MemberLoc, DeclarationName Member,
|
||||
NestedNameSpecifier *NNS, SourceRange Range);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Extra semantic analysis beyond the C type system
|
||||
private:
|
||||
|
|
|
@ -311,7 +311,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
if (SD)
|
||||
DiagID = diag::err_expected_class_or_namespace;
|
||||
else if (SS.isSet())
|
||||
DiagID = diag::err_typecheck_no_member;
|
||||
DiagID = diag::err_typecheck_no_member_deprecated;
|
||||
else
|
||||
DiagID = diag::err_undeclared_var_use;
|
||||
|
||||
|
|
|
@ -2205,8 +2205,10 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
}
|
||||
} else if (D.getCXXScopeSpec().isSet()) {
|
||||
// No previous declaration in the qualifying scope.
|
||||
Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)
|
||||
<< Name << D.getCXXScopeSpec().getRange();
|
||||
NestedNameSpecifier *NNS =
|
||||
(NestedNameSpecifier *)D.getCXXScopeSpec().getScopeRep();
|
||||
DiagnoseMissingMember(D.getIdentifierLoc(), Name, NNS,
|
||||
D.getCXXScopeSpec().getRange());
|
||||
NewVD->setInvalidDecl();
|
||||
}
|
||||
|
||||
|
|
|
@ -2189,7 +2189,7 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
|
|||
Name, LookupOrdinaryName);
|
||||
|
||||
if (!R) {
|
||||
Diag(IdentLoc, diag::err_typecheck_no_member) << Name << SS.getRange();
|
||||
Diag(IdentLoc, diag::err_typecheck_no_member_deprecated) << Name << SS.getRange();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -789,10 +789,12 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
else {
|
||||
// If this name wasn't predeclared and if this is not a function call,
|
||||
// diagnose the problem.
|
||||
if (SS && !SS->isEmpty())
|
||||
return ExprError(Diag(Loc, diag::err_typecheck_no_member)
|
||||
<< Name << SS->getRange());
|
||||
else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
|
||||
if (SS && !SS->isEmpty()) {
|
||||
DiagnoseMissingMember(Loc, Name,
|
||||
(NestedNameSpecifier *)SS->getScopeRep(),
|
||||
SS->getRange());
|
||||
return ExprError();
|
||||
} else if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
|
||||
return ExprError(Diag(Loc, diag::err_undeclared_use)
|
||||
<< Name.getAsString());
|
||||
|
@ -2088,7 +2090,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
}
|
||||
|
||||
if (!Result)
|
||||
return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member)
|
||||
return ExprError(Diag(MemberLoc, diag::err_typecheck_no_member_deprecated)
|
||||
<< MemberName << BaseExpr->getSourceRange());
|
||||
if (Result.isAmbiguous()) {
|
||||
DiagnoseAmbiguousLookup(Result, MemberName, MemberLoc,
|
||||
|
@ -5475,7 +5477,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
|
|||
.getAsDecl());
|
||||
// FIXME: Leaks Res
|
||||
if (!MemberDecl)
|
||||
return ExprError(Diag(BuiltinLoc, diag::err_typecheck_no_member)
|
||||
return ExprError(Diag(BuiltinLoc, diag::err_typecheck_no_member_deprecated)
|
||||
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd));
|
||||
|
||||
// FIXME: C++: Verify that MemberDecl isn't a static field.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
namespace A {
|
||||
namespace B {
|
||||
class C { };
|
||||
struct S { };
|
||||
union U { };
|
||||
}
|
||||
}
|
||||
|
||||
void f() {
|
||||
A::B::i; // expected-error {{namespace 'A::B' has no member named 'i'}}
|
||||
A::B::C::i; // expected-error {{class 'A::B::C' has no member named 'i'}}
|
||||
::i; // expected-error {{the global scope has no member named 'i'}}
|
||||
}
|
||||
|
||||
int A::B::i = 10; // expected-error {{namespace 'A::B' has no member named 'i'}}
|
||||
int A::B::C::i = 10; // expected-error {{class 'A::B::C' has no member named 'i'}}
|
||||
int A::B::S::i = 10; // expected-error {{struct 'A::B::S' has no member named 'i'}}
|
||||
int A::B::U::i = 10; // expected-error {{union 'A::B::U' has no member named 'i'}}
|
||||
|
Loading…
Reference in New Issue