summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-01-10 14:41:13 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-01-10 14:41:13 +0000
commita41b64721d4be78870711cbb7b5af156a9e1f4ad (patch)
tree9c99b043456496fb3dff7864795ae4209831c27d
parent54f39e116b9602b7d947e5bfd25b153f4c70e6be (diff)
[Sema] Avoid -Wshadow warning when a "redefinition of " error is presented
This commit ensures that clang avoids the redundant -Wshadow warning for variables that already get a "redefinition of " error. rdar://29067894 Differential Revision: https://reviews.llvm.org/D28350 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291564 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDecl.cpp57
-rw-r--r--test/SemaCXX/warn-shadow-in-lambdas.cpp8
-rw-r--r--test/SemaCXX/warn-shadow.cpp10
4 files changed, 55 insertions, 23 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index d5e4b069f8..8867b1212d 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1709,7 +1709,8 @@ public:
static bool adjustContextForLocalExternDecl(DeclContext *&DC);
void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
- void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
+ NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R);
+ void CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R);
void CheckShadow(Scope *S, VarDecl *D);
/// Warn if 'E', which is an expression that is about to be modified, refers
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7cb3adb8d3..cdc9882d14 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6426,9 +6426,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
- // Diagnose shadowed variables before filtering for scope.
- if (D.getCXXScopeSpec().isEmpty())
- CheckShadow(S, NewVD, Previous);
+ // Find the shadowed declaration before filtering for scope.
+ NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()
+ ? getShadowedDeclaration(NewVD, Previous)
+ : nullptr;
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
@@ -6523,6 +6524,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
+ // Diagnose shadowed variables iff this isn't a redeclaration.
+ if (ShadowedDecl && !D.isRedeclaration())
+ CheckShadow(NewVD, ShadowedDecl, Previous);
+
ProcessPragmaWeak(S, NewVD);
// If this is the first declaration of an extern C variable, update
@@ -6596,33 +6601,40 @@ static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
return SourceLocation();
}
-/// \brief Diagnose variable or built-in function shadowing. Implements
-/// -Wshadow.
-///
-/// This method is called whenever a VarDecl is added to a "useful"
-/// scope.
-///
-/// \param S the scope in which the shadowing name is being declared
-/// \param R the lookup of the name
-///
-void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
+/// \brief Return the declaration shadowed by the given variable \p D, or null
+/// if it doesn't shadow any declaration or shadowing warnings are disabled.
+NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D,
+ const LookupResult &R) {
// Return if warning is ignored.
if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()))
- return;
+ return nullptr;
// Don't diagnose declarations at file scope.
if (D->hasGlobalStorage())
- return;
-
- DeclContext *NewDC = D->getDeclContext();
+ return nullptr;
// Only diagnose if we're shadowing an unambiguous field or variable.
if (R.getResultKind() != LookupResult::Found)
- return;
+ return nullptr;
- NamedDecl* ShadowedDecl = R.getFoundDecl();
- if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
- return;
+ NamedDecl *ShadowedDecl = R.getFoundDecl();
+ return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl)
+ ? ShadowedDecl
+ : nullptr;
+}
+
+/// \brief Diagnose variable or built-in function shadowing. Implements
+/// -Wshadow.
+///
+/// This method is called whenever a VarDecl is added to a "useful"
+/// scope.
+///
+/// \param ShadowedDecl the declaration that is shadowed by the given variable
+/// \param R the lookup of the name
+///
+void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl,
+ const LookupResult &R) {
+ DeclContext *NewDC = D->getDeclContext();
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
// Fields are not shadowed by variables in C++ static methods.
@@ -6733,7 +6745,8 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
LookupResult R(*this, D->getDeclName(), D->getLocation(),
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
LookupName(R, S);
- CheckShadow(S, D, R);
+ if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R))
+ CheckShadow(D, ShadowedDecl, R);
}
/// Check if 'E', which is an expression that is about to be modified, refers
diff --git a/test/SemaCXX/warn-shadow-in-lambdas.cpp b/test/SemaCXX/warn-shadow-in-lambdas.cpp
index 575664482d..b0dcd122a5 100644
--- a/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ b/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -137,3 +137,11 @@ void foo(int param) { // expected-note 1+ {{previous declaration is here}}
auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
(auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
}
+
+void avoidWarningWhenRedefining() {
+ int a = 1;
+ auto l = [b = a] { // expected-note {{previous definition is here}}
+ // Don't warn on redefinitions.
+ int b = 0; // expected-error {{redefinition of 'b'}}
+ };
+}
diff --git a/test/SemaCXX/warn-shadow.cpp b/test/SemaCXX/warn-shadow.cpp
index 9d68fe7c47..1316b6dd88 100644
--- a/test/SemaCXX/warn-shadow.cpp
+++ b/test/SemaCXX/warn-shadow.cpp
@@ -97,3 +97,13 @@ void rdar8883302() {
void test8() {
int bob; // expected-warning {{declaration shadows a variable in the global namespace}}
}
+
+namespace rdar29067894 {
+
+void avoidWarningWhenRedefining(int b) { // expected-note {{previous definition is here}}
+ int a = 0; // expected-note {{previous definition is here}}
+ int a = 1; // expected-error {{redefinition of 'a'}}
+ int b = 2; // expected-error {{redefinition of 'b'}}
+}
+
+}