aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-03-16 21:48:18 +0000
committerJohn McCall <rjmccall@apple.com>2010-03-16 21:48:18 +0000
commit8472af4df9292e02fb25c952d25a81f3ca296252 (patch)
tree654a521276eb06bc3e717854e5a3765ca099eeaa /lib/Sema/SemaDecl.cpp
parent5d7650b71bfd8d9957bc34d36b055cb4f3e29f6c (diff)
Implement -Wshadow. Based on a patch by Mike M.!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98684 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp62
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 776f0ddf1a..5db817192f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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.
///