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 ReturnType : DiagGroup<"return-type">;
|
||||||
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
|
def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
|
||||||
def : DiagGroup<"sequence-point">;
|
def : DiagGroup<"sequence-point">;
|
||||||
def : DiagGroup<"shadow">;
|
def Shadow : DiagGroup<"shadow">;
|
||||||
def : DiagGroup<"shorten-64-to-32">;
|
def : DiagGroup<"shorten-64-to-32">;
|
||||||
def SignCompare : DiagGroup<"sign-compare">;
|
def SignCompare : DiagGroup<"sign-compare">;
|
||||||
def : DiagGroup<"synth">;
|
def : DiagGroup<"synth">;
|
||||||
|
|
|
@ -108,6 +108,15 @@ def warn_use_out_of_scope_declaration : Warning<
|
||||||
def err_inline_non_function : Error<
|
def err_inline_non_function : Error<
|
||||||
"'inline' can only appear on functions">;
|
"'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
|
// C++ using declarations
|
||||||
def err_using_requires_qualname : Error<
|
def err_using_requires_qualname : Error<
|
||||||
"using declaration requires a qualified name">;
|
"using declaration requires a qualified name">;
|
||||||
|
|
|
@ -430,7 +430,10 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
||||||
for (; I!=End; ++I)
|
for (; I!=End; ++I)
|
||||||
QualName += *I + "::";
|
QualName += *I + "::";
|
||||||
|
|
||||||
|
if (getDeclName())
|
||||||
QualName += getNameAsString();
|
QualName += getNameAsString();
|
||||||
|
else
|
||||||
|
QualName += "<anonymous>";
|
||||||
|
|
||||||
return QualName;
|
return QualName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -778,6 +778,7 @@ public:
|
||||||
const LookupResult &Previous,
|
const LookupResult &Previous,
|
||||||
Scope *S);
|
Scope *S);
|
||||||
void DiagnoseFunctionSpecifiers(Declarator& D);
|
void DiagnoseFunctionSpecifiers(Declarator& D);
|
||||||
|
void DiagnoseShadow(NamedDecl* D, const LookupResult& R);
|
||||||
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
QualType R, TypeSourceInfo *TInfo,
|
QualType R, TypeSourceInfo *TInfo,
|
||||||
LookupResult &Previous, bool &Redeclaration);
|
LookupResult &Previous, bool &Redeclaration);
|
||||||
|
|
|
@ -2403,6 +2403,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString()));
|
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
|
// Don't consider existing declarations that are in a different
|
||||||
// scope and are out-of-semantic-context declarations (if the new
|
// scope and are out-of-semantic-context declarations (if the new
|
||||||
// declaration has linkage).
|
// declaration has linkage).
|
||||||
|
@ -2454,6 +2457,65 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
return NewVD;
|
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
|
/// \brief Perform semantic checking on a newly-created variable
|
||||||
/// declaration.
|
/// declaration.
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue