forked from OSchip/llvm-project
Implement -Wshadow. Based on a patch by Mike M.!
llvm-svn: 98684
This commit is contained in:
parent
c953bca10b
commit
a2a3f7dc11
|
@ -73,7 +73,7 @@ def : DiagGroup<"redundant-decls">;
|
|||
def ReturnType : DiagGroup<"return-type">;
|
||||
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
|
||||
def : DiagGroup<"sequence-point">;
|
||||
def : DiagGroup<"shadow">;
|
||||
def Shadow : DiagGroup<"shadow">;
|
||||
def : DiagGroup<"shorten-64-to-32">;
|
||||
def SignCompare : DiagGroup<"sign-compare">;
|
||||
def : DiagGroup<"synth">;
|
||||
|
|
|
@ -108,6 +108,15 @@ def warn_use_out_of_scope_declaration : Warning<
|
|||
def err_inline_non_function : Error<
|
||||
"'inline' can only appear on functions">;
|
||||
|
||||
def warn_decl_shadow :
|
||||
Warning<"declaration shadows a %select{"
|
||||
"local variable|"
|
||||
"variable in %2|"
|
||||
"static data member of %2|"
|
||||
"field of %2|"
|
||||
"global built-in function}1">,
|
||||
InGroup<Shadow>, DefaultIgnore;
|
||||
|
||||
// C++ using declarations
|
||||
def err_using_requires_qualname : Error<
|
||||
"using declaration requires a qualified name">;
|
||||
|
|
|
@ -430,7 +430,10 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
|||
for (; I!=End; ++I)
|
||||
QualName += *I + "::";
|
||||
|
||||
if (getDeclName())
|
||||
QualName += getNameAsString();
|
||||
else
|
||||
QualName += "<anonymous>";
|
||||
|
||||
return QualName;
|
||||
}
|
||||
|
|
|
@ -778,6 +778,7 @@ public:
|
|||
const LookupResult &Previous,
|
||||
Scope *S);
|
||||
void DiagnoseFunctionSpecifiers(Declarator& D);
|
||||
void DiagnoseShadow(NamedDecl* D, const LookupResult& R);
|
||||
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
QualType R, TypeSourceInfo *TInfo,
|
||||
LookupResult &Previous, bool &Redeclaration);
|
||||
|
|
|
@ -2403,6 +2403,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
|
||||
}
|
||||
|
||||
// Diagnose shadowed variables before filtering for scope.
|
||||
DiagnoseShadow(NewVD, Previous);
|
||||
|
||||
// Don't consider existing declarations that are in a different
|
||||
// scope and are out-of-semantic-context declarations (if the new
|
||||
// declaration has linkage).
|
||||
|
@ -2454,6 +2457,65 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
return NewVD;
|
||||
}
|
||||
|
||||
/// \brief Diagnose variable or built-in function shadowing.
|
||||
///
|
||||
/// This method is called as soon as a NamedDecl materializes to check
|
||||
/// if it shadows another local or global variable, or a built-in function.
|
||||
///
|
||||
/// For performance reasons, the lookup results are reused from the calling
|
||||
/// context.
|
||||
///
|
||||
/// \param D variable decl to diagnose. Must be a variable.
|
||||
/// \param R cached previous lookup of \p D.
|
||||
///
|
||||
void Sema::DiagnoseShadow(NamedDecl* D, const LookupResult& R) {
|
||||
assert(D->getKind() == Decl::Var && "Expecting variable.");
|
||||
|
||||
// Return if warning is ignored.
|
||||
if (Diags.getDiagnosticLevel(diag::warn_decl_shadow) == Diagnostic::Ignored)
|
||||
return;
|
||||
|
||||
// Return if not local decl.
|
||||
if (!D->getDeclContext()->isFunctionOrMethod())
|
||||
return;
|
||||
|
||||
DeclarationName Name = D->getDeclName();
|
||||
|
||||
// Return if lookup has no result.
|
||||
if (R.getResultKind() != LookupResult::Found) {
|
||||
// Emit warning for built-in shadowing.
|
||||
if (Name.getAsIdentifierInfo() &&
|
||||
Name.getAsIdentifierInfo()->getBuiltinID())
|
||||
Diag(D->getLocation(), diag::warn_decl_shadow)
|
||||
<< Name
|
||||
<< 4 // global builtin
|
||||
<< Context.getTranslationUnitDecl();
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if not variable decl.
|
||||
NamedDecl* ShadowedDecl = R.getFoundDecl();
|
||||
if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
|
||||
return;
|
||||
|
||||
// Determine kind of declaration.
|
||||
DeclContext *DC = ShadowedDecl->getDeclContext();
|
||||
unsigned Kind;
|
||||
if (isa<RecordDecl>(DC)) {
|
||||
if (isa<FieldDecl>(ShadowedDecl))
|
||||
Kind = 3; // field
|
||||
else
|
||||
Kind = 2; // static data member
|
||||
} else if (DC->isFileContext())
|
||||
Kind = 1; // global
|
||||
else
|
||||
Kind = 0; // local
|
||||
|
||||
// Emit warning and note.
|
||||
Diag(D->getLocation(), diag::warn_decl_shadow) << Name << Kind << DC;
|
||||
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
|
||||
}
|
||||
|
||||
/// \brief Perform semantic checking on a newly-created variable
|
||||
/// declaration.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue