mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 13:56:06 +00:00
Revert "[clang] Fix missing diagnostic of declaration use when accessing TypeDecls through typename access (#129681)"
This caused incorrect -Wunguarded-availability warnings. See comment on the pull request. > We were missing a call to DiagnoseUseOfDecl when performing typename > access. > > This refactors the code so that TypeDecl lookups funnel through a helper > which performs all the necessary checks, removing some related > duplication on the way. > > Fixes #58547 > > Differential Revision: https://reviews.llvm.org/D136533 This reverts commit 4c4fd6b03149348cf11af245ad2603d24144a9d5.
This commit is contained in:
parent
848ba3854c
commit
28fa1fcf55
@ -35,9 +35,6 @@ Potentially Breaking Changes
|
|||||||
============================
|
============================
|
||||||
|
|
||||||
- The Objective-C ARC migrator (ARCMigrate) has been removed.
|
- The Objective-C ARC migrator (ARCMigrate) has been removed.
|
||||||
- Fix missing diagnostics for uses of declarations when performing typename access,
|
|
||||||
such as when performing member access on a '[[deprecated]]' type alias.
|
|
||||||
(#GH58547)
|
|
||||||
|
|
||||||
C/C++ Language Potentially Breaking Changes
|
C/C++ Language Potentially Breaking Changes
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
@ -3168,13 +3168,6 @@ public:
|
|||||||
|
|
||||||
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
|
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
|
||||||
|
|
||||||
enum class DiagCtorKind { None, Implicit, Typename };
|
|
||||||
/// Returns the TypeDeclType for the given type declaration,
|
|
||||||
/// as ASTContext::getTypeDeclType would, but
|
|
||||||
/// performs the required semantic checks for name lookup of said entity.
|
|
||||||
QualType getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
|
|
||||||
TypeDecl *TD, SourceLocation NameLoc);
|
|
||||||
|
|
||||||
/// If the identifier refers to a type name within this scope,
|
/// If the identifier refers to a type name within this scope,
|
||||||
/// return the declaration of that type.
|
/// return the declaration of that type.
|
||||||
///
|
///
|
||||||
|
@ -139,26 +139,6 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
|
|||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
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 {
|
namespace {
|
||||||
enum class UnqualifiedTypeNameLookupResult {
|
enum class UnqualifiedTypeNameLookupResult {
|
||||||
NotFound,
|
NotFound,
|
||||||
@ -315,11 +295,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
|||||||
bool IsClassTemplateDeductionContext,
|
bool IsClassTemplateDeductionContext,
|
||||||
ImplicitTypenameContext AllowImplicitTypename,
|
ImplicitTypenameContext AllowImplicitTypename,
|
||||||
IdentifierInfo **CorrectedII) {
|
IdentifierInfo **CorrectedII) {
|
||||||
bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
|
|
||||||
// FIXME: Consider allowing this outside C++1z mode as an extension.
|
// FIXME: Consider allowing this outside C++1z mode as an extension.
|
||||||
bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
|
bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
|
||||||
getLangOpts().CPlusPlus17 && IsImplicitTypename &&
|
getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
|
||||||
!HasTrailingDot;
|
!isClassName && !HasTrailingDot;
|
||||||
|
|
||||||
// Determine where we will perform name lookup.
|
// Determine where we will perform name lookup.
|
||||||
DeclContext *LookupCtx = nullptr;
|
DeclContext *LookupCtx = nullptr;
|
||||||
@ -343,9 +322,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
|||||||
// refer to a member of an unknown specialization.
|
// refer to a member of an unknown specialization.
|
||||||
// In C++2a, in several contexts a 'typename' is not required. Also
|
// In C++2a, in several contexts a 'typename' is not required. Also
|
||||||
// allow this as an extension.
|
// allow this as an extension.
|
||||||
|
if (AllowImplicitTypename == ImplicitTypenameContext::No &&
|
||||||
|
!isClassName && !IsCtorOrDtorName)
|
||||||
|
return nullptr;
|
||||||
|
bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
|
||||||
if (IsImplicitTypename) {
|
if (IsImplicitTypename) {
|
||||||
if (AllowImplicitTypename == ImplicitTypenameContext::No)
|
|
||||||
return nullptr;
|
|
||||||
SourceLocation QualifiedLoc = SS->getRange().getBegin();
|
SourceLocation QualifiedLoc = SS->getRange().getBegin();
|
||||||
if (getLangOpts().CPlusPlus20)
|
if (getLangOpts().CPlusPlus20)
|
||||||
Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
|
Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
|
||||||
@ -534,10 +515,18 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
|
|||||||
// C++ [class.qual]p2: A lookup that would find the injected-class-name
|
// 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.
|
// 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.
|
// This is ill-formed when we're not actually forming a ctor or dtor name.
|
||||||
T = getTypeDeclType(LookupCtx,
|
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
|
||||||
IsImplicitTypename ? DiagCtorKind::Implicit
|
auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
|
||||||
: DiagCtorKind::None,
|
if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD &&
|
||||||
TD, NameLoc);
|
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);
|
||||||
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
|
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
|
||||||
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
|
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
|
||||||
if (!HasTrailingDot)
|
if (!HasTrailingDot)
|
||||||
|
@ -10918,15 +10918,20 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
|
|||||||
//
|
//
|
||||||
// FIXME: That's not strictly true: mem-initializer-id lookup does not
|
// FIXME: That's not strictly true: mem-initializer-id lookup does not
|
||||||
// ignore functions, but that appears to be an oversight.
|
// ignore functions, but that appears to be an oversight.
|
||||||
QualType T = getTypeDeclType(Ctx,
|
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(Ctx);
|
||||||
Keyword == ElaboratedTypeKeyword::Typename
|
auto *FoundRD = dyn_cast<CXXRecordDecl>(Type);
|
||||||
? DiagCtorKind::Typename
|
if (Keyword == ElaboratedTypeKeyword::Typename && LookupRD && FoundRD &&
|
||||||
: DiagCtorKind::None,
|
FoundRD->isInjectedClassName() &&
|
||||||
Type, IILoc);
|
declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
|
||||||
|
Diag(IILoc, diag::ext_out_of_line_qualified_id_type_names_constructor)
|
||||||
|
<< &II << 1 << 0 /*'typename' keyword used*/;
|
||||||
|
|
||||||
// We found a type. Build an ElaboratedType, since the
|
// We found a type. Build an ElaboratedType, since the
|
||||||
// typename-specifier was just sugar.
|
// typename-specifier was just sugar.
|
||||||
return Context.getElaboratedType(
|
MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
|
||||||
Keyword, QualifierLoc.getNestedNameSpecifier(), T);
|
return Context.getElaboratedType(Keyword,
|
||||||
|
QualifierLoc.getNestedNameSpecifier(),
|
||||||
|
Context.getTypeDeclType(Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ [dcl.type.simple]p2:
|
// C++ [dcl.type.simple]p2:
|
||||||
|
@ -58,17 +58,3 @@ template <typename T>
|
|||||||
FunS2 f;// No warning, entire function is deprecated, so usage here should be fine.
|
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
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user