aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-03-20 04:12:52 +0000
committerJohn McCall <rjmccall@apple.com>2010-03-20 04:12:52 +0000
commita369a95f756b6190b5611ff4118b4cabfc704dc0 (patch)
tree160bbc2ba6c28eba31902e143f5ee28b130e7fc9
parentff4417bbf993d1695567ce8672a2c19f6f48f557 (diff)
Implement -Wshadow for parameter declarations as well.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99037 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaDecl.cpp54
-rw-r--r--test/Sema/warn-shadow.c29
-rw-r--r--test/SemaCXX/warn-shadow.cpp6
4 files changed, 70 insertions, 21 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index aca4fdcb61..be0fa32257 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -784,7 +784,7 @@ public:
const LookupResult &Previous,
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
- void DiagnoseShadow(NamedDecl* D, const LookupResult& R);
+ void DiagnoseShadow(Scope *S, Declarator &D, const LookupResult& R);
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, TypeSourceInfo *TInfo,
LookupResult &Previous, bool &Redeclaration);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2e69108617..bab3d98e21 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2404,7 +2404,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
// Diagnose shadowed variables before filtering for scope.
- DiagnoseShadow(NewVD, Previous);
+ if (!D.getCXXScopeSpec().isSet())
+ DiagnoseShadow(S, D, Previous);
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
@@ -2465,46 +2466,61 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
/// 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.
+/// \param S the scope in which the shadowing name is being declared
+/// \param R the lookup of the name
///
-void Sema::DiagnoseShadow(NamedDecl* D, const LookupResult& R) {
- assert(D->getKind() == Decl::Var && "Expecting variable.");
-
+void Sema::DiagnoseShadow(Scope *S, Declarator &D,
+ const LookupResult& R) {
// Return if warning is ignored.
if (Diags.getDiagnosticLevel(diag::warn_decl_shadow) == Diagnostic::Ignored)
return;
- // Return if not local decl.
- if (!D->getDeclContext()->isFunctionOrMethod())
+ // Don't diagnose declarations at file scope. The scope might not
+ // have a DeclContext if (e.g.) we're parsing a function prototype.
+ DeclContext *NewDC = static_cast<DeclContext*>(S->getEntity());
+ if (NewDC && NewDC->isFileContext())
return;
-
- DeclarationName Name = D->getDeclName();
-
- // Return if lookup has no result.
+
+ // Only diagnose if we're shadowing an unambiguous field or variable.
if (R.getResultKind() != LookupResult::Found)
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();
+ DeclContext *OldDC = ShadowedDecl->getDeclContext();
+
+ // Only warn about certain kinds of shadowing for class members.
+ if (NewDC && NewDC->isRecord()) {
+ // In particular, don't warn about shadowing non-class members.
+ if (!OldDC->isRecord())
+ return;
+
+ // TODO: should we warn about static data members shadowing
+ // static data members from base classes?
+
+ // TODO: don't diagnose for inaccessible shadowed members.
+ // This is hard to do perfectly because we might friend the
+ // shadowing context, but that's just a false negative.
+ }
+
+ // Determine what kind of declaration we're shadowing.
unsigned Kind;
- if (isa<RecordDecl>(DC)) {
+ if (isa<RecordDecl>(OldDC)) {
if (isa<FieldDecl>(ShadowedDecl))
Kind = 3; // field
else
Kind = 2; // static data member
- } else if (DC->isFileContext())
+ } else if (OldDC->isFileContext())
Kind = 1; // global
else
Kind = 0; // local
+ DeclarationName Name = R.getLookupName();
+
// Emit warning and note.
- Diag(D->getLocation(), diag::warn_decl_shadow) << Name << Kind << DC;
+ Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC;
Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration);
}
@@ -3968,6 +3984,8 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
II = 0;
D.SetIdentifier(0, D.getIdentifierLoc());
D.setInvalidType(true);
+ } else {
+ DiagnoseShadow(S, D, R);
}
}
}
diff --git a/test/Sema/warn-shadow.c b/test/Sema/warn-shadow.c
index dacf66d592..c9a783b437 100644
--- a/test/Sema/warn-shadow.c
+++ b/test/Sema/warn-shadow.c
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -Wshadow %s
+// RUN: %clang_cc1 -verify -fsyntax-only -fblocks -Wshadow %s
-int i; // expected-note {{previous declaration is here}}
+int i; // expected-note 3 {{previous declaration is here}}
void foo() {
int pass1;
@@ -18,3 +18,28 @@ void foo() {
int sin; // okay; 'sin' has not been declared, even though it's a builtin.
}
+
+// <rdar://problem/7677531>
+void (^test1)(int) = ^(int i) { // expected-warning {{declaration shadows a variable in the global scope}} \
+ // expected-note{{previous declaration is here}}
+ {
+ int i; // expected-warning {{declaration shadows a local variable}} \
+ // expected-note{{previous declaration is here}}
+
+ (^(int i) { return i; })(i); //expected-warning {{declaration shadows a local variable}}
+ }
+};
+
+
+struct test2 {
+ int i;
+};
+
+void test3(void) {
+ struct test4 {
+ int i;
+ };
+}
+
+void test4(int i) { // expected-warning {{declaration shadows a variable in the global scope}}
+}
diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp
index c637f42ea9..509c344355 100644
--- a/test/SemaCXX/warn-shadow.cpp
+++ b/test/SemaCXX/warn-shadow.cpp
@@ -36,3 +36,9 @@ class A {
char *data; // expected-warning {{declaration shadows a static data member of 'A'}}
}
};
+
+// TODO: this should warn, <rdar://problem/5018057>
+class B : A {
+ int data;
+ static int field;
+};