diff options
Diffstat (limited to 'clang/lib/Sema')
52 files changed, 2829 insertions, 2639 deletions
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index fdb6302..dd418f7 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -227,14 +227,11 @@ static bool hasRecursiveCallInPath(const FunctionDecl *FD, CFGBlock &Block) { // Skip function calls which are qualified with a templated class. if (const DeclRefExpr *DRE = - dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) { - if (NestedNameSpecifier *NNS = DRE->getQualifier()) { - if (NNS->getKind() == NestedNameSpecifier::TypeSpec && - isa<TemplateSpecializationType>(NNS->getAsType())) { + dyn_cast<DeclRefExpr>(CE->getCallee()->IgnoreParenImpCasts())) + if (NestedNameSpecifier NNS = DRE->getQualifier(); + NNS.getKind() == NestedNameSpecifier::Kind::Type) + if (isa_and_nonnull<TemplateSpecializationType>(NNS.getAsType())) continue; - } - } - } const CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(CE); if (!MCE || isa<CXXThisExpr>(MCE->getImplicitObjectArgument()) || diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index f0f1d66..8756ce5 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -48,9 +48,9 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } -void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL, - SourceLocation ColonColonLoc) { - Builder.Extend(Context, TL, ColonColonLoc); +void CXXScopeSpec::Make(ASTContext &Context, TypeLoc TL, + SourceLocation ColonColonLoc) { + Builder.Make(Context, TL, ColonColonLoc); if (Range.getBegin().isInvalid()) Range.setBegin(TL.getBeginLoc()); Range.setEnd(ColonColonLoc); @@ -59,19 +59,6 @@ void CXXScopeSpec::Extend(ASTContext &Context, TypeLoc TL, "NestedNameSpecifierLoc range computation incorrect"); } -void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, - SourceLocation IdentifierLoc, - SourceLocation ColonColonLoc) { - Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); - - if (Range.getBegin().isInvalid()) - Range.setBegin(IdentifierLoc); - Range.setEnd(ColonColonLoc); - - assert(Range == Builder.getSourceRange() && - "NestedNameSpecifierLoc range computation incorrect"); -} - void CXXScopeSpec::Extend(ASTContext &Context, NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { @@ -95,10 +82,10 @@ void CXXScopeSpec::MakeGlobal(ASTContext &Context, "NestedNameSpecifierLoc range computation incorrect"); } -void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD, - SourceLocation SuperLoc, - SourceLocation ColonColonLoc) { - Builder.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); +void CXXScopeSpec::MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc) { + Builder.MakeMicrosoftSuper(Context, RD, SuperLoc, ColonColonLoc); Range.setBegin(SuperLoc); Range.setEnd(ColonColonLoc); @@ -108,7 +95,7 @@ void CXXScopeSpec::MakeSuper(ASTContext &Context, CXXRecordDecl *RD, } void CXXScopeSpec::MakeTrivial(ASTContext &Context, - NestedNameSpecifier *Qualifier, SourceRange R) { + NestedNameSpecifier Qualifier, SourceRange R) { Builder.MakeTrivial(Context, Qualifier, R); Range = R; } diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 87f9ae0..806800c 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -313,9 +313,6 @@ TemplateParameterListBuilder::finalizeTemplateArgs(ConceptDecl *CD) { Builder.Record->getDeclContext()->addDecl(Builder.Template); Params.clear(); - QualType T = Builder.Template->getInjectedClassNameSpecialization(); - T = AST.getInjectedClassNameType(Builder.Record, T); - return Builder; } @@ -351,7 +348,7 @@ BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, ASTContext &AST = DB.SemaRef.getASTContext(); if (IsCtor) { Name = AST.DeclarationNames.getCXXConstructorName( - DB.Record->getTypeForDecl()->getCanonicalTypeUnqualified()); + AST.getCanonicalTagType(DB.Record)); } else { const IdentifierInfo &II = AST.Idents.get(NameStr, tok::TokenKind::identifier); @@ -553,9 +550,9 @@ BuiltinTypeDeclBuilder::BuiltinTypeDeclBuilder(Sema &SemaRef, return; } - Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace, - SourceLocation(), SourceLocation(), &II, - PrevDecl, true); + Record = + CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace, + SourceLocation(), SourceLocation(), &II, PrevDecl); Record->setImplicit(true); Record->setLexicalDeclContext(HLSLNamespace); Record->setHasExternalLexicalStorage(); @@ -570,18 +567,6 @@ BuiltinTypeDeclBuilder::~BuiltinTypeDeclBuilder() { HLSLNamespace->addDecl(Record); } -CXXRecordDecl *BuiltinTypeDeclBuilder::finalizeForwardDeclaration() { - // Force the QualType to be generated for the record declaration. In most - // cases this will happen naturally when something uses the type the - // QualType gets lazily created. Unfortunately, with our injected types if a - // type isn't used in a translation unit the QualType may not get - // automatically generated before a PCH is generated. To resolve this we - // just force that the QualType is generated after we create a forward - // declaration. - (void)Record->getASTContext().getRecordType(Record); - return Record; -} - BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs, diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index 36c4add..098b726 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -64,7 +64,7 @@ public: BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef<StringRef> Names, ConceptDecl *CD); - CXXRecordDecl *finalizeForwardDeclaration(); + CXXRecordDecl *finalizeForwardDeclaration() { return Record; } BuiltinTypeDeclBuilder &completeDefinition(); BuiltinTypeDeclBuilder & diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index 6874d30..9c56dd3 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -44,7 +44,7 @@ public: resolveDependentNameType(const DependentNameType *DNT); std::vector<const NamedDecl *> resolveTemplateSpecializationType( const DependentTemplateSpecializationType *DTST); - QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS); + QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS); QualType getPointeeType(QualType T); std::vector<const NamedDecl *> lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, @@ -101,9 +101,8 @@ QualType resolveDeclsToType(const std::vector<const NamedDecl *> &Decls, ASTContext &Ctx) { if (Decls.size() != 1) // Names an overload set -- just bail. return QualType(); - if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) { - return Ctx.getTypeDeclType(TD); - } + if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) + return Ctx.getCanonicalTypeDeclType(TD); if (const auto *VD = dyn_cast<ValueDecl>(Decls[0])) { return VD->getType(); } @@ -139,8 +138,7 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) { T = T->getCanonicalTypeInternal().getTypePtr(); } - if (auto *TT = T->getAs<TagType>()) { - TagDecl *TD = TT->getDecl(); + if (auto *TD = T->getAsTagDecl()) { // Template might not be instantiated yet, fall back to primary template // in such cases. if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) { @@ -151,11 +149,6 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) { return TD; } - if (const auto *ICNT = T->getAs<InjectedClassNameType>()) - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); - if (!T) - return nullptr; - TemplateName TN = getReferencedTemplateName(T); if (TN.isNull()) return nullptr; @@ -292,7 +285,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr( // an instance method, it's represented as a CXXDependentScopeMemberExpr // with `this` as the base expression as `X` as the qualifier // (which could be valid if `X` names a base class after instantiation). - if (NestedNameSpecifier *NNS = ME->getQualifier()) { + if (NestedNameSpecifier NNS = ME->getQualifier()) { if (QualType QualifierType = resolveNestedNameSpecifierToType(NNS); !QualifierType.isNull()) { auto Decls = @@ -348,7 +341,10 @@ HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) { std::vector<const NamedDecl *> HeuristicResolverImpl::resolveUsingValueDecl( const UnresolvedUsingValueDecl *UUVD) { - return resolveDependentMember(QualType(UUVD->getQualifier()->getAsType(), 0), + NestedNameSpecifier Qualifier = UUVD->getQualifier(); + if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type) + return {}; + return resolveDependentMember(QualType(Qualifier.getAsType(), 0), UUVD->getNameInfo().getName(), ValueFilter); } @@ -399,23 +395,23 @@ QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) { } QualType HeuristicResolverImpl::resolveNestedNameSpecifierToType( - const NestedNameSpecifier *NNS) { - if (!NNS) - return QualType(); - + NestedNameSpecifier NNS) { // The purpose of this function is to handle the dependent (Kind == // Identifier) case, but we need to recurse on the prefix because // that may be dependent as well, so for convenience handle // the TypeSpec cases too. - switch (NNS->getKind()) { - case NestedNameSpecifier::TypeSpec: - return QualType(NNS->getAsType(), 0); - case NestedNameSpecifier::Identifier: { - return resolveDeclsToType( - resolveDependentMember( - resolveNestedNameSpecifierToType(NNS->getPrefix()), - NNS->getAsIdentifier(), TypeFilter), - Ctx); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Type: { + const auto *T = NNS.getAsType(); + // FIXME: Should this handle the DependentTemplateSpecializationType as + // well? + if (const auto *DTN = dyn_cast<DependentNameType>(T)) + return resolveDeclsToType( + resolveDependentMember( + resolveNestedNameSpecifierToType(DTN->getQualifier()), + DTN->getIdentifier(), TypeFilter), + Ctx); + return QualType(T, 0); } default: break; @@ -590,7 +586,7 @@ HeuristicResolver::resolveTemplateSpecializationType( return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST); } QualType HeuristicResolver::resolveNestedNameSpecifierToType( - const NestedNameSpecifier *NNS) const { + NestedNameSpecifier NNS) const { return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS); } std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName( diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index cfb2f60..12e5c65 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1883,9 +1883,10 @@ public: for (const FieldDecl *FD : RD->fields()) { QualType FT = FD->getType(); if (const auto *RT = FT->getAs<RecordType>()) - if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) - if (ClassDecl->hasDefinition()) - if (CXXDestructorDecl *MemberDtor = ClassDecl->getDestructor()) + if (const auto *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) + if (const auto *Def = ClassDecl->getDefinition()) + if (CXXDestructorDecl *MemberDtor = Def->getDestructor()) asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor); } @@ -1893,9 +1894,10 @@ public: for (const auto &Base : RD->bases()) { QualType BaseType = Base.getType(); if (const auto *RT = BaseType->getAs<RecordType>()) - if (const auto *BaseDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) - if (BaseDecl->hasDefinition()) - if (CXXDestructorDecl *BaseDtor = BaseDecl->getDestructor()) + if (const auto *BaseDecl = + dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) + if (const auto *Def = BaseDecl->getDefinition()) + if (CXXDestructorDecl *BaseDtor = Def->getDestructor()) asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor); } } @@ -1908,9 +1910,10 @@ public: VD->needsDestruction(S.Context)) { QualType VT = VD->getType(); if (const auto *RT = VT->getAs<RecordType>()) - if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) - if (ClassDecl->hasDefinition()) - if (CXXDestructorDecl *Dtor = ClassDecl->getDestructor()) + if (const auto *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) + if (const auto *Def = ClassDecl->getDefinition()) + if (CXXDestructorDecl *Dtor = Def->getDestructor()) asImpl().visitUsedDecl(Dtor->getLocation(), Dtor); } diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 83a07a2..ba560d3 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -318,11 +318,8 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, const CXXRecordDecl *RD; QualType T = I.getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - RD = cast<CXXRecordDecl>(RT->getDecl()); - } else if (const InjectedClassNameType *IT - = T->getAs<InjectedClassNameType>()) { - RD = IT->getDecl(); + if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) { + RD = Rec; } else { assert(T->isDependentType() && "non-dependent base wasn't a record?"); OnFailure = AR_dependent; @@ -443,7 +440,9 @@ static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, CanQualType Friend) { if (const RecordType *RT = Friend->getAs<RecordType>()) - return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); + return MatchesFriend( + S, EC, + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf()); // TODO: we can do better than this if (Friend->isDependentType()) @@ -671,11 +670,8 @@ struct ProtectedFriendContext { const CXXRecordDecl *RD; QualType T = I.getType(); - if (const RecordType *RT = T->getAs<RecordType>()) { - RD = cast<CXXRecordDecl>(RT->getDecl()); - } else if (const InjectedClassNameType *IT - = T->getAs<InjectedClassNameType>()) { - RD = IT->getDecl(); + if (CXXRecordDecl *Rec = T->getAsCXXRecordDecl()) { + RD = Rec; } else { assert(T->isDependentType() && "non-dependent base wasn't a record?"); EverDependent = true; @@ -1072,7 +1068,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, // TODO: it would be great to have a fixit here, since this is // such an obvious error. S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject) - << S.Context.getTypeDeclType(ECRecord); + << S.Context.getCanonicalTagType(ECRecord); return true; } @@ -1101,7 +1097,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, // Otherwise, use the generic diagnostic. return S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) - << S.Context.getTypeDeclType(ECRecord); + << S.Context.getCanonicalTagType(ECRecord); } return false; @@ -1129,7 +1125,7 @@ static void diagnoseBadDirectAccess(Sema &S, else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) PrevDecl = TND->getPreviousDecl(); else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - if (auto *RD = dyn_cast<CXXRecordDecl>(D); + if (const auto *RD = dyn_cast<CXXRecordDecl>(TD); RD && RD->isInjectedClassName()) break; PrevDecl = TD->getPreviousDecl(); @@ -1284,10 +1280,10 @@ static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr); S.Diag(Loc, Entity.getDiag()) - << (Entity.getAccess() == AS_protected) - << (D ? D->getDeclName() : DeclarationName()) - << S.Context.getTypeDeclType(NamingClass) - << S.Context.getTypeDeclType(DeclaringClass); + << (Entity.getAccess() == AS_protected) + << (D ? D->getDeclName() : DeclarationName()) + << S.Context.getCanonicalTagType(NamingClass) + << S.Context.getCanonicalTagType(DeclaringClass); DiagnoseAccessPath(S, EC, Entity); } @@ -1640,7 +1636,8 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, return AR_accessible; CXXRecordDecl *NamingClass = Dtor->getParent(); - if (ObjectTy.isNull()) ObjectTy = Context.getTypeDeclType(NamingClass); + if (ObjectTy.isNull()) + ObjectTy = Context.getCanonicalTagType(NamingClass); AccessTarget Entity(Context, AccessTarget::Member, NamingClass, DeclAccessPair::make(Dtor, Access), @@ -1728,7 +1725,7 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, AccessTarget AccessEntity( Context, AccessTarget::Member, NamingClass, DeclAccessPair::make(Constructor, Found.getAccess()), - Context.getTypeDeclType(ObjectClass)); + Context.getCanonicalTagType(ObjectClass)); AccessEntity.setDiag(PD); return CheckAccess(*this, UseLoc, AccessEntity); @@ -1776,7 +1773,7 @@ Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc, return AR_accessible; AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field, - Context.getRecordType(DecomposedClass)); + Context.getCanonicalTagType(DecomposedClass)); Entity.setDiag(diag::err_decomp_decl_inaccessible_field); return CheckAccess(*this, UseLoc, Entity); @@ -1790,7 +1787,8 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, return AR_accessible; const RecordType *RT = ObjectExpr->getType()->castAs<RecordType>(); - CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); + CXXRecordDecl *NamingClass = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, ObjectExpr->getType()); diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 68a698f..1c48b3c 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -102,7 +102,7 @@ Sema::ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message, break; for (const Type *T = TD->getUnderlyingType().getTypePtr(); /**/; /**/) { if (auto *TT = dyn_cast<TagType>(T)) { - D = TT->getDecl(); + D = TT->getOriginalDecl()->getDefinitionOrSelf(); } else if (isa<SubstTemplateTypeParmType>(T)) { // A Subst* node represents a use through a template. // Any uses of the underlying declaration happened through it's template @@ -1017,7 +1017,7 @@ bool DiagnoseUnguardedAvailability::VisitTypeLoc(TypeLoc Ty) { return true; if (const auto *TT = dyn_cast<TagType>(TyPtr)) { - TagDecl *TD = TT->getDecl(); + TagDecl *TD = TT->getOriginalDecl()->getDefinitionOrSelf(); DiagnoseDeclAvailability(TD, Range); } else if (const auto *TD = dyn_cast<TypedefType>(TyPtr)) { diff --git a/clang/lib/Sema/SemaBPF.cpp b/clang/lib/Sema/SemaBPF.cpp index 7c00084..6428435 100644 --- a/clang/lib/Sema/SemaBPF.cpp +++ b/clang/lib/Sema/SemaBPF.cpp @@ -58,10 +58,10 @@ static bool isValidPreserveTypeInfoArg(Expr *Arg) { // Record type or Enum type. const Type *Ty = ArgType->getUnqualifiedDesugaredType(); if (const auto *RT = Ty->getAs<RecordType>()) { - if (!RT->getDecl()->getDeclName().isEmpty()) + if (!RT->getOriginalDecl()->getDeclName().isEmpty()) return true; } else if (const auto *ET = Ty->getAs<EnumType>()) { - if (!ET->getDecl()->getDeclName().isEmpty()) + if (!ET->getOriginalDecl()->getDeclName().isEmpty()) return true; } @@ -105,7 +105,7 @@ static bool isValidPreserveEnumValueArg(Expr *Arg) { return false; // The enum value must be supported. - return llvm::is_contained(ET->getDecl()->enumerators(), Enumerator); + return llvm::is_contained(ET->getOriginalDecl()->enumerators(), Enumerator); } bool SemaBPF::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index 24cb8c3..fbf64d3 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -426,7 +426,8 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, continue; } - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(BaseType->getOriginalDecl())->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = SemaRef.LookupSpecialMember(BaseClassDecl, CSM, /* ConstArg */ ConstRHS, @@ -471,7 +472,9 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, continue; } - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl()); + CXXRecordDecl *FieldRecDecl = + cast<CXXRecordDecl>(FieldType->getOriginalDecl()) + ->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = SemaRef.LookupSpecialMember(FieldRecDecl, CSM, /* ConstArg */ ConstRHS && !F->isMutable(), diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 6ac0483..45de8ff 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -28,24 +28,21 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, if (T.isNull()) return nullptr; - const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); - if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - if (Record->isCurrentInstantiation(CurContext)) - return Record; - - return nullptr; - } else if (isa<InjectedClassNameType>(Ty)) - return cast<InjectedClassNameType>(Ty)->getDecl(); - else + const TagType *TagTy = dyn_cast<TagType>(T->getCanonicalTypeInternal()); + if (!isa_and_present<RecordType, InjectedClassNameType>(TagTy)) return nullptr; + auto *RD = + cast<CXXRecordDecl>(TagTy->getOriginalDecl())->getDefinitionOrSelf(); + if (isa<InjectedClassNameType>(TagTy) || + RD->isCurrentInstantiation(CurContext)) + return RD; + return nullptr; } DeclContext *Sema::computeDeclContext(QualType T) { if (!T->isDependentType()) - if (const TagType *Tag = T->getAs<TagType>()) - return Tag->getDecl(); - + if (auto *D = T->getAsTagDecl()) + return D; return ::getCurrentInstantiationOf(T, CurContext); } @@ -54,18 +51,17 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, if (!SS.isSet() || SS.isInvalid()) return nullptr; - NestedNameSpecifier *NNS = SS.getScopeRep(); - if (NNS->isDependent()) { + NestedNameSpecifier NNS = SS.getScopeRep(); + if (NNS.isDependent()) { // If this nested-name-specifier refers to the current // instantiation, return its DeclContext. if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) return Record; if (EnteringContext) { - const Type *NNSType = NNS->getAsType(); - if (!NNSType) { + if (NNS.getKind() != NestedNameSpecifier::Kind::Type) return nullptr; - } + const Type *NNSType = NNS.getAsType(); // Look through type alias templates, per C++0x [temp.dep.type]p1. NNSType = Context.getCanonicalType(NNSType); @@ -118,38 +114,39 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // If the type of the nested name specifier is the same as the // injected class name of the named class template, we're entering // into that class template definition. - QualType Injected = - ClassTemplate->getInjectedClassNameSpecialization(); + CanQualType Injected = + ClassTemplate->getCanonicalInjectedSpecializationType(Context); if (Context.hasSameType(Injected, QualType(SpecType, 0))) return ClassTemplate->getTemplatedDecl(); } - } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) { + } else if (const auto *RecordT = dyn_cast<RecordType>(NNSType)) { // The nested name specifier refers to a member of a class template. - return RecordT->getDecl(); + return RecordT->getOriginalDecl()->getDefinitionOrSelf(); } } return nullptr; } - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - llvm_unreachable("Dependent nested-name-specifier has no DeclContext"); - - case NestedNameSpecifier::Namespace: - return NNS->getAsNamespace()->getNamespace(); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: + return const_cast<NamespaceDecl *>( + NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); - case NestedNameSpecifier::TypeSpec: { - const TagType *Tag = NNS->getAsType()->getAs<TagType>(); - assert(Tag && "Non-tag type in nested-name-specifier"); - return Tag->getDecl(); + case NestedNameSpecifier::Kind::Type: { + auto *TD = NNS.getAsType()->getAsTagDecl(); + assert(TD && "Non-tag type in nested-name-specifier"); + return TD; } - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: return Context.getTranslationUnitDecl(); - case NestedNameSpecifier::Super: - return NNS->getAsRecordDecl(); + case NestedNameSpecifier::Kind::MicrosoftSuper: + return NNS.getAsMicrosoftSuper(); + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); @@ -159,17 +156,17 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; - return SS.getScopeRep()->isDependent(); + return SS.getScopeRep().isDependent(); } -CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { +CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier NNS) { assert(getLangOpts().CPlusPlus && "Only callable in C++"); - assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); + assert(NNS.isDependent() && "Only dependent nested-name-specifier allowed"); - if (!NNS->getAsType()) + if (NNS.getKind() != NestedNameSpecifier::Kind::Type) return nullptr; - QualType T = QualType(NNS->getAsType(), 0); + QualType T = QualType(NNS.getAsType(), 0); return ::getCurrentInstantiationOf(T, CurContext); } @@ -195,8 +192,7 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, return false; // Grab the tag definition, if there is one. - QualType type = Context.getTypeDeclType(tag); - tag = type->getAsTagDecl(); + tag = tag->getDefinitionOrSelf(); // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. @@ -207,7 +203,8 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, if (loc.isInvalid()) loc = SS.getRange().getBegin(); // The type must be complete. - if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec, + if (RequireCompleteType(loc, Context.getCanonicalTagType(tag), + diag::err_incomplete_nested_name_spec, SS.getRange())) { SS.SetInvalid(SS.getRange()); return true; @@ -259,10 +256,10 @@ bool Sema::RequireCompleteEnumDecl(EnumDecl *EnumD, SourceLocation L, if (SS) { Diag(L, diag::err_incomplete_nested_name_spec) - << QualType(EnumD->getTypeForDecl(), 0) << SS->getRange(); + << Context.getCanonicalTagType(EnumD) << SS->getRange(); SS->SetInvalid(SS->getRange()); } else { - Diag(L, diag::err_incomplete_enum) << QualType(EnumD->getTypeForDecl(), 0); + Diag(L, diag::err_incomplete_enum) << Context.getCanonicalTagType(EnumD); Diag(EnumD->getLocation(), diag::note_declared_at); } @@ -304,7 +301,7 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc, return true; } - SS.MakeSuper(Context, RD, SuperLoc, ColonColonLoc); + SS.MakeMicrosoftSuper(Context, RD, SuperLoc, ColonColonLoc); return false; } @@ -324,9 +321,6 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, // Determine whether we have a class (or, in C++11, an enum) or // a typedef thereof. If so, build the nested-name-specifier. - QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); - if (T->isDependentType()) - return true; if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { if (TD->getUnderlyingType()->isRecordType()) return true; @@ -344,32 +338,42 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, if (IsExtension) *IsExtension = true; } + if (auto *TD = dyn_cast<TagDecl>(SD)) { + if (TD->isDependentType()) + return true; + } else if (Context.getCanonicalTypeDeclType(cast<TypeDecl>(SD)) + ->isDependentType()) { + return true; + } return false; } -NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { - if (!S || !NNS) +NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS) { + if (!S) return nullptr; - while (NNS->getPrefix()) - NNS = NNS->getPrefix(); - - if (NNS->getKind() != NestedNameSpecifier::Identifier) - return nullptr; + while (NNS.getKind() == NestedNameSpecifier::Kind::Type) { + const Type *T = NNS.getAsType(); + if ((NNS = T->getPrefix())) + continue; - LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), - LookupNestedNameSpecifierName); - LookupName(Found, S); - assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); + const auto *DNT = dyn_cast<DependentNameType>(T); + if (!DNT) + break; - if (!Found.isSingleResult()) - return nullptr; + LookupResult Found(*this, DNT->getIdentifier(), SourceLocation(), + LookupNestedNameSpecifierName); + LookupName(Found, S); + assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); - NamedDecl *Result = Found.getFoundDecl(); - if (isAcceptableNestedNameSpecifier(Result)) - return Result; + if (!Found.isSingleResult()) + return nullptr; + NamedDecl *Result = Found.getFoundDecl(); + if (isAcceptableNestedNameSpecifier(Result)) + return Result; + } return nullptr; } @@ -493,7 +497,18 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, // base object type or prior nested-name-specifier, so this // nested-name-specifier refers to an unknown specialization. Just build // a dependent nested-name-specifier. - SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); + + TypeLocBuilder TLB; + + QualType DTN = Context.getDependentNameType( + ElaboratedTypeKeyword::None, SS.getScopeRep(), IdInfo.Identifier); + auto DTNL = TLB.push<DependentNameTypeLoc>(DTN); + DTNL.setElaboratedKeywordLoc(SourceLocation()); + DTNL.setNameLoc(IdInfo.IdentifierLoc); + DTNL.setQualifierLoc(SS.getWithLocInContext(Context)); + + SS.clear(); + SS.Make(Context, TLB.getTypeLocInContext(Context, DTN), IdInfo.CCLoc); return false; } @@ -599,8 +614,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) || !Context.hasSameType( - Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), - Context.getTypeDeclType(cast<TypeDecl>(SD))))) { + Context.getCanonicalTypeDeclType(cast<TypeDecl>(OuterDecl)), + Context.getCanonicalTypeDeclType(cast<TypeDecl>(SD))))) { if (ErrorRecoveryLookup) return true; @@ -613,7 +628,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, // Fall through so that we'll pick the name we found in the object // type, since that's probably what the user wanted anyway. - } + } } if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(SD)) @@ -637,50 +652,44 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, return false; } - QualType T = - Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl())); - - if (T->isEnumeralType()) + const auto *TD = cast<TypeDecl>(SD->getUnderlyingDecl()); + 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(USD, T); - TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<InjectedClassNameType>(T)) { - InjectedClassNameTypeLoc InjectedTL - = TLB.push<InjectedClassNameTypeLoc>(T); - InjectedTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<RecordType>(T)) { - RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); - RecordTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<TypedefType>(T)) { - TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); - TypedefTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<EnumType>(T)) { - EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); - EnumTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<TemplateTypeParmType>(T)) { - TemplateTypeParmTypeLoc TemplateTypeTL - = TLB.push<TemplateTypeParmTypeLoc>(T); - TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<UnresolvedUsingType>(T)) { - UnresolvedUsingTypeLoc UnresolvedTL - = TLB.push<UnresolvedUsingTypeLoc>(T); - UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<SubstTemplateTypeParmType>(T)) { - SubstTemplateTypeParmTypeLoc TL - = TLB.push<SubstTemplateTypeParmTypeLoc>(T); - TL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa<SubstTemplateTypeParmPackType>(T)) { - SubstTemplateTypeParmPackTypeLoc TL - = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); - TL.setNameLoc(IdInfo.IdentifierLoc); + 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 { - llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); + assert(SS.isEmpty()); + T = Context.getTypeDeclType(TD); + TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc); } - - SS.Extend(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc); + SS.clear(); + SS.Make(Context, TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc); return false; } @@ -722,16 +731,34 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; + + TypeLocBuilder TLB; + // Fake up a nested-name-specifier that starts with the // injected-class-name of the enclosing class. - QualType T = Context.getTypeDeclType(ContainingClass); - TypeLocBuilder TLB; - TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); - SS.Extend(Context, TLB.getTypeLocInContext(Context, T), - IdInfo.IdentifierLoc); - // Add the identifier to form a dependent name. - SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, - IdInfo.CCLoc); + // FIXME: This should be done as part of an adjustment, so that this + // doesn't get confused with something written in source. + QualType Result = + Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + ContainingClass, /*OwnsTag=*/false); + auto TTL = TLB.push<TagTypeLoc>(Result); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(SS.getWithLocInContext(Context)); + TTL.setNameLoc(IdInfo.IdentifierLoc); + SS.Make(Context, TLB.getTypeLocInContext(Context, Result), + SourceLocation()); + + TLB.clear(); + + // Form a DependentNameType. + QualType DTN = Context.getDependentNameType( + ElaboratedTypeKeyword::None, SS.getScopeRep(), IdInfo.Identifier); + auto DTNL = TLB.push<DependentNameTypeLoc>(DTN); + DTNL.setElaboratedKeywordLoc(SourceLocation()); + DTNL.setNameLoc(IdInfo.IdentifierLoc); + DTNL.setQualifierLoc(SS.getWithLocInContext(Context)); + SS.clear(); + SS.Make(Context, TLB.getTypeLocInContext(Context, DTN), IdInfo.CCLoc); return false; } } @@ -739,8 +766,19 @@ 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); + } + Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) - << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; + << T << getLangOpts().CPlusPlus; } else if (Found.getAsSingle<TemplateDecl>()) { ParsedType SuggestedType; DiagnoseUnknownTypeName(IdInfo.Identifier, IdInfo.IdentifierLoc, S, &SS, @@ -786,17 +824,19 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, if (T.isNull()) return true; - if (!T->isDependentType() && !T->getAs<TagType>()) { + if (!T->isDependentType() && !isa<TagType>(T.getCanonicalType())) { Diag(DS.getTypeSpecTypeLoc(), diag::err_expected_class_or_namespace) << T << getLangOpts().CPlusPlus; return true; } + assert(SS.isEmpty()); + TypeLocBuilder TLB; DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); - SS.Extend(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc); + SS.Make(Context, TLB.getTypeLocInContext(Context, T), ColonColonLoc); return false; } @@ -812,13 +852,15 @@ bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, if (Type.isNull()) return true; + assert(SS.isEmpty()); + TypeLocBuilder TLB; TLB.pushTrivial(getASTContext(), cast<PackIndexingType>(Type.getTypePtr())->getPattern(), DS.getBeginLoc()); PackIndexingTypeLoc PIT = TLB.push<PackIndexingTypeLoc>(Type); PIT.setEllipsisLoc(DS.getEllipsisLoc()); - SS.Extend(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc); + SS.Make(Context, TLB.getTypeLocInContext(Context, Type), ColonColonLoc); return false; } @@ -858,7 +900,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, assert(DTN->getQualifier() == SS.getScopeRep()); QualType T = Context.getDependentTemplateSpecializationType( ElaboratedTypeKeyword::None, - {/*Qualifier=*/nullptr, DTN->getName().getIdentifier(), + {SS.getScopeRep(), DTN->getName().getIdentifier(), TemplateKWLoc.isValid()}, TemplateArgs.arguments()); @@ -867,7 +909,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, DependentTemplateSpecializationTypeLoc SpecTL = Builder.push<DependentTemplateSpecializationTypeLoc>(T); SpecTL.setElaboratedKeywordLoc(SourceLocation()); - SpecTL.setQualifierLoc(NestedNameSpecifierLoc()); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateNameLoc); SpecTL.setLAngleLoc(LAngleLoc); @@ -875,7 +917,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc); + SS.clear(); + SS.Make(Context, Builder.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -900,30 +943,28 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, // We were able to resolve the template name to an actual template. // Build an appropriate nested-name-specifier. - QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + QualType T = CheckTemplateIdType(ElaboratedTypeKeyword::None, Template, + TemplateNameLoc, TemplateArgs); if (T.isNull()) return true; // Alias template specializations can produce types which are not valid // nested name specifiers. - if (!T->isDependentType() && !T->getAs<TagType>()) { + if (!T->isDependentType() && !isa<TagType>(T.getCanonicalType())) { Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; NoteAllFoundTemplates(Template); return true; } // Provide source-location information for the template specialization type. - TypeLocBuilder Builder; - TemplateSpecializationTypeLoc SpecTL - = Builder.push<TemplateSpecializationTypeLoc>(T); - SpecTL.setTemplateKeywordLoc(TemplateKWLoc); - SpecTL.setTemplateNameLoc(TemplateNameLoc); - SpecTL.setLAngleLoc(LAngleLoc); - SpecTL.setRAngleLoc(RAngleLoc); - for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - - SS.Extend(Context, Builder.getTypeLocInContext(Context, T), CCLoc); + TypeLocBuilder TLB; + TLB.push<TemplateSpecializationTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), TemplateKWLoc, TemplateNameLoc, + TemplateArgs); + + SS.clear(); + SS.Make(Context, TLB.getTypeLocInContext(Context, T), CCLoc); return false; } @@ -931,7 +972,7 @@ namespace { /// A structure that stores a nested-name-specifier annotation, /// including both the nested-name-specifier struct NestedNameSpecifierAnnotation { - NestedNameSpecifier *NNS; + NestedNameSpecifier NNS = std::nullopt; }; } @@ -970,8 +1011,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { if (isa<ObjCContainerDecl>(CurContext) || isa<ObjCMethodDecl>(CurContext)) return false; - NestedNameSpecifier *Qualifier = SS.getScopeRep(); - // There are only two places a well-formed program may qualify a // declarator: first, when defining a namespace or class member // out-of-line, and second, when naming an explicitly-qualified @@ -986,18 +1025,20 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { // granting friendship. // i.e. we don't push a scope unless it's a class member. - switch (Qualifier->getKind()) { - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Namespace: + switch (SS.getScopeRep().getKind()) { + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::Namespace: // These are always namespace scopes. We never want to enter a // namespace scope from anything but a file context. return CurContext->getRedeclContext()->isFileContext(); - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::Type: + case NestedNameSpecifier::Kind::MicrosoftSuper: // These are never namespace scopes. return true; + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 01252a4..da43848 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -964,7 +964,7 @@ void CastOperation::CheckDynamicCast() { } // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. - const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(); + const RecordDecl *SrcDecl = SrcRecord->getOriginalDecl()->getDefinition(); assert(SrcDecl && "Definition missing"); if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) @@ -1455,7 +1455,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // converted to an integral type. [...] A value of a scoped enumeration type // can also be explicitly converted to a floating-point type [...]. if (const EnumType *Enum = SrcType->getAs<EnumType>()) { - if (Enum->getDecl()->isScoped()) { + if (Enum->getOriginalDecl()->isScoped()) { if (DestType->isBooleanType()) { Kind = CK_IntegralToBoolean; return TC_Success; @@ -1487,8 +1487,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, // [expr.static.cast]p10 If the enumeration type has a fixed underlying // type, the value is first converted to that type by integral conversion const EnumType *Enum = DestType->castAs<EnumType>(); - Kind = Enum->getDecl()->isFixed() && - Enum->getDecl()->getIntegerType()->isBooleanType() + const EnumDecl *ED = Enum->getOriginalDecl()->getDefinitionOrSelf(); + Kind = ED->isFixed() && ED->getIntegerType()->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast; return TC_Success; @@ -1856,7 +1856,7 @@ TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, FoundOverload)) { CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); SrcType = Self.Context.getMemberPointerType( - Fn->getType(), /*Qualifier=*/nullptr, M->getParent()); + Fn->getType(), /*Qualifier=*/std::nullopt, M->getParent()); WasOverloadedFunction = true; } } @@ -2102,9 +2102,9 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, return; } // or one of the types is a tag type. - if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) { + if (isa<TagType>(SrcTy.getCanonicalType()) || + isa<TagType>(DestTy.getCanonicalType())) return; - } // FIXME: Scoped enums? if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || @@ -3097,27 +3097,26 @@ void CastOperation::CheckCStyleCast() { if (!DestType->isScalarType() && !DestType->isVectorType() && !DestType->isMatrixType()) { - const RecordType *DestRecordTy = DestType->getAs<RecordType>(); - - if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){ - // GCC struct/union extension: allow cast to self. - Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) - << DestType << SrcExpr.get()->getSourceRange(); - Kind = CK_NoOp; - return; - } - - // GCC's cast to union extension. - if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) { - RecordDecl *RD = DestRecordTy->getDecl(); - if (CastExpr::getTargetFieldForToUnionCast(RD, SrcType)) { - Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union) - << SrcExpr.get()->getSourceRange(); - Kind = CK_ToUnion; + if (const RecordType *DestRecordTy = DestType->getAs<RecordType>()) { + if (Self.Context.hasSameUnqualifiedType(DestType, SrcType)) { + // GCC struct/union extension: allow cast to self. + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) + << DestType << SrcExpr.get()->getSourceRange(); + Kind = CK_NoOp; return; - } else { + } + + // GCC's cast to union extension. + if (RecordDecl *RD = DestRecordTy->getOriginalDecl(); RD->isUnion()) { + if (CastExpr::getTargetFieldForToUnionCast(RD->getDefinitionOrSelf(), + SrcType)) { + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union) + << SrcExpr.get()->getSourceRange(); + Kind = CK_ToUnion; + return; + } Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type) - << SrcType << SrcExpr.get()->getSourceRange(); + << SrcType << SrcExpr.get()->getSourceRange(); SrcExpr = ExprError(); return; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3c4511b..9ecee18 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -604,7 +604,7 @@ struct BuiltinDumpStructGenerator { bool dumpUnnamedRecord(const RecordDecl *RD, Expr *E, unsigned Depth) { Expr *IndentLit = getIndentString(Depth); - Expr *TypeLit = getTypeString(S.Context.getRecordType(RD)); + Expr *TypeLit = getTypeString(S.Context.getCanonicalTagType(RD)); if (IndentLit ? callPrintFunction("%s%s", {IndentLit, TypeLit}) : callPrintFunction("%s", {TypeLit})) return true; @@ -2289,7 +2289,7 @@ static ExprResult BuiltinInvoke(Sema &S, CallExpr *TheCall) { return ExprError(); } - const Type *MemPtrClass = MPT->getQualifier()->getAsType(); + const Type *MemPtrClass = MPT->getQualifier().getAsType(); QualType ObjectT = Args[1]->getType(); if (MPT->isMemberDataPointer() && S.checkArgCount(TheCall, 2)) @@ -3318,7 +3318,9 @@ static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { // As a special case, transparent unions initialized with zero are // considered null for the purposes of the nonnull attribute. if (const RecordType *UT = Expr->getType()->getAsUnionType(); - UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { + UT && UT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr<TransparentUnionAttr>()) { if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Expr)) if (const auto *ILE = dyn_cast<InitListExpr>(CLE->getInitializer())) Expr = ILE->getInit(0); @@ -5175,7 +5177,9 @@ bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { return false; if (!Type->isEnumeralType()) return true; - const EnumDecl *ED = Type->castAs<EnumType>()->getDecl(); + const EnumDecl *ED = Type->castAs<EnumType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); return !(ED && Context.typesAreCompatible(ED->getPromotionType(), Type)); }()) { @@ -7791,8 +7795,11 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { if (!RT) return Results; - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD || !RD->getDefinition()) + CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()); + if (!RD) + return Results; + RD = RD->getDefinition(); + if (!RD) return Results; LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(), @@ -7801,7 +7808,7 @@ CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) { // We just need to include all members of the right kind turned up by the // filter, at this point. - if (S.LookupQualifiedName(R, RT->getDecl())) + if (S.LookupQualifiedName(R, RD)) for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *decl = (*I)->getUnderlyingDecl(); if (MemberKind *FK = dyn_cast<MemberKind>(decl)) @@ -8328,7 +8335,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, bool IsScopedEnum = false; QualType IntendedTy = ExprTy; if (auto EnumTy = ExprTy->getAs<EnumType>()) { - IntendedTy = EnumTy->getDecl()->getIntegerType(); + IntendedTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (EnumTy->isUnscopedEnumerationType()) { ExprTy = IntendedTy; // This controls whether we're talking about the underlying type or not, @@ -8364,7 +8372,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, NamedDecl *ND = Result.getFoundDecl(); if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND)) if (TD->getUnderlyingType() == IntendedTy) - IntendedTy = S.Context.getTypedefType(TD); + IntendedTy = + S.Context.getTypedefType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD); } } } @@ -9622,7 +9632,10 @@ struct SearchNonTrivialToInitializeField S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1); } void visitStruct(QualType FT, SourceLocation SL) { - for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields()) + for (const FieldDecl *FD : FT->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) visit(FD->getType(), FD->getLocation()); } void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK, @@ -9667,7 +9680,10 @@ struct SearchNonTrivialToCopyField S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0); } void visitStruct(QualType FT, SourceLocation SL) { - for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields()) + for (const FieldDecl *FD : FT->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) visit(FD->getType(), FD->getLocation()); } void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT, @@ -9948,8 +9964,9 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, getLangOpts().CPlusPlus && !RT->isIncompleteType() && !RT->desugar().isTriviallyCopyableType(Context); + const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) && - RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) { + RD->isNonTrivialToPrimitiveDefaultInitialize()) { DiagRuntimeBehavior(Dest->getExprLoc(), Dest, PDiag(diag::warn_cstruct_memaccess) << ArgIdx << FnName << PointeeTy << 0); @@ -9962,7 +9979,7 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, PDiag(diag::warn_cxxstruct_memaccess) << FnName << PointeeTy); } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) && - RT->getDecl()->isNonTrivialToPrimitiveCopy()) { + RD->isNonTrivialToPrimitiveCopy()) { DiagRuntimeBehavior(Dest->getExprLoc(), Dest, PDiag(diag::warn_cstruct_memaccess) << ArgIdx << FnName << PointeeTy << 1); @@ -10468,10 +10485,14 @@ struct IntRange { if (!C.getLangOpts().CPlusPlus) { // For enum types in C code, use the underlying datatype. if (const auto *ET = dyn_cast<EnumType>(T)) - T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr(); + T = ET->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType() + .getDesugaredType(C) + .getTypePtr(); } else if (const auto *ET = dyn_cast<EnumType>(T)) { // For enum types in C++, use the known bit width of the enumerators. - EnumDecl *Enum = ET->getDecl(); + EnumDecl *Enum = ET->getOriginalDecl()->getDefinitionOrSelf(); // In C++11, enums can have a fixed underlying type. Use this type to // compute the range. if (Enum->isFixed()) { @@ -10513,7 +10534,9 @@ struct IntRange { if (const AtomicType *AT = dyn_cast<AtomicType>(T)) T = AT->getValueType().getTypePtr(); if (const EnumType *ET = dyn_cast<EnumType>(T)) - T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr(); + T = C.getCanonicalType( + ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType()) + .getTypePtr(); if (const auto *EIT = dyn_cast<BitIntType>(T)) return IntRange(EIT->getNumBits(), EIT->isUnsigned()); @@ -11485,7 +11508,9 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, return false; if (BitfieldType->isEnumeralType()) { - EnumDecl *BitfieldEnumDecl = BitfieldType->castAs<EnumType>()->getDecl(); + EnumDecl *BitfieldEnumDecl = BitfieldType->castAs<EnumType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); // If the underlying enum type was not explicitly specified as an unsigned // type and the enum contain only positive values, MSVC++ will cause an // inconsistency by storing this as a signed type. @@ -11522,7 +11547,7 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, EnumTy = PTAttr->getType()->getAs<EnumType>(); } if (EnumTy) { - EnumDecl *ED = EnumTy->getDecl(); + EnumDecl *ED = EnumTy->getOriginalDecl()->getDefinitionOrSelf(); bool SignedBitfield = BitfieldType->isSignedIntegerOrEnumerationType(); // Enum types are implicitly signed on Windows, so check if there are any @@ -12588,8 +12613,8 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, if (const EnumType *SourceEnum = Source->getAs<EnumType>()) if (const EnumType *TargetEnum = Target->getAs<EnumType>()) - if (SourceEnum->getDecl()->hasNameForLinkage() && - TargetEnum->getDecl()->hasNameForLinkage() && + if (SourceEnum->getOriginalDecl()->hasNameForLinkage() && + TargetEnum->getOriginalDecl()->hasNameForLinkage() && SourceEnum != TargetEnum) { if (SourceMgr.isInSystemMacro(CC)) return; @@ -15113,10 +15138,9 @@ static bool isLayoutCompatible(const ASTContext &C, const EnumDecl *ED1, static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1, const FieldDecl *Field2, bool AreUnionMembers = false) { - [[maybe_unused]] const Type *Field1Parent = - Field1->getParent()->getTypeForDecl(); - [[maybe_unused]] const Type *Field2Parent = - Field2->getParent()->getTypeForDecl(); +#ifndef NDEBUG + CanQualType Field1Parent = C.getCanonicalTagType(Field1->getParent()); + CanQualType Field2Parent = C.getCanonicalTagType(Field2->getParent()); assert(((Field1Parent->isStructureOrClassType() && Field2Parent->isStructureOrClassType()) || (Field1Parent->isUnionType() && Field2Parent->isUnionType())) && @@ -15125,6 +15149,7 @@ static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1, assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) || (AreUnionMembers && Field1Parent->isUnionType())) && "AreUnionMembers should be 'true' for union fields (only)."); +#endif if (!isLayoutCompatible(C, Field1->getType(), Field2->getType())) return false; @@ -15229,16 +15254,16 @@ static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2) { return false; if (TC1 == Type::Enum) { - return isLayoutCompatible(C, - cast<EnumType>(T1)->getDecl(), - cast<EnumType>(T2)->getDecl()); + return isLayoutCompatible( + C, cast<EnumType>(T1)->getOriginalDecl()->getDefinitionOrSelf(), + cast<EnumType>(T2)->getOriginalDecl()->getDefinitionOrSelf()); } else if (TC1 == Type::Record) { if (!T1->isStandardLayoutType() || !T2->isStandardLayoutType()) return false; - return isLayoutCompatible(C, - cast<RecordType>(T1)->getDecl(), - cast<RecordType>(T2)->getDecl()); + return isLayoutCompatible( + C, cast<RecordType>(T1)->getOriginalDecl()->getDefinitionOrSelf(), + cast<RecordType>(T2)->getOriginalDecl()->getDefinitionOrSelf()); } return false; @@ -15592,7 +15617,9 @@ void Sema::RefersToMemberWithReducedAlignment( return; if (ME->isArrow()) BaseType = BaseType->getPointeeType(); - RecordDecl *RD = BaseType->castAs<RecordType>()->getDecl(); + RecordDecl *RD = BaseType->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return; @@ -15637,7 +15664,7 @@ void Sema::RefersToMemberWithReducedAlignment( // Compute the CompleteObjectAlignment as the alignment of the whole chain. CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars( - ReverseMemberChain.back()->getParent()->getTypeForDecl()); + Context.getCanonicalTagType(ReverseMemberChain.back()->getParent())); // The base expression of the innermost MemberExpr may give // stronger guarantees than the class containing the member. @@ -15667,9 +15694,9 @@ void Sema::RefersToMemberWithReducedAlignment( if (FDI->hasAttr<PackedAttr>() || FDI->getParent()->hasAttr<PackedAttr>()) { FD = FDI; - Alignment = std::min( - Context.getTypeAlignInChars(FD->getType()), - Context.getTypeAlignInChars(FD->getParent()->getTypeForDecl())); + Alignment = std::min(Context.getTypeAlignInChars(FD->getType()), + Context.getTypeAlignInChars( + Context.getCanonicalTagType(FD->getParent()))); break; } } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 0de5580..e4f2760 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -732,7 +732,7 @@ ResultBuilder::ShadowMapEntry::end() const { /// /// \returns a nested name specifier that refers into the target context, or /// NULL if no qualification is needed. -static NestedNameSpecifier * +static NestedNameSpecifier getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, const DeclContext *TargetContext) { SmallVector<const DeclContext *, 4> TargetParents; @@ -747,7 +747,7 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, TargetParents.push_back(CommonAncestor); } - NestedNameSpecifier *Result = nullptr; + NestedNameSpecifier Result = std::nullopt; while (!TargetParents.empty()) { const DeclContext *Parent = TargetParents.pop_back_val(); @@ -755,10 +755,12 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, if (!Namespace->getIdentifier()) continue; - Result = NestedNameSpecifier::Create(Context, Result, Namespace); - } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) - Result = NestedNameSpecifier::Create( - Context, Result, Context.getTypeDeclType(TD).getTypePtr()); + Result = NestedNameSpecifier(Context, Namespace, Result); + } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) { + QualType TT = Context.getTagType(ElaboratedTypeKeyword::None, Result, TD, + /*OwnsTag=*/false); + Result = NestedNameSpecifier(TT.getTypePtr()); + } } return Result; } @@ -937,11 +939,12 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { /// Get the type that a given expression will have if this declaration /// is used as an expression in its "typical" code-completion form. -QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { +QualType clang::getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier, + const NamedDecl *ND) { ND = ND->getUnderlyingDecl(); if (const auto *Type = dyn_cast<TypeDecl>(ND)) - return C.getTypeDeclType(Type); + return C.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, Type); if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) return C.getObjCInterfaceType(Iface); @@ -951,7 +954,9 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getSendResultType(); else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) - T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); + T = C.getTagType(ElaboratedTypeKeyword::None, Qualifier, + cast<EnumDecl>(Enumerator->getDeclContext()), + /*OwnsTag=*/false); else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) T = Property->getType(); else if (const auto *Value = dyn_cast<ValueDecl>(ND)) @@ -1053,7 +1058,7 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { // If we have a preferred type, adjust the priority for results with exactly- // matching or nearly-matching types. if (!PreferredType.isNull()) { - QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); + QualType T = getDeclUsageType(SemaRef.Context, R.Qualifier, R.Declaration); if (!T.isNull()) { CanQualType TC = SemaRef.Context.getCanonicalType(T); // Check for exactly-matching types (modulo qualifiers). @@ -1070,10 +1075,9 @@ void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { static DeclContext::lookup_result getConstructors(ASTContext &Context, const CXXRecordDecl *Record) { - QualType RecordTy = Context.getTypeDeclType(Record); + CanQualType RecordTy = Context.getCanonicalTagType(Record); DeclarationName ConstructorName = - Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(RecordTy)); + Context.DeclarationNames.getCXXConstructorName(RecordTy); return Record->lookup(ConstructorName); } @@ -1216,11 +1220,13 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { const DeclContext *Ctx = R.Declaration->getDeclContext(); if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) R.Qualifier = - NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt); else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create( - SemaRef.Context, nullptr, - SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + R.Qualifier = NestedNameSpecifier( + SemaRef.Context + .getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false) + .getTypePtr()); else R.QualifierIsInformative = false; } @@ -1405,11 +1411,13 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, const DeclContext *Ctx = R.Declaration->getDeclContext(); if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx)) R.Qualifier = - NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt); else if (const auto *Tag = dyn_cast<TagDecl>(Ctx)) - R.Qualifier = NestedNameSpecifier::Create( - SemaRef.Context, nullptr, - SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + R.Qualifier = NestedNameSpecifier( + SemaRef.Context + .getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, Tag, /*OwnsTag=*/false) + .getTypePtr()); else R.QualifierIsInformative = false; } @@ -1664,7 +1672,8 @@ static bool isObjCReceiverType(ASTContext &C, QualType T) { } bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { - QualType T = getDeclUsageType(SemaRef.Context, ND); + QualType T = + getDeclUsageType(SemaRef.Context, /*Qualifier=*/std::nullopt, ND); if (T.isNull()) return false; @@ -1689,7 +1698,8 @@ bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) return false; - QualType T = getDeclUsageType(SemaRef.Context, ND); + QualType T = + getDeclUsageType(SemaRef.Context, /*Qualifier=*/std::nullopt, ND); if (T.isNull()) return false; @@ -1745,8 +1755,10 @@ public: void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass) override { - ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, - false, IsAccessible(ND, Ctx), FixIts); + ResultBuilder::Result Result(ND, Results.getBasePriority(ND), + /*Qualifier=*/std::nullopt, + /*QualifierIsInformative=*/false, + IsAccessible(ND, Ctx), FixIts); Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass, BaseType); } @@ -2010,7 +2022,6 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, Policy.AnonymousTagLocations = false; Policy.SuppressStrongLifetime = true; Policy.SuppressUnwrittenScope = true; - Policy.SuppressScope = true; Policy.CleanUglifiedParameters = true; return Policy; } @@ -2035,7 +2046,7 @@ static const char *GetCompletionTypeString(QualType T, ASTContext &Context, // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast<TagType>(T)) - if (TagDecl *Tag = TagT->getDecl()) + if (TagDecl *Tag = TagT->getOriginalDecl()) if (!Tag->hasNameForLinkage()) { switch (Tag->getTagKind()) { case TagTypeKind::Struct: @@ -2925,8 +2936,8 @@ static void AddResultTypeChunk(ASTContext &Context, else T = Method->getReturnType(); } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { - T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); - T = clang::TypeName::getFullyQualifiedType(T, Context); + T = Context.getCanonicalTagType( + cast<EnumDecl>(Enumerator->getDeclContext())); } else if (isa<UnresolvedUsingValueDecl>(ND)) { /* Do nothing: ignore unresolved using declarations*/ } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { @@ -3021,7 +3032,7 @@ static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo, if (!SuppressBlock) { if (TypedefTypeLoc TypedefTL = TL.getAsAdjusted<TypedefTypeLoc>()) { if (TypeSourceInfo *InnerTSInfo = - TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) { + TypedefTL.getDecl()->getTypeSourceInfo()) { TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); continue; } @@ -3381,7 +3392,7 @@ static void AddTemplateParameterChunks( /// Add a qualifier to the given code-completion string, if the /// provided nested-name-specifier is non-NULL. static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, - NestedNameSpecifier *Qualifier, + NestedNameSpecifier Qualifier, bool QualifierIsInformative, ASTContext &Context, const PrintingPolicy &Policy) { @@ -3391,7 +3402,7 @@ static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, std::string PrintedNNS; { llvm::raw_string_ostream OS(PrintedNNS); - Qualifier->print(OS, Policy); + Qualifier.print(OS, Policy); } if (QualifierIsInformative) Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); @@ -3520,11 +3531,9 @@ static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, case DeclarationName::CXXConstructorName: { CXXRecordDecl *Record = nullptr; QualType Ty = Name.getCXXNameType(); - if (const auto *RecordTy = Ty->getAs<RecordType>()) - Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>()) - Record = InjectedTy->getDecl(); - else { + if (auto *RD = Ty->getAsCXXRecordDecl()) { + Record = RD; + } else { Result.AddTypedTextChunk( Result.getAllocator().CopyString(ND->getNameAsString())); break; @@ -4506,12 +4515,12 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, // If we need a nested-name-specifier, add one now. if (!InContext) { - NestedNameSpecifier *NNS = getRequiredQualification( + NestedNameSpecifier NNS = getRequiredQualification( S.Context, CurContext, Overridden->getDeclContext()); if (NNS) { std::string Str; llvm::raw_string_ostream OS(Str); - NNS->print(OS, Policy); + NNS.print(OS, Policy); Builder.AddTextChunk(Results.getAllocator().CopyString(Str)); } } else if (!InContext->Equals(Overridden->getDeclContext())) @@ -4920,14 +4929,14 @@ namespace { /// Information that allows to avoid completing redundant enumerators. struct CoveredEnumerators { llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen; - NestedNameSpecifier *SuggestedQualifier = nullptr; + NestedNameSpecifier SuggestedQualifier = std::nullopt; }; } // namespace static void AddEnumerators(ResultBuilder &Results, ASTContext &Context, EnumDecl *Enum, DeclContext *CurContext, const CoveredEnumerators &Enumerators) { - NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier; + NestedNameSpecifier Qualifier = Enumerators.SuggestedQualifier; if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) { // If there are no prior enumerators in C++, check whether we have to // qualify the names of the enumerators that we suggest, because they @@ -5059,9 +5068,9 @@ void SemaCodeCompletion::CodeCompleteExpression( Data.PreferredType->isMemberPointerType() || Data.PreferredType->isBlockPointerType(); if (Data.PreferredType->isEnumeralType()) { - EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl(); - if (auto *Def = Enum->getDefinition()) - Enum = Def; + EnumDecl *Enum = Data.PreferredType->castAs<EnumType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); // FIXME: collect covered enumerators in cases like: // if (x == my_enum::one) { ... } else if (x == ^) {} AddEnumerators(Results, getASTContext(), Enum, SemaRef.CurContext, @@ -5185,7 +5194,8 @@ AddObjCProperties(const CodeCompletionContext &CCContext, // expressions. if (!P->getType().getTypePtr()->isBlockPointerType() || !IsBaseExprStatement) { - Result R = Result(P, Results.getBasePriority(P), nullptr); + Result R = + Result(P, Results.getBasePriority(P), /*Qualifier=*/std::nullopt); if (!InOriginalClass) setInBaseClass(R); Results.MaybeAddResult(R, CurContext); @@ -5199,7 +5209,8 @@ AddObjCProperties(const CodeCompletionContext &CCContext, findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc, BlockProtoLoc); if (!BlockLoc) { - Result R = Result(P, Results.getBasePriority(P), nullptr); + Result R = + Result(P, Results.getBasePriority(P), /*Qualifier=*/std::nullopt); if (!InOriginalClass) setInBaseClass(R); Results.MaybeAddResult(R, CurContext); @@ -5611,15 +5622,18 @@ private: // In T::foo, `foo` is a static member function/variable. bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) override { - if (E->getQualifier() && isApprox(E->getQualifier()->getAsType(), T)) + NestedNameSpecifier Qualifier = E->getQualifier(); + if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type && + isApprox(Qualifier.getAsType(), T)) addValue(E, E->getDeclName(), Member::Colons); return true; } // In T::typename foo, `foo` is a type. bool VisitDependentNameType(DependentNameType *DNT) override { - const auto *Q = DNT->getQualifier(); - if (Q && isApprox(Q->getAsType(), T)) + NestedNameSpecifier Q = DNT->getQualifier(); + if (Q.getKind() == NestedNameSpecifier::Kind::Type && + isApprox(Q.getAsType(), T)) addType(DNT->getIdentifier()); return true; } @@ -5628,10 +5642,15 @@ private: // VisitNNS() doesn't exist, and TraverseNNS isn't always called :-( bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSL) override { if (NNSL) { - NestedNameSpecifier *NNS = NNSL.getNestedNameSpecifier(); - const auto *Q = NNS->getPrefix(); - if (Q && isApprox(Q->getAsType(), T)) - addType(NNS->getAsIdentifier()); + NestedNameSpecifier NNS = NNSL.getNestedNameSpecifier(); + if (NNS.getKind() == NestedNameSpecifier::Kind::Type) { + const Type *NNST = NNS.getAsType(); + if (NestedNameSpecifier Q = NNST->getPrefix(); + Q.getKind() == NestedNameSpecifier::Kind::Type && + isApprox(Q.getAsType(), T)) + if (const auto *DNT = dyn_cast_or_null<DependentNameType>(NNST)) + addType(DNT->getIdentifier()); + } } // FIXME: also handle T::foo<X>::bar return DynamicRecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNSL); @@ -5777,7 +5796,7 @@ QualType getApproximateType(const Expr *E, HeuristicResolver &Resolver) { if (auto Decls = Resolver.resolveDependentNameType(DNT); Decls.size() == 1) { if (const auto *TD = dyn_cast<TypeDecl>(Decls[0])) - return QualType(TD->getTypeForDecl(), 0); + return TD->getASTContext().getTypeDeclType(TD); } } // We only resolve DependentTy, or undeduced autos (including auto* etc). @@ -6184,9 +6203,8 @@ void SemaCodeCompletion::CodeCompleteCase(Scope *S) { // Code-complete the cases of a switch statement over an enumeration type // by providing the list of - EnumDecl *Enum = type->castAs<EnumType>()->getDecl(); - if (EnumDecl *Def = Enum->getDefinition()) - Enum = Def; + EnumDecl *Enum = + type->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf(); // Determine which enumerators we have already seen in the switch statement. // FIXME: Ideally, we would also be able to look *past* the code-completion @@ -6887,8 +6905,8 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // Try to instantiate any non-dependent declaration contexts before // we look in them. Bail out if we fail. - NestedNameSpecifier *NNS = SS.getScopeRep(); - if (NNS != nullptr && SS.isValid() && !NNS->isDependent()) { + NestedNameSpecifier NNS = SS.getScopeRep(); + if (NNS && !NNS.isDependent()) { if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx)) return; } @@ -6902,14 +6920,13 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, // The "template" keyword can follow "::" in the grammar, but only // put it into the grammar if the nested-name-specifier is dependent. // FIXME: results is always empty, this appears to be dead. - if (!Results.empty() && NNS && NNS->isDependent()) + if (!Results.empty() && NNS.isDependent()) Results.AddResult("template"); // If the scope is a concept-constrained type parameter, infer nested // members based on the constraints. - if (NNS) { - if (const auto *TTPT = - dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) { + if (NNS.getKind() == NestedNameSpecifier::Kind::Type) { + if (const auto *TTPT = dyn_cast<TemplateTypeParmType>(NNS.getAsType())) { for (const auto &R : ConceptInfo(*TTPT, S).members()) { if (R.Operator != ConceptInfo::Member::Colons) continue; @@ -7034,7 +7051,7 @@ void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) { NS != NSEnd; ++NS) Results.AddResult( CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), - nullptr), + /*Qualifier=*/std::nullopt), SemaRef.CurContext, nullptr, false); Results.ExitScope(); } @@ -7821,7 +7838,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container, if (!Selectors.insert(M->getSelector()).second) continue; - Result R = Result(M, Results.getBasePriority(M), nullptr); + Result R = + Result(M, Results.getBasePriority(M), /*Qualifier=*/std::nullopt); R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = (WantKind != MK_Any); if (!InOriginalClass) @@ -8412,7 +8430,8 @@ AddClassMessageCompletions(Sema &SemaRef, Scope *S, ParsedType Receiver, continue; Result R(MethList->getMethod(), - Results.getBasePriority(MethList->getMethod()), nullptr); + Results.getBasePriority(MethList->getMethod()), + /*Qualifier=*/std::nullopt); R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; Results.MaybeAddResult(R, SemaRef.CurContext); @@ -8588,7 +8607,8 @@ void SemaCodeCompletion::CodeCompleteObjCInstanceMessage( continue; Result R(MethList->getMethod(), - Results.getBasePriority(MethList->getMethod()), nullptr); + Results.getBasePriority(MethList->getMethod()), + /*Qualifier=*/std::nullopt); R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; Results.MaybeAddResult(R, SemaRef.CurContext); @@ -8704,9 +8724,9 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, // Record any protocols we find. if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D)) if (!OnlyForwardDeclarations || !Proto->hasDefinition()) - Results.AddResult( - Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext, - nullptr, false); + Results.AddResult(Result(Proto, Results.getBasePriority(Proto), + /*Qualifier=*/std::nullopt), + CurContext, nullptr, false); } } @@ -8772,9 +8792,9 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult( - Result(Class, Results.getBasePriority(Class), nullptr), CurContext, - nullptr, false); + Results.AddResult(Result(Class, Results.getBasePriority(Class), + /*Qualifier=*/std::nullopt), + CurContext, nullptr, false); } } @@ -8886,9 +8906,9 @@ void SemaCodeCompletion::CodeCompleteObjCInterfaceCategory( for (const auto *D : TU->decls()) if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D)) if (CategoryNames.insert(Category->getIdentifier()).second) - Results.AddResult( - Result(Category, Results.getBasePriority(Category), nullptr), - SemaRef.CurContext, nullptr, false); + Results.AddResult(Result(Category, Results.getBasePriority(Category), + /*Qualifier=*/std::nullopt), + SemaRef.CurContext, nullptr, false); Results.ExitScope(); HandleCodeCompleteResults(&SemaRef, CodeCompleter, @@ -8923,7 +8943,8 @@ void SemaCodeCompletion::CodeCompleteObjCImplementationCategory( for (const auto *Cat : Class->visible_categories()) { if ((!IgnoreImplemented || !Cat->getImplementation()) && CategoryNames.insert(Cat->getIdentifier()).second) - Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr), + Results.AddResult(Result(Cat, Results.getBasePriority(Cat), + /*Qualifier=*/std::nullopt), SemaRef.CurContext, nullptr, false); } @@ -9023,7 +9044,8 @@ void SemaCodeCompletion::CodeCompleteObjCPropertySynthesizeIvar( for (; Class; Class = Class->getSuperClass()) { for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; Ivar = Ivar->getNextIvar()) { - Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), + Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), + /*Qualifier=*/std::nullopt), SemaRef.CurContext, nullptr, false); // Determine whether we've seen an ivar with a name similar to the @@ -10039,7 +10061,8 @@ void SemaCodeCompletion::CodeCompleteObjCMethodDeclSelector( } Result R(MethList->getMethod(), - Results.getBasePriority(MethList->getMethod()), nullptr); + Results.getBasePriority(MethList->getMethod()), + /*Qualifier=*/std::nullopt); R.StartParameter = SelIdents.size(); R.AllParametersAreInformative = false; R.DeclaringEntity = true; diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index d193a33..cc03616 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -89,8 +89,8 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, AddArg(T); // Build the template-id. - QualType CoroTrait = - S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args); + QualType CoroTrait = S.CheckTemplateIdType( + ElaboratedTypeKeyword::None, TemplateName(CoroTraits), KwLoc, Args); if (CoroTrait.isNull()) return QualType(); if (S.RequireCompleteType(KwLoc, CoroTrait, @@ -111,23 +111,18 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, << RD; return QualType(); } - // The promise type is required to be a class type. - QualType PromiseType = S.Context.getTypeDeclType(Promise); - - auto buildElaboratedType = [&]() { - auto *NNS = NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace()); - NNS = NestedNameSpecifier::Create(S.Context, NNS, CoroTrait.getTypePtr()); - return S.Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, - PromiseType); - }; + NestedNameSpecifier Qualifier(CoroTrait.getTypePtr()); + QualType PromiseType = S.Context.getTypeDeclType(ElaboratedTypeKeyword::None, + Qualifier, Promise); + // The promise type is required to be a class type. if (!PromiseType->getAsCXXRecordDecl()) { S.Diag(FuncLoc, diag::err_implied_std_coroutine_traits_promise_type_not_class) - << buildElaboratedType(); + << PromiseType; return QualType(); } - if (S.RequireCompleteType(FuncLoc, buildElaboratedType(), + if (S.RequireCompleteType(FuncLoc, PromiseType, diag::err_coroutine_promise_type_incomplete)) return QualType(); @@ -167,8 +162,8 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, S.Context.getTrivialTypeSourceInfo(PromiseType, Loc))); // Build the template-id. - QualType CoroHandleType = - S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args); + QualType CoroHandleType = S.CheckTemplateIdType( + ElaboratedTypeKeyword::None, TemplateName(CoroHandle), Loc, Args); if (CoroHandleType.isNull()) return QualType(); if (S.RequireCompleteType(Loc, CoroHandleType, @@ -643,7 +638,9 @@ static void checkNoThrow(Sema &S, const Stmt *E, QualType::DestructionKind::DK_cxx_destructor) { const auto *T = cast<RecordType>(ReturnType.getCanonicalType().getTypePtr()); - checkDeclNoexcept(cast<CXXRecordDecl>(T->getDecl())->getDestructor(), + checkDeclNoexcept(cast<CXXRecordDecl>(T->getOriginalDecl()) + ->getDefinition() + ->getDestructor(), /*IsDtor=*/true); } } else @@ -1083,9 +1080,9 @@ static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) { static TypeSourceInfo *getTypeSourceInfoForStdAlignValT(Sema &S, SourceLocation Loc) { - EnumDecl *StdAlignValT = S.getStdAlignValT(); - QualType StdAlignValDecl = S.Context.getTypeDeclType(StdAlignValT); - return S.Context.getTrivialTypeSourceInfo(StdAlignValDecl); + EnumDecl *StdAlignValDecl = S.getStdAlignValT(); + CanQualType StdAlignValT = S.Context.getCanonicalTagType(StdAlignValDecl); + return S.Context.getTrivialTypeSourceInfo(StdAlignValT); } // When searching for custom allocators on the PromiseType we want to diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b5eb825..cb59782 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -140,8 +140,8 @@ class TypeNameValidatorCCC final : public CorrectionCandidateCallback { } // end anonymous namespace -QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, - TypeDecl *TD, SourceLocation NameLoc) { +void Sema::checkTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, + TypeDecl *TD, SourceLocation NameLoc) { auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx); auto *FoundRD = dyn_cast<CXXRecordDecl>(TD); if (DCK != DiagCtorKind::None && LookupRD && FoundRD && @@ -157,7 +157,6 @@ QualType Sema::getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, DiagnoseUseOfDecl(TD, NameLoc); MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); - return Context.getTypeDeclType(TD); } namespace { @@ -182,13 +181,13 @@ lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II, UnqualifiedTypeNameLookupResult FoundTypeDecl = UnqualifiedTypeNameLookupResult::NotFound; for (const auto &Base : RD->bases()) { - const CXXRecordDecl *BaseRD = nullptr; - if (auto *BaseTT = Base.getType()->getAs<TagType>()) - BaseRD = BaseTT->getAsCXXRecordDecl(); - else if (auto *TST = Base.getType()->getAs<TemplateSpecializationType>()) { + const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl(); + if (BaseRD) { + } else if (auto *TST = dyn_cast<TemplateSpecializationType>( + Base.getType().getCanonicalType())) { // Look for type decls in dependent base classes that have known primary // templates. - if (!TST || !TST->isDependentType()) + if (!TST->isDependentType()) continue; auto *TD = TST->getTemplateName().getAsTemplateDecl(); if (!TD) @@ -253,8 +252,7 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, S.Diag(NameLoc, diag::ext_found_in_dependent_base) << &II; ASTContext &Context = S.Context; - auto *NNS = NestedNameSpecifier::Create( - Context, nullptr, cast<Type>(Context.getRecordType(RD))); + NestedNameSpecifier NNS(Context.getCanonicalTagType(RD).getTypePtr()); QualType T = Context.getDependentNameType(ElaboratedTypeKeyword::None, NNS, &II); @@ -269,45 +267,6 @@ static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } -/// Build a ParsedType for a simple-type-specifier with a nested-name-specifier. -static ParsedType buildNamedType(Sema &S, const CXXScopeSpec *SS, QualType T, - SourceLocation NameLoc, - bool WantNontrivialTypeSourceInfo = true) { - switch (T->getTypeClass()) { - case Type::DeducedTemplateSpecialization: - case Type::Enum: - case Type::InjectedClassName: - case Type::Record: - case Type::Typedef: - case Type::UnresolvedUsing: - case Type::Using: - break; - // These can never be qualified so an ElaboratedType node - // would carry no additional meaning. - case Type::ObjCInterface: - case Type::ObjCTypeParam: - case Type::TemplateTypeParm: - return ParsedType::make(T); - default: - llvm_unreachable("Unexpected Type Class"); - } - - if (!SS || SS->isEmpty()) - return ParsedType::make(S.Context.getElaboratedType( - ElaboratedTypeKeyword::None, nullptr, T, nullptr)); - - QualType ElTy = S.getElaboratedType(ElaboratedTypeKeyword::None, *SS, T); - if (!WantNontrivialTypeSourceInfo) - return ParsedType::make(ElTy); - - TypeLocBuilder Builder; - Builder.pushTypeSpec(T).setNameLoc(NameLoc); - ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(ElTy); - ElabTL.setElaboratedKeywordLoc(SourceLocation()); - ElabTL.setQualifierLoc(SS->getWithLocInContext(S.Context)); - return S.CreateParsedType(ElTy, Builder.getTypeSourceInfo(S.Context, ElTy)); -} - ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, ParsedType ObjectTypePtr, @@ -348,9 +307,10 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, if (AllowImplicitTypename == ImplicitTypenameContext::No) return nullptr; SourceLocation QualifiedLoc = SS->getRange().getBegin(); - auto DB = - DiagCompat(QualifiedLoc, diag_compat::implicit_typename) - << NestedNameSpecifier::Create(Context, SS->getScopeRep(), &II); + // FIXME: Defer the diagnostic after we build the type and use it. + auto DB = DiagCompat(QualifiedLoc, diag_compat::implicit_typename) + << Context.getDependentNameType(ElaboratedTypeKeyword::None, + SS->getScopeRep(), &II); if (!getLangOpts().CPlusPlus20) DB << FixItHint::CreateInsertion(QualifiedLoc, "typename "); } @@ -430,7 +390,7 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, bool MemberOfUnknownSpecialization; UnqualifiedId TemplateName; TemplateName.setIdentifier(NewII, NameLoc); - NestedNameSpecifier *NNS = Correction.getCorrectionSpecifier(); + NestedNameSpecifier NNS = Correction.getCorrectionSpecifier(); CXXScopeSpec NewSS, *NewSSPtr = SS; if (SS && NNS) { NewSS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); @@ -530,20 +490,78 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, assert(IIDecl && "Didn't find decl"); - QualType T; + TypeLocBuilder TLB; if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { - // C++ [class.qual]p2: A lookup that would find the injected-class-name - // instead names the constructors of the class, except when naming a class. - // This is ill-formed when we're not actually forming a ctor or dtor name. - T = getTypeDeclType(LookupCtx, - IsImplicitTypename ? DiagCtorKind::Implicit - : DiagCtorKind::None, - TD, NameLoc); - } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { + checkTypeDeclType(LookupCtx, + IsImplicitTypename ? DiagCtorKind::Implicit + : DiagCtorKind::None, + TD, NameLoc); + QualType T; + if (FoundUsingShadow) { + T = Context.getUsingType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, + FoundUsingShadow); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + NameLoc); + } else if (auto *Tag = dyn_cast<TagDecl>(TD)) { + T = Context.getTagType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, Tag, + /*OwnsTag=*/false); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + auto TL = TLB.push<TagTypeLoc>(T); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc()); + TL.setNameLoc(NameLoc); + } else if (auto *TN = dyn_cast<TypedefNameDecl>(TD); + TN && !isa<ObjCTypeParamDecl>(TN)) { + T = Context.getTypedefType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, TN); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + TLB.push<TypedefTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + NameLoc); + } else if (auto *UD = dyn_cast<UnresolvedUsingTypenameDecl>(TD)) { + T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, + UD); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + TLB.push<UnresolvedUsingTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + NameLoc); + } else { + T = Context.getTypeDeclType(TD); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + if (isa<ObjCTypeParamType>(T)) + TLB.push<ObjCTypeParamTypeLoc>(T).setNameLoc(NameLoc); + else + TLB.pushTypeSpec(T).setNameLoc(NameLoc); + } + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { (void)DiagnoseUseOfDecl(IDecl, NameLoc); - if (!HasTrailingDot) - T = Context.getObjCInterfaceType(IDecl); - FoundUsingShadow = nullptr; // FIXME: Target must be a TypeDecl. + if (!HasTrailingDot) { + // FIXME: Support UsingType for this case. + QualType T = Context.getObjCInterfaceType(IDecl); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + auto TL = TLB.push<ObjCInterfaceTypeLoc>(T); + TL.setNameLoc(NameLoc); + // FIXME: Pass in this source location. + TL.setNameEndLoc(NameLoc); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } } else if (auto *UD = dyn_cast<UnresolvedUsingIfExistsDecl>(IIDecl)) { (void)DiagnoseUseOfDecl(UD, NameLoc); // Recover with 'int' @@ -551,41 +569,38 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } else if (AllowDeducedTemplate) { if (auto *TD = getAsTypeTemplateDecl(IIDecl)) { assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD); + // FIXME: Support UsingType here. TemplateName Template = Context.getQualifiedTemplateName( - SS ? SS->getScopeRep() : nullptr, /*TemplateKeyword=*/false, + SS ? SS->getScopeRep() : std::nullopt, /*TemplateKeyword=*/false, FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD)); - T = Context.getDeducedTemplateSpecializationType(Template, QualType(), - false); - // Don't wrap in a further UsingType. - FoundUsingShadow = nullptr; + QualType T = Context.getDeducedTemplateSpecializationType( + ElaboratedTypeKeyword::None, Template, QualType(), false); + auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setNameLoc(NameLoc); + TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); } } - if (T.isNull()) { - // If it's not plausibly a type, suppress diagnostics. - Result.suppressDiagnostics(); - return nullptr; - } - - if (FoundUsingShadow) - T = Context.getUsingType(FoundUsingShadow, T); - - return buildNamedType(*this, SS, T, NameLoc, WantNontrivialTypeSourceInfo); + // As it's not plausibly a type, suppress diagnostics. + Result.suppressDiagnostics(); + return nullptr; } // Builds a fake NNS for the given decl context. -static NestedNameSpecifier * +static NestedNameSpecifier synthesizeCurrentNestedNameSpecifier(ASTContext &Context, DeclContext *DC) { for (;; DC = DC->getLookupParent()) { DC = DC->getPrimaryContext(); auto *ND = dyn_cast<NamespaceDecl>(DC); if (ND && !ND->isInline() && !ND->isAnonymousNamespace()) - return NestedNameSpecifier::Create(Context, nullptr, ND); + return NestedNameSpecifier(Context, ND, std::nullopt); if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) - return NestedNameSpecifier::Create(Context, nullptr, - RD->getTypeForDecl()); + return NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr()); if (isa<TranslationUnitDecl>(DC)) - return NestedNameSpecifier::GlobalSpecifier(Context); + return NestedNameSpecifier::getGlobal(); } llvm_unreachable("something isn't in TU scope?"); } @@ -610,7 +625,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, bool IsTemplateTypeArg) { assert(getLangOpts().MSVCCompat && "shouldn't be called in non-MSVC mode"); - NestedNameSpecifier *NNS = nullptr; + NestedNameSpecifier NNS = std::nullopt; if (IsTemplateTypeArg && getCurScope()->isTemplateParamScope()) { // If we weren't able to parse a default template argument, delay lookup // until instantiation time by making a non-dependent DependentTypeName. We @@ -625,7 +640,7 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, findRecordWithDependentBasesOfEnclosingMethod(CurContext)) { // Build a DependentNameType that will perform lookup into RD at // instantiation time. - NNS = NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl()); + NNS = NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr()); // Diagnose that this identifier was undeclared, and retry the lookup during // template instantiation. @@ -678,19 +693,22 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { } bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { - if (CurContext->isRecord()) { - if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super) - return true; - - const Type *Ty = SS->getScopeRep()->getAsType(); + if (!CurContext->isRecord()) + return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); - CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); - for (const auto &Base : RD->bases()) - if (Ty && Context.hasSameUnqualifiedType(QualType(Ty, 1), Base.getType())) + switch (SS->getScopeRep().getKind()) { + case NestedNameSpecifier::Kind::MicrosoftSuper: + return true; + case NestedNameSpecifier::Kind::Type: { + QualType T(SS->getScopeRep().getAsType(), 0); + for (const auto &Base : cast<CXXRecordDecl>(CurContext)->bases()) + if (Context.hasSameUnqualifiedType(T, Base.getType())) return true; + [[fallthrough]]; + } + default: return S->isFunctionPrototypeScope(); } - return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope(); } void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, @@ -786,7 +804,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, Diag(IILoc, IsTemplateName ? diag::err_no_member_template : diag::err_typename_nested_not_found) << II << DC << SS->getRange(); - else if (SS->isValid() && SS->getScopeRep()->containsErrors()) { + else if (SS->isValid() && SS->getScopeRep().containsErrors()) { SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); } else if (isDependentScopeSpecifier(*SS)) { @@ -794,12 +812,13 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S)) DiagID = diag::ext_typename_missing; + SuggestedType = + ActOnTypenameType(S, SourceLocation(), *SS, *II, IILoc).get(); + Diag(SS->getRange().getBegin(), DiagID) - << NestedNameSpecifier::Create(Context, SS->getScopeRep(), II) + << GetTypeFromParser(SuggestedType) << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); - SuggestedType = ActOnTypenameType(S, SourceLocation(), - *SS, *II, IILoc).get(); } else { assert(SS && SS->isInvalid() && "Invalid scope specifier has already been diagnosed"); @@ -1156,10 +1175,34 @@ Corrected: } auto BuildTypeFor = [&](TypeDecl *Type, NamedDecl *Found) { - QualType T = Context.getTypeDeclType(Type); - if (const auto *USD = dyn_cast<UsingShadowDecl>(Found)) - T = Context.getUsingType(USD, T); - return buildNamedType(*this, &SS, T, NameLoc); + QualType T; + TypeLocBuilder TLB; + if (const auto *USD = dyn_cast<UsingShadowDecl>(Found)) { + T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + USD); + TLB.push<UsingTypeLoc>(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameLoc); + } else { + T = Context.getTypeDeclType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + Type); + if (isa<TagType>(T)) { + auto TTL = TLB.push<TagTypeLoc>(T); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(SS.getWithLocInContext(Context)); + TTL.setNameLoc(NameLoc); + } else if (isa<TypedefType>(T)) { + TLB.push<TypedefTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameLoc); + } else if (isa<UnresolvedUsingType>(T)) { + TLB.push<UnresolvedUsingTypeLoc>(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameLoc); + } else { + TLB.pushTypeSpec(T).setNameLoc(NameLoc); + } + } + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); }; NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); @@ -2009,8 +2052,7 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts, // consistent for both scalars and arrays. Ty = Ty->getBaseElementTypeUnsafe(); - if (const TagType *TT = Ty->getAs<TagType>()) { - const TagDecl *Tag = TT->getDecl(); + if (const TagDecl *Tag = Ty->getAsTagDecl()) { if (Tag->hasAttr<UnusedAttr>()) return false; @@ -2070,7 +2112,7 @@ void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D) { void Sema::DiagnoseUnusedNestedTypedefs(const RecordDecl *D, DiagReceiverTy DiagReceiver) { - if (D->getTypeForDecl()->isDependentType()) + if (D->isDependentType()) return; for (auto *TmpD : D->decls()) { @@ -2128,8 +2170,7 @@ void Sema::DiagnoseUnusedButSetDecl(const VarDecl *VD, if (Ty->isReferenceType() || Ty->isDependentType()) return; - if (const TagType *TT = Ty->getAs<TagType>()) { - const TagDecl *Tag = TT->getDecl(); + if (const TagDecl *Tag = Ty->getAsTagDecl()) { if (Tag->hasAttr<UnusedAttr>()) return; // In C++, don't warn for record types that don't have WarnUnusedAttr, to @@ -2508,7 +2549,8 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, } Context.setObjCIdRedefinitionType(T); // Install the built-in type for 'id', ignoring the current definition. - New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); + New->setModedTypeSourceInfo(New->getTypeSourceInfo(), + Context.getObjCIdType()); return; } case 5: @@ -2516,14 +2558,16 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, break; Context.setObjCClassRedefinitionType(New->getUnderlyingType()); // Install the built-in type for 'Class', ignoring the current definition. - New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); + New->setModedTypeSourceInfo(New->getTypeSourceInfo(), + Context.getObjCClassType()); return; case 3: if (!TypeID->isStr("SEL")) break; Context.setObjCSelRedefinitionType(New->getUnderlyingType()); // Install the built-in type for 'SEL', ignoring the current definition. - New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); + New->setModedTypeSourceInfo(New->getTypeSourceInfo(), + Context.getObjCSelType()); return; } // Fall through - the typedef name was not a builtin type. @@ -2555,7 +2599,6 @@ void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, !hasVisibleDefinition(OldTag, &Hidden)) { // There is a definition of this tag, but it is not visible. Use it // instead of our tag. - New->setTypeForDecl(OldTD->getTypeForDecl()); if (OldTD->isModed()) New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(), OldTD->getUnderlyingType()); @@ -2742,7 +2785,7 @@ static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) { if (ValueDecl *VD = dyn_cast<ValueDecl>(New)) Ty = VD->getType(); else - Ty = S.Context.getTagDeclType(cast<TagDecl>(New)); + Ty = S.Context.getCanonicalTagType(cast<TagDecl>(New)); if (OldAlign == 0) OldAlign = S.Context.getTypeAlign(Ty); @@ -2913,8 +2956,11 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, } static const NamedDecl *getDefinition(const Decl *D) { - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) - return TD->getDefinition(); + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (const auto *Def = TD->getDefinition(); Def && !Def->isBeingDefined()) + return Def; + return nullptr; + } if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { const VarDecl *Def = VD->getDefinition(); if (Def) @@ -5024,7 +5070,7 @@ void Sema::setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, // The type must match the tag exactly; no qualifiers allowed. if (!Context.hasSameType(NewTD->getUnderlyingType(), - Context.getTagDeclType(TagFromDeclSpec))) { + Context.getCanonicalTagType(TagFromDeclSpec))) { if (getLangOpts().CPlusPlus) Context.addTypedefNameForUnnamedTagDecl(TagFromDeclSpec, NewTD); return; @@ -5232,9 +5278,9 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Record = dyn_cast<RecordDecl>(Tag); else if (const RecordType *RT = DS.getRepAsType().get()->getAsStructureType()) - Record = RT->getDecl(); + Record = RT->getOriginalDecl()->getDefinitionOrSelf(); else if (const RecordType *UT = DS.getRepAsType().get()->getAsUnionType()) - Record = UT->getDecl(); + Record = UT->getOriginalDecl()->getDefinitionOrSelf(); if (Record && getLangOpts().MicrosoftExt) { Diag(DS.getBeginLoc(), diag::ext_ms_anonymous_record) @@ -5762,7 +5808,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { Anon = FieldDecl::Create( Context, OwningClass, DS.getBeginLoc(), Record->getLocation(), - /*IdentifierInfo=*/nullptr, Context.getTypeDeclType(Record), TInfo, + /*IdentifierInfo=*/nullptr, Context.getCanonicalTagType(Record), TInfo, /*BitWidth=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); Anon->setAccess(AS); @@ -5782,7 +5828,7 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(), Record->getLocation(), /*IdentifierInfo=*/nullptr, - Context.getTypeDeclType(Record), TInfo, SC); + Context.getCanonicalTagType(Record), TInfo, SC); if (Invalid) Anon->setInvalidDecl(); @@ -5845,7 +5891,7 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, assert(TInfo && "couldn't build declarator info for anonymous struct"); auto *ParentDecl = cast<RecordDecl>(CurContext); - QualType RecTy = Context.getTypeDeclType(Record); + CanQualType RecTy = Context.getCanonicalTagType(Record); // Create a declaration for this anonymous struct. NamedDecl *Anon = @@ -5964,14 +6010,14 @@ Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { return DeclarationNameInfo(); // Determine the type of the class being constructed. - QualType CurClassType = Context.getTypeDeclType(CurClass); + CanQualType CurClassType = Context.getCanonicalTagType(CurClass); // FIXME: Check two things: that the template-id names the same type as // CurClassType, and that the template-id does not occur when the name // was qualified. - NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(CurClassType))); + NameInfo.setName( + Context.DeclarationNames.getCXXConstructorName(CurClassType)); // FIXME: should we retrieve TypeSourceInfo? NameInfo.setNamedTypeInfo(nullptr); return NameInfo; @@ -6259,8 +6305,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, // that's the case, then drop this declaration entirely. if ((Name.getNameKind() == DeclarationName::CXXConstructorName || Name.getNameKind() == DeclarationName::CXXDestructorName) && - !Context.hasSameType(Name.getCXXNameType(), - Context.getTypeDeclType(cast<CXXRecordDecl>(Cur)))) + !Context.hasSameType( + Name.getCXXNameType(), + Context.getCanonicalTagType(cast<CXXRecordDecl>(Cur)))) return true; return false; @@ -6280,36 +6327,48 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, << FixItHint::CreateRemoval(TemplateId->TemplateKWLoc); NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data()); - do { - if (TypeLoc TL = SpecLoc.getTypeLoc()) { - if (SourceLocation TemplateKeywordLoc = TL.getTemplateKeywordLoc(); - TemplateKeywordLoc.isValid()) - Diag(Loc, diag::ext_template_after_declarative_nns) - << FixItHint::CreateRemoval(TemplateKeywordLoc); - } - - if (const Type *T = SpecLoc.getNestedNameSpecifier()->getAsType()) { - if (const auto *TST = T->getAsAdjusted<TemplateSpecializationType>()) { - // C++23 [expr.prim.id.qual]p3: - // [...] If a nested-name-specifier N is declarative and has a - // simple-template-id with a template argument list A that involves a - // template parameter, let T be the template nominated by N without A. - // T shall be a class template. - if (TST->isDependentType() && TST->isTypeAlias()) - Diag(Loc, diag::ext_alias_template_in_declarative_nns) - << SpecLoc.getLocalSourceRange(); - } else if (T->isDecltypeType() || T->getAsAdjusted<PackIndexingType>()) { - // C++23 [expr.prim.id.qual]p2: - // [...] A declarative nested-name-specifier shall not have a - // computed-type-specifier. - // - // CWG2858 changed this from 'decltype-specifier' to - // 'computed-type-specifier'. - Diag(Loc, diag::err_computed_type_in_declarative_nns) - << T->isDecltypeType() << SpecLoc.getTypeLoc().getSourceRange(); - } + for (TypeLoc TL = SpecLoc.getAsTypeLoc(), NextTL; TL; + TL = std::exchange(NextTL, TypeLoc())) { + SourceLocation TemplateKeywordLoc; + switch (TL.getTypeLocClass()) { + case TypeLoc::TemplateSpecialization: { + auto TST = TL.castAs<TemplateSpecializationTypeLoc>(); + TemplateKeywordLoc = TST.getTemplateKeywordLoc(); + if (auto *T = TST.getTypePtr(); T->isDependentType() && T->isTypeAlias()) + Diag(Loc, diag::ext_alias_template_in_declarative_nns) + << TST.getLocalSourceRange(); + break; + } + case TypeLoc::Decltype: + case TypeLoc::PackIndexing: { + const Type *T = TL.getTypePtr(); + // C++23 [expr.prim.id.qual]p2: + // [...] A declarative nested-name-specifier shall not have a + // computed-type-specifier. + // + // CWG2858 changed this from 'decltype-specifier' to + // 'computed-type-specifier'. + Diag(Loc, diag::err_computed_type_in_declarative_nns) + << T->isDecltypeType() << TL.getSourceRange(); + break; } - } while ((SpecLoc = SpecLoc.getPrefix())); + case TypeLoc::DependentName: + NextTL = + TL.castAs<DependentNameTypeLoc>().getQualifierLoc().getAsTypeLoc(); + break; + case TypeLoc::DependentTemplateSpecialization: { + auto TST = TL.castAs<DependentTemplateSpecializationTypeLoc>(); + TemplateKeywordLoc = TST.getTemplateKeywordLoc(); + NextTL = TST.getQualifierLoc().getAsTypeLoc(); + break; + } + default: + break; + } + if (TemplateKeywordLoc.isValid()) + Diag(Loc, diag::ext_template_after_declarative_nns) + << FixItHint::CreateRemoval(TemplateKeywordLoc); + } return false; } @@ -9046,9 +9105,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // We really want to find the base class destructor here. - QualType T = Context.getTypeDeclType(BaseRecord); - CanQualType CT = Context.getCanonicalType(T); - Name = Context.DeclarationNames.getCXXDestructorName(CT); + Name = Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalTagType(BaseRecord)); } for (NamedDecl *BaseND : BaseRecord->lookup(Name)) { @@ -9734,7 +9792,8 @@ static void checkIsValidOpenCLKernelParameter( // At this point we already handled everything except of a RecordType. assert(PT->isRecordType() && "Unexpected type."); - const RecordDecl *PD = PT->castAs<RecordType>()->getDecl(); + const RecordDecl *PD = + PT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); VisitStack.push_back(PD); assert(VisitStack.back() && "First decl null?"); @@ -9762,7 +9821,9 @@ static void checkIsValidOpenCLKernelParameter( "Unexpected type."); const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType(); - RD = FieldRecTy->castAs<RecordType>()->getDecl(); + RD = FieldRecTy->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); } else { RD = cast<RecordDecl>(Next); } @@ -10768,7 +10829,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // redeclaration lookup found nothing at all. Diagnose that now; // nothing will diagnose that error later. if (isFriend && - (D.getCXXScopeSpec().getScopeRep()->isDependent() || + (D.getCXXScopeSpec().getScopeRep().isDependent() || (!Previous.empty() && CurContext->isDependentContext()))) { // ignore these } else if (NewFD->isCPUDispatchMultiVersion() || @@ -12272,11 +12333,11 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // template struct A<B>; if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None || !Destructor->getFunctionObjectParameterType()->isDependentType()) { - CXXRecordDecl *Record = Destructor->getParent(); - QualType ClassType = Context.getTypeDeclType(Record); + CanQualType ClassType = + Context.getCanonicalTagType(Destructor->getParent()); - DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( - Context.getCanonicalType(ClassType)); + DeclarationName Name = + Context.DeclarationNames.getCXXDestructorName(ClassType); if (NewFD->getDeclName() != Name) { Diag(NewFD->getLocation(), diag::err_destructor_name); NewFD->setInvalidDecl(); @@ -13280,7 +13341,8 @@ struct DiagNonTrivalCUnionDefaultInitializeVisitor } void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { - const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); + const RecordDecl *RD = + QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) { if (OrigLoc.isValid()) { bool IsUnion = false; @@ -13346,7 +13408,8 @@ struct DiagNonTrivalCUnionDestructedTypeVisitor } void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { - const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); + const RecordDecl *RD = + QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) { if (OrigLoc.isValid()) { bool IsUnion = false; @@ -13411,7 +13474,8 @@ struct DiagNonTrivalCUnionCopyVisitor } void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { - const RecordDecl *RD = QT->castAs<RecordType>()->getDecl(); + const RecordDecl *RD = + QT->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) { if (OrigLoc.isValid()) { bool IsUnion = false; @@ -14384,7 +14448,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { if (getLangOpts().CPlusPlus && Var->hasLocalStorage()) { if (const RecordType *Record = Context.getBaseElementType(Type)->getAs<RecordType>()) { - CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl()); + CXXRecordDecl *CXXRecord = + cast<CXXRecordDecl>(Record->getOriginalDecl()) + ->getDefinitionOrSelf(); // Mark the function (if we're in one) for further checking even if the // looser rules of C++11 do not require such checks, so that we can // diagnose incompatibilities with C++98. @@ -17483,6 +17549,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // FIXME: Check member specializations more carefully. bool isMemberSpecialization = false; + bool IsInjectedClassName = false; bool Invalid = false; // We only need to do this matching if we have template parameters @@ -17948,8 +18015,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (getLangOpts().CPlusPlus) { if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { - if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { - TagDecl *Tag = TT->getDecl(); + if (TagDecl *Tag = TD->getUnderlyingType()->getAsTagDecl()) { if (Tag->getDeclName() == Name && Tag->getDeclContext()->getRedeclContext() ->Equals(TD->getDeclContext()->getRedeclContext())) { @@ -17959,6 +18025,15 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, Previous.resolveKind(); } } + } else if (auto *RD = dyn_cast<CXXRecordDecl>(PrevDecl); + RD && RD->isInjectedClassName()) { + // If lookup found the injected class name, the previous declaration is + // the class being injected into. + PrevDecl = cast<TagDecl>(RD->getDeclContext()); + Previous.clear(); + Previous.addDecl(PrevDecl); + Previous.resolveKind(); + IsInjectedClassName = true; } } @@ -18082,78 +18157,79 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // Diagnose attempts to redefine a tag. if (TUK == TagUseKind::Definition) { - if (NamedDecl *Def = PrevTagDecl->getDefinition()) { - // If we're defining a specialization and the previous definition - // is from an implicit instantiation, don't emit an error - // here; we'll catch this in the general case below. - bool IsExplicitSpecializationAfterInstantiation = false; - if (isMemberSpecialization) { - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def)) - IsExplicitSpecializationAfterInstantiation = - RD->getTemplateSpecializationKind() != - TSK_ExplicitSpecialization; - else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def)) - IsExplicitSpecializationAfterInstantiation = - ED->getTemplateSpecializationKind() != - TSK_ExplicitSpecialization; - } - - // Note that clang allows ODR-like semantics for ObjC/C, i.e., do - // not keep more that one definition around (merge them). However, - // ensure the decl passes the structural compatibility check in - // C11 6.2.7/1 (or 6.1.2.6/1 in C89). - NamedDecl *Hidden = nullptr; - if (SkipBody && - (!hasVisibleDefinition(Def, &Hidden) || getLangOpts().C23)) { - // There is a definition of this tag, but it is not visible. We - // explicitly make use of C++'s one definition rule here, and - // assume that this definition is identical to the hidden one - // we already have. Make the existing definition visible and - // use it in place of this one. - if (!getLangOpts().CPlusPlus) { - // Postpone making the old definition visible until after we - // complete parsing the new one and do the structural - // comparison. - SkipBody->CheckSameAsPrevious = true; - SkipBody->New = createTagFromNewDecl(); - SkipBody->Previous = Def; - - ProcessDeclAttributeList(S, SkipBody->New, Attrs); - return Def; - } else { - SkipBody->ShouldSkip = true; - SkipBody->Previous = Def; - makeMergedDefinitionVisible(Hidden); - // Carry on and handle it like a normal definition. We'll - // skip starting the definition later. - } - } else if (!IsExplicitSpecializationAfterInstantiation) { - // A redeclaration in function prototype scope in C isn't - // visible elsewhere, so merely issue a warning. - if (!getLangOpts().CPlusPlus && S->containedInPrototypeScope()) - Diag(NameLoc, diag::warn_redefinition_in_param_list) << Name; - else - Diag(NameLoc, diag::err_redefinition) << Name; - notePreviousDefinition(Def, - NameLoc.isValid() ? NameLoc : KWLoc); - // If this is a redefinition, recover by making this - // struct be anonymous, which will make any later - // references get the previous definition. - Name = nullptr; - Previous.clear(); - Invalid = true; - } - } else { + if (TagDecl *Def = PrevTagDecl->getDefinition()) { // If the type is currently being defined, complain // about a nested redefinition. - auto *TD = Context.getTagDeclType(PrevTagDecl)->getAsTagDecl(); - if (TD->isBeingDefined()) { + if (Def->isBeingDefined()) { Diag(NameLoc, diag::err_nested_redefinition) << Name; Diag(PrevTagDecl->getLocation(), diag::note_previous_definition); Name = nullptr; Previous.clear(); Invalid = true; + } else { + // If we're defining a specialization and the previous + // definition is from an implicit instantiation, don't emit an + // error here; we'll catch this in the general case below. + bool IsExplicitSpecializationAfterInstantiation = false; + if (isMemberSpecialization) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + RD->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + else if (EnumDecl *ED = dyn_cast<EnumDecl>(Def)) + IsExplicitSpecializationAfterInstantiation = + ED->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + } + + // Note that clang allows ODR-like semantics for ObjC/C, i.e., + // do not keep more that one definition around (merge them). + // However, ensure the decl passes the structural compatibility + // check in C11 6.2.7/1 (or 6.1.2.6/1 in C89). + NamedDecl *Hidden = nullptr; + if (SkipBody && (!hasVisibleDefinition(Def, &Hidden) || + getLangOpts().C23)) { + // There is a definition of this tag, but it is not visible. + // We explicitly make use of C++'s one definition rule here, + // and assume that this definition is identical to the hidden + // one we already have. Make the existing definition visible + // and use it in place of this one. + if (!getLangOpts().CPlusPlus) { + // Postpone making the old definition visible until after we + // complete parsing the new one and do the structural + // comparison. + SkipBody->CheckSameAsPrevious = true; + SkipBody->New = createTagFromNewDecl(); + SkipBody->Previous = Def; + + ProcessDeclAttributeList(S, SkipBody->New, Attrs); + return Def; + } else { + SkipBody->ShouldSkip = true; + SkipBody->Previous = Def; + makeMergedDefinitionVisible(Hidden); + // Carry on and handle it like a normal definition. We'll + // skip starting the definition later. + } + } else if (!IsExplicitSpecializationAfterInstantiation) { + // A redeclaration in function prototype scope in C isn't + // visible elsewhere, so merely issue a warning. + if (!getLangOpts().CPlusPlus && + S->containedInPrototypeScope()) + Diag(NameLoc, diag::warn_redefinition_in_param_list) + << Name; + else + Diag(NameLoc, diag::err_redefinition) << Name; + notePreviousDefinition(Def, + NameLoc.isValid() ? NameLoc : KWLoc); + // If this is a redefinition, recover by making this + // struct be anonymous, which will make any later + // references get the previous definition. + Name = nullptr; + Previous.clear(); + Invalid = true; + } } } @@ -18324,14 +18400,14 @@ CreateNewDecl: (IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TagUseKind::Definition) { Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) - << Context.getTagDeclType(New); + << Context.getCanonicalTagType(New); Invalid = true; } if (!Invalid && getLangOpts().CPlusPlus && TUK == TagUseKind::Definition && DC->getDeclKind() == Decl::Enum) { Diag(New->getLocation(), diag::err_type_defined_in_enum) - << Context.getTagDeclType(New); + << Context.getCanonicalTagType(New); Invalid = true; } @@ -18412,7 +18488,8 @@ CreateNewDecl: // In C23 mode, if the declaration is complete, we do not want to // diagnose. if (!getLangOpts().C23 || TUK != TagUseKind::Definition) - Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); + Diag(Loc, diag::warn_decl_in_param_list) + << Context.getCanonicalTagType(New); } } @@ -18444,7 +18521,7 @@ CreateNewDecl: AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. - if (TUK == TagUseKind::Friend) { + if (TUK == TagUseKind::Friend || IsInjectedClassName) { // We might be replacing an existing declaration in the lookup tables; // if so, borrow its access specifier. if (PrevDecl) @@ -18564,14 +18641,12 @@ void Sema::ActOnStartCXXMemberDeclarations( // as if it were a public member name. CXXRecordDecl *InjectedClassName = CXXRecordDecl::Create( Context, Record->getTagKind(), CurContext, Record->getBeginLoc(), - Record->getLocation(), Record->getIdentifier(), - /*PrevDecl=*/nullptr, - /*DelayTypeCreation=*/true); - Context.getTypeDeclType(InjectedClassName, Record); + Record->getLocation(), Record->getIdentifier()); InjectedClassName->setImplicit(); InjectedClassName->setAccess(AS_public); if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) InjectedClassName->setDescribedClassTemplate(Template); + PushOnScopeChains(InjectedClassName, S); assert(InjectedClassName->isInjectedClassName() && "Broken injected-class-name"); @@ -19001,7 +19076,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (!InvalidDecl && getLangOpts().CPlusPlus) { if (Record->isUnion()) { if (const RecordType *RT = EltTy->getAs<RecordType>()) { - CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); + CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getOriginalDecl()); if (RDecl->getDefinition()) { // C++ [class.union]p1: An object of a class with a non-trivial // constructor, a non-trivial copy constructor, a non-trivial @@ -19067,7 +19142,8 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { QualType EltTy = Context.getBaseElementType(FD->getType()); if (const RecordType *RT = EltTy->getAs<RecordType>()) { - CXXRecordDecl *RDecl = cast<CXXRecordDecl>(RT->getDecl()); + CXXRecordDecl *RDecl = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); if (RDecl->getDefinition()) { // We check for copy constructors before constructors // because otherwise we'll never get complaints about @@ -19390,7 +19466,7 @@ bool Sema::EntirelyFunctionPointers(const RecordDecl *Record) { } // If a member is a struct entirely of function pointers, that counts too. if (const RecordType *RT = FieldType->getAs<RecordType>()) { - const RecordDecl *Record = RT->getDecl(); + const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); if (Record->isStruct() && EntirelyFunctionPointers(Record)) return true; } @@ -19548,7 +19624,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, EnclosingDecl->setInvalidDecl(); continue; } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) { - if (Record && FDTTy->getDecl()->hasFlexibleArrayMember()) { + if (Record && FDTTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) { // A type which contains a flexible array member is considered to be a // flexible array member. Record->setHasFlexibleArrayMember(true); @@ -19574,9 +19652,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Ivars can not have abstract class types FD->setInvalidDecl(); } - if (Record && FDTTy->getDecl()->hasObjectMember()) + const RecordDecl *RD = FDTTy->getOriginalDecl()->getDefinitionOrSelf(); + if (Record && RD->hasObjectMember()) Record->setHasObjectMember(true); - if (Record && FDTTy->getDecl()->hasVolatileMember()) + if (Record && RD->hasVolatileMember()) Record->setHasVolatileMember(true); } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object @@ -19607,8 +19686,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->setHasObjectMember(true); else if (Context.getAsArrayType(FD->getType())) { QualType BaseType = Context.getBaseElementType(FD->getType()); - if (BaseType->isRecordType() && - BaseType->castAs<RecordType>()->getDecl()->hasObjectMember()) + if (BaseType->isRecordType() && BaseType->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasObjectMember()) Record->setHasObjectMember(true); else if (BaseType->isObjCObjectPointerType() || BaseType.isObjCGCStrong()) @@ -19641,7 +19722,9 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } if (const auto *RT = FT->getAs<RecordType>()) { - if (RT->getDecl()->getArgPassingRestrictions() == + if (RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->getArgPassingRestrictions() == RecordArgPassingKind::CanNeverPassInRegs) Record->setArgPassingRestrictions( RecordArgPassingKind::CanNeverPassInRegs); @@ -20407,7 +20490,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S, const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast<EnumDecl>(EnumDeclX); - QualType EnumType = Context.getTypeDeclType(Enum); + CanQualType EnumType = Context.getCanonicalTagType(Enum); ProcessDeclAttributeList(S, Enum, Attrs); ProcessAPINotes(Enum); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 16b18bc..7a18510 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -177,7 +177,7 @@ static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { return !Result.empty(); }; - const RecordDecl *Record = RT->getDecl(); + const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); bool foundStarOperator = IsOverloadedOperatorPresent(Record, OO_Star); bool foundArrowOperator = IsOverloadedOperatorPresent(Record, OO_Arrow); if (foundStarOperator && foundArrowOperator) @@ -271,7 +271,8 @@ static bool checkRecordTypeForCapability(Sema &S, QualType Ty) { if (threadSafetyCheckIsSmartPointer(S, RT)) return true; - return checkRecordDeclForAttr<CapabilityAttr>(RT->getDecl()); + return checkRecordDeclForAttr<CapabilityAttr>( + RT->getOriginalDecl()->getDefinitionOrSelf()); } static bool checkRecordTypeForScopedCapability(Sema &S, QualType Ty) { @@ -284,7 +285,8 @@ static bool checkRecordTypeForScopedCapability(Sema &S, QualType Ty) { if (RT->isIncompleteType()) return true; - return checkRecordDeclForAttr<ScopedLockableAttr>(RT->getDecl()); + return checkRecordDeclForAttr<ScopedLockableAttr>( + RT->getOriginalDecl()->getDefinitionOrSelf()); } static bool checkTypedefTypeForCapability(QualType Ty) { @@ -1254,8 +1256,8 @@ bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { // The nonnull attribute, and other similar attributes, can be applied to a // transparent union that contains a pointer type. if (const RecordType *UT = T->getAsUnionType()) { - if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { - RecordDecl *UD = UT->getDecl(); + RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + if (UD->hasAttr<TransparentUnionAttr>()) { for (const auto *I : UD->fields()) { QualType QT = I->getType(); if (QT->isAnyPointerType() || QT->isBlockPointerType()) @@ -3560,7 +3562,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } Ty = getFunctionOrMethodResultType(D); // replace instancetype with the class type - auto Instancetype = S.Context.getObjCInstanceTypeDecl()->getTypeForDecl(); + auto *Instancetype = cast<TypedefType>(S.Context.getTypedefType( + ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, + S.Context.getObjCInstanceTypeDecl())); if (Ty->getAs<TypedefType>() == Instancetype) if (auto *OMD = dyn_cast<ObjCMethodDecl>(D)) if (auto *Interface = OMD->getClassInterface()) @@ -4154,7 +4158,10 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { RecordDecl *RD = nullptr; const auto *TD = dyn_cast<TypedefNameDecl>(D); if (TD && TD->getUnderlyingType()->isUnionType()) - RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); + RD = TD->getUnderlyingType() + ->getAsUnionType() + ->getOriginalDecl() + ->getDefinitionOrSelf(); else RD = dyn_cast<RecordDecl>(D); @@ -4507,7 +4514,7 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { if (const auto *VD = dyn_cast<ValueDecl>(D)) { UnderlyingTy = DiagTy = VD->getType(); } else { - UnderlyingTy = DiagTy = Context.getTagDeclType(cast<TagDecl>(D)); + UnderlyingTy = DiagTy = Context.getCanonicalTagType(cast<TagDecl>(D)); if (const auto *ED = dyn_cast<EnumDecl>(D)) UnderlyingTy = ED->getIntegerType(); } @@ -7441,6 +7448,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_HLSLVkConstantId: S.HLSL().handleVkConstantIdAttr(D, AL); break; + case ParsedAttr::AT_HLSLVkBinding: + S.HLSL().handleVkBindingAttr(D, AL); + break; case ParsedAttr::AT_HLSLSV_GroupThreadID: S.HLSL().handleSV_GroupThreadIDAttr(D, AL); break; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index f5b4614..0477d37 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "TypeLocBuilder.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -1101,15 +1102,13 @@ static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, return std::string(OS.str()); } -static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, - SourceLocation Loc, StringRef Trait, - TemplateArgumentListInfo &Args, - unsigned DiagID) { +static QualType getStdTrait(Sema &S, SourceLocation Loc, StringRef Trait, + TemplateArgumentListInfo &Args, unsigned DiagID) { auto DiagnoseMissing = [&] { if (DiagID) S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(), Args, /*Params*/ nullptr); - return true; + return QualType(); }; // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine. @@ -1122,12 +1121,12 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, // missing specialization, because this can only fail if the user has been // declaring their own names in namespace std or we don't support the // standard library implementation in use. - LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), - Loc, Sema::LookupOrdinaryName); + LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), Loc, + Sema::LookupOrdinaryName); if (!S.LookupQualifiedName(Result, Std)) return DiagnoseMissing(); if (Result.isAmbiguous()) - return true; + return QualType(); ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>(); if (!TraitTD) { @@ -1135,28 +1134,31 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, NamedDecl *Found = *Result.begin(); S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait; S.Diag(Found->getLocation(), diag::note_declared_at); - return true; + return QualType(); } // Build the template-id. - QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args); + QualType TraitTy = S.CheckTemplateIdType(ElaboratedTypeKeyword::None, + TemplateName(TraitTD), Loc, Args); if (TraitTy.isNull()) - return true; + return QualType(); + if (!S.isCompleteType(Loc, TraitTy)) { if (DiagID) S.RequireCompleteType( Loc, TraitTy, DiagID, printTemplateArgs(S.Context.getPrintingPolicy(), Args, TraitTD->getTemplateParameters())); - return true; + return QualType(); } + return TraitTy; +} - CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl(); +static bool lookupMember(Sema &S, CXXRecordDecl *RD, + LookupResult &MemberLookup) { assert(RD && "specialization of class template is not a class?"); - - // Look up the member of the trait type. - S.LookupQualifiedName(TraitMemberLookup, RD); - return TraitMemberLookup.isAmbiguous(); + S.LookupQualifiedName(MemberLookup, RD); + return MemberLookup.isAmbiguous(); } static TemplateArgumentLoc @@ -1178,17 +1180,20 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, EnterExpressionEvaluationContext ContextRAII( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - DeclarationName Value = S.PP.getIdentifierInfo("value"); - LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName); - // Form template argument list for tuple_size<T>. TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); + QualType TraitTy = getStdTrait(S, Loc, "tuple_size", Args, /*DiagID=*/0); + if (TraitTy.isNull()) + return IsTupleLike::NotTupleLike; + + DeclarationName Value = S.PP.getIdentifierInfo("value"); + LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName); + // If there's no tuple_size specialization or the lookup of 'value' is empty, // it's not tuple-like. - if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/ 0) || - R.empty()) + if (lookupMember(S, TraitTy->getAsCXXRecordDecl(), R) || R.empty()) return IsTupleLike::NotTupleLike; // If we get this far, we've committed to the tuple interpretation, but @@ -1228,11 +1233,15 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); + QualType TraitTy = + getStdTrait(S, Loc, "tuple_element", Args, + diag::err_decomp_decl_std_tuple_element_not_specialized); + if (TraitTy.isNull()) + return QualType(); + DeclarationName TypeDN = S.PP.getIdentifierInfo("type"); LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName); - if (lookupStdTypeTraitMember( - S, R, Loc, "tuple_element", Args, - diag::err_decomp_decl_std_tuple_element_not_specialized)) + if (lookupMember(S, TraitTy->getAsCXXRecordDecl(), R)) return QualType(); auto *TD = R.getAsSingle<TypeDecl>(); @@ -1246,7 +1255,8 @@ static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, return QualType(); } - return S.Context.getTypeDeclType(TD); + NestedNameSpecifier Qualifier(TraitTy.getTypePtr()); + return S.Context.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, TD); } namespace { @@ -1452,7 +1462,7 @@ static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc, } // ... [accessible, implied by other rules] base class of E. - S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD), + S.CheckBaseClassAccess(Loc, BaseType, S.Context.getCanonicalTagType(RD), *BestPath, diag::err_decomp_decl_inaccessible_base); AS = BestPath->Access; @@ -1528,8 +1538,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, const auto *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl()); if (!RD) return true; - QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD), - DecompType.getQualifiers()); + QualType BaseType = S.Context.getQualifiedType( + S.Context.getCanonicalTagType(RD), DecompType.getQualifiers()); auto *DD = cast<DecompositionDecl>(Src); unsigned NumFields = llvm::count_if( @@ -2174,7 +2184,10 @@ static bool CheckConstexprCtorInitializer(Sema &SemaRef, return false; } } else if (Field->isAnonymousStructOrUnion()) { - const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl(); + const RecordDecl *RD = Field->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); for (auto *I : RD->fields()) // If an anonymous union contains an anonymous struct of which any member // is initialized, all members must be initialized. @@ -2666,7 +2679,9 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { return DynamicRecursiveASTVisitor::TraverseCXXConstructorDecl(Ctr); } - bool TraverseType(QualType T) override { return true; } + bool TraverseType(QualType T, bool TraverseQualifier) override { + return true; + } bool VisitBlockExpr(BlockExpr *T) override { return true; } } Visitor(*this, FD); @@ -2969,7 +2984,8 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { - const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getOriginalDecl()) + ->getDefinitionOrSelf(); if (Class->isInterface() && (!RD->isInterfaceLike() || KnownBase->getAccessSpecifier() != AS_public)) { @@ -3050,7 +3066,7 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, // FIXME: In a modules build, do we need the entire path to be visible for us // to be able to use the inheritance relationship? - if (!isCompleteType(Loc, Context.getTypeDeclType(Derived)) && + if (!isCompleteType(Loc, Context.getCanonicalTagType(Derived)) && !Derived->isBeingDefined()) return false; @@ -3205,7 +3221,8 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { // We haven't displayed a path to this particular base // class subobject yet. PathDisplayStr += "\n "; - PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); + PathDisplayStr += QualType(Context.getCanonicalTagType(Paths.getOrigin())) + .getAsString(); for (CXXBasePath::const_iterator Element = Path->begin(); Element != Path->end(); ++Element) PathDisplayStr += " -> " + Element->Base->getType().getAsString(); @@ -4245,7 +4262,7 @@ static bool FindBaseInitializer(Sema &SemaRef, CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(), - SemaRef.Context.getTypeDeclType(ClassDecl), + SemaRef.Context.getCanonicalTagType(ClassDecl), BaseType, Paths)) { for (CXXBasePaths::paths_iterator Path = Paths.begin(); Path != Paths.end(); ++Path) { @@ -4481,7 +4498,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (getLangOpts().MSVCCompat && !getLangOpts().CPlusPlus20) { if (auto UnqualifiedBase = R.getAsSingle<ClassTemplateDecl>()) { auto *TempSpec = cast<TemplateSpecializationType>( - UnqualifiedBase->getInjectedClassNameSpecialization()); + UnqualifiedBase->getCanonicalInjectedSpecializationType(Context)); TemplateName TN = TempSpec->getTemplateName(); for (auto const &Base : ClassDecl->bases()) { auto BaseTemplate = @@ -4545,14 +4562,29 @@ Sema::BuildMemInitializer(Decl *ConstructorD, } if (BaseType.isNull()) { - BaseType = getElaboratedType(ElaboratedTypeKeyword::None, SS, - Context.getTypeDeclType(TyD)); MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); - TInfo = Context.CreateTypeSourceInfo(BaseType); - ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>(); - TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); - TL.setElaboratedKeywordLoc(SourceLocation()); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); + + TypeLocBuilder TLB; + if (const auto *TD = dyn_cast<TagDecl>(TyD)) { + BaseType = Context.getTagType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TD, /*OwnsTag=*/false); + auto TL = TLB.push<TagTypeLoc>(BaseType); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(IdLoc); + } else if (auto *TN = dyn_cast<TypedefNameDecl>(TyD)) { + BaseType = Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TN); + TLB.push<TypedefTypeLoc>(BaseType).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), IdLoc); + } else { + // FIXME: What else can appear here? + assert(SS.isEmpty()); + BaseType = Context.getTypeDeclType(TyD); + TLB.pushTypeSpec(BaseType).setNameLoc(IdLoc); + } + TInfo = TLB.getTypeSourceInfo(Context, BaseType); } } @@ -4661,10 +4693,12 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } + CanQualType ClassType = Context.getCanonicalTagType(ClassDecl); + SourceRange InitRange = Init->getSourceRange(); // Initialize the object. - InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( - QualType(ClassDecl->getTypeForDecl(), 0)); + InitializedEntity DelegationEntity = + InitializedEntity::InitializeDelegation(ClassType); InitializationKind Kind = InitList ? InitializationKind::CreateDirectList( NameLoc, Init->getBeginLoc(), Init->getEndLoc()) @@ -4686,9 +4720,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, } if (DelegationInit.isInvalid()) { - DelegationInit = - CreateRecoveryExpr(InitRange.getBegin(), InitRange.getEnd(), Args, - QualType(ClassDecl->getTypeForDecl(), 0)); + DelegationInit = CreateRecoveryExpr(InitRange.getBegin(), + InitRange.getEnd(), Args, ClassType); if (DelegationInit.isInvalid()) return true; } else { @@ -4753,8 +4786,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, const CXXBaseSpecifier *DirectBaseSpec = nullptr; const CXXBaseSpecifier *VirtualBaseSpec = nullptr; if (!Dependent) { - if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), - BaseType)) + if (declaresSameEntity(ClassDecl, BaseType->getAsCXXRecordDecl())) return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, @@ -4774,7 +4806,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, Dependent = true; else return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) - << BaseType << Context.getTypeDeclType(ClassDecl) + << BaseType << Context.getCanonicalTagType(ClassDecl) << BaseTInfo->getTypeLoc().getSourceRange(); } } @@ -5078,9 +5110,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, if (FieldBaseElementType->isReferenceType()) { SemaRef.Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) - << (int)Constructor->isImplicit() - << SemaRef.Context.getTagDeclType(Constructor->getParent()) - << 0 << Field->getDeclName(); + << (int)Constructor->isImplicit() + << SemaRef.Context.getCanonicalTagType(Constructor->getParent()) << 0 + << Field->getDeclName(); SemaRef.Diag(Field->getLocation(), diag::note_declared_at); return true; } @@ -5088,9 +5120,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, if (FieldBaseElementType.isConstQualified()) { SemaRef.Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) - << (int)Constructor->isImplicit() - << SemaRef.Context.getTagDeclType(Constructor->getParent()) - << 1 << Field->getDeclName(); + << (int)Constructor->isImplicit() + << SemaRef.Context.getCanonicalTagType(Constructor->getParent()) << 1 + << Field->getDeclName(); SemaRef.Diag(Field->getLocation(), diag::note_declared_at); return true; } @@ -5391,7 +5423,7 @@ static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location, S.CheckDestructorAccess(Base.getBeginLoc(), Dtor, S.PDiag(diag::err_access_dtor_base) << Base.getType() << Base.getSourceRange(), - S.Context.getTypeDeclType(ClassDecl)); + S.Context.getCanonicalTagType(ClassDecl)); S.MarkFunctionReferenced(Location, Dtor); S.DiagnoseUseOfDecl(Dtor, Location); @@ -5594,9 +5626,9 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) { if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl(); if (RD->isAnonymousStructOrUnion()) { - for (auto *Field : RD->fields()) + for (auto *Field : RD->getDefinitionOrSelf()->fields()) PopulateKeysForFields(Field, IdealInits); return; } @@ -5928,16 +5960,14 @@ void Sema::MarkVirtualBaseDestructorsReferenced( if (!Dtor) continue; - if (CheckDestructorAccess( - ClassDecl->getLocation(), Dtor, - PDiag(diag::err_access_dtor_vbase) - << Context.getTypeDeclType(ClassDecl) << VBase.getType(), - Context.getTypeDeclType(ClassDecl)) == - AR_accessible) { + CanQualType CT = Context.getCanonicalTagType(ClassDecl); + if (CheckDestructorAccess(ClassDecl->getLocation(), Dtor, + PDiag(diag::err_access_dtor_vbase) + << CT << VBase.getType(), + CT) == AR_accessible) { CheckDerivedToBaseConversion( - Context.getTypeDeclType(ClassDecl), VBase.getType(), - diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(), - SourceRange(), DeclarationName(), nullptr); + CT, VBase.getType(), diag::err_access_dtor_vbase, 0, + ClassDecl->getLocation(), SourceRange(), DeclarationName(), nullptr); } MarkFunctionReferenced(Location, Dtor); @@ -6052,10 +6082,8 @@ struct AbstractUsageInfo { bool Invalid; AbstractUsageInfo(Sema &S, CXXRecordDecl *Record) - : S(S), Record(Record), - AbstractType(S.Context.getCanonicalType( - S.Context.getTypeDeclType(Record))), - Invalid(false) {} + : S(S), Record(Record), + AbstractType(S.Context.getCanonicalTagType(Record)), Invalid(false) {} void DiagnoseAbstractType() { if (Invalid) return; @@ -6868,8 +6896,8 @@ static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64(); uint64_t TypeSize = isAArch64 ? 128 : 64; - if (CopyCtorIsTrivial && - S.getASTContext().getTypeSize(D->getTypeForDecl()) <= TypeSize) + if (CopyCtorIsTrivial && S.getASTContext().getTypeSize( + S.Context.getCanonicalTagType(D)) <= TypeSize) return true; return false; } @@ -7000,7 +7028,8 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) && !Record->hasAttr<FinalAttr>()) Diag(dtor ? dtor->getLocation() : Record->getLocation(), - diag::warn_non_virtual_dtor) << Context.getRecordType(Record); + diag::warn_non_virtual_dtor) + << Context.getCanonicalTagType(Record); } if (Record->isAbstract()) { @@ -7022,7 +7051,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { (FA->isSpelledAsSealed() ? " sealed" : " final")); Diag(Record->getLocation(), diag::note_final_dtor_non_final_class_silence) - << Context.getRecordType(Record) << FA->isSpelledAsSealed(); + << Context.getCanonicalTagType(Record) << FA->isSpelledAsSealed(); } } } @@ -7177,7 +7206,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { return true; }; EffectivelyConstexprDestructor = - Check(QualType(Record->getTypeForDecl(), 0), Check); + Check(Context.getCanonicalTagType(Record), Check); } // Define defaulted constexpr virtual functions that override a base class @@ -7333,7 +7362,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { NewDecls.empty() ? NewKind : DeleteKind); Diag(Record->getLocation(), diag::err_type_aware_allocator_missing_matching_operator) - << FoundOperator << Context.getRecordType(Record) + << FoundOperator << Context.getCanonicalTagType(Record) << MissingOperator; for (auto MD : NewDecls) Diag(MD->getLocation(), @@ -7572,7 +7601,9 @@ static bool defaultedSpecialMemberIsConstexpr( const RecordType *BaseType = B.getType()->getAs<RecordType>(); if (!BaseType) continue; - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(BaseType->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, InheritedCtor, Inherited)) return false; @@ -7595,7 +7626,9 @@ static bool defaultedSpecialMemberIsConstexpr( continue; QualType BaseType = S.Context.getBaseElementType(F->getType()); if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + CXXRecordDecl *FieldRecDecl = + cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, BaseType.getCVRQualifiers(), ConstArg && !F->isMutable())) @@ -7782,9 +7815,9 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, ReturnType = Type->getReturnType(); QualType ThisType = MD->getFunctionObjectParameterType(); - QualType DeclType = Context.getTypeDeclType(RD); - DeclType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, - DeclType, nullptr); + QualType DeclType = + Context.getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, RD, /*OwnsTag=*/false); DeclType = Context.getAddrSpaceQualType( DeclType, ThisType.getQualifiers().getAddressSpace()); QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType); @@ -7819,7 +7852,7 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, if (!ExplicitObjectParameter.isNull() && (!ExplicitObjectParameter->isReferenceType() || !Context.hasSameType(ExplicitObjectParameter.getNonReferenceType(), - Context.getRecordType(RD)))) { + Context.getCanonicalTagType(RD)))) { if (DeleteOnTypeMismatch) ShouldDeleteForTypeMismatch = true; else { @@ -8278,7 +8311,7 @@ private: Best->FoundDecl.getDecl()->isCXXClassMember()) { QualType ObjectType = Subobj.Kind == Subobject::Member ? Args[0]->getType() - : S.Context.getRecordType(RD); + : S.Context.getCanonicalTagType(RD); if (!S.isMemberAccessibleForDeletion( ArgClass, Best->FoundDecl, ObjectType, Subobj.Loc, Diagnose == ExplainDeleted @@ -8979,7 +9012,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, bool Ok = !IsMethod || FD->hasCXXExplicitFunctionObjectParameter(); QualType ExpectedTy; if (RD) - ExpectedTy = Context.getRecordType(RD); + ExpectedTy = Context.getCanonicalTagType(RD); if (auto *Ref = CTy->getAs<LValueReferenceType>()) { CTy = Ref->getPointeeType(); if (RD) @@ -9002,7 +9035,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, // corresponding defaulted 'operator<=>' already. if (!FD->isImplicit()) { if (RD) { - QualType PlainTy = Context.getRecordType(RD); + CanQualType PlainTy = Context.getCanonicalTagType(RD); QualType RefTy = Context.getLValueReferenceType(PlainTy.withConst()); Diag(FD->getLocation(), diag::err_defaulted_comparison_param) @@ -9033,7 +9066,7 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD, } else { // Out of class, require the defaulted comparison to be a friend (of a // complete type, per CWG2547). - if (RequireCompleteType(FD->getLocation(), Context.getRecordType(RD), + if (RequireCompleteType(FD->getLocation(), Context.getCanonicalTagType(RD), diag::err_defaulted_comparison_not_friend, int(DCK), int(1))) return true; @@ -9486,15 +9519,15 @@ bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, CXXMethodDecl *target) { /// If we're operating on a base class, the object type is the /// type of this special member. - QualType objectTy; + CanQualType objectTy; AccessSpecifier access = target->getAccess(); if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) { - objectTy = S.Context.getTypeDeclType(MD->getParent()); + objectTy = S.Context.getCanonicalTagType(MD->getParent()); access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); // If we're operating on a field, the object type is the type of the field. } else { - objectTy = S.Context.getTypeDeclType(target->getParent()); + objectTy = S.Context.getCanonicalTagType(target->getParent()); } return S.isMemberAccessibleForDeletion( @@ -9912,7 +9945,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, // results in an ambiguity or in a function that is deleted or inaccessible if (CSM == CXXSpecialMemberKind::Destructor && MD->isVirtual()) { FunctionDecl *OperatorDelete = nullptr; - QualType DeallocType = Context.getRecordType(RD); + CanQualType DeallocType = Context.getCanonicalTagType(RD); DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); ImplicitDeallocationParameters IDP = { @@ -10245,7 +10278,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMemberKind CSM) { - QualType Ty = Context.getRecordType(RD); + CanQualType Ty = Context.getCanonicalTagType(RD); bool ConstArg = (CSM == CXXSpecialMemberKind::CopyConstructor || CSM == CXXSpecialMemberKind::CopyAssignment); @@ -10293,9 +10326,9 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, ClangABICompat14)) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) - << Param0->getSourceRange() << Param0->getType() - << Context.getLValueReferenceType( - Context.getRecordType(RD).withConst()); + << Param0->getSourceRange() << Param0->getType() + << Context.getLValueReferenceType( + Context.getCanonicalTagType(RD).withConst()); return false; } @@ -10312,8 +10345,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, if (!RT || RT->getPointeeType().getCVRQualifiers()) { if (Diagnose) Diag(Param0->getLocation(), diag::note_nontrivial_param_type) - << Param0->getSourceRange() << Param0->getType() - << Context.getRValueReferenceType(Context.getRecordType(RD)); + << Param0->getSourceRange() << Param0->getType() + << Context.getRValueReferenceType(Context.getCanonicalTagType(RD)); return false; } break; @@ -10432,8 +10465,10 @@ public: /// method overloads virtual methods in a base class without overriding any, /// to be used with CXXRecordDecl::lookupInBases(). bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - RecordDecl *BaseRecord = - Specifier->getType()->castAs<RecordType>()->getDecl(); + RecordDecl *BaseRecord = Specifier->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); DeclarationName Name = Method->getDeclName(); assert(Name.getNameKind() == DeclarationName::Identifier); @@ -10591,7 +10626,8 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>()) if (!RT->isDependentType() && - !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) { + !cast<CXXRecordDecl>(RT->getOriginalDecl()->getDefinitionOrSelf()) + ->canPassInRegisters()) { PrintDiagAndRemoveAttr(5); return; } @@ -10626,7 +10662,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { void Sema::checkIncorrectVTablePointerAuthenticationAttribute( CXXRecordDecl &RD) { - if (RequireCompleteType(RD.getLocation(), Context.getRecordType(&RD), + if (RequireCompleteType(RD.getLocation(), Context.getCanonicalTagType(&RD), diag::err_incomplete_type_vtable_pointer_auth)) return; @@ -11056,9 +11092,10 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { if (!Constructor->isInvalidDecl() && Constructor->hasOneParamOrDefaultArgs() && !Constructor->isFunctionTemplateSpecialization()) { - QualType ParamType = Constructor->getParamDecl(0)->getType(); - QualType ClassTy = Context.getTagDeclType(ClassDecl); - if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { + CanQualType ParamType = + Constructor->getParamDecl(0)->getType()->getCanonicalTypeUnqualified(); + CanQualType ClassTy = Context.getCanonicalTagType(ClassDecl); + if (ParamType == ClassTy) { SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); const char *ConstRef = Constructor->getParamDecl(0)->getIdentifier() ? "const &" @@ -11429,8 +11466,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { // same object type (or a reference to it), to a (possibly // cv-qualified) base class of that type (or a reference to it), // or to (possibly cv-qualified) void. - QualType ClassType - = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + CanQualType ClassType = Context.getCanonicalTagType(ClassDecl); if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>()) ConvType = ConvTypeRef->getPointeeType(); if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && @@ -11698,8 +11734,8 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, const QualifiedTemplateName *Qualifiers = SpecifiedName.getAsQualifiedTemplateName(); assert(Qualifiers && "expected QualifiedTemplate"); - bool SimplyWritten = !Qualifiers->hasTemplateKeyword() && - Qualifiers->getQualifier() == nullptr; + bool SimplyWritten = + !Qualifiers->hasTemplateKeyword() && !Qualifiers->getQualifier(); if (SimplyWritten && TemplateMatches) AcceptableReturnType = true; else { @@ -12004,10 +12040,11 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind, // Use an elaborated type for diagnostics which has a name containing the // prepended 'std' namespace but not any inline namespace names. auto TyForDiags = [&](ComparisonCategoryInfo *Info) { - auto *NNS = - NestedNameSpecifier::Create(Context, nullptr, getStdNamespace()); - return Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, - Info->getType()); + NestedNameSpecifier Qualifier(Context, getStdNamespace(), + /*Prefix=*/std::nullopt); + return Context.getTagType(ElaboratedTypeKeyword::None, Qualifier, + Info->Record, + /*OwnsTag=*/false); }; // Check if we've already successfully checked the comparison category type @@ -12143,26 +12180,14 @@ static bool isStdClassTemplate(Sema &S, QualType SugaredType, QualType *TypeArg, ClassTemplateDecl *Template = nullptr; ArrayRef<TemplateArgument> Arguments; - { - const TemplateSpecializationType *TST = - SugaredType->getAsNonAliasTemplateSpecializationType(); - if (!TST) - if (const auto *ICN = SugaredType->getAs<InjectedClassNameType>()) - TST = ICN->getInjectedTST(); - if (TST) { - Template = dyn_cast_or_null<ClassTemplateDecl>( - TST->getTemplateName().getAsTemplateDecl()); - Arguments = TST->template_arguments(); - } else if (const RecordType *RT = SugaredType->getAs<RecordType>()) { - ClassTemplateSpecializationDecl *Specialization = - dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); - if (!Specialization) { - ReportMatchingNameAsMalformed(RT->getDecl()); - return false; - } - Template = Specialization->getSpecializedTemplate(); - Arguments = Specialization->getTemplateArgs().asArray(); - } + if (const TemplateSpecializationType *TST = + SugaredType->getAsNonAliasTemplateSpecializationType()) { + Template = dyn_cast_or_null<ClassTemplateDecl>( + TST->getTemplateName().getAsTemplateDecl()); + Arguments = TST->template_arguments(); + } else if (const auto *TT = SugaredType->getAs<TagType>()) { + Template = TT->getTemplateDecl(); + Arguments = TT->getTemplateArgs(S.Context); } if (!Template) { @@ -12288,13 +12313,8 @@ static QualType BuildStdClassTemplate(Sema &S, ClassTemplateDecl *CTD, auto TSI = S.Context.getTrivialTypeSourceInfo(TypeParam, Loc); Args.addArgument(TemplateArgumentLoc(TemplateArgument(TypeParam), TSI)); - QualType T = S.CheckTemplateIdType(TemplateName(CTD), Loc, Args); - if (T.isNull()) - return QualType(); - - return S.Context.getElaboratedType( - ElaboratedTypeKeyword::None, - NestedNameSpecifier::Create(S.Context, nullptr, S.getStdNamespace()), T); + return S.CheckTemplateIdType(ElaboratedTypeKeyword::None, TemplateName(CTD), + Loc, Args); } QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { @@ -12436,9 +12456,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, S = S->getDeclParent(); UsingDirectiveDecl *UDir = nullptr; - NestedNameSpecifier *Qualifier = nullptr; - if (SS.isSet()) - Qualifier = SS.getScopeRep(); + NestedNameSpecifier Qualifier = SS.getScopeRep(); // Lookup namespace name. LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); @@ -12450,14 +12468,16 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, R.clear(); // Allow "using namespace std;" or "using namespace ::std;" even if // "std" hasn't been defined yet, for GCC compatibility. - if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && + if ((!Qualifier || + Qualifier.getKind() == NestedNameSpecifier::Kind::Global) && NamespcName->isStr("std")) { Diag(IdentLoc, diag::ext_using_undefined_std); R.addDecl(getOrCreateStdNamespace()); R.resolveKind(); } // Otherwise, attempt typo correction. - else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); + else + TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); } if (!R.empty()) { @@ -12584,7 +12604,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) return nullptr; } else { - if (!SS.getScopeRep()->containsUnexpandedParameterPack() && + if (!SS.getScopeRep().containsUnexpandedParameterPack() && !TargetNameInfo.containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); @@ -12869,7 +12889,7 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, UsingDecl *Using = cast<UsingDecl>(BUD); bool IsVirtualBase = isVirtualDirectBase(cast<CXXRecordDecl>(CurContext), - Using->getQualifier()->getAsRecordDecl()); + Using->getQualifier().getAsRecordDecl()); Shadow = ConstructorUsingShadowDecl::Create( Context, CurContext, Using->getLocation(), Using, Orig, IsVirtualBase); } else { @@ -12935,7 +12955,7 @@ namespace { class UsingValidatorCCC final : public CorrectionCandidateCallback { public: UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, - NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf) + NestedNameSpecifier NNS, CXXRecordDecl *RequireMemberOf) : HasTypenameKeyword(HasTypenameKeyword), IsInstantiation(IsInstantiation), OldNNS(NNS), RequireMemberOf(RequireMemberOf) {} @@ -12962,24 +12982,23 @@ public: ASTContext &Ctx = ND->getASTContext(); if (!Ctx.getLangOpts().CPlusPlus11) return false; - QualType FoundType = Ctx.getRecordType(FoundRecord); + CanQualType FoundType = Ctx.getCanonicalTagType(FoundRecord); // Check that the injected-class-name is named as a member of its own // type; we don't want to suggest 'using Derived::Base;', since that // means something else. - NestedNameSpecifier *Specifier = - Candidate.WillReplaceSpecifier() - ? Candidate.getCorrectionSpecifier() - : OldNNS; - if (!Specifier->getAsType() || - !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType)) + NestedNameSpecifier Specifier = Candidate.WillReplaceSpecifier() + ? Candidate.getCorrectionSpecifier() + : OldNNS; + if (Specifier.getKind() != NestedNameSpecifier::Kind::Type || + !Ctx.hasSameType(QualType(Specifier.getAsType(), 0), FoundType)) return false; // Check that this inheriting constructor declaration actually names a // direct base class of the current class. bool AnyDependentBases = false; if (!findDirectBaseWithType(RequireMemberOf, - Ctx.getRecordType(FoundRecord), + Ctx.getCanonicalTagType(FoundRecord), AnyDependentBases) && !AnyDependentBases) return false; @@ -13009,7 +13028,7 @@ public: private: bool HasTypenameKeyword; bool IsInstantiation; - NestedNameSpecifier *OldNNS; + NestedNameSpecifier OldNNS; CXXRecordDecl *RequireMemberOf; }; } // end anonymous namespace @@ -13051,7 +13070,7 @@ NamedDecl *Sema::BuildUsingDeclaration( if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName) if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext)) UsingName.setName(Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(RD)))); + Context.getCanonicalTagType(RD))); // Do the redeclaration lookup in the current scope. LookupResult Previous(*this, UsingName, LookupUsingDeclName, @@ -13154,7 +13173,7 @@ NamedDecl *Sema::BuildUsingDeclaration( // equal to that of the current context. if (CurContext->isRecord()) { R.setBaseObjectType( - Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext))); + Context.getCanonicalTagType(cast<CXXRecordDecl>(CurContext))); } LookupQualifiedName(R, LookupContext); @@ -13220,7 +13239,7 @@ NamedDecl *Sema::BuildUsingDeclaration( // constructor. auto *CurClass = cast<CXXRecordDecl>(CurContext); UsingName.setName(Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Context.getRecordType(CurClass)))); + Context.getCanonicalTagType(CurClass))); UsingName.setNamedTypeInfo(nullptr); for (auto *Ctor : LookupConstructors(RD)) R.addDecl(Ctor); @@ -13366,20 +13385,16 @@ NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); - const Type *SourceType = UD->getQualifier()->getAsType(); - assert(SourceType && - "Using decl naming constructor doesn't have type in scope spec."); + QualType SourceType(UD->getQualifier().getAsType(), 0); CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext); // Check whether the named type is a direct base class. bool AnyDependentBases = false; - auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0), - AnyDependentBases); + auto *Base = + findDirectBaseWithType(TargetClass, SourceType, AnyDependentBases); if (!Base && !AnyDependentBases) { - Diag(UD->getUsingLoc(), - diag::err_using_decl_constructor_not_in_direct_base) - << UD->getNameInfo().getSourceRange() - << QualType(SourceType, 0) << TargetClass; + Diag(UD->getUsingLoc(), diag::err_using_decl_constructor_not_in_direct_base) + << UD->getNameInfo().getSourceRange() << SourceType << TargetClass; UD->setInvalidDecl(); return true; } @@ -13395,7 +13410,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Prev) { - NestedNameSpecifier *Qual = SS.getScopeRep(); + NestedNameSpecifier Qual = SS.getScopeRep(); // C++03 [namespace.udecl]p8: // C++0x [namespace.udecl]p10: @@ -13410,7 +13425,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // declaration in the same scope. // FIXME: How should we check for dependent type-type conflicts at block // scope? - if (Qual->isDependent() && !HasTypenameKeyword) { + if (Qual.isDependent() && !HasTypenameKeyword) { for (auto *D : Prev) { if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) { bool OldCouldBeEnumerator = @@ -13427,13 +13442,12 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, return false; } - const NestedNameSpecifier *CNNS = - Context.getCanonicalNestedNameSpecifier(Qual); + NestedNameSpecifier CNNS = Qual.getCanonical(); for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { NamedDecl *D = *I; bool DTypename; - NestedNameSpecifier *DQual; + NestedNameSpecifier DQual = std::nullopt; if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { DTypename = UD->hasTypename(); DQual = UD->getQualifier(); @@ -13454,7 +13468,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // using decls differ if they name different scopes (but note that // template instantiation can cause this check to trigger when it // didn't before instantiation). - if (CNNS != Context.getCanonicalNestedNameSpecifier(DQual)) + if (CNNS != DQual.getCanonical()) continue; Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); @@ -13914,7 +13928,8 @@ bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { if (!RT) return false; - auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl()); + auto *BaseClass = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); if (auto *BaseCtor = SMOR.getMethod()) { visitSubobjectCall(Base, BaseCtor); @@ -13940,8 +13955,9 @@ bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { ExceptSpec.CalledExpr(E); } else if (auto *RT = S.Context.getBaseElementType(FD->getType()) ->getAs<RecordType>()) { - visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD, - FD->getType().getCVRQualifiers()); + visitClassSubobject( + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(), FD, + FD->getType().getCVRQualifiers()); } return false; } @@ -14003,7 +14019,7 @@ ComputeDefaultedSpecialMemberExceptionSpec( // attempting to resolve an exception specification before it's known // at a higher level. if (S.RequireCompleteType(MD->getLocation(), - S.Context.getRecordType(ClassDecl), + S.Context.getCanonicalTagType(ClassDecl), diag::err_exception_spec_incomplete_type)) return Info.ExceptSpec; @@ -14134,8 +14150,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( *this, ClassDecl, CXXSpecialMemberKind::DefaultConstructor, false); // Create the actual constructor declaration. - CanQualType ClassType - = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + CanQualType ClassType = Context.getCanonicalTagType(ClassDecl); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(ClassType); @@ -14420,8 +14435,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { *this, ClassDecl, CXXSpecialMemberKind::Destructor, false); // Create the actual destructor declaration. - CanQualType ClassType - = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + CanQualType ClassType = Context.getCanonicalTagType(ClassDecl); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(ClassType); @@ -14759,9 +14773,10 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, VK_PRValue, OK_Ordinary, Loc, false, S.CurFPFeatureOverrides()); const Type *E = T->getBaseElementTypeUnsafe(); - bool NeedsCollectableMemCpy = - E->isRecordType() && - E->castAs<RecordType>()->getDecl()->hasObjectMember(); + bool NeedsCollectableMemCpy = E->isRecordType() && E->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasObjectMember(); // Create a reference to the __builtin_objc_memmove_collectable function StringRef MemCpyName = NeedsCollectableMemCpy ? @@ -14838,7 +14853,8 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // ignoring any possible virtual overriding functions in more derived // classes); if (const RecordType *RecordTy = T->getAs<RecordType>()) { - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + CXXRecordDecl *ClassDecl = + cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); // Look for operator=. DeclarationName Name @@ -14885,10 +14901,9 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // reference to operator=; this is required to suppress the virtual // call mechanism. CXXScopeSpec SS; + // FIXME: Don't canonicalize this. const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); - SS.MakeTrivial(S.Context, - NestedNameSpecifier::Create(S.Context, nullptr, CanonicalT), - Loc); + SS.MakeTrivial(S.Context, NestedNameSpecifier(CanonicalT), Loc); // Create the reference to operator=. ExprResult OpEqualRef @@ -15042,9 +15057,9 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { if (DSM.isAlreadyBeingDeclared()) return nullptr; - QualType ArgType = Context.getTypeDeclType(ClassDecl); - ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, - ArgType, nullptr); + QualType ArgType = Context.getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, ClassDecl, + /*OwnsTag=*/false); LangAS AS = getDefaultCXXMethodAddrSpace(); if (AS != LangAS::Default) ArgType = Context.getAddrSpaceQualType(ArgType, AS); @@ -15303,7 +15318,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Check for members of reference type; we can't copy those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + << Context.getCanonicalTagType(ClassDecl) << 0 + << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; @@ -15313,7 +15329,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, QualType BaseType = Context.getBaseElementType(Field->getType()); if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + << Context.getCanonicalTagType(ClassDecl) << 1 + << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; @@ -15398,9 +15415,9 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { // Note: The following rules are largely analoguous to the move // constructor rules. - QualType ArgType = Context.getTypeDeclType(ClassDecl); - ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, - ArgType, nullptr); + QualType ArgType = Context.getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, ClassDecl, + /*OwnsTag=*/false); LangAS AS = getDefaultCXXMethodAddrSpace(); if (AS != LangAS::Default) ArgType = Context.getAddrSpaceQualType(ArgType, AS); @@ -15690,7 +15707,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // Check for members of reference type; we can't move those. if (Field->getType()->isReferenceType()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + << Context.getCanonicalTagType(ClassDecl) << 0 + << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; @@ -15700,7 +15718,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, QualType BaseType = Context.getBaseElementType(Field->getType()); if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) { Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) - << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + << Context.getCanonicalTagType(ClassDecl) << 1 + << Field->getDeclName(); Diag(Field->getLocation(), diag::note_declared_at); Invalid = true; continue; @@ -15791,10 +15810,10 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( if (DSM.isAlreadyBeingDeclared()) return nullptr; - QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ClassType = Context.getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, ClassDecl, + /*OwnsTag=*/false); QualType ArgType = ClassType; - ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, - ArgType, nullptr); bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); @@ -15938,11 +15957,11 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( if (DSM.isAlreadyBeingDeclared()) return nullptr; - QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ClassType = Context.getTagType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, ClassDecl, + /*OwnsTag=*/false); QualType ArgType = ClassType; - ArgType = Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, - ArgType, nullptr); LangAS AS = getDefaultCXXMethodAddrSpace(); if (AS != LangAS::Default) ArgType = Context.getAddrSpaceQualType(ClassType, AS); @@ -16297,7 +16316,8 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->getInit() && VD->getInit()->containsErrors()) return; - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); + CXXRecordDecl *ClassDecl = + cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf(); if (ClassDecl->isInvalidDecl()) return; if (ClassDecl->hasIrrelevantDestructor()) return; if (ClassDecl->isDependentContext()) return; @@ -16639,10 +16659,10 @@ static inline bool CheckOperatorNewDeleteTypes( if (CheckType(SizeParameterIndex, SemaRef.Context.getSizeType(), "size_t")) return true; - TypeDecl *StdAlignValTDecl = SemaRef.getStdAlignValT(); - QualType StdAlignValT = - StdAlignValTDecl ? SemaRef.Context.getTypeDeclType(StdAlignValTDecl) - : QualType(); + TagDecl *StdAlignValTDecl = SemaRef.getStdAlignValT(); + CanQualType StdAlignValT = + StdAlignValTDecl ? SemaRef.Context.getCanonicalTagType(StdAlignValTDecl) + : CanQualType(); if (CheckType(SizeParameterIndex + 1, StdAlignValT, "std::align_val_t")) return true; @@ -16682,8 +16702,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { auto *MD = dyn_cast<CXXMethodDecl>(FnDecl); auto ConstructDestroyingDeleteAddressType = [&]() { assert(MD); - return SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType( - SemaRef.Context.getRecordType(MD->getParent()))); + return SemaRef.Context.getPointerType( + SemaRef.Context.getCanonicalTagType(MD->getParent())); }; // C++ P2719: A destroying operator delete cannot be type aware @@ -16722,8 +16742,8 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { // function shall be of type void *. CanQualType ExpectedAddressParamType = MD && IsPotentiallyDestroyingOperatorDelete(SemaRef, MD) - ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType( - SemaRef.Context.getRecordType(MD->getParent()))) + ? SemaRef.Context.getPointerType( + SemaRef.Context.getCanonicalTagType(MD->getParent())) : SemaRef.Context.VoidPtrTy; // C++ [basic.stc.dynamic.deallocation]p2: @@ -17954,27 +17974,14 @@ DeclResult Sema::ActOnTemplatedFriendTag( /*OOK=*/OffsetOfKind::Outside); } + TypeSourceInfo *TSI = nullptr; ElaboratedTypeKeyword Keyword = TypeWithKeyword::getKeywordForTagTypeKind(Kind); - QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, - *Name, NameLoc); + QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, *Name, + NameLoc, &TSI, /*DeducedTSTContext=*/true); if (T.isNull()) return true; - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = - TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); - TL.setElaboratedKeywordLoc(TagLoc); - TL.setQualifierLoc(QualifierLoc); - TL.setNameLoc(NameLoc); - } else { - ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); - TL.setElaboratedKeywordLoc(TagLoc); - TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc); - } - FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, TSI, FriendLoc, EllipsisLoc, TempParamLists); @@ -18286,7 +18293,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // - There's a non-dependent scope specifier, in which case we // compute it and do a previous lookup there for a function // or function template. - } else if (!SS.getScopeRep()->isDependent()) { + } else if (!SS.getScopeRep().isDependent()) { DC = computeDeclContext(SS); if (!DC) return nullptr; @@ -18793,7 +18800,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, // complete at the point of declaration of D::f or shall be the class // type D. if (const RecordType *RT = NewClassTy->getAs<RecordType>()) { - if (!RT->isBeingDefined() && + if (!RT->getOriginalDecl()->isEntityBeingDefined() && RequireCompleteType(New->getLocation(), NewClassTy, diag::err_covariant_return_incomplete, New->getDeclName())) @@ -19148,8 +19155,9 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, return; for (const auto &I : RD->bases()) { - const auto *Base = - cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); + const auto *Base = cast<CXXRecordDecl>( + I.getType()->castAs<RecordType>()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (Base->getNumVBases() == 0) continue; MarkVirtualMembersReferenced(Loc, Base); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index bbd1049..88ed83e 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -591,12 +591,13 @@ void SemaObjC::ActOnSuperClassOfClassInterface( // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. if (const TypedefNameDecl *TDecl = - dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { + dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) { SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); - SuperClassType = Context.getTypeDeclType(TDecl); + SuperClassType = Context.getTypeDeclType( + ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, TDecl); // This handles the following case: // @interface NewI @end @@ -1389,11 +1390,9 @@ class ObjCTypeArgOrProtocolValidatorCCC final // Make sure the type is something we would accept as a type // argument. - auto type = Context.getTypeDeclType(typeDecl); - if (type->isObjCObjectPointerType() || - type->isBlockPointerType() || + if (CanQualType type = Context.getCanonicalTypeDeclType(typeDecl); type->isDependentType() || - type->isObjCObjectType()) + isa<ObjCObjectPointerType, BlockPointerType, ObjCObjectType>(type)) return true; return false; @@ -1589,7 +1588,9 @@ void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers( unsigned diagID; // unused QualType type; if (auto *actualTypeDecl = dyn_cast<TypeDecl *>(typeDecl)) - type = Context.getTypeDeclType(actualTypeDecl); + type = + Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, actualTypeDecl); else type = Context.getObjCInterfaceType(cast<ObjCInterfaceDecl *>(typeDecl)); TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc); @@ -3231,8 +3232,10 @@ static bool tryMatchRecordTypes(ASTContext &Context, assert(lt && rt && lt != rt); if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false; - RecordDecl *left = cast<RecordType>(lt)->getDecl(); - RecordDecl *right = cast<RecordType>(rt)->getDecl(); + RecordDecl *left = + cast<RecordType>(lt)->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *right = + cast<RecordType>(rt)->getOriginalDecl()->getDefinitionOrSelf(); // Require union-hood to match. if (left->isUnion() != right->isUnion()) return false; @@ -3846,7 +3849,9 @@ static bool IsVariableSizedType(QualType T) { if (T->isIncompleteArrayType()) return true; const auto *RecordTy = T->getAs<RecordType>(); - return (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()); + return (RecordTy && RecordTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()); } static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { @@ -3892,7 +3897,9 @@ static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { << TagTypeKind::Class; // Use "class" for Obj-C. IsInvalidIvar = true; } else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) { - if (RecordTy->getDecl()->hasFlexibleArrayMember()) { + if (RecordTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) { S.Diag(ivar->getLocation(), diag::err_objc_variable_sized_type_not_at_end) << ivar->getDeclName() << IvarTy; @@ -5537,7 +5544,8 @@ void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { if (const RecordType *RecordTy = Context.getBaseElementType(Field->getType()) ->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf(); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) { SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor); SemaRef.CheckDestructorAccess( diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 0a6cea8..94413b5 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -163,8 +163,9 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { DiagID = diag::ext_incomplete_in_exception_spec; ReturnValueOnError = false; } - if (!(PointeeT->isRecordType() && - PointeeT->castAs<RecordType>()->isBeingDefined()) && + if (!(PointeeT->isRecordType() && PointeeT->castAs<RecordType>() + ->getOriginalDecl() + ->isEntityBeingDefined()) && RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range)) return ReturnValueOnError; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6793d6d..8532039 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1528,8 +1528,8 @@ void Sema::checkEnumArithmeticConversions(Expr *LHS, Expr *RHS, // are ill-formed. if (getLangOpts().CPlusPlus26) DiagID = diag::warn_conv_mixed_enum_types_cxx26; - else if (!L->castAs<EnumType>()->getDecl()->hasNameForLinkage() || - !R->castAs<EnumType>()->getDecl()->hasNameForLinkage()) { + else if (!L->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage() || + !R->castAs<EnumType>()->getOriginalDecl()->hasNameForLinkage()) { // If either enumeration type is unnamed, it's less likely that the // user cares about this, but this situation is still deprecated in // C++2a. Use a different warning group. @@ -2531,7 +2531,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, if (isa<CXXRecordDecl>(DC)) { if (ExplicitTemplateArgs) { if (LookupTemplateName( - R, S, SS, Context.getRecordType(cast<CXXRecordDecl>(DC)), + R, S, SS, Context.getCanonicalTagType(cast<CXXRecordDecl>(DC)), /*EnteringContext*/ false, TemplateNameIsRequired, /*RequiredTemplateKind*/ nullptr, /*AllowTypoCorrection*/ true)) return true; @@ -2607,11 +2607,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, } R.addDecl(ND); if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) { - CXXRecordDecl *Record = nullptr; - if (Corrected.getCorrectionSpecifier()) { - const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType(); - Record = Ty->getAsCXXRecordDecl(); - } + CXXRecordDecl *Record = + Corrected.getCorrectionSpecifier().getAsRecordDecl(); if (!Record) Record = cast<CXXRecordDecl>( ND->getDeclContext()->getRedeclContext()); @@ -2707,8 +2704,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context, // Synthesize a fake NNS that points to the derived class. This will // perform name lookup during template instantiation. CXXScopeSpec SS; - auto *NNS = - NestedNameSpecifier::Create(Context, nullptr, RD->getTypeForDecl()); + NestedNameSpecifier NNS(Context.getCanonicalTagType(RD)->getTypePtr()); SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc)); return DependentScopeDeclRefExpr::Create( Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo, @@ -2831,8 +2827,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // If this name wasn't predeclared and if this is not a function // call, diagnose the problem. - DefaultFilterCCC DefaultValidator(II, SS.isValid() ? SS.getScopeRep() - : nullptr); + DefaultFilterCCC DefaultValidator(II, SS.getScopeRep()); DefaultValidator.IsAddressOfOperand = IsAddressOfOperand; assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) && "Typo correction callback misconfigured"); @@ -2943,8 +2938,28 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( } if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) { - QualType Ty = Context.getTypeDeclType(TD); - QualType ET = getElaboratedType(ElaboratedTypeKeyword::None, SS, Ty); + QualType ET; + TypeLocBuilder TLB; + if (auto *TagD = dyn_cast<TagDecl>(TD)) { + ET = SemaRef.Context.getTagType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TagD, + /*OwnsTag=*/false); + auto TL = TLB.push<TagTypeLoc>(ET); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameInfo.getLoc()); + } else if (auto *TypedefD = dyn_cast<TypedefNameDecl>(TD)) { + ET = SemaRef.Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TypedefD); + TLB.push<TypedefTypeLoc>(ET).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameInfo.getLoc()); + } else { + // FIXME: What else can appear here? + ET = SemaRef.Context.getTypeDeclType(TD); + TLB.pushTypeSpec(ET).setNameLoc(NameInfo.getLoc()); + assert(SS.isEmpty()); + } // Diagnose a missing typename if this resolved unambiguously to a type in // a dependent context. If we can recover with a type, downgrade this to @@ -2965,13 +2980,6 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( D << FixItHint::CreateInsertion(Loc, "typename "); // Recover by pretending this was an elaborated type. - TypeLocBuilder TLB; - TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc()); - - ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET); - QTL.setElaboratedKeywordLoc(SourceLocation()); - QTL.setQualifierLoc(SS.getWithLocInContext(Context)); - *RecoveryTSI = TLB.getTypeSourceInfo(Context, ET); return ExprEmpty(); @@ -2987,11 +2995,10 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return BuildDeclarationNameExpr(SS, R, /*ADL=*/false); } -ExprResult -Sema::PerformObjectMemberConversion(Expr *From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - NamedDecl *Member) { +ExprResult Sema::PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member) { const auto *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext()); if (!RD) return From; @@ -3002,7 +3009,7 @@ Sema::PerformObjectMemberConversion(Expr *From, QualType FromType = From->getType(); bool PointerConversions = false; if (isa<FieldDecl>(Member)) { - DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + DestRecordType = Context.getCanonicalTagType(RD); auto FromPtrType = FromType->getAs<PointerType>(); DestRecordType = Context.getAddrSpaceQualType( DestRecordType, FromPtrType @@ -3080,8 +3087,8 @@ Sema::PerformObjectMemberConversion(Expr *From, // x = 17; // error: ambiguous base subobjects // Derived1::x = 17; // okay, pick the Base subobject of Derived1 // } - if (Qualifier && Qualifier->getAsType()) { - QualType QType = QualType(Qualifier->getAsType(), 0); + if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type) { + QualType QType = QualType(Qualifier.getAsType(), 0); assert(QType->isRecordType() && "lookup done with non-record type"); QualType QRecordType = QualType(QType->castAs<RecordType>(), 0); @@ -4483,9 +4490,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::BitInt: case Type::HLSLInlineSpirv: llvm_unreachable("type class is never variably-modified!"); - case Type::Elaborated: - T = cast<ElaboratedType>(Ty)->getNamedType(); - break; case Type::Adjusted: T = cast<AdjustedType>(Ty)->getOriginalType(); break; @@ -5877,7 +5881,7 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) { return DRE->hasQualifier(); } if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens())) - return OVL->getQualifier(); + return bool(OVL->getQualifier()); return false; } @@ -7076,7 +7080,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, for (unsigned i = 0, e = Args.size(); i != e; i++) { if (const auto *RT = dyn_cast<RecordType>(Args[i]->getType().getCanonicalType())) { - if (RT->getDecl()->isOrContainsUnion()) + if (RT->getOriginalDecl()->isOrContainsUnion()) Diag(Args[i]->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 0 << i; } @@ -8605,7 +8609,8 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // type. if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3 if (const RecordType *RHSRT = RHSTy->getAs<RecordType>()) - if (LHSRT->getDecl() == RHSRT->getDecl()) + if (declaresSameEntity(LHSRT->getOriginalDecl(), + RHSRT->getOriginalDecl())) // "If both the operands have structure or union type, the result has // that type." This implies that CV qualifiers are dropped. return Context.getCommonSugaredType(LHSTy.getUnqualifiedType(), @@ -9674,11 +9679,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. const RecordType *UT = ArgType->getAsUnionType(); - if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (!UT) + return AssignConvertType::Incompatible; + + RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + if (!UD->hasAttr<TransparentUnionAttr>()) return AssignConvertType::Incompatible; // The field to initialize within the transparent union. - RecordDecl *UD = UT->getDecl(); FieldDecl *InitField = nullptr; // It's compatible if the expression matches any of the fields. for (auto *it : UD->fields()) { @@ -11401,7 +11409,7 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, static bool isScopedEnumerationType(QualType T) { if (const EnumType *ET = T->getAs<EnumType>()) - return ET->getDecl()->isScoped(); + return ET->getOriginalDecl()->isScoped(); return false; } @@ -12290,8 +12298,10 @@ static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S, S.InvalidOperands(Loc, LHS, RHS); return QualType(); } - QualType IntType = - LHSStrippedType->castAs<EnumType>()->getDecl()->getIntegerType(); + QualType IntType = LHSStrippedType->castAs<EnumType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType(); assert(IntType->isArithmeticType()); // We can't use `CK_IntegralCast` when the underlying type is 'bool', so we @@ -12457,7 +12467,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, auto computeResultTy = [&]() { if (Opc != BO_Cmp) - return Context.getLogicalOperationType(); + return QualType(Context.getLogicalOperationType()); assert(getLangOpts().CPlusPlus); assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType())); @@ -13694,8 +13704,10 @@ static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD, // diagnostics in field nesting order. while (RecordTypeList.size() > NextToCheckIndex) { bool IsNested = NextToCheckIndex > 0; - for (const FieldDecl *Field : - RecordTypeList[NextToCheckIndex]->getDecl()->fields()) { + for (const FieldDecl *Field : RecordTypeList[NextToCheckIndex] + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) { // First, check every field for constness. QualType FieldTy = Field->getType(); if (FieldTy.isConstQualified()) { @@ -16150,7 +16162,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, if (!RC) return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) << CurrentType); - RecordDecl *RD = RC->getDecl(); + RecordDecl *RD = RC->getOriginalDecl()->getDefinitionOrSelf(); // C++ [lib.support.types]p5: // The macro offsetof accepts a restricted set of type arguments in this @@ -16211,8 +16223,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // If the member was found in a base class, introduce OffsetOfNodes for // the base class indirections. CXXBasePaths Paths; - if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent), - Paths)) { + if (IsDerivedFrom(OC.LocStart, CurrentType, + Context.getCanonicalTagType(Parent), Paths)) { if (Paths.getDetectedVirtual()) { Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base) << MemberDecl->getDeclName() @@ -16777,7 +16789,8 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, // that. QualType UnderlyingType = TInfo->getType(); if (const auto *ET = UnderlyingType->getAs<EnumType>()) - UnderlyingType = ET->getDecl()->getIntegerType(); + UnderlyingType = + ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (Context.typesAreCompatible(PromoteType, UnderlyingType, /*CompareUnqualified*/ true)) PromoteType = QualType(); @@ -16923,7 +16936,7 @@ ExprResult Sema::ActOnSourceLocExpr(SourceLocIdentKind Kind, return ExprError(); } ResultTy = Context.getPointerType( - Context.getRecordType(StdSourceLocationImplDecl).withConst()); + Context.getCanonicalTagType(StdSourceLocationImplDecl).withConst()); break; } @@ -18772,7 +18785,9 @@ static bool isVariableCapturable(CapturingScopeInfo *CSI, ValueDecl *Var, // Prohibit structs with flexible array members too. // We cannot capture what is in the tail end of the struct. if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) { - if (VTTy->getDecl()->hasFlexibleArrayMember()) { + if (VTTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) { if (Diagnose) { if (IsBlock) S.Diag(Loc, diag::err_ref_flexarray_type); @@ -21213,7 +21228,7 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { NamedDecl *Temp = *ULE->decls_begin(); const bool IsTypeAliasTemplateDecl = isa<TypeAliasTemplateDecl>(Temp); - NestedNameSpecifier *NNS = ULE->getQualifierLoc().getNestedNameSpecifier(); + NestedNameSpecifier NNS = ULE->getQualifierLoc().getNestedNameSpecifier(); // FIXME: AssumedTemplate is not very appropriate for error recovery here, // as it models only the unqualified-id case, where this case can clearly be // qualified. Thus we can't just qualify an assumed template. @@ -21239,16 +21254,16 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { QualType TST; { SFINAETrap Trap(*this); - TST = CheckTemplateIdType(TN, NameInfo.getBeginLoc(), TAL); + TST = CheckTemplateIdType(ElaboratedTypeKeyword::None, TN, + NameInfo.getBeginLoc(), TAL); } if (TST.isNull()) TST = Context.getTemplateSpecializationType( - TN, ULE->template_arguments(), /*CanonicalArgs=*/{}, + ElaboratedTypeKeyword::None, TN, ULE->template_arguments(), + /*CanonicalArgs=*/{}, HasAnyDependentTA ? Context.DependentTy : Context.IntTy); - QualType ET = - Context.getElaboratedType(ElaboratedTypeKeyword::None, NNS, TST); return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}, - ET); + TST); } // Overloaded expressions. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 0edfd60..29c9c47 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -57,11 +57,11 @@ using namespace sema; ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, SourceLocation NameLoc, const IdentifierInfo &Name) { - NestedNameSpecifier *NNS = SS.getScopeRep(); - if ([[maybe_unused]] const IdentifierInfo *II = NNS->getAsIdentifier()) - assert(II == &Name && "not a constructor name"); + NestedNameSpecifier NNS = SS.getScopeRep(); + QualType Type(NNS.getAsType(), 0); + if ([[maybe_unused]] const auto *DNT = dyn_cast<DependentNameType>(Type)) + assert(DNT->getIdentifier() == &Name && "not a constructor name"); - QualType Type(NNS->translateToType(Context), 0); // This reference to the type is located entirely at the location of the // final identifier in the qualified-id. return CreateParsedType(Type, @@ -111,10 +111,8 @@ ParsedType Sema::getConstructorName(const IdentifierInfo &II, return ParsedType(); } - QualType T = Context.getTypeDeclType(InjectedClassName); - DiagnoseUseOfDecl(InjectedClassName, NameLoc); - MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false); - + QualType T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + InjectedClassName, /*OwnsTag=*/false); return ParsedType::make(T); } @@ -175,7 +173,7 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, if (SearchType.isNull() || SearchType->isDependentType()) return true; - QualType T = Context.getTypeDeclType(Type); + CanQualType T = Context.getCanonicalTypeDeclType(Type); return Context.hasSameUnqualifiedType(T, SearchType); }; @@ -207,7 +205,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, NamedDecl *D = F.next(); if (auto *TD = dyn_cast<TypeDecl>(D->getUnderlyingDecl())) Diag(D->getLocation(), diag::note_destructor_type_here) - << Context.getTypeDeclType(TD); + << Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD); else Diag(D->getLocation(), diag::note_destructor_nontype_here); @@ -222,11 +221,11 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { if (IsAcceptableResult(Type)) { - QualType T = Context.getTypeDeclType(Type); + QualType T = Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, Type); MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); - return CreateParsedType( - Context.getElaboratedType(ElaboratedTypeKeyword::None, nullptr, T), - Context.getTrivialTypeSourceInfo(T, NameLoc)); + return CreateParsedType(T, + Context.getTrivialTypeSourceInfo(T, NameLoc)); } } @@ -311,15 +310,23 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, // If both lookups succeed and find a dependent result, which result should // we retain? (Same question for p->~type-name().) - if (NestedNameSpecifier *Prefix = - SS.isSet() ? SS.getScopeRep()->getPrefix() : nullptr) { + auto Prefix = [&]() -> NestedNameSpecifierLoc { + NestedNameSpecifierLoc NNS = SS.getWithLocInContext(Context); + if (!NNS) + return NestedNameSpecifierLoc(); + if (auto TL = NNS.getAsTypeLoc()) + return TL.getPrefix(); + return NNS.getAsNamespaceAndPrefix().Prefix; + }(); + + if (Prefix) { // This is // // nested-name-specifier type-name :: ~ type-name // // Look for the second type-name in the nested-name-specifier. CXXScopeSpec PrefixSS; - PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data())); + PrefixSS.Adopt(Prefix); if (ParsedType T = LookupInNestedNameSpec(PrefixSS)) return T; } else { @@ -374,7 +381,7 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, // // also looks for type-name in the scope. Unfortunately, we can't // reasonably apply this fallback for dependent nested-name-specifiers. - if (SS.isValid() && SS.getScopeRep()->getPrefix()) { + if (Prefix) { if (ParsedType T = LookupInScope()) { Diag(SS.getEndLoc(), diag::ext_qualified_dtor_named_in_lexical_scope) << FixItHint::CreateRemoval(SS.getRange()); @@ -419,9 +426,10 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, if (auto *TD = dyn_cast<TypeDecl>(FoundDecls[0]->getUnderlyingDecl())) { assert(!SearchType.isNull() && "should only reject a type result if we have a search type"); - QualType T = Context.getTypeDeclType(TD); Diag(NameLoc, diag::err_destructor_expr_type_mismatch) - << T << SearchType << MakeFixItHint(); + << Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD) + << SearchType << MakeFixItHint(); } else { Diag(NameLoc, diag::err_destructor_expr_nontype) << &II << MakeFixItHint(); @@ -435,7 +443,8 @@ ParsedType Sema::getDestructorName(const IdentifierInfo &II, for (NamedDecl *FoundD : FoundDecls) { if (auto *TD = dyn_cast<TypeDecl>(FoundD->getUnderlyingDecl())) Diag(FoundD->getLocation(), diag::note_destructor_type_here) - << Context.getTypeDeclType(TD); + << Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD); else Diag(FoundD->getLocation(), diag::note_destructor_nontype_here) << FoundD; @@ -501,12 +510,8 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, << II << static_cast<int>(Status) << Hint; } - if (!SS.isValid()) - return false; - - switch (SS.getScopeRep()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::TypeSpec: + switch (SS.getScopeRep().getKind()) { + case NestedNameSpecifier::Kind::Type: // Per C++11 [over.literal]p2, literal operators can only be declared at // namespace scope. Therefore, this unqualified-id cannot name anything. // Reject it early, because we have no AST representation for this in the @@ -515,9 +520,10 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, << SS.getScopeRep(); return true; - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: + case NestedNameSpecifier::Kind::Namespace: return false; } @@ -565,7 +571,8 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, QualType T = E->getType(); if (const RecordType *RecordT = T->getAs<RecordType>()) { - CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl()); + CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getOriginalDecl()) + ->getDefinitionOrSelf(); // C++ [expr.typeid]p3: // [...] If the type of the expression is a class type, the class // shall be completely-defined. @@ -659,7 +666,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return ExprError(Diag(OpLoc, diag::err_no_typeid_with_fno_rtti)); } - QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); + CanQualType TypeInfoType = Context.getCanonicalTagType(CXXTypeInfoDecl); if (isType) { // The operand is a type; handle it as such. @@ -1214,7 +1221,7 @@ QualType Sema::getCurrentThisType() { // This is a lambda call operator that is being instantiated as a default // initializer. DC must point to the enclosing class type, so we can recover // the 'this' type from it. - QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC)); + CanQualType ClassTy = Context.getCanonicalTagType(cast<CXXRecordDecl>(DC)); // There are no cv-qualifiers for 'this' within default initializers, // per [expr.prim.general]p4. ThisTy = Context.getPointerType(ClassTy); @@ -1244,7 +1251,7 @@ Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, else Record = cast<CXXRecordDecl>(ContextDecl); - QualType T = S.Context.getRecordType(Record); + QualType T = S.Context.getCanonicalTagType(Record); T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals); S.CXXThisTypeOverride = @@ -1732,7 +1739,7 @@ static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { if (S.getLangOpts().AlignedAllocation && UsualParams < FD->getNumParams() && S.Context.hasSameUnqualifiedType( FD->getParamDecl(UsualParams)->getType(), - S.Context.getTypeDeclType(S.getStdAlignValT()))) + S.Context.getCanonicalTagType(S.getStdAlignValT()))) ++UsualParams; return UsualParams == FD->getNumParams(); @@ -1860,8 +1867,8 @@ namespace { if (FunctionTemplateDecl *Best = S.getMoreSpecializedTemplate( PrimaryTemplate, OtherPrimaryTemplate, SourceLocation(), TPOC_Call, ImplicitArgCount, - DC ? QualType(DC->getTypeForDecl(), 0) : QualType{}, - OtherDC ? QualType(OtherDC->getTypeForDecl(), 0) : QualType{}, + DC ? S.Context.getCanonicalTagType(DC) : QualType{}, + OtherDC ? S.Context.getCanonicalTagType(OtherDC) : QualType{}, false)) { return Best == PrimaryTemplate ? 1 : -1; } @@ -1977,7 +1984,7 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, DeclarationName deleteName = S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName); - S.LookupQualifiedName(ops, record->getDecl()); + S.LookupQualifiedName(ops, record->getOriginalDecl()->getDefinitionOrSelf()); // We're just doing this for information. ops.suppressDiagnostics(); @@ -2505,7 +2512,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // because there might not be a `std::align_val_t` type. EnumDecl *StdAlignValT = getStdAlignValT(); QualType AlignValT = - StdAlignValT ? Context.getTypeDeclType(StdAlignValT) : SizeTy; + StdAlignValT ? Context.getCanonicalTagType(StdAlignValT) : SizeTy; IntegerLiteral AlignmentLiteral( Context, llvm::APInt(Context.getTypeSize(SizeTy), @@ -2966,7 +2973,7 @@ bool Sema::FindAllocationFunctions( isTypeAwareAllocation(IAP.PassTypeIdentity); if (IncludeAlignParam) { DeclareGlobalNewDelete(); - AlignValT = Context.getTypeDeclType(getStdAlignValT()); + AlignValT = Context.getCanonicalTagType(getStdAlignValT()); } CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation()); if (IncludeAlignParam) @@ -3048,8 +3055,9 @@ bool Sema::FindAllocationFunctions( LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); if (AllocElemType->isRecordType() && DeleteScope != AllocationFunctionScope::Global) { - auto *RD = - cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl()); + auto *RD = cast<CXXRecordDecl>( + AllocElemType->castAs<RecordType>()->getOriginalDecl()) + ->getDefinitionOrSelf(); LookupQualifiedName(FoundDelete, RD); } if (FoundDelete.isAmbiguous()) @@ -3426,7 +3434,7 @@ void Sema::DeclareGlobalNewDelete() { for (int Aligned = 0; Aligned < NumAlignVariants; ++Aligned) { if (Aligned) - Params.push_back(Context.getTypeDeclType(getStdAlignValT())); + Params.push_back(Context.getCanonicalTagType(getStdAlignValT())); DeclareGlobalAllocationFunction( Context.DeclarationNames.getCXXOperatorName(Kind), Return, Params); @@ -3483,7 +3491,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = Name.isAnyOperatorNew(); if (HasBadAllocExceptionSpec) { if (!getLangOpts().CPlusPlus11) { - BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); + BadAllocType = Context.getCanonicalTagType(getStdBadAlloc()); assert(StdBadAlloc && "Must have std::bad_alloc declared"); EPI.ExceptionSpec.Type = EST_Dynamic; EPI.ExceptionSpec.Exceptions = llvm::ArrayRef(BadAllocType); @@ -3497,6 +3505,19 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, } auto CreateAllocationFunctionDecl = [&](Attr *ExtraAttr) { + // The MSVC STL has explicit cdecl on its (host-side) allocation function + // specializations for the allocation, so in order to prevent a CC clash + // we use the host's CC, if available, or CC_C as a fallback, for the + // host-side implicit decls, knowing these do not get emitted when compiling + // for device. + if (getLangOpts().CUDAIsDevice && ExtraAttr && + isa<CUDAHostAttr>(ExtraAttr) && + Context.getTargetInfo().getTriple().isSPIRV()) { + if (auto *ATI = Context.getAuxTargetInfo()) + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(ATI->getDefaultCallingConv()); + else + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallingConv::CC_C); + } QualType FnType = Context.getFunctionType(Return, Params, EPI); FunctionDecl *Alloc = FunctionDecl::Create( Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, FnType, @@ -3593,7 +3614,7 @@ FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc, DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); FunctionDecl *OperatorDelete = nullptr; - QualType DeallocType = Context.getRecordType(RD); + CanQualType DeallocType = Context.getCanonicalTagType(RD); ImplicitDeallocationParameters IDP = { DeallocType, ShouldUseTypeAwareOperatorNewOrDelete(), AlignedAllocationMode::No, SizedDeallocationMode::No}; @@ -3627,7 +3648,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Found.suppressDiagnostics(); if (!isAlignedAllocation(IDP.PassAlignment) && - hasNewExtendedAlignment(*this, Context.getRecordType(RD))) + hasNewExtendedAlignment(*this, Context.getCanonicalTagType(RD))) IDP.PassAlignment = AlignedAllocationMode::Yes; // C++17 [expr.delete]p10: @@ -4050,7 +4071,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, : diag::warn_delete_incomplete, Ex.get())) { if (const RecordType *RT = PointeeElem->getAs<RecordType>()) - PointeeRD = cast<CXXRecordDecl>(RT->getDecl()); + PointeeRD = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); } } @@ -4574,7 +4596,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // If the user-defined conversion is specified by a conversion function, // the initial standard conversion sequence converts the source type to // the implicit object parameter of the conversion function. - BeforeToType = Context.getTagDeclType(Conv->getParent()); + BeforeToType = Context.getCanonicalTagType(Conv->getParent()); } else { const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD); CastKind = CK_ConstructorConversion; @@ -4818,7 +4840,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, if (FromType->isVectorType() || ToType->isVectorType()) StepTy = adjustVectorType(Context, FromType, ToType, &ElTy); if (ElTy->isBooleanType()) { - assert(FromType->castAs<EnumType>()->getDecl()->isFixed() && + assert(FromType->castAs<EnumType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->isFixed() && SCS.Second == ICK_Integral_Promotion && "only enums with fixed underlying type can promote to bool"); From = ImpCastExprToType(From, StepTy, CK_IntegralToBoolean, VK_PRValue, @@ -5370,16 +5395,18 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } + // FIXME: use sugared type from member pointer. + CanQualType RHSClassType = Context.getCanonicalTagType(RHSClass); CXXCastPath BasePath; if (CheckDerivedToBaseConversion( - LHSType, QualType(RHSClass->getTypeForDecl(), 0), Loc, + LHSType, RHSClassType, Loc, SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()), &BasePath)) return QualType(); // Cast LHS to type of use. - QualType UseType = Context.getQualifiedType(RHSClass->getTypeForDecl(), - LHSType.getQualifiers()); + QualType UseType = + Context.getQualifiedType(RHSClassType, LHSType.getQualifiers()); if (isIndirect) UseType = Context.getPointerType(UseType); ExprValueKind VK = isIndirect ? VK_PRValue : LHS.get()->getValueKind(); @@ -6184,7 +6211,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, case Pointer: return Ctx.getPointerType(T); case MemberPointer: - return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr, + return Ctx.getMemberPointerType(T, /*Qualifier=*/std::nullopt, ClassOrBound->getAsCXXRecordDecl()); case ObjCPointer: return Ctx.getObjCObjectPointerType(T); @@ -6357,7 +6384,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return QualType(); Steps.emplace_back(Step::MemberPointer, - Context.getTypeDeclType(Cls).getTypePtr()); + Context.getCanonicalTagType(Cls).getTypePtr()); continue; } @@ -6636,7 +6663,8 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { // That should be enough to guarantee that this type is complete, if we're // not processing a decltype expression. - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + CXXRecordDecl *RD = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); if (RD->isInvalidDecl() || RD->isDependentContext()) return E; @@ -7243,16 +7271,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(S, - SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, - TemplateId->Name, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - /*IsCtorOrDtorName*/true); + TypeResult T = ActOnTemplateIdType( + S, ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, + /*IsCtorOrDtorName*/ true); if (T.isInvalid() || !T.get()) { // Recover by assuming we had the right type all along. DestructedType = ObjectType; @@ -7296,16 +7321,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(S, - SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, - TemplateId->Name, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - /*IsCtorOrDtorName*/true); + TypeResult T = ActOnTemplateIdType( + S, ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, + /*IsCtorOrDtorName*/ true); if (T.isInvalid() || !T.get()) { // Recover by dropping this type. ScopeType = QualType(); @@ -7505,7 +7527,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // GCC seems to also exclude expressions of incomplete enum type. if (const EnumType *T = E->getType()->getAs<EnumType>()) { - if (!T->getDecl()->isComplete()) { + if (!T->getOriginalDecl()->getDefinitionOrSelf()->isComplete()) { // FIXME: stupid workaround for a codegen bug! E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).get(); return E; diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 5dca509..4a31a13 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -492,13 +492,14 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize); // Now look up the TypeDefDecl from the vector type. Without this, - // diagostics look bad. We want extended vector types to appear built-in. + // diagnostics look bad. We want extended vector types to appear built-in. for (Sema::ExtVectorDeclsType::iterator I = S.ExtVectorDecls.begin(S.getExternalSource()), E = S.ExtVectorDecls.end(); I != E; ++I) { if ((*I)->getUnderlyingType() == VT) - return S.Context.getTypedefType(*I); + return S.Context.getTypedefType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, *I); } return VT; // should never get here (a typedef type should always be found). @@ -881,7 +882,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && - (SS.isSet() ? SS.getScopeRep()->isDependent() + (SS.isSet() ? SS.getScopeRep().isDependent() : BaseExprType->isDependentType()))) return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index e0662d8..03b5c79 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -639,14 +639,14 @@ ExprResult SemaObjC::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ValueType); BoxedType = NSNumberPointer; } else if (const EnumType *ET = ValueType->getAs<EnumType>()) { - if (!ET->getDecl()->isComplete()) { + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) { Diag(Loc, diag::err_objc_incomplete_boxed_expression_type) << ValueType << ValueExpr->getSourceRange(); return ExprError(); } - BoxingMethod = getNSNumberFactoryMethod(*this, Loc, - ET->getDecl()->getIntegerType()); + BoxingMethod = getNSNumberFactoryMethod(*this, Loc, ED->getIntegerType()); BoxedType = NSNumberPointer; } else if (ValueType->isObjCBoxableRecordType()) { // Support for structure types, that marked as objc_boxable @@ -2337,10 +2337,10 @@ SemaObjC::getObjCMessageKind(Scope *S, IdentifierInfo *Name, if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) T = Context.getObjCInterfaceType(Class); else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) { - T = Context.getTypeDeclType(Type); SemaRef.DiagnoseUseOfDecl(Type, NameLoc); - } - else + T = Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, Type); + } else return ObjCInstanceMessage; // We have a class message, and T is the type we're @@ -3847,7 +3847,8 @@ static inline T *getObjCBridgeAttr(const TypedefType *TD) { if (QT->isPointerType()) { QT = QT->getPointeeType(); if (const RecordType *RT = QT->getAs<RecordType>()) { - for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) { + for (auto *Redecl : + RT->getOriginalDecl()->getMostRecentDecl()->redecls()) { if (auto *attr = Redecl->getAttr<T>()) return attr; } diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 1592862..8590ee8 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -1352,11 +1352,15 @@ private: return true; } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override { + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node, + bool TraverseQualifier) override { return true; } - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { return true; } + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node, + bool TraverseQualifier) override { + return true; + } bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override { return true; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e59849a..b4bbe02 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -234,7 +234,7 @@ static unsigned calculateLegacyCbufferSize(const ASTContext &Context, constexpr unsigned CBufferAlign = 16; if (const RecordType *RT = T->getAs<RecordType>()) { unsigned Size = 0; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); for (const FieldDecl *Field : RD->fields()) { QualType Ty = Field->getType(); unsigned FieldSize = calculateLegacyCbufferSize(Context, Ty); @@ -337,16 +337,9 @@ static bool isZeroSizedArray(const ConstantArrayType *CAT) { return CAT != nullptr; } -// Returns true if the record type is an HLSL resource class or an array of -// resource classes -static bool isResourceRecordTypeOrArrayOf(const Type *Ty) { - while (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) - Ty = CAT->getArrayElementTypeNoTypeQual(); - return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr; -} - static bool isResourceRecordTypeOrArrayOf(VarDecl *VD) { - return isResourceRecordTypeOrArrayOf(VD->getType().getTypePtr()); + const Type *Ty = VD->getType().getTypePtr(); + return Ty->isHLSLResourceRecord() || Ty->isHLSLResourceRecordArray(); } // Returns true if the type is a leaf element type that is not valid to be @@ -355,7 +348,7 @@ static bool isResourceRecordTypeOrArrayOf(VarDecl *VD) { // type or if it is a record type that needs to be inspected further. static bool isInvalidConstantBufferLeafElementType(const Type *Ty) { Ty = Ty->getUnqualifiedDesugaredType(); - if (isResourceRecordTypeOrArrayOf(Ty)) + if (Ty->isHLSLResourceRecord() || Ty->isHLSLResourceRecordArray()) return true; if (Ty->isRecordType()) return Ty->getAsCXXRecordDecl()->isEmpty(); @@ -373,7 +366,7 @@ static bool isInvalidConstantBufferLeafElementType(const Type *Ty) { // needs to be created for HLSL Buffer use that will exclude these unwanted // declarations (see createHostLayoutStruct function). static bool requiresImplicitBufferLayoutStructure(const CXXRecordDecl *RD) { - if (RD->getTypeForDecl()->isHLSLIntangibleType() || RD->isEmpty()) + if (RD->isHLSLIntangible() || RD->isEmpty()) return true; // check fields for (const FieldDecl *Field : RD->fields()) { @@ -458,7 +451,7 @@ static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty, RD = createHostLayoutStruct(S, RD); if (!RD) return nullptr; - Ty = RD->getTypeForDecl(); + Ty = S.Context.getCanonicalTagType(RD)->getTypePtr(); } } @@ -508,8 +501,8 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S, if (requiresImplicitBufferLayoutStructure(BaseDecl)) { BaseDecl = createHostLayoutStruct(S, BaseDecl); if (BaseDecl) { - TypeSourceInfo *TSI = AST.getTrivialTypeSourceInfo( - QualType(BaseDecl->getTypeForDecl(), 0)); + TypeSourceInfo *TSI = + AST.getTrivialTypeSourceInfo(AST.getCanonicalTagType(BaseDecl)); Base = CXXBaseSpecifier(SourceRange(), false, StructDecl->isClass(), AS_none, TSI, SourceLocation()); } @@ -597,8 +590,9 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) { // create buffer layout struct createHostLayoutStructForBuffer(SemaRef, BufDecl); + HLSLVkBindingAttr *VkBinding = Dcl->getAttr<HLSLVkBindingAttr>(); HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>(); - if (!RBA || !RBA->hasRegisterSlot()) { + if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) { SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding); // Use HLSLResourceBindingAttr to transfer implicit binding order_ID // to codegen. If it does not exist, create an implicit attribute. @@ -1496,6 +1490,23 @@ void SemaHLSL::handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL) { D->addAttr(NewAttr); } +void SemaHLSL::handleVkBindingAttr(Decl *D, const ParsedAttr &AL) { + // The vk::binding attribute only applies to SPIR-V. + if (!getASTContext().getTargetInfo().getTriple().isSPIRV()) + return; + + uint32_t Binding = 0; + if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding)) + return; + uint32_t Set = 0; + if (AL.getNumArgs() > 1 && + !SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(1), Set)) + return; + + D->addAttr(::new (getASTContext()) + HLSLVkBindingAttr(getASTContext(), AL, Binding, Set)); +} + bool SemaHLSL::diagnoseInputIDType(QualType T, const ParsedAttr &AL) { const auto *VT = T->getAs<VectorType>(); @@ -1825,7 +1836,7 @@ SemaHLSL::TakeLocForHLSLAttribute(const HLSLAttributedResourceType *RT) { // requirements and adds them to Bindings void SemaHLSL::collectResourceBindingsOnUserRecordDecl(const VarDecl *VD, const RecordType *RT) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); for (FieldDecl *FD : RD->fields()) { const Type *Ty = FD->getType()->getUnqualifiedDesugaredType(); @@ -3378,7 +3389,7 @@ bool SemaHLSL::ContainsBitField(QualType BaseTy) { continue; } if (const auto *RT = dyn_cast<RecordType>(T)) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) continue; @@ -3579,7 +3590,7 @@ void SemaHLSL::deduceAddressSpace(VarDecl *Decl) { return; // Resource handles. - if (isResourceRecordTypeOrArrayOf(Type->getUnqualifiedDesugaredType())) + if (Type->isHLSLResourceRecord() || Type->isHLSLResourceRecordArray()) return; // Only static globals belong to the Private address space. @@ -3619,10 +3630,7 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) { if (VD->getType()->isHLSLIntangibleType()) collectResourceBindingsOnVarDecl(VD); - const Type *VarType = VD->getType().getTypePtr(); - while (VarType->isArrayType()) - VarType = VarType->getArrayElementTypeNoTypeQual(); - if (VarType->isHLSLResourceRecord() || + if (isResourceRecordTypeOrArrayOf(VD) || VD->hasAttr<HLSLVkConstantIdAttr>()) { // Make the variable for resources static. The global externally visible // storage is accessed through the handle, which is a member. The variable @@ -3660,8 +3668,12 @@ static bool initVarDeclWithCtor(Sema &S, VarDecl *VD, bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) { std::optional<uint32_t> RegisterSlot; uint32_t SpaceNo = 0; + HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>(); HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>(); - if (RBA) { + if (VkBinding) { + RegisterSlot = VkBinding->getBinding(); + SpaceNo = VkBinding->getSet(); + } else if (RBA) { if (RBA->hasRegisterSlot()) RegisterSlot = RBA->getSlotNumber(); SpaceNo = RBA->getSpaceNumber(); @@ -3764,6 +3776,9 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) { bool HasBinding = false; for (Attr *A : VD->attrs()) { + if (isa<HLSLVkBindingAttr>(A)) + HasBinding = true; + HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A); if (!RBA || !RBA->hasRegisterSlot()) continue; @@ -3894,7 +3909,8 @@ class InitListTransformer { } while (!RecordTypes.empty()) { const RecordType *RT = RecordTypes.pop_back_val(); - for (auto *FD : RT->getDecl()->fields()) { + for (auto *FD : + RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { DeclAccessPair Found = DeclAccessPair::make(FD, FD->getAccess()); DeclarationNameInfo NameInfo(FD->getDeclName(), E->getBeginLoc()); ExprResult Res = S.BuildFieldReferenceExpr( @@ -3942,7 +3958,8 @@ class InitListTransformer { } while (!RecordTypes.empty()) { const RecordType *RT = RecordTypes.pop_back_val(); - for (auto *FD : RT->getDecl()->fields()) { + for (auto *FD : + RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { Inits.push_back(generateInitListsImpl(FD->getType())); } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1dd38c0..d7cca4b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -446,7 +446,6 @@ class InitListChecker { unsigned ExpectedNumInits); int numArrayElements(QualType DeclType); int numStructUnionElements(QualType DeclType); - static RecordDecl *getRecordDecl(QualType DeclType); ExprResult PerformEmptyInit(SourceLocation Loc, const InitializedEntity &Entity); @@ -776,7 +775,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field, if (Init >= NumInits || !ILE->getInit(Init)) { if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) - if (!RType->getDecl()->isUnion()) + if (!RType->getOriginalDecl()->isUnion()) assert((Init < NumInits || VerifyOnly) && "This ILE should have been expanded"); @@ -923,7 +922,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, return; if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { - const RecordDecl *RDecl = RType->getDecl(); + const RecordDecl *RDecl = RType->getOriginalDecl()->getDefinitionOrSelf(); if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) { FillInEmptyInitForField(0, ILE->getInitializedFieldInUnion(), Entity, ILE, RequiresSecondPass, FillWithNoInit); @@ -1127,7 +1126,8 @@ int InitListChecker::numArrayElements(QualType DeclType) { } int InitListChecker::numStructUnionElements(QualType DeclType) { - RecordDecl *structDecl = DeclType->castAs<RecordType>()->getDecl(); + RecordDecl *structDecl = + DeclType->castAs<RecordType>()->getOriginalDecl()->getDefinitionOrSelf(); int InitializableMembers = 0; if (auto *CXXRD = dyn_cast<CXXRecordDecl>(structDecl)) InitializableMembers += CXXRD->getNumBases(); @@ -1140,14 +1140,6 @@ int InitListChecker::numStructUnionElements(QualType DeclType) { return InitializableMembers - structDecl->hasFlexibleArrayMember(); } -RecordDecl *InitListChecker::getRecordDecl(QualType DeclType) { - if (const auto *RT = DeclType->getAs<RecordType>()) - return RT->getDecl(); - if (const auto *Inject = DeclType->getAs<InjectedClassNameType>()) - return Inject->getDecl(); - return nullptr; -} - /// Determine whether Entity is an entity for which it is idiomatic to elide /// the braces in aggregate initialization. static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { @@ -1164,16 +1156,22 @@ static bool isIdiomaticBraceElisionEntity(const InitializedEntity &Entity) { // Allows elide brace initialization for aggregates with empty base. if (Entity.getKind() == InitializedEntity::EK_Base) { - auto *ParentRD = - Entity.getParent()->getType()->castAs<RecordType>()->getDecl(); + auto *ParentRD = Entity.getParent() + ->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); CXXRecordDecl *CXXRD = cast<CXXRecordDecl>(ParentRD); return CXXRD->getNumBases() == 1 && CXXRD->field_empty(); } // Allow brace elision if the only subobject is a field. if (Entity.getKind() == InitializedEntity::EK_Member) { - auto *ParentRD = - Entity.getParent()->getType()->castAs<RecordType>()->getDecl(); + auto *ParentRD = Entity.getParent() + ->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(ParentRD)) { if (CXXRD->getNumBases()) { return false; @@ -1442,7 +1440,7 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, } else if (DeclType->isVectorType()) { CheckVectorType(Entity, IList, DeclType, Index, StructuredList, StructuredIndex); - } else if (const RecordDecl *RD = getRecordDecl(DeclType)) { + } else if (const RecordDecl *RD = DeclType->getAsRecordDecl()) { auto Bases = CXXRecordDecl::base_class_const_range(CXXRecordDecl::base_class_const_iterator(), CXXRecordDecl::base_class_const_iterator()); @@ -2320,7 +2318,7 @@ void InitListChecker::CheckStructUnionTypes( bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject) { - const RecordDecl *RD = getRecordDecl(DeclType); + const RecordDecl *RD = DeclType->getAsRecordDecl(); // If the record is invalid, some of it's members are invalid. To avoid // confusion, we forgo checking the initializer for the entire record. @@ -2889,7 +2887,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // then the current object (defined below) shall have // structure or union type and the identifier shall be the // name of a member of that type. - RecordDecl *RD = getRecordDecl(CurrentObjectType); + RecordDecl *RD = CurrentObjectType->getAsRecordDecl(); if (!RD) { SourceLocation Loc = D->getDotLoc(); if (Loc.isInvalid()) @@ -4337,8 +4335,8 @@ static bool hasCopyOrMoveCtorParam(ASTContext &Ctx, QualType ParmT = Info.Constructor->getParamDecl(0)->getType().getNonReferenceType(); - QualType ClassT = - Ctx.getRecordType(cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext())); + CanQualType ClassT = Ctx.getCanonicalTagType( + cast<CXXRecordDecl>(Info.FoundDecl->getDeclContext())); return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } @@ -4537,8 +4535,8 @@ static void TryConstructorInitialization(Sema &S, const RecordType *DestRecordType = DestType->getAs<RecordType>(); assert(DestRecordType && "Constructor initialization requires record type"); - CXXRecordDecl *DestRecordDecl - = cast<CXXRecordDecl>(DestRecordType->getDecl()); + auto *DestRecordDecl = cast<CXXRecordDecl>(DestRecordType->getOriginalDecl()) + ->getDefinitionOrSelf(); // Build the candidate set directly in the initialization sequence // structure, so that it will persist if we fail. @@ -5059,8 +5057,8 @@ static void TryListInitialization(Sema &S, // the underlying type of T, the program is ill-formed. auto *ET = DestType->getAs<EnumType>(); if (S.getLangOpts().CPlusPlus17 && - Kind.getKind() == InitializationKind::IK_DirectList && - ET && ET->getDecl()->isFixed() && + Kind.getKind() == InitializationKind::IK_DirectList && ET && + ET->getOriginalDecl()->getDefinitionOrSelf()->isFixed() && !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && (E->getType()->isIntegralOrUnscopedEnumerationType() || E->getType()->isFloatingType())) { @@ -5170,7 +5168,8 @@ static OverloadingResult TryRefInitWithConversionFunction( S.isCompleteType(Kind.getLocation(), T1)) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. - CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); + auto *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getOriginalDecl()) + ->getDefinitionOrSelf(); for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) { auto Info = getConstructorInfo(D); @@ -5193,7 +5192,8 @@ static OverloadingResult TryRefInitWithConversionFunction( } } } - if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) + if (T1RecordType && + T1RecordType->getOriginalDecl()->getDefinitionOrSelf()->isInvalidDecl()) return OR_No_Viable_Function; const RecordType *T2RecordType = nullptr; @@ -5201,7 +5201,8 @@ static OverloadingResult TryRefInitWithConversionFunction( S.isCompleteType(Kind.getLocation(), T2)) { // The type we're converting from is a class type, enumerate its conversion // functions. - CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl()); + auto *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getOriginalDecl()) + ->getDefinitionOrSelf(); const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { @@ -5237,7 +5238,8 @@ static OverloadingResult TryRefInitWithConversionFunction( } } } - if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) + if (T2RecordType && + T2RecordType->getOriginalDecl()->getDefinitionOrSelf()->isInvalidDecl()) return OR_No_Viable_Function; SourceLocation DeclLoc = Initializer->getBeginLoc(); @@ -5715,7 +5717,9 @@ static void TryValueInitialization(Sema &S, T = S.Context.getBaseElementType(T); if (const RecordType *RT = T->getAs<RecordType>()) { - if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + if (CXXRecordDecl *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getOriginalDecl())) { + ClassDecl = ClassDecl->getDefinitionOrSelf(); bool NeedZeroInitialization = true; // C++98: // -- if T is a class type (clause 9) with a user-declared constructor @@ -5913,7 +5917,8 @@ static void TryOrBuildParenListInitialization( } } else if (auto *RT = Entity.getType()->getAs<RecordType>()) { bool IsUnion = RT->isUnionType(); - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + const auto *RD = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); if (RD->isInvalidDecl()) { // Exit early to avoid confusion when processing members. // We do the same for braced list initialization in @@ -6102,8 +6107,9 @@ static void TryUserDefinedConversion(Sema &S, if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. - CXXRecordDecl *DestRecordDecl - = cast<CXXRecordDecl>(DestRecordType->getDecl()); + auto *DestRecordDecl = + cast<CXXRecordDecl>(DestRecordType->getOriginalDecl()) + ->getDefinitionOrSelf(); // Try to complete the type we're converting to. if (S.isCompleteType(Kind.getLocation(), DestType)) { @@ -6139,8 +6145,9 @@ static void TryUserDefinedConversion(Sema &S, // We can only enumerate the conversion functions for a complete type; if // the type isn't complete, simply skip this step. if (S.isCompleteType(DeclLoc, SourceType)) { - CXXRecordDecl *SourceRecordDecl - = cast<CXXRecordDecl>(SourceRecordType->getDecl()); + auto *SourceRecordDecl = + cast<CXXRecordDecl>(SourceRecordType->getOriginalDecl()) + ->getDefinitionOrSelf(); const auto &Conversions = SourceRecordDecl->getVisibleConversionFunctions(); @@ -7173,7 +7180,8 @@ static ExprResult CopyObject(Sema &S, Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = nullptr; if (const RecordType *Record = T->getAs<RecordType>()) - Class = cast<CXXRecordDecl>(Record->getDecl()); + Class = + cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf(); if (!Class) return CurInit; @@ -7328,8 +7336,8 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, // Find constructors which would have been considered. OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - DeclContext::lookup_result Ctors = - S.LookupConstructors(cast<CXXRecordDecl>(Record->getDecl())); + DeclContext::lookup_result Ctors = S.LookupConstructors( + cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf()); // Perform overload resolution. OverloadCandidateSet::iterator Best; @@ -8160,8 +8168,9 @@ ExprResult InitializationSequence::Perform(Sema &S, // regardless of how we initialized the entity. QualType T = CurInit.get()->getType(); if (const RecordType *Record = T->getAs<RecordType>()) { - CXXDestructorDecl *Destructor - = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); + CXXDestructorDecl *Destructor = + S.LookupDestructor(cast<CXXRecordDecl>(Record->getOriginalDecl()) + ->getDefinitionOrSelf()); S.CheckDestructorAccess(CurInit.get()->getBeginLoc(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); S.MarkFunctionReferenced(CurInit.get()->getBeginLoc(), Destructor); @@ -8808,8 +8817,8 @@ static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, destPointeeType.getQualifiers().compatiblyIncludes( fromPointeeType.getQualifiers(), S.getASTContext())) S.Diag(fromDecl->getLocation(), diag::note_forward_class_conversion) - << S.getASTContext().getTagDeclType(fromDecl) - << S.getASTContext().getTagDeclType(destDecl); + << S.getASTContext().getCanonicalTagType(fromDecl) + << S.getASTContext().getCanonicalTagType(destDecl); } static void diagnoseListInit(Sema &S, const InitializedEntity &Entity, @@ -9208,32 +9217,34 @@ bool InitializationSequence::Diagnose(Sema &S, InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass(); if (Entity.getKind() == InitializedEntity::EK_Base) { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) - << S.Context.getTypeDeclType(Constructor->getParent()) - << /*base=*/0 - << Entity.getType() - << InheritedFrom; - - RecordDecl *BaseDecl - = Entity.getBaseSpecifier()->getType()->castAs<RecordType>() - ->getDecl(); + << (InheritedFrom ? 2 + : Constructor->isImplicit() ? 1 + : 0) + << S.Context.getCanonicalTagType(Constructor->getParent()) + << /*base=*/0 << Entity.getType() << InheritedFrom; + + RecordDecl *BaseDecl = Entity.getBaseSpecifier() + ->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf(); S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) - << S.Context.getTagDeclType(BaseDecl); + << S.Context.getCanonicalTagType(BaseDecl); } else { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0) - << S.Context.getTypeDeclType(Constructor->getParent()) - << /*member=*/1 - << Entity.getName() - << InheritedFrom; + << (InheritedFrom ? 2 + : Constructor->isImplicit() ? 1 + : 0) + << S.Context.getCanonicalTagType(Constructor->getParent()) + << /*member=*/1 << Entity.getName() << InheritedFrom; S.Diag(Entity.getDecl()->getLocation(), diag::note_member_declared_at); if (const RecordType *Record = Entity.getType()->getAs<RecordType>()) - S.Diag(Record->getDecl()->getLocation(), + S.Diag(Record->getOriginalDecl()->getLocation(), diag::note_previous_decl) - << S.Context.getTagDeclType(Record->getDecl()); + << S.Context.getCanonicalTagType(Record->getOriginalDecl()); } break; } @@ -9300,11 +9311,11 @@ bool InitializationSequence::Diagnose(Sema &S, // initialized. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext); S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) - << (Constructor->getInheritedConstructor() ? 2 : - Constructor->isImplicit() ? 1 : 0) - << S.Context.getTypeDeclType(Constructor->getParent()) - << /*const=*/1 - << Entity.getName(); + << (Constructor->getInheritedConstructor() ? 2 + : Constructor->isImplicit() ? 1 + : 0) + << S.Context.getCanonicalTagType(Constructor->getParent()) + << /*const=*/1 << Entity.getName(); S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) << Entity.getName(); } else if (const auto *VD = dyn_cast_if_present<VarDecl>(Entity.getDecl()); @@ -10157,7 +10168,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( auto *RD = cast<CXXRecordDecl>(Pattern->getTemplatedDecl()); if (!(RD->getDefinition() && RD->isAggregate())) return; - QualType Ty = Context.getRecordType(RD); + QualType Ty = Context.getCanonicalTagType(RD); SmallVector<QualType, 8> ElementTypes; InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); @@ -10297,8 +10308,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( case OR_No_Viable_Function: { CXXRecordDecl *Primary = cast<ClassTemplateDecl>(Template)->getTemplatedDecl(); - bool Complete = - isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary)); + bool Complete = isCompleteType(Kind.getLocation(), + Context.getCanonicalTagType(Primary)); Candidates.NoteCandidates( PartialDiagnosticAt( Kind.getLocation(), diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index bc3c4b0..0d891fc 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -425,7 +425,7 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda( .getNonReferenceType() .getUnqualifiedType() .getDesugaredType(getASTContext()); - QualType LambdaType = getASTContext().getRecordType(RD); + CanQualType LambdaType = getASTContext().getCanonicalTagType(RD); if (LambdaType == ExplicitObjectParameterType) return false; @@ -457,7 +457,7 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda( return true; } - if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) { + if (Paths.isAmbiguous(LambdaType)) { std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths); Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base) << LambdaType << PathsDisplay; @@ -642,7 +642,7 @@ static EnumDecl *findEnumForBlockReturn(Expr *E) { // - it is an expression of that formal enum type. if (const EnumType *ET = E->getType()->getAs<EnumType>()) { - return ET->getDecl(); + return ET->getOriginalDecl()->getDefinitionOrSelf(); } // Otherwise, nope. @@ -759,7 +759,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(isa<BlockScopeInfo>(CSI)); const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns); if (ED) { - CSI.ReturnType = Context.getTypeDeclType(ED); + CSI.ReturnType = Context.getCanonicalTagType(ED); adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType); return; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index dc73ded..e28492b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -563,9 +563,8 @@ void LookupResult::resolveKind() { // no ambiguity if they all refer to the same type, so unique based on the // canonical type. if (const auto *TD = dyn_cast<TypeDecl>(D)) { - QualType T = getSema().Context.getTypeDeclType(TD); auto UniqueResult = UniqueTypes.insert( - std::make_pair(getSema().Context.getCanonicalType(T), I)); + std::make_pair(getSema().Context.getCanonicalTypeDeclType(TD), I)); if (!UniqueResult.second) { // The type is not unique. ExistingI = UniqueResult.first->second; @@ -717,7 +716,7 @@ static QualType getOpenCLEnumType(Sema &S, llvm::StringRef Name) { EnumDecl *Decl = Result.getAsSingle<EnumDecl>(); if (!Decl) return diagOpenCLBuiltinTypeError(S, "enum", Name); - return S.Context.getEnumType(Decl); + return S.Context.getCanonicalTagType(Decl); } /// Lookup an OpenCL typedef type. @@ -730,7 +729,8 @@ static QualType getOpenCLTypedefType(Sema &S, llvm::StringRef Name) { TypedefNameDecl *Decl = Result.getAsSingle<TypedefNameDecl>(); if (!Decl) return diagOpenCLBuiltinTypeError(S, "typedef", Name); - return S.Context.getTypedefType(Decl); + return S.Context.getTypedefType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, Decl); } /// Get the QualType instances of the return type and arguments for an OpenCL @@ -1001,7 +1001,7 @@ static void LookupPredefedObjCSuperType(Sema &Sema, Scope *S) { Sema.LookupName(Result, S); if (Result.getResultKind() == LookupResultKind::Found) if (const TagDecl *TD = Result.getAsSingle<TagDecl>()) - Context.setObjCSuperType(Context.getTagDeclType(TD)); + Context.setObjCSuperType(Context.getCanonicalTagType(TD)); } void Sema::LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID) { @@ -2435,12 +2435,12 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, if (!R.getLookupName()) return false; +#ifndef NDEBUG // Make sure that the declaration context is complete. - assert((!isa<TagDecl>(LookupCtx) || - LookupCtx->isDependentContext() || - cast<TagDecl>(LookupCtx)->isCompleteDefinition() || - cast<TagDecl>(LookupCtx)->isBeingDefined()) && - "Declaration context must already be complete!"); + if (const auto *TD = dyn_cast<TagDecl>(LookupCtx); + TD && !TD->isDependentType() && TD->getDefinition() == nullptr) + llvm_unreachable("Declaration context must already be complete!"); +#endif struct QualifiedLookupInScope { bool oldVal; @@ -2596,10 +2596,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // C++ [class.member.lookup]p3: // type declarations (including injected-class-names) are replaced by // the types they designate - if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) { - QualType T = Context.getTypeDeclType(TD); - return T.getCanonicalType().getAsOpaquePtr(); - } + if (const TypeDecl *TD = dyn_cast<TypeDecl>(ND->getUnderlyingDecl())) + return Context.getCanonicalTypeDeclType(TD).getAsOpaquePtr(); return ND->getUnderlyingDecl()->getCanonicalDecl(); } @@ -2704,12 +2702,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXScopeSpec &SS) { - auto *NNS = SS.getScopeRep(); - if (NNS && NNS->getKind() == NestedNameSpecifier::Super) - return LookupInSuper(R, NNS->getAsRecordDecl()); - else - - return LookupQualifiedName(R, LookupCtx); + NestedNameSpecifier Qualifier = SS.getScopeRep(); + if (Qualifier.getKind() == NestedNameSpecifier::Kind::MicrosoftSuper) + return LookupInSuper(R, Qualifier.getAsMicrosoftSuper()); + return LookupQualifiedName(R, LookupCtx); } bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, @@ -2731,7 +2727,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, IsDependent = !DC && ObjectType->isDependentType(); assert(((!DC && ObjectType->isDependentType()) || !ObjectType->isIncompleteType() || !ObjectType->getAs<TagType>() || - ObjectType->castAs<TagType>()->isBeingDefined()) && + ObjectType->castAs<TagType>() + ->getOriginalDecl() + ->isEntityBeingDefined()) && "Caller should have completed object type"); } else if (SS && SS->isNotEmpty()) { // This nested-name-specifier occurs after another nested-name-specifier, @@ -2744,9 +2742,9 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, // FIXME: '__super' lookup semantics could be implemented by a // LookupResult::isSuperLookup flag which skips the initial search of // the lookup context in LookupQualified. - if (NestedNameSpecifier *NNS = SS->getScopeRep(); - NNS->getKind() == NestedNameSpecifier::Super) - return LookupInSuper(R, NNS->getAsRecordDecl()); + if (NestedNameSpecifier Qualifier = SS->getScopeRep(); + Qualifier.getKind() == NestedNameSpecifier::Kind::MicrosoftSuper) + return LookupInSuper(R, Qualifier.getAsMicrosoftSuper()); } IsDependent = !DC && isDependentScopeSpecifier(*SS); } else { @@ -2772,10 +2770,12 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { // members of Class itself. That is, the naming class is Class, and the // access includes the access of the base. for (const auto &BaseSpec : Class->bases()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>( - BaseSpec.getType()->castAs<RecordType>()->getDecl()); + CXXRecordDecl *RD = + cast<CXXRecordDecl>( + BaseSpec.getType()->castAs<RecordType>()->getOriginalDecl()) + ->getDefinitionOrSelf(); LookupResult Result(*this, R.getLookupNameInfo(), R.getLookupKind()); - Result.setBaseObjectType(Context.getRecordType(Class)); + Result.setBaseObjectType(Context.getCanonicalTagType(Class)); LookupQualifiedName(Result, RD); // Copy the lookup results into the target, merging the base's access into @@ -3101,7 +3101,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // Only recurse into base classes for complete types. if (!Result.S.isCompleteType(Result.InstantiationLoc, - Result.S.Context.getRecordType(Class))) + Result.S.Context.getCanonicalTagType(Class))) return; // Add direct and indirect base classes along with their associated @@ -3123,7 +3123,8 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // the classes and namespaces of known non-dependent arguments. if (!BaseType) continue; - CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getOriginalDecl()) + ->getDefinitionOrSelf(); if (Result.addClassTransitive(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); @@ -3194,8 +3195,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // Its associated namespaces are the innermost enclosing // namespaces of its associated classes. case Type::Record: { + // FIXME: This should use the original decl. CXXRecordDecl *Class = - cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl()); + cast<CXXRecordDecl>(cast<RecordType>(T)->getOriginalDecl()) + ->getDefinitionOrSelf(); addAssociatedClassesAndNamespaces(Result, Class); break; } @@ -3205,7 +3208,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // If it is a class member, its associated class is the // member’s class; else it has no associated class. case Type::Enum: { - EnumDecl *Enum = cast<EnumType>(T)->getDecl(); + // FIXME: This should use the original decl. + EnumDecl *Enum = + cast<EnumType>(T)->getOriginalDecl()->getDefinitionOrSelf(); DeclContext *Ctx = Enum->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) @@ -3438,7 +3443,7 @@ Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMemberKind SM, // Prepare for overload resolution. Here we construct a synthetic argument // if necessary and make sure that implicit functions are declared. - CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(RD)); + CanQualType CanTy = Context.getCanonicalTagType(RD); DeclarationName Name; Expr *Arg = nullptr; unsigned NumArgs; @@ -3645,7 +3650,7 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { }); } - CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class)); + CanQualType T = Context.getCanonicalTagType(Class); DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T); return Class->lookup(Name); } @@ -4260,7 +4265,7 @@ private: const auto *Record = BaseType->getAs<RecordType>(); if (!Record) continue; - RD = Record->getDecl(); + RD = Record->getOriginalDecl()->getDefinitionOrSelf(); } // FIXME: It would be nice to be able to determine whether referencing @@ -4546,40 +4551,101 @@ static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC) { // the given NestedNameSpecifier (i.e. given a NestedNameSpecifier "foo::bar::", // fill the vector with the IdentifierInfo pointers for "foo" and "bar"). static void getNestedNameSpecifierIdentifiers( - NestedNameSpecifier *NNS, - SmallVectorImpl<const IdentifierInfo*> &Identifiers) { - if (NestedNameSpecifier *Prefix = NNS->getPrefix()) - getNestedNameSpecifierIdentifiers(Prefix, Identifiers); - else + NestedNameSpecifier NNS, + SmallVectorImpl<const IdentifierInfo *> &Identifiers) { + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Null: Identifiers.clear(); + return; - const IdentifierInfo *II = nullptr; - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - II = NNS->getAsIdentifier(); - break; - - case NestedNameSpecifier::Namespace: { - const NamespaceBaseDecl *Namespace = NNS->getAsNamespace(); + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix(); + getNestedNameSpecifierIdentifiers(Prefix, Identifiers); if (const auto *NS = dyn_cast<NamespaceDecl>(Namespace); NS && NS->isAnonymousNamespace()) return; - II = Namespace->getIdentifier(); - break; + Identifiers.push_back(Namespace->getIdentifier()); + return; } - case NestedNameSpecifier::TypeSpec: - II = QualType(NNS->getAsType(), 0).getBaseTypeIdentifier(); + case NestedNameSpecifier::Kind::Type: { + for (const Type *T = NNS.getAsType(); /**/; /**/) { + switch (T->getTypeClass()) { + case Type::DependentName: { + auto *DT = cast<DependentNameType>(T); + getNestedNameSpecifierIdentifiers(DT->getQualifier(), Identifiers); + Identifiers.push_back(DT->getIdentifier()); + return; + } + case Type::TemplateSpecialization: { + TemplateName Name = + cast<TemplateSpecializationType>(T)->getTemplateName(); + if (const QualifiedTemplateName *QTN = + Name.getAsAdjustedQualifiedTemplateName()) { + getNestedNameSpecifierIdentifiers(QTN->getQualifier(), Identifiers); + Name = QTN->getUnderlyingTemplate(); + } + if (const auto *TD = Name.getAsTemplateDecl(/*IgnoreDeduced=*/true)) + Identifiers.push_back(TD->getIdentifier()); + return; + } + case Type::DependentTemplateSpecialization: { + const DependentTemplateStorage &S = + cast<DependentTemplateSpecializationType>(T) + ->getDependentTemplateName(); + getNestedNameSpecifierIdentifiers(S.getQualifier(), Identifiers); + // FIXME: Should this dig into the Name as well? + // Identifiers.push_back(S.getName().getIdentifier()); + return; + } + case Type::SubstTemplateTypeParm: + T = cast<SubstTemplateTypeParmType>(T) + ->getReplacementType() + .getTypePtr(); + continue; + case Type::TemplateTypeParm: + Identifiers.push_back(cast<TemplateTypeParmType>(T)->getIdentifier()); + return; + case Type::Decltype: + return; + case Type::Enum: + case Type::Record: + case Type::InjectedClassName: { + auto *TT = cast<TagType>(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getOriginalDecl()->getIdentifier()); + return; + } + case Type::Typedef: { + auto *TT = cast<TypedefType>(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getDecl()->getIdentifier()); + return; + } + case Type::Using: { + auto *TT = cast<UsingType>(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getDecl()->getIdentifier()); + return; + } + case Type::UnresolvedUsing: { + auto *TT = cast<UnresolvedUsingType>(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getDecl()->getIdentifier()); + return; + } + default: + Identifiers.push_back(QualType(T, 0).getBaseTypeIdentifier()); + return; + } + } break; + } - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: return; } - - if (II) - Identifiers.push_back(II); } void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, @@ -4612,11 +4678,11 @@ void TypoCorrectionConsumer::FoundName(StringRef Name) { void TypoCorrectionConsumer::addKeywordResult(StringRef Keyword) { // Compute the edit distance between the typo and this keyword, // and add the keyword to the list of results. - addName(Keyword, nullptr, nullptr, true); + addName(Keyword, /*ND=*/nullptr, /*NNS=*/std::nullopt, /*isKeyword=*/true); } void TypoCorrectionConsumer::addName(StringRef Name, NamedDecl *ND, - NestedNameSpecifier *NNS, bool isKeyword) { + NestedNameSpecifier NNS, bool isKeyword) { // Use a simple length-based heuristic to determine the minimum possible // edit distance. If the minimum isn't good enough, bail out early. StringRef TypoStr = Typo->getName(); @@ -4708,10 +4774,10 @@ void TypoCorrectionConsumer::addNamespaces( Namespaces.addNameSpecifier(KNPair.first); bool SSIsTemplate = false; - if (NestedNameSpecifier *NNS = - (SS && SS->isValid()) ? SS->getScopeRep() : nullptr) { - if (const Type *T = NNS->getAsType()) - SSIsTemplate = T->getTypeClass() == Type::TemplateSpecialization; + if (NestedNameSpecifier NNS = (SS ? SS->getScopeRep() : std::nullopt)) { + if (NNS.getKind() == NestedNameSpecifier::Kind::Type) + SSIsTemplate = + NNS.getAsType()->getTypeClass() == Type::TemplateSpecialization; } // Do not transform this into an iterator-based loop. The loop body can // trigger the creation of further types (through lazy deserialization) and @@ -4813,17 +4879,15 @@ void TypoCorrectionConsumer::performQualifiedLookups() { for (const TypoCorrection &QR : QualifiedResults) { for (const auto &NSI : Namespaces) { DeclContext *Ctx = NSI.DeclCtx; - const Type *NSType = NSI.NameSpecifier->getAsType(); + CXXRecordDecl *NamingClass = NSI.NameSpecifier.getAsRecordDecl(); // If the current NestedNameSpecifier refers to a class and the // current correction candidate is the name of that class, then skip // it as it is unlikely a qualified version of the class' constructor // is an appropriate correction. - if (CXXRecordDecl *NSDecl = NSType ? NSType->getAsCXXRecordDecl() : - nullptr) { - if (NSDecl->getIdentifier() == QR.getCorrectionAsIdentifierInfo()) - continue; - } + if (NamingClass && + NamingClass->getIdentifier() == QR.getCorrectionAsIdentifierInfo()) + continue; TypoCorrection TC(QR); TC.ClearCorrectionDecls(); @@ -4853,7 +4917,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() { std::string NewQualified = TC.getAsString(SemaRef.getLangOpts()); std::string OldQualified; llvm::raw_string_ostream OldOStream(OldQualified); - SS->getScopeRep()->print(OldOStream, SemaRef.getPrintingPolicy()); + SS->getScopeRep().print(OldOStream, SemaRef.getPrintingPolicy()); OldOStream << Typo->getName(); // If correction candidate would be an identical written qualified // identifier, then the existing CXXScopeSpec probably included a @@ -4864,8 +4928,7 @@ void TypoCorrectionConsumer::performQualifiedLookups() { for (LookupResult::iterator TRD = Result.begin(), TRDEnd = Result.end(); TRD != TRDEnd; ++TRD) { if (SemaRef.CheckMemberAccess(TC.getCorrectionRange().getBegin(), - NSType ? NSType->getAsCXXRecordDecl() - : nullptr, + NamingClass, TRD.getPair()) == Sema::AR_accessible) TC.addCorrectionDecl(*TRD); } @@ -4889,10 +4952,10 @@ void TypoCorrectionConsumer::performQualifiedLookups() { TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec) : Context(Context), CurContextChain(buildContextChain(CurContext)) { - if (NestedNameSpecifier *NNS = - CurScopeSpec ? CurScopeSpec->getScopeRep() : nullptr) { + if (NestedNameSpecifier NNS = + CurScopeSpec ? CurScopeSpec->getScopeRep() : std::nullopt) { llvm::raw_string_ostream SpecifierOStream(CurNameSpecifier); - NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + NNS.print(SpecifierOStream, Context.getPrintingPolicy()); getNestedNameSpecifierIdentifiers(NNS, CurNameSpecifierIdentifiers); } @@ -4906,7 +4969,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::NamespaceSpecifierSet( // Add the global context as a NestedNameSpecifier SpecifierInfo SI = {cast<DeclContext>(Context.getTranslationUnitDecl()), - NestedNameSpecifier::GlobalSpecifier(Context), 1}; + NestedNameSpecifier::getGlobal(), 1}; DistanceMap[1].push_back(SI); } @@ -4926,14 +4989,16 @@ auto TypoCorrectionConsumer::NamespaceSpecifierSet::buildContextChain( unsigned TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( - DeclContextList &DeclChain, NestedNameSpecifier *&NNS) { + DeclContextList &DeclChain, NestedNameSpecifier &NNS) { unsigned NumSpecifiers = 0; for (DeclContext *C : llvm::reverse(DeclChain)) { if (auto *ND = dyn_cast_or_null<NamespaceDecl>(C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, ND); + NNS = NestedNameSpecifier(Context, ND, NNS); ++NumSpecifiers; } else if (auto *RD = dyn_cast_or_null<RecordDecl>(C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, RD->getTypeForDecl()); + QualType T = Context.getTagType(ElaboratedTypeKeyword::None, NNS, RD, + /*OwnsTag=*/false); + NNS = NestedNameSpecifier(T.getTypePtr()); ++NumSpecifiers; } } @@ -4942,7 +5007,7 @@ TypoCorrectionConsumer::NamespaceSpecifierSet::buildNestedNameSpecifier( void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( DeclContext *Ctx) { - NestedNameSpecifier *NNS = nullptr; + NestedNameSpecifier NNS = std::nullopt; unsigned NumSpecifiers = 0; DeclContextList NamespaceDeclChain(buildContextChain(Ctx)); DeclContextList FullNamespaceDeclChain(NamespaceDeclChain); @@ -4960,7 +5025,7 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( // Add an explicit leading '::' specifier if needed. if (NamespaceDeclChain.empty()) { // Rebuild the NestedNameSpecifier as a globally-qualified specifier. - NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NNS = NestedNameSpecifier::getGlobal(); NumSpecifiers = buildNestedNameSpecifier(FullNamespaceDeclChain, NNS); } else if (NamedDecl *ND = @@ -4972,12 +5037,12 @@ void TypoCorrectionConsumer::NamespaceSpecifierSet::addNameSpecifier( llvm::raw_string_ostream SpecifierOStream(NewNameSpecifier); SmallVector<const IdentifierInfo *, 4> NewNameSpecifierIdentifiers; getNestedNameSpecifierIdentifiers(NNS, NewNameSpecifierIdentifiers); - NNS->print(SpecifierOStream, Context.getPrintingPolicy()); + NNS.print(SpecifierOStream, Context.getPrintingPolicy()); SameNameSpecifier = NewNameSpecifier == CurNameSpecifier; } if (SameNameSpecifier || llvm::is_contained(CurContextIdentifiers, Name)) { // Rebuild the NestedNameSpecifier as a globally-qualified specifier. - NNS = NestedNameSpecifier::GlobalSpecifier(Context); + NNS = NestedNameSpecifier::getGlobal(); NumSpecifiers = buildNestedNameSpecifier(FullNamespaceDeclChain, NNS); } @@ -5463,7 +5528,7 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const { if (CorrectionNameSpec) { std::string tmpBuffer; llvm::raw_string_ostream PrefixOStream(tmpBuffer); - CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO)); + CorrectionNameSpec.print(PrefixOStream, PrintingPolicy(LO)); PrefixOStream << CorrectionName; return PrefixOStream.str(); } diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index b137549..ff9f85f 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -1222,7 +1222,8 @@ bool ExposureChecker::isTULocal(const NamedDecl *D) { // [basic.link]p15.5 // - a specialization of a template whose (possibly instantiated) declaration // is an exposure. - if (checkExposure(PrimaryTemplate, /*Diag=*/false)) + if (ExposureSet.count(PrimaryTemplate) || + checkExposure(PrimaryTemplate, /*Diag=*/false)) return true; // Avoid calling checkExposure again since it is expensive. diff --git a/clang/lib/Sema/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp index 0f39a98..8d8d5e8 100644 --- a/clang/lib/Sema/SemaObjC.cpp +++ b/clang/lib/Sema/SemaObjC.cpp @@ -691,7 +691,7 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) { S.Diag(loc, diag::err_objc_type_args_wrong_arity) << (typeArgs.size() < typeParams->size()) << objcClass->getDeclName() - << (unsigned)finalTypeArgs.size() << (unsigned)numTypeParams; + << (unsigned)finalTypeArgs.size() << numTypeParams; S.Diag(objcClass->getLocation(), diag::note_previous_decl) << objcClass; if (failOnError) @@ -1407,7 +1407,8 @@ SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { int NoIntegrals = 0, NoObjCIdPointers = 0; SmallVector<CXXConversionDecl *, 4> ConversionDecls; - for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl()) + for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf() ->getVisibleConversionFunctions()) { if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) { @@ -1510,7 +1511,7 @@ bool SemaObjC::isCFStringType(QualType T) { if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl(); if (RD->getTagKind() != TagTypeKind::Struct) return false; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 9dbb1d2..bf6c364 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1321,7 +1321,9 @@ Decl *SemaObjC::ActOnPropertyImplDecl( } if (!CompleteTypeErr) { const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>(); - if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) { + if (RecordTy && RecordTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) { Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar) << PropertyIvarType; CompleteTypeErr = true; // suppress later diagnostics about the ivar diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 62fe3d1..4d58b4a 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -646,8 +646,17 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr, if (auto *RefTy = InnerTy->getAs<ReferenceType>()) InnerTy = RefTy->getPointeeType(); - if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe()) + if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe()) { + // Non constant arrays decay to 'pointer', so warn and return that we're + // successful. + if (!ArrTy->isConstantArrayType()) { + S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_non_const_array) + << InnerTy << CK; + return VarExpr; + } + return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType()); + } auto *RD = InnerTy->getAsCXXRecordDecl(); @@ -2575,8 +2584,8 @@ SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) { return BuildOpenACCAsteriskSizeExpr(AsteriskLoc); } -VarDecl *SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, - const Expr *VarExpr) { +std::pair<VarDecl *, VarDecl *> +SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, const Expr *VarExpr) { // Strip off any array subscripts/array section exprs to get to the type of // the variable. while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) { @@ -2590,7 +2599,7 @@ VarDecl *SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, // fill in with nullptr. We'll count on TreeTransform to make this if // necessary. if (!VarExpr || VarExpr->getType()->isDependentType()) - return nullptr; + return {nullptr, nullptr}; QualType VarTy = VarExpr->getType().getNonReferenceType().getUnqualifiedType(); @@ -2602,6 +2611,7 @@ VarDecl *SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto); ExprResult Init; + VarDecl *Temporary = nullptr; if (CK == OpenACCClauseKind::Private) { // Trap errors so we don't get weird ones here. If we can't init, we'll just @@ -2626,5 +2636,5 @@ VarDecl *SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, Recipe->setInitStyle(VarDecl::CallInit); } - return Recipe; + return {Recipe, Temporary}; } diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp index 88d217f..e8a18243 100644 --- a/clang/lib/Sema/SemaOpenACCClause.cpp +++ b/clang/lib/Sema/SemaOpenACCClause.cpp @@ -800,7 +800,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( // Assemble the recipes list. for (const Expr *VarExpr : Clause.getVarList()) InitRecipes.push_back( - SemaRef.CreateInitRecipe(OpenACCClauseKind::Private, VarExpr)); + SemaRef.CreateInitRecipe(OpenACCClauseKind::Private, VarExpr).first); return OpenACCPrivateClause::Create( Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(), @@ -813,7 +813,7 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause( // really isn't anything to do here. GCC does some duplicate-finding, though // it isn't apparent in the standard where this is justified. - llvm::SmallVector<VarDecl *> InitRecipes; + llvm::SmallVector<OpenACCFirstPrivateRecipe> InitRecipes; // Assemble the recipes list. for (const Expr *VarExpr : Clause.getVarList()) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2c5d97c..7d800c4 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -7358,7 +7358,9 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR; return std::nullopt; } - QualType InteropType = Context.getTypeDeclType(TD); + QualType InteropType = + Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD); if (PTy->isVariadic()) { Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR; return std::nullopt; @@ -7378,7 +7380,7 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG, auto *Method = dyn_cast<CXXMethodDecl>(FD); if (Method && !Method->isStatic()) { FnPtrType = Context.getMemberPointerType( - AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent()); + AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent()); ExprResult ER; { // Build addr_of unary op to correctly handle type checks for member @@ -18629,10 +18631,11 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, if (const auto *TyRec = Ty->getAs<RecordType>()) { // Complete the type if it can be completed. // If the type is neither complete nor being defined, bail out now. - if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() || - TyRec->getDecl()->getDefinition()) { + bool IsComplete = SemaRef.isCompleteType(Loc, Ty); + RecordDecl *RD = TyRec->getOriginalDecl()->getDefinition(); + if (IsComplete || RD) { Lookup.clear(); - SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl()); + SemaRef.LookupQualifiedName(Lookup, RD); if (Lookup.empty()) { Lookups.emplace_back(); Lookups.back().append(Lookup.begin(), Lookup.end()); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 76e189d..d593d1d 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -370,7 +370,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( // the underlying type is narrowing. This only arises for expressions of // the form 'Enum{init}'. if (auto *ET = ToType->getAs<EnumType>()) - ToType = ET->getDecl()->getIntegerType(); + ToType = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); switch (Second) { // 'bool' is an integral type; dispatch to the right place to handle it. @@ -1063,7 +1063,8 @@ static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc, return true; LookupResult Members(S, NotEqOp, OpLoc, Sema::LookupNameKind::LookupMemberName); - S.LookupQualifiedName(Members, RHSRec->getDecl()); + S.LookupQualifiedName(Members, + RHSRec->getOriginalDecl()->getDefinitionOrSelf()); Members.suppressAccessDiagnostics(); for (NamedDecl *Op : Members) if (FunctionsCorrespond(S.Context, EqFD, Op->getAsFunction())) @@ -1268,7 +1269,7 @@ OverloadKind Sema::CheckOverload(Scope *S, FunctionDecl *New, // // Exception: if the scope is dependent and this is not a class // member, the using declaration can only introduce an enumerator. - if (UUD->getQualifier()->isDependent() && !UUD->isCXXClassMember()) { + if (UUD->getQualifier().isDependent() && !UUD->isCXXClassMember()) { Match = *I; return OverloadKind::NonFunction; } @@ -1471,9 +1472,8 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, if (OldMethod->isImplicitObjectMemberFunction() && OldMethod->getParent() != NewMethod->getParent()) { - QualType ParentType = - SemaRef.Context.getTypeDeclType(OldMethod->getParent()) - .getCanonicalType(); + CanQualType ParentType = + SemaRef.Context.getCanonicalTagType(OldMethod->getParent()); if (ParentType.getTypePtr() != BS.Ty) return false; BS.Ty = DS.Ty; @@ -2293,7 +2293,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, == UO_AddrOf && "Non-address-of operator on non-static member address"); FromType = S.Context.getMemberPointerType( - FromType, /*Qualifier=*/nullptr, Method->getParent()); + FromType, /*Qualifier=*/std::nullopt, Method->getParent()); } else if (isa<UnaryOperator>(From->IgnoreParens())) { assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == UO_AddrOf && @@ -2602,10 +2602,12 @@ IsTransparentUnionStandardConversion(Sema &S, Expr* From, bool CStyle) { const RecordType *UT = ToType->getAsUnionType(); - if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (!UT) return false; // The field to initialize within the transparent union. - RecordDecl *UD = UT->getDecl(); + const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + if (!UD->hasAttr<TransparentUnionAttr>()) + return false; // It's compatible if the expression matches any of the fields. for (const auto *it : UD->fields()) { if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, @@ -2663,15 +2665,17 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) { // C++0x 7.2p9: Note that this implicit enum to int conversion is not // provided for a scoped enumeration. - if (FromEnumType->getDecl()->isScoped()) + const EnumDecl *FromED = + FromEnumType->getOriginalDecl()->getDefinitionOrSelf(); + if (FromED->isScoped()) return false; // We can perform an integral promotion to the underlying type of the enum, // even if that's not the promoted type. Note that the check for promoting // the underlying type is based on the type alone, and does not consider // the bitfield-ness of the actual source expression. - if (FromEnumType->getDecl()->isFixed()) { - QualType Underlying = FromEnumType->getDecl()->getIntegerType(); + if (FromED->isFixed()) { + QualType Underlying = FromED->getIntegerType(); return Context.hasSameUnqualifiedType(Underlying, ToType) || IsIntegralPromotion(nullptr, Underlying, ToType); } @@ -2679,8 +2683,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && isCompleteType(From->getBeginLoc(), FromType)) - return Context.hasSameUnqualifiedType( - ToType, FromEnumType->getDecl()->getPromotionType()); + return Context.hasSameUnqualifiedType(ToType, FromED->getPromotionType()); // C++ [conv.prom]p5: // If the bit-field has an enumerated type, it is treated as any other @@ -3347,12 +3350,12 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, ToMember->getMostRecentCXXRecordDecl())) { PDiag << ft_different_class; if (ToMember->isSugared()) - PDiag << Context.getTypeDeclType( + PDiag << Context.getCanonicalTagType( ToMember->getMostRecentCXXRecordDecl()); else PDiag << ToMember->getQualifier(); if (FromMember->isSugared()) - PDiag << Context.getTypeDeclType( + PDiag << Context.getCanonicalTagType( FromMember->getMostRecentCXXRecordDecl()); else PDiag << FromMember->getQualifier(); @@ -3636,12 +3639,12 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(), *ToClass = ToPtrType->getMostRecentCXXRecordDecl(); - auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual, - const CXXRecordDecl *Cls) { - if (declaresSameEntity(Qual->getAsRecordDecl(), Cls)) + auto DiagCls = [&](PartialDiagnostic &PD, NestedNameSpecifier Qual, + const CXXRecordDecl *Cls) { + if (declaresSameEntity(Qual.getAsRecordDecl(), Cls)) PD << Qual; else - PD << QualType(Cls->getTypeForDecl(), 0); + PD << Context.getCanonicalTagType(Cls); }; auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & { DiagCls(PD, FromPtrType->getQualifier(), FromClass); @@ -3658,8 +3661,7 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths)) return MemberPointerConversionResult::NotDerived; - if (Paths.isAmbiguous( - Base->getTypeForDecl()->getCanonicalTypeUnqualified())) { + if (Paths.isAmbiguous(Context.getCanonicalTagType(Base))) { PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv); PD << int(Direction); DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange; @@ -3687,8 +3689,8 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion( ? diag::err_upcast_to_inaccessible_base : diag::err_downcast_from_inaccessible_base, [&](PartialDiagnostic &PD) { - NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(), - *DerivedQual = ToPtrType->getQualifier(); + NestedNameSpecifier BaseQual = FromPtrType->getQualifier(), + DerivedQual = ToPtrType->getQualifier(); if (Direction == MemberPointerConversionDirection::Upcast) std::swap(BaseQual, DerivedQual); DiagCls(PD, DerivedQual, Derived); @@ -3983,8 +3985,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, if (!S.isCompleteType(From->getExprLoc(), ToType)) { // We're not going to find any constructors. - } else if (CXXRecordDecl *ToRecordDecl - = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { + } else if (auto *ToRecordDecl = + dyn_cast<CXXRecordDecl>(ToRecordType->getOriginalDecl())) { + ToRecordDecl = ToRecordDecl->getDefinitionOrSelf(); Expr **Args = &From; unsigned NumArgs = 1; @@ -4057,8 +4060,9 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType = From->getType()->getAs<RecordType>()) { - if (CXXRecordDecl *FromRecordDecl - = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { + if (auto *FromRecordDecl = + dyn_cast<CXXRecordDecl>(FromRecordType->getOriginalDecl())) { + FromRecordDecl = FromRecordDecl->getDefinitionOrSelf(); // Add all of the conversion functions as candidates. const auto &Conversions = FromRecordDecl->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) { @@ -4509,7 +4513,8 @@ getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) { if (!FromType->isEnumeralType()) return FixedEnumPromotion::None; - EnumDecl *Enum = FromType->castAs<EnumType>()->getDecl(); + EnumDecl *Enum = + FromType->castAs<EnumType>()->getOriginalDecl()->getDefinitionOrSelf(); if (!Enum->isFixed()) return FixedEnumPromotion::None; @@ -5145,7 +5150,9 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, Expr *Init, QualType T2, bool AllowRvalues, bool AllowExplicit) { assert(T2->isRecordType() && "Can only find conversions of record types."); - auto *T2RecordDecl = cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl()); + auto *T2RecordDecl = + cast<CXXRecordDecl>(T2->castAs<RecordType>()->getOriginalDecl()) + ->getDefinitionOrSelf(); OverloadCandidateSet CandidateSet( DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion); @@ -5934,7 +5941,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( assert(FromType->isRecordType()); - QualType ClassType = S.Context.getTypeDeclType(ActingContext); + CanQualType ClassType = S.Context.getCanonicalTagType(ActingContext); // C++98 [class.dtor]p2: // A destructor can be invoked for a const, volatile or const volatile // object. @@ -6055,7 +6062,7 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( /// the implicit object parameter for the given Method with the given /// expression. ExprResult Sema::PerformImplicitObjectArgumentInitialization( - Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, + Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getFunctionObjectParameterType(); @@ -6840,8 +6847,9 @@ ExprResult Sema::PerformContextualImplicitConversion( UnresolvedSet<4> ViableConversions; // These are *potentially* viable in C++1y. UnresolvedSet<4> ExplicitConversions; - const auto &Conversions = - cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + const auto &Conversions = cast<CXXRecordDecl>(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf() + ->getVisibleConversionFunctions(); bool HadMultipleCandidates = (std::distance(Conversions.begin(), Conversions.end()) > 1); @@ -7160,7 +7168,8 @@ void Sema::AddOverloadCandidate( // C++ [class.copy]p3: // A member function template is never instantiated to perform the copy // of a class object to an object of its class type. - QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); + CanQualType ClassType = + Context.getCanonicalTagType(Constructor->getParent()); if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() && (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || IsDerivedFrom(Args[0]->getBeginLoc(), Args[0]->getType(), @@ -7181,8 +7190,8 @@ void Sema::AddOverloadCandidate( if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 && Constructor->getParamDecl(0)->getType()->isReferenceType()) { QualType P = Constructor->getParamDecl(0)->getType()->getPointeeType(); - QualType C = Context.getRecordType(Constructor->getParent()); - QualType D = Context.getRecordType(Shadow->getParent()); + CanQualType C = Context.getCanonicalTagType(Constructor->getParent()); + CanQualType D = Context.getCanonicalTagType(Shadow->getParent()); SourceLocation Loc = Args.front()->getExprLoc(); if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, C)) && (Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, P))) { @@ -7403,7 +7412,7 @@ static bool convertArgsForAvailabilityChecks( "Shouldn't have `this` for ctors!"); assert(!Method->isStatic() && "Shouldn't have `this` for static methods!"); ExprResult R = S.PerformImplicitObjectArgumentInitialization( - ThisArg, /*Qualifier=*/nullptr, Method, Method); + ThisArg, /*Qualifier=*/std::nullopt, Method, Method); if (R.isInvalid()) return false; ConvertedThis = R.get(); @@ -8159,29 +8168,24 @@ bool Sema::CheckNonDependentConversions( ArgType = ArgType->getPointeeType(); } - if (auto *RT = ParamType->getAs<RecordType>()) - if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - RD && RD->hasDefinition()) { - if (llvm::any_of(LookupConstructors(RD), [](NamedDecl *ND) { - auto Info = getConstructorInfo(ND); - if (!Info) - return false; - CXXConstructorDecl *Ctor = Info.Constructor; - /// isConvertingConstructor takes copy/move constructors into - /// account! - return !Ctor->isCopyOrMoveConstructor() && - Ctor->isConvertingConstructor( - /*AllowExplicit=*/true); - })) - return true; - } - - if (auto *RT = ArgType->getAs<RecordType>()) - if (auto *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - RD && RD->hasDefinition() && - !RD->getVisibleConversionFunctions().empty()) { - return true; - } + if (auto *RD = ParamType->getAsCXXRecordDecl(); + RD && RD->hasDefinition() && + llvm::any_of(LookupConstructors(RD), [](NamedDecl *ND) { + auto Info = getConstructorInfo(ND); + if (!Info) + return false; + CXXConstructorDecl *Ctor = Info.Constructor; + /// isConvertingConstructor takes copy/move constructors into + /// account! + return !Ctor->isCopyOrMoveConstructor() && + Ctor->isConvertingConstructor( + /*AllowExplicit=*/true); + })) + return true; + if (auto *RD = ArgType->getAsCXXRecordDecl(); + RD && RD->hasDefinition() && + !RD->getVisibleConversionFunctions().empty()) + return true; return false; }; @@ -8336,7 +8340,8 @@ void Sema::AddConversionCandidate( if (const auto *FromPtrType = ObjectType->getAs<PointerType>()) ObjectType = FromPtrType->getPointeeType(); const auto *ConversionContext = - cast<CXXRecordDecl>(ObjectType->castAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(ObjectType->castAs<RecordType>()->getOriginalDecl()) + ->getDefinitionOrSelf(); // C++23 [over.best.ics.general] // However, if the target is [...] @@ -8736,15 +8741,16 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise, // the set of member candidates is empty. if (const RecordType *T1Rec = T1->getAs<RecordType>()) { + bool IsComplete = isCompleteType(OpLoc, T1); + CXXRecordDecl *T1RD = + cast<CXXRecordDecl>(T1Rec->getOriginalDecl())->getDefinition(); // Complete the type if it can be completed. - if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined()) - return; // If the type is neither complete nor being defined, bail out now. - if (!T1Rec->getDecl()->getDefinition()) + if (!T1RD || (!IsComplete && !T1RD->isBeingDefined())) return; LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName); - LookupQualifiedName(Operators, T1Rec->getDecl()); + LookupQualifiedName(Operators, T1RD); Operators.suppressAccessDiagnostics(); for (LookupResult::iterator Oper = Operators.begin(), @@ -9009,8 +9015,8 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( if ((CVR | BaseCVR) != CVR) continue; QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); - MemberPointerTypes.insert( - Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls)); + MemberPointerTypes.insert(Context.getMemberPointerType( + QPointeeTy, /*Qualifier=*/std::nullopt, Cls)); } return true; @@ -9087,7 +9093,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, if (!SemaRef.isCompleteType(Loc, Ty)) return; - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); + auto *ClassDecl = + cast<CXXRecordDecl>(TyRec->getOriginalDecl())->getDefinitionOrSelf(); for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) { if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -10199,7 +10206,7 @@ public: if (S.getLangOpts().CPlusPlus11) { for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { - if (!EnumTy->castAs<EnumType>()->getDecl()->isScoped()) + if (!EnumTy->castAs<EnumType>()->getOriginalDecl()->isScoped()) continue; if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second) @@ -10955,9 +10962,9 @@ bool clang::isBetterOverloadCandidate( isa<CXXConversionDecl>(Cand1.Function) ? TPOC_Conversion : TPOC_Call, Cand1.ExplicitCallArguments, - Obj1Context ? QualType(Obj1Context->getTypeForDecl(), 0) + Obj1Context ? S.Context.getCanonicalTagType(Obj1Context) : QualType{}, - Obj2Context ? QualType(Obj2Context->getTypeForDecl(), 0) + Obj2Context ? S.Context.getCanonicalTagType(Obj2Context) : QualType{}, Cand1.isReversed() ^ Cand2.isReversed(), PartialOverloading)) { return BetterTemplate == Cand1.Function->getPrimaryTemplate(); @@ -14863,8 +14870,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, if (Method->isExplicitObjectMemberFunction()) Exp = InitializeExplicitObjectArgument(*this, E, Method); else - Exp = PerformImplicitObjectArgumentInitialization(E, /*Qualifier=*/nullptr, - FoundDecl, Method); + Exp = PerformImplicitObjectArgumentInitialization( + E, /*Qualifier=*/std::nullopt, FoundDecl, Method); if (Exp.isInvalid()) return true; @@ -15025,7 +15032,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, InputInit = InitializeExplicitObjectArgument(*this, Input, Method); else InputInit = PerformImplicitObjectArgumentInitialization( - Input, /*Qualifier=*/nullptr, Best->FoundDecl, Method); + Input, /*Qualifier=*/std::nullopt, Best->FoundDecl, Method); if (InputInit.isInvalid()) return ExprError(); Base = Input = InputInit.get(); @@ -15408,7 +15415,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, ParamIdx = 1; } else { Arg0 = PerformImplicitObjectArgumentInitialization( - Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method); + Args[0], /*Qualifier=*/std::nullopt, Best->FoundDecl, Method); } Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( @@ -15878,7 +15885,7 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ArgExpr = Args; } else { ExprResult Arg0 = PerformImplicitObjectArgumentInitialization( - Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method); + Args[0], /*Qualifier=*/std::nullopt, Best->FoundDecl, Method); if (Arg0.isInvalid()) return ExprError(); @@ -16074,7 +16081,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, CXXMethodDecl *Method = nullptr; bool HadMultipleCandidates = false; DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public); - NestedNameSpecifier *Qualifier = nullptr; + NestedNameSpecifier Qualifier = std::nullopt; if (isa<MemberExpr>(NakedMemExpr)) { MemExpr = cast<MemberExpr>(NakedMemExpr); Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl()); @@ -16346,7 +16353,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, const auto *Record = Object.get()->getType()->castAs<RecordType>(); LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); - LookupQualifiedName(R, Record->getDecl()); + LookupQualifiedName(R, Record->getOriginalDecl()->getDefinitionOrSelf()); R.suppressAccessDiagnostics(); for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); @@ -16390,8 +16397,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // functions for each conversion function declared in an // accessible base class provided the function is not hidden // within T by another intervening declaration. - const auto &Conversions = - cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions(); + const auto &Conversions = cast<CXXRecordDecl>(Record->getOriginalDecl()) + ->getDefinitionOrSelf() + ->getVisibleConversionFunctions(); for (auto I = Conversions.begin(), E = Conversions.end(); !IgnoreSurrogateFunctions && I != E; ++I) { NamedDecl *D = *I; @@ -16541,7 +16549,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, IsError |= PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs); } else { ExprResult ObjRes = PerformImplicitObjectArgumentInitialization( - Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method); + Object.get(), /*Qualifier=*/std::nullopt, Best->FoundDecl, Method); if (ObjRes.isInvalid()) IsError = true; else @@ -16612,7 +16620,10 @@ ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, return ExprError(); LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName); - LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl()); + LookupQualifiedName(R, Base->getType() + ->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf()); R.suppressAccessDiagnostics(); for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); @@ -16686,7 +16697,7 @@ ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, Base = R.get(); } else { ExprResult BaseResult = PerformImplicitObjectArgumentInitialization( - Base, /*Qualifier=*/nullptr, Best->FoundDecl, Method); + Base, /*Qualifier=*/std::nullopt, Best->FoundDecl, Method); if (BaseResult.isInvalid()) return ExprError(); Base = BaseResult.get(); @@ -16940,7 +16951,7 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, assert(isa<DeclRefExpr>(SubExpr.get()) && "fixed to something other than a decl ref"); - NestedNameSpecifier *Qualifier = + NestedNameSpecifier Qualifier = cast<DeclRefExpr>(SubExpr.get())->getQualifier(); assert(Qualifier && "fixed to a member ref with no nested name qualifier"); diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp index d5c83ae..7c82e54 100644 --- a/clang/lib/Sema/SemaPPC.cpp +++ b/clang/lib/Sema/SemaPPC.cpp @@ -41,8 +41,10 @@ void SemaPPC::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) { return; QualType ArgType = Arg->getType(); - for (const FieldDecl *FD : - ArgType->castAs<RecordType>()->getDecl()->fields()) { + for (const FieldDecl *FD : ArgType->castAs<RecordType>() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) { if (const auto *AA = FD->getAttr<AlignedAttr>()) { CharUnits Alignment = getASTContext().toCharUnitsFromBits( AA->getAlignment(getASTContext())); diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 4683c81..dd25336 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -221,7 +221,7 @@ static SourceLocation SourceLocationForUserDeclaredType(QualType QT) { SourceLocation Loc; const Type *T = QT->getUnqualifiedDesugaredType(); if (const TagType *TT = dyn_cast<TagType>(T)) - Loc = TT->getDecl()->getLocation(); + Loc = TT->getOriginalDecl()->getLocation(); else if (const ObjCInterfaceType *ObjCIT = dyn_cast<ObjCInterfaceType>(T)) Loc = ObjCIT->getDecl()->getLocation(); return Loc; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a5f9202..efc0b35 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -798,7 +798,7 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) { const auto *MPT = CalleeBinOp->getRHS()->getType()->castAs<MemberPointerType>(); CalleeType.This = - Context.getTypeDeclType(MPT->getMostRecentCXXRecordDecl()); + Context.getCanonicalTagType(MPT->getMostRecentCXXRecordDecl()); CalleeType.Func = MPT->getPointeeType()->castAs<FunctionProtoType>(); CalleeType.MemberType = FuncType::ft_pointer_to_member; } else if (isa<CXXPseudoDestructorExpr>(CalleeExpr)) { @@ -1254,7 +1254,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) { if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { QualType VarType = VD->getType(); - QualType EnumType = S.Context.getTypeDeclType(ED); + CanQualType EnumType = S.Context.getCanonicalTagType(ED); if (VD->hasGlobalStorage() && VarType.isConstQualified() && S.Context.hasSameUnqualifiedType(EnumType, VarType)) return false; @@ -1284,11 +1284,11 @@ static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond, return; // Ignore anonymous enums. - if (!CondEnumType->getDecl()->getIdentifier() && - !CondEnumType->getDecl()->getTypedefNameForAnonDecl()) + if (!CondEnumType->getOriginalDecl()->getIdentifier() && + !CondEnumType->getOriginalDecl()->getTypedefNameForAnonDecl()) return; - if (!CaseEnumType->getDecl()->getIdentifier() && - !CaseEnumType->getDecl()->getTypedefNameForAnonDecl()) + if (!CaseEnumType->getOriginalDecl()->getIdentifier() && + !CaseEnumType->getOriginalDecl()->getTypedefNameForAnonDecl()) return; if (S.Context.hasSameUnqualifiedType(CondType, CaseType)) @@ -1601,9 +1601,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, // If switch has default case, then ignore it. if (!CaseListIsErroneous && !CaseListIsIncomplete && !HasConstantCond && - ET && ET->getDecl()->isCompleteDefinition() && - !ET->getDecl()->enumerators().empty()) { - const EnumDecl *ED = ET->getDecl(); + ET) { + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isCompleteDefinition() || ED->enumerators().empty()) + goto enum_out; + EnumValsTy EnumVals; // Gather all enum values, set their type and sort them, @@ -1716,6 +1718,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (!hasCasesNotInSwitch) SS->setAllEnumCasesCovered(); } + enum_out:; } if (BodyStmt) @@ -1745,7 +1748,7 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, if (SrcExpr->isTypeDependent() || SrcExpr->isValueDependent()) return; - const EnumDecl *ED = ET->getDecl(); + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); if (!ED->isClosed()) return; @@ -3710,7 +3713,7 @@ private: Sema &S; }; bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) { - auto *R = dyn_cast<CXXRecordDecl>(RT->getDecl()); + auto *R = dyn_cast<CXXRecordDecl>(RT->getOriginalDecl()); if (!R || !R->isLocalClass() || !R->isLocalClass()->isExternallyVisible() || R->isDependentType()) return true; @@ -3929,7 +3932,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, << RetValExp->getSourceRange(); if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) { if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) { - if (RT->getDecl()->isOrContainsUnion()) + if (RT->getOriginalDecl()->isOrContainsUnion()) Diag(RetValExp->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 1; } } @@ -4620,7 +4623,8 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, // Build the context parameter DeclContext *DC = CapturedDecl::castToDeclContext(CD); IdentifierInfo *ParamName = &Context.Idents.get("__context"); - QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); + CanQualType ParamType = + Context.getPointerType(Context.getCanonicalTagType(RD)); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, ImplicitParamKind::CapturedContext); @@ -4662,9 +4666,10 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, assert(!ContextIsFound && "null type has been found already for '__context' parameter"); IdentifierInfo *ParamName = &Context.Idents.get("__context"); - QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)) - .withConst() - .withRestrict(); + QualType ParamType = + Context.getPointerType(Context.getCanonicalTagType(RD)) + .withConst() + .withRestrict(); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, ImplicitParamKind::CapturedContext); @@ -4684,7 +4689,8 @@ void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, if (!ContextIsFound) { // Add __context implicitly if it is not specified. IdentifierInfo *ParamName = &Context.Idents.get("__context"); - QualType ParamType = Context.getPointerType(Context.getTagDeclType(RD)); + CanQualType ParamType = + Context.getPointerType(Context.getCanonicalTagType(RD)); auto *Param = ImplicitParamDecl::Create(Context, DC, Loc, ParamName, ParamType, ImplicitParamKind::CapturedContext); diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 4507a21..cd8b98c 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -894,7 +894,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, QT = PT->getPointeeType(); RT = QT->getAs<RecordType>(); } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl)) - RT = TD->getTypeForDecl()->getAs<RecordType>(); + RT = Context.getTypeDeclType(TD)->getAs<RecordType>(); else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl)) RT = TD->getType()->getAs<RecordType>(); if (!RT) @@ -907,7 +907,8 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, LookupResult FieldResult(*this, &Context.Idents.get(NextMember), SourceLocation(), LookupMemberName); - if (!LookupQualifiedName(FieldResult, RT->getDecl())) + RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (!LookupQualifiedName(FieldResult, RD)) return true; if (!FieldResult.isSingleResult()) @@ -919,7 +920,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, if (!FD) return true; - const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); + const ASTRecordLayout &RL = Context.getASTRecordLayout(RD); unsigned i = FD->getFieldIndex(); CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); Offset += (unsigned)Result.getQuantity(); @@ -951,7 +952,8 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, LookupMemberName); - if (!LookupQualifiedName(FieldResult, RT->getDecl())) + if (!LookupQualifiedName(FieldResult, + RT->getOriginalDecl()->getDefinitionOrSelf())) return ExprResult(); // Only normal and indirect field results will work. diff --git a/clang/lib/Sema/SemaSwift.cpp b/clang/lib/Sema/SemaSwift.cpp index 4000bef..a99222c 100644 --- a/clang/lib/Sema/SemaSwift.cpp +++ b/clang/lib/Sema/SemaSwift.cpp @@ -130,7 +130,7 @@ static bool isErrorParameter(Sema &S, QualType QT) { // Check for CFError**. if (const auto *PT = Pointee->getAs<PointerType>()) if (const auto *RT = PT->getPointeeType()->getAs<RecordType>()) - if (S.ObjC().isCFError(RT->getDecl())) + if (S.ObjC().isCFError(RT->getOriginalDecl()->getDefinitionOrSelf())) return true; return false; @@ -272,7 +272,8 @@ static void checkSwiftAsyncErrorBlock(Sema &S, Decl *D, // Check for CFError *. if (const auto *PtrTy = Param->getAs<PointerType>()) { if (const auto *RT = PtrTy->getPointeeType()->getAs<RecordType>()) { - if (S.ObjC().isCFError(RT->getDecl())) { + if (S.ObjC().isCFError( + RT->getOriginalDecl()->getDefinitionOrSelf())) { AnyErrorParams = true; break; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b6b8932..72d98ca 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -293,7 +293,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD); assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD); if (!SS.isInvalid()) { - NestedNameSpecifier *Qualifier = SS.getScopeRep(); + NestedNameSpecifier Qualifier = SS.getScopeRep(); Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword, Template); } @@ -367,9 +367,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, // The code is missing a 'template' keyword prior to the dependent template // name. - NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep(); SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName( - {Qualifier, &II, /*HasTemplateKeyword=*/false})); + {SS->getScopeRep(), &II, /*HasTemplateKeyword=*/false})); Diag(IILoc, diag::err_template_kw_missing) << SuggestedTemplate.get() << FixItHint::CreateInsertion(IILoc, "template "); @@ -401,7 +400,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, IsDependent = !LookupCtx && ObjectType->isDependentType(); assert((IsDependent || !ObjectType->isIncompleteType() || !ObjectType->getAs<TagType>() || - ObjectType->castAs<TagType>()->isBeingDefined()) && + ObjectType->castAs<TagType>() + ->getOriginalDecl() + ->isEntityBeingDefined()) && "Caller should have completed object type"); // Template names cannot appear inside an Objective-C class or object type @@ -801,9 +802,9 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) return true; - QualType InstantiationTy; + CanQualType InstantiationTy; if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation)) - InstantiationTy = Context.getTypeDeclType(TD); + InstantiationTy = Context.getCanonicalTagType(TD); if (PatternDef) { Diag(PointOfInstantiation, diag::err_template_instantiate_within_definition) @@ -911,7 +912,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, TypeSourceInfo *DI; QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); if (!DI) - DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation()); + DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getNameLoc()); return TemplateArgumentLoc(TemplateArgument(T), DI); } @@ -928,9 +929,9 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, else TArg = Template; return TemplateArgumentLoc( - SemaRef.Context, TArg, + SemaRef.Context, TArg, Arg.getTemplateKwLoc(), Arg.getScopeSpec().getWithLocInContext(SemaRef.Context), - Arg.getLocation(), Arg.getEllipsisLoc()); + Arg.getNameLoc(), Arg.getEllipsisLoc()); } } @@ -971,15 +972,12 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { TL = PET.getPatternLoc(); } - CXXScopeSpec SS; - if (auto ET = TL.getAs<ElaboratedTypeLoc>()) { - SS.Adopt(ET.getQualifierLoc()); - TL = ET.getNamedTypeLoc(); - } - if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) { TemplateName Name = DTST.getTypePtr()->getTemplateName(); - ParsedTemplateArgument Result(SS, TemplateTy::make(Name), + CXXScopeSpec SS; + SS.Adopt(DTST.getQualifierLoc()); + ParsedTemplateArgument Result(/*TemplateKwLoc=*/SourceLocation(), SS, + TemplateTy::make(Name), DTST.getTemplateNameLoc()); if (EllipsisLoc.isValid()) Result = Result.getTemplatePackExpansion(EllipsisLoc); @@ -2145,11 +2143,11 @@ DeclResult Sema::CheckClassTemplate( bool ShouldAddRedecl = !(TUK == TagUseKind::Friend && CurContext->isDependentContext()); - CXXRecordDecl *NewClass = - CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, - PrevClassTemplate && ShouldAddRedecl ? - PrevClassTemplate->getTemplatedDecl() : nullptr, - /*DelayTypeCreation=*/true); + CXXRecordDecl *NewClass = CXXRecordDecl::Create( + Context, Kind, SemanticContext, KWLoc, NameLoc, Name, + PrevClassTemplate && ShouldAddRedecl + ? PrevClassTemplate->getTemplatedDecl() + : nullptr); SetNestedNameSpecifier(*this, NewClass, SS); if (NumOuterTemplateParamLists > 0) NewClass->setTemplateParameterListsInfo( @@ -2178,12 +2176,6 @@ DeclResult Sema::CheckClassTemplate( if (ModulePrivateLoc.isValid()) NewTemplate->setModulePrivate(); - // Build the type for the class template declaration now. - QualType T = NewTemplate->getInjectedClassNameSpecialization(); - T = Context.getInjectedClassNameType(NewClass, T); - assert(T->isDependentType() && "Class template type is not dependent?"); - (void)T; - // If we are providing an explicit specialization of a member that is a // class template, make a note of that. if (PrevClassTemplate && @@ -2674,11 +2666,11 @@ struct DependencyChecker : DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseStmt(S); } - bool TraverseTypeLoc(TypeLoc TL) override { + bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) override { if (IgnoreNonTypeDependent && !TL.isNull() && !TL.getType()->isDependentType()) return true; - return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL, TraverseQualifier); } bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override { @@ -2727,8 +2719,12 @@ struct DependencyChecker : DynamicRecursiveASTVisitor { return TraverseTemplateArgument(T->getArgumentPack()); } - bool TraverseInjectedClassNameType(InjectedClassNameType *T) override { - return TraverseType(T->getInjectedSpecializationType()); + bool TraverseInjectedClassNameType(InjectedClassNameType *T, + bool TraverseQualifier) override { + // An InjectedClassNameType will never have a dependent template name, + // so no need to traverse it. + return TraverseTemplateArguments( + T->getTemplateArgs(T->getOriginalDecl()->getASTContext())); } }; } // end anonymous namespace @@ -2751,14 +2747,14 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, QualType T, const CXXScopeSpec &SS) { NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data()); - while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) { - if (const Type *CurType = NNS->getAsType()) { - if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0))) - return NNSLoc.getTypeLoc().getSourceRange(); - } else + for (;;) { + NestedNameSpecifier NNS = NNSLoc.getNestedNameSpecifier(); + if (NNS.getKind() != NestedNameSpecifier::Kind::Type) break; - - NNSLoc = NNSLoc.getPrefix(); + if (Context.hasSameUnqualifiedType(T, QualType(NNS.getAsType(), 0))) + return NNSLoc.castAsTypeLoc().getSourceRange(); + // FIXME: This will always be empty. + NNSLoc = NNSLoc.getAsNamespaceAndPrefix().Prefix; } return SourceRange(); @@ -2777,12 +2773,13 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // by the nested-name-specifier and walking out until we run out of types. SmallVector<QualType, 4> NestedTypes; QualType T; - if (SS.getScopeRep()) { - if (CXXRecordDecl *Record - = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true))) - T = Context.getTypeDeclType(Record); + if (NestedNameSpecifier Qualifier = SS.getScopeRep(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Type) { + if (CXXRecordDecl *Record = + dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true))) + T = Context.getCanonicalTagType(Record); else - T = QualType(SS.getScopeRep()->getAsType(), 0); + T = QualType(Qualifier.getAsType(), 0); } // If we found an explicit specialization that prevents us from needing @@ -2830,9 +2827,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Look one step prior in a dependent template specialization type. if (const DependentTemplateSpecializationType *DependentTST = T->getAs<DependentTemplateSpecializationType>()) { - if (NestedNameSpecifier *NNS = - DependentTST->getDependentTemplateName().getQualifier()) - T = QualType(NNS->getAsType(), 0); + if (NestedNameSpecifier NNS = + DependentTST->getDependentTemplateName().getQualifier(); + NNS.getKind() == NestedNameSpecifier::Kind::Type) + T = QualType(NNS.getAsType(), 0); else T = QualType(); continue; @@ -2840,8 +2838,9 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Look one step prior in a dependent name type. if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){ - if (NestedNameSpecifier *NNS = DependentName->getQualifier()) - T = QualType(NNS->getAsType(), 0); + if (NestedNameSpecifier NNS = DependentName->getQualifier(); + NNS.getKind() == NestedNameSpecifier::Kind::Type) + T = QualType(NNS.getAsType(), 0); else T = QualType(); continue; @@ -2851,7 +2850,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( if (const EnumType *EnumT = T->getAs<EnumType>()) { // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization // check here. - EnumDecl *Enum = EnumT->getDecl(); + EnumDecl *Enum = EnumT->getOriginalDecl(); // Get to the parent type. if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent())) @@ -3151,7 +3150,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } -static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, +static QualType builtinCommonTypeImpl(Sema &S, ElaboratedTypeKeyword Keyword, + TemplateName BaseTemplate, SourceLocation TemplateLoc, ArrayRef<TemplateArgument> Ts) { auto lookUpCommonType = [&](TemplateArgument T1, @@ -3159,7 +3159,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, // Don't bother looking for other specializations if both types are // builtins - users aren't allowed to specialize for them if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType()) - return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2}); + return builtinCommonTypeImpl(S, Keyword, BaseTemplate, TemplateLoc, + {T1, T2}); TemplateArgumentListInfo Args; Args.addArgument(TemplateArgumentLoc( @@ -3173,7 +3174,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); QualType BaseTemplateInst = - S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args); + S.CheckTemplateIdType(Keyword, BaseTemplate, TemplateLoc, Args); if (SFINAE.hasErrorOccurred()) return QualType(); @@ -3286,7 +3287,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate, } static bool isInVkNamespace(const RecordType *RT) { - DeclContext *DC = RT->getDecl()->getDeclContext(); + DeclContext *DC = RT->getOriginalDecl()->getDeclContext(); if (!DC) return false; @@ -3303,8 +3304,9 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef, if (auto *RT = OperandArg->getAs<RecordType>()) { bool Literal = false; SourceLocation LiteralLoc; - if (isInVkNamespace(RT) && RT->getDecl()->getName() == "Literal") { - auto SpecDecl = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); + if (isInVkNamespace(RT) && RT->getOriginalDecl()->getName() == "Literal") { + auto SpecDecl = + dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl()); assert(SpecDecl); const TemplateArgumentList &LiteralArgs = SpecDecl->getTemplateArgs(); @@ -3315,8 +3317,9 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef, } if (RT && isInVkNamespace(RT) && - RT->getDecl()->getName() == "integral_constant") { - auto SpecDecl = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); + RT->getOriginalDecl()->getName() == "integral_constant") { + auto SpecDecl = + dyn_cast<ClassTemplateSpecializationDecl>(RT->getOriginalDecl()); assert(SpecDecl); const TemplateArgumentList &ConstantArgs = SpecDecl->getTemplateArgs(); @@ -3338,11 +3341,10 @@ static SpirvOperand checkHLSLSpirvTypeOperand(Sema &SemaRef, return SpirvOperand::createType(OperandArg); } -static QualType -checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, - ArrayRef<TemplateArgument> Converted, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs) { +static QualType checkBuiltinTemplateIdType( + Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD, + ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs) { ASTContext &Context = SemaRef.getASTContext(); switch (BTD->getBuiltinTemplateKind()) { @@ -3389,7 +3391,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, // The first template argument will be reused as the template decl that // our synthetic template arguments will be applied to. - return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(), + return SemaRef.CheckTemplateIdType(Keyword, Converted[0].getAsTemplate(), TemplateLoc, SyntheticTemplateArgs); } @@ -3426,14 +3428,16 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, TemplateName BaseTemplate = Converted[0].getAsTemplate(); ArrayRef<TemplateArgument> Ts = Converted[3].getPackAsArray(); - if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts); + if (auto CT = builtinCommonTypeImpl(SemaRef, Keyword, BaseTemplate, + TemplateLoc, Ts); !CT.isNull()) { TemplateArgumentListInfo TAs; TAs.addArgument(TemplateArgumentLoc( TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo( CT, TemplateArgs[1].getLocation()))); TemplateName HasTypeMember = Converted[1].getAsTemplate(); - return SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs); + return SemaRef.CheckTemplateIdType(Keyword, HasTypeMember, TemplateLoc, + TAs); } QualType HasNoTypeMember = Converted[2].getAsType(); return HasNoTypeMember; @@ -3545,7 +3549,7 @@ public: if (DR && DR->getQualifier()) { // If this is a qualified name, expand the template arguments in nested // qualifiers. - DR->getQualifier()->print(OS, Policy, true); + DR->getQualifier().print(OS, Policy, true); // Then print the decl itself. const ValueDecl *VD = DR->getDecl(); OS << VD->getName(); @@ -3610,7 +3614,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) { return { FailedCond, Description }; } -QualType Sema::CheckTemplateIdType(TemplateName Name, +QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword, + TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { // FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias @@ -3661,6 +3666,18 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, } else if (TypeAliasTemplateDecl *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template)) { + // C++0x [dcl.type.elab]p2: + // If the identifier resolves to a typedef-name or the simple-template-id + // resolves to an alias template specialization, the + // elaborated-type-specifier is ill-formed. + if (Keyword != ElaboratedTypeKeyword::None && + Keyword != ElaboratedTypeKeyword::Typename) { + SemaRef.Diag(TemplateLoc, diag::err_tag_reference_non_tag) + << AliasTemplate << NonTagKind::TypeAliasTemplate + << KeywordHelpers::getTagTypeKindForKeyword(Keyword); + SemaRef.Diag(AliasTemplate->getLocation(), diag::note_declared_at); + } + // Find the canonical type for this type alias template specialization. TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); if (Pattern->isInvalidDecl()) @@ -3728,8 +3745,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, return QualType(); } } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { - CanonType = checkBuiltinTemplateIdType(*this, BTD, CTAI.SugaredConverted, - TemplateLoc, TemplateArgs); + CanonType = checkBuiltinTemplateIdType( + *this, Keyword, BTD, CTAI.SugaredConverted, TemplateLoc, TemplateArgs); } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( TemplateArgs, CTAI.CanonicalConverted)) { @@ -3768,16 +3785,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Fetch the injected class name type and check whether its // injected type is equal to the type we just built. - QualType ICNT = Context.getTypeDeclType(Record); - QualType Injected = cast<InjectedClassNameType>(ICNT) - ->getInjectedSpecializationType(); + CanQualType ICNT = Context.getCanonicalTagType(Record); + CanQualType Injected = + Record->getCanonicalTemplateSpecializationType(Context); - if (CanonType != Injected->getCanonicalTypeInternal()) + if (CanonType != Injected) continue; // If so, the canonical type of this TST is the injected // class name type of the record we just found. - assert(ICNT.isCanonical()); CanonType = ICNT; break; } @@ -3819,7 +3835,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Diagnose uses of this specialization. (void)DiagnoseUseOfDecl(Decl, TemplateLoc); - CanonType = Context.getTypeDeclType(Decl); + CanonType = Context.getCanonicalTagType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); } else { @@ -3830,7 +3846,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // specialization, which refers back to the class template // specialization we created or found. return Context.getTemplateSpecializationType( - Name, TemplateArgs.arguments(), CTAI.CanonicalConverted, CanonType); + Keyword, Name, TemplateArgs.arguments(), CTAI.CanonicalConverted, + CanonType); } void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName, @@ -3878,7 +3895,7 @@ bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name, diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << ATN->getDeclName()); Name = Context.getQualifiedTemplateName( - /*NNS=*/nullptr, /*TemplateKeyword=*/false, + /*Qualifier=*/std::nullopt, /*TemplateKeyword=*/false, TemplateName(Corrected.getCorrectionDeclAs<TemplateDecl>())); return false; } @@ -3889,11 +3906,12 @@ bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name, } TypeResult Sema::ActOnTemplateIdType( - Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - TemplateTy TemplateD, const IdentifierInfo *TemplateII, - SourceLocation TemplateIILoc, SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc, - bool IsCtorOrDtorName, bool IsClassName, + Scope *S, ElaboratedTypeKeyword ElaboratedKeyword, + SourceLocation ElaboratedKeywordLoc, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, TemplateTy TemplateD, + const IdentifierInfo *TemplateII, SourceLocation TemplateIILoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, bool IsCtorOrDtorName, bool IsClassName, ImplicitTypenameContext AllowImplicitTypename) { if (SS.isInvalid()) return true; @@ -3909,8 +3927,9 @@ TypeResult Sema::ActOnTemplateIdType( // elaborated-type-specifier (7.1.5.3). if (!LookupCtx && isDependentScopeSpecifier(SS)) { // C++2a relaxes some of those restrictions in [temp.res]p5. - NestedNameSpecifier *NNS = - NestedNameSpecifier::Create(Context, SS.getScopeRep(), TemplateII); + QualType DNT = Context.getDependentNameType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TemplateII); + NestedNameSpecifier NNS(DNT.getTypePtr()); if (AllowImplicitTypename == ImplicitTypenameContext::Yes) { auto DB = DiagCompat(SS.getBeginLoc(), diag_compat::implicit_typename) << NNS; @@ -3954,12 +3973,12 @@ TypeResult Sema::ActOnTemplateIdType( if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { assert(SS.getScopeRep() == DTN->getQualifier()); QualType T = Context.getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, *DTN, TemplateArgs.arguments()); + ElaboratedKeyword, *DTN, TemplateArgs.arguments()); // Build type-source information. TypeLocBuilder TLB; DependentTemplateSpecializationTypeLoc SpecTL = TLB.push<DependentTemplateSpecializationTypeLoc>(T); - SpecTL.setElaboratedKeywordLoc(SourceLocation()); + SpecTL.setElaboratedKeywordLoc(ElaboratedKeywordLoc); SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateIILoc); @@ -3970,30 +3989,17 @@ TypeResult Sema::ActOnTemplateIdType( return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); } - QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); + QualType SpecTy = CheckTemplateIdType(ElaboratedKeyword, Template, + TemplateIILoc, TemplateArgs); if (SpecTy.isNull()) return true; // Build type-source information. TypeLocBuilder TLB; - TemplateSpecializationTypeLoc SpecTL = - TLB.push<TemplateSpecializationTypeLoc>(SpecTy); - SpecTL.setTemplateKeywordLoc(TemplateKWLoc); - SpecTL.setTemplateNameLoc(TemplateIILoc); - SpecTL.setLAngleLoc(LAngleLoc); - SpecTL.setRAngleLoc(RAngleLoc); - for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) - SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - - // Create an elaborated-type-specifier containing the nested-name-specifier. - QualType ElTy = - getElaboratedType(ElaboratedTypeKeyword::None, - !IsCtorOrDtorName ? SS : CXXScopeSpec(), SpecTy); - ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(ElTy); - ElabTL.setElaboratedKeywordLoc(SourceLocation()); - if (!ElabTL.isEmpty()) - ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); - return CreateParsedType(ElTy, TLB.getTypeSourceInfo(Context, ElTy)); + TLB.push<TemplateSpecializationTypeLoc>(SpecTy).set( + ElaboratedKeywordLoc, SS.getWithLocInContext(Context), TemplateKWLoc, + TemplateIILoc, TemplateArgs); + return CreateParsedType(SpecTy, TLB.getTypeSourceInfo(Context, SpecTy)); } TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, @@ -4040,24 +4046,14 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); } - if (TypeAliasTemplateDecl *TAT = - dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) { - // C++0x [dcl.type.elab]p2: - // If the identifier resolves to a typedef-name or the simple-template-id - // resolves to an alias template specialization, the - // elaborated-type-specifier is ill-formed. - Diag(TemplateLoc, diag::err_tag_reference_non_tag) - << TAT << NonTagKind::TypeAliasTemplate << TagKind; - Diag(TAT->getLocation(), diag::note_declared_at); - } - - QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + QualType Result = + CheckTemplateIdType(Keyword, Template, TemplateLoc, TemplateArgs); if (Result.isNull()) return TypeResult(true); // Check the tag kind if (const RecordType *RT = Result->getAs<RecordType>()) { - RecordDecl *D = RT->getDecl(); + RecordDecl *D = RT->getOriginalDecl()->getDefinitionOrSelf(); IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); @@ -4073,21 +4069,9 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, // Provide source-location information for the template specialization. TypeLocBuilder TLB; - TemplateSpecializationTypeLoc SpecTL - = TLB.push<TemplateSpecializationTypeLoc>(Result); - SpecTL.setTemplateKeywordLoc(TemplateKWLoc); - SpecTL.setTemplateNameLoc(TemplateLoc); - SpecTL.setLAngleLoc(LAngleLoc); - SpecTL.setRAngleLoc(RAngleLoc); - for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) - SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - - // Construct an elaborated type containing the nested-name-specifier (if any) - // and tag keyword. - Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); - ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); - ElabTL.setElaboratedKeywordLoc(TagLoc); - ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + TLB.push<TemplateSpecializationTypeLoc>(Result).set( + TagLoc, SS.getWithLocInContext(Context), TemplateKWLoc, TemplateLoc, + TemplateArgs); return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } @@ -4099,7 +4083,6 @@ static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized, static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D); static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, - NamedDecl *Param, unsigned Depth, unsigned Index) { switch (Arg.getKind()) { @@ -4139,8 +4122,9 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, } static bool isSameAsPrimaryTemplate(TemplateParameterList *Params, + TemplateParameterList *SpecParams, ArrayRef<TemplateArgument> Args) { - if (Params->size() != Args.size()) + if (Params->size() != Args.size() || Params->size() != SpecParams->size()) return false; unsigned Depth = Params->getDepth(); @@ -4157,9 +4141,19 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params, Arg = Arg.pack_begin()->getPackExpansionPattern(); } - if (!isTemplateArgumentTemplateParameter(Arg, Params->getParam(I), Depth, - I)) + if (!isTemplateArgumentTemplateParameter(Arg, Depth, I)) return false; + + // For NTTPs further specialization is allowed via deduced types, so + // we need to make sure to only reject here if primary template and + // specialization use the same type for the NTTP. + if (auto *SpecNTTP = + dyn_cast<NonTypeTemplateParmDecl>(SpecParams->getParam(I))) { + auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(I)); + if (!NTTP || NTTP->getType().getCanonicalType() != + SpecNTTP->getType().getCanonicalType()) + return false; + } } return true; @@ -4357,7 +4351,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), - CTAI.CanonicalConverted) && + TemplateParams, CTAI.CanonicalConverted) && (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: @@ -5055,7 +5049,7 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S, return TNK_Non_template; } - NestedNameSpecifier *Qualifier = SS.getScopeRep(); + NestedNameSpecifier Qualifier = SS.getScopeRep(); switch (Name.getKind()) { case UnqualifiedIdKind::IK_Identifier: @@ -5343,8 +5337,9 @@ static bool SubstDefaultTemplateArgument( /// /// \returns the substituted template argument, or NULL if an error occurred. static TemplateName SubstDefaultTemplateArgument( - Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param, + Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateKWLoc, + SourceLocation TemplateLoc, SourceLocation RAngleLoc, + TemplateTemplateParmDecl *Param, ArrayRef<TemplateArgument> SugaredConverted, ArrayRef<TemplateArgument> CanonicalConverted, NestedNameSpecifierLoc &QualifierLoc) { @@ -5361,25 +5356,17 @@ static TemplateName SubstDefaultTemplateArgument( TemplateArgLists.addOuterTemplateArguments(std::nullopt); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); - // Substitute into the nested-name-specifier first, - QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); - if (QualifierLoc) { - QualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists); - if (!QualifierLoc) - return TemplateName(); - } - return SemaRef.SubstTemplateName( - QualifierLoc, - Param->getDefaultArgument().getArgument().getAsTemplate(), - Param->getDefaultArgument().getTemplateNameLoc(), - TemplateArgLists); + const TemplateArgumentLoc &A = Param->getDefaultArgument(); + QualifierLoc = A.getTemplateQualifierLoc(); + return SemaRef.SubstTemplateName(TemplateKWLoc, QualifierLoc, + A.getArgument().getAsTemplate(), + A.getTemplateNameLoc(), TemplateArgLists); } TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( - TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, Decl *Param, + TemplateDecl *Template, SourceLocation TemplateKWLoc, + SourceLocation TemplateNameLoc, SourceLocation RAngleLoc, Decl *Param, ArrayRef<TemplateArgument> SugaredConverted, ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg) { HasDefaultArg = false; @@ -5390,8 +5377,8 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( HasDefaultArg = true; TemplateArgumentLoc Output; - if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, - TypeParm, SugaredConverted, + if (SubstDefaultTemplateArgument(*this, Template, TemplateNameLoc, + RAngleLoc, TypeParm, SugaredConverted, CanonicalConverted, Output)) return TemplateArgumentLoc(); return Output; @@ -5404,8 +5391,8 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( HasDefaultArg = true; TemplateArgumentLoc Output; - if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, - NonTypeParm, SugaredConverted, + if (SubstDefaultTemplateArgument(*this, Template, TemplateNameLoc, + RAngleLoc, NonTypeParm, SugaredConverted, CanonicalConverted, Output)) return TemplateArgumentLoc(); return Output; @@ -5417,17 +5404,16 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( return TemplateArgumentLoc(); HasDefaultArg = true; + const TemplateArgumentLoc &A = TempTempParm->getDefaultArgument(); NestedNameSpecifierLoc QualifierLoc; TemplateName TName = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, TempTempParm, SugaredConverted, - CanonicalConverted, QualifierLoc); + *this, Template, TemplateKWLoc, TemplateNameLoc, RAngleLoc, TempTempParm, + SugaredConverted, CanonicalConverted, QualifierLoc); if (TName.isNull()) return TemplateArgumentLoc(); - return TemplateArgumentLoc( - Context, TemplateArgument(TName), - TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), - TempTempParm->getDefaultArgument().getTemplateNameLoc()); + return TemplateArgumentLoc(Context, TemplateArgument(TName), TemplateKWLoc, + QualifierLoc, A.getTemplateNameLoc()); } /// Convert a template-argument that we parsed as a type into a template, if @@ -5435,33 +5421,24 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( /// template template arguments and as template type arguments. static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { - // Extract and step over any surrounding nested-name-specifier. - NestedNameSpecifierLoc QualLoc; - if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) { - if (ETLoc.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None) - return TemplateArgumentLoc(); + auto TagLoc = TLoc.getAs<TagTypeLoc>(); + if (!TagLoc) + return TemplateArgumentLoc(); - QualLoc = ETLoc.getQualifierLoc(); - TLoc = ETLoc.getNamedTypeLoc(); - } // If this type was written as an injected-class-name, it can be used as a // template template argument. - if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>()) - return TemplateArgumentLoc(Context, InjLoc.getTypePtr()->getTemplateName(), - QualLoc, InjLoc.getNameLoc()); - // If this type was written as an injected-class-name, it may have been // converted to a RecordType during instantiation. If the RecordType is // *not* wrapped in a TemplateSpecializationType and denotes a class // template specialization, it must have come from an injected-class-name. - if (auto RecLoc = TLoc.getAs<RecordTypeLoc>()) - if (auto *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl())) - return TemplateArgumentLoc(Context, - TemplateName(CTSD->getSpecializedTemplate()), - QualLoc, RecLoc.getNameLoc()); - return TemplateArgumentLoc(); + TemplateName Name = TagLoc.getTypePtr()->getTemplateName(Context); + if (Name.isNull()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(Context, Name, + /*TemplateKWLoc=*/SourceLocation(), + TagLoc.getQualifierLoc(), TagLoc.getNameLoc()); } bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, @@ -6007,8 +5984,8 @@ bool Sema::CheckTemplateArgumentList( // (when the template parameter was part of a nested template) into // the default argument. TemplateArgumentLoc Arg = SubstDefaultTemplateArgumentIfAvailable( - Template, TemplateLoc, RAngleLoc, *Param, CTAI.SugaredConverted, - CTAI.CanonicalConverted, HasDefaultArg); + Template, /*TemplateKWLoc=*/SourceLocation(), TemplateLoc, RAngleLoc, + *Param, CTAI.SugaredConverted, CTAI.CanonicalConverted, HasDefaultArg); if (Arg.getArgument().isNull()) { if (!HasDefaultArg) { @@ -6152,7 +6129,7 @@ namespace { #include "clang/AST/TypeNodes.inc" bool VisitTagDecl(const TagDecl *Tag); - bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + bool VisitNestedNameSpecifier(NestedNameSpecifier NNS); }; } // end anonymous namespace @@ -6297,11 +6274,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType( } bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) { - return VisitTagDecl(T->getDecl()); + return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf()); } bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) { - return VisitTagDecl(T->getDecl()); + return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf()); } bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType( @@ -6321,7 +6298,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType( const InjectedClassNameType* T) { - return VisitTagDecl(T->getDecl()); + return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf()); } bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( @@ -6331,10 +6308,7 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType( const DependentTemplateSpecializationType* T) { - if (auto *Q = T->getDependentTemplateName().getQualifier()) - return VisitNestedNameSpecifier(Q); - - return false; + return VisitNestedNameSpecifier(T->getDependentTemplateName().getQualifier()); } bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType( @@ -6380,11 +6354,10 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentBitIntType( bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { if (Tag->getDeclContext()->isFunctionOrMethod()) { - S.Diag(SR.getBegin(), - S.getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_template_arg_local_type : - diag::ext_template_arg_local_type) - << S.Context.getTypeDeclType(Tag) << SR; + S.Diag(SR.getBegin(), S.getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_template_arg_local_type + : diag::ext_template_arg_local_type) + << S.Context.getCanonicalTagType(Tag) << SR; return true; } @@ -6401,20 +6374,15 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { } bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( - NestedNameSpecifier *NNS) { - assert(NNS); - if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix())) - return true; - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + NestedNameSpecifier NNS) { + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Namespace: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: return false; - - case NestedNameSpecifier::TypeSpec: - return Visit(QualType(NNS->getAsType(), 0)); + case NestedNameSpecifier::Kind::Type: + return Visit(QualType(NNS.getAsType(), 0)); } llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } @@ -7382,7 +7350,8 @@ ExprResult Sema::CheckTemplateArgument(NamedDecl *Param, QualType ParamType, // that case, this may extend the argument from 1 bit to 8 bits. QualType IntegerType = ParamType; if (const EnumType *Enum = IntegerType->getAs<EnumType>()) - IntegerType = Enum->getDecl()->getIntegerType(); + IntegerType = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); Value = Value.extOrTrunc(IntegerType->isBitIntType() ? Context.getIntWidth(IntegerType) : Context.getTypeSize(IntegerType)); @@ -7480,7 +7449,8 @@ ExprResult Sema::CheckTemplateArgument(NamedDecl *Param, QualType ParamType, QualType IntegerType = ParamType; if (const EnumType *Enum = IntegerType->getAs<EnumType>()) { - IntegerType = Enum->getDecl()->getIntegerType(); + IntegerType = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); } if (ParamType->isBooleanType()) { @@ -7903,10 +7873,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument( assert(VD->getDeclContext()->isRecord() && (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))); - QualType ClassType - = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext())); - NestedNameSpecifier *Qualifier = - NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr()); + CanQualType ClassType = + Context.getCanonicalTagType(cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier Qualifier(ClassType.getTypePtr()); SS.MakeTrivial(Context, Qualifier, Loc); } @@ -7998,7 +7967,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue( // type of literal for it. QualType T = OrigT; if (const EnumType *ET = OrigT->getAs<EnumType>()) - T = ET->getDecl()->getIntegerType(); + T = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); Expr *E; if (T->isAnyCharacterType()) { @@ -8881,7 +8850,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization( isPartialSpecialization)) return true; - QualType CanonType; if (!isPartialSpecialization) { // Create a new class template specialization declaration node for // this explicit specialization or friend declaration. @@ -8897,18 +8865,14 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (!PrevDecl) ClassTemplate->AddSpecialization(Specialization, InsertPos); - - if (!CurContext->isDependentContext()) - CanonType = Context.getTypeDeclType(Specialization); - } - - TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo( - Name, TemplateNameLoc, TemplateArgs, CTAI.CanonicalConverted, CanonType); - - if (isPartialSpecialization) { + } else { + CanQualType CanonType = CanQualType::CreateUnsafe( + Context.getCanonicalTemplateSpecializationType( + TemplateName(ClassTemplate->getCanonicalDecl()), + CTAI.CanonicalConverted)); if (Context.hasSameType( - WrittenTy->getType(), - ClassTemplate->getInjectedClassNameSpecialization()) && + CanonType, + ClassTemplate->getCanonicalInjectedSpecializationType(Context)) && (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: @@ -8930,13 +8894,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } // Create a new class template partial specialization declaration node. - ClassTemplatePartialSpecializationDecl *PrevPartial - = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); + ClassTemplatePartialSpecializationDecl *PrevPartial = + cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create( Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, - ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(), - PrevPartial); + ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial); Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { @@ -8975,7 +8938,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (!Okay) { SourceRange Range(TemplateNameLoc, RAngleLoc); Diag(TemplateNameLoc, diag::err_specialization_after_instantiation) - << Context.getTypeDeclType(Specialization) << Range; + << Context.getCanonicalTagType(Specialization) << Range; Diag(PrevDecl->getPointOfInstantiation(), diag::note_instantiation_required_here) @@ -9038,6 +9001,13 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->startDefinition(); if (TUK == TagUseKind::Friend) { + CanQualType CanonType = Context.getCanonicalTagType(Specialization); + TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo( + ElaboratedTypeKeyword::None, /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), + /*TemplateKeywordLoc=*/SourceLocation(), Name, TemplateNameLoc, + TemplateArgs, CTAI.CanonicalConverted, CanonType); + // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved @@ -10078,9 +10048,6 @@ static bool CheckExplicitInstantiation(Sema &S, NamedDecl *D, /// Determine whether the given scope specifier has a template-id in it. static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { - if (!SS.isSet()) - return false; - // C++11 [temp.explicit]p3: // If the explicit instantiation is for a member function, a member class // or a static data member of a class template specialization, the name of @@ -10088,12 +10055,14 @@ static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { // name shall be a simple-template-id. // // C++98 has the same restriction, just worded differently. - for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS; - NNS = NNS->getPrefix()) - if (const Type *T = NNS->getAsType()) - if (isa<TemplateSpecializationType>(T)) - return true; - + for (NestedNameSpecifier NNS = SS.getScopeRep(); + NNS.getKind() == NestedNameSpecifier::Kind::Type; + /**/) { + const Type *T = NNS.getAsType(); + if (isa<TemplateSpecializationType>(T)) + return true; + NNS = T->getPrefix(); + } return false; } @@ -10448,7 +10417,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); if (!Pattern) { Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type) - << Context.getTypeDeclType(Record); + << Context.getCanonicalTagType(Record); Diag(Record->getLocation(), diag::note_nontemplate_decl_here); return true; } @@ -10995,7 +10964,7 @@ TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // This has to hold, because SS is expected to be defined. assert(Name && "Expected a name in a dependent tag"); - NestedNameSpecifier *NNS = SS.getScopeRep(); + NestedNameSpecifier NNS = SS.getScopeRep(); if (!NNS) return true; @@ -11107,7 +11076,10 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } - QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); + QualType T = CheckTemplateIdType(TypenameLoc.isValid() + ? ElaboratedTypeKeyword::Typename + : ElaboratedTypeKeyword::None, + Template, TemplateIILoc, TemplateArgs); if (T.isNull()) return true; @@ -11115,18 +11087,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, TypeLocBuilder Builder; TemplateSpecializationTypeLoc SpecTL = Builder.push<TemplateSpecializationTypeLoc>(T); - SpecTL.setTemplateKeywordLoc(TemplateKWLoc); - SpecTL.setTemplateNameLoc(TemplateIILoc); - SpecTL.setLAngleLoc(LAngleLoc); - SpecTL.setRAngleLoc(RAngleLoc); - for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); - - T = Context.getElaboratedType(Keyword, SS.getScopeRep(), T); - ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); - TL.setElaboratedKeywordLoc(TypenameLoc); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); - + SpecTL.set(TypenameLoc, SS.getWithLocInContext(Context), TemplateKWLoc, + TemplateIILoc, TemplateArgs); TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); return CreateParsedType(T, TSI); } @@ -11140,11 +11102,12 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, return false; // ... within an explicitly-written template specialization... - if (!NNS || !NNS.getNestedNameSpecifier()->getAsType()) + if (NNS.getNestedNameSpecifier().getKind() != NestedNameSpecifier::Kind::Type) return false; - TypeLoc EnableIfTy = NNS.getTypeLoc(); - TemplateSpecializationTypeLoc EnableIfTSTLoc = - EnableIfTy.getAs<TemplateSpecializationTypeLoc>(); + + // FIXME: Look through sugar. + auto EnableIfTSTLoc = + NNS.castAsTypeLoc().getAs<TemplateSpecializationTypeLoc>(); if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0) return false; const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr(); @@ -11192,19 +11155,33 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, if (T.isNull()) return QualType(); - *TSI = Context.CreateTypeSourceInfo(T); + TypeLocBuilder TLB; if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = - (*TSI)->getTypeLoc().castAs<DependentNameTypeLoc>(); + auto TL = TLB.push<DependentNameTypeLoc>(T); TL.setElaboratedKeywordLoc(KeywordLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IILoc); - } else { - ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs<ElaboratedTypeLoc>(); + } else if (isa<DeducedTemplateSpecializationType>(T)) { + auto TL = TLB.push<DeducedTemplateSpecializationTypeLoc>(T); + TL.setElaboratedKeywordLoc(KeywordLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(IILoc); + } else if (isa<TemplateTypeParmType>(T)) { + // FIXME: There might be a 'typename' keyword here, but we just drop it + // as it can't be represented. + assert(!QualifierLoc); + TLB.pushTypeSpec(T).setNameLoc(IILoc); + } else if (isa<TagType>(T)) { + auto TL = TLB.push<TagTypeLoc>(T); TL.setElaboratedKeywordLoc(KeywordLoc); TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IILoc); + TL.setNameLoc(IILoc); + } else if (isa<TypedefType>(T)) { + TLB.push<TypedefTypeLoc>(T).set(KeywordLoc, QualifierLoc, IILoc); + } else { + TLB.push<UnresolvedUsingTypeLoc>(T).set(KeywordLoc, QualifierLoc, IILoc); } + *TSI = TLB.getTypeSourceInfo(Context, T); return T; } @@ -11227,7 +11204,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, if (!Ctx) { // If the nested-name-specifier is dependent and couldn't be // resolved to a type, build a typename type. - assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + assert(QualifierLoc.getNestedNameSpecifier().isDependent()); return Context.getDependentNameType(Keyword, QualifierLoc.getNestedNameSpecifier(), &II); @@ -11309,6 +11286,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, &II); case LookupResultKind::Found: + // FXIME: Missing support for UsingShadowDecl on this path? if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { // C++ [class.qual]p2: // In a lookup in which function names are not ignored and the @@ -11324,15 +11302,20 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // // FIXME: That's not strictly true: mem-initializer-id lookup does not // ignore functions, but that appears to be an oversight. - QualType T = getTypeDeclType(Ctx, - Keyword == ElaboratedTypeKeyword::Typename - ? DiagCtorKind::Typename - : DiagCtorKind::None, - Type, IILoc); - // We found a type. Build an ElaboratedType, since the - // typename-specifier was just sugar. - return Context.getElaboratedType( - Keyword, QualifierLoc.getNestedNameSpecifier(), T); + checkTypeDeclType(Ctx, + Keyword == ElaboratedTypeKeyword::Typename + ? DiagCtorKind::Typename + : DiagCtorKind::None, + Type, IILoc); + // FIXME: This appears to be the only case where a template type parameter + // can have an elaborated keyword. We should preserve it somehow. + if (isa<TemplateTypeParmDecl>(Type)) { + assert(Keyword == ElaboratedTypeKeyword::Typename); + assert(!QualifierLoc); + Keyword = ElaboratedTypeKeyword::None; + } + return Context.getTypeDeclType( + Keyword, QualifierLoc.getNestedNameSpecifier(), Type); } // C++ [dcl.type.simple]p2: @@ -11342,22 +11325,22 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, if (getLangOpts().CPlusPlus17) { if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) { if (!DeducedTSTContext) { - QualType T(QualifierLoc - ? QualifierLoc.getNestedNameSpecifier()->getAsType() - : nullptr, 0); - if (!T.isNull()) + NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier(); + if (Qualifier.getKind() == NestedNameSpecifier::Kind::Type) Diag(IILoc, diag::err_dependent_deduced_tst) - << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T; + << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) + << QualType(Qualifier.getAsType(), 0); else Diag(IILoc, diag::err_deduced_tst) << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)); NoteTemplateLocation(*TD); return QualType(); } - return Context.getElaboratedType( - Keyword, QualifierLoc.getNestedNameSpecifier(), - Context.getDeducedTemplateSpecializationType(TemplateName(TD), - QualType(), false)); + TemplateName Name = Context.getQualifiedTemplateName( + QualifierLoc.getNestedNameSpecifier(), /*TemplateKeyword=*/false, + TemplateName(TD)); + return Context.getDeducedTemplateSpecializationType( + Keyword, Name, /*DeducedType=*/QualType(), /*IsDependent=*/false); } } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 0d70321..3aa808e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -691,38 +691,29 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, TemplateDeductionInfo &Info, bool PartialOrdering, SmallVectorImpl<DeducedTemplateArgument> &Deduced, bool *HasDeducedAnyParam) { - QualType UP = P; - if (const auto *IP = P->getAs<InjectedClassNameType>()) - UP = IP->getInjectedSpecializationType(); - - assert(isa<TemplateSpecializationType>(UP.getCanonicalType())); - const TemplateSpecializationType *TP = ::getLastTemplateSpecType(UP); - TemplateName TNP = TP->getTemplateName(); + TemplateName TNP; + ArrayRef<TemplateArgument> PResolved; + if (isa<TemplateSpecializationType>(P.getCanonicalType())) { + const TemplateSpecializationType *TP = ::getLastTemplateSpecType(P); + TNP = TP->getTemplateName(); + // FIXME: To preserve sugar, the TST needs to carry sugared resolved + // arguments. + PResolved = TP->getCanonicalTypeInternal() + ->castAs<TemplateSpecializationType>() + ->template_arguments(); + } else { + const auto *TT = P->castAs<InjectedClassNameType>(); + TNP = TT->getTemplateName(S.Context); + PResolved = TT->getTemplateArgs(S.Context); + } // If the parameter is an alias template, there is nothing to deduce. if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias()) return TemplateDeductionResult::Success; - // FIXME: To preserve sugar, the TST needs to carry sugared resolved - // arguments. - ArrayRef<TemplateArgument> PResolved = - TP->getCanonicalTypeInternal() - ->castAs<TemplateSpecializationType>() - ->template_arguments(); - - QualType UA = A; - std::optional<NestedNameSpecifier *> NNS; - // Treat an injected-class-name as its underlying template-id. - if (const auto *Elaborated = A->getAs<ElaboratedType>()) { - NNS = Elaborated->getQualifier(); - } else if (const auto *Injected = A->getAs<InjectedClassNameType>()) { - UA = Injected->getInjectedSpecializationType(); - NNS = nullptr; - } - // Check whether the template argument is a dependent template-id. - if (isa<TemplateSpecializationType>(UA.getCanonicalType())) { - const TemplateSpecializationType *SA = ::getLastTemplateSpecType(UA); + if (isa<TemplateSpecializationType>(A.getCanonicalType())) { + const TemplateSpecializationType *SA = ::getLastTemplateSpecType(A); TemplateName TNA = SA->getTemplateName(); // If the argument is an alias template, there is nothing to deduce. @@ -756,34 +747,36 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, // If the argument type is a class template specialization, we // perform template argument deduction using its template // arguments. - const auto *RA = UA->getAs<RecordType>(); - const auto *SA = - RA ? dyn_cast<ClassTemplateSpecializationDecl>(RA->getDecl()) : nullptr; - if (!SA) { + const auto *TA = A->getAs<TagType>(); + TemplateName TNA; + if (TA) { + // FIXME: Can't use the template arguments from this TST, as they are not + // resolved. + if (const auto *TST = A->getAsNonAliasTemplateSpecializationType()) + TNA = TST->getTemplateName(); + else + TNA = TA->getTemplateName(S.Context); + } + if (TNA.isNull()) { Info.FirstArg = TemplateArgument(P); Info.SecondArg = TemplateArgument(A); return TemplateDeductionResult::NonDeducedMismatch; } - TemplateName TNA = TemplateName(SA->getSpecializedTemplate()); - if (NNS) - TNA = S.Context.getQualifiedTemplateName( - *NNS, false, TemplateName(SA->getSpecializedTemplate())); - + ArrayRef<TemplateArgument> AResolved = TA->getTemplateArgs(S.Context); // Perform template argument deduction for the template name. - if (auto Result = DeduceTemplateArguments( - S, TemplateParams, TNP, TNA, Info, - /*DefaultArguments=*/SA->getTemplateArgs().asArray(), PartialOrdering, - Deduced, HasDeducedAnyParam); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, + /*DefaultArguments=*/AResolved, + PartialOrdering, Deduced, HasDeducedAnyParam); Result != TemplateDeductionResult::Success) return Result; // Perform template argument deduction for the template arguments. - return DeduceTemplateArguments(S, TemplateParams, PResolved, - SA->getTemplateArgs().asArray(), Info, Deduced, - /*NumberOfArgumentsMustMatch=*/true, - PartialOrdering, PackFold::ParameterToArgument, - HasDeducedAnyParam); + return DeduceTemplateArguments( + S, TemplateParams, PResolved, AResolved, Info, Deduced, + /*NumberOfArgumentsMustMatch=*/true, PartialOrdering, + PackFold::ParameterToArgument, HasDeducedAnyParam); } static bool IsPossiblyOpaquelyQualifiedTypeInternal(const Type *T) { @@ -2188,26 +2181,19 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( Result != TemplateDeductionResult::Success) return Result; - QualType TP; - if (MPP->isSugared()) { - TP = S.Context.getTypeDeclType(MPP->getMostRecentCXXRecordDecl()); - } else { - NestedNameSpecifier *QP = MPP->getQualifier(); - if (QP->getKind() == NestedNameSpecifier::Identifier) - // Skip translation if it's a non-deduced context anyway. - return TemplateDeductionResult::Success; - TP = QualType(QP->translateToType(S.Context), 0); - } + QualType TP = + MPP->isSugared() + ? S.Context.getCanonicalTagType(MPP->getMostRecentCXXRecordDecl()) + : QualType(MPP->getQualifier().getAsType(), 0); assert(!TP.isNull() && "member pointer with non-type class"); - QualType TA; - if (MPA->isSugared()) { - TA = S.Context.getTypeDeclType(MPA->getMostRecentCXXRecordDecl()); - } else { - NestedNameSpecifier *QA = MPA->getQualifier(); - TA = QualType(QA->translateToType(S.Context), 0).getUnqualifiedType(); - } + QualType TA = + MPA->isSugared() + ? S.Context.getCanonicalTagType(MPA->getMostRecentCXXRecordDecl()) + : QualType(MPA->getQualifier().getAsType(), 0) + .getUnqualifiedType(); assert(!TA.isNull() && "member pointer with non-type class"); + return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, TP, TA, Info, Deduced, SubTDF, degradeCallPartialOrderingKind(POK), @@ -2930,13 +2916,11 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Builder.MakeTrivial(Context, QTN->getQualifier(), Loc); - - if (Arg.getKind() == TemplateArgument::Template) - return TemplateArgumentLoc(Context, Arg, - Builder.getWithLocInContext(Context), Loc); - return TemplateArgumentLoc( - Context, Arg, Builder.getWithLocInContext(Context), Loc, Loc); + Context, Arg, Loc, Builder.getWithLocInContext(Context), Loc, + /*EllipsisLoc=*/Arg.getKind() == TemplateArgument::TemplateExpansion + ? Loc + : SourceLocation()); } case TemplateArgument::Expression: @@ -3154,8 +3138,9 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( S.getLangOpts().CPlusPlus17); DefArg = S.SubstDefaultTemplateArgumentIfAvailable( - TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, - CTAI.SugaredConverted, CTAI.CanonicalConverted, HasDefaultArg); + TD, /*TemplateKWLoc=*/SourceLocation(), TD->getLocation(), + TD->getSourceRange().getEnd(), Param, CTAI.SugaredConverted, + CTAI.CanonicalConverted, HasDefaultArg); } // If there was no default argument, deduction is incomplete. @@ -3512,7 +3497,7 @@ Sema::DeduceTemplateArgumentsFromType(TemplateDecl *TD, QualType FromType, QualType PType; if (const auto *CTD = dyn_cast<ClassTemplateDecl>(TD)) { // Use the InjectedClassNameType. - PType = Context.getTypeDeclType(CTD->getTemplatedDecl()); + PType = Context.getCanonicalTagType(CTD->getTemplatedDecl()); } else if (const auto *AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(TD)) { PType = AliasTemplate->getTemplatedDecl()->getUnderlyingType(); } else { @@ -4182,7 +4167,7 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R, return {}; return S.Context.getMemberPointerType( - Fn->getType(), /*Qualifier=*/nullptr, Method->getParent()); + Fn->getType(), /*Qualifier=*/std::nullopt, Method->getParent()); } if (!R.IsAddressOfOperand) return Fn->getType(); @@ -5138,10 +5123,12 @@ namespace { return TransformDesugared(TLB, TL); QualType Result = SemaRef.Context.getDeducedTemplateSpecializationType( - TL.getTypePtr()->getTemplateName(), + TL.getTypePtr()->getKeyword(), TL.getTypePtr()->getTemplateName(), Replacement, Replacement.isNull()); auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setQualifierLoc(TL.getQualifierLoc()); return Result; } @@ -5607,7 +5594,8 @@ static TemplateDeductionResult CheckDeductionConsistency( bool IsDeductionGuide = isa<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); if (IsDeductionGuide) { if (auto *Injected = P->getAs<InjectedClassNameType>()) - P = Injected->getInjectedSpecializationType(); + P = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( + S.Context); } QualType InstP = S.SubstType(P.getCanonicalType(), MLTAL, FTD->getLocation(), FTD->getDeclName(), &IsIncompleteSubstitution); @@ -5627,9 +5615,11 @@ static TemplateDeductionResult CheckDeductionConsistency( auto T2 = S.Context.getUnqualifiedArrayType(A.getNonReferenceType()); if (IsDeductionGuide) { if (auto *Injected = T1->getAs<InjectedClassNameType>()) - T1 = Injected->getInjectedSpecializationType(); + T1 = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( + S.Context); if (auto *Injected = T2->getAs<InjectedClassNameType>()) - T2 = Injected->getInjectedSpecializationType(); + T2 = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( + S.Context); } if (!S.Context.hasSameType(T1, T2)) return TemplateDeductionResult::NonDeducedMismatch; @@ -6471,8 +6461,8 @@ Sema::getMoreSpecializedPartialSpecialization( ClassTemplatePartialSpecializationDecl *PS1, ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc) { - QualType PT1 = PS1->getInjectedSpecializationType().getCanonicalType(); - QualType PT2 = PS2->getInjectedSpecializationType().getCanonicalType(); + QualType PT1 = PS1->getCanonicalInjectedSpecializationType(Context); + QualType PT2 = PS2->getCanonicalInjectedSpecializationType(Context); TemplateDeductionInfo Info(Loc); return getMoreSpecialized(*this, PT1, PT2, PS1, PS2, Info); @@ -6481,9 +6471,8 @@ Sema::getMoreSpecializedPartialSpecialization( bool Sema::isMoreSpecializedThanPrimary( ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo &Info) { ClassTemplateDecl *Primary = Spec->getSpecializedTemplate(); - QualType PrimaryT = - Primary->getInjectedClassNameSpecialization().getCanonicalType(); - QualType PartialT = Spec->getInjectedSpecializationType().getCanonicalType(); + QualType PrimaryT = Primary->getCanonicalInjectedSpecializationType(Context); + QualType PartialT = Spec->getCanonicalInjectedSpecializationType(Context); ClassTemplatePartialSpecializationDecl *MaybeSpec = getMoreSpecialized(*this, PartialT, PrimaryT, Spec, Primary, Info); @@ -6790,19 +6779,13 @@ MarkUsedTemplateParameters(ASTContext &Ctx, /// Mark the template parameters that are used by the given /// nested name specifier. -static void -MarkUsedTemplateParameters(ASTContext &Ctx, - NestedNameSpecifier *NNS, - bool OnlyDeduced, - unsigned Depth, - llvm::SmallBitVector &Used) { - if (!NNS) +static void MarkUsedTemplateParameters(ASTContext &Ctx, NestedNameSpecifier NNS, + bool OnlyDeduced, unsigned Depth, + llvm::SmallBitVector &Used) { + if (NNS.getKind() != NestedNameSpecifier::Kind::Type) return; - - MarkUsedTemplateParameters(Ctx, NNS->getPrefix(), OnlyDeduced, Depth, - Used); - MarkUsedTemplateParameters(Ctx, QualType(NNS->getAsType(), 0), - OnlyDeduced, Depth, Used); + MarkUsedTemplateParameters(Ctx, QualType(NNS.getAsType(), 0), OnlyDeduced, + Depth, Used); } /// Mark the template parameters that are used by the given @@ -6876,7 +6859,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced, Depth, Used); MarkUsedTemplateParameters(Ctx, - QualType(MemPtr->getQualifier()->getAsType(), 0), + QualType(MemPtr->getQualifier().getAsType(), 0), OnlyDeduced, Depth, Used); break; } @@ -6994,7 +6977,9 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, } case Type::InjectedClassName: - T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType(); + T = cast<InjectedClassNameType>(T) + ->getOriginalDecl() + ->getCanonicalTemplateSpecializationType(Ctx); [[fallthrough]]; case Type::TemplateSpecialization: { diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 9be1c9c..6045914 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -105,22 +105,21 @@ public: return false; } - QualType - RebuildTemplateSpecializationType(TemplateName Template, - SourceLocation TemplateNameLoc, - TemplateArgumentListInfo &TemplateArgs) { + QualType RebuildTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, TemplateName Template, + SourceLocation TemplateNameLoc, TemplateArgumentListInfo &TemplateArgs) { if (!OuterInstantiationArgs || !isa_and_present<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) - return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, - TemplateArgs); + return Base::RebuildTemplateSpecializationType( + Keyword, Template, TemplateNameLoc, TemplateArgs); auto *TATD = cast<TypeAliasTemplateDecl>(Template.getAsTemplateDecl()); auto *Pattern = TATD; while (Pattern->getInstantiatedFromMemberTemplate()) Pattern = Pattern->getInstantiatedFromMemberTemplate(); if (!mightReferToOuterTemplateParameters(Pattern->getTemplatedDecl())) - return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, - TemplateArgs); + return Base::RebuildTemplateSpecializationType( + Keyword, Template, TemplateNameLoc, TemplateArgs); Decl *NewD = TypedefNameInstantiator->InstantiateTypeAliasTemplateDecl(TATD); @@ -131,13 +130,14 @@ public: MaterializedTypedefs.push_back(NewTATD->getTemplatedDecl()); return Base::RebuildTemplateSpecializationType( - TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); + Keyword, TemplateName(NewTATD), TemplateNameLoc, TemplateArgs); } QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { ASTContext &Context = SemaRef.getASTContext(); - TypedefNameDecl *OrigDecl = TL.getTypedefNameDecl(); + TypedefNameDecl *OrigDecl = TL.getDecl(); TypedefNameDecl *Decl = OrigDecl; + const TypedefType *T = TL.getTypePtr(); // Transform the underlying type of the typedef and clone the Decl only if // the typedef has a dependent context. bool InDependentContext = OrigDecl->getDeclContext()->isDependentContext(); @@ -155,7 +155,7 @@ public: // }; // }; if (OuterInstantiationArgs && InDependentContext && - TL.getTypePtr()->isInstantiationDependentType()) { + T->isInstantiationDependentType()) { Decl = cast_if_present<TypedefNameDecl>( TypedefNameInstantiator->InstantiateTypedefNameDecl( OrigDecl, /*IsTypeAlias=*/isa<TypeAliasDecl>(OrigDecl))); @@ -180,10 +180,17 @@ public: MaterializedTypedefs.push_back(Decl); } - QualType TDTy = Context.getTypedefType(Decl); - TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(TDTy); - TypedefTL.setNameLoc(TL.getNameLoc()); + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + } + QualType TDTy = Context.getTypedefType( + T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), Decl); + TLB.push<TypedefTypeLoc>(TDTy).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); return TDTy; } }; @@ -327,7 +334,7 @@ struct ConvertConstructorToDeductionGuideTransform { DeclarationName DeductionGuideName = SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template); - QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary); + QualType DeducedType = SemaRef.Context.getCanonicalTagType(Primary); // Index adjustment to apply to convert depth-1 template parameters into // depth-0 template parameters. @@ -593,7 +600,10 @@ private: // context of the template), so implicit deduction guides can never collide // with explicit ones. QualType ReturnType = DeducedType; - TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation()); + auto TTL = TLB.push<TagTypeLoc>(ReturnType); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(NestedNameSpecifierLoc()); + TTL.setNameLoc(Primary->getLocation()); // Resolving a wording defect, we also inherit the variadicness of the // constructor. @@ -954,7 +964,8 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, SmallVector<TypeSourceInfo *> IsDeducibleTypeTraitArgs = { Context.getTrivialTypeSourceInfo( Context.getDeducedTemplateSpecializationType( - TemplateName(AliasTemplate), /*DeducedType=*/QualType(), + ElaboratedTypeKeyword::None, TemplateName(AliasTemplate), + /*DeducedType=*/QualType(), /*IsDependent=*/true), AliasTemplate->getLocation()), // template specialization type whose // arguments will be deduced. @@ -970,10 +981,7 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>> getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { - // Unwrap the sugared ElaboratedType. - auto RhsType = AliasTemplate->getTemplatedDecl() - ->getUnderlyingType() - .getSingleStepDesugaredType(SemaRef.Context); + auto RhsType = AliasTemplate->getTemplatedDecl()->getUnderlyingType(); TemplateDecl *Template = nullptr; llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs; if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) { @@ -1048,12 +1056,11 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, // The (trailing) return type of the deduction guide. const TemplateSpecializationType *FReturnType = RType->getAs<TemplateSpecializationType>(); - if (const auto *InjectedCNT = RType->getAs<InjectedClassNameType>()) + if (const auto *ICNT = RType->getAs<InjectedClassNameType>()) // implicitly-generated deduction guide. - FReturnType = InjectedCNT->getInjectedTST(); - else if (const auto *ET = RType->getAs<ElaboratedType>()) - // explicit deduction guide. - FReturnType = ET->getNamedType()->getAsNonAliasTemplateSpecializationType(); + FReturnType = cast<TemplateSpecializationType>( + ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType( + SemaRef.Context)); assert(FReturnType && "expected to see a return type"); // Deduce template arguments of the deduction guide f from the RHS of // the alias. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 0d96d18..5e8dfd1 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -353,45 +353,50 @@ Response HandleFunctionTemplateDecl(Sema &SemaRef, SemaRef.Context), /*Final=*/false); - NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier(); - - while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) { - if (NNS->isInstantiationDependent()) { - if (const auto *TSTy = Ty->getAs<TemplateSpecializationType>()) { - ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments(); - // Prefer template arguments from the injected-class-type if possible. - // For example, - // ```cpp - // template <class... Pack> struct S { - // template <class T> void foo(); - // }; - // template <class... Pack> template <class T> - // ^^^^^^^^^^^^^ InjectedTemplateArgs - // They're of kind TemplateArgument::Pack, not of - // TemplateArgument::Type. - // void S<Pack...>::foo() {} - // ^^^^^^^ - // TSTy->template_arguments() (which are of PackExpansionType) - // ``` - // This meets the contract in - // TreeTransform::TryExpandParameterPacks that the template arguments - // for unexpanded parameters should be of a Pack kind. - if (TSTy->isCurrentInstantiation()) { - auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl(); - if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) - Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context); - else if (auto *Specialization = - dyn_cast<ClassTemplateSpecializationDecl>(RD)) - Arguments = - Specialization->getTemplateInstantiationArgs().asArray(); - } - Result.addOuterTemplateArguments( - TSTy->getTemplateName().getAsTemplateDecl(), Arguments, - /*Final=*/false); - } - } + NestedNameSpecifier NNS = FTD->getTemplatedDecl()->getQualifier(); + + for (const Type *Ty = NNS.getKind() == NestedNameSpecifier::Kind::Type + ? NNS.getAsType() + : nullptr, + *NextTy = nullptr; + Ty && Ty->isInstantiationDependentType(); + Ty = std::exchange(NextTy, nullptr)) { + if (NestedNameSpecifier P = Ty->getPrefix(); + P.getKind() == NestedNameSpecifier::Kind::Type) + NextTy = P.getAsType(); + const auto *TSTy = dyn_cast<TemplateSpecializationType>(Ty); + if (!TSTy) + continue; - NNS = NNS->getPrefix(); + ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments(); + // Prefer template arguments from the injected-class-type if possible. + // For example, + // ```cpp + // template <class... Pack> struct S { + // template <class T> void foo(); + // }; + // template <class... Pack> template <class T> + // ^^^^^^^^^^^^^ InjectedTemplateArgs + // They're of kind TemplateArgument::Pack, not of + // TemplateArgument::Type. + // void S<Pack...>::foo() {} + // ^^^^^^^ + // TSTy->template_arguments() (which are of PackExpansionType) + // ``` + // This meets the contract in + // TreeTransform::TryExpandParameterPacks that the template arguments + // for unexpanded parameters should be of a Pack kind. + if (TSTy->isCurrentInstantiation()) { + auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl(); + if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) + Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context); + else if (auto *Specialization = + dyn_cast<ClassTemplateSpecializationDecl>(RD)) + Arguments = Specialization->getTemplateInstantiationArgs().asArray(); + } + Result.addOuterTemplateArguments( + TSTy->getTemplateName().getAsTemplateDecl(), Arguments, + /*Final=*/false); } } @@ -1165,7 +1170,7 @@ void Sema::PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc) { DiagFunc(Active->PointOfInstantiation, PDiag(diag::note_member_synthesized_at) << MD->isExplicitlyDefaulted() << DFK.asSpecialMember() - << Context.getTagDeclType(MD->getParent())); + << Context.getCanonicalTagType(MD->getParent())); } else if (DFK.isComparison()) { QualType RecordType = FD->getParamDecl(0) ->getType() @@ -1595,15 +1600,9 @@ namespace { VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, TypeSourceInfo *TSInfo, QualType T); - /// Check for tag mismatches when instantiating an - /// elaborated type. - QualType RebuildElaboratedType(SourceLocation KeywordLoc, - ElaboratedTypeKeyword Keyword, - NestedNameSpecifierLoc QualifierLoc, - QualType T); - TemplateName - TransformTemplateName(CXXScopeSpec &SS, TemplateName Name, + TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc, + SourceLocation TemplateKWLoc, TemplateName Name, SourceLocation NameLoc, QualType ObjectType = QualType(), NamedDecl *FirstQualifierInScope = nullptr, @@ -1649,22 +1648,20 @@ namespace { return inherited::TransformFunctionProtoType(TLB, TL); } - QualType TransformInjectedClassNameType(TypeLocBuilder &TLB, - InjectedClassNameTypeLoc TL) { - auto Type = inherited::TransformInjectedClassNameType(TLB, TL); + QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL) { + auto Type = inherited::TransformTagType(TLB, TL); + if (!Type.isNull()) + return Type; // Special case for transforming a deduction guide, we return a // transformed TemplateSpecializationType. - if (Type.isNull() && - SemaRef.CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::BuildingDeductionGuides) { - // Return a TemplateSpecializationType for transforming a deduction - // guide. - if (auto *ICT = TL.getType()->getAs<InjectedClassNameType>()) { - auto Type = - inherited::TransformType(ICT->getInjectedSpecializationType()); - TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc()); - return Type; - } + // FIXME: Why is this hack necessary? + if (const auto *ICNT = dyn_cast<InjectedClassNameType>(TL.getTypePtr()); + ICNT && SemaRef.CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::BuildingDeductionGuides) { + Type = inherited::TransformType( + ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType( + SemaRef.Context)); + TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc()); } return Type; } @@ -2049,7 +2046,7 @@ TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, return cast_or_null<NamedDecl>(TransformDecl(Loc, D)); if (const TagType *Tag = T->getAs<TagType>()) - return Tag->getDecl(); + return Tag->getOriginalDecl(); // The resulting type is not a tag; complain. getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T; @@ -2082,41 +2079,10 @@ VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, return Var; } -QualType -TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, - ElaboratedTypeKeyword Keyword, - NestedNameSpecifierLoc QualifierLoc, - QualType T) { - if (const TagType *TT = T->getAs<TagType>()) { - TagDecl* TD = TT->getDecl(); - - SourceLocation TagLocation = KeywordLoc; - - IdentifierInfo *Id = TD->getIdentifier(); - - // TODO: should we even warn on struct/class mismatches for this? Seems - // like it's likely to produce a lot of spurious errors. - if (Id && Keyword != ElaboratedTypeKeyword::None && - Keyword != ElaboratedTypeKeyword::Typename) { - TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); - if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false, - TagLocation, Id)) { - SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag) - << Id - << FixItHint::CreateReplacement(SourceRange(TagLocation), - TD->getKindName()); - SemaRef.Diag(TD->getLocation(), diag::note_previous_use); - } - } - } - - return inherited::RebuildElaboratedType(KeywordLoc, Keyword, QualifierLoc, T); -} - TemplateName TemplateInstantiator::TransformTemplateName( - CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc, - QualType ObjectType, NamedDecl *FirstQualifierInScope, - bool AllowInjectedClassName) { + NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc, + TemplateName Name, SourceLocation NameLoc, QualType ObjectType, + NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) { if (TemplateTemplateParmDecl *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) { if (TTP->getDepth() < TemplateArgs.getNumLevels()) { @@ -2163,6 +2129,12 @@ TemplateName TemplateInstantiator::TransformTemplateName( TemplateName Template = Arg.getAsTemplate(); assert(!Template.isNull() && "Null template template argument"); + if (NestedNameSpecifier Qualifier = Template.getQualifier()) { + NestedNameSpecifierLocBuilder Builder; + Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc); + QualifierLoc = Builder.getWithLocInContext(SemaRef.Context); + } + return getSema().Context.getSubstTemplateTemplateParm( Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final); } @@ -2181,9 +2153,9 @@ TemplateName TemplateInstantiator::TransformTemplateName( getPackIndex(Pack), SubstPack->getFinal()); } - return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, - FirstQualifierInScope, - AllowInjectedClassName); + return inherited::TransformTemplateName( + QualifierLoc, TemplateKWLoc, Name, NameLoc, ObjectType, + FirstQualifierInScope, AllowInjectedClassName); } ExprResult @@ -3159,10 +3131,6 @@ namespace { // Only these types can contain 'auto' types, and subsequently be replaced // by references to invented parameters. - TemplateTypeParmDecl *VisitElaboratedType(const ElaboratedType *T) { - return Visit(T->getNamedType()); - } - TemplateTypeParmDecl *VisitPointerType(const PointerType *T) { return Visit(T->getPointeeType()); } @@ -4557,14 +4525,14 @@ Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, } TemplateName -Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, - TemplateName Name, SourceLocation Loc, +Sema::SubstTemplateName(SourceLocation TemplateKWLoc, + NestedNameSpecifierLoc &QualifierLoc, TemplateName Name, + SourceLocation NameLoc, const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, + TemplateInstantiator Instantiator(*this, TemplateArgs, NameLoc, DeclarationName()); - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - return Instantiator.TransformTemplateName(SS, Name, Loc); + return Instantiator.TransformTemplateName(QualifierLoc, TemplateKWLoc, Name, + NameLoc); } static const Decl *getCanonicalParmVarDecl(const Decl *D) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 87ec4f7..f02a295 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1483,9 +1483,9 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, // If the old typedef was the name for linkage purposes of an anonymous // tag decl, re-establish that relationship for the new typedef. if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) { - TagDecl *oldTag = oldTagType->getDecl(); + TagDecl *oldTag = oldTagType->getOriginalDecl(); if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) { - TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); + TagDecl *newTag = DI->getType()->castAs<TagType>()->getOriginalDecl(); assert(!newTag->hasNameForLinkage()); newTag->setTypedefNameForAnonDecl(Typedef); } @@ -2250,8 +2250,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *RecordInst = CXXRecordDecl::Create( SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(), - Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, - /*DelayTypeCreation=*/true); + Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl); if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); @@ -2271,8 +2270,6 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (PrevClassTemplate) { Inst->setCommonPtr(PrevClassTemplate->getCommonPtr()); - RecordInst->setTypeForDecl( - PrevClassTemplate->getTemplatedDecl()->getTypeForDecl()); const ClassTemplateDecl *MostRecentPrevCT = PrevClassTemplate->getMostRecentDecl(); TemplateParameterList *PrevParams = @@ -2306,10 +2303,6 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Inst->setPreviousDecl(PrevClassTemplate); - // Trigger creation of the type for the instantiation. - SemaRef.Context.getInjectedClassNameType( - RecordInst, Inst->getInjectedClassNameSpecialization()); - // Finish handling of friends. if (isFriend) { DC->makeDeclVisibleInContext(Inst); @@ -2515,11 +2508,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { else Record = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), D->getLocation(), - D->getIdentifier(), PrevDecl, - /*DelayTypeCreation=*/IsInjectedClassName); - // Link the type of the injected-class-name to that of the outer class. - if (IsInjectedClassName) - (void)SemaRef.Context.getTypeDeclType(Record, cast<CXXRecordDecl>(Owner)); + D->getIdentifier(), PrevDecl); + + Record->setImplicit(D->isImplicit()); // Substitute the nested name specifier, if any. if (SubstQualifier(D, Record)) @@ -2528,7 +2519,6 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, StartingScope); - Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that // the tag decls introduced by friend class declarations don't have an access // specifier. Remove once this area of the code gets sorted out. @@ -3164,8 +3154,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Method->setIneligibleOrNotSelected(true); Method->setRangeEnd(Destructor->getEndLoc()); Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName( - SemaRef.Context.getCanonicalType( - SemaRef.Context.getTypeDeclType(Record)))); + + SemaRef.Context.getCanonicalTagType(Record))); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, @@ -3793,19 +3783,18 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( D->getPosition(), D->isParameterPack(), D->getIdentifier(), D->templateParameterKind(), D->wasDeclaredWithTypename(), InstParams); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - NestedNameSpecifierLoc QualifierLoc = - D->getDefaultArgument().getTemplateQualifierLoc(); - QualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); + const TemplateArgumentLoc &A = D->getDefaultArgument(); + NestedNameSpecifierLoc QualifierLoc = A.getTemplateQualifierLoc(); + // FIXME: Pass in the template keyword location. TemplateName TName = SemaRef.SubstTemplateName( - QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(), - D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); + A.getTemplateKWLoc(), QualifierLoc, A.getArgument().getAsTemplate(), + A.getTemplateNameLoc(), TemplateArgs); if (!TName.isNull()) Param->setDefaultArgument( SemaRef.Context, TemplateArgumentLoc(SemaRef.Context, TemplateArgument(TName), - D->getDefaultArgument().getTemplateQualifierLoc(), - D->getDefaultArgument().getTemplateNameLoc())); + A.getTemplateKWLoc(), QualifierLoc, + A.getTemplateNameLoc())); } Param->setAccess(AS_public); Param->setImplicit(D->isImplicit()); @@ -3907,7 +3896,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) if (auto *RD = dyn_cast<CXXRecordDecl>(SemaRef.CurContext)) NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName( - SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD)))); + SemaRef.Context.getCanonicalTagType(RD))); // We only need to do redeclaration lookups if we're in a class scope (in // fact, it's not really even possible in non-class scopes). @@ -4819,18 +4808,13 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( ClassTemplate->findPartialSpecialization(CTAI.CanonicalConverted, InstParams, InsertPos); - // Build the type that describes the converted template arguments of the class - // template partial specialization. - TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(ClassTemplate), TemplArgInfo->getLAngleLoc(), - InstTemplateArgs, CTAI.CanonicalConverted); - // Create the class template partial specialization declaration. ClassTemplatePartialSpecializationDecl *InstPartialSpec = ClassTemplatePartialSpecializationDecl::Create( SemaRef.Context, PartialSpec->getTagKind(), Owner, PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, CTAI.CanonicalConverted, WrittenTy->getType(), + ClassTemplate, CTAI.CanonicalConverted, + /*CanonInjectedTST=*/CanQualType(), /*PrevDecl=*/nullptr); InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); @@ -4861,7 +4845,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( diag::err_partial_spec_redeclared) << InstPartialSpec; SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) - << SemaRef.Context.getTypeDeclType(PrevDecl); + << SemaRef.Context.getCanonicalTagType(PrevDecl); return nullptr; } @@ -5750,15 +5734,19 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, QualType TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) { const RecordType *T = TL.getTypePtr(); RecordDecl *Record = cast_or_null<RecordDecl>( - getDerived().TransformDecl(TL.getNameLoc(), T->getDecl())); + getDerived().TransformDecl(TL.getNameLoc(), T->getOriginalDecl())); if (Record != OldDecl) return Base::TransformRecordType(TLB, TL); - QualType Result = getDerived().RebuildRecordType(NewDecl); + // FIXME: transform the rest of the record type. + QualType Result = getDerived().RebuildTagType( + ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, NewDecl); if (Result.isNull()) return QualType(); - RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + TagTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + NewTL.setElaboratedKeywordLoc(SourceLocation()); + NewTL.setQualifierLoc(NestedNameSpecifierLoc()); NewTL.setNameLoc(TL.getNameLoc()); return Result; } @@ -6922,7 +6910,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, Args.addArgument( getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc)); } - QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); + QualType T = CheckTemplateIdType(ElaboratedTypeKeyword::None, + TemplateName(TD), Loc, Args); // We may get a non-null type with errors, in which case // `getAsCXXRecordDecl` will return `nullptr`. For instance, this // happens when one of the template arguments is an invalid @@ -6988,16 +6977,17 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, bool IsBeingInstantiated = false; if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { if (!Spec->isDependentContext()) { - QualType T = Context.getTypeDeclType(Spec); + CanQualType T = Context.getCanonicalTagType(Spec); const RecordType *Tag = T->getAs<RecordType>(); assert(Tag && "type of non-dependent record is not a RecordType"); - if (Tag->isBeingDefined()) + auto *TagDecl = + cast<CXXRecordDecl>(Tag->getOriginalDecl())->getDefinitionOrSelf(); + if (TagDecl->isBeingDefined()) IsBeingInstantiated = true; - if (!Tag->isBeingDefined() && - RequireCompleteType(Loc, T, diag::err_incomplete_type)) + else if (RequireCompleteType(Loc, T, diag::err_incomplete_type)) return nullptr; - ParentDC = Tag->getDecl(); + ParentDC = TagDecl; } } @@ -7043,8 +7033,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // of member classes, and introduces ordering dependencies via // template instantiation. Diag(Loc, diag::err_member_not_yet_instantiated) - << D->getDeclName() - << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); + << D->getDeclName() + << Context.getCanonicalTagType(cast<CXXRecordDecl>(ParentDC)); Diag(D->getLocation(), diag::note_non_instantiated_member_here); } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { // This enumeration constant was found when the template was defined, @@ -7059,7 +7049,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, << D->getDeclName() << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext())); Diag(Spec->getLocation(), diag::note_enum_specialized_here) - << Context.getTypeDeclType(Spec); + << Context.getCanonicalTagType(Spec); } else { // We should have found something, but didn't. llvm_unreachable("Unable to find instantiation of declaration!"); diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index d2baa2e..377f2ed 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -155,21 +155,22 @@ class CollectUnexpandedParameterPacksVisitor /// Suppress traversal into types that do not contain /// unexpanded parameter packs. - bool TraverseType(QualType T) override { + bool TraverseType(QualType T, bool TraverseQualifier = true) override { if ((!T.isNull() && T->containsUnexpandedParameterPack()) || InLambdaOrBlock) - return DynamicRecursiveASTVisitor::TraverseType(T); + return DynamicRecursiveASTVisitor::TraverseType(T, TraverseQualifier); return true; } /// Suppress traversal into types with location information /// that do not contain unexpanded parameter packs. - bool TraverseTypeLoc(TypeLoc TL) override { + bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) override { if ((!TL.getType().isNull() && TL.getType()->containsUnexpandedParameterPack()) || InLambdaOrBlock) - return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL); + return DynamicRecursiveASTVisitor::TraverseTypeLoc(TL, + TraverseQualifier); return true; } @@ -195,10 +196,12 @@ class CollectUnexpandedParameterPacksVisitor /// Suppress traversal of pack expansion expressions and types. ///@{ - bool TraversePackExpansionType(PackExpansionType *T) override { + bool TraversePackExpansionType(PackExpansionType *T, + bool TraverseQualifier) override { return true; } - bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL) override { + bool TraversePackExpansionTypeLoc(PackExpansionTypeLoc TL, + bool TraverseQualifier) override { return true; } bool TraversePackExpansionExpr(PackExpansionExpr *E) override { @@ -208,10 +211,12 @@ class CollectUnexpandedParameterPacksVisitor bool TraversePackIndexingExpr(PackIndexingExpr *E) override { return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); } - bool TraversePackIndexingType(PackIndexingType *E) override { + bool TraversePackIndexingType(PackIndexingType *E, + bool TraverseQualifier) override { return DynamicRecursiveASTVisitor::TraverseStmt(E->getIndexExpr()); } - bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL) override { + bool TraversePackIndexingTypeLoc(PackIndexingTypeLoc TL, + bool TraverseQualifier) override { return DynamicRecursiveASTVisitor::TraverseStmt(TL.getIndexExpr()); } @@ -525,8 +530,7 @@ bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, // C++0x [temp.variadic]p5: // An appearance of a name of a parameter pack that is not expanded is // ill-formed. - if (!SS.getScopeRep() || - !SS.getScopeRep()->containsUnexpandedParameterPack()) + if (!SS.getScopeRep().containsUnexpandedParameterPack()) return false; SmallVector<UnexpandedParameterPack, 2> Unexpanded; @@ -654,7 +658,7 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, return ParsedTemplateArgument(); return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), - Arg.getLocation()); + Arg.getNameLoc()); } case ParsedTemplateArgument::NonType: { @@ -663,12 +667,12 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, return ParsedTemplateArgument(); return ParsedTemplateArgument(Arg.getKind(), Result.get(), - Arg.getLocation()); + Arg.getNameLoc()); } case ParsedTemplateArgument::Template: if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { - SourceRange R(Arg.getLocation()); + SourceRange R(Arg.getNameLoc()); if (Arg.getScopeSpec().isValid()) R.setBegin(Arg.getScopeSpec().getBeginLoc()); Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) @@ -1115,8 +1119,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { break; case DeclaratorChunk::MemberPointer: - if (Chunk.Mem.Scope().getScopeRep() && - Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) + if (Chunk.Mem.Scope().getScopeRep().containsUnexpandedParameterPack()) return true; break; } @@ -1300,9 +1303,9 @@ TemplateArgumentLoc Sema::getTemplateArgumentPackExpansionPattern( case TemplateArgument::TemplateExpansion: Ellipsis = OrigLoc.getTemplateEllipsisLoc(); NumExpansions = Argument.getNumTemplateExpansions(); - return TemplateArgumentLoc(Context, Argument.getPackExpansionPattern(), - OrigLoc.getTemplateQualifierLoc(), - OrigLoc.getTemplateNameLoc()); + return TemplateArgumentLoc( + Context, Argument.getPackExpansionPattern(), OrigLoc.getTemplateKWLoc(), + OrigLoc.getTemplateQualifierLoc(), OrigLoc.getTemplateNameLoc()); case TemplateArgument::Declaration: case TemplateArgument::NullPtr: diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 1289bed..0985b5b 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1211,14 +1211,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { DS.getTypeSpecSign() == TypeSpecifierSign::Unspecified && "No qualifiers on tag names!"); + ElaboratedTypeKeyword Keyword = + KeywordHelpers::getKeywordForTypeSpec(DS.getTypeSpecType()); // TypeQuals handled by caller. - Result = Context.getTypeDeclType(D); - - // In both C and C++, make an ElaboratedType. - ElaboratedTypeKeyword Keyword - = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); - Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result, - DS.isTypeSpecOwned() ? D : nullptr); + Result = Context.getTagType(Keyword, DS.getTypeSpecScope().getScopeRep(), D, + DS.isTypeSpecOwned()); break; } case DeclSpec::TST_typename: { @@ -1241,7 +1238,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { assert(!Result.isNull() && "Didn't get a type for typeof?"); if (!Result->isDependentType()) if (const TagType *TT = Result->getAs<TagType>()) - S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc()); + S.DiagnoseUseOfDecl(TT->getOriginalDecl(), DS.getTypeSpecTypeLoc()); // TypeQuals handled by caller. Result = Context.getTypeOfType( Result, DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType @@ -2085,7 +2082,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, // an inheritance model, even if it's inside an unused typedef. if (Context.getTargetInfo().getCXXABI().isMicrosoft()) if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) - if (!MPTy->getQualifier()->isDependent()) + if (!MPTy->getQualifier().isDependent()) (void)isCompleteType(Loc, T); } else { @@ -2120,7 +2117,9 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, if (const RecordType *EltTy = T->getAs<RecordType>()) { // If the element type is a struct or union that contains a variadic // array, accept it as a GNU extension: C99 6.7.2.1p2. - if (EltTy->getDecl()->hasFlexibleArrayMember()) + if (EltTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) Diag(Loc, diag::ext_flexible_array_in_array) << T; } else if (T->isObjCObjectType()) { Diag(Loc, diag::err_objc_array_of_interfaces) << T; @@ -3460,7 +3459,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (DiagID != 0) { SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID) - << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + << SemaRef.Context.getCanonicalTagType(OwnedTagDecl); D.setInvalidType(true); } } @@ -3653,11 +3652,22 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { // here: even (e.g.) "int ::x" is visually ambiguous even though it's // formally unambiguous. if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) { - for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS; - NNS = NNS->getPrefix()) { - if (NNS->getKind() == NestedNameSpecifier::Global) + NestedNameSpecifier NNS = D.getCXXScopeSpec().getScopeRep(); + for (;;) { + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Global: return; + case NestedNameSpecifier::Kind::Type: + NNS = NNS.getAsType()->getPrefix(); + continue; + case NestedNameSpecifier::Kind::Namespace: + NNS = NNS.getAsNamespaceAndPrefix().Prefix; + continue; + default: + goto out; + } } + out:; } S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator) @@ -3965,7 +3975,8 @@ classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator, return PointerDeclaratorKind::NonPointer; if (auto recordType = type->getAs<RecordType>()) { - RecordDecl *recordDecl = recordType->getDecl(); + RecordDecl *recordDecl = + recordType->getOriginalDecl()->getDefinitionOrSelf(); // If this is CFErrorRef*, report it as such. if (numNormalPointers == 2 && numTypeSpecifierPointers < 2 && @@ -5101,7 +5112,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Types shall not be defined in return or parameter types. TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type) - << Context.getTypeDeclType(Tag); + << Context.getCanonicalTagType(Tag); } // Exception specs are not allowed in typedefs. Complain, but add it @@ -5319,7 +5330,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, state.getDeclarator() .getCXXScopeSpec() .getScopeRep() - ->getKind() == NestedNameSpecifier::TypeSpec) || + .getKind() == NestedNameSpecifier::Kind::Type) || state.getDeclarator().getContext() == DeclaratorContext::Member || state.getDeclarator().getContext() == @@ -5898,7 +5909,49 @@ namespace { // int __attr * __attr * __attr *p; void VisitPointerTypeLoc(PointerTypeLoc TL) { Visit(TL.getNextTypeLoc()); } void VisitTypedefTypeLoc(TypedefTypeLoc TL) { - TL.setNameLoc(DS.getTypeSpecTypeLoc()); + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(TInfo->getTypeLoc().castAs<TypedefTypeLoc>()); + return; + } + } + TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None + ? DS.getTypeSpecTypeLoc() + : SourceLocation(), + DS.getTypeSpecScope().getWithLocInContext(Context), + DS.getTypeSpecTypeNameLoc()); + } + void VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(TInfo->getTypeLoc().castAs<UnresolvedUsingTypeLoc>()); + return; + } + } + TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None + ? DS.getTypeSpecTypeLoc() + : SourceLocation(), + DS.getTypeSpecScope().getWithLocInContext(Context), + DS.getTypeSpecTypeNameLoc()); + } + void VisitUsingTypeLoc(UsingTypeLoc TL) { + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(TInfo->getTypeLoc().castAs<UsingTypeLoc>()); + return; + } + } + TL.set(TL.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None + ? DS.getTypeSpecTypeLoc() + : SourceLocation(), + DS.getTypeSpecScope().getWithLocInContext(Context), + DS.getTypeSpecTypeNameLoc()); } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeLoc()); @@ -5929,16 +5982,9 @@ namespace { } TypeLoc OldTL = TInfo->getTypeLoc(); - if (TInfo->getType()->getAs<ElaboratedType>()) { - ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>(); - TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc() - .castAs<TemplateSpecializationTypeLoc>(); - TL.copy(NamedTL); - } else { - TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>()); - assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc()); - } - + TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>()); + assert(TL.getRAngleLoc() == + OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc()); } void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr || @@ -5987,24 +6033,6 @@ namespace { TL.expandBuiltinRange(DS.getTypeSpecWidthRange()); } } - void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - if (DS.getTypeSpecType() == TST_typename) { - TypeSourceInfo *TInfo = nullptr; - Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); - if (TInfo) - if (auto ETL = TInfo->getTypeLoc().getAs<ElaboratedTypeLoc>()) { - TL.copy(ETL); - return; - } - } - const ElaboratedType *T = TL.getTypePtr(); - TL.setElaboratedKeywordLoc(T->getKeyword() != ElaboratedTypeKeyword::None - ? DS.getTypeSpecTypeLoc() - : SourceLocation()); - const CXXScopeSpec& SS = DS.getTypeSpecScope(); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); - Visit(TL.getNextTypeLoc().getUnqualifiedLoc()); - } void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { assert(DS.getTypeSpecType() == TST_typename); TypeSourceInfo *TInfo = nullptr; @@ -6063,7 +6091,29 @@ namespace { ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo)); TL.setConceptReference(CR); } + void VisitDeducedTemplateSpecializationTypeLoc( + DeducedTemplateSpecializationTypeLoc TL) { + assert(DS.getTypeSpecType() == TST_typename); + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + assert(TInfo); + TL.copy( + TInfo->getTypeLoc().castAs<DeducedTemplateSpecializationTypeLoc>()); + } void VisitTagTypeLoc(TagTypeLoc TL) { + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(TInfo->getTypeLoc().castAs<TagTypeLoc>()); + return; + } + } + TL.setElaboratedKeywordLoc(TL.getTypePtr()->getKeyword() != + ElaboratedTypeKeyword::None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + TL.setQualifierLoc(DS.getTypeSpecScope().getWithLocInContext(Context)); TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitAtomicTypeLoc(AtomicTypeLoc TL) { @@ -7029,9 +7079,6 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, if (const TypedefType *TT = dyn_cast<TypedefType>(Desugared)) { Desugared = TT->desugar(); continue; - } else if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Desugared)) { - Desugared = ET->desugar(); - continue; } const AttributedType *AT = dyn_cast<AttributedType>(Desugared); if (!AT) @@ -9170,11 +9217,9 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { if (RequireCompleteTypeImpl(Loc, T, Kind, &Diagnoser)) return true; - if (const TagType *Tag = T->getAs<TagType>()) { - if (!Tag->getDecl()->isCompleteDefinitionRequired()) { - Tag->getDecl()->setCompleteDefinitionRequired(); - Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl()); - } + if (auto *TD = T->getAsTagDecl(); TD && !TD->isCompleteDefinitionRequired()) { + TD->setCompleteDefinitionRequired(); + Consumer.HandleTagDeclRequiredDefinition(TD); } return false; } @@ -9312,7 +9357,7 @@ bool Sema::hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested, /// Locks in the inheritance model for the given class and all of its bases. static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { - RD = RD->getMostRecentNonInjectedDecl(); + RD = RD->getMostRecentDecl(); if (!RD->hasAttr<MSInheritanceAttr>()) { MSInheritanceModel IM; bool BestCase = false; @@ -9352,10 +9397,10 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // assert(!T->isDependentType() && // "Can't ask whether a dependent type is complete"); - if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) { + if (const auto *MPTy = dyn_cast<MemberPointerType>(T.getCanonicalType())) { if (CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl(); RD && !RD->isDependentType()) { - QualType T = Context.getTypeDeclType(RD); + CanQualType T = Context.getCanonicalTagType(RD); if (getLangOpts().CompleteMemberPointers && !RD->isBeingDefined() && RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete)) return true; @@ -9492,10 +9537,10 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // If the type was a forward declaration of a class/struct/union // type, produce a note. if (Tag && !Tag->isInvalidDecl() && !Tag->getLocation().isInvalid()) - Diag(Tag->getLocation(), - Tag->isBeingDefined() ? diag::note_type_being_defined - : diag::note_forward_declaration) - << Context.getTagDeclType(Tag); + Diag(Tag->getLocation(), Tag->isBeingDefined() + ? diag::note_type_being_defined + : diag::note_forward_declaration) + << Context.getCanonicalTagType(Tag); // If the Objective-C class was a forward declaration, produce a note. if (IFace && !IFace->isInvalidDecl() && !IFace->getLocation().isInvalid()) @@ -9550,7 +9595,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, if (!RT) return true; - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); // A partially-defined class type can't be a literal type, because a literal // class type must have a trivial destructor (which can't be checked until @@ -9628,15 +9674,6 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) { return RequireLiteralType(Loc, T, Diagnoser); } -QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, - const CXXScopeSpec &SS, QualType T, - TagDecl *OwnedTagDecl) { - if (T.isNull()) - return T; - return Context.getElaboratedType( - Keyword, SS.isValid() ? SS.getScopeRep() : nullptr, T, OwnedTagDecl); -} - QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) { assert(!E->hasPlaceholderType() && "unexpected placeholder"); @@ -9647,7 +9684,7 @@ QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) { if (!E->isTypeDependent()) { QualType T = E->getType(); if (const TagType *TT = T->getAs<TagType>()) - DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc()); + DiagnoseUseOfDecl(TT->getOriginalDecl(), E->getExprLoc()); } return Context.getTypeOfExprType(E, Kind); } @@ -9813,8 +9850,7 @@ QualType Sema::BuildPackIndexingType(QualType Pattern, Expr *IndexExpr, static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType, SourceLocation Loc) { assert(BaseType->isEnumeralType()); - EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl(); - assert(ED && "EnumType has no EnumDecl"); + EnumDecl *ED = BaseType->castAs<EnumType>()->getOriginalDecl(); S.DiagnoseUseOfDecl(ED, Loc); diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1d8687e..9b9dd17 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -32,8 +32,7 @@ static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef, RD = RD->getDefinition(); SourceLocation LookupLoc = RD->getLocation(); - CanQualType CanTy = SemaRef.getASTContext().getCanonicalType( - SemaRef.getASTContext().getTagDeclType(RD)); + CanQualType CanTy = SemaRef.getASTContext().getCanonicalTagType(RD); DeclarationName Name; Expr *Arg = nullptr; unsigned NumArgs; @@ -562,7 +561,8 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, bool (CXXRecordDecl::*HasTrivial)() const, bool (CXXRecordDecl::*HasNonTrivial)() const, bool (CXXMethodDecl::*IsDesiredOp)() const) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + CXXRecordDecl *RD = + cast<CXXRecordDecl>(RT->getOriginalDecl())->getDefinitionOrSelf(); if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)()) return true; @@ -599,6 +599,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, if (Decl->isLambda()) return Decl->isCapturelessLambda(); + CanQualType T = S.Context.getCanonicalTagType(Decl); { EnterExpressionEvaluationContext UnevaluatedContext( S, Sema::ExpressionEvaluationContext::Unevaluated); @@ -606,10 +607,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl()); // const ClassT& obj; - OpaqueValueExpr Operand( - KeyLoc, - Decl->getTypeForDecl()->getCanonicalTypeUnqualified().withConst(), - ExprValueKind::VK_LValue); + OpaqueValueExpr Operand(KeyLoc, T.withConst(), ExprValueKind::VK_LValue); UnresolvedSet<16> Functions; // obj == obj; S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions); @@ -628,8 +626,7 @@ static bool HasNonDeletedDefaultedEqualityComparison(Sema &S, return false; if (!ParamT->isReferenceType() && !Decl->isTriviallyCopyable()) return false; - if (ParamT.getNonReferenceType()->getUnqualifiedDesugaredType() != - Decl->getTypeForDecl()) + if (!S.Context.hasSameUnqualifiedType(ParamT.getNonReferenceType(), T)) return false; } @@ -1613,9 +1610,9 @@ bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, // Unions are never base classes, and never have base classes. // It doesn't matter if they are complete or not. See PR#41843 - if (lhsRecord && lhsRecord->getDecl()->isUnion()) + if (lhsRecord && lhsRecord->getOriginalDecl()->isUnion()) return false; - if (rhsRecord && rhsRecord->getDecl()->isUnion()) + if (rhsRecord && rhsRecord->getOriginalDecl()->isUnion()) return false; if (lhsRecord == rhsRecord) @@ -1629,8 +1626,8 @@ bool Sema::BuiltinIsBaseOf(SourceLocation RhsTLoc, QualType LhsT, diag::err_incomplete_type_used_in_type_trait_expr)) return false; - return cast<CXXRecordDecl>(rhsRecord->getDecl()) - ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl())); + return cast<CXXRecordDecl>(rhsRecord->getOriginalDecl()) + ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getOriginalDecl())); } static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, @@ -1670,8 +1667,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, diag::err_incomplete_type)) return false; - return cast<CXXRecordDecl>(DerivedRecord->getDecl()) - ->isVirtuallyDerivedFrom(cast<CXXRecordDecl>(BaseRecord->getDecl())); + return cast<CXXRecordDecl>(DerivedRecord->getOriginalDecl()) + ->isVirtuallyDerivedFrom( + cast<CXXRecordDecl>(BaseRecord->getOriginalDecl())); } case BTT_IsSame: return Self.Context.hasSameType(LhsT, RhsT); @@ -2018,11 +2016,10 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { // std::is_xxx<>::value if (const auto *VD = dyn_cast<VarDecl>(Ref->getDecl()); Ref->hasQualifier() && VD && VD->getIdentifier()->isStr("value")) { - const Type *T = Ref->getQualifier()->getAsType(); - if (!T) + NestedNameSpecifier Qualifier = Ref->getQualifier(); + if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type) return std::nullopt; - const TemplateSpecializationType *Ts = - T->getAs<TemplateSpecializationType>(); + const auto *Ts = Qualifier.getAsType()->getAs<TemplateSpecializationType>(); if (!Ts) return std::nullopt; const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl(); diff --git a/clang/lib/Sema/SemaWasm.cpp b/clang/lib/Sema/SemaWasm.cpp index 8998492..e773113 100644 --- a/clang/lib/Sema/SemaWasm.cpp +++ b/clang/lib/Sema/SemaWasm.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Attr.h" #include "clang/Sema/Sema.h" @@ -227,7 +228,8 @@ bool SemaWasm::BuiltinWasmTableCopy(CallExpr *TheCall) { return false; } -bool SemaWasm::BuiltinWasmTestFunctionPointerSignature(CallExpr *TheCall) { +bool SemaWasm::BuiltinWasmTestFunctionPointerSignature(const TargetInfo &TI, + CallExpr *TheCall) { if (SemaRef.checkArgCount(TheCall, 1)) return true; @@ -250,27 +252,31 @@ bool SemaWasm::BuiltinWasmTestFunctionPointerSignature(CallExpr *TheCall) { << ArgType << FuncPtrArg->getSourceRange(); } - // Check that the function pointer doesn't use reference types - if (FuncTy->getReturnType().isWebAssemblyReferenceType()) { - return Diag( - FuncPtrArg->getBeginLoc(), - diag::err_wasm_builtin_test_fp_sig_cannot_include_reference_type) - << 0 << FuncTy->getReturnType() << FuncPtrArg->getSourceRange(); - } - auto NParams = FuncTy->getNumParams(); - for (unsigned I = 0; I < NParams; I++) { - if (FuncTy->getParamType(I).isWebAssemblyReferenceType()) { + if (TI.getABI() == "experimental-mv") { + auto isStructOrUnion = [](QualType T) { + return T->isUnionType() || T->isStructureType(); + }; + if (isStructOrUnion(FuncTy->getReturnType())) { return Diag( FuncPtrArg->getBeginLoc(), diag:: - err_wasm_builtin_test_fp_sig_cannot_include_reference_type) - << 1 << FuncPtrArg->getSourceRange(); + err_wasm_builtin_test_fp_sig_cannot_include_struct_or_union) + << 0 << FuncTy->getReturnType() << FuncPtrArg->getSourceRange(); + } + auto NParams = FuncTy->getNumParams(); + for (unsigned I = 0; I < NParams; I++) { + if (isStructOrUnion(FuncTy->getParamType(I))) { + return Diag( + FuncPtrArg->getBeginLoc(), + diag:: + err_wasm_builtin_test_fp_sig_cannot_include_struct_or_union) + << 1 << FuncPtrArg->getSourceRange(); + } } } // Set return type to int (the result of the test) TheCall->setType(getASTContext().IntTy); - return false; } @@ -297,7 +303,7 @@ bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, case WebAssembly::BI__builtin_wasm_table_copy: return BuiltinWasmTableCopy(TheCall); case WebAssembly::BI__builtin_wasm_test_function_pointer_signature: - return BuiltinWasmTestFunctionPointerSignature(TheCall); + return BuiltinWasmTestFunctionPointerSignature(TI, TheCall); } return false; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 6ce5535..1863e7f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -591,12 +591,12 @@ public: /// By default, transforms the template name by transforming the declarations /// and nested-name-specifiers that occur within the template name. /// Subclasses may override this function to provide alternate behavior. - TemplateName - TransformTemplateName(CXXScopeSpec &SS, TemplateName Name, - SourceLocation NameLoc, - QualType ObjectType = QualType(), - NamedDecl *FirstQualifierInScope = nullptr, - bool AllowInjectedClassName = false); + TemplateName TransformTemplateName(NestedNameSpecifierLoc &QualifierLoc, + SourceLocation TemplateKWLoc, + TemplateName Name, SourceLocation NameLoc, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = nullptr, + bool AllowInjectedClassName = false); /// Transform the given template argument. /// @@ -610,9 +610,9 @@ public: TemplateArgumentLoc &Output, bool Uneval = false); - TemplateArgument - TransformNamedTemplateTemplateArgument(CXXScopeSpec &SS, TemplateName Name, - SourceLocation NameLoc); + TemplateArgument TransformNamedTemplateTemplateArgument( + NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKeywordLoc, + TemplateName Name, SourceLocation NameLoc); /// Transform the given set of template arguments. /// @@ -697,20 +697,17 @@ public: StmtResult TransformSEHHandler(Stmt *Handler); - QualType - TransformTemplateSpecializationType(TypeLocBuilder &TLB, - TemplateSpecializationTypeLoc TL, - TemplateName Template); - - QualType - TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL, + QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL, TemplateName Template, CXXScopeSpec &SS); QualType TransformDependentTemplateSpecializationType( TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, - CXXScopeSpec &SS); + QualType ObjectType, NamedDecl *UnqualLookup, + bool AllowInjectedClassName); + + QualType TransformTagType(TypeLocBuilder &TLB, TagTypeLoc TL); /// Transforms the parameters of a function type into the /// given vectors. @@ -1020,16 +1017,22 @@ public: /// Rebuild an unresolved typename type, given the decl that /// the UnresolvedUsingTypenameDecl was transformed to. - QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D); + QualType RebuildUnresolvedUsingType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier Qualifier, + SourceLocation NameLoc, Decl *D); /// Build a new type found via an alias. - QualType RebuildUsingType(UsingShadowDecl *Found, QualType Underlying) { - return SemaRef.Context.getUsingType(Found, Underlying); + QualType RebuildUsingType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier Qualifier, UsingShadowDecl *D, + QualType UnderlyingType) { + return SemaRef.Context.getUsingType(Keyword, Qualifier, D, UnderlyingType); } /// Build a new typedef type. - QualType RebuildTypedefType(TypedefNameDecl *Typedef) { - return SemaRef.Context.getTypeDeclType(Typedef); + QualType RebuildTypedefType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier Qualifier, + TypedefNameDecl *Typedef) { + return SemaRef.Context.getTypedefType(Keyword, Qualifier, Typedef); } /// Build a new MacroDefined type. @@ -1038,14 +1041,14 @@ public: return SemaRef.Context.getMacroQualifiedType(T, MacroII); } - /// Build a new class/struct/union type. - QualType RebuildRecordType(RecordDecl *Record) { - return SemaRef.Context.getTypeDeclType(Record); + /// Build a new class/struct/union/enum type. + QualType RebuildTagType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier Qualifier, TagDecl *Tag) { + return SemaRef.Context.getTagType(Keyword, Qualifier, Tag, + /*OwnsTag=*/false); } - - /// Build a new Enum type. - QualType RebuildEnumType(EnumDecl *Enum) { - return SemaRef.Context.getTypeDeclType(Enum); + QualType RebuildCanonicalTagType(TagDecl *Tag) { + return SemaRef.Context.getCanonicalTagType(Tag); } /// Build a new typeof(expr) type. @@ -1094,10 +1097,10 @@ public: /// By default, builds a new DeducedTemplateSpecializationType with the given /// deduced type. - QualType RebuildDeducedTemplateSpecializationType(TemplateName Template, - QualType Deduced) { + QualType RebuildDeducedTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, TemplateName Template, QualType Deduced) { return SemaRef.Context.getDeducedTemplateSpecializationType( - Template, Deduced, /*IsDependent*/ false); + Keyword, Template, Deduced, /*IsDependent*/ false); } /// Build a new template specialization type. @@ -1105,7 +1108,8 @@ public: /// By default, performs semantic analysis when building the template /// specialization type. Subclasses may override this routine to provide /// different behavior. - QualType RebuildTemplateSpecializationType(TemplateName Template, + QualType RebuildTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &Args); @@ -1117,41 +1121,22 @@ public: return SemaRef.BuildParenType(InnerType); } - /// Build a new qualified name type. - /// - /// By default, builds a new ElaboratedType type from the keyword, - /// the nested-name-specifier and the named type. - /// Subclasses may override this routine to provide different behavior. - QualType RebuildElaboratedType(SourceLocation KeywordLoc, - ElaboratedTypeKeyword Keyword, - NestedNameSpecifierLoc QualifierLoc, - QualType Named) { - return SemaRef.Context.getElaboratedType(Keyword, - QualifierLoc.getNestedNameSpecifier(), - Named); - } - /// Build a new typename type that refers to a template-id. /// /// By default, builds a new DependentNameType type from the /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. QualType RebuildDependentTemplateSpecializationType( - ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - SourceLocation TemplateKWLoc, TemplateName Name, SourceLocation NameLoc, - TemplateArgumentListInfo &Args, bool AllowInjectedClassName) { + ElaboratedTypeKeyword Keyword, SourceLocation TemplateKWLoc, + TemplateName Name, SourceLocation NameLoc, TemplateArgumentListInfo &Args, + bool AllowInjectedClassName) { // If it's still dependent, make a dependent specialization. if (const DependentTemplateStorage *S = Name.getAsDependentTemplateName()) return SemaRef.Context.getDependentTemplateSpecializationType( Keyword, *S, Args.arguments()); - // Otherwise, make an elaborated type wrapping a non-dependent - // specialization. - QualType T = - getDerived().RebuildTemplateSpecializationType(Name, NameLoc, Args); - if (T.isNull()) - return QualType(); - return SemaRef.Context.getElaboratedType(Keyword, NNS, T); + return getDerived().RebuildTemplateSpecializationType(Keyword, Name, + NameLoc, Args); } /// Build a new typename type that refers to an identifier. @@ -1168,7 +1153,7 @@ public: CXXScopeSpec SS; SS.Adopt(QualifierLoc); - if (QualifierLoc.getNestedNameSpecifier()->isDependent()) { + if (QualifierLoc.getNestedNameSpecifier().isDependent()) { // If the name is still dependent, just build a new dependent name type. if (!SemaRef.computeDeclContext(SS)) return SemaRef.Context.getDependentNameType(Keyword, @@ -1238,19 +1223,14 @@ public: } return QualType(); } - if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false, IdLoc, Id)) { SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id; SemaRef.Diag(Tag->getLocation(), diag::note_previous_use); return QualType(); } - - // Build the elaborated-type-specifier type. - QualType T = SemaRef.Context.getTypeDeclType(Tag); - return SemaRef.Context.getElaboratedType(Keyword, - QualifierLoc.getNestedNameSpecifier(), - T); + return getDerived().RebuildTagType( + Keyword, QualifierLoc.getNestedNameSpecifier(), Tag); } /// Build a new pack expansion type. @@ -1303,7 +1283,6 @@ public: SourceLocation TemplateKWLoc, const IdentifierInfo &Name, SourceLocation NameLoc, QualType ObjectType, - NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName); /// Build a new template name given a nested name specifier and the @@ -1323,7 +1302,6 @@ public: SourceLocation TemplateKWLoc, IdentifierOrOverloadedOperator IO, SourceLocation NameLoc, QualType ObjectType, - NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName); /// Build a new template name given a template template parameter pack @@ -4012,8 +3990,8 @@ public: SemaRef.Context, TemplateArgument(Pattern.getArgument().getAsTemplate(), NumExpansions), - Pattern.getTemplateQualifierLoc(), Pattern.getTemplateNameLoc(), - EllipsisLoc); + Pattern.getTemplateKWLoc(), Pattern.getTemplateQualifierLoc(), + Pattern.getTemplateNameLoc(), EllipsisLoc); case TemplateArgument::Null: case TemplateArgument::Integral: @@ -4258,23 +4236,29 @@ public: } private: - TypeLoc TransformTypeInObjectScope(TypeLoc TL, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - CXXScopeSpec &SS); + QualType TransformTypeInObjectScope(TypeLocBuilder &TLB, TypeLoc TL, + QualType ObjectType, + NamedDecl *FirstQualifierInScope); TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo, QualType ObjectType, - NamedDecl *FirstQualifierInScope, - CXXScopeSpec &SS); + NamedDecl *FirstQualifierInScope) { + if (getDerived().AlreadyTransformed(TSInfo->getType())) + return TSInfo; - TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType, - NamedDecl *FirstQualifierInScope, - CXXScopeSpec &SS); + TypeLocBuilder TLB; + QualType T = TransformTypeInObjectScope(TLB, TSInfo->getTypeLoc(), + ObjectType, FirstQualifierInScope); + if (T.isNull()) + return nullptr; + return TLB.getTypeSourceInfo(SemaRef.Context, T); + } QualType TransformDependentNameType(TypeLocBuilder &TLB, DependentNameTypeLoc TL, - bool DeducibleTSTContext); + bool DeducibleTSTContext, + QualType ObjectType = QualType(), + NamedDecl *UnqualLookup = nullptr); llvm::SmallVector<OpenACCClause *> TransformOpenACCClauseList(OpenACCDirectiveKind DirKind, @@ -4603,7 +4587,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc( auto insertNNS = [&Qualifiers](NestedNameSpecifierLoc NNS) { for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; - Qualifier = Qualifier.getPrefix()) + Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix) Qualifiers.push_back(Qualifier); }; insertNNS(NNS); @@ -4611,76 +4595,87 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc( CXXScopeSpec SS; while (!Qualifiers.empty()) { NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); - NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier(); - - switch (QNNS->getKind()) { - case NestedNameSpecifier::Identifier: { - Sema::NestedNameSpecInfo IdInfo(QNNS->getAsIdentifier(), - Q.getLocalBeginLoc(), Q.getLocalEndLoc(), - ObjectType); - if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, false, - SS, FirstQualifierInScope, false)) - return NestedNameSpecifierLoc(); - break; - } + NestedNameSpecifier QNNS = Q.getNestedNameSpecifier(); + + switch (QNNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); - case NestedNameSpecifier::Namespace: { + case NestedNameSpecifier::Kind::Namespace: { auto *NS = cast<NamespaceBaseDecl>(getDerived().TransformDecl( - Q.getLocalBeginLoc(), QNNS->getAsNamespace())); + Q.getLocalBeginLoc(), const_cast<NamespaceBaseDecl *>( + QNNS.getAsNamespaceAndPrefix().Namespace))); SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc()); break; } - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: // There is no meaningful transformation that one could perform on the // global scope. SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); break; - case NestedNameSpecifier::Super: { - CXXRecordDecl *RD = - cast_or_null<CXXRecordDecl>(getDerived().TransformDecl( - SourceLocation(), QNNS->getAsRecordDecl())); - SS.MakeSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc()); + case NestedNameSpecifier::Kind::MicrosoftSuper: { + CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>( + getDerived().TransformDecl(SourceLocation(), QNNS.getAsRecordDecl())); + SS.MakeMicrosoftSuper(SemaRef.Context, RD, Q.getBeginLoc(), + Q.getEndLoc()); break; } - case NestedNameSpecifier::TypeSpec: { - TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, - FirstQualifierInScope, SS); - - if (!TL) - return NestedNameSpecifierLoc(); + case NestedNameSpecifier::Kind::Type: { + assert(SS.isEmpty()); + TypeLoc TL = Q.castAsTypeLoc(); + + if (auto DNT = TL.getAs<DependentNameTypeLoc>()) { + NestedNameSpecifierLoc QualifierLoc = DNT.getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc( + QualifierLoc, ObjectType, FirstQualifierInScope); + if (!QualifierLoc) + return NestedNameSpecifierLoc(); + ObjectType = QualType(); + FirstQualifierInScope = nullptr; + } + SS.Adopt(QualifierLoc); + Sema::NestedNameSpecInfo IdInfo( + const_cast<IdentifierInfo *>(DNT.getTypePtr()->getIdentifier()), + DNT.getNameLoc(), Q.getLocalEndLoc(), ObjectType); + if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, + false, SS, + FirstQualifierInScope, false)) + return NestedNameSpecifierLoc(); + return SS.getWithLocInContext(SemaRef.Context); + } QualType T = TL.getType(); + TypeLocBuilder TLB; + if (!getDerived().AlreadyTransformed(T)) { + T = TransformTypeInObjectScope(TLB, TL, ObjectType, + FirstQualifierInScope); + if (T.isNull()) + return NestedNameSpecifierLoc(); + TL = TLB.getTypeLocInContext(SemaRef.Context, T); + } + if (T->isDependentType() || T->isRecordType() || (SemaRef.getLangOpts().CPlusPlus11 && T->isEnumeralType())) { if (T->isEnumeralType()) SemaRef.Diag(TL.getBeginLoc(), diag::warn_cxx98_compat_enum_nested_name_spec); - - if (const auto ETL = TL.getAs<ElaboratedTypeLoc>()) { - SS.Adopt(ETL.getQualifierLoc()); - TL = ETL.getNamedTypeLoc(); - } - - SS.Extend(SemaRef.Context, TL, Q.getLocalEndLoc()); + SS.Make(SemaRef.Context, TL, Q.getLocalEndLoc()); break; } // If the nested-name-specifier is an invalid type def, don't emit an // error because a previous error should have already been emitted. TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>(); - if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) { + if (!TTL || !TTL.getDecl()->isInvalidDecl()) { SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) << T << SS.getRange(); } return NestedNameSpecifierLoc(); } } - - // The qualifier-in-scope and object type only apply to the leftmost entity. - FirstQualifierInScope = nullptr; - ObjectType = QualType(); } // Don't rebuild the nested-name-specifier if we don't have to. @@ -4766,30 +4761,32 @@ template <typename Derived> TemplateName TreeTransform<Derived>::RebuildTemplateName( CXXScopeSpec &SS, SourceLocation TemplateKWLoc, IdentifierOrOverloadedOperator IO, SourceLocation NameLoc, - QualType ObjectType, NamedDecl *FirstQualifierInScope, - bool AllowInjectedClassName) { - if (const IdentifierInfo *II = IO.getIdentifier()) { + QualType ObjectType, bool AllowInjectedClassName) { + if (const IdentifierInfo *II = IO.getIdentifier()) return getDerived().RebuildTemplateName(SS, TemplateKWLoc, *II, NameLoc, - ObjectType, FirstQualifierInScope, - AllowInjectedClassName); - } + ObjectType, AllowInjectedClassName); return getDerived().RebuildTemplateName(SS, TemplateKWLoc, IO.getOperator(), NameLoc, ObjectType, AllowInjectedClassName); } -template<typename Derived> -TemplateName -TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, - TemplateName Name, - SourceLocation NameLoc, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - bool AllowInjectedClassName) { +template <typename Derived> +TemplateName TreeTransform<Derived>::TransformTemplateName( + NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc, + TemplateName Name, SourceLocation NameLoc, QualType ObjectType, + NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) { if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { + // FIXME: Preserve UsingTemplateName. TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl(); assert(Template && "qualified template name must refer to a template"); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc( + QualifierLoc, ObjectType, FirstQualifierInScope); + if (!QualifierLoc) + return TemplateName(); + } + TemplateDecl *TransTemplate = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, Template)); @@ -4797,41 +4794,67 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, return TemplateName(); if (!getDerived().AlwaysRebuild() && - SS.getScopeRep() == QTN->getQualifier() && + QualifierLoc.getNestedNameSpecifier() == QTN->getQualifier() && TransTemplate == Template) return Name; - + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(), TransTemplate); } if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { - if (SS.getScopeRep()) { - // These apply to the scope specifier, not the template. + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc( + QualifierLoc, ObjectType, FirstQualifierInScope); + if (!QualifierLoc) + return TemplateName(); + // The qualifier-in-scope and object type only apply to the leftmost + // entity. ObjectType = QualType(); - FirstQualifierInScope = nullptr; } if (!getDerived().AlwaysRebuild() && - SS.getScopeRep() == DTN->getQualifier() && + QualifierLoc.getNestedNameSpecifier() == DTN->getQualifier() && ObjectType.isNull()) return Name; - // FIXME: Preserve the location of the "template" keyword. - SourceLocation TemplateKWLoc = NameLoc; - return getDerived().RebuildTemplateName( - SS, TemplateKWLoc, DTN->getName(), NameLoc, ObjectType, + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + return getDerived().RebuildTemplateName(SS, TemplateKWLoc, DTN->getName(), + NameLoc, ObjectType, + AllowInjectedClassName); + } + + if (SubstTemplateTemplateParmStorage *S = + Name.getAsSubstTemplateTemplateParm()) { + TemplateName NewName = getDerived().TransformTemplateName( + QualifierLoc, TemplateKWLoc, S->getReplacement(), NameLoc, ObjectType, FirstQualifierInScope, AllowInjectedClassName); + if (NewName.isNull()) + return TemplateName(); + Decl *AssociatedDecl = + getDerived().TransformDecl(NameLoc, S->getAssociatedDecl()); + if (!getDerived().AlwaysRebuild() && NewName == S->getReplacement() && + AssociatedDecl == S->getAssociatedDecl()) + return Name; + return SemaRef.Context.getSubstTemplateTemplateParm( + NewName, AssociatedDecl, S->getIndex(), S->getPackIndex(), + S->getFinal()); } - // FIXME: Try to preserve more of the TemplateName. + assert(!Name.getAsDeducedTemplateName() && + "DeducedTemplateName should not escape partial ordering"); + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + assert(!QualifierLoc && "missed a Qualified Template"); TemplateDecl *TransTemplate = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, Template)); if (!TransTemplate) return TemplateName(); + CXXScopeSpec SS; return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false, TransTemplate); } @@ -4849,8 +4872,10 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, template <typename Derived> TemplateArgument TreeTransform<Derived>::TransformNamedTemplateTemplateArgument( - CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc) { - TemplateName TN = getDerived().TransformTemplateName(SS, Name, NameLoc); + NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKeywordLoc, + TemplateName Name, SourceLocation NameLoc) { + TemplateName TN = getDerived().TransformTemplateName( + QualifierLoc, TemplateKeywordLoc, Name, NameLoc); if (TN.isNull()) return TemplateArgument(); return TemplateArgument(TN); @@ -4932,21 +4957,14 @@ bool TreeTransform<Derived>::TransformTemplateArgument( case TemplateArgument::Template: { NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); - if (QualifierLoc) { - QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); - if (!QualifierLoc) - return true; - } - - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); TemplateArgument Out = getDerived().TransformNamedTemplateTemplateArgument( - SS, Arg.getAsTemplate(), Input.getTemplateNameLoc()); + QualifierLoc, Input.getTemplateKWLoc(), Arg.getAsTemplate(), + Input.getTemplateNameLoc()); if (Out.isNull()) return true; - Output = TemplateArgumentLoc(SemaRef.Context, Out, QualifierLoc, - Input.getTemplateNameLoc()); + Output = TemplateArgumentLoc(SemaRef.Context, Out, Input.getTemplateKWLoc(), + QualifierLoc, Input.getTemplateNameLoc()); return false; } @@ -5380,85 +5398,37 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T, return SemaRef.BuildQualifiedType(T, Loc, Quals); } -template<typename Derived> -TypeLoc -TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, - QualType ObjectType, - NamedDecl *UnqualLookup, - CXXScopeSpec &SS) { - if (getDerived().AlreadyTransformed(TL.getType())) - return TL; - - TypeSourceInfo *TSI = - TransformTSIInObjectScope(TL, ObjectType, UnqualLookup, SS); - if (TSI) - return TSI->getTypeLoc(); - return TypeLoc(); -} - -template<typename Derived> -TypeSourceInfo * -TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, - QualType ObjectType, - NamedDecl *UnqualLookup, - CXXScopeSpec &SS) { - if (getDerived().AlreadyTransformed(TSInfo->getType())) - return TSInfo; - - return TransformTSIInObjectScope(TSInfo->getTypeLoc(), ObjectType, - UnqualLookup, SS); -} - template <typename Derived> -TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope( - TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup, - CXXScopeSpec &SS) { - QualType T = TL.getType(); - assert(!getDerived().AlreadyTransformed(T)); - - TypeLocBuilder TLB; - QualType Result; - - if (isa<TemplateSpecializationType>(T)) { - TemplateSpecializationTypeLoc SpecTL = - TL.castAs<TemplateSpecializationTypeLoc>(); - - TemplateName Template = getDerived().TransformTemplateName( - SS, SpecTL.getTypePtr()->getTemplateName(), SpecTL.getTemplateNameLoc(), - ObjectType, UnqualLookup, /*AllowInjectedClassName*/true); - if (Template.isNull()) - return nullptr; - - Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, - Template); - } else if (isa<DependentTemplateSpecializationType>(T)) { - DependentTemplateSpecializationTypeLoc SpecTL = - TL.castAs<DependentTemplateSpecializationTypeLoc>(); - - const IdentifierInfo *II = SpecTL.getTypePtr() - ->getDependentTemplateName() - .getName() - .getIdentifier(); - TemplateName Template = getDerived().RebuildTemplateName( - SS, SpecTL.getTemplateKeywordLoc(), *II, SpecTL.getTemplateNameLoc(), - ObjectType, UnqualLookup, - /*AllowInjectedClassName*/ true); - if (Template.isNull()) - return nullptr; +QualType TreeTransform<Derived>::TransformTypeInObjectScope( + TypeLocBuilder &TLB, TypeLoc TL, QualType ObjectType, + NamedDecl *UnqualLookup) { + assert(!getDerived().AlreadyTransformed(TL.getType())); - Result = getDerived().TransformDependentTemplateSpecializationType(TLB, - SpecTL, - Template, - SS); - } else { - // Nothing special needs to be done for these. - Result = getDerived().TransformType(TLB, TL); + switch (TL.getTypeLocClass()) { + case TypeLoc::DependentTemplateSpecialization: + return getDerived().TransformDependentTemplateSpecializationType( + TLB, TL.castAs<DependentTemplateSpecializationTypeLoc>(), ObjectType, + UnqualLookup, /*AllowInjectedClassName=*/true); + case TypeLoc::DependentName: { + return getDerived().TransformDependentNameType( + TLB, TL.castAs<DependentNameTypeLoc>(), /*DeducedTSTContext=*/false, + ObjectType, UnqualLookup); + } + case TypeLoc::Typedef: + case TypeLoc::TemplateSpecialization: + case TypeLoc::SubstTemplateTypeParm: + case TypeLoc::PackIndexing: + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + case TypeLoc::TemplateTypeParm: + case TypeLoc::Decltype: + case TypeLoc::UnresolvedUsing: + case TypeLoc::Using: + return getDerived().TransformType(TLB, TL); + default: + llvm_unreachable("unexpected type class"); } - - if (Result.isNull()) - return nullptr; - - return TLB.getTypeSourceInfo(SemaRef.Context, Result); } template <class TyLoc> static inline @@ -6694,23 +6664,38 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType( template <typename Derived> QualType TreeTransform<Derived>::TransformUnresolvedUsingType( TypeLocBuilder &TLB, UnresolvedUsingTypeLoc TL) { + const UnresolvedUsingType *T = TL.getTypePtr(); - Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()); + bool Changed = false; + + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + Changed |= QualifierLoc != OldQualifierLoc; + } + + auto *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()); if (!D) return QualType(); + Changed |= D != T->getDecl(); QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || D != T->getDecl()) { - Result = getDerived().RebuildUnresolvedUsingType(TL.getNameLoc(), D); + if (getDerived().AlwaysRebuild() || Changed) { + Result = getDerived().RebuildUnresolvedUsingType( + T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), TL.getNameLoc(), + D); if (Result.isNull()) return QualType(); } - // We might get an arbitrary type spec type back. We should at - // least always get a type spec type, though. - TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result); - NewTL.setNameLoc(TL.getNameLoc()); - + if (isa<UsingType>(Result)) + TLB.push<UsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); + else + TLB.push<UnresolvedUsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); return Result; } @@ -6718,25 +6703,37 @@ template <typename Derived> QualType TreeTransform<Derived>::TransformUsingType(TypeLocBuilder &TLB, UsingTypeLoc TL) { const UsingType *T = TL.getTypePtr(); + bool Changed = false; + + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + Changed |= QualifierLoc != OldQualifierLoc; + } - auto *Found = cast_or_null<UsingShadowDecl>(getDerived().TransformDecl( - TL.getLocalSourceRange().getBegin(), T->getFoundDecl())); - if (!Found) + auto *D = cast_or_null<UsingShadowDecl>( + getDerived().TransformDecl(TL.getNameLoc(), T->getDecl())); + if (!D) return QualType(); + Changed |= D != T->getDecl(); - QualType Underlying = getDerived().TransformType(T->desugar()); - if (Underlying.isNull()) + QualType UnderlyingType = getDerived().TransformType(T->desugar()); + if (UnderlyingType.isNull()) return QualType(); + Changed |= UnderlyingType != T->desugar(); QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || Found != T->getFoundDecl() || - Underlying != T->getUnderlyingType()) { - Result = getDerived().RebuildUsingType(Found, Underlying); + if (getDerived().AlwaysRebuild() || Changed) { + Result = getDerived().RebuildUsingType( + T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), D, + UnderlyingType); if (Result.isNull()) return QualType(); } - - TLB.pushTypeSpec(Result).setNameLoc(TL.getNameLoc()); + TLB.push<UsingTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), QualifierLoc, + TL.getNameLoc()); return Result; } @@ -6744,23 +6741,34 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { const TypedefType *T = TL.getTypePtr(); - TypedefNameDecl *Typedef - = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); + bool Changed = false; + + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + Changed |= QualifierLoc != OldQualifierLoc; + } + + auto *Typedef = cast_or_null<TypedefNameDecl>( + getDerived().TransformDecl(TL.getNameLoc(), T->getDecl())); if (!Typedef) return QualType(); + Changed |= Typedef != T->getDecl(); + + // FIXME: Transform the UnderlyingType if different from decl. QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - Typedef != T->getDecl()) { - Result = getDerived().RebuildTypedefType(Typedef); + if (getDerived().AlwaysRebuild() || Changed) { + Result = getDerived().RebuildTypedefType( + T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), Typedef); if (Result.isNull()) return QualType(); } - TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); - + TLB.push<TypedefTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); return Result; } @@ -6996,9 +7004,10 @@ QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializationType( TypeLocBuilder &TLB, DeducedTemplateSpecializationTypeLoc TL) { const DeducedTemplateSpecializationType *T = TL.getTypePtr(); - CXXScopeSpec SS; + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); TemplateName TemplateName = getDerived().TransformTemplateName( - SS, T->getTemplateName(), TL.getTemplateNameLoc()); + QualifierLoc, /*TemplateKELoc=*/SourceLocation(), T->getTemplateName(), + TL.getTemplateNameLoc()); if (TemplateName.isNull()) return QualType(); @@ -7011,76 +7020,71 @@ QualType TreeTransform<Derived>::TransformDeducedTemplateSpecializationType( } QualType Result = getDerived().RebuildDeducedTemplateSpecializationType( - TemplateName, NewDeduced); + T->getKeyword(), TemplateName, NewDeduced); if (Result.isNull()) return QualType(); - DeducedTemplateSpecializationTypeLoc NewTL = - TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - + NewTL.setQualifierLoc(QualifierLoc); return Result; } -template<typename Derived> -QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB, - RecordTypeLoc TL) { - const RecordType *T = TL.getTypePtr(); - RecordDecl *Record - = cast_or_null<RecordDecl>(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); - if (!Record) +template <typename Derived> +QualType TreeTransform<Derived>::TransformTagType(TypeLocBuilder &TLB, + TagTypeLoc TL) { + const TagType *T = TL.getTypePtr(); + + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + } + + auto *TD = cast_or_null<TagDecl>( + getDerived().TransformDecl(TL.getNameLoc(), T->getOriginalDecl())); + if (!TD) return QualType(); QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - Record != T->getDecl()) { - Result = getDerived().RebuildRecordType(Record); + if (getDerived().AlwaysRebuild() || QualifierLoc != TL.getQualifierLoc() || + TD != T->getOriginalDecl()) { + if (T->isCanonicalUnqualified()) + Result = getDerived().RebuildCanonicalTagType(TD); + else + Result = getDerived().RebuildTagType( + T->getKeyword(), QualifierLoc.getNestedNameSpecifier(), TD); if (Result.isNull()) return QualType(); } - RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + TagTypeLoc NewTL = TLB.push<TagTypeLoc>(Result); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); NewTL.setNameLoc(TL.getNameLoc()); return Result; } -template<typename Derived> +template <typename Derived> QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB, EnumTypeLoc TL) { - const EnumType *T = TL.getTypePtr(); - EnumDecl *Enum - = cast_or_null<EnumDecl>(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); - if (!Enum) - return QualType(); - - QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - Enum != T->getDecl()) { - Result = getDerived().RebuildEnumType(Enum); - if (Result.isNull()) - return QualType(); - } - - EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); + return getDerived().TransformTagType(TLB, TL); +} - return Result; +template <typename Derived> +QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB, + RecordTypeLoc TL) { + return getDerived().TransformTagType(TLB, TL); } template<typename Derived> QualType TreeTransform<Derived>::TransformInjectedClassNameType( TypeLocBuilder &TLB, InjectedClassNameTypeLoc TL) { - Decl *D = getDerived().TransformDecl(TL.getNameLoc(), - TL.getTypePtr()->getDecl()); - if (!D) return QualType(); - - QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D)); - TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc()); - return T; + return getDerived().TransformTagType(TLB, TL); } template<typename Derived> @@ -7142,24 +7146,6 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType( } template<typename Derived> -QualType TreeTransform<Derived>::TransformTemplateSpecializationType( - TypeLocBuilder &TLB, - TemplateSpecializationTypeLoc TL) { - const TemplateSpecializationType *T = TL.getTypePtr(); - - // The nested-name-specifier never matters in a TemplateSpecializationType, - // because we can't have a dependent nested-name-specifier anyway. - CXXScopeSpec SS; - TemplateName Template - = getDerived().TransformTemplateName(SS, T->getTemplateName(), - TL.getTemplateNameLoc()); - if (Template.isNull()) - return QualType(); - - return getDerived().TransformTemplateSpecializationType(TLB, TL, Template); -} - -template<typename Derived> QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB, AtomicTypeLoc TL) { QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc()); @@ -7398,9 +7384,16 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, template <typename Derived> QualType TreeTransform<Derived>::TransformTemplateSpecializationType( - TypeLocBuilder &TLB, - TemplateSpecializationTypeLoc TL, - TemplateName Template) { + TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL) { + const TemplateSpecializationType *T = TL.getTypePtr(); + + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + TemplateName Template = getDerived().TransformTemplateName( + QualifierLoc, TL.getTemplateKeywordLoc(), T->getTemplateName(), + TL.getTemplateNameLoc()); + if (Template.isNull()) + return QualType(); + TemplateArgumentListInfo NewTemplateArgs; NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); @@ -7415,10 +7408,9 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( // original template changed. If the template changed, and even if the // arguments didn't change, these arguments might not correspond to their // respective parameters, therefore needing conversions. - QualType Result = - getDerived().RebuildTemplateSpecializationType(Template, - TL.getTemplateNameLoc(), - NewTemplateArgs); + QualType Result = getDerived().RebuildTemplateSpecializationType( + TL.getTypePtr()->getKeyword(), Template, TL.getTemplateNameLoc(), + NewTemplateArgs); if (!Result.isNull()) { // Specializations of template template parameters are represented as @@ -7428,8 +7420,8 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( if (isa<DependentTemplateSpecializationType>(Result)) { DependentTemplateSpecializationTypeLoc NewTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); - NewTL.setElaboratedKeywordLoc(SourceLocation()); - NewTL.setQualifierLoc(NestedNameSpecifierLoc()); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); NewTL.setLAngleLoc(TL.getLAngleLoc()); @@ -7438,133 +7430,15 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType( NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); return Result; } - - TemplateSpecializationTypeLoc NewTL - = TLB.push<TemplateSpecializationTypeLoc>(Result); - NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); - NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - NewTL.setLAngleLoc(TL.getLAngleLoc()); - NewTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) - NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + TLB.push<TemplateSpecializationTypeLoc>(Result).set( + TL.getElaboratedKeywordLoc(), QualifierLoc, TL.getTemplateKeywordLoc(), + TL.getTemplateNameLoc(), NewTemplateArgs); } return Result; } template <typename Derived> -QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( - TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL, - TemplateName Template, - CXXScopeSpec &SS) { - TemplateArgumentListInfo NewTemplateArgs; - NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); - NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); - typedef TemplateArgumentLocContainerIterator< - DependentTemplateSpecializationTypeLoc> ArgIterator; - if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), - ArgIterator(TL, TL.getNumArgs()), - NewTemplateArgs)) - return QualType(); - - // FIXME: maybe don't rebuild if all the template arguments are the same. - - if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { - assert(DTN->getQualifier() == SS.getScopeRep()); - QualType Result = getSema().Context.getDependentTemplateSpecializationType( - TL.getTypePtr()->getKeyword(), *DTN, NewTemplateArgs.arguments()); - - DependentTemplateSpecializationTypeLoc NewTL - = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); - NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); - NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); - NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); - NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - NewTL.setLAngleLoc(TL.getLAngleLoc()); - NewTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) - NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); - return Result; - } - - QualType Result - = getDerived().RebuildTemplateSpecializationType(Template, - TL.getTemplateNameLoc(), - NewTemplateArgs); - - if (!Result.isNull()) { - /// FIXME: Wrap this in an elaborated-type-specifier? - TemplateSpecializationTypeLoc NewTL - = TLB.push<TemplateSpecializationTypeLoc>(Result); - NewTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); - NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - NewTL.setLAngleLoc(TL.getLAngleLoc()); - NewTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) - NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); - } - - return Result; -} - -template<typename Derived> -QualType -TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, - ElaboratedTypeLoc TL) { - const ElaboratedType *T = TL.getTypePtr(); - - NestedNameSpecifierLoc QualifierLoc; - // NOTE: the qualifier in an ElaboratedType is optional. - if (TL.getQualifierLoc()) { - QualifierLoc - = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); - if (!QualifierLoc) - return QualType(); - } - - QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); - if (NamedT.isNull()) - return QualType(); - - // C++0x [dcl.type.elab]p2: - // If the identifier resolves to a typedef-name or the simple-template-id - // resolves to an alias template specialization, the - // elaborated-type-specifier is ill-formed. - if (T->getKeyword() != ElaboratedTypeKeyword::None && - T->getKeyword() != ElaboratedTypeKeyword::Typename) { - if (const TemplateSpecializationType *TST = - NamedT->getAs<TemplateSpecializationType>()) { - TemplateName Template = TST->getTemplateName(); - if (TypeAliasTemplateDecl *TAT = dyn_cast_or_null<TypeAliasTemplateDecl>( - Template.getAsTemplateDecl())) { - SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), - diag::err_tag_reference_non_tag) - << TAT << NonTagKind::TypeAliasTemplate - << ElaboratedType::getTagTypeKindForKeyword(T->getKeyword()); - SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); - } - } - } - - QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - QualifierLoc != TL.getQualifierLoc() || - NamedT != T->getNamedType()) { - Result = getDerived().RebuildElaboratedType(TL.getElaboratedKeywordLoc(), - T->getKeyword(), - QualifierLoc, NamedT); - if (Result.isNull()) - return QualType(); - } - - ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); - NewTL.setQualifierLoc(QualifierLoc); - return Result; -} - -template <typename Derived> QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB, AttributedTypeLoc TL) { const AttributedType *oldType = TL.getTypePtr(); @@ -7754,15 +7628,22 @@ QualType TreeTransform<Derived>::TransformDependentNameType( return TransformDependentNameType(TLB, TL, false); } -template<typename Derived> +template <typename Derived> QualType TreeTransform<Derived>::TransformDependentNameType( - TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext) { + TypeLocBuilder &TLB, DependentNameTypeLoc TL, bool DeducedTSTContext, + QualType ObjectType, NamedDecl *UnqualLookup) { const DependentNameType *T = TL.getTypePtr(); - NestedNameSpecifierLoc QualifierLoc - = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); - if (!QualifierLoc) - return QualType(); + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc( + QualifierLoc, ObjectType, UnqualLookup); + if (!QualifierLoc) + return QualType(); + } else { + assert((ObjectType.isNull() && !UnqualLookup) && + "must be transformed by TransformNestedNameSpecifierLoc"); + } QualType Result = getDerived().RebuildDependentNameType(T->getKeyword(), @@ -7774,13 +7655,19 @@ QualType TreeTransform<Derived>::TransformDependentNameType( if (Result.isNull()) return QualType(); - if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { - QualType NamedT = ElabT->getNamedType(); - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - - ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + if (isa<TagType>(Result)) { + auto NewTL = TLB.push<TagTypeLoc>(Result); NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); NewTL.setQualifierLoc(QualifierLoc); + NewTL.setNameLoc(TL.getNameLoc()); + } else if (isa<DeducedTemplateSpecializationType>(Result)) { + auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); + NewTL.setTemplateNameLoc(TL.getNameLoc()); + NewTL.setQualifierLoc(QualifierLoc); + } else if (isa<TypedefType>(Result)) { + TLB.push<TypedefTypeLoc>(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); } else { DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); @@ -7790,33 +7677,34 @@ QualType TreeTransform<Derived>::TransformDependentNameType( return Result; } -template<typename Derived> -QualType TreeTransform<Derived>:: - TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, - DependentTemplateSpecializationTypeLoc TL) { - NestedNameSpecifierLoc QualifierLoc; - if (TL.getQualifierLoc()) { - QualifierLoc - = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); - if (!QualifierLoc) - return QualType(); - } - - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - return getDerived().TransformDependentTemplateSpecializationType(TLB, TL, SS); +template <typename Derived> +QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) { + return getDerived().TransformDependentTemplateSpecializationType( + TLB, TL, QualType(), nullptr, false); } template <typename Derived> QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL, - CXXScopeSpec &SS) { + QualType ObjectType, NamedDecl *UnqualLookup, bool AllowInjectedClassName) { const DependentTemplateSpecializationType *T = TL.getTypePtr(); - TemplateArgumentListInfo NewTemplateArgs; - NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); - NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc( + QualifierLoc, ObjectType, UnqualLookup); + if (!QualifierLoc) + return QualType(); + // These only apply to the leftmost prefix. + ObjectType = QualType(); + UnqualLookup = nullptr; + } + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + TemplateArgumentListInfo NewTemplateArgs(TL.getLAngleLoc(), + TL.getRAngleLoc()); auto ArgsRange = llvm::make_range<TemplateArgumentLocContainerIterator< DependentTemplateSpecializationTypeLoc>>({TL, 0}, {TL, TL.getNumArgs()}); @@ -7833,43 +7721,27 @@ QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || SS.getScopeRep() != DTN.getQualifier() || - TemplateArgumentsChanged) { + TemplateArgumentsChanged || !ObjectType.isNull()) { TemplateName Name = getDerived().RebuildTemplateName( SS, TL.getTemplateKeywordLoc(), DTN.getName(), TL.getTemplateNameLoc(), - /*ObjectType=*/QualType(), /*FirstQualifierInScope=*/nullptr, - /*AllowInjectedClassName=*/false); + ObjectType, AllowInjectedClassName); if (Name.isNull()) return QualType(); Result = getDerived().RebuildDependentTemplateSpecializationType( - T->getKeyword(), SS.getScopeRep(), TL.getTemplateKeywordLoc(), Name, + T->getKeyword(), TL.getTemplateKeywordLoc(), Name, TL.getTemplateNameLoc(), NewTemplateArgs, /*AllowInjectedClassName=*/false); if (Result.isNull()) return QualType(); } - NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(SemaRef.Context); - if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) { - QualType NamedT = ElabT->getNamedType(); - - // Copy information relevant to the template specialization. - TemplateSpecializationTypeLoc NamedTL - = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - NamedTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); - NamedTL.setTemplateNameLoc(TL.getTemplateNameLoc()); - NamedTL.setLAngleLoc(TL.getLAngleLoc()); - NamedTL.setRAngleLoc(TL.getRAngleLoc()); - for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) - NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); - - // Copy information relevant to the elaborated type. - ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); - NewTL.setQualifierLoc(QualifierLoc); + QualifierLoc = SS.getWithLocInContext(SemaRef.Context); + if (isa<TemplateSpecializationType>(Result)) { + TLB.push<TemplateSpecializationTypeLoc>(Result).set( + TL.getElaboratedKeywordLoc(), QualifierLoc, TL.getTemplateKeywordLoc(), + TL.getTemplateNameLoc(), NewTemplateArgs); } else { - assert(isa<DependentTemplateSpecializationType>(Result)); - DependentTemplateSpecializationTypeLoc SpecTL - = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + auto SpecTL = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); SpecTL.setQualifierLoc(QualifierLoc); SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); @@ -8590,14 +8462,18 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { DeclChanged = true; if (LSI) { - if (auto *TD = dyn_cast<TypeDecl>(Transformed)) - LSI->ContainsUnexpandedParameterPack |= - getSema() - .getASTContext() - .getTypeDeclType(TD) - .getSingleStepDesugaredType(getSema().getASTContext()) - ->containsUnexpandedParameterPack(); - + if (auto *TD = dyn_cast<TypeDecl>(Transformed)) { + if (auto *TN = dyn_cast<TypedefNameDecl>(TD)) { + LSI->ContainsUnexpandedParameterPack |= + TN->getUnderlyingType()->containsUnexpandedParameterPack(); + } else { + LSI->ContainsUnexpandedParameterPack |= + getSema() + .getASTContext() + .getTypeDeclType(TD) + ->containsUnexpandedParameterPack(); + } + } if (auto *VD = dyn_cast<VarDecl>(Transformed)) LSI->ContainsUnexpandedParameterPack |= VD->getType()->containsUnexpandedParameterPack(); @@ -11901,8 +11777,11 @@ void OpenACCClauseTransform<Derived>::VisitPrivateClause( if (InitRecipe) InitRecipes.push_back(InitRecipe); else - InitRecipes.push_back(Self.getSema().OpenACC().CreateInitRecipe( - OpenACCClauseKind::Private, VarRef.get())); + InitRecipes.push_back( + Self.getSema() + .OpenACC() + .CreateInitRecipe(OpenACCClauseKind::Private, VarRef.get()) + .first); } } ParsedClause.setVarListDetails(InstantiatedVarList, @@ -11942,7 +11821,7 @@ template <typename Derived> void OpenACCClauseTransform<Derived>::VisitFirstPrivateClause( const OpenACCFirstPrivateClause &C) { llvm::SmallVector<Expr *> InstantiatedVarList; - llvm::SmallVector<VarDecl *> InitRecipes; + llvm::SmallVector<OpenACCFirstPrivateRecipe> InitRecipes; for (const auto [RefExpr, InitRecipe] : llvm::zip(C.getVarList(), C.getInitRecipes())) { @@ -11953,7 +11832,7 @@ void OpenACCClauseTransform<Derived>::VisitFirstPrivateClause( // We only have to create a new one if it is dependent, and Sema won't // make one of these unless the type is non-dependent. - if (InitRecipe) + if (InitRecipe.RecipeDecl) InitRecipes.push_back(InitRecipe); else InitRecipes.push_back(Self.getSema().OpenACC().CreateInitRecipe( @@ -14350,7 +14229,7 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { auto EvalCtx = Sema::ExpressionEvaluationContext::Unevaluated; if (E->isGLValue()) if (auto *RecordT = Op->getType()->getAs<RecordType>()) - if (cast<CXXRecordDecl>(RecordT->getDecl())->isPolymorphic()) + if (cast<CXXRecordDecl>(RecordT->getOriginalDecl())->isPolymorphic()) EvalCtx = SemaRef.ExprEvalContexts.back().Context; EnterExpressionEvaluationContext Unevaluated(SemaRef, EvalCtx, @@ -14590,7 +14469,8 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { QualType ElementType = SemaRef.Context.getBaseElementType(E->getAllocatedType()); if (const RecordType *RecordT = ElementType->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl()); + CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getOriginalDecl()) + ->getDefinitionOrSelf(); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Destructor); } @@ -14660,7 +14540,9 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); + CXXRecordDecl *Record = + cast<CXXRecordDecl>(DestroyedRec->getOriginalDecl()) + ->getDefinitionOrSelf(); SemaRef.MarkFunctionReferenced(E->getBeginLoc(), SemaRef.LookupDestructor(Record)); } @@ -14704,9 +14586,9 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( PseudoDestructorTypeStorage Destroyed; if (E->getDestroyedTypeInfo()) { - TypeSourceInfo *DestroyedTypeInfo - = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), - ObjectType, nullptr, SS); + TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope( + E->getDestroyedTypeInfo(), ObjectType, + /*FirstQualifierInScope=*/nullptr); if (!DestroyedTypeInfo) return ExprError(); Destroyed = DestroyedTypeInfo; @@ -14730,9 +14612,8 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( TypeSourceInfo *ScopeTypeInfo = nullptr; if (E->getScopeTypeInfo()) { - CXXScopeSpec EmptySS; ScopeTypeInfo = getDerived().TransformTypeInObjectScope( - E->getScopeTypeInfo(), ObjectType, nullptr, EmptySS); + E->getScopeTypeInfo(), ObjectType, nullptr); if (!ScopeTypeInfo) return ExprError(); } @@ -15853,10 +15734,6 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // parameters are dependent. DependencyKind = getDerived().ComputeLambdaDependency(&LSICopy); Class->setLambdaDependencyKind(DependencyKind); - // Clean up the type cache created previously. Then, we re-create a type for - // such Decl with the new DependencyKind. - Class->setTypeForDecl(nullptr); - getSema().Context.getTypeDeclType(Class); return getDerived().RebuildLambdaExpr(E->getBeginLoc(), Body.get()->getEndLoc(), &LSICopy); @@ -17359,9 +17236,10 @@ QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) { return SemaRef.Context.getFunctionNoProtoType(T); } -template<typename Derived> -QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, - Decl *D) { +template <typename Derived> +QualType TreeTransform<Derived>::RebuildUnresolvedUsingType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, + SourceLocation NameLoc, Decl *D) { assert(D && "no decl found"); if (D->isInvalidDecl()) return QualType(); @@ -17371,7 +17249,7 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, // UsingDecls, but they must each have exactly one type, and it must be // the same type in every case. But we must have at least one expansion! if (UPD->expansions().empty()) { - getSema().Diag(Loc, diag::err_using_pack_expansion_empty) + getSema().Diag(NameLoc, diag::err_using_pack_expansion_empty) << UPD->isCXXClassMember() << UPD; return QualType(); } @@ -17382,10 +17260,11 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, QualType FallbackT; QualType T; for (auto *E : UPD->expansions()) { - QualType ThisT = RebuildUnresolvedUsingType(Loc, E); + QualType ThisT = + RebuildUnresolvedUsingType(Keyword, Qualifier, NameLoc, E); if (ThisT.isNull()) continue; - else if (ThisT->getAs<UnresolvedUsingType>()) + if (ThisT->getAs<UnresolvedUsingType>()) FallbackT = ThisT; else if (T.isNull()) T = ThisT; @@ -17394,7 +17273,8 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, "mismatched resolved types in using pack expansion"); } return T.isNull() ? FallbackT : T; - } else if (auto *Using = dyn_cast<UsingDecl>(D)) { + } + if (auto *Using = dyn_cast<UsingDecl>(D)) { assert(Using->hasTypename() && "UnresolvedUsingTypenameDecl transformed to non-typename using"); @@ -17402,17 +17282,14 @@ QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, assert(++Using->shadow_begin() == Using->shadow_end()); UsingShadowDecl *Shadow = *Using->shadow_begin(); - if (SemaRef.DiagnoseUseOfDecl(Shadow->getTargetDecl(), Loc)) + if (SemaRef.DiagnoseUseOfDecl(Shadow->getTargetDecl(), NameLoc)) return QualType(); - return SemaRef.Context.getUsingType( - Shadow, SemaRef.Context.getTypeDeclType( - cast<TypeDecl>(Shadow->getTargetDecl()))); - } else { - assert(isa<UnresolvedUsingTypenameDecl>(D) && - "UnresolvedUsingTypenameDecl transformed to non-using decl"); - return SemaRef.Context.getTypeDeclType( - cast<UnresolvedUsingTypenameDecl>(D)); + return SemaRef.Context.getUsingType(Keyword, Qualifier, Shadow); } + assert(isa<UnresolvedUsingTypenameDecl>(D) && + "UnresolvedUsingTypenameDecl transformed to non-using decl"); + return SemaRef.Context.getUnresolvedUsingType( + Keyword, Qualifier, cast<UnresolvedUsingTypenameDecl>(D)); } template <typename Derived> @@ -17448,12 +17325,12 @@ QualType TreeTransform<Derived>::RebuildUnaryTransformType(QualType BaseType, return SemaRef.BuildUnaryTransformType(BaseType, UKind, Loc); } -template<typename Derived> +template <typename Derived> QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( - TemplateName Template, - SourceLocation TemplateNameLoc, - TemplateArgumentListInfo &TemplateArgs) { - return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + ElaboratedTypeKeyword Keyword, TemplateName Template, + SourceLocation TemplateNameLoc, TemplateArgumentListInfo &TemplateArgs) { + return SemaRef.CheckTemplateIdType(Keyword, Template, TemplateNameLoc, + TemplateArgs); } template<typename Derived> @@ -17496,15 +17373,10 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, TemplateName(Template)); } -template<typename Derived> -TemplateName -TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const IdentifierInfo &Name, - SourceLocation NameLoc, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - bool AllowInjectedClassName) { +template <typename Derived> +TemplateName TreeTransform<Derived>::RebuildTemplateName( + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const IdentifierInfo &Name, + SourceLocation NameLoc, QualType ObjectType, bool AllowInjectedClassName) { UnqualifiedId TemplateName; TemplateName.setIdentifier(&Name, NameLoc); Sema::TemplateTy Template; @@ -17646,15 +17518,16 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, NameInfo.setNamedTypeInfo(DestroyedType); // The scope type is now known to be a valid nested name specifier - // component. Tack it on to the end of the nested name specifier. + // component. Tack it on to the nested name specifier. if (ScopeType) { - if (!ScopeType->getType()->getAs<TagType>()) { + if (!isa<TagType>(ScopeType->getType().getCanonicalType())) { getSema().Diag(ScopeType->getTypeLoc().getBeginLoc(), diag::err_expected_class_or_namespace) << ScopeType->getType() << getSema().getLangOpts().CPlusPlus; return ExprError(); } - SS.Extend(SemaRef.Context, ScopeType->getTypeLoc(), CCLoc); + SS.clear(); + SS.Make(SemaRef.Context, ScopeType->getTypeLoc(), CCLoc); } SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller. diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h index 580d702..ad475ab 100644 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ b/clang/lib/Sema/UsedDeclVisitor.h @@ -71,9 +71,10 @@ public: if (!DestroyedOrNull.isNull()) { QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); - if (Record->getDefinition()) - asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); + CXXRecordDecl *Record = + cast<CXXRecordDecl>(DestroyedRec->getOriginalDecl()); + if (auto *Def = Record->getDefinition()) + asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Def)); } } |