[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 llvm-svn: 291564
This commit is contained in:
parent
00b3f3c11b
commit
0e613727ee
|
@ -1709,7 +1709,8 @@ public:
|
||||||
|
|
||||||
static bool adjustContextForLocalExternDecl(DeclContext *&DC);
|
static bool adjustContextForLocalExternDecl(DeclContext *&DC);
|
||||||
void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
|
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);
|
void CheckShadow(Scope *S, VarDecl *D);
|
||||||
|
|
||||||
/// Warn if 'E', which is an expression that is about to be modified, refers
|
/// Warn if 'E', which is an expression that is about to be modified, refers
|
||||||
|
|
|
@ -6426,9 +6426,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnose shadowed variables before filtering for scope.
|
// Find the shadowed declaration before filtering for scope.
|
||||||
if (D.getCXXScopeSpec().isEmpty())
|
NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()
|
||||||
CheckShadow(S, NewVD, Previous);
|
? getShadowedDeclaration(NewVD, Previous)
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -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);
|
ProcessPragmaWeak(S, NewVD);
|
||||||
|
|
||||||
// If this is the first declaration of an extern C variable, update
|
// If this is the first declaration of an extern C variable, update
|
||||||
|
@ -6596,34 +6601,41 @@ static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI,
|
||||||
return SourceLocation();
|
return SourceLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \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 nullptr;
|
||||||
|
|
||||||
|
// Don't diagnose declarations at file scope.
|
||||||
|
if (D->hasGlobalStorage())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// Only diagnose if we're shadowing an unambiguous field or variable.
|
||||||
|
if (R.getResultKind() != LookupResult::Found)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
NamedDecl *ShadowedDecl = R.getFoundDecl();
|
||||||
|
return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl)
|
||||||
|
? ShadowedDecl
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Diagnose variable or built-in function shadowing. Implements
|
/// \brief Diagnose variable or built-in function shadowing. Implements
|
||||||
/// -Wshadow.
|
/// -Wshadow.
|
||||||
///
|
///
|
||||||
/// This method is called whenever a VarDecl is added to a "useful"
|
/// This method is called whenever a VarDecl is added to a "useful"
|
||||||
/// scope.
|
/// scope.
|
||||||
///
|
///
|
||||||
/// \param S the scope in which the shadowing name is being declared
|
/// \param ShadowedDecl the declaration that is shadowed by the given variable
|
||||||
/// \param R the lookup of the name
|
/// \param R the lookup of the name
|
||||||
///
|
///
|
||||||
void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) {
|
void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl,
|
||||||
// Return if warning is ignored.
|
const LookupResult &R) {
|
||||||
if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Don't diagnose declarations at file scope.
|
|
||||||
if (D->hasGlobalStorage())
|
|
||||||
return;
|
|
||||||
|
|
||||||
DeclContext *NewDC = D->getDeclContext();
|
DeclContext *NewDC = D->getDeclContext();
|
||||||
|
|
||||||
// Only diagnose if we're shadowing an unambiguous field or variable.
|
|
||||||
if (R.getResultKind() != LookupResult::Found)
|
|
||||||
return;
|
|
||||||
|
|
||||||
NamedDecl* ShadowedDecl = R.getFoundDecl();
|
|
||||||
if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
|
if (FieldDecl *FD = dyn_cast<FieldDecl>(ShadowedDecl)) {
|
||||||
// Fields are not shadowed by variables in C++ static methods.
|
// Fields are not shadowed by variables in C++ static methods.
|
||||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
|
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC))
|
||||||
|
@ -6733,7 +6745,8 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
|
||||||
LookupResult R(*this, D->getDeclName(), D->getLocation(),
|
LookupResult R(*this, D->getDeclName(), D->getLocation(),
|
||||||
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
||||||
LookupName(R, S);
|
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
|
/// Check if 'E', which is an expression that is about to be modified, refers
|
||||||
|
|
|
@ -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 g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
|
||||||
(auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
|
(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'}}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -97,3 +97,13 @@ void rdar8883302() {
|
||||||
void test8() {
|
void test8() {
|
||||||
int bob; // expected-warning {{declaration shadows a variable in the global namespace}}
|
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'}}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue