@@ -137,6 +137,26 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback {
137
137
138
138
} // end anonymous namespace
139
139
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
+
140
160
namespace {
141
161
enum class UnqualifiedTypeNameLookupResult {
142
162
NotFound,
@@ -293,10 +313,11 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
293
313
bool IsClassTemplateDeductionContext,
294
314
ImplicitTypenameContext AllowImplicitTypename,
295
315
IdentifierInfo **CorrectedII) {
316
+ bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
296
317
// FIXME: Consider allowing this outside C++1z mode as an extension.
297
318
bool AllowDeducedTemplate = IsClassTemplateDeductionContext &&
298
- getLangOpts().CPlusPlus17 && !IsCtorOrDtorName &&
299
- !isClassName && ! HasTrailingDot;
319
+ getLangOpts().CPlusPlus17 && IsImplicitTypename &&
320
+ !HasTrailingDot;
300
321
301
322
// Determine where we will perform name lookup.
302
323
DeclContext *LookupCtx = nullptr;
@@ -320,11 +341,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
320
341
// refer to a member of an unknown specialization.
321
342
// In C++2a, in several contexts a 'typename' is not required. Also
322
343
// allow this as an extension.
323
- if (AllowImplicitTypename == ImplicitTypenameContext::No &&
324
- !isClassName && !IsCtorOrDtorName)
325
- return nullptr;
326
- bool IsImplicitTypename = !isClassName && !IsCtorOrDtorName;
327
344
if (IsImplicitTypename) {
345
+ if (AllowImplicitTypename == ImplicitTypenameContext::No)
346
+ return nullptr;
328
347
SourceLocation QualifiedLoc = SS->getRange().getBegin();
329
348
if (getLangOpts().CPlusPlus20)
330
349
Diag(QualifiedLoc, diag::warn_cxx17_compat_implicit_typename);
@@ -513,18 +532,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
513
532
// C++ [class.qual]p2: A lookup that would find the injected-class-name
514
533
// instead names the constructors of the class, except when naming a class.
515
534
// 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);
528
539
} else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
529
540
(void)DiagnoseUseOfDecl(IDecl, NameLoc);
530
541
if (!HasTrailingDot)
0 commit comments