[clang] dc17043 - [clang] Fix missing diagnostic of declaration use when accessing TypeDecls through typename access
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 24 17:47:38 PDT 2022
Author: Matheus Izvekov
Date: 2022-10-25T02:46:35+02:00
New Revision: dc170433137aeda5e5276bd292cac12aa93fee7c
URL: https://github.com/llvm/llvm-project/commit/dc170433137aeda5e5276bd292cac12aa93fee7c
DIFF: https://github.com/llvm/llvm-project/commit/dc170433137aeda5e5276bd292cac12aa93fee7c.diff
LOG: [clang] Fix missing diagnostic of declaration use when accessing TypeDecls through typename access
Fixes GH58547.
Signed-off-by: Matheus Izvekov <mizvekov at gmail.com>
Differential Revision: https://reviews.llvm.org/D136533
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 170b27b013e6c..5b85816d97241 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -255,6 +255,9 @@ Bug Fixes
- Reject non-type template arguments formed by casting a non-zero integer
to a pointer in pre-C++17 modes, instead of treating them as null
pointers.
+- Fix missing diagnostics for uses of declarations when performing typename access,
+ such as when performing member access on a '[[deprecated]]' type alias.
+ `Issue 58547 <https://github.com/llvm/llvm-project/issues/58547>`
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e84e6b22f2817..92c89e757c9d9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2566,6 +2566,10 @@ class Sema final {
bool isSimpleTypeSpecifier(tok::TokenKind Kind) const;
+ enum class DiagCtorKind { None, Implicit, Typename };
+ QualType getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
+ TypeDecl *TD, SourceLocation NameLoc);
+
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS = nullptr,
bool isClassName = false, bool HasTrailingDot = false,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 19bd670e791bc..e0605fea8e27f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -169,6 +169,26 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
return false;
}
+QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
+ TypeDecl *TD, SourceLocation NameLoc) {
+ auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
+ auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
+ if (DCK != DiagCtorKind::None && LookupRD && FoundRD &&
+ FoundRD->isInjectedClassName() &&
+ declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent()))) {
+ Diag(NameLoc,
+ DCK == DiagCtorKind::Typename
+ ? diag::ext_out_of_line_qualified_id_type_names_constructor
+ : diag::err_out_of_line_qualified_id_type_names_constructor)
+ << TD->getIdentifier() << /*Type*/ 1
+ << 0 /*if any keyword was present, it was 'typename'*/;
+ }
+
+ DiagnoseUseOfDecl(TD, NameLoc);
+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
+ return Context.getTypeDeclType(TD);
+}
+
namespace {
enum class UnqualifiedTypeNameLookupResult {
NotFound,
@@ -332,10 +352,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
bool IsClassTemplateDeductionContext,
ImplicitTypenameContext AllowImplicitTypename,
IdentifierInfo **CorrectedII) {
+ bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
// FIXME: Consider allowing this outside C++1z mode as an extension.
bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
- getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
- !isClassName && !HasTrailingDot;
+ getLangOpts().CPlusPlus17 && IsImplicitTypename &&
+ !HasTrailingDot;
// Determine where we will perform name lookup.
DeclContext *LookupCtx = nullptr;
@@ -359,11 +380,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
// refer to a member of an unknown specialization.
// In C++2a, in several contexts a 'typename' is not required. Also
// allow this as an extension.
- if (AllowImplicitTypename == ImplicitTypenameContext::No &&
- !isClassName && !IsCtorOrDtorName)
- return nullptr;
- bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
if (IsImplicitTypename) {
+ if (AllowImplicitTypename == ImplicitTypenameContext::No)
+ return nullptr;
SourceLocation QualifiedLoc = SS->getRange().getBegin();
if (getLangOpts().CPlusPlus20)
Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
@@ -537,18 +556,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
// C++ [class.qual]p2: A lookup that would find the injected-class-name
// instead names the constructors of the class, except when naming a class.
// This is ill-formed when we're not actually forming a ctor or dtor name.
- auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
- auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
- if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD &&
- FoundRD->isInjectedClassName() &&
- declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
- Diag(NameLoc, diag::err_out_of_line_qualified_id_type_names_constructor)
- << &II << /*Type*/1;
-
- DiagnoseUseOfDecl(IIDecl, NameLoc);
-
- T = Context.getTypeDeclType(TD);
- MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
+ T = getTypeDeclType(LookupCtx,
+ IsImplicitTypename ? DiagCtorKind::Implicit
+ : DiagCtorKind::None,
+ TD, NameLoc);
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
if (!HasTrailingDot)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7a30a736bff9f..84f06bceeea88 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10963,20 +10963,14 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
//
// FIXME: That's not strictly true: mem-initializer-id lookup does not
// ignore functions, but that appears to be an oversight.
- auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(Ctx);
- auto *FoundRD = dyn_cast<CXXRecordDecl>(Type);
- if (Keyword == ETK_Typename && LookupRD && FoundRD &&
- FoundRD->isInjectedClassName() &&
- declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
- Diag(IILoc, diag::ext_out_of_line_qualified_id_type_names_constructor)
- << &II << 1 << 0 /*'typename' keyword used*/;
-
+ QualType T = getTypeDeclType(
+ Ctx,
+ Keyword == ETK_Typename ? DiagCtorKind::Typename : DiagCtorKind::None,
+ Type, IILoc);
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
- MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
- return Context.getElaboratedType(Keyword,
- QualifierLoc.getNestedNameSpecifier(),
- Context.getTypeDeclType(Type));
+ return Context.getElaboratedType(
+ Keyword, QualifierLoc.getNestedNameSpecifier(), T);
}
// C++ [dcl.type.simple]p2:
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
index 58c7c0cfac8bf..26738583da506 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
@@ -58,3 +58,17 @@ template <typename T>
FunS2 f;// No warning, entire function is deprecated, so usage here should be fine.
}
+
+namespace GH58547 {
+struct A {
+ using ta [[deprecated]] = int; // expected-note 2{{marked deprecated here}}
+};
+
+using t1 = typename A::ta; // expected-warning {{'ta' is deprecated}}
+
+template <class B1> struct B {
+ using tb = typename B1::ta; // expected-warning {{'ta' is deprecated}}
+};
+
+template struct B<A>; // expected-note {{requested here}}
+} // namespace GH58547
diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp
index efb57b6e496ef..40fdaf8219deb 100644
--- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp
+++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp
@@ -13,7 +13,8 @@
// Deprecated in C++17
-// UNSUPPORTED: c++03, c++11, c++14
+// FIXME: Remove 'clang-16' from UNSUPPORTED by 2022-11-05 (bugfix D136533).
+// UNSUPPORTED: c++03, c++11, c++14, clang-16
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS
@@ -23,7 +24,11 @@
int main(int, char**)
{
std::allocator<int> a;
- TEST_IGNORE_NODISCARD a.allocate(3, nullptr); // expected-warning {{'allocate' is deprecated}}
-
+ TEST_IGNORE_NODISCARD a.allocate(3, nullptr);
+ // expected-warning at -1 {{'allocate' is deprecated}}
+#if defined(TEST_CLANG_VER) && TEST_CLANG_VER >= 1600
+ // expected-warning@*:* {{'pointer' is deprecated}}
+ // expected-warning@*:* {{'const_pointer' is deprecated}}
+#endif
return 0;
}
More information about the cfe-commits
mailing list