@@ -139,6 +139,26 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
139139
140140} // end anonymous namespace
141141
142+ QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
143+ TypeDecl *TD, SourceLocation NameLoc) {
144+ auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
145+ auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
146+ if (DCK != DiagCtorKind::None && LookupRD && FoundRD &&
147+ FoundRD->isInjectedClassName() &&
148+ declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent()))) {
149+ Diag(NameLoc,
150+ DCK == DiagCtorKind::Typename
151+ ? diag::ext_out_of_line_qualified_id_type_names_constructor
152+ : diag::err_out_of_line_qualified_id_type_names_constructor)
153+ << TD->getIdentifier() << /*Type=*/1
154+ << 0 /*if any keyword was present, it was 'typename'*/;
155+ }
156+
157+ DiagnoseUseOfDecl(TD, NameLoc);
158+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
159+ return Context.getTypeDeclType(TD);
160+ }
161+
142162namespace {
143163enum class UnqualifiedTypeNameLookupResult {
144164 NotFound,
@@ -295,10 +315,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
295315 bool IsClassTemplateDeductionContext,
296316 ImplicitTypenameContext AllowImplicitTypename,
297317 IdentifierInfo **CorrectedII) {
318+ bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
298319 // FIXME: Consider allowing this outside C++1z mode as an extension.
299320 bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
300- getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
301- !isClassName && ! HasTrailingDot;
321+ getLangOpts().CPlusPlus17 && IsImplicitTypename &&
322+ !HasTrailingDot;
302323
303324 // Determine where we will perform name lookup.
304325 DeclContext *LookupCtx = nullptr;
@@ -322,11 +343,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
322343 // refer to a member of an unknown specialization.
323344 // In C++2a, in several contexts a 'typename' is not required. Also
324345 // allow this as an extension.
325- if (AllowImplicitTypename == ImplicitTypenameContext::No &&
326- !isClassName && !IsCtorOrDtorName)
327- return nullptr;
328- bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
329346 if (IsImplicitTypename) {
347+ if (AllowImplicitTypename == ImplicitTypenameContext::No)
348+ return nullptr;
330349 SourceLocation QualifiedLoc = SS->getRange().getBegin();
331350 if (getLangOpts().CPlusPlus20)
332351 Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
@@ -515,18 +534,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
515534 // C++ [class.qual]p2: A lookup that would find the injected-class-name
516535 // instead names the constructors of the class, except when naming a class.
517536 // This is ill-formed when we're not actually forming a ctor or dtor name.
518- auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
519- auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
520- if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD &&
521- FoundRD->isInjectedClassName() &&
522- declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
523- Diag(NameLoc, diag::err_out_of_line_qualified_id_type_names_constructor)
524- << &II << /*Type*/1;
525-
526- DiagnoseUseOfDecl(IIDecl, NameLoc);
527-
528- T = Context.getTypeDeclType(TD);
529- MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
537+ T = getTypeDeclType(LookupCtx,
538+ IsImplicitTypename ? DiagCtorKind::Implicit
539+ : DiagCtorKind::None,
540+ TD, NameLoc);
530541 } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
531542 (void)DiagnoseUseOfDecl(IDecl, NameLoc);
532543 if (!HasTrailingDot)
0 commit comments