Vexthil updated this revision to Diff 321930.
Vexthil added a comment.
Fixed the update by doing a full diff rather than just the additive update
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D96147/new/
https://reviews.llvm.org/D96147
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/warn-shadow.cpp
Index: clang/test/SemaCXX/warn-shadow.cpp
===================================================================
--- clang/test/SemaCXX/warn-shadow.cpp
+++ clang/test/SemaCXX/warn-shadow.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify -fsyntax-only -std=c++11 -Wshadow-all %s
+// RUN: %clang_cc1 -verify -fsyntax-only -std=c++17 -Wshadow-all %s
namespace {
int i; // expected-note {{previous declaration is here}}
@@ -265,3 +265,86 @@
PR24718_1 // Does not shadow a type.
};
};
+
+// MyTuple and std code is copied from live-bindings-test.cpp
+
+//#define USE_STD
+
+#ifndef USE_STD
+// Machinery required for custom structured bindings decomposition.
+typedef unsigned long size_t;
+
+namespace std {
+template <class T> class tuple_size;
+template <class T>
+constexpr size_t tuple_size_v = tuple_size<T>::value;
+template <size_t I, class T> class tuple_element;
+
+template <class T, T v>
+struct integral_constant {
+ static constexpr T value = v;
+ typedef T value_type;
+ typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+};
+} // namespace std
+
+struct MyTuple {
+ int a;
+ int b;
+
+ template <size_t N>
+ int get() const {
+ if constexpr (N == 0)
+ return a;
+ else if constexpr (N == 1)
+ return b;
+ }
+};
+
+namespace std {
+template <>
+struct tuple_size<MyTuple>
+ : std::integral_constant<size_t, 2> {};
+
+template <size_t N>
+struct tuple_element<N, MyTuple> {
+ using type = int;
+};
+} // namespace std
+
+MyTuple getMyTuple();
+#else
+
+#include <tuple>
+std::tuple<int, int> getMyTuple();
+#endif
+
+
+namespace structured_binding_tests {
+int x; // expected-note {{previous declaration is here}}
+int y; // expected-note {{previous declaration is here}}
+
+void test1() {
+ const auto [x, y] = getMyTuple(); // expected-warning 2 {{declaration shadows a variable in namespace 'structured_binding_tests'}}
+}
+
+void test2() {
+ int a; // expected-note {{previous declaration is here}}
+ bool b; // expected-note {{previous declaration is here}}
+ {
+ auto [a, b] = getMyTuple(); // expected-warning 2 {{declaration shadows a local variable}}
+ }
+}
+
+class A
+{
+ int m_a; // expected-note {{previous declaration is here}}
+ int m_b; // expected-note {{previous declaration is here}}
+
+ void test3() {
+ auto [m_a, m_b] = getMyTuple(); // expected-warning 2 {{declaration shadows a field of 'structured_binding_tests::A'}}
+ }
+};
+
+}; // namespace structured_binding_tests
\ No newline at end of file
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -857,17 +857,28 @@
Previous.clear();
}
+ auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
+
+ // Find the shadowed declaration before filtering for scope.
+ NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty()
+ ? getShadowedDeclaration(BD, Previous)
+ : nullptr;
+
bool ConsiderLinkage = DC->isFunctionOrMethod() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern;
FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
/*AllowInlineNamespace*/false);
+
+ // Diagnose shadowed variables if this isn't a redeclaration.
+ if (ShadowedDecl && !D.isRedeclaration())
+ CheckShadow(BD, ShadowedDecl, Previous);
+
if (!Previous.empty()) {
auto *Old = Previous.getRepresentativeDecl();
Diag(B.NameLoc, diag::err_redefinition) << B.Name;
Diag(Old->getLocation(), diag::note_previous_definition);
}
- auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
PushOnScopeChains(BD, S, true);
Bindings.push_back(BD);
ParsingInitForAutoVars.insert(BD);
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -7560,6 +7560,19 @@
return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr;
}
+/// 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 BindingDecl *D,
+ const LookupResult &R) {
+ if (!shouldWarnIfShadowedDecl(Diags, R))
+ return nullptr;
+
+ NamedDecl *ShadowedDecl = R.getFoundDecl();
+ return isa<VarDecl>(ShadowedDecl) || isa<FieldDecl>(ShadowedDecl)
+ ? ShadowedDecl
+ : nullptr;
+}
+
/// Diagnose variable or built-in function shadowing. Implements
/// -Wshadow.
///
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2598,6 +2598,8 @@
NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D,
const LookupResult &R);
NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R);
+ NamedDecl *getShadowedDeclaration(const BindingDecl *D,
+ const LookupResult &R);
void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
const LookupResult &R);
void CheckShadow(Scope *S, VarDecl *D);
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -71,7 +71,7 @@
Modified Compiler Flags
-----------------------
-- ...
+- -Wshadow now also checks for shadowed structured bindings
Removed Compiler Flags
-------------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits