@@ -398,6 +398,54 @@ class NestedNameSpecifierValidatorCCC final
398
398
399
399
}
400
400
401
+ [[nodiscard]] static bool ExtendNestedNameSpecifier (Sema &S, CXXScopeSpec &SS,
402
+ const NamedDecl *ND,
403
+ SourceLocation NameLoc,
404
+ SourceLocation CCLoc) {
405
+ TypeLocBuilder TLB;
406
+ QualType T;
407
+ if (const auto *USD = dyn_cast<UsingShadowDecl>(ND)) {
408
+ T = S.Context .getUsingType (ElaboratedTypeKeyword::None, SS.getScopeRep (),
409
+ USD);
410
+ TLB.push <UsingTypeLoc>(T).set (/* ElaboratedKeywordLoc=*/ SourceLocation (),
411
+ SS.getWithLocInContext (S.Context ), NameLoc);
412
+ } else if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
413
+ T = S.Context .getTypeDeclType (ElaboratedTypeKeyword::None, SS.getScopeRep (),
414
+ TD);
415
+ switch (T->getTypeClass ()) {
416
+ case Type::Record:
417
+ case Type::InjectedClassName:
418
+ case Type::Enum: {
419
+ auto TTL = TLB.push <TagTypeLoc>(T);
420
+ TTL.setElaboratedKeywordLoc (SourceLocation ());
421
+ TTL.setQualifierLoc (SS.getWithLocInContext (S.Context ));
422
+ TTL.setNameLoc (NameLoc);
423
+ break ;
424
+ }
425
+ case Type::Typedef:
426
+ TLB.push <TypedefTypeLoc>(T).set (/* ElaboratedKeywordLoc=*/ SourceLocation (),
427
+ SS.getWithLocInContext (S.Context ),
428
+ NameLoc);
429
+ break ;
430
+ case Type::UnresolvedUsing:
431
+ TLB.push <UnresolvedUsingTypeLoc>(T).set (
432
+ /* ElaboratedKeywordLoc=*/ SourceLocation (),
433
+ SS.getWithLocInContext (S.Context ), NameLoc);
434
+ break ;
435
+ default :
436
+ assert (SS.isEmpty ());
437
+ T = S.Context .getTypeDeclType (TD);
438
+ TLB.pushTypeSpec (T).setNameLoc (NameLoc);
439
+ break ;
440
+ }
441
+ } else {
442
+ return false ;
443
+ }
444
+ SS.clear ();
445
+ SS.Make (S.Context , TLB.getTypeLocInContext (S.Context , T), CCLoc);
446
+ return true ;
447
+ }
448
+
401
449
bool Sema::BuildCXXNestedNameSpecifier (Scope *S, NestedNameSpecInfo &IdInfo,
402
450
bool EnteringContext, CXXScopeSpec &SS,
403
451
NamedDecl *ScopeLookupResult,
@@ -653,40 +701,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
653
701
if (isa<EnumDecl>(TD))
654
702
Diag (IdInfo.IdentifierLoc , diag::warn_cxx98_compat_enum_nested_name_spec);
655
703
656
- QualType T;
657
- TypeLocBuilder TLB;
658
- if (const auto *USD = dyn_cast<UsingShadowDecl>(SD)) {
659
- T = Context.getUsingType (ElaboratedTypeKeyword::None, SS.getScopeRep (),
660
- USD);
661
- TLB.push <UsingTypeLoc>(T).set (/* ElaboratedKeywordLoc=*/ SourceLocation (),
662
- SS.getWithLocInContext (Context),
663
- IdInfo.IdentifierLoc );
664
- } else if (const auto *Tag = dyn_cast<TagDecl>(TD)) {
665
- T = Context.getTagType (ElaboratedTypeKeyword::None, SS.getScopeRep (), Tag,
666
- /* OwnsTag=*/ false );
667
- auto TTL = TLB.push <TagTypeLoc>(T);
668
- TTL.setElaboratedKeywordLoc (SourceLocation ());
669
- TTL.setQualifierLoc (SS.getWithLocInContext (SemaRef.Context ));
670
- TTL.setNameLoc (IdInfo.IdentifierLoc );
671
- } else if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
672
- T = Context.getTypedefType (ElaboratedTypeKeyword::None, SS.getScopeRep (),
673
- TN);
674
- TLB.push <TypedefTypeLoc>(T).set (/* ElaboratedKeywordLoc=*/ SourceLocation (),
675
- SS.getWithLocInContext (SemaRef.Context ),
676
- IdInfo.IdentifierLoc );
677
- } else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) {
678
- T = Context.getUnresolvedUsingType (ElaboratedTypeKeyword::None,
679
- SS.getScopeRep (), UD);
680
- TLB.push <UnresolvedUsingTypeLoc>(T).set (
681
- /* ElaboratedKeywordLoc=*/ SourceLocation (),
682
- SS.getWithLocInContext (SemaRef.Context ), IdInfo.IdentifierLoc );
683
- } else {
684
- assert (SS.isEmpty ());
685
- T = Context.getTypeDeclType (TD);
686
- TLB.pushTypeSpec (T).setNameLoc (IdInfo.IdentifierLoc );
687
- }
688
- SS.clear ();
689
- SS.Make (Context, TLB.getTypeLocInContext (Context, T), IdInfo.CCLoc );
704
+ [[maybe_unused]] bool IsType = ::ExtendNestedNameSpecifier (
705
+ *this , SS, SD, IdInfo.IdentifierLoc , IdInfo.CCLoc );
706
+ assert (IsType && " unhandled declaration kind" );
690
707
return false ;
691
708
}
692
709
@@ -762,21 +779,16 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
762
779
}
763
780
764
781
if (!Found.empty ()) {
765
- if (TypeDecl *TD = Found.getAsSingle <TypeDecl>()) {
766
- QualType T;
767
- if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) {
768
- T = Context.getTypedefType (ElaboratedTypeKeyword::None,
769
- SS.getScopeRep (), TN);
770
- } else {
771
- // FIXME: Enumerate the possibilities here.
772
- assert (!isa<TagDecl>(TD));
773
- assert (SS.isEmpty ());
774
- T = Context.getTypeDeclType (TD);
775
- }
776
-
782
+ const auto *ND = Found.getAsSingle <NamedDecl>();
783
+ if (::ExtendNestedNameSpecifier (*this , SS, ND, IdInfo.IdentifierLoc ,
784
+ IdInfo.CCLoc )) {
785
+ const Type *T = SS.getScopeRep ().getAsType ();
777
786
Diag (IdInfo.IdentifierLoc , diag::err_expected_class_or_namespace)
778
- << T << getLangOpts ().CPlusPlus ;
779
- } else if (Found.getAsSingle <TemplateDecl>()) {
787
+ << QualType (T, 0 ) << getLangOpts ().CPlusPlus ;
788
+ // Recover with this type if it would be a valid nested name specifier.
789
+ return !T->getAsCanonical <TagType>();
790
+ }
791
+ if (isa<TemplateDecl>(ND)) {
780
792
ParsedType SuggestedType;
781
793
DiagnoseUnknownTypeName (IdInfo.Identifier , IdInfo.IdentifierLoc , S, &SS,
782
794
SuggestedType);
0 commit comments