diff options
author | John McCall <rjmccall@apple.com> | 2010-03-16 21:48:18 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-03-16 21:48:18 +0000 |
commit | 8472af4df9292e02fb25c952d25a81f3ca296252 (patch) | |
tree | 654a521276eb06bc3e717854e5a3765ca099eeaa /lib/Sema/SemaDecl.cpp | |
parent | 5d7650b71bfd8d9957bc34d36b055cb4f3e29f6c (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.cpp | 62 |
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. /// |