diff options
Diffstat (limited to 'clang/lib/Sema/SemaCXXScopeSpec.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 115 |
1 files changed, 62 insertions, 53 deletions
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 45de8ff3ba26..437c69aa1587 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -133,11 +133,8 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, return const_cast<NamespaceDecl *>( NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); - case NestedNameSpecifier::Kind::Type: { - auto *TD = NNS.getAsType()->getAsTagDecl(); - assert(TD && "Non-tag type in nested-name-specifier"); - return TD; - } + case NestedNameSpecifier::Kind::Type: + return NNS.getAsType()->castAsTagDecl(); case NestedNameSpecifier::Kind::Global: return Context.getTranslationUnitDecl(); @@ -401,6 +398,54 @@ public: } +[[nodiscard]] static bool ExtendNestedNameSpecifier(Sema &S, CXXScopeSpec &SS, + const NamedDecl *ND, + SourceLocation NameLoc, + SourceLocation CCLoc) { + TypeLocBuilder TLB; + QualType T; + if (const auto *USD = dyn_cast<UsingShadowDecl>(ND)) { + T = S.Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + USD); + TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(S.Context), NameLoc); + } else if (const auto *TD = dyn_cast<TypeDecl>(ND)) { + T = S.Context.getTypeDeclType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + TD); + switch (T->getTypeClass()) { + case Type::Record: + case Type::InjectedClassName: + case Type::Enum: { + auto TTL = TLB.push<TagTypeLoc>(T); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(SS.getWithLocInContext(S.Context)); + TTL.setNameLoc(NameLoc); + break; + } + case Type::Typedef: + TLB.push<TypedefTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(S.Context), + NameLoc); + break; + case Type::UnresolvedUsing: + TLB.push<UnresolvedUsingTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(S.Context), NameLoc); + break; + default: + assert(SS.isEmpty()); + T = S.Context.getTypeDeclType(TD); + TLB.pushTypeSpec(T).setNameLoc(NameLoc); + break; + } + } else { + return false; + } + SS.clear(); + SS.Make(S.Context, TLB.getTypeLocInContext(S.Context, T), CCLoc); + return true; +} + bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, @@ -656,40 +701,9 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, if (isa<EnumDecl>(TD)) Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); - QualType T; - TypeLocBuilder TLB; - if (const auto *USD = dyn_cast<UsingShadowDecl>(SD)) { - T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(), - USD); - TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), - SS.getWithLocInContext(Context), - IdInfo.IdentifierLoc); - } else if (const auto *Tag = dyn_cast<TagDecl>(TD)) { - T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), Tag, - /*OwnsTag=*/false); - auto TTL = TLB.push<TagTypeLoc>(T); - TTL.setElaboratedKeywordLoc(SourceLocation()); - TTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); - TTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) { - T = Context.getTypedefType(ElaboratedTypeKeyword::None, SS.getScopeRep(), - TN); - TLB.push<TypedefTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), - SS.getWithLocInContext(SemaRef.Context), - IdInfo.IdentifierLoc); - } else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) { - T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None, - SS.getScopeRep(), UD); - TLB.push<UnresolvedUsingTypeLoc>(T).set( - /*ElaboratedKeywordLoc=*/SourceLocation(), - SS.getWithLocInContext(SemaRef.Context), IdInfo.IdentifierLoc); - } else { - assert(SS.isEmpty()); - T = Context.getTypeDeclType(TD); - TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc); - } - SS.clear(); - SS.Make(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc); + [[maybe_unused]] bool IsType = ::ExtendNestedNameSpecifier( + *this, SS, SD, IdInfo.IdentifierLoc, IdInfo.CCLoc); + assert(IsType && "unhandled declaration kind"); return false; } @@ -765,21 +779,16 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, } if (!Found.empty()) { - if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) { - QualType T; - if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) { - T = Context.getTypedefType(ElaboratedTypeKeyword::None, - SS.getScopeRep(), TN); - } else { - // FIXME: Enumerate the possibilities here. - assert(!isa<TagDecl>(TD)); - assert(SS.isEmpty()); - T = Context.getTypeDeclType(TD); - } - + const auto *ND = Found.getAsSingle<NamedDecl>(); + if (::ExtendNestedNameSpecifier(*this, SS, ND, IdInfo.IdentifierLoc, + IdInfo.CCLoc)) { + const Type *T = SS.getScopeRep().getAsType(); Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) - << T << getLangOpts().CPlusPlus; - } else if (Found.getAsSingle<TemplateDecl>()) { + << QualType(T, 0) << getLangOpts().CPlusPlus; + // Recover with this type if it would be a valid nested name specifier. + return !T->getAsCanonical<TagType>(); + } + if (isa<TemplateDecl>(ND)) { ParsedType SuggestedType; DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS, SuggestedType); |
