@@ -137,6 +137,26 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
137137
138138} // end anonymous namespace
139139
140+ QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK,
141+ TypeDecl *TD, SourceLocation NameLoc) {
142+ auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
143+ auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
144+ if (DCK != DiagCtorKind::None && LookupRD && FoundRD &&
145+ FoundRD->isInjectedClassName() &&
146+ declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent()))) {
147+ Diag(NameLoc,
148+ DCK == DiagCtorKind::Typename
149+ ? diag::ext_out_of_line_qualified_id_type_names_constructor
150+ : diag::err_out_of_line_qualified_id_type_names_constructor)
151+ << TD->getIdentifier() << /*Type=*/1
152+ << 0 /*if any keyword was present, it was 'typename'*/;
153+ }
154+
155+ DiagnoseUseOfDecl(TD, NameLoc);
156+ MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
157+ return Context.getTypeDeclType(TD);
158+ }
159+
140160namespace {
141161enum class UnqualifiedTypeNameLookupResult {
142162 NotFound,
@@ -293,10 +313,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
293313 bool IsClassTemplateDeductionContext,
294314 ImplicitTypenameContext AllowImplicitTypename,
295315 IdentifierInfo **CorrectedII) {
316+ bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
296317 // FIXME: Consider allowing this outside C++1z mode as an extension.
297318 bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
298- getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
299- !isClassName && ! HasTrailingDot;
319+ getLangOpts().CPlusPlus17 && IsImplicitTypename &&
320+ !HasTrailingDot;
300321
301322 // Determine where we will perform name lookup.
302323 DeclContext *LookupCtx = nullptr;
@@ -320,11 +341,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
320341 // refer to a member of an unknown specialization.
321342 // In C++2a, in several contexts a 'typename' is not required. Also
322343 // allow this as an extension.
323- if (AllowImplicitTypename == ImplicitTypenameContext::No &&
324- !isClassName && !IsCtorOrDtorName)
325- return nullptr;
326- bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
327344 if (IsImplicitTypename) {
345+ if (AllowImplicitTypename == ImplicitTypenameContext::No)
346+ return nullptr;
328347 SourceLocation QualifiedLoc = SS->getRange().getBegin();
329348 if (getLangOpts().CPlusPlus20)
330349 Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
@@ -513,18 +532,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
513532 // C++ [class.qual]p2: A lookup that would find the injected-class-name
514533 // instead names the constructors of the class, except when naming a class.
515534 // This is ill-formed when we're not actually forming a ctor or dtor name.
516- auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
517- auto *FoundRD = dyn_cast<CXXRecordDecl>(TD);
518- if (!isClassName && !IsCtorOrDtorName && LookupRD && FoundRD &&
519- FoundRD->isInjectedClassName() &&
520- declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
521- Diag(NameLoc, diag::err_out_of_line_qualified_id_type_names_constructor)
522- << &II << /*Type*/1;
523-
524- DiagnoseUseOfDecl(IIDecl, NameLoc);
525-
526- T = Context.getTypeDeclType(TD);
527- MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
535+ T = getTypeDeclType(LookupCtx,
536+ IsImplicitTypename ? DiagCtorKind::Implicit
537+ : DiagCtorKind::None,
538+ TD, NameLoc);
528539 } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
529540 (void)DiagnoseUseOfDecl(IDecl, NameLoc);
530541 if (!HasTrailingDot)
0 commit comments