diff --git a/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp index 3e367ab1a5558..471ca45fb5a53 100644 --- a/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp +++ b/clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp @@ -31,24 +31,9 @@ llvm::SmallVector splitSymbolName(llvm::StringRef Name) { return Splitted; } -SourceLocation startLocationForType(TypeLoc TLoc) { - // For elaborated types (e.g. `struct a::A`) we want the portion after the - // `struct` but including the namespace qualifier, `a::`. - if (TLoc.getTypeLocClass() == TypeLoc::Elaborated) { - NestedNameSpecifierLoc NestedNameSpecifier = - TLoc.castAs().getQualifierLoc(); - if (NestedNameSpecifier.getNestedNameSpecifier()) - return NestedNameSpecifier.getBeginLoc(); - TLoc = TLoc.getNextTypeLoc(); - } - return TLoc.getBeginLoc(); -} - SourceLocation endLocationForType(TypeLoc TLoc) { - // Dig past any namespace or keyword qualifications. - while (TLoc.getTypeLocClass() == TypeLoc::Elaborated || - TLoc.getTypeLocClass() == TypeLoc::Qualified) - TLoc = TLoc.getNextTypeLoc(); + if (auto QTL = TLoc.getAs()) + TLoc = QTL.getUnqualifiedLoc(); // The location for template specializations (e.g. Foo) includes the // templated types in its location range. We want to restrict this to just @@ -550,8 +535,8 @@ void ChangeNamespaceTool::run( Result.Nodes.getNodeAs( "nested_specifier_loc")) { SourceLocation Start = Specifier->getBeginLoc(); - SourceLocation End = endLocationForType(Specifier->getTypeLoc()); - fixTypeLoc(Result, Start, End, Specifier->getTypeLoc()); + SourceLocation End = endLocationForType(Specifier->castAsTypeLoc()); + fixTypeLoc(Result, Start, End, Specifier->castAsTypeLoc()); } else if (const auto *BaseInitializer = Result.Nodes.getNodeAs( "base_initializer")) { @@ -562,19 +547,16 @@ void ChangeNamespaceTool::run( // filtered by matchers in some cases, e.g. the type is templated. We should // handle the record type qualifier instead. TypeLoc Loc = *TLoc; - while (Loc.getTypeLocClass() == TypeLoc::Qualified) - Loc = Loc.getNextTypeLoc(); - if (Loc.getTypeLocClass() == TypeLoc::Elaborated) { - NestedNameSpecifierLoc NestedNameSpecifier = - Loc.castAs().getQualifierLoc(); - // FIXME: avoid changing injected class names. - if (auto *NNS = NestedNameSpecifier.getNestedNameSpecifier()) { - const Type *SpecifierType = NNS->getAsType(); - if (SpecifierType && SpecifierType->isRecordType()) - return; - } - } - fixTypeLoc(Result, startLocationForType(Loc), endLocationForType(Loc), Loc); + if (auto QTL = Loc.getAs()) + Loc = QTL.getUnqualifiedLoc(); + // FIXME: avoid changing injected class names. + if (NestedNameSpecifier NestedNameSpecifier = + Loc.getPrefix().getNestedNameSpecifier(); + NestedNameSpecifier.getKind() == NestedNameSpecifier::Kind::Type && + NestedNameSpecifier.getAsType()->isRecordType()) + return; + fixTypeLoc(Result, Loc.getNonElaboratedBeginLoc(), endLocationForType(Loc), + Loc); } else if (const auto *VarRef = Result.Nodes.getNodeAs("var_ref")) { const auto *Var = Result.Nodes.getNodeAs("var_decl"); @@ -588,10 +570,9 @@ void ChangeNamespaceTool::run( } else if (const auto *EnumConstRef = Result.Nodes.getNodeAs("enum_const_ref")) { // Do not rename the reference if it is already scoped by the EnumDecl name. - if (EnumConstRef->hasQualifier() && - EnumConstRef->getQualifier()->getKind() == - NestedNameSpecifier::SpecifierKind::TypeSpec && - EnumConstRef->getQualifier()->getAsType()->isEnumeralType()) + if (NestedNameSpecifier Qualifier = EnumConstRef->getQualifier(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Type && + Qualifier.getAsType()->isEnumeralType()) return; const auto *EnumConstDecl = Result.Nodes.getNodeAs("enum_const_decl"); diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index de73f68b09386..bcab4f1b8a729 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -902,8 +902,8 @@ parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir, return; for (const CXXBaseSpecifier &B : D->bases()) { if (const RecordType *Ty = B.getType()->getAs()) { - if (const CXXRecordDecl *Base = - cast_or_null(Ty->getDecl()->getDefinition())) { + if (const CXXRecordDecl *Base = cast_or_null( + Ty->getOriginalDecl()->getDefinition())) { // Initialized without USR and name, this will be set in the following // if-else stmt. BaseRecordInfo BI( diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp index bb48883f88815..1f30d27c0a54f 100644 --- a/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp +++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/FindAllSymbols.cpp @@ -216,8 +216,7 @@ void FindAllSymbols::registerMatchers(MatchFinder *MatchFinder) { // Uses of most types: just look at what the typeLoc refers to. MatchFinder->addMatcher( typeLoc(isExpansionInMainFile(), - loc(qualType(allOf(unless(elaboratedType()), - hasDeclaration(Types.bind("use")))))), + loc(qualType(hasDeclaration(Types.bind("use"))))), this); // Uses of typedefs: these are often transparent to hasDeclaration, so we need // to handle them explicitly. diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index f9d75978d0ea8..fac6e0418d163 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -533,7 +533,8 @@ void ClangTidyDiagnosticConsumer::forwardDiagnostic(const Diagnostic &Info) { Builder << reinterpret_cast(Info.getRawArg(Index)); break; case clang::DiagnosticsEngine::ak_nestednamespec: - Builder << reinterpret_cast(Info.getRawArg(Index)); + Builder << NestedNameSpecifier::getFromVoidPointer( + reinterpret_cast(Info.getRawArg(Index))); break; case clang::DiagnosticsEngine::ak_declcontext: Builder << reinterpret_cast(Info.getRawArg(Index)); diff --git a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp index 6565fa3f7c85b..0625468d9da88 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp @@ -43,7 +43,8 @@ static bool isDerivedClassBefriended(const CXXRecordDecl *CRTP, return false; } - return FriendType->getType()->getAsCXXRecordDecl() == Derived; + return declaresSameEntity(FriendType->getType()->getAsCXXRecordDecl(), + Derived); }); } @@ -55,7 +56,8 @@ getDerivedParameter(const ClassTemplateSpecializationDecl *CRTP, CRTP->getTemplateArgs().asArray(), [&](const TemplateArgument &Arg) { ++Idx; return Arg.getKind() == TemplateArgument::Type && - Arg.getAsType()->getAsCXXRecordDecl() == Derived; + declaresSameEntity(Arg.getAsType()->getAsCXXRecordDecl(), + Derived); }); return AnyOf ? CRTP->getSpecializedTemplate() diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp index a179d4bf66b4d..3cacb90cace52 100644 --- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp @@ -577,7 +577,7 @@ approximateImplicitConversion(const TheCheck &Check, QualType LType, ImplicitConversionModellingMode ImplicitMode); static inline bool isUselessSugar(const Type *T) { - return isa(T); + return isa(T); } namespace { @@ -1040,7 +1040,9 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, const auto *ToRecord = To->getAsCXXRecordDecl(); if (isDerivedToBase(FromRecord, ToRecord)) { LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n"); - WorkType = QualType{ToRecord->getTypeForDecl(), FastQualifiersToApply}; + WorkType = QualType{ + ToRecord->getASTContext().getCanonicalTagType(ToRecord)->getTypePtr(), + FastQualifiersToApply}; } if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) { @@ -1072,9 +1074,9 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, WorkType = To; } - if (WorkType == To) { + if (Ctx.hasSameType(WorkType, To)) { LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Reached 'To' type.\n"); - return {WorkType}; + return {Ctx.getCommonSugaredType(WorkType, To)}; } LLVM_DEBUG(llvm::dbgs() << "<<< approximateStdConv. Did not reach 'To'.\n"); @@ -1219,7 +1221,7 @@ tryConversionOperators(const TheCheck &Check, const CXXRecordDecl *RD, if (std::optional SelectedConversion = ConversionSet()) { - QualType RecordType{RD->getTypeForDecl(), 0}; + CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); ConversionSequence Result{RecordType, ToType}; // The conversion from the operator call's return type to ToType was @@ -1270,7 +1272,7 @@ tryConvertingConstructors(const TheCheck &Check, QualType FromType, if (std::optional SelectedConversion = ConversionSet()) { - QualType RecordType{RD->getTypeForDecl(), 0}; + CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); ConversionSequence Result{FromType, RecordType}; Result.AfterFirstStandard = SelectedConversion->Seq.AfterFirstStandard; diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp index 75ef628436738..070ed04efffc4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp @@ -69,10 +69,9 @@ void ForwardDeclarationNamespaceCheck::check( // struct B { friend A; }; // \endcode // `A` will not be marked as "referenced" in the AST. - if (const TypeSourceInfo *Tsi = Decl->getFriendType()) { - QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context); - FriendTypes.insert(Desugared.getTypePtr()); - } + if (const TypeSourceInfo *Tsi = Decl->getFriendType()) + FriendTypes.insert( + Tsi->getType()->getCanonicalTypeUnqualified().getTypePtr()); } } @@ -119,7 +118,9 @@ void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() { if (CurDecl->hasDefinition() || CurDecl->isReferenced()) { continue; // Skip forward declarations that are used/referenced. } - if (FriendTypes.contains(CurDecl->getTypeForDecl())) { + if (FriendTypes.contains(CurDecl->getASTContext() + .getCanonicalTagType(CurDecl) + ->getTypePtr())) { continue; // Skip forward declarations referenced as friend. } if (CurDecl->getLocation().isMacroID() || diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index 00e8f7e514368..10b747e17e2ad 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -33,21 +33,17 @@ AST_MATCHER(QualType, isEnableIf) { BaseType = BaseType->getPointeeType().getTypePtr(); } // Case: type parameter dependent (enable_if>). - if (const auto *Dependent = BaseType->getAs()) { - BaseType = Dependent->getQualifier()->getAsType(); - } + if (const auto *Dependent = BaseType->getAs()) + BaseType = Dependent->getQualifier().getAsType(); if (!BaseType) return false; if (CheckTemplate(BaseType->getAs())) return true; // Case: enable_if_t< >. - if (const auto *Elaborated = BaseType->getAs()) { - if (const auto *Q = Elaborated->getQualifier()) - if (const auto *Qualifier = Q->getAsType()) { - if (CheckTemplate(Qualifier->getAs())) { - return true; // Case: enable_if< >::type. - } - } - } + if (const auto *TT = BaseType->getAs()) + if (NestedNameSpecifier Q = TT->getQualifier(); + Q.getKind() == NestedNameSpecifier::Kind::Type) + if (CheckTemplate(Q.getAsType()->getAs())) + return true; // Case: enable_if< >::type. return false; } AST_MATCHER_P(TemplateTypeParmDecl, hasDefaultArgument, diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp index 75f1107904fce..07cd90d64c2a4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp @@ -32,13 +32,10 @@ AST_MATCHER_P(TemplateTypeParmDecl, hasUnnamedDefaultArgument, void IncorrectEnableIfCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( templateTypeParmDecl( - hasUnnamedDefaultArgument( - elaboratedTypeLoc( - hasNamedTypeLoc(templateSpecializationTypeLoc( - loc(qualType(hasDeclaration(namedDecl( - hasName("::std::enable_if")))))) - .bind("enable_if_specialization"))) - .bind("elaborated"))) + hasUnnamedDefaultArgument(templateSpecializationTypeLoc( + loc(qualType(hasDeclaration(namedDecl( + hasName("::std::enable_if")))))) + .bind("enable_if_specialization"))) .bind("enable_if"), this); } @@ -46,13 +43,11 @@ void IncorrectEnableIfCheck::registerMatchers(MatchFinder *Finder) { void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) { const auto *EnableIf = Result.Nodes.getNodeAs("enable_if"); - const auto *ElaboratedLoc = - Result.Nodes.getNodeAs("elaborated"); const auto *EnableIfSpecializationLoc = Result.Nodes.getNodeAs( "enable_if_specialization"); - if (!EnableIf || !ElaboratedLoc || !EnableIfSpecializationLoc) + if (!EnableIf || !EnableIfSpecializationLoc) return; const SourceManager &SM = *Result.SourceManager; @@ -62,8 +57,10 @@ void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) { auto Diag = diag(EnableIf->getBeginLoc(), "incorrect std::enable_if usage detected; use " "'typename std::enable_if<...>::type'"); + // FIXME: This should handle the enable_if specialization already having an + // elaborated keyword. if (!getLangOpts().CPlusPlus20) { - Diag << FixItHint::CreateInsertion(ElaboratedLoc->getBeginLoc(), + Diag << FixItHint::CreateInsertion(EnableIfSpecializationLoc->getBeginLoc(), "typename "); } Diag << FixItHint::CreateInsertion(RAngleLoc.getLocWithOffset(1), "::type"); diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp index f903e631e0be0..7d92ef301aec3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp @@ -67,15 +67,15 @@ class FindEnumMember : public TypeVisitor { return Visit(T->getElementType().getTypePtr()); } bool VisitEnumType(const EnumType *T) { - if (isCompleteAndHasNoZeroValue(T->getDecl())) { + if (isCompleteAndHasNoZeroValue(T->getOriginalDecl())) { FoundEnum = T; return true; } return false; } bool VisitRecordType(const RecordType *T) { - const RecordDecl *RD = T->getDecl(); - if (RD->isUnion()) + const RecordDecl *RD = T->getOriginalDecl()->getDefinition(); + if (!RD || RD->isUnion()) return false; auto VisitField = [this](const FieldDecl *F) { return Visit(F->getType().getTypePtr()); @@ -125,7 +125,7 @@ void InvalidEnumDefaultInitializationCheck::check( if (!Finder.Visit(InitList->getArrayFiller()->getType().getTypePtr())) return; InitExpr = InitList; - Enum = Finder.FoundEnum->getDecl(); + Enum = Finder.FoundEnum->getOriginalDecl(); } if (!InitExpr || !Enum) diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp index bfa2ab51a6d03..5dc988d6662df 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp @@ -39,24 +39,31 @@ static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee, // std::move(). This will hopefully prevent erroneous replacements if the // code does unusual things (e.g. create an alias for std::move() in // another namespace). - NestedNameSpecifier *NNS = Callee->getQualifier(); - if (!NNS) { + NestedNameSpecifier NNS = Callee->getQualifier(); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Null: // Called as "move" (i.e. presumably the code had a "using std::move;"). // We still conservatively put a "std::" in front of the forward because // we don't know whether the code also had a "using std::forward;". Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName); - } else if (const NamespaceBaseDecl *Namespace = NNS->getAsNamespace()) { + break; + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix(); if (Namespace->getName() == "std") { - if (!NNS->getPrefix()) { + if (!Prefix) { // Called as "std::move". Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName); - } else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) { + } else if (Prefix.getKind() == NestedNameSpecifier::Kind::Global) { // Called as "::std::move". Diag << FixItHint::CreateReplacement(CallRange, "::std::" + ForwardName); } } + break; + } + default: + return; } } } diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp index 88e048e65d4e8..8da6227e172cd 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp @@ -425,7 +425,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { "suspicious usage of 'sizeof(array)/sizeof(...)';" " denominator differs from the size of array elements") << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); - } else if (NumTy && DenomTy && NumTy == DenomTy && + } else if (NumTy && DenomTy && Ctx.hasSameType(NumTy, DenomTy) && !NumTy->isDependentType()) { // Dependent type should not be compared. diag(E->getOperatorLoc(), @@ -434,7 +434,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } else if (!WarnOnSizeOfPointer) { // When 'WarnOnSizeOfPointer' is enabled, these messages become redundant: - if (PointedTy && DenomTy && PointedTy == DenomTy) { + if (PointedTy && DenomTy && Ctx.hasSameType(PointedTy, DenomTy)) { diag(E->getOperatorLoc(), "suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer " "is divided by size of pointed type") @@ -463,7 +463,8 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { const auto *SizeOfExpr = Result.Nodes.getNodeAs("sizeof-ptr-mul-expr"); - if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) { + if (Ctx.hasSameType(LPtrTy, RPtrTy) && + Ctx.hasSameType(LPtrTy, SizeofArgTy)) { diag(SizeOfExpr->getBeginLoc(), "suspicious usage of 'sizeof(...)' in " "pointer arithmetic") << SizeOfExpr->getSourceRange() << E->getOperatorLoc() @@ -477,7 +478,8 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { const auto *SizeOfExpr = Result.Nodes.getNodeAs("sizeof-ptr-div-expr"); - if ((LPtrTy == RPtrTy) && (LPtrTy == SizeofArgTy)) { + if (Ctx.hasSameType(LPtrTy, RPtrTy) && + Ctx.hasSameType(LPtrTy, SizeofArgTy)) { diag(SizeOfExpr->getBeginLoc(), "suspicious usage of 'sizeof(...)' in " "pointer arithmetic") << SizeOfExpr->getSourceRange() << E->getOperatorLoc() diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp index ca293178c78b4..29470b1f725fb 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp @@ -23,9 +23,9 @@ void NoSuspendWithLockCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void NoSuspendWithLockCheck::registerMatchers(MatchFinder *Finder) { - auto LockType = elaboratedType(namesType(templateSpecializationType( + auto LockType = templateSpecializationType( hasDeclaration(namedDecl(matchers::matchesAnyListedName( - utils::options::parseStringList(LockGuards))))))); + utils::options::parseStringList(LockGuards))))); StatementMatcher Lock = declStmt(has(varDecl(hasType(LockType)).bind("lock-decl"))) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index b413b12cd37ab..40607597297b5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -190,7 +190,7 @@ struct InitializerInsertion { // Convenience utility to get a RecordDecl from a QualType. const RecordDecl *getCanonicalRecordDecl(const QualType &Type) { if (const auto *RT = Type.getCanonicalType()->getAs()) - return RT->getDecl(); + return RT->getOriginalDecl(); return nullptr; } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp index 76754394de760..40fd15c08f0a1 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp @@ -92,7 +92,7 @@ void SlicingCheck::diagnoseSlicedOverriddenMethods( for (const auto &Base : DerivedDecl.bases()) { if (const auto *BaseRecordType = Base.getType()->getAs()) { if (const auto *BaseRecord = cast_or_null( - BaseRecordType->getDecl()->getDefinition())) + BaseRecordType->getOriginalDecl()->getDefinition())) diagnoseSlicedOverriddenMethods(Call, *BaseRecord, BaseDecl); } } diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp index 80ff97a762134..0302a5ad4957c 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp @@ -74,7 +74,7 @@ bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) { const auto *Ty = I.getType()->getAs(); if (!Ty) continue; - const RecordDecl *D = Ty->getDecl()->getDefinition(); + const RecordDecl *D = Ty->getOriginalDecl()->getDefinition(); if (!D) continue; const auto *Base = cast(D); @@ -106,7 +106,8 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { const auto *Ty = I.getType()->getAs(); if (!Ty) continue; - const auto *Base = cast(Ty->getDecl()->getDefinition()); + const auto *Base = + cast(Ty->getOriginalDecl()->getDefinition()); if (!isInterface(Base)) NumConcrete++; } @@ -117,7 +118,8 @@ void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { const auto *Ty = V.getType()->getAs(); if (!Ty) continue; - const auto *Base = cast(Ty->getDecl()->getDefinition()); + const auto *Base = + cast(Ty->getOriginalDecl()->getDefinition()); if (!isInterface(Base)) NumConcrete++; } diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp index e076b39b5d978..14e11eb0bc697 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp @@ -89,6 +89,30 @@ static StringRef getDestTypeString(const SourceManager &SM, SM, LangOpts); } +static bool sameTypeAsWritten(QualType X, QualType Y) { + if (X.getCanonicalType() != Y.getCanonicalType()) + return false; + + auto TC = X->getTypeClass(); + if (TC != Y->getTypeClass()) + return false; + + switch (TC) { + case Type::Typedef: + return declaresSameEntity(cast(X)->getDecl(), + cast(Y)->getDecl()); + case Type::Pointer: + return sameTypeAsWritten(cast(X)->getPointeeType(), + cast(Y)->getPointeeType()); + case Type::RValueReference: + case Type::LValueReference: + return sameTypeAsWritten(cast(X)->getPointeeType(), + cast(Y)->getPointeeType()); + default: + return true; + } +} + void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { const auto *CastExpr = Result.Nodes.getNodeAs("cast"); @@ -128,12 +152,7 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { // case of overloaded functions, so detection of redundant casts is trickier // in this case. Don't emit "redundant cast" warnings for function // pointer/reference types. - QualType Src = SourceTypeAsWritten, Dst = DestTypeAsWritten; - if (const auto *ElTy = dyn_cast(Src)) - Src = ElTy->getNamedType(); - if (const auto *ElTy = dyn_cast(Dst)) - Dst = ElTy->getNamedType(); - if (Src == Dst) { + if (sameTypeAsWritten(SourceTypeAsWritten, DestTypeAsWritten)) { diag(CastExpr->getBeginLoc(), "redundant cast to the same type") << FixItHint::CreateRemoval(ReplaceRange); return; diff --git a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp index 3deea0620514b..68233ec6bd441 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp @@ -72,7 +72,7 @@ static bool isStdInitializerList(QualType Type) { } if (const auto *RT = Type->getAs()) { if (const auto *Specialization = - dyn_cast(RT->getDecl())) + dyn_cast(RT->getOriginalDecl())) return declIsStdInitializerList(Specialization->getSpecializedTemplate()); } return false; diff --git a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp index 805dcaf3ce402..274b8afa98bd6 100644 --- a/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp @@ -257,8 +257,13 @@ getAliasNameRange(const MatchFinder::MatchResult &Result) { return CharSourceRange::getTokenRange( Using->getNameInfo().getSourceRange()); } - return CharSourceRange::getTokenRange( - Result.Nodes.getNodeAs("typeloc")->getSourceRange()); + TypeLoc TL = *Result.Nodes.getNodeAs("typeloc"); + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); + + if (auto TTL = TL.getAs()) + return CharSourceRange::getTokenRange(TTL.getNameLoc()); + return CharSourceRange::getTokenRange(TL.castAs().getNameLoc()); } void UpgradeGoogletestCaseCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index 697398a54332d..b32507d66cbac 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -98,11 +98,12 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) { hasType(referenceType(pointee(hasCanonicalType(templateTypeParmType())))), hasType(referenceType(pointee(substTemplateTypeParmType())))); - const auto AllowedType = hasType(qualType(anyOf( - hasDeclaration(namedDecl(matchers::matchesAnyListedName(AllowedTypes))), - references(namedDecl(matchers::matchesAnyListedName(AllowedTypes))), - pointerType(pointee(hasDeclaration( - namedDecl(matchers::matchesAnyListedName(AllowedTypes)))))))); + auto AllowedTypeDecl = namedDecl( + anyOf(matchers::matchesAnyListedName(AllowedTypes), usingShadowDecl())); + + const auto AllowedType = hasType(qualType( + anyOf(hasDeclaration(AllowedTypeDecl), references(AllowedTypeDecl), + pointerType(pointee(hasDeclaration(AllowedTypeDecl)))))); const auto AutoTemplateType = varDecl( anyOf(hasType(autoType()), hasType(referenceType(pointee(autoType()))), diff --git a/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp b/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp index 0cdd48c13b2a6..bb64a5618620c 100644 --- a/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/MisplacedConstCheck.cpp @@ -19,13 +19,13 @@ void MisplacedConstCheck::registerMatchers(MatchFinder *Finder) { pointee(anyOf(isConstQualified(), ignoringParens(functionType())))))); Finder->addMatcher( - valueDecl(hasType(qualType( - isConstQualified(), - elaboratedType(namesType(typedefType(hasDeclaration( - anyOf(typedefDecl(NonConstAndNonFunctionPointerType) - .bind("typedef"), - typeAliasDecl(NonConstAndNonFunctionPointerType) - .bind("typeAlias"))))))))) + valueDecl( + hasType(qualType(isConstQualified(), + typedefType(hasDeclaration(anyOf( + typedefDecl(NonConstAndNonFunctionPointerType) + .bind("typedef"), + typeAliasDecl(NonConstAndNonFunctionPointerType) + .bind("typeAlias"))))))) .bind("decl"), this); } diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index 9b2af2a8ca7d8..107eda2e98f27 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -45,14 +45,6 @@ static bool incrementWithoutOverflow(const APSInt &Value, APSInt &Result) { return Value < Result; } -static bool areEquivalentNameSpecifier(const NestedNameSpecifier *Left, - const NestedNameSpecifier *Right) { - llvm::FoldingSetNodeID LeftID, RightID; - Left->Profile(LeftID); - Right->Profile(RightID); - return LeftID == RightID; -} - static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { if (!Left || !Right) return !Left && !Right; @@ -104,9 +96,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { if (cast(Left)->getDeclName() != cast(Right)->getDeclName()) return false; - return areEquivalentNameSpecifier( - cast(Left)->getQualifier(), - cast(Right)->getQualifier()); + return cast(Left)->getQualifier() == + cast(Right)->getQualifier(); case Stmt::DeclRefExprClass: return cast(Left)->getDecl() == cast(Right)->getDecl(); diff --git a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp index 86992cd8a141b..4fa679aa8dd88 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedAliasDeclsCheck.cpp @@ -35,12 +35,12 @@ void UnusedAliasDeclsCheck::check(const MatchFinder::MatchResult &Result) { } if (const auto *NestedName = - Result.Nodes.getNodeAs("nns")) { - if (const auto *AliasDecl = dyn_cast_if_present( - NestedName->getAsNamespace())) { + Result.Nodes.getNodeAs("nns"); + NestedName && + NestedName->getKind() == NestedNameSpecifier::Kind::Namespace) + if (const auto *AliasDecl = dyn_cast( + NestedName->getAsNamespaceAndPrefix().Namespace)) FoundDecls[AliasDecl] = CharSourceRange(); - } - } } void UnusedAliasDeclsCheck::onEndOfTranslationUnit() { diff --git a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp index d5c5fa3364d63..8211a0ec6a5e1 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp @@ -71,11 +71,7 @@ void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) { templateArgument().bind("used")))), this); Finder->addMatcher(userDefinedLiteral().bind("used"), this); - Finder->addMatcher( - loc(elaboratedType(unless(hasQualifier(nestedNameSpecifier())), - hasUnqualifiedDesugaredType( - type(asTagDecl(tagDecl().bind("used")))))), - this); + Finder->addMatcher(loc(asTagDecl(tagDecl().bind("used"))), this); // Cases where we can identify the UsingShadowDecl directly, rather than // just its target. // FIXME: cover more cases in this way, as the AST supports it. @@ -136,7 +132,7 @@ void UnusedUsingDeclsCheck::check(const MatchFinder::MatchResult &Result) { } if (const auto *ECD = dyn_cast(Used)) { if (const auto *ET = ECD->getType()->getAs()) - removeFromFoundDecls(ET->getDecl()); + removeFromFoundDecls(ET->getOriginalDecl()); } }; // We rely on the fact that the clang AST is walked in order, usages are only diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp index f22f48d831608..2aca61021166d 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp @@ -29,8 +29,7 @@ static std::optional getReplacementType(StringRef Type) { void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) { auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl"); - auto IoStateType = - qualType(hasDeclaration(IoStateDecl), unless(elaboratedType())); + auto IoStateType = typedefType(hasDeclaration(IoStateDecl)); Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this); } @@ -43,12 +42,14 @@ void DeprecatedIosBaseAliasesCheck::check( StringRef TypeName = Typedef->getName(); auto Replacement = getReplacementType(TypeName); - const auto *TL = Result.Nodes.getNodeAs("TypeLoc"); - SourceLocation IoStateLoc = TL->getBeginLoc(); + TypeLoc TL = *Result.Nodes.getNodeAs("TypeLoc"); + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); + SourceLocation IoStateLoc = TL.castAs().getNameLoc(); // Do not generate fixits for matches depending on template arguments and // macro expansions. - bool Fix = Replacement && !TL->getType()->isDependentType(); + bool Fix = Replacement && !TL.getType()->isDependentType(); if (IoStateLoc.isMacroID()) { IoStateLoc = SM.getSpellingLoc(IoStateLoc); Fix = false; diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp index 1e271dfa768ce..a54d0721a5b7d 100644 --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -77,8 +77,7 @@ AST_MATCHER_P(CXXRecordDecl, isMoveConstructibleInBoundCXXRecordDecl, StringRef, static TypeMatcher notTemplateSpecConstRefType() { return lValueReferenceType( - pointee(unless(elaboratedType(namesType(templateSpecializationType()))), - isConstQualified())); + pointee(unless(templateSpecializationType()), isConstQualified())); } static TypeMatcher nonConstValueType() { diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp index 1ad31d315dc2a..f2142b810a126 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -48,7 +48,7 @@ void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { auto AutoPtrDecl = recordDecl(hasName("auto_ptr"), isInStdNamespace()); - auto AutoPtrType = qualType(hasDeclaration(AutoPtrDecl)); + auto AutoPtrType = hasCanonicalType(recordType(hasDeclaration(AutoPtrDecl))); // std::auto_ptr a; // ^~~~~~~~~~~~~ @@ -58,11 +58,7 @@ void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { // // std::auto_ptr fn(std::auto_ptr); // ^~~~~~~~~~~~~ ^~~~~~~~~~~~~ - Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType, - // Skip elaboratedType() as the named - // type will match soon thereafter. - unless(elaboratedType())))) - .bind(AutoPtrTokenId), + Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType))).bind(AutoPtrTokenId), this); // using std::auto_ptr; @@ -118,10 +114,13 @@ void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) { } SourceLocation AutoPtrLoc; - if (const auto *TL = Result.Nodes.getNodeAs(AutoPtrTokenId)) { + if (const auto *PTL = Result.Nodes.getNodeAs(AutoPtrTokenId)) { + auto TL = *PTL; + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); // std::auto_ptr i; // ^ - if (auto Loc = TL->getAs()) + if (auto Loc = TL.getAs()) AutoPtrLoc = Loc.getTemplateNameLoc(); } else if (const auto *D = Result.Nodes.getNodeAs(AutoPtrTokenId)) { diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index ff0b3213cb58f..de2d42d760550 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -168,19 +168,6 @@ static DeclarationName getName(const DeclRefExpr &D) { return D.getDecl()->getDeclName(); } -static bool isNamedType(const ElaboratedTypeLoc &ETL) { - if (const auto *TFT = - ETL.getNamedTypeLoc().getTypePtr()->getAs()) { - const TypedefNameDecl *Decl = TFT->getDecl(); - return Decl->getDeclName().isIdentifier() && Decl->getName() == "type"; - } - return false; -} - -static bool isNamedType(const DependentNameTypeLoc &DTL) { - return DTL.getTypePtr()->getIdentifier()->getName() == "type"; -} - namespace { AST_POLYMORPHIC_MATCHER(isValue, AST_POLYMORPHIC_SUPPORTED_TYPES( DeclRefExpr, DependentScopeDeclRefExpr)) { @@ -188,10 +175,14 @@ AST_POLYMORPHIC_MATCHER(isValue, AST_POLYMORPHIC_SUPPORTED_TYPES( return Ident && Ident->isStr("value"); } -AST_POLYMORPHIC_MATCHER(isType, - AST_POLYMORPHIC_SUPPORTED_TYPES(ElaboratedTypeLoc, - DependentNameTypeLoc)) { - return Node.getBeginLoc().isValid() && isNamedType(Node); +AST_MATCHER(TypeLoc, isType) { + if (auto TL = Node.getAs()) { + const auto *TD = TL.getDecl(); + return TD->getDeclName().isIdentifier() && TD->getName() == "type"; + } + if (auto TL = Node.getAs()) + return TL.getTypePtr()->getIdentifier()->getName() == "type"; + return false; } } // namespace @@ -214,10 +205,7 @@ void TypeTraitsCheck::registerMatchers(MatchFinder *Finder) { .bind(Bind), this); } - Finder->addMatcher(mapAnyOf(elaboratedTypeLoc, dependentNameTypeLoc) - .with(isType()) - .bind(Bind), - this); + Finder->addMatcher(typeLoc(isType()).bind(Bind), this); } static bool isNamedDeclInStdTraitsSet(const NamedDecl *ND, @@ -226,14 +214,11 @@ static bool isNamedDeclInStdTraitsSet(const NamedDecl *ND, Set.contains(ND->getName()); } -static bool checkTemplatedDecl(const NestedNameSpecifier *NNS, +static bool checkTemplatedDecl(NestedNameSpecifier NNS, const llvm::StringSet<> &Set) { - if (!NNS) + if (NNS.getKind() != NestedNameSpecifier::Kind::Type) return false; - const Type *NNST = NNS->getAsType(); - if (!NNST) - return false; - const auto *TST = NNST->getAs(); + const auto *TST = NNS.getAsType()->getAs(); if (!TST) return false; if (const TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl()) { @@ -250,8 +235,8 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) { auto EmitValueWarning = [this, &Result](const NestedNameSpecifierLoc &QualLoc, SourceLocation EndLoc) { SourceLocation TemplateNameEndLoc; - if (auto TSTL = QualLoc.getTypeLoc().getAs(); - !TSTL.isNull()) + if (auto TSTL = + QualLoc.getAsTypeLoc().getAs()) TemplateNameEndLoc = Lexer::getLocForEndOfToken( TSTL.getTemplateNameLoc(), 0, *Result.SourceManager, Result.Context->getLangOpts()); @@ -274,8 +259,8 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) { SourceLocation EndLoc, SourceLocation TypenameLoc) { SourceLocation TemplateNameEndLoc; - if (auto TSTL = QualLoc.getTypeLoc().getAs(); - !TSTL.isNull()) + if (auto TSTL = + QualLoc.getAsTypeLoc().getAs()) TemplateNameEndLoc = Lexer::getLocForEndOfToken( TSTL.getTemplateNameLoc(), 0, *Result.SourceManager, Result.Context->getLangOpts()); @@ -301,23 +286,21 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) { if (!DRE->hasQualifier()) return; if (const auto *CTSD = dyn_cast_if_present( - DRE->getQualifier()->getAsRecordDecl())) { + DRE->getQualifier().getAsRecordDecl())) { if (isNamedDeclInStdTraitsSet(CTSD, ValueTraits)) EmitValueWarning(DRE->getQualifierLoc(), DRE->getEndLoc()); } return; } - if (const auto *ETL = Result.Nodes.getNodeAs(Bind)) { - const NestedNameSpecifierLoc QualLoc = ETL->getQualifierLoc(); - const auto *NNS = QualLoc.getNestedNameSpecifier(); - if (!NNS) - return; + if (const auto *TL = Result.Nodes.getNodeAs(Bind)) { + const NestedNameSpecifierLoc QualLoc = TL->getQualifierLoc(); + NestedNameSpecifier NNS = QualLoc.getNestedNameSpecifier(); if (const auto *CTSD = dyn_cast_if_present( - NNS->getAsRecordDecl())) { + NNS.getAsRecordDecl())) { if (isNamedDeclInStdTraitsSet(CTSD, TypeTraits)) - EmitTypeWarning(ETL->getQualifierLoc(), ETL->getEndLoc(), - ETL->getElaboratedKeywordLoc()); + EmitTypeWarning(TL->getQualifierLoc(), TL->getEndLoc(), + TL->getElaboratedKeywordLoc()); } return; } diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index f4b63087b7234..b601620633cee 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -186,16 +186,14 @@ TypeMatcher nestedIterator() { /// declarations and which name standard iterators for standard containers. TypeMatcher iteratorFromUsingDeclaration() { auto HasIteratorDecl = hasDeclaration(namedDecl(hasStdIteratorName())); - // Types resulting from using declarations are represented by elaboratedType. - return elaboratedType( - // Unwrap the nested name specifier to test for one of the standard - // containers. - hasQualifier(specifiesType(templateSpecializationType(hasDeclaration( - namedDecl(hasStdContainerName(), isInStdNamespace()))))), - // the named type is what comes after the final '::' in the type. It - // should name one of the standard iterator names. - namesType( - anyOf(typedefType(HasIteratorDecl), recordType(HasIteratorDecl)))); + // Unwrap the nested name specifier to test for one of the standard + // containers. + auto Qualifier = hasQualifier(specifiesType(templateSpecializationType( + hasDeclaration(namedDecl(hasStdContainerName(), isInStdNamespace()))))); + // the named type is what comes after the final '::' in the type. It should + // name one of the standard iterator names. + return anyOf(typedefType(HasIteratorDecl, Qualifier), + recordType(HasIteratorDecl, Qualifier)); } /// This matcher returns declaration statements that contain variable diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index e9b96c4016af6..07274d0376207 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -60,9 +60,11 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) { Keyword != ElaboratedTypeKeyword::None)) { return std::nullopt; } - TheType = Dep.getQualifierLoc().getTypeLoc(); + TheType = Dep.getQualifierLoc().getAsTypeLoc(); if (TheType.isNull()) return std::nullopt; + } else { + return std::nullopt; } if (const auto SpecializationLoc = @@ -89,9 +91,6 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) { static std::optional matchEnableIfSpecializationImplTrait(TypeLoc TheType) { - if (const auto Elaborated = TheType.getAs()) - TheType = Elaborated.getNamedTypeLoc(); - if (const auto SpecializationLoc = TheType.getAs()) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp index aaf24eaa33c1b..ee49d8a7cb0b0 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -164,10 +164,10 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { auto CallEmplacy = cxxMemberCallExpr( hasDeclaration( functionDecl(hasAnyNameIgnoringTemplates(EmplacyFunctions))), - on(hasTypeOrPointeeType(hasCanonicalType(hasDeclaration( - has(typedefNameDecl(hasName("value_type"), - hasType(type(hasUnqualifiedDesugaredType( - recordType().bind("value_type"))))))))))); + on(hasTypeOrPointeeType( + hasCanonicalType(hasDeclaration(has(typedefNameDecl( + hasName("value_type"), + hasType(hasCanonicalType(recordType().bind("value_type")))))))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of @@ -241,17 +241,16 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { auto HasConstructExprWithValueTypeType = has(ignoringImplicit(cxxConstructExpr( - SoughtConstructExpr, hasType(type(hasUnqualifiedDesugaredType( - type(equalsBoundNode("value_type")))))))); - - auto HasBracedInitListWithValueTypeType = - anyOf(allOf(HasConstructInitListExpr, - has(initListExpr(hasType(type(hasUnqualifiedDesugaredType( - type(equalsBoundNode("value_type")))))))), - has(cxxBindTemporaryExpr( - HasConstructInitListExpr, - has(initListExpr(hasType(type(hasUnqualifiedDesugaredType( - type(equalsBoundNode("value_type")))))))))); + SoughtConstructExpr, + hasType(hasCanonicalType(type(equalsBoundNode("value_type"))))))); + + auto HasBracedInitListWithValueTypeType = anyOf( + allOf(HasConstructInitListExpr, + has(initListExpr(hasType( + hasCanonicalType(type(equalsBoundNode("value_type"))))))), + has(cxxBindTemporaryExpr(HasConstructInitListExpr, + has(initListExpr(hasType(hasCanonicalType( + type(equalsBoundNode("value_type"))))))))); auto HasConstructExprWithValueTypeTypeAsLastArgument = hasLastArgument( materializeTemporaryExpr( @@ -289,19 +288,17 @@ void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { this); Finder->addMatcher( - traverse( - TK_AsIs, - cxxMemberCallExpr( - CallEmplacy, - on(hasType(cxxRecordDecl(has(typedefNameDecl( - hasName("value_type"), - hasType(type( - hasUnqualifiedDesugaredType(recordType(hasDeclaration( - cxxRecordDecl(hasAnyName(SmallVector( - TupleTypes.begin(), TupleTypes.end()))))))))))))), - has(MakeTuple), hasSameNumArgsAsDeclNumParams(), - unless(isInTemplateInstantiation())) - .bind("emplacy_call")), + traverse(TK_AsIs, + cxxMemberCallExpr( + CallEmplacy, + on(hasType(cxxRecordDecl(has(typedefNameDecl( + hasName("value_type"), + hasType(hasCanonicalType(recordType(hasDeclaration( + cxxRecordDecl(hasAnyName(SmallVector( + TupleTypes.begin(), TupleTypes.end())))))))))))), + has(MakeTuple), hasSameNumArgsAsDeclNumParams(), + unless(isInTemplateInstantiation())) + .bind("emplacy_call")), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp index 52e9a9f8d49e0..5310f2fd25381 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseScopedLockCheck.cpp @@ -29,7 +29,7 @@ static bool isLockGuardDecl(const NamedDecl *Decl) { static bool isLockGuard(const QualType &Type) { if (const auto *Record = Type->getAs()) - if (const RecordDecl *Decl = Record->getDecl()) + if (const RecordDecl *Decl = Record->getOriginalDecl()) return isLockGuardDecl(Decl); if (const auto *TemplateSpecType = Type->getAs()) @@ -89,17 +89,6 @@ findLocksInCompoundStmt(const CompoundStmt *Block, return LockGuardGroups; } -static TemplateSpecializationTypeLoc -getTemplateLockGuardTypeLoc(const TypeSourceInfo *SourceInfo) { - const TypeLoc Loc = SourceInfo->getTypeLoc(); - - const auto ElaboratedLoc = Loc.getAs(); - if (!ElaboratedLoc) - return {}; - - return ElaboratedLoc.getNamedTypeLoc().getAs(); -} - // Find the exact source range of the 'lock_guard' token static SourceRange getLockGuardRange(const TypeSourceInfo *SourceInfo) { const TypeLoc LockGuardTypeLoc = SourceInfo->getTypeLoc(); @@ -110,7 +99,7 @@ static SourceRange getLockGuardRange(const TypeSourceInfo *SourceInfo) { // Find the exact source range of the 'lock_guard' name token static SourceRange getLockGuardNameRange(const TypeSourceInfo *SourceInfo) { const TemplateSpecializationTypeLoc TemplateLoc = - getTemplateLockGuardTypeLoc(SourceInfo); + SourceInfo->getTypeLoc().getAs(); if (!TemplateLoc) return {}; @@ -136,11 +125,11 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) { const auto LockGuardClassDecl = namedDecl(hasName("lock_guard"), isInStdNamespace()); - const auto LockGuardType = qualType(anyOf( - hasUnqualifiedDesugaredType( - recordType(hasDeclaration(LockGuardClassDecl))), - elaboratedType(namesType(hasUnqualifiedDesugaredType( - templateSpecializationType(hasDeclaration(LockGuardClassDecl))))))); + const auto LockGuardType = + qualType(anyOf(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(LockGuardClassDecl))), + hasUnqualifiedDesugaredType(templateSpecializationType( + hasDeclaration(LockGuardClassDecl))))); const auto LockVarDecl = varDecl(hasType(LockGuardType)); @@ -165,18 +154,16 @@ void UseScopedLockCheck::registerMatchers(MatchFinder *Finder) { if (WarnOnUsingAndTypedef) { // Match 'typedef std::lock_guard Lock' Finder->addMatcher(typedefDecl(unless(isExpansionInSystemHeader()), - hasUnderlyingType(LockGuardType)) + hasType(hasUnderlyingType(LockGuardType))) .bind("lock-guard-typedef"), this); // Match 'using Lock = std::lock_guard' - Finder->addMatcher( - typeAliasDecl( - unless(isExpansionInSystemHeader()), - hasType(elaboratedType(namesType(templateSpecializationType( - hasDeclaration(LockGuardClassDecl)))))) - .bind("lock-guard-using-alias"), - this); + Finder->addMatcher(typeAliasDecl(unless(isExpansionInSystemHeader()), + hasType(templateSpecializationType( + hasDeclaration(LockGuardClassDecl)))) + .bind("lock-guard-using-alias"), + this); // Match 'using std::lock_guard' Finder->addMatcher( @@ -288,8 +275,8 @@ void UseScopedLockCheck::diagOnSourceInfo( const ast_matchers::MatchFinder::MatchResult &Result) { const TypeLoc TL = LockGuardSourceInfo->getTypeLoc(); - if (const auto ElaboratedTL = TL.getAs()) { - auto Diag = diag(ElaboratedTL.getBeginLoc(), UseScopedLockMessage); + if (const auto TTL = TL.getAs()) { + auto Diag = diag(TTL.getBeginLoc(), UseScopedLockMessage); const SourceRange LockGuardRange = getLockGuardNameRange(LockGuardSourceInfo); diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp index ced4825f79a99..82f64096cbec1 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp @@ -64,66 +64,65 @@ struct UnqualNameVisitor : public RecursiveASTVisitor { return false; } - bool TraverseTypeLoc(TypeLoc TL, bool Elaborated = false) { + bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) { if (TL.isNull()) return true; - if (!Elaborated) { - switch (TL.getTypeLocClass()) { - case TypeLoc::Record: - if (visitUnqualName( - TL.getAs().getTypePtr()->getDecl()->getName())) - return false; + switch (TL.getTypeLocClass()) { + case TypeLoc::InjectedClassName: + case TypeLoc::Record: + case TypeLoc::Enum: { + auto TTL = TL.getAs(); + const auto *T = TTL.getTypePtr(); + if (T->getKeyword() != ElaboratedTypeKeyword::None || + TTL.getQualifierLoc()) break; - case TypeLoc::Enum: - if (visitUnqualName( - TL.getAs().getTypePtr()->getDecl()->getName())) - return false; - break; - case TypeLoc::TemplateSpecialization: - if (visitUnqualName(TL.getAs() - .getTypePtr() - ->getTemplateName() - .getAsTemplateDecl() - ->getName())) - return false; - break; - case TypeLoc::Typedef: - if (visitUnqualName( - TL.getAs().getTypePtr()->getDecl()->getName())) - return false; + if (visitUnqualName(T->getOriginalDecl()->getName())) + return false; + break; + } + case TypeLoc::TemplateSpecialization: { + auto TTL = TL.getAs(); + const auto *T = TTL.getTypePtr(); + if (T->getKeyword() != ElaboratedTypeKeyword::None || + TTL.getQualifierLoc()) break; - case TypeLoc::Using: - if (visitUnqualName(TL.getAs() - .getTypePtr() - ->getFoundDecl() - ->getName())) - return false; + if (visitUnqualName(T->getTemplateName().getAsTemplateDecl()->getName())) + return false; + break; + } + case TypeLoc::Typedef: { + auto TTL = TL.getAs(); + const auto *T = TTL.getTypePtr(); + if (T->getKeyword() != ElaboratedTypeKeyword::None || + TTL.getQualifierLoc()) break; - default: + if (visitUnqualName(T->getDecl()->getName())) + return false; + break; + } + case TypeLoc::Using: { + auto TTL = TL.getAs(); + const auto *T = TTL.getTypePtr(); + if (T->getKeyword() != ElaboratedTypeKeyword::None || + TTL.getQualifierLoc()) break; - } + if (visitUnqualName(T->getDecl()->getName())) + return false; + break; + } + default: + break; } - return RecursiveASTVisitor::TraverseTypeLoc(TL); + return RecursiveASTVisitor::TraverseTypeLoc( + TL, TraverseQualifier); } // Replace the base method in order to call our own // TraverseTypeLoc(). - bool TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { - return TraverseTypeLoc(TL.getUnqualifiedLoc()); - } - - // Replace the base version to inform TraverseTypeLoc that the type is - // elaborated. - bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc TL) { - if (TL.getQualifierLoc() && - !TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())) - return false; - const auto *T = TL.getTypePtr(); - return TraverseTypeLoc(TL.getNamedTypeLoc(), - T->getKeyword() != ElaboratedTypeKeyword::None || - T->getQualifier()); + bool TraverseQualifiedTypeLoc(QualifiedTypeLoc TL, bool TraverseQualifier) { + return TraverseTypeLoc(TL.getUnqualifiedLoc(), TraverseQualifier); } bool VisitDeclRefExpr(DeclRefExpr *S) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp index a053c07f95ce2..2373a26fe48b4 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp @@ -37,15 +37,13 @@ void UseTransparentFunctorsCheck::registerMatchers(MatchFinder *Finder) { // Non-transparent functor mentioned as a template parameter. FIXIT. Finder->addMatcher( - loc(qualType( - unless(elaboratedType()), - hasDeclaration(classTemplateSpecializationDecl( - unless(hasAnyTemplateArgument(templateArgument(refersToType( - qualType(pointsTo(qualType(isAnyCharacter()))))))), - hasAnyTemplateArgument( - templateArgument(refersToType(qualType(hasDeclaration( - TransparentFunctors)))) - .bind("Functor")))))) + loc(qualType(hasDeclaration(classTemplateSpecializationDecl( + unless(hasAnyTemplateArgument(templateArgument(refersToType( + qualType(pointsTo(qualType(isAnyCharacter()))))))), + hasAnyTemplateArgument( + templateArgument(refersToType(qualType( + hasDeclaration(TransparentFunctors)))) + .bind("Functor")))))) .bind("FunctorParentLoc"), this); diff --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp index 7022e9d784fa7..1c018999432e3 100644 --- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp @@ -42,11 +42,11 @@ void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) { // A matcher for a `DstT::DstT(const Src&)` where DstT also has a // `DstT::DstT(Src&&)`. const auto LValueRefCtor = cxxConstructorDecl( - hasParameter(0, - hasType(lValueReferenceType(pointee(type().bind("SrcT"))))), + hasParameter(0, hasType(hasCanonicalType( + lValueReferenceType(pointee(type().bind("SrcT")))))), ofClass(cxxRecordDecl(hasMethod(cxxConstructorDecl( - hasParameter(0, hasType(rValueReferenceType( - pointee(type(equalsBoundNode("SrcT"))))))))))); + hasParameter(0, hasType(hasCanonicalType(rValueReferenceType( + pointee(type(equalsBoundNode("SrcT")))))))))))); // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an // instantiation of `template DstT::DstT(U&&)`. diff --git a/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp b/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp index 3b4d65be7dfa1..5a3c9a4203eb9 100644 --- a/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/portability/StdAllocatorConstCheck.cpp @@ -15,10 +15,11 @@ namespace clang::tidy::portability { void StdAllocatorConstCheck::registerMatchers(MatchFinder *Finder) { // Match std::allocator. - auto AllocatorConst = + auto AllocatorConst = qualType(hasCanonicalType( recordType(hasDeclaration(classTemplateSpecializationDecl( hasName("::std::allocator"), - hasTemplateArgument(0, refersToType(qualType(isConstQualified())))))); + hasTemplateArgument(0, + refersToType(qualType(isConstQualified())))))))); auto HasContainerName = hasAnyName("::std::vector", "::std::deque", "::std::list", @@ -31,8 +32,10 @@ void StdAllocatorConstCheck::registerMatchers(MatchFinder *Finder) { // aren't caught. Finder->addMatcher( typeLoc( - templateSpecializationTypeLoc(), - loc(hasUnqualifiedDesugaredType(anyOf( + anyOf(templateSpecializationTypeLoc(), + qualifiedTypeLoc( + hasUnqualifiedLoc(templateSpecializationTypeLoc()))), + loc(qualType(anyOf( recordType(hasDeclaration(classTemplateSpecializationDecl( HasContainerName, anyOf( diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp index fffb136e5a332..a7b3c4a1f7cf9 100644 --- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp @@ -19,19 +19,25 @@ namespace { AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); } } // namespace -static unsigned getNameSpecifierNestingLevel(const QualType &QType) { - if (const auto *ElType = QType->getAs()) { - if (const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier()) { - unsigned NameSpecifierNestingLevel = 1; - do { - NameSpecifierNestingLevel++; - NestedSpecifiers = NestedSpecifiers->getPrefix(); - } while (NestedSpecifiers); - +static unsigned getNameSpecifierNestingLevel(QualType QType) { + unsigned NameSpecifierNestingLevel = 1; + for (NestedNameSpecifier Qualifier = QType->getPrefix(); /**/; + ++NameSpecifierNestingLevel) { + switch (Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: return NameSpecifierNestingLevel; + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: + return NameSpecifierNestingLevel + 1; + case NestedNameSpecifier::Kind::Namespace: + Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix; + continue; + case NestedNameSpecifier::Kind::Type: + Qualifier = Qualifier.getAsType()->getPrefix(); + continue; } + llvm_unreachable("unhandled nested name specifier kind"); } - return 0; } void StaticAccessedThroughInstanceCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp index 5a04029e4a6fa..447c2437666cf 100644 --- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -414,9 +414,9 @@ static bool areTypesCompatible(QualType ArgType, QualType ParamType, // Arithmetic types are interconvertible, except scoped enums. if (ParamType->isArithmeticType() && ArgType->isArithmeticType()) { if ((ParamType->isEnumeralType() && - ParamType->castAs()->getDecl()->isScoped()) || + ParamType->castAs()->getOriginalDecl()->isScoped()) || (ArgType->isEnumeralType() && - ArgType->castAs()->getDecl()->isScoped())) + ArgType->castAs()->getOriginalDecl()->isScoped())) return false; return true; diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp index 6f6b8a853a91e..718467ed02f0a 100644 --- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp @@ -67,11 +67,7 @@ static QualType getNonTemplateAlias(QualType QT) { if (!TT->getDecl()->getDescribedTemplate() && !TT->getDecl()->getDeclContext()->isDependentContext()) return QT; - QT = TT->getDecl()->getUnderlyingType(); - } - // cast to elaborated type - else if (const ElaboratedType *ET = dyn_cast(QT)) { - QT = ET->getNamedType(); + QT = TT->desugar(); } else { break; } diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp index 0637d0eff688c..aa6aefcf0c493 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp @@ -66,7 +66,8 @@ ExceptionSpecAnalyzer::analyzeBase(const CXXBaseSpecifier &Base, if (!RecType) return State::Unknown; - const auto *BaseClass = cast(RecType->getDecl()); + const auto *BaseClass = + cast(RecType->getOriginalDecl())->getDefinitionOrSelf(); return analyzeRecord(BaseClass, Kind); } diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp index e1c1bee97f6d4..0df8e913100fc 100644 --- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp +++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp @@ -461,8 +461,9 @@ bool FormatStringConverter::emitIntegerArgument( // the signedness based on the format string, so we need to do the // same. if (const auto *ET = ArgType->getAs()) { - if (const std::optional MaybeCastType = - castTypeForArgument(ArgKind, ET->getDecl()->getIntegerType())) + if (const std::optional MaybeCastType = castTypeForArgument( + ArgKind, + ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType())) ArgFixes.emplace_back( ArgIndex, (Twine("static_cast<") + *MaybeCastType + ">(").str()); else diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp index 4974a9cdb9f4b..bd7b03eb39ad7 100644 --- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp +++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp @@ -34,7 +34,7 @@ bool MatchesAnyListedTypeNameMatcher::matches( PrintingPolicy PrintingPolicyWithSuppressedTag( Finder->getASTContext().getLangOpts()); PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes; - PrintingPolicyWithSuppressedTag.SuppressElaboration = true; + PrintingPolicyWithSuppressedTag.FullyQualifiedName = true; PrintingPolicyWithSuppressedTag.SuppressScope = false; PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true; PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true; diff --git a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp index eaa04fef08c43..20853dc00123c 100644 --- a/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp @@ -281,9 +281,10 @@ class RenamerClangTidyVisitor } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Loc) { - if (const NestedNameSpecifier *Spec = Loc.getNestedNameSpecifier()) { + if (NestedNameSpecifier Spec = Loc.getNestedNameSpecifier(); + Spec.getKind() == NestedNameSpecifier::Kind::Namespace) { if (const auto *Decl = - dyn_cast_if_present(Spec->getAsNamespace())) + dyn_cast(Spec.getAsNamespaceAndPrefix().Namespace)) Check->addUsage(Decl, Loc.getLocalSourceRange(), SM); } @@ -323,48 +324,34 @@ class RenamerClangTidyVisitor } bool VisitTypedefTypeLoc(const TypedefTypeLoc &Loc) { - Check->addUsage(Loc.getTypedefNameDecl(), Loc.getSourceRange(), SM); + Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM); return true; } bool VisitTagTypeLoc(const TagTypeLoc &Loc) { - Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM); - return true; - } - - bool VisitInjectedClassNameTypeLoc(const InjectedClassNameTypeLoc &Loc) { - Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM); + Check->addUsage(Loc.getOriginalDecl(), Loc.getNameLoc(), SM); return true; } bool VisitUnresolvedUsingTypeLoc(const UnresolvedUsingTypeLoc &Loc) { - Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM); + Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM); return true; } bool VisitTemplateTypeParmTypeLoc(const TemplateTypeParmTypeLoc &Loc) { - Check->addUsage(Loc.getDecl(), Loc.getSourceRange(), SM); + Check->addUsage(Loc.getDecl(), Loc.getNameLoc(), SM); return true; } bool VisitTemplateSpecializationTypeLoc(const TemplateSpecializationTypeLoc &Loc) { const TemplateDecl *Decl = - Loc.getTypePtr()->getTemplateName().getAsTemplateDecl(); + Loc.getTypePtr()->getTemplateName().getAsTemplateDecl( + /*IgnoreDeduced=*/true); - SourceRange Range(Loc.getTemplateNameLoc(), Loc.getTemplateNameLoc()); - if (const auto *ClassDecl = dyn_cast(Decl)) { + if (const auto *ClassDecl = dyn_cast(Decl)) if (const NamedDecl *TemplDecl = ClassDecl->getTemplatedDecl()) - Check->addUsage(TemplDecl, Range, SM); - } - - return true; - } - - bool VisitDependentTemplateSpecializationTypeLoc( - const DependentTemplateSpecializationTypeLoc &Loc) { - if (const TagDecl *Decl = Loc.getTypePtr()->getAsTagDecl()) - Check->addUsage(Decl, Loc.getSourceRange(), SM); + Check->addUsage(TemplDecl, Loc.getTemplateNameLoc(), SM); return true; } diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp index 44db0c2aed607..96d3a5bbd86a2 100644 --- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp +++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp @@ -124,7 +124,8 @@ bool isTriviallyDefaultConstructible(QualType Type, const ASTContext &Context) { return true; if (const auto *RT = CanonicalType->getAs()) { - return recordIsTriviallyDefaultConstructible(*RT->getDecl(), Context); + return recordIsTriviallyDefaultConstructible( + *RT->getOriginalDecl()->getDefinitionOrSelf(), Context); } // No other types can match. diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp index f2631e5abb6a3..82aee4c84d074 100644 --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -102,54 +102,78 @@ getUsingNamespaceDirectives(const DeclContext *DestContext, // ancestor is redundant, therefore we stop at lowest common ancestor. // In addition to that stops early whenever IsVisible returns true. This can be // used to implement support for "using namespace" decls. -std::string -getQualification(ASTContext &Context, const DeclContext *DestContext, - const DeclContext *SourceContext, - llvm::function_ref IsVisible) { - std::vector Parents; - bool ReachedNS = false; +std::string getQualification(ASTContext &Context, + const DeclContext *DestContext, + const DeclContext *SourceContext, + llvm::function_ref IsVisible) { + std::vector Parents; + [[maybe_unused]] bool ReachedNS = false; for (const DeclContext *CurContext = SourceContext; CurContext; CurContext = CurContext->getLookupParent()) { // Stop once we reach a common ancestor. if (CurContext->Encloses(DestContext)) break; - NestedNameSpecifier *NNS = nullptr; + const Decl *CurD; if (auto *TD = llvm::dyn_cast(CurContext)) { // There can't be any more tag parents after hitting a namespace. assert(!ReachedNS); - (void)ReachedNS; - NNS = NestedNameSpecifier::Create(Context, nullptr, TD->getTypeForDecl()); + CurD = TD; } else if (auto *NSD = llvm::dyn_cast(CurContext)) { ReachedNS = true; - NNS = NestedNameSpecifier::Create(Context, nullptr, NSD); // Anonymous and inline namespace names are not spelled while qualifying // a name, so skip those. if (NSD->isAnonymousNamespace() || NSD->isInlineNamespace()) continue; + CurD = NSD; } else { // Other types of contexts cannot be spelled in code, just skip over // them. continue; } // Stop if this namespace is already visible at DestContext. - if (IsVisible(NNS)) + if (IsVisible(CurD)) break; - Parents.push_back(NNS); + Parents.push_back(CurD); + } + + // Go over the declarations in reverse order, since we stored inner-most + // parent first. + NestedNameSpecifier Qualifier = std::nullopt; + bool IsFirst = true; + for (const auto *CurD : llvm::reverse(Parents)) { + if (auto *TD = llvm::dyn_cast(CurD)) { + QualType T; + if (const auto *RD = dyn_cast(TD); + ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) { + ArrayRef Args; + if (const auto *SD = dyn_cast(RD)) + Args = SD->getTemplateArgs().asArray(); + else + Args = CTD->getTemplateParameters()->getInjectedTemplateArgs(Context); + T = Context.getTemplateSpecializationType( + ElaboratedTypeKeyword::None, + Context.getQualifiedTemplateName( + Qualifier, /*TemplateKeyword=*/!IsFirst, TemplateName(CTD)), + Args, /*CanonicalArgs=*/{}, Context.getCanonicalTagType(RD)); + } else { + T = Context.getTagType(ElaboratedTypeKeyword::None, Qualifier, TD, + /*OwnsTag=*/false); + } + Qualifier = NestedNameSpecifier(T.getTypePtr()); + } else { + Qualifier = + NestedNameSpecifier(Context, cast(CurD), Qualifier); + } + IsFirst = false; } + if (!Qualifier) + return ""; - // Go over name-specifiers in reverse order to create necessary qualification, - // since we stored inner-most parent first. std::string Result; llvm::raw_string_ostream OS(Result); - for (const auto *Parent : llvm::reverse(Parents)) { - if (Parent != *Parents.rbegin() && Parent->isDependent() && - Parent->getAsRecordDecl() && - Parent->getAsRecordDecl()->getDescribedClassTemplate()) - OS << "template "; - Parent->print(OS, Context.getPrintingPolicy()); - } + Qualifier.print(OS, Context.getPrintingPolicy()); return OS.str(); } @@ -187,6 +211,7 @@ std::string printQualifiedName(const NamedDecl &ND) { // include them, but at query time it's hard to find all the inline // namespaces to query: the preamble doesn't have a dedicated list. Policy.SuppressUnwrittenScope = true; + Policy.SuppressScope = true; // (unnamed struct), not (unnamed struct at /path/to/foo.cc:42:1). // In clangd, context is usually available and paths are mostly noise. Policy.AnonymousTagLocations = false; @@ -213,8 +238,7 @@ std::string printUsingNamespaceName(const ASTContext &Ctx, std::string Name; llvm::raw_string_ostream Out(Name); - if (auto *Qual = D.getQualifier()) - Qual->print(Out, PP); + D.getQualifier().print(Out, PP); D.getNominatedNamespaceAsWritten()->printName(Out); return Out.str(); } @@ -229,8 +253,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { // Handle 'using namespace'. They all have the same name - . if (auto *UD = llvm::dyn_cast(&ND)) { Out << "using namespace "; - if (auto *Qual = UD->getQualifier()) - Qual->print(Out, PP); + UD->getQualifier().print(Out, PP); UD->getNominatedNamespaceAsWritten()->printName(Out); return Out.str(); } @@ -250,8 +273,7 @@ std::string printName(const ASTContext &Ctx, const NamedDecl &ND) { } // Print nested name qualifier if it was written in the source code. - if (auto *Qualifier = getQualifierLoc(ND).getNestedNameSpecifier()) - Qualifier->print(Out, PP); + getQualifierLoc(ND).getNestedNameSpecifier().print(Out, PP); // Print the name itself. ND.getDeclName().print(Out, PP); // Print template arguments. @@ -391,12 +413,13 @@ preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, } std::string printType(const QualType QT, const DeclContext &CurContext, - const llvm::StringRef Placeholder) { + const llvm::StringRef Placeholder, bool FullyQualify) { std::string Result; llvm::raw_string_ostream OS(Result); PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy()); PP.SuppressTagKeyword = true; PP.SuppressUnwrittenScope = true; + PP.FullyQualifiedName = FullyQualify; class PrintCB : public PrintingCallbacks { public: @@ -439,6 +462,7 @@ QualType declaredType(const TypeDecl *D) { if (const auto *CTSD = llvm::dyn_cast(D)) if (const auto *Args = CTSD->getTemplateArgsAsWritten()) return Context.getTemplateSpecializationType( + ElaboratedTypeKeyword::None, TemplateName(CTSD->getSpecializedTemplate()), Args->arguments(), /*CanonicalArgs=*/{}); return Context.getTypeDeclType(D); @@ -664,13 +688,10 @@ std::string getQualification(ASTContext &Context, auto VisibleNamespaceDecls = getUsingNamespaceDirectives(DestContext, InsertionPoint); return getQualification( - Context, DestContext, ND->getDeclContext(), - [&](NestedNameSpecifier *NNS) { - const NamespaceDecl *NS = - dyn_cast_if_present(NNS->getAsNamespace()); - if (!NS) + Context, DestContext, ND->getDeclContext(), [&](const Decl *D) { + if (D->getKind() != Decl::Namespace) return false; - NS = NS->getCanonicalDecl(); + const auto *NS = cast(D)->getCanonicalDecl(); return llvm::any_of(VisibleNamespaceDecls, [NS](const NamespaceDecl *NSD) { return NSD->getCanonicalDecl() == NS; @@ -687,12 +708,11 @@ std::string getQualification(ASTContext &Context, (void)NS; } return getQualification( - Context, DestContext, ND->getDeclContext(), - [&](NestedNameSpecifier *NNS) { + Context, DestContext, ND->getDeclContext(), [&](const Decl *D) { return llvm::any_of(VisibleNamespaces, [&](llvm::StringRef Namespace) { std::string NS; llvm::raw_string_ostream OS(NS); - NNS->print(OS, Context.getPrintingPolicy()); + D->print(OS, Context.getPrintingPolicy()); return OS.str() == Namespace; }); }); diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h index fb0722d697cd0..1538d12172593 100644 --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -135,7 +135,8 @@ preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, /// Returns a QualType as string. The result doesn't contain unwritten scopes /// like anonymous/inline namespace. std::string printType(const QualType QT, const DeclContext &CurContext, - llvm::StringRef Placeholder = ""); + llvm::StringRef Placeholder = "", + bool FullyQualify = false); /// Indicates if \p D is a template instantiation implicitly generated by the /// compiler, e.g. diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 9c17b4ca9b706..a1efd4eeb4898 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1466,19 +1466,15 @@ bool allowIndex(CodeCompletionContext &CC) { auto Scope = CC.getCXXScopeSpecifier(); if (!Scope) return true; - NestedNameSpecifier *NameSpec = (*Scope)->getScopeRep(); - if (!NameSpec) - return true; // We only query the index when qualifier is a namespace. // If it's a class, we rely solely on sema completions. - switch (NameSpec->getKind()) { - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Namespace: + switch ((*Scope)->getScopeRep().getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::Namespace: return true; - case NestedNameSpecifier::Super: - case NestedNameSpecifier::TypeSpec: - // Unresolved inside a template. - case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Kind::MicrosoftSuper: + case NestedNameSpecifier::Kind::Type: return false; } llvm_unreachable("invalid NestedNameSpecifier kind"); diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index c6075e75e9a6b..9a8d41d870929 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -147,17 +147,17 @@ class DumpVisitor : public RecursiveASTVisitor { } llvm_unreachable("Unhandled ArgKind enum"); } - std::string getKind(const NestedNameSpecifierLoc &NNSL) { - assert(NNSL.getNestedNameSpecifier()); - switch (NNSL.getNestedNameSpecifier()->getKind()) { + std::string getKind(NestedNameSpecifierLoc NNSL) { + switch (NNSL.getNestedNameSpecifier().getKind()) { + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); #define NNS_KIND(X) \ - case NestedNameSpecifier::X: \ + case NestedNameSpecifier::Kind::X: \ return #X - NNS_KIND(Identifier); NNS_KIND(Namespace); - NNS_KIND(TypeSpec); + NNS_KIND(Type); NNS_KIND(Global); - NNS_KIND(Super); + NNS_KIND(MicrosoftSuper); #undef NNS_KIND } llvm_unreachable("Unhandled SpecifierKind enum"); @@ -261,7 +261,7 @@ class DumpVisitor : public RecursiveASTVisitor { return TL.getType().getLocalQualifiers().getAsString( Ctx.getPrintingPolicy()); if (const auto *TT = dyn_cast(TL.getTypePtr())) - return getDetail(TT->getDecl()); + return getDetail(TT->getOriginalDecl()); if (const auto *DT = dyn_cast(TL.getTypePtr())) if (DT->isDeduced()) return DT->getDeducedType().getAsString(Ctx.getPrintingPolicy()); @@ -273,16 +273,11 @@ class DumpVisitor : public RecursiveASTVisitor { return getDetail(TT->getDecl()); return ""; } - std::string getDetail(const NestedNameSpecifierLoc &NNSL) { - const auto &NNS = *NNSL.getNestedNameSpecifier(); - switch (NNS.getKind()) { - case NestedNameSpecifier::Identifier: - return NNS.getAsIdentifier()->getName().str() + "::"; - case NestedNameSpecifier::Namespace: - return NNS.getAsNamespace()->getNameAsString() + "::"; - default: + std::string getDetail(NestedNameSpecifierLoc NNSL) { + NestedNameSpecifier NNS = NNSL.getNestedNameSpecifier(); + if (NNS.getKind() != NestedNameSpecifier::Kind::Namespace) return ""; - } + return NNS.getAsNamespaceAndPrefix().Namespace->getNameAsString() + "::"; } std::string getDetail(const CXXCtorInitializer *CCI) { if (FieldDecl *FD = CCI->getAnyMember()) @@ -346,8 +341,10 @@ class DumpVisitor : public RecursiveASTVisitor { return !D || isInjectedClassName(D) || traverseNode("declaration", D, [&] { Base::TraverseDecl(D); }); } - bool TraverseTypeLoc(TypeLoc TL) { - return !TL || traverseNode("type", TL, [&] { Base::TraverseTypeLoc(TL); }); + bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) { + return !TL || traverseNode("type", TL, [&] { + Base::TraverseTypeLoc(TL, TraverseQualifier); + }); } bool TraverseTemplateName(const TemplateName &TN) { return traverseNode("template name", TN, @@ -389,11 +386,11 @@ class DumpVisitor : public RecursiveASTVisitor { // This means we'd never see 'int' in 'const int'! Work around that here. // (The reason for the behavior is to avoid traversing the nested Type twice, // but we ignore TraverseType anyway). - bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QTL) { + bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QTL, bool TraverseQualifier) { return TraverseTypeLoc(QTL.getUnqualifiedLoc()); } // Uninteresting parts of the AST that don't have locations within them. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; } + bool TraverseNestedNameSpecifier(NestedNameSpecifier) { return true; } bool TraverseType(QualType) { return true; } // OpaqueValueExpr blocks traversal, we must explicitly traverse it. @@ -420,7 +417,7 @@ ASTNode dumpAST(const DynTypedNode &N, const syntax::TokenBuffer &Tokens, V.TraverseNestedNameSpecifierLoc( *const_cast(NNSL)); else if (const auto *NNS = N.get()) - V.TraverseNestedNameSpecifier(const_cast(NNS)); + V.TraverseNestedNameSpecifier(*NNS); else if (const auto *TL = N.get()) V.TraverseTypeLoc(*const_cast(TL)); else if (const auto *QT = N.get()) diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index b1089577ba819..32018d1bf3a84 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -366,19 +366,11 @@ struct TargetFinder { Visitor(TargetFinder &Outer, RelSet Flags) : Outer(Outer), Flags(Flags) {} void VisitTagType(const TagType *TT) { - Outer.add(TT->getAsTagDecl(), Flags); - } - - void VisitElaboratedType(const ElaboratedType *ET) { - Outer.add(ET->desugar(), Flags); + Outer.add(cast(TT)->getOriginalDecl(), Flags); } void VisitUsingType(const UsingType *ET) { - Outer.add(ET->getFoundDecl(), Flags); - } - - void VisitInjectedClassNameType(const InjectedClassNameType *ICNT) { - Outer.add(ICNT->getDecl(), Flags); + Outer.add(ET->getDecl(), Flags); } void VisitDecltypeType(const DecltypeType *DTT) { @@ -483,30 +475,27 @@ struct TargetFinder { Visitor(*this, Flags).Visit(T.getTypePtr()); } - void add(const NestedNameSpecifier *NNS, RelSet Flags) { + void add(NestedNameSpecifier NNS, RelSet Flags) { if (!NNS) return; - debug(*NNS, Flags); - switch (NNS->getKind()) { - case NestedNameSpecifier::Namespace: - add(NNS->getAsNamespace(), Flags); - return; - case NestedNameSpecifier::Identifier: - if (Resolver) { - add(Resolver->resolveNestedNameSpecifierToType(NNS), Flags); - } + debug(NNS, Flags); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: + add(NNS.getAsNamespaceAndPrefix().Namespace, Flags); return; - case NestedNameSpecifier::TypeSpec: - add(QualType(NNS->getAsType(), 0), Flags); + case NestedNameSpecifier::Kind::Type: + add(QualType(NNS.getAsType(), 0), Flags); return; - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: // This should be TUDecl, but we can't get a pointer to it! return; - case NestedNameSpecifier::Super: - add(NNS->getAsRecordDecl(), Flags); + case NestedNameSpecifier::Kind::MicrosoftSuper: + add(NNS.getAsMicrosoftSuper(), Flags); return; + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } - llvm_unreachable("unhandled NestedNameSpecifier::SpecifierKind"); + llvm_unreachable("unhandled NestedNameSpecifier::Kind"); } void add(const CXXCtorInitializer *CCI, RelSet Flags) { @@ -555,7 +544,7 @@ allTargetDecls(const DynTypedNode &N, const HeuristicResolver *Resolver) { else if (const NestedNameSpecifierLoc *NNSL = N.get()) Finder.add(NNSL->getNestedNameSpecifier(), Flags); else if (const NestedNameSpecifier *NNS = N.get()) - Finder.add(NNS, Flags); + Finder.add(*NNS, Flags); else if (const TypeLoc *TL = N.get()) Finder.add(TL->getType(), Flags); else if (const QualType *QT = N.get()) @@ -861,32 +850,25 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) { const HeuristicResolver *Resolver; llvm::SmallVector Refs; - void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) { - // We only know about qualifier, rest if filled by inner locations. - size_t InitialSize = Refs.size(); - Visit(L.getNamedTypeLoc().getUnqualifiedLoc()); - size_t NewSize = Refs.size(); - // Add qualifier for the newly-added refs. - for (unsigned I = InitialSize; I < NewSize; ++I) { - ReferenceLoc *Ref = &Refs[I]; - // Fill in the qualifier. - assert(!Ref->Qualifier.hasQualifier() && "qualifier already set"); - Ref->Qualifier = L.getQualifierLoc(); - } + void VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc L) { + Refs.push_back(ReferenceLoc{L.getQualifierLoc(), + L.getLocalSourceRange().getBegin(), + /*IsDecl=*/false, + {L.getDecl()}}); } void VisitUsingTypeLoc(UsingTypeLoc L) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + Refs.push_back(ReferenceLoc{L.getQualifierLoc(), L.getLocalSourceRange().getBegin(), /*IsDecl=*/false, - {L.getFoundDecl()}}); + {L.getDecl()}}); } void VisitTagTypeLoc(TagTypeLoc L) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + Refs.push_back(ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false, - {L.getDecl()}}); + {L.getOriginalDecl()}}); } void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) { @@ -906,25 +888,18 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) { // 2. 'vector' with mask 'Underlying'. // we want to return only #1 in this case. Refs.push_back(ReferenceLoc{ - NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, + L.getQualifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false, explicitReferenceTargets(DynTypedNode::create(L.getType()), DeclRelation::Alias, Resolver)}); } void VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc L) { Refs.push_back(ReferenceLoc{ - NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, + L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false, explicitReferenceTargets(DynTypedNode::create(L.getType()), DeclRelation::Alias, Resolver)}); } - void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), - TL.getNameLoc(), - /*IsDecl=*/false, - {TL.getDecl()}}); - } - void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc L) { Refs.push_back( @@ -943,12 +918,12 @@ refInTypeLoc(TypeLoc L, const HeuristicResolver *Resolver) { } void VisitTypedefTypeLoc(TypedefTypeLoc L) { - if (shouldSkipTypedef(L.getTypedefNameDecl())) + if (shouldSkipTypedef(L.getDecl())) return; - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + Refs.push_back(ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false, - {L.getTypedefNameDecl()}}); + {L.getDecl()}}); } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) { @@ -980,17 +955,6 @@ class ExplicitReferenceCollector return true; } - bool TraverseElaboratedTypeLoc(ElaboratedTypeLoc L) { - // ElaboratedTypeLoc will reports information for its inner type loc. - // Otherwise we loose information about inner types loc's qualifier. - TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc(); - if (L.getBeginLoc() == Inner.getBeginLoc()) - return RecursiveASTVisitor::TraverseTypeLoc(Inner); - else - TypeLocsToSkip.insert(Inner.getBeginLoc()); - return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L); - } - bool VisitStmt(Stmt *S) { visitNode(DynTypedNode::create(*S)); return true; @@ -1051,7 +1015,7 @@ class ExplicitReferenceCollector return true; visitNode(DynTypedNode::create(L)); // Inner type is missing information about its qualifier, skip it. - if (auto TL = L.getTypeLoc()) + if (auto TL = L.getAsTypeLoc()) TypeLocsToSkip.insert(TL.getBeginLoc()); return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L); } @@ -1092,12 +1056,21 @@ class ExplicitReferenceCollector if (auto *S = N.get()) return refInStmt(S, Resolver); if (auto *NNSL = N.get()) { - // (!) 'DeclRelation::Alias' ensures we do not loose namespace aliases. - return {ReferenceLoc{ - NNSL->getPrefix(), NNSL->getLocalBeginLoc(), false, - explicitReferenceTargets( - DynTypedNode::create(*NNSL->getNestedNameSpecifier()), - DeclRelation::Alias, Resolver)}}; + // (!) 'DeclRelation::Alias' ensures we do not lose namespace aliases. + NestedNameSpecifierLoc Qualifier; + SourceLocation NameLoc; + if (auto TL = NNSL->getAsTypeLoc()) { + Qualifier = TL.getPrefix(); + NameLoc = TL.getNonPrefixBeginLoc(); + } else { + Qualifier = NNSL->getAsNamespaceAndPrefix().Prefix; + NameLoc = NNSL->getLocalBeginLoc(); + } + return { + ReferenceLoc{Qualifier, NameLoc, false, + explicitReferenceTargets( + DynTypedNode::create(NNSL->getNestedNameSpecifier()), + DeclRelation::Alias, Resolver)}}; } if (const TypeLoc *TL = N.get()) return refInTypeLoc(*TL, Resolver); @@ -1210,8 +1183,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R) { OS << "}"; if (R.Qualifier) { OS << ", qualifier = '"; - R.Qualifier.getNestedNameSpecifier()->print(OS, - PrintingPolicy(LangOptions())); + R.Qualifier.getNestedNameSpecifier().print(OS, + PrintingPolicy(LangOptions())); OS << "'"; } if (R.IsDecl) diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 0afa90285db52..a7cf45c632827 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -172,13 +172,14 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx, QT = QT->castAs()->getUnderlyingType(); HoverInfo::PrintedType Result; llvm::raw_string_ostream OS(Result.Type); - // Special case: if the outer type is a tag type without qualifiers, then - // include the tag for extra clarity. - // This isn't very idiomatic, so don't attempt it for complex cases, including - // pointers/references, template specializations, etc. + // Special case: if the outer type is a canonical tag type, then include the + // tag for extra clarity. This isn't very idiomatic, so don't attempt it for + // complex cases, including pointers/references, template specializations, + // etc. if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) { - if (auto *TT = llvm::dyn_cast(QT.getTypePtr())) - OS << TT->getDecl()->getKindName() << " "; + if (auto *TT = llvm::dyn_cast(QT.getTypePtr()); + TT && TT->isCanonicalUnqualified()) + OS << TT->getOriginalDecl()->getKindName() << " "; } QT.print(OS, PP); @@ -454,7 +455,7 @@ std::optional printExprValue(const Expr *E, // Compare to int64_t to avoid bit-width match requirements. int64_t Val = Constant.Val.getInt().getExtValue(); for (const EnumConstantDecl *ECD : - T->castAs()->getDecl()->enumerators()) + T->castAs()->getOriginalDecl()->enumerators()) if (ECD->getInitVal() == Val) return llvm::formatv("{0} ({1})", ECD->getNameAsString(), printHex(Constant.Val.getInt())) @@ -972,10 +973,11 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) { const auto &Ctx = ND.getASTContext(); if (auto *RD = llvm::dyn_cast(&ND)) { - if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RD->getTypeForDecl())) + CanQualType RT = Ctx.getCanonicalTagType(RD); + if (auto Size = Ctx.getTypeSizeInCharsIfKnown(RT)) HI.Size = Size->getQuantity() * 8; if (!RD->isDependentType() && RD->isCompleteDefinition()) - HI.Align = Ctx.getTypeAlign(RD->getTypeForDecl()); + HI.Align = Ctx.getTypeAlign(RT); return; } diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index 50bc2bd7ccb94..c27d960cd963b 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -173,7 +173,7 @@ std::vector IncludeFixer::fix(DiagnosticsEngine::Level DiagLevel, // `enum x : int;' is not formally an incomplete type. // We may need a full definition anyway. if (auto * ET = llvm::dyn_cast(T)) - if (!ET->getDecl()->getDefinition()) + if (!ET->getOriginalDecl()->getDefinition()) return fixIncompleteType(*T); } } @@ -400,35 +400,35 @@ std::optional extractUnresolvedNameCheaply( CheapUnresolvedName Result; Result.Name = Unresolved.getAsString(); if (SS && SS->isNotEmpty()) { // "::" or "ns::" - if (auto *Nested = SS->getScopeRep()) { - if (Nested->getKind() == NestedNameSpecifier::Global) { - Result.ResolvedScope = ""; - } else if (const NamespaceBaseDecl *NSB = Nested->getAsNamespace()) { - if (const auto *NS = dyn_cast(NSB)) { - std::string SpecifiedNS = printNamespaceScope(*NS); - std::optional Spelling = getSpelledSpecifier(*SS, SM); - - // Check the specifier spelled in the source. - // If the resolved scope doesn't end with the spelled scope, the - // resolved scope may come from a sema typo correction. For example, - // sema assumes that "clangd::" is a typo of "clang::" and uses - // "clang::" as the specified scope in: - // namespace clang { clangd::X; } - // In this case, we use the "typo" specifier as extra scope instead - // of using the scope assumed by sema. - if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) { - Result.ResolvedScope = std::move(SpecifiedNS); - } else { - Result.UnresolvedScope = std::move(*Spelling); - } + NestedNameSpecifier Nested = SS->getScopeRep(); + if (Nested.getKind() == NestedNameSpecifier::Kind::Global) { + Result.ResolvedScope = ""; + } else if (Nested.getKind() == NestedNameSpecifier::Kind::Namespace) { + const NamespaceBaseDecl *NSB = Nested.getAsNamespaceAndPrefix().Namespace; + if (const auto *NS = dyn_cast(NSB)) { + std::string SpecifiedNS = printNamespaceScope(*NS); + std::optional Spelling = getSpelledSpecifier(*SS, SM); + + // Check the specifier spelled in the source. + // If the resolved scope doesn't end with the spelled scope, the + // resolved scope may come from a sema typo correction. For example, + // sema assumes that "clangd::" is a typo of "clang::" and uses + // "clang::" as the specified scope in: + // namespace clang { clangd::X; } + // In this case, we use the "typo" specifier as extra scope instead + // of using the scope assumed by sema. + if (!Spelling || llvm::StringRef(SpecifiedNS).ends_with(*Spelling)) { + Result.ResolvedScope = std::move(SpecifiedNS); } else { - Result.ResolvedScope = printNamespaceScope(*cast(NSB)->getNamespace()); + Result.UnresolvedScope = std::move(*Spelling); } } else { - // We don't fix symbols in scopes that are not top-level e.g. class - // members, as we don't collect includes for them. - return std::nullopt; + Result.ResolvedScope = printNamespaceScope(*cast(NSB)->getNamespace()); } + } else { + // We don't fix symbols in scopes that are not top-level e.g. class + // members, as we don't collect includes for them. + return std::nullopt; } } diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 197c62c40dcf0..cd479e1b7c9bc 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -55,18 +55,24 @@ void stripLeadingUnderscores(StringRef &Name) { Name = Name.ltrim('_'); } // getDeclForType() returns the decl responsible for Type's spelling. // This is the inverse of ASTContext::getTypeDeclType(). -template getDecl())> -const NamedDecl *getDeclForTypeImpl(const Ty *T) { - return T->getDecl(); -} -const NamedDecl *getDeclForTypeImpl(const void *T) { return nullptr; } const NamedDecl *getDeclForType(const Type *T) { switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(TY, BASE) -#define TYPE(TY, BASE) \ - case Type::TY: \ - return getDeclForTypeImpl(llvm::cast(T)); -#include "clang/AST/TypeNodes.inc" + case Type::Enum: + case Type::Record: + case Type::InjectedClassName: + return cast(T)->getOriginalDecl(); + case Type::TemplateSpecialization: + return cast(T) + ->getTemplateName() + .getAsTemplateDecl(/*IgnoreDeduced=*/true); + case Type::Typedef: + return cast(T)->getDecl(); + case Type::UnresolvedUsing: + return cast(T)->getDecl(); + case Type::Using: + return cast(T)->getDecl(); + default: + return nullptr; } llvm_unreachable("Unknown TypeClass enum"); } @@ -81,8 +87,6 @@ llvm::StringRef getSimpleName(const NamedDecl &D) { return getSimpleName(D.getDeclName()); } llvm::StringRef getSimpleName(QualType T) { - if (const auto *ET = llvm::dyn_cast(T)) - return getSimpleName(ET->getNamedType()); if (const auto *BT = llvm::dyn_cast(T)) { PrintingPolicy PP(LangOptions{}); PP.adjustForCPlusPlus(); diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index 277cb8769a1b1..06165dfbbcdd2 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -62,7 +62,8 @@ void recordMetrics(const SelectionTree &S, const LangOptions &Lang) { } // Return the range covering a node and all its children. -SourceRange getSourceRange(const DynTypedNode &N) { +SourceRange getSourceRange(const DynTypedNode &N, + bool IncludeQualifier = false) { // MemberExprs to implicitly access anonymous fields should not claim any // tokens for themselves. Given: // struct A { struct { int b; }; }; @@ -80,7 +81,7 @@ SourceRange getSourceRange(const DynTypedNode &N) { ? getSourceRange(DynTypedNode::create(*ME->getBase())) : SourceRange(); } - return N.getSourceRange(); + return N.getSourceRange(IncludeQualifier); } // An IntervalSet maintains a set of disjoint subranges of an array. @@ -643,8 +644,9 @@ class SelectionVisitor : public RecursiveASTVisitor { } return traverseNode(X, [&] { return Base::TraverseDecl(X); }); } - bool TraverseTypeLoc(TypeLoc X) { - return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); + bool TraverseTypeLoc(TypeLoc X, bool TraverseQualifier = true) { + return traverseNode( + &X, [&] { return Base::TraverseTypeLoc(X, TraverseQualifier); }); } bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) { return traverseNode(&X, @@ -690,7 +692,8 @@ class SelectionVisitor : public RecursiveASTVisitor { // This means we'd never see 'int' in 'const int'! Work around that here. // (The reason for the behavior is to avoid traversing the nested Type twice, // but we ignore TraverseType anyway). - bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QX) { + bool TraverseQualifiedTypeLoc(QualifiedTypeLoc QX, + bool TraverseQualifier = true) { return traverseNode( &QX, [&] { return TraverseTypeLoc(QX.getUnqualifiedLoc()); }); } @@ -698,7 +701,7 @@ class SelectionVisitor : public RecursiveASTVisitor { return traverseNode(&PL, [&] { return Base::TraverseObjCProtocolLoc(PL); }); } // Uninteresting parts of the AST that don't have locations within them. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *) { return true; } + bool TraverseNestedNameSpecifier(NestedNameSpecifier) { return true; } bool TraverseType(QualType) { return true; } // The DeclStmt for the loop variable claims to cover the whole range @@ -798,7 +801,7 @@ class SelectionVisitor : public RecursiveASTVisitor { // An optimization for a common case: nodes outside macro expansions that // don't intersect the selection may be recursively skipped. bool canSafelySkipNode(const DynTypedNode &N) { - SourceRange S = getSourceRange(N); + SourceRange S = getSourceRange(N, /*IncludeQualifier=*/true); if (auto *TL = N.get()) { // FIXME: TypeLoc::getBeginLoc()/getEndLoc() are pretty fragile // heuristics. We should consider only pruning critical TypeLoc nodes, to diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index e6d5cf7053694..2b151b1274428 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -1127,21 +1127,6 @@ class CollectExtraHighlightings return RecursiveASTVisitor::TraverseTemplateArgumentLoc(L); } - // findExplicitReferences will walk nested-name-specifiers and - // find anything that can be resolved to a Decl. However, non-leaf - // components of nested-name-specifiers which are dependent names - // (kind "Identifier") cannot be resolved to a decl, so we visit - // them here. - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc Q) { - if (NestedNameSpecifier *NNS = Q.getNestedNameSpecifier()) { - if (NNS->getKind() == NestedNameSpecifier::Identifier) - H.addToken(Q.getLocalBeginLoc(), HighlightingKind::Type) - .addModifier(HighlightingModifier::DependentName) - .addModifier(HighlightingModifier::ClassScope); - } - return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(Q); - } - private: HighlightingsBuilder &H; }; diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 83a8b7289aec3..11ee51072dccf 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -1965,7 +1965,8 @@ std::vector findRecordTypeAt(ParsedAST &AST, // Return the type most associated with an AST node. // This isn't precisely defined: we want "go to type" to do something useful. -static QualType typeForNode(const SelectionTree::Node *N) { +static QualType typeForNode(const ASTContext &Ctx, + const SelectionTree::Node *N) { // If we're looking at a namespace qualifier, walk up to what it's qualifying. // (If we're pointing at a *class* inside a NNS, N will be a TypeLoc). while (N && N->ASTNode.get()) @@ -1999,10 +2000,13 @@ static QualType typeForNode(const SelectionTree::Node *N) { if (const Decl *D = N->ASTNode.get()) { struct Visitor : ConstDeclVisitor { + const ASTContext &Ctx; + Visitor(const ASTContext &Ctx) : Ctx(Ctx) {} + QualType VisitValueDecl(const ValueDecl *D) { return D->getType(); } // Declaration of a type => that type. QualType VisitTypeDecl(const TypeDecl *D) { - return QualType(D->getTypeForDecl(), 0); + return Ctx.getTypeDeclType(D); } // Exception: alias declaration => the underlying type, not the alias. QualType VisitTypedefNameDecl(const TypedefNameDecl *D) { @@ -2012,7 +2016,7 @@ static QualType typeForNode(const SelectionTree::Node *N) { QualType VisitTemplateDecl(const TemplateDecl *D) { return Visit(D->getTemplatedDecl()); } - } V; + } V(Ctx); return V.Visit(D); } @@ -2156,7 +2160,8 @@ std::vector findType(ParsedAST &AST, Position Pos, // unique_ptr>. Let's *not* remove them, because it gives you some // information about the type you may have not known before // (since unique_ptr> != unique_ptr). - for (const QualType& Type : unwrapFindType(typeForNode(N), AST.getHeuristicResolver())) + for (const QualType &Type : unwrapFindType( + typeForNode(AST.getASTContext(), N), AST.getHeuristicResolver())) llvm::copy(locateSymbolForType(AST, Type, Index), std::back_inserter(LocatedSymbols)); diff --git a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp index 67fc451a6a1a1..f65c74fdbc9ee 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/AddUsing.cpp @@ -115,13 +115,6 @@ class UsingFinder : public RecursiveASTVisitor { const SourceManager &SM; }; -bool isFullyQualified(const NestedNameSpecifier *NNS) { - if (!NNS) - return false; - return NNS->getKind() == NestedNameSpecifier::Global || - isFullyQualified(NNS->getPrefix()); -} - struct InsertionPointData { // Location to insert the "using" statement. If invalid then the statement // should not be inserted at all (it already exists). @@ -167,18 +160,20 @@ findInsertionPoint(const Tweak::Selection &Inputs, for (auto &U : Usings) { // Only "upgrade" to fully qualified is all relevant using decls are fully // qualified. Otherwise trust what the user typed. - if (!isFullyQualified(U->getQualifier())) + if (!U->getQualifier().isFullyQualified()) AlwaysFullyQualify = false; if (SM.isBeforeInTranslationUnit(Inputs.Cursor, U->getUsingLoc())) // "Usings" is sorted, so we're done. break; - if (const auto *Namespace = dyn_cast_if_present( - U->getQualifier()->getAsNamespace())) { + if (NestedNameSpecifier Qualifier = U->getQualifier(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) { + const auto *Namespace = + U->getQualifier().getAsNamespaceAndPrefix().Namespace; if (Namespace->getCanonicalDecl() == QualifierToRemove.getNestedNameSpecifier() - ->getAsNamespace() - ->getCanonicalDecl() && + .getAsNamespaceAndPrefix() + .Namespace->getCanonicalDecl() && U->getName() == Name) { return InsertionPointData(); } @@ -232,8 +227,9 @@ findInsertionPoint(const Tweak::Selection &Inputs, } bool isNamespaceForbidden(const Tweak::Selection &Inputs, - const NestedNameSpecifier &Namespace) { - const auto *NS = dyn_cast(Namespace.getAsNamespace()); + NestedNameSpecifier Namespace) { + const auto *NS = + dyn_cast(Namespace.getAsNamespaceAndPrefix().Namespace); if (!NS) return true; std::string NamespaceStr = printNamespaceScope(*NS); @@ -247,11 +243,11 @@ bool isNamespaceForbidden(const Tweak::Selection &Inputs, return false; } -std::string getNNSLAsString(NestedNameSpecifierLoc &NNSL, +std::string getNNSLAsString(NestedNameSpecifierLoc NNSL, const PrintingPolicy &Policy) { std::string Out; llvm::raw_string_ostream OutStream(Out); - NNSL.getNestedNameSpecifier()->print(OutStream, Policy); + NNSL.getNestedNameSpecifier().print(OutStream, Policy); return OutStream.str(); } @@ -276,16 +272,15 @@ bool AddUsing::prepare(const Selection &Inputs) { continue; } if (auto *T = Node->ASTNode.get()) { - if (T->getAs()) { + // Find the outermost TypeLoc. + if (Node->Parent->ASTNode.get()) + continue; + if (isa(T->getTypePtr())) break; - } - if (Node->Parent->ASTNode.get() || - Node->Parent->ASTNode.get()) { - // Node is TypeLoc, but it's parent is either TypeLoc or - // NestedNameSpecifier. In both cases, we want to go up, to find - // the outermost TypeLoc. + // Find the outermost TypeLoc. + if (Node->Parent->ASTNode.get()) continue; - } } break; } @@ -307,32 +302,70 @@ bool AddUsing::prepare(const Selection &Inputs) { MustInsertAfterLoc = D->getDecl()->getBeginLoc(); } } else if (auto *T = Node->ASTNode.get()) { - if (auto E = T->getAs()) { - QualifierToRemove = E.getQualifierLoc(); - - SpelledNameRange = E.getSourceRange(); - if (auto T = E.getNamedTypeLoc().getAs()) { - // Remove the template arguments from the name. - SpelledNameRange.setEnd(T.getLAngleLoc().getLocWithOffset(-1)); - } - - if (const auto *ET = E.getTypePtr()) { - if (const auto *TDT = - dyn_cast(ET->getNamedType().getTypePtr())) { - MustInsertAfterLoc = TDT->getDecl()->getBeginLoc(); - } else if (auto *TD = ET->getAsTagDecl()) { - MustInsertAfterLoc = TD->getBeginLoc(); - } - } + switch (T->getTypeLocClass()) { + case TypeLoc::TemplateSpecialization: { + auto TL = T->castAs(); + QualifierToRemove = TL.getQualifierLoc(); + if (!QualifierToRemove) + break; + SpelledNameRange = TL.getTemplateNameLoc(); + if (auto *TD = TL.getTypePtr()->getTemplateName().getAsTemplateDecl( + /*IgnoreDeduced=*/true)) + MustInsertAfterLoc = TD->getBeginLoc(); + break; + } + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: { + auto TL = T->castAs(); + QualifierToRemove = TL.getQualifierLoc(); + if (!QualifierToRemove) + break; + SpelledNameRange = TL.getNameLoc(); + MustInsertAfterLoc = TL.getOriginalDecl()->getBeginLoc(); + break; + } + case TypeLoc::Typedef: { + auto TL = T->castAs(); + QualifierToRemove = TL.getQualifierLoc(); + if (!QualifierToRemove) + break; + SpelledNameRange = TL.getNameLoc(); + MustInsertAfterLoc = TL.getDecl()->getBeginLoc(); + break; + } + case TypeLoc::UnresolvedUsing: { + auto TL = T->castAs(); + QualifierToRemove = TL.getQualifierLoc(); + if (!QualifierToRemove) + break; + SpelledNameRange = TL.getNameLoc(); + MustInsertAfterLoc = TL.getDecl()->getBeginLoc(); + break; + } + case TypeLoc::Using: { + auto TL = T->castAs(); + QualifierToRemove = TL.getQualifierLoc(); + if (!QualifierToRemove) + break; + SpelledNameRange = TL.getNameLoc(); + MustInsertAfterLoc = TL.getDecl()->getBeginLoc(); + break; + } + default: + break; } + if (QualifierToRemove) + SpelledNameRange.setBegin(QualifierToRemove.getBeginLoc()); } if (!QualifierToRemove || // FIXME: This only supports removing qualifiers that are made up of just // namespace names. If qualifier contains a type, we could take the // longest namespace prefix and remove that. - !QualifierToRemove.getNestedNameSpecifier()->getAsNamespace() || + QualifierToRemove.getNestedNameSpecifier().getKind() != + NestedNameSpecifier::Kind::Namespace || // Respect user config. - isNamespaceForbidden(Inputs, *QualifierToRemove.getNestedNameSpecifier())) + isNamespaceForbidden(Inputs, QualifierToRemove.getNestedNameSpecifier())) return false; // Macros are difficult. We only want to offer code action when what's spelled // under the cursor is a namespace qualifier. If it's a macro that expands to @@ -384,7 +417,7 @@ Expected AddUsing::apply(const Selection &Inputs) { llvm::raw_string_ostream UsingTextStream(UsingText); UsingTextStream << "using "; if (InsertionPoint->AlwaysFullyQualify && - !isFullyQualified(QualifierToRemove.getNestedNameSpecifier())) + !QualifierToRemove.getNestedNameSpecifier().isFullyQualified()) UsingTextStream << "::"; UsingTextStream << QualifierToSpell << SpelledName << ";" << InsertionPoint->Suffix; diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp index cd07cbf73635c..134ae89288300 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractFunction.cpp @@ -362,7 +362,7 @@ struct NewFunction { SourceLocation DefinitionPoint; std::optional ForwardDeclarationPoint; const CXXRecordDecl *EnclosingClass = nullptr; - const NestedNameSpecifier *DefinitionQualifier = nullptr; + NestedNameSpecifier DefinitionQualifier = std::nullopt; const DeclContext *SemanticDC = nullptr; const DeclContext *SyntacticDC = nullptr; const DeclContext *ForwardDeclarationSyntacticDC = nullptr; @@ -455,13 +455,12 @@ std::string NewFunction::renderQualifiers() const { } std::string NewFunction::renderDeclarationName(FunctionDeclKind K) const { - if (DefinitionQualifier == nullptr || K != OutOfLineDefinition) { + if (!DefinitionQualifier || K != OutOfLineDefinition) return Name; - } std::string QualifierName; llvm::raw_string_ostream Oss(QualifierName); - DefinitionQualifier->print(Oss, *LangOpts); + DefinitionQualifier.print(Oss, *LangOpts); return llvm::formatv("{0}{1}", QualifierName, Name); } diff --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp index 43cfc769f7f71..7e616968c6046 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp @@ -116,7 +116,7 @@ bool PopulateSwitch::prepare(const Selection &Sel) { EnumT = Cond->getType().getCanonicalType()->getAsAdjusted(); if (!EnumT) return false; - EnumD = EnumT->getDecl(); + EnumD = EnumT->getOriginalDecl(); if (!EnumD || EnumD->isDependentType()) return false; diff --git a/clang-tools-extra/clangd/unittests/ASTTests.cpp b/clang-tools-extra/clangd/unittests/ASTTests.cpp index d0bc3c4d7db98..76d46bad82224 100644 --- a/clang-tools-extra/clangd/unittests/ASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ASTTests.cpp @@ -421,7 +421,7 @@ TEST(ClangdAST, GetQualification) { { R"cpp( namespace ns1 { namespace ns2 { void Foo(); } } - void insert(); // ns2::Foo + void insert(); // ns1::ns2::Foo namespace ns1 { void insert(); // ns2::Foo namespace ns2 { @@ -429,7 +429,7 @@ TEST(ClangdAST, GetQualification) { } } )cpp", - {"ns2::", "ns2::", ""}, + {"ns1::ns2::", "ns2::", ""}, {"ns1::"}, }, { @@ -531,7 +531,8 @@ TEST(ClangdAST, PrintType) { ASSERT_EQ(InsertionPoints.size(), Case.Types.size()); for (size_t I = 0, E = InsertionPoints.size(); I != E; ++I) { const auto *DC = InsertionPoints[I]; - EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC), + EXPECT_EQ(printType(AST.getASTContext().getTypeDeclType(TargetDecl), *DC, + /*Placeholder=*/"", /*FullyQualify=*/true), Case.Types[I]); } } diff --git a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp index cb2c17ad4ef0d..5c857d0b8ae3e 100644 --- a/clang-tools-extra/clangd/unittests/DumpASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/DumpASTTests.cpp @@ -72,15 +72,14 @@ declaration: Namespace - root expression: BinaryOperator - + expression: ImplicitCast - LValueToRValue expression: DeclRef - x - specifier: TypeSpec + specifier: Type type: Record - S expression: ImplicitCast - LValueToRValue expression: Member - x expression: CXXBindTemporary expression: CXXTemporaryObject - S - type: Elaborated + type: Record - S specifier: Namespace - root:: - type: Record - S )"}, {R"cpp( namespace root { @@ -104,14 +103,13 @@ declaration: Namespace - root expression: BinaryOperator - + expression: ImplicitCast - LValueToRValue expression: DeclRef - x - specifier: TypeSpec + specifier: Type type: Record - S expression: ImplicitCast - LValueToRValue expression: Member - x expression: CXXTemporaryObject - S - type: Elaborated + type: Record - S specifier: Namespace - root:: - type: Record - S )"}, {R"cpp( namespace root { @@ -138,7 +136,7 @@ declaration: Namespace - root type: Builtin - unsigned int statement: Return expression: DependentScopeDeclRef - value - specifier: TypeSpec + specifier: Type type: TemplateTypeParm - T )"}, {R"cpp( @@ -154,8 +152,7 @@ declaration: Var - root expression: DeclRef - operator+ expression: MaterializeTemporary - lvalue expression: CXXTemporaryObject - Foo - type: Elaborated - type: Record - Foo + type: Record - Foo expression: IntegerLiteral - 42 )"}, {R"cpp( diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 4d77f9d690ca0..20fd23ed4fcdc 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -992,7 +992,7 @@ TEST_F(TargetDeclTest, DependentTypes) { )cpp"; EXPECT_DECLS("DependentNameTypeLoc", "struct B"); - // Heuristic resolution of dependent type name which doesn't get a TypeLoc + // Heuristic resolution of dependent type name within a NestedNameSpecifierLoc Code = R"cpp( template struct A { struct B { struct C {}; }; }; @@ -1000,7 +1000,7 @@ TEST_F(TargetDeclTest, DependentTypes) { template void foo(typename A::[[B]]::C); )cpp"; - EXPECT_DECLS("NestedNameSpecifierLoc", "struct B"); + EXPECT_DECLS("DependentNameTypeLoc", "struct B"); // Heuristic resolution of dependent type name whose qualifier is also // dependent diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 3331164ab0024..6407349d9af9b 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -2894,7 +2894,7 @@ TEST(Hover, All) { )cpp", [](HoverInfo &HI) { HI.Name = "this"; - HI.Definition = "const Foo *"; + HI.Definition = "const ns::Foo *"; }}, { R"cpp(// this expr for specialization class @@ -2910,7 +2910,7 @@ TEST(Hover, All) { )cpp", [](HoverInfo &HI) { HI.Name = "this"; - HI.Definition = "Foo *"; + HI.Definition = "ns::Foo *"; }}, { R"cpp(// this expr for partial specialization struct @@ -2926,7 +2926,7 @@ TEST(Hover, All) { )cpp", [](HoverInfo &HI) { HI.Name = "this"; - HI.Definition = "const Foo *"; + HI.Definition = "const ns::Foo *"; }}, { R"cpp( @@ -3046,8 +3046,8 @@ TEST(Hover, All) { HI.Kind = index::SymbolKind::Function; HI.NamespaceScope = ""; HI.Definition = "MyRect foobar()"; - HI.Type = {"MyRect ()", "MyRect ()"}; - HI.ReturnType = {"MyRect", "MyRect"}; + HI.Type = {"MyRect ()", "struct MyRect ()"}; + HI.ReturnType = {"MyRect", "struct MyRect"}; HI.Parameters.emplace(); }}, {R"cpp( diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index e0cd955bb1c9a..99e728c40063d 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -1295,14 +1295,7 @@ TEST(TypeHints, NoQualifiers) { } } )cpp", - ExpectedHint{": S1", "x"}, - // FIXME: We want to suppress scope specifiers - // here because we are into the whole - // brevity thing, but the ElaboratedType - // printer does not honor the SuppressScope - // flag by design, so we need to extend the - // PrintingPolicy to support this use case. - ExpectedHint{": S2::Inner", "y"}); + ExpectedHint{": S1", "x"}, ExpectedHint{": Inner", "y"}); } TEST(TypeHints, Lambda) { diff --git a/clang-tools-extra/clangd/unittests/QualityTests.cpp b/clang-tools-extra/clangd/unittests/QualityTests.cpp index 619ea32115357..4954659a45e02 100644 --- a/clang-tools-extra/clangd/unittests/QualityTests.cpp +++ b/clang-tools-extra/clangd/unittests/QualityTests.cpp @@ -121,7 +121,9 @@ TEST(QualityTests, SymbolRelevanceSignalExtraction) { SymbolRelevanceSignals Relevance; Relevance.merge(CodeCompletionResult(&findDecl(AST, "deprecated"), - /*Priority=*/42, nullptr, false, + /*Priority=*/42, + /*Qualifier=*/std::nullopt, + /*QualifierIsInformative=*/false, /*Accessible=*/false)); EXPECT_EQ(Relevance.NameMatch, SymbolRelevanceSignals().NameMatch); EXPECT_TRUE(Relevance.Forbidden); @@ -487,13 +489,15 @@ TEST(QualityTests, ItemWithFixItsRankedDown) { auto AST = Header.build(); SymbolRelevanceSignals RelevanceWithFixIt; - RelevanceWithFixIt.merge(CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr, - false, true, {FixItHint{}})); + RelevanceWithFixIt.merge(CodeCompletionResult( + &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt, + /*QualifierIsInformative=*/false, /*Accessible=*/true, {FixItHint{}})); EXPECT_TRUE(RelevanceWithFixIt.NeedsFixIts); SymbolRelevanceSignals RelevanceWithoutFixIt; - RelevanceWithoutFixIt.merge( - CodeCompletionResult(&findDecl(AST, "x"), 0, nullptr, false, true, {})); + RelevanceWithoutFixIt.merge(CodeCompletionResult( + &findDecl(AST, "x"), /*Priority=*/0, /*Qualifier=*/std::nullopt, + /*QualifierIsInformative=*/false, /*Accessible=*/true, {})); EXPECT_FALSE(RelevanceWithoutFixIt.NeedsFixIts); EXPECT_LT(RelevanceWithFixIt.evaluateHeuristics(), diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index aaaf758e72236..3df19d8fc174d 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -104,9 +104,9 @@ TEST(SelectionTest, CommonAncestor) { { R"cpp( template - int x = [[T::^U::]]ccc(); + int x = T::[[^U]]::ccc(); )cpp", - "NestedNameSpecifierLoc", + "DependentNameTypeLoc", }, { R"cpp( diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index 49cc13606f4c2..0cbf9a080a3ce 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -60,14 +60,10 @@ class ASTWalker : public RecursiveASTVisitor { NamedDecl *getMemberProvider(QualType Base) { if (Base->isPointerType()) return getMemberProvider(Base->getPointeeType()); - // Unwrap the sugar ElaboratedType. - if (const auto *ElTy = dyn_cast(Base)) - return getMemberProvider(ElTy->getNamedType()); - if (const auto *TT = dyn_cast(Base)) return TT->getDecl(); if (const auto *UT = dyn_cast(Base)) - return UT->getFoundDecl(); + return UT->getDecl(); // A heuristic: to resolve a template type to **only** its template name. // We're only using this method for the base type of MemberExpr, in general // the template provides the member, and the critical case `unique_ptr` @@ -135,16 +131,14 @@ class ASTWalker : public RecursiveASTVisitor { } bool qualifierIsNamespaceOrNone(DeclRefExpr *DRE) { - const auto *Qual = DRE->getQualifier(); - if (!Qual) - return true; - switch (Qual->getKind()) { - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Global: + NestedNameSpecifier Qual = DRE->getQualifier(); + switch (Qual.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Namespace: + case NestedNameSpecifier::Kind::Global: return true; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::Super: - case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Kind::Type: + case NestedNameSpecifier::Kind::MicrosoftSuper: return false; } llvm_unreachable("Unknown value for NestedNameSpecifierKind"); @@ -341,17 +335,17 @@ class ASTWalker : public RecursiveASTVisitor { } bool VisitUsingTypeLoc(UsingTypeLoc TL) { - reportType(TL.getNameLoc(), TL.getFoundDecl()); + reportType(TL.getNameLoc(), TL.getDecl()); return true; } bool VisitTagTypeLoc(TagTypeLoc TTL) { - reportType(TTL.getNameLoc(), TTL.getDecl()); + reportType(TTL.getNameLoc(), TTL.getOriginalDecl()); return true; } bool VisitTypedefTypeLoc(TypedefTypeLoc TTL) { - reportType(TTL.getNameLoc(), TTL.getTypedefNameDecl()); + reportType(TTL.getNameLoc(), TTL.getDecl()); return true; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp index b42d3fcd2b62b..35314d12b59bf 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/copy-constructor-init.cpp @@ -165,7 +165,6 @@ FROMMACRO class X15 : public CopyableAlias2 { X15(const X15 &other) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: calling a base constructor - // CHECK-FIXES: X15(const X15 &other) : Copyable5(other) {} }; class X16 : public NonCopyable { diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp index 721c55b1fb538..5dd23871b21b3 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable.cpp @@ -69,14 +69,14 @@ template T qux(T Generic) { async::Future PendingA = acquireUnits(); auto PendingB = acquireUnits(); - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'async::Future') [bugprone-unused-local-non-trivial-variable] async::Future MustBeUsed; // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unused local variable 'MustBeUsed' of type 'async::Future' [bugprone-unused-local-non-trivial-variable] PendingA.get(); async::Future TemplateType; // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future' [bugprone-unused-local-non-trivial-variable] a::Future AliasTemplateType; - // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future' (aka 'async::Future') [bugprone-unused-local-non-trivial-variable] [[maybe_unused]] async::Future MaybeUnused; return Generic; } @@ -86,7 +86,7 @@ async::Future Global; int bar(int Num) { a::Future PendingA = acquireUnits(); a::Future PendingB = acquireUnits(); // not used at all, unused variable not fired because of destructor side effect - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'Future') [bugprone-unused-local-non-trivial-variable] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'PendingB' of type 'a::Future' (aka 'async::Future') [bugprone-unused-local-non-trivial-variable] auto Num2 = PendingA.get(); auto Num3 = qux(Num); async::Ptr> Shared = async::Ptr>(acquireUnits()); diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp index 732cf5d34aca9..a38594aa94cbb 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/portability/std-allocator-const.cpp @@ -43,25 +43,25 @@ template class allocator {}; void simple(const std::vector &v, std::deque *d) { - // CHECK-MESSAGES: [[#@LINE-1]]:24: warning: container using std::allocator is a deprecated libc++ extension; remove const for compatibility with other standard libraries - // CHECK-MESSAGES: [[#@LINE-2]]:52: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:19: warning: container using std::allocator is a deprecated libc++ extension; remove const for compatibility with other standard libraries + // CHECK-MESSAGES: [[#@LINE-2]]:47: warning: container std::list l; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::multiset ms; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::set> s; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::unordered_multiset ums; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::unordered_set us; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container absl::flat_hash_set fhs; - // CHECK-MESSAGES: [[#@LINE-1]]:9: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container using my_vector = std::vector; - // CHECK-MESSAGES: [[#@LINE-1]]:26: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:21: warning: container my_vector v1; using my_vector2 = my_vector; @@ -76,7 +76,7 @@ void simple(const std::vector &v, std::deque *d) { template void temp1() { std::vector v; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::vector neg1; std::forward_list neg2; @@ -87,7 +87,7 @@ template void temp2() { // Match std::vector for the uninstantiated temp2. std::vector v; - // CHECK-MESSAGES: [[#@LINE-1]]:8: warning: container + // CHECK-MESSAGES: [[#@LINE-1]]:3: warning: container std::vector neg1; std::forward_list neg2; diff --git a/clang/bindings/python/tests/cindex/test_type.py b/clang/bindings/python/tests/cindex/test_type.py index 34081bb88f3dd..cc101beca8cc5 100644 --- a/clang/bindings/python/tests/cindex/test_type.py +++ b/clang/bindings/python/tests/cindex/test_type.py @@ -63,7 +63,7 @@ def test_a_struct(self): self.assertIsNotNone(fields[1].translation_unit) self.assertEqual(fields[1].spelling, "b") self.assertFalse(fields[1].type.is_const_qualified()) - self.assertEqual(fields[1].type.kind, TypeKind.ELABORATED) + self.assertEqual(fields[1].type.kind, TypeKind.TYPEDEF) self.assertEqual(fields[1].type.get_canonical().kind, TypeKind.INT) self.assertEqual(fields[1].type.get_declaration().spelling, "I") self.assertEqual(fields[1].type.get_typedef_name(), "I") diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 7ccac4481b14c..72da0059744f2 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_AST_ASTCONCEPT_H #include "clang/AST/DeclarationName.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/TemplateBase.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/UnsignedOrNone.h" @@ -177,12 +177,7 @@ class ConceptReference { SourceLocation getLocation() const { return getConceptNameLoc(); } - SourceLocation getBeginLoc() const LLVM_READONLY { - // Note that if the qualifier is null the template KW must also be null. - if (auto QualifierLoc = getNestedNameSpecifierLoc()) - return QualifierLoc.getBeginLoc(); - return getConceptNameInfo().getBeginLoc(); - } + SourceLocation getBeginLoc() const LLVM_READONLY; SourceLocation getEndLoc() const LLVM_READONLY { return getTemplateArgsAsWritten() && diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 00dfcd46aabc2..7c2566a09665d 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -283,11 +283,11 @@ class ASTContext : public RefCountedBase { llvm::to_underlying(PredefinedSugarType::Kind::Last) + 1> PredefinedSugarTypes{}; - /// The set of nested name specifiers. + /// Internal storage for NestedNameSpecifiers. /// /// This set is managed by the NestedNameSpecifier class. - mutable llvm::FoldingSet NestedNameSpecifiers; - mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr; + mutable llvm::FoldingSet + NamespaceAndPrefixStorages; /// A cache mapping from RecordDecls to ASTRecordLayouts. /// @@ -1629,7 +1629,7 @@ class ASTContext : public RefCountedBase { /// Return the uniqued reference to the type for a member pointer to /// the specified type in the specified nested name. - QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier, + QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const; /// Return a non-unique reference to the type for a variable array of @@ -1930,7 +1930,7 @@ class ASTContext : public RefCountedBase { const IdentifierInfo *MacroII) const; QualType getDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, + NestedNameSpecifier NNS, const IdentifierInfo *Name) const; QualType getDependentTemplateSpecializationType( @@ -2504,7 +2504,7 @@ class ASTContext : public RefCountedBase { UnresolvedSetIterator End) const; TemplateName getAssumedTemplateName(DeclarationName Name) const; - TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, + TemplateName getQualifiedTemplateName(NestedNameSpecifier Qualifier, bool TemplateKeyword, TemplateName Template) const; TemplateName @@ -2946,32 +2946,6 @@ class ASTContext : public RefCountedBase { /// Determine if two types are similar, ignoring only CVR qualifiers. bool hasCvrSimilarType(QualType T1, QualType T2); - /// Retrieves the "canonical" nested name specifier for a - /// given nested name specifier. - /// - /// The canonical nested name specifier is a nested name specifier - /// that uniquely identifies a type or namespace within the type - /// system. For example, given: - /// - /// \code - /// namespace N { - /// struct S { - /// template struct X { typename T* type; }; - /// }; - /// } - /// - /// template struct Y { - /// typename N::S::X::type member; - /// }; - /// \endcode - /// - /// Here, the nested-name-specifier for N::S::X:: will be - /// S::X, since 'S' and 'X' are uniquely defined - /// by declarations in the type system and the canonical type for - /// the template type parameter 'T' is template-param-0-0. - NestedNameSpecifier * - getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const; - /// Retrieves the default calling convention for the current context. /// /// The context's default calling convention may differ from the current diff --git a/clang/include/clang/AST/ASTImporter.h b/clang/include/clang/AST/ASTImporter.h index c40b92666a2ff..4a0ca45b785a9 100644 --- a/clang/include/clang/AST/ASTImporter.h +++ b/clang/include/clang/AST/ASTImporter.h @@ -404,7 +404,7 @@ class TypeSourceInfo; /// /// \returns The equivalent nested-name-specifier in the "to" /// context, or the import error. - llvm::Expected Import(NestedNameSpecifier *FromNNS); + llvm::Expected Import(NestedNameSpecifier FromNNS); /// Import the given nested-name-specifier-loc from the "from" /// context into the "to" context. diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 1d846a1f9df35..d9dc8290b0e49 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -394,12 +394,14 @@ class ASTNodeTraverser } void VisitMemberPointerType(const MemberPointerType *T) { // FIXME: Provide a NestedNameSpecifier visitor. - NestedNameSpecifier *Qualifier = T->getQualifier(); - if (NestedNameSpecifier::SpecifierKind K = Qualifier->getKind(); - K == NestedNameSpecifier::TypeSpec) - Visit(Qualifier->getAsType()); + NestedNameSpecifier Qualifier = T->getQualifier(); + if (NestedNameSpecifier::Kind K = Qualifier.getKind(); + K == NestedNameSpecifier::Kind::Type) + Visit(Qualifier.getAsType()); if (T->isSugared()) - Visit(T->getMostRecentCXXRecordDecl()->getTypeForDecl()); + Visit(cast(T->getCanonicalTypeUnqualified()) + ->getQualifier() + .getAsType()); Visit(T->getPointeeType()); } void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); } diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h index d63cbf405fba1..6f40705fb7436 100644 --- a/clang/include/clang/AST/ASTTypeTraits.h +++ b/clang/include/clang/AST/ASTTypeTraits.h @@ -336,9 +336,9 @@ class DynTypedNode { NodeKind)) { auto NNSLA = getUnchecked(); auto NNSLB = Other.getUnchecked(); - return std::make_pair(NNSLA.getNestedNameSpecifier(), + return std::make_pair(NNSLA.getNestedNameSpecifier().getAsVoidPointer(), NNSLA.getOpaqueData()) < - std::make_pair(NNSLB.getNestedNameSpecifier(), + std::make_pair(NNSLB.getNestedNameSpecifier().getAsVoidPointer(), NNSLB.getOpaqueData()); } @@ -393,8 +393,9 @@ class DynTypedNode { if (ASTNodeKind::getFromNodeKind().isSame( Val.NodeKind)) { auto NNSL = Val.getUnchecked(); - return llvm::hash_combine(NNSL.getNestedNameSpecifier(), - NNSL.getOpaqueData()); + return llvm::hash_combine( + NNSL.getNestedNameSpecifier().getAsVoidPointer(), + NNSL.getOpaqueData()); } assert(Val.getMemoizationData()); @@ -539,8 +540,8 @@ struct DynTypedNode::BaseConverter< : public DynCastPtrConverter {}; template <> -struct DynTypedNode::BaseConverter< - NestedNameSpecifier, void> : public PtrConverter {}; +struct DynTypedNode::BaseConverter + : public ValueConverter {}; template <> struct DynTypedNode::BaseConverter< diff --git a/clang/include/clang/AST/AbstractBasicReader.h b/clang/include/clang/AST/AbstractBasicReader.h index 8f5fdc9d93c78..26052b8086cf7 100644 --- a/clang/include/clang/AST/AbstractBasicReader.h +++ b/clang/include/clang/AST/AbstractBasicReader.h @@ -252,39 +252,34 @@ class DataStreamBasicReader : public BasicReaderBase { return EffectConditionExpr{asImpl().readExprRef()}; } - NestedNameSpecifier *readNestedNameSpecifier() { + NestedNameSpecifier readNestedNameSpecifier() { auto &ctx = getASTContext(); // We build this up iteratively. - NestedNameSpecifier *cur = nullptr; + NestedNameSpecifier cur = std::nullopt; uint32_t depth = asImpl().readUInt32(); for (uint32_t i = 0; i != depth; ++i) { auto kind = asImpl().readNestedNameSpecifierKind(); switch (kind) { - case NestedNameSpecifier::Identifier: - cur = NestedNameSpecifier::Create(ctx, cur, - asImpl().readIdentifier()); + case NestedNameSpecifier::Kind::Namespace: + cur = + NestedNameSpecifier(ctx, asImpl().readNamespaceBaseDeclRef(), cur); continue; - - case NestedNameSpecifier::Namespace: - cur = NestedNameSpecifier::Create(ctx, cur, - asImpl().readNamespaceBaseDeclRef()); + case NestedNameSpecifier::Kind::Type: + assert(!cur); + cur = NestedNameSpecifier(asImpl().readQualType().getTypePtr()); continue; - - case NestedNameSpecifier::TypeSpec: - cur = NestedNameSpecifier::Create(ctx, cur, - asImpl().readQualType().getTypePtr()); + case NestedNameSpecifier::Kind::Global: + assert(!cur); + cur = NestedNameSpecifier::getGlobal(); continue; - - case NestedNameSpecifier::Global: - cur = NestedNameSpecifier::GlobalSpecifier(ctx); - continue; - - case NestedNameSpecifier::Super: - cur = NestedNameSpecifier::SuperSpecifier(ctx, - asImpl().readCXXRecordDeclRef()); + case NestedNameSpecifier::Kind::MicrosoftSuper: + assert(!cur); + cur = NestedNameSpecifier(asImpl().readCXXRecordDeclRef()); continue; + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } llvm_unreachable("bad nested name specifier kind"); } diff --git a/clang/include/clang/AST/AbstractBasicWriter.h b/clang/include/clang/AST/AbstractBasicWriter.h index fbbaba5f7327b..d41e655986ef9 100644 --- a/clang/include/clang/AST/AbstractBasicWriter.h +++ b/clang/include/clang/AST/AbstractBasicWriter.h @@ -229,42 +229,43 @@ class DataStreamBasicWriter : public BasicWriterBase { asImpl().writeExprRef(CE.getCondition()); } - void writeNestedNameSpecifier(NestedNameSpecifier *NNS) { + void writeNestedNameSpecifier(NestedNameSpecifier NNS) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. - SmallVector nestedNames; + SmallVector nestedNames; // Push each of the NNS's onto a stack for serialization in reverse order. while (NNS) { nestedNames.push_back(NNS); - NNS = NNS->getPrefix(); + NNS = NNS.getKind() == NestedNameSpecifier::Kind::Namespace + ? NNS.getAsNamespaceAndPrefix().Prefix + : std::nullopt; } asImpl().writeUInt32(nestedNames.size()); while (!nestedNames.empty()) { NNS = nestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind kind = NNS->getKind(); + NestedNameSpecifier::Kind kind = NNS.getKind(); asImpl().writeNestedNameSpecifierKind(kind); switch (kind) { - case NestedNameSpecifier::Identifier: - asImpl().writeIdentifier(NNS->getAsIdentifier()); + case NestedNameSpecifier::Kind::Namespace: + asImpl().writeNamespaceBaseDeclRef( + NNS.getAsNamespaceAndPrefix().Namespace); continue; - - case NestedNameSpecifier::Namespace: - asImpl().writeNamespaceBaseDeclRef(NNS->getAsNamespace()); - continue; - - case NestedNameSpecifier::TypeSpec: - asImpl().writeQualType(QualType(NNS->getAsType(), 0)); + case NestedNameSpecifier::Kind::Type: + asImpl().writeQualType(QualType(NNS.getAsType(), 0)); continue; - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: // Don't need to write an associated value. continue; - case NestedNameSpecifier::Super: - asImpl().writeDeclRef(NNS->getAsRecordDecl()); + case NestedNameSpecifier::Kind::MicrosoftSuper: + asImpl().writeDeclRef(NNS.getAsMicrosoftSuper()); continue; + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } llvm_unreachable("bad nested name specifier kind"); } diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h index 10dab7fbdfa77..b5a4e94e1330a 100644 --- a/clang/include/clang/AST/CanonicalType.h +++ b/clang/include/clang/AST/CanonicalType.h @@ -453,7 +453,7 @@ template<> struct CanProxyAdaptor : public CanProxyBase { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier, getQualifier) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *, getMostRecentCXXRecordDecl) }; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f95a98d88adb9..400d3686076ae 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -20,7 +20,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" @@ -833,9 +833,9 @@ class DeclaratorDecl : public ValueDecl { /// Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : nullptr; + : std::nullopt; } /// Retrieve the nested-name-specifier (with source-location @@ -3943,9 +3943,9 @@ class TagDecl : public TypeDecl, /// Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() - : nullptr; + : std::nullopt; } /// Retrieve the nested-name-specifier (with source-location diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 5ac664202db6d..c6326a8ba506d 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -622,6 +622,12 @@ class alignas(8) Decl { void setReferenced(bool R = true) { Referenced = R; } + /// When doing manipulations which might change the computed linkage, + /// such as changing the DeclContext after the declaration has already been + /// used, invalidating the cache will make sure its linkage will be + /// recomputed. + void invalidateCachedLinkage() { setCachedLinkage(Linkage::Invalid); } + /// Whether this declaration is a top-level declaration (function, /// global variable, etc.) that is lexically inside an objc container /// definition. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index d9b222067c41b..1d2ef0f4f2319 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -3136,7 +3136,7 @@ class UsingDirectiveDecl : public NamedDecl { /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3257,7 +3257,7 @@ class NamespaceAliasDecl : public NamespaceBaseDecl, /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3619,7 +3619,7 @@ class UsingDecl : public BaseUsingDecl, public Mergeable { NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3809,13 +3809,11 @@ class UsingEnumDecl : public BaseUsingDecl, public Mergeable { /// The source location of the 'enum' keyword. SourceLocation getEnumLoc() const { return EnumLocation; } void setEnumLoc(SourceLocation L) { EnumLocation = L; } - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return getQualifierLoc().getNestedNameSpecifier(); } NestedNameSpecifierLoc getQualifierLoc() const { - if (auto ETL = EnumType->getTypeLoc().getAs()) - return ETL.getQualifierLoc(); - return NestedNameSpecifierLoc(); + return getEnumTypeLoc().getPrefix(); } // Returns the "qualifier::Name" part as a TypeLoc. TypeLoc getEnumTypeLoc() const { @@ -3975,7 +3973,7 @@ class UnresolvedUsingValueDecl : public ValueDecl, NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -4065,7 +4063,7 @@ class UnresolvedUsingTypenameDecl NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h index bdcaabc143cc4..c4395259f0758 100644 --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -293,7 +293,7 @@ inline TypeDependence toSemanticDependence(TypeDependence D) { } inline NestedNameSpecifierDependence -toNestedNameSpecifierDependendence(TypeDependence D) { +toNestedNameSpecifierDependence(TypeDependence D) { return Dependence(D).nestedNameSpecifier(); } diff --git a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h index 0bcd67322c7f6..7b5bdca318348 100644 --- a/clang/include/clang/AST/DynamicRecursiveASTVisitor.h +++ b/clang/include/clang/AST/DynamicRecursiveASTVisitor.h @@ -134,8 +134,7 @@ template class DynamicRecursiveASTVisitorBase { /// Recursively visit a C++ nested-name-specifier. /// /// \returns false if the visitation was terminated early, true otherwise. - virtual bool - TraverseNestedNameSpecifier(MaybeConst *NNS); + virtual bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS); /// Recursively visit a C++ nested-name-specifier with location /// information. diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 5653b2549ac3c..77d0912d1f41b 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -1369,7 +1369,7 @@ class DeclRefExpr final /// If the name was qualified, retrieves the nested-name-specifier /// that precedes the name. Otherwise, returns NULL. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return getQualifierLoc().getNestedNameSpecifier(); } @@ -3398,7 +3398,7 @@ class MemberExpr final /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return getQualifierLoc().getNestedNameSpecifier(); } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 7a26934de6259..5508890f12b58 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2781,7 +2781,7 @@ class CXXPseudoDestructorExpr : public Expr { /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// null. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3222,7 +3222,7 @@ class OverloadExpr : public Expr { SourceLocation getNameLoc() const { return NameInfo.getLoc(); } /// Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3540,7 +3540,7 @@ class DependentScopeDeclRefExpr final /// Retrieve the nested-name-specifier that qualifies this /// declaration. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3955,7 +3955,7 @@ class CXXDependentScopeMemberExpr final } /// Retrieve the nested-name-specifier that qualifies the member name. - NestedNameSpecifier *getQualifier() const { + NestedNameSpecifier getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } diff --git a/clang/include/clang/AST/NestedNameSpecifier.h b/clang/include/clang/AST/NestedNameSpecifier.h index 1614f9d7c94e4..f198a8bca9078 100644 --- a/clang/include/clang/AST/NestedNameSpecifier.h +++ b/clang/include/clang/AST/NestedNameSpecifier.h @@ -6,507 +6,266 @@ // //===----------------------------------------------------------------------===// // -// This file defines the NestedNameSpecifier class, which represents -// a C++ nested-name-specifier. +// This file completes the definition of the NestedNameSpecifier class. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H -#include "clang/AST/DependenceFlags.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/AST/Decl.h" +#include "clang/AST/NestedNameSpecifierBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/Support/Compiler.h" -#include -#include -#include namespace clang { -class ASTContext; -class CXXRecordDecl; -class IdentifierInfo; -class LangOptions; -class NamespaceBaseDecl; -struct PrintingPolicy; -class Type; -class TypeLoc; - -/// Represents a C++ nested name specifier, such as -/// "\::std::vector::". -/// -/// C++ nested name specifiers are the prefixes to qualified -/// names. For example, "foo::" in "foo::x" is a nested name -/// specifier. Nested name specifiers are made up of a sequence of -/// specifiers, each of which can be a namespace, type, identifier -/// (for dependent names), decltype specifier, or the global specifier ('::'). -/// The last two specifiers can only appear at the start of a -/// nested-namespace-specifier. -class NestedNameSpecifier : public llvm::FoldingSetNode { - /// Enumeration describing - enum StoredSpecifierKind { - StoredIdentifier = 0, - StoredDecl = 1, - StoredTypeSpec = 2 - }; - - /// The nested name specifier that precedes this nested name - /// specifier. - /// - /// The pointer is the nested-name-specifier that precedes this - /// one. The integer stores one of the first four values of type - /// SpecifierKind. - llvm::PointerIntPair Prefix; - - /// The last component in the nested name specifier, which - /// can be an identifier, a declaration, or a type. - /// - /// When the pointer is NULL, this specifier represents the global - /// specifier '::'. Otherwise, the pointer is one of - /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of - /// specifier as encoded within the prefix. - void* Specifier = nullptr; - -public: - /// The kind of specifier that completes this nested name - /// specifier. - enum SpecifierKind { - /// An identifier, stored as an IdentifierInfo*. - Identifier, - - /// A namespace-like entity, stored as a NamespaceBaseDecl*. - Namespace, - - /// A type, stored as a Type*. - TypeSpec, - - /// The global specifier '::'. There is no stored value. - Global, - - /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of - /// the class it appeared in. - Super - }; - -private: - /// Builds the global specifier. - NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} - - /// Copy constructor used internally to clone nested name - /// specifiers. - NestedNameSpecifier(const NestedNameSpecifier &Other) = default; - - /// Either find or insert the given nested name specifier - /// mockup in the given context. - static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, - const NestedNameSpecifier &Mockup); - -public: - NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; - - /// Builds a specifier combining a prefix and an identifier. - /// - /// The prefix must be dependent, since nested name specifiers - /// referencing an identifier are only permitted when the identifier - /// cannot be resolved. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const IdentifierInfo *II); - - /// Builds a nested name specifier that names a namespace or namespace alias. - static NestedNameSpecifier *Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceBaseDecl *NS); - - /// Builds a nested name specifier that names a type. - static NestedNameSpecifier * - Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const Type *T); - - /// Builds a specifier that consists of just an identifier. - /// - /// The nested-name-specifier is assumed to be dependent, but has no - /// prefix because the prefix is implied by something outside of the - /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent - /// type. - static NestedNameSpecifier *Create(const ASTContext &Context, - const IdentifierInfo *II); - - /// Returns the nested name specifier representing the global - /// scope. - static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); - - /// Returns the nested name specifier representing the __super scope - /// for the given CXXRecordDecl. - static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, - CXXRecordDecl *RD); - - /// Return the prefix of this nested name specifier. - /// - /// The prefix contains all of the parts of the nested name - /// specifier that precede this current specifier. For example, for a - /// nested name specifier that represents "foo::bar::", the current - /// specifier will contain "bar::" and the prefix will contain - /// "foo::". - NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } - - /// Determine what kind of nested name specifier is stored. - SpecifierKind getKind() const; - - /// Retrieve the identifier stored in this nested name - /// specifier. - IdentifierInfo *getAsIdentifier() const { - if (Prefix.getInt() == StoredIdentifier) - return (IdentifierInfo *)Specifier; - - return nullptr; +auto NestedNameSpecifier::getKind() const -> Kind { + if (!isStoredKind()) { + switch (getFlagKind()) { + case FlagKind::Null: + return Kind::Null; + case FlagKind::Global: + return Kind::Global; + case FlagKind::Invalid: + llvm_unreachable("use of invalid NestedNameSpecifier"); + } + llvm_unreachable("unhandled FlagKind"); } + switch (auto [K, Ptr] = getStored(); K) { + case StoredKind::Type: + return Kind::Type; + case StoredKind::NamespaceWithGlobal: + case StoredKind::NamespaceWithNamespace: + return Kind::Namespace; + case StoredKind::NamespaceOrSuper: + switch (static_cast(Ptr)->getKind()) { + case Decl::Namespace: + case Decl::NamespaceAlias: + return Kind::Namespace; + case Decl::CXXRecord: + case Decl::ClassTemplateSpecialization: + case Decl::ClassTemplatePartialSpecialization: + return Kind::MicrosoftSuper; + default: + llvm_unreachable("unexpected decl kind"); + } + } + llvm_unreachable("unknown StoredKind"); +} - /// Retrieve the namespace or namespace alias stored in this nested name - /// specifier. - NamespaceBaseDecl *getAsNamespace() const; - - /// Retrieve the record declaration stored in this nested name - /// specifier. - CXXRecordDecl *getAsRecordDecl() const; - - /// Retrieve the type stored in this nested name specifier. - const Type *getAsType() const { - if (Prefix.getInt() == StoredTypeSpec) - return (const Type *)Specifier; +NestedNameSpecifier::NestedNameSpecifier(const Type *T) + : NestedNameSpecifier({StoredKind::Type, T}) { + assert(getKind() == Kind::Type); +} - return nullptr; +auto NestedNameSpecifier::MakeNamespacePtrKind( + const ASTContext &Ctx, const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix) -> PtrKind { + switch (Prefix.getKind()) { + case Kind::Null: + return {StoredKind::NamespaceOrSuper, Namespace}; + case Kind::Global: + return {StoredKind::NamespaceWithGlobal, Namespace}; + case Kind::Namespace: + return {StoredKind::NamespaceWithNamespace, + MakeNamespaceAndPrefixStorage(Ctx, Namespace, Prefix)}; + case Kind::MicrosoftSuper: + case Kind::Type: + llvm_unreachable("invalid prefix for namespace"); } + llvm_unreachable("unhandled kind"); +} - /// Fully translate this nested name specifier to a type. - /// Unlike getAsType, this will convert this entire nested - /// name specifier chain into its equivalent type. - const Type *translateToType(const ASTContext &Context) const; +/// Builds a nested name specifier that names a namespace. +NestedNameSpecifier::NestedNameSpecifier(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix) + : NestedNameSpecifier(MakeNamespacePtrKind(Ctx, Namespace, Prefix)) { + assert(getKind() == Kind::Namespace); +} - NestedNameSpecifierDependence getDependence() const; +/// Builds a nested name specifier that names a class through microsoft's +/// __super specifier. +NestedNameSpecifier::NestedNameSpecifier(CXXRecordDecl *RD) + : NestedNameSpecifier({StoredKind::NamespaceOrSuper, RD}) { + assert(getKind() == Kind::MicrosoftSuper); +} - /// Whether this nested name specifier refers to a dependent - /// type or not. - bool isDependent() const; +CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { + switch (getKind()) { + case Kind::MicrosoftSuper: + return getAsMicrosoftSuper(); + case Kind::Type: + return getAsType()->getAsCXXRecordDecl(); + case Kind::Global: + case Kind::Namespace: + case Kind::Null: + return nullptr; + } + llvm_unreachable("Invalid NNS Kind!"); +} - /// Whether this nested name specifier involves a template - /// parameter. - bool isInstantiationDependent() const; +NestedNameSpecifier NestedNameSpecifier::getCanonical() const { + switch (getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: + // These are canonical and unique. + return *this; + case NestedNameSpecifier::Kind::Namespace: { + // A namespace is canonical; build a nested-name-specifier with + // this namespace and no prefix. + const NamespaceBaseDecl *ND = getAsNamespaceAndPrefix().Namespace; + return NestedNameSpecifier( + {StoredKind::NamespaceOrSuper, ND->getNamespace()->getCanonicalDecl()}); + } + case NestedNameSpecifier::Kind::Type: + return NestedNameSpecifier( + getAsType()->getCanonicalTypeInternal().getTypePtr()); + } + llvm_unreachable("unhandled kind"); +} - /// Whether this nested-name-specifier contains an unexpanded - /// parameter pack (for C++11 variadic templates). - bool containsUnexpandedParameterPack() const; +bool NestedNameSpecifier::isCanonical() const { + return *this == getCanonical(); +} - /// Whether this nested name specifier contains an error. - bool containsErrors() const; +TypeLoc NestedNameSpecifierLoc::castAsTypeLoc() const { + return TypeLoc(Qualifier.getAsType(), LoadPointer(/*Offset=*/0)); +} - /// Print this nested name specifier to the given output stream. If - /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. - /// `ns::SomeTemplate` instead of - /// `ns::SomeTemplate`. - void print(raw_ostream &OS, const PrintingPolicy &Policy, - bool ResolveTemplateArguments = false, - bool PrintFinalScopeResOp = true) const; +TypeLoc NestedNameSpecifierLoc::getAsTypeLoc() const { + if (Qualifier.getKind() != NestedNameSpecifier::Kind::Type) + return TypeLoc(); + return castAsTypeLoc(); +} - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddPointer(Prefix.getOpaqueValue()); - ID.AddPointer(Specifier); +unsigned +NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier Qualifier) { + // Location of the trailing '::'. + unsigned Length = sizeof(SourceLocation::UIntTy); + + switch (Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Global: + // Nothing more to add. + break; + + case NestedNameSpecifier::Kind::Namespace: + case NestedNameSpecifier::Kind::MicrosoftSuper: + // The location of the identifier or namespace name. + Length += sizeof(SourceLocation::UIntTy); + break; + + case NestedNameSpecifier::Kind::Type: + // The "void*" that points at the TypeLoc data. + // Note: the 'template' keyword is part of the TypeLoc. + Length += sizeof(void *); + break; + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("Expected a non-NULL qualifier"); } - /// Dump the nested name specifier to standard output to aid - /// in debugging. - void dump(const LangOptions &LO) const; - void dump() const; - void dump(llvm::raw_ostream &OS) const; - void dump(llvm::raw_ostream &OS, const LangOptions &LO) const; -}; + return Length; +} -/// A C++ nested-name-specifier augmented with source location -/// information. -class NestedNameSpecifierLoc { - NestedNameSpecifier *Qualifier = nullptr; - void *Data = nullptr; - - /// Determines the data length for the last component in the - /// given nested-name-specifier. - static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); - - /// Determines the data length for the entire - /// nested-name-specifier. - static unsigned getDataLength(NestedNameSpecifier *Qualifier); - -public: - /// Construct an empty nested-name-specifier. - NestedNameSpecifierLoc() = default; - - /// Construct a nested-name-specifier with source location information - /// from - NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) - : Qualifier(Qualifier), Data(Data) {} - - /// Evaluates true when this nested-name-specifier location is - /// non-empty. - explicit operator bool() const { return Qualifier; } - - /// Evaluates true when this nested-name-specifier location is - /// non-empty. - bool hasQualifier() const { return Qualifier; } - - /// Retrieve the nested-name-specifier to which this instance - /// refers. - NestedNameSpecifier *getNestedNameSpecifier() const { - return Qualifier; - } +NamespaceAndPrefixLoc NestedNameSpecifierLoc::castAsNamespaceAndPrefix() const { + auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix(); + return {Namespace, NestedNameSpecifierLoc(Prefix, Data)}; +} - /// Retrieve the opaque pointer that refers to source-location data. - void *getOpaqueData() const { return Data; } - - /// Retrieve the source range covering the entirety of this - /// nested-name-specifier. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector::, the returned source range would cover - /// from the initial '::' to the last '::'. - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getBeginLoc(), getEndLoc()); - } +NamespaceAndPrefixLoc NestedNameSpecifierLoc::getAsNamespaceAndPrefix() const { + if (Qualifier.getKind() != NestedNameSpecifier::Kind::Namespace) + return {}; + return castAsNamespaceAndPrefix(); +} - /// Retrieve the source range covering just the last part of - /// this nested-name-specifier, not including the prefix. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector::, the returned source range would cover - /// from "vector" to the last '::'. - SourceRange getLocalSourceRange() const; - - /// Retrieve the location of the beginning of this - /// nested-name-specifier. - SourceLocation getBeginLoc() const { - if (!Qualifier) - return SourceLocation(); - - NestedNameSpecifierLoc First = *this; - while (NestedNameSpecifierLoc Prefix = First.getPrefix()) - First = Prefix; - return First.getLocalSourceRange().getBegin(); +unsigned NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier Qualifier) { + unsigned Length = 0; + for (; Qualifier; Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix) { + Length += getLocalDataLength(Qualifier); + if (Qualifier.getKind() != NestedNameSpecifier::Kind::Namespace) + break; } + return Length; +} - /// Retrieve the location of the end of this - /// nested-name-specifier. - SourceLocation getEndLoc() const { return getLocalSourceRange().getEnd(); } +unsigned NestedNameSpecifierLoc::getDataLength() const { + return getDataLength(Qualifier); +} - /// Retrieve the location of the beginning of this - /// component of the nested-name-specifier. - SourceLocation getLocalBeginLoc() const { - return getLocalSourceRange().getBegin(); +SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { + switch (auto Kind = Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: + return SourceRange(); + case NestedNameSpecifier::Kind::Global: + return LoadSourceLocation(/*Offset=*/0); + case NestedNameSpecifier::Kind::Namespace: + case NestedNameSpecifier::Kind::MicrosoftSuper: { + unsigned Offset = + Kind == NestedNameSpecifier::Kind::Namespace + ? getDataLength(Qualifier.getAsNamespaceAndPrefix().Prefix) + : 0; + return SourceRange( + LoadSourceLocation(Offset), + LoadSourceLocation(Offset + sizeof(SourceLocation::UIntTy))); } - - /// Retrieve the location of the end of this component of the - /// nested-name-specifier. - SourceLocation getLocalEndLoc() const { - return getLocalSourceRange().getEnd(); + case NestedNameSpecifier::Kind::Type: { + // The "void*" that points at the TypeLoc data. + // Note: the 'template' keyword is part of the TypeLoc. + void *TypeData = LoadPointer(/*Offset=*/0); + TypeLoc TL(Qualifier.getAsType(), TypeData); + return SourceRange(TL.getBeginLoc(), LoadSourceLocation(sizeof(void *))); } - - /// Return the prefix of this nested-name-specifier. - /// - /// For example, if this instance refers to a nested-name-specifier - /// \c \::std::vector::, the prefix is \c \::std::. Note that the - /// returned prefix may be empty, if this is the first component of - /// the nested-name-specifier. - NestedNameSpecifierLoc getPrefix() const { - if (!Qualifier) - return *this; - - return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); } - /// For a nested-name-specifier that refers to a type, - /// retrieve the type with source-location information. - TypeLoc getTypeLoc() const; + llvm_unreachable("Invalid NNS Kind!"); +} - /// Determines the data length for the entire - /// nested-name-specifier. - unsigned getDataLength() const { return getDataLength(Qualifier); } +SourceRange NestedNameSpecifierLoc::getSourceRange() const { + return SourceRange(getBeginLoc(), getEndLoc()); +} - friend bool operator==(NestedNameSpecifierLoc X, - NestedNameSpecifierLoc Y) { - return X.Qualifier == Y.Qualifier && X.Data == Y.Data; - } +SourceLocation NestedNameSpecifierLoc::getEndLoc() const { + return getLocalSourceRange().getEnd(); +} - friend bool operator!=(NestedNameSpecifierLoc X, - NestedNameSpecifierLoc Y) { - return !(X == Y); - } -}; +/// Retrieve the location of the beginning of this +/// component of the nested-name-specifier. +SourceLocation NestedNameSpecifierLoc::getLocalBeginLoc() const { + return getLocalSourceRange().getBegin(); +} -/// Class that aids in the construction of nested-name-specifiers along -/// with source-location information for all of the components of the +/// Retrieve the location of the end of this component of the /// nested-name-specifier. -class NestedNameSpecifierLocBuilder { - /// The current representation of the nested-name-specifier we're - /// building. - NestedNameSpecifier *Representation = nullptr; - - /// Buffer used to store source-location information for the - /// nested-name-specifier. - /// - /// Note that we explicitly manage the buffer (rather than using a - /// SmallVector) because \c Declarator expects it to be possible to memcpy() - /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. - char *Buffer = nullptr; - - /// The size of the buffer used to store source-location information - /// for the nested-name-specifier. - unsigned BufferSize = 0; - - /// The capacity of the buffer used to store source-location - /// information for the nested-name-specifier. - unsigned BufferCapacity = 0; - -public: - NestedNameSpecifierLocBuilder() = default; - NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); - - NestedNameSpecifierLocBuilder & - operator=(const NestedNameSpecifierLocBuilder &Other); - - ~NestedNameSpecifierLocBuilder() { - if (BufferCapacity) - free(Buffer); - } +SourceLocation NestedNameSpecifierLoc::getLocalEndLoc() const { + return getLocalSourceRange().getEnd(); +} - /// Retrieve the representation of the nested-name-specifier. - NestedNameSpecifier *getRepresentation() const { return Representation; } - - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'type::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param TL The TypeLoc that describes the type preceding the '::'. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); - - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'identifier::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Identifier The identifier. - /// - /// \param IdentifierLoc The location of the identifier. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, IdentifierInfo *Identifier, - SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); - - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'namespace::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Namespace The namespace or namespace alias. - /// - /// \param NamespaceLoc The location of the namespace name or the namespace - // alias. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, NamespaceBaseDecl *Namespace, - SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - - /// Turn this (empty) nested-name-specifier into the global - /// nested-name-specifier '::'. - void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); - - /// Turns this (empty) nested-name-specifier into '__super' - /// nested-name-specifier. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param RD The declaration of the class in which nested-name-specifier - /// appeared. - /// - /// \param SuperLoc The location of the '__super' keyword. - /// name. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, - SourceLocation SuperLoc, SourceLocation ColonColonLoc); - - /// Make a new nested-name-specifier from incomplete source-location - /// information. - /// - /// This routine should be used very, very rarely, in cases where we - /// need to synthesize a nested-name-specifier. Most code should instead use - /// \c Adopt() with a proper \c NestedNameSpecifierLoc. - void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, - SourceRange R); - - /// Adopt an existing nested-name-specifier (with source-range - /// information). - void Adopt(NestedNameSpecifierLoc Other); - - /// Retrieve the source range covered by this nested-name-specifier. - SourceRange getSourceRange() const LLVM_READONLY { - return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); - } +SourceRange NestedNameSpecifierLocBuilder::getSourceRange() const { + return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); +} - /// Retrieve a nested-name-specifier with location information, - /// copied into the given AST context. - /// - /// \param Context The context into which this nested-name-specifier will be - /// copied. - NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; - - /// Retrieve a nested-name-specifier with location - /// information based on the information in this builder. - /// - /// This loc will contain references to the builder's internal data and may - /// be invalidated by any change to the builder. - NestedNameSpecifierLoc getTemporary() const { - return NestedNameSpecifierLoc(Representation, Buffer); - } +} // namespace clang + +namespace llvm { + +template <> struct DenseMapInfo { + static clang::NestedNameSpecifier getEmptyKey() { return std::nullopt; } - /// Clear out this builder, and prepare it to build another - /// nested-name-specifier with source-location information. - void Clear() { - Representation = nullptr; - BufferSize = 0; + static clang::NestedNameSpecifier getTombstoneKey() { + return clang::NestedNameSpecifier::getInvalid(); } - /// Retrieve the underlying buffer. - /// - /// \returns A pair containing a pointer to the buffer of source-location - /// data and the size of the source-location data that resides in that - /// buffer. - std::pair getBuffer() const { - return std::make_pair(Buffer, BufferSize); + static unsigned getHashValue(const clang::NestedNameSpecifier &V) { + return hash_combine(V.getAsVoidPointer()); } }; -/// Insertion operator for diagnostics. This allows sending -/// NestedNameSpecifiers into a diagnostic with <<. -inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, - NestedNameSpecifier *NNS) { - DB.AddTaggedVal(reinterpret_cast(NNS), - DiagnosticsEngine::ak_nestednamespec); - return DB; -} - -} // namespace clang - -namespace llvm { - template <> struct DenseMapInfo { - using FirstInfo = DenseMapInfo; + using FirstInfo = DenseMapInfo; using SecondInfo = DenseMapInfo; static clang::NestedNameSpecifierLoc getEmptyKey() { diff --git a/clang/include/clang/AST/NestedNameSpecifierBase.h b/clang/include/clang/AST/NestedNameSpecifierBase.h new file mode 100644 index 0000000000000..73c60ba695419 --- /dev/null +++ b/clang/include/clang/AST/NestedNameSpecifierBase.h @@ -0,0 +1,586 @@ +//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the NestedNameSpecifier class, which represents +// a C++ nested-name-specifier. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H +#define LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H + +#include "clang/AST/DependenceFlags.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include +#include +#include + +namespace clang { + +class ASTContext; +class CXXRecordDecl; +class NamedDecl; +class IdentifierInfo; +class LangOptions; +class NamespaceBaseDecl; +struct PrintingPolicy; +class Type; +class TypeLoc; + +struct NamespaceAndPrefix; +struct alignas(8) NamespaceAndPrefixStorage; + +/// Represents a C++ nested name specifier, such as +/// "\::std::vector::". +/// +/// C++ nested name specifiers are the prefixes to qualified +/// names. For example, "foo::" in "foo::x" is a nested name +/// specifier. Nested name specifiers are made up of a sequence of +/// specifiers, each of which can be a namespace, type, decltype specifier, or +/// the global specifier ('::'). The last two specifiers can only appear at the +/// start of a nested-namespace-specifier. +class NestedNameSpecifier { + enum class FlagKind { Null, Global, Invalid }; + enum class StoredKind { + Type, + NamespaceOrSuper, + NamespaceWithGlobal, + NamespaceWithNamespace + }; + static constexpr uintptr_t FlagBits = 2, FlagMask = (1u << FlagBits) - 1u, + FlagOffset = 1, PtrOffset = FlagBits + FlagOffset, + PtrMask = (1u << PtrOffset) - 1u; + + uintptr_t StoredOrFlag; + + explicit NestedNameSpecifier(uintptr_t StoredOrFlag) + : StoredOrFlag(StoredOrFlag) {} + struct PtrKind { + StoredKind SK; + const void *Ptr; + }; + explicit NestedNameSpecifier(PtrKind PK) + : StoredOrFlag(uintptr_t(PK.Ptr) | (uintptr_t(PK.SK) << FlagOffset)) { + assert(PK.Ptr != nullptr); + assert((uintptr_t(PK.Ptr) & ((1u << PtrOffset) - 1u)) == 0); + assert((uintptr_t(PK.Ptr) >> PtrOffset) != 0); + } + + explicit constexpr NestedNameSpecifier(FlagKind K) + : StoredOrFlag(uintptr_t(K) << FlagOffset) {} + + bool isStoredKind() const { return (StoredOrFlag >> PtrOffset) != 0; } + + std::pair getStored() const { + assert(isStoredKind()); + return {StoredKind(StoredOrFlag >> FlagOffset & FlagMask), + reinterpret_cast(StoredOrFlag & ~PtrMask)}; + } + + FlagKind getFlagKind() const { + assert(!isStoredKind()); + return FlagKind(StoredOrFlag >> FlagOffset); + } + + static const NamespaceAndPrefixStorage * + MakeNamespaceAndPrefixStorage(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix); + static inline PtrKind MakeNamespacePtrKind(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix); + +public: + static constexpr NestedNameSpecifier getInvalid() { + return NestedNameSpecifier(FlagKind::Invalid); + } + + static constexpr NestedNameSpecifier getGlobal() { + return NestedNameSpecifier(FlagKind::Global); + } + + NestedNameSpecifier() : NestedNameSpecifier(FlagKind::Invalid) {} + + /// The kind of specifier that completes this nested name + /// specifier. + enum class Kind { + /// Empty. + Null, + + /// The global specifier '::'. There is no stored value. + Global, + + /// A type, stored as a Type*. + Type, + + /// A namespace-like entity, stored as a NamespaceBaseDecl*. + Namespace, + + /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of + /// the class it appeared in. + MicrosoftSuper, + }; + + inline Kind getKind() const; + + NestedNameSpecifier(std::nullopt_t) : StoredOrFlag(0) {} + + explicit inline NestedNameSpecifier(const Type *T); + + /// Builds a nested name specifier that names a namespace. + inline NestedNameSpecifier(const ASTContext &Ctx, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix); + + /// Builds a nested name specifier that names a class through microsoft's + /// __super specifier. + explicit inline NestedNameSpecifier(CXXRecordDecl *RD); + + explicit operator bool() const { return StoredOrFlag != 0; } + + void *getAsVoidPointer() const { + return reinterpret_cast(StoredOrFlag); + } + static NestedNameSpecifier getFromVoidPointer(const void *Ptr) { + return NestedNameSpecifier(reinterpret_cast(Ptr)); + } + + const Type *getAsType() const { + auto [Kind, Ptr] = getStored(); + assert(Kind == StoredKind::Type); + assert(Ptr != nullptr); + return static_cast(Ptr); + } + + inline NamespaceAndPrefix getAsNamespaceAndPrefix() const; + + CXXRecordDecl *getAsMicrosoftSuper() const { + auto [Kind, Ptr] = getStored(); + assert(Kind == StoredKind::NamespaceOrSuper); + assert(Ptr != nullptr); + return static_cast(const_cast(Ptr)); + } + + /// Retrieve the record declaration stored in this nested name + /// specifier, or null. + inline CXXRecordDecl *getAsRecordDecl() const; + + friend bool operator==(NestedNameSpecifier LHS, NestedNameSpecifier RHS) { + return LHS.StoredOrFlag == RHS.StoredOrFlag; + } + friend bool operator!=(NestedNameSpecifier LHS, NestedNameSpecifier RHS) { + return LHS.StoredOrFlag != RHS.StoredOrFlag; + } + + /// Retrieves the "canonical" nested name specifier for a + /// given nested name specifier. + /// + /// The canonical nested name specifier is a nested name specifier + /// that uniquely identifies a type or namespace within the type + /// system. For example, given: + /// + /// \code + /// namespace N { + /// struct S { + /// template struct X { typename T* type; }; + /// }; + /// } + /// + /// template struct Y { + /// typename N::S::X::type member; + /// }; + /// \endcode + /// + /// Here, the nested-name-specifier for N::S::X:: will be + /// S::X, since 'S' and 'X' are uniquely defined + /// by declarations in the type system and the canonical type for + /// the template type parameter 'T' is template-param-0-0. + inline NestedNameSpecifier getCanonical() const; + + /// Whether this nested name specifier is canonical. + inline bool isCanonical() const; + + /// Whether this nested name specifier starts with a '::'. + bool isFullyQualified() const; + + NestedNameSpecifierDependence getDependence() const; + + /// Whether this nested name specifier refers to a dependent + /// type or not. + bool isDependent() const { + return getDependence() & NestedNameSpecifierDependence::Dependent; + } + + /// Whether this nested name specifier involves a template + /// parameter. + bool isInstantiationDependent() const { + return getDependence() & NestedNameSpecifierDependence::Instantiation; + } + + /// Whether this nested-name-specifier contains an unexpanded + /// parameter pack (for C++11 variadic templates). + bool containsUnexpandedParameterPack() const { + return getDependence() & NestedNameSpecifierDependence::UnexpandedPack; + } + + /// Whether this nested name specifier contains an error. + bool containsErrors() const { + return getDependence() & NestedNameSpecifierDependence::Error; + } + + /// Print this nested name specifier to the given output stream. If + /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. + /// `ns::SomeTemplate` instead of + /// `ns::SomeTemplate`. + void print(raw_ostream &OS, const PrintingPolicy &Policy, + bool ResolveTemplateArguments = false, + bool PrintFinalScopeResOp = true) const; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(StoredOrFlag); + } + + /// Dump the nested name specifier to aid in debugging. + void dump(llvm::raw_ostream *OS = nullptr, + const LangOptions *LO = nullptr) const; + void dump(const LangOptions &LO) const; + void dump(llvm::raw_ostream &OS) const; + void dump(llvm::raw_ostream &OS, const LangOptions &LO) const; + + static constexpr auto NumLowBitsAvailable = FlagOffset; +}; + +struct NamespaceAndPrefix { + const NamespaceBaseDecl *Namespace; + NestedNameSpecifier Prefix; +}; + +struct alignas(8) NamespaceAndPrefixStorage : NamespaceAndPrefix, + llvm::FoldingSetNode { + NamespaceAndPrefixStorage(const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix) + : NamespaceAndPrefix{Namespace, Prefix} {} + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Namespace, Prefix); } + static void Profile(llvm::FoldingSetNodeID &ID, + const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix) { + ID.AddPointer(Namespace); + Prefix.Profile(ID); + } +}; + +NamespaceAndPrefix NestedNameSpecifier::getAsNamespaceAndPrefix() const { + auto [Kind, Ptr] = getStored(); + switch (Kind) { + case StoredKind::NamespaceOrSuper: + case StoredKind::NamespaceWithGlobal: + return {static_cast(Ptr), + Kind == StoredKind::NamespaceWithGlobal + ? NestedNameSpecifier::getGlobal() + : std::nullopt}; + case StoredKind::NamespaceWithNamespace: + return *static_cast(Ptr); + case StoredKind::Type:; + } + llvm_unreachable("unexpected stored kind"); +} + +struct NamespaceAndPrefixLoc; + +/// A C++ nested-name-specifier augmented with source location +/// information. +class NestedNameSpecifierLoc { + NestedNameSpecifier Qualifier = std::nullopt; + void *Data = nullptr; + + /// Load a (possibly unaligned) source location from a given address + /// and offset. + SourceLocation LoadSourceLocation(unsigned Offset) const { + SourceLocation::UIntTy Raw; + memcpy(&Raw, static_cast(Data) + Offset, sizeof(Raw)); + return SourceLocation::getFromRawEncoding(Raw); + } + + /// Load a (possibly unaligned) pointer from a given address and + /// offset. + void *LoadPointer(unsigned Offset) const { + void *Result; + memcpy(&Result, static_cast(Data) + Offset, sizeof(void *)); + return Result; + } + + /// Determines the data length for the last component in the + /// given nested-name-specifier. + static inline unsigned getLocalDataLength(NestedNameSpecifier Qualifier); + + /// Determines the data length for the entire + /// nested-name-specifier. + static inline unsigned getDataLength(NestedNameSpecifier Qualifier); + +public: + /// Construct an empty nested-name-specifier. + NestedNameSpecifierLoc() = default; + + /// Construct a nested-name-specifier with source location information + /// from + NestedNameSpecifierLoc(NestedNameSpecifier Qualifier, void *Data) + : Qualifier(Qualifier), Data(Data) {} + + /// Evaluates true when this nested-name-specifier location is + /// non-empty. + explicit operator bool() const { return bool(Qualifier); } + + /// Evaluates true when this nested-name-specifier location is + /// non-empty. + bool hasQualifier() const { return bool(Qualifier); } + + /// Retrieve the nested-name-specifier to which this instance + /// refers. + NestedNameSpecifier getNestedNameSpecifier() const { return Qualifier; } + + /// Retrieve the opaque pointer that refers to source-location data. + void *getOpaqueData() const { return Data; } + + /// Retrieve the source range covering the entirety of this + /// nested-name-specifier. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c \::std::vector::, the returned source range would cover + /// from the initial '::' to the last '::'. + inline SourceRange getSourceRange() const LLVM_READONLY; + + /// Retrieve the source range covering just the last part of + /// this nested-name-specifier, not including the prefix. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c \::std::vector::, the returned source range would cover + /// from "vector" to the last '::'. + inline SourceRange getLocalSourceRange() const; + + /// Retrieve the location of the beginning of this + /// nested-name-specifier. + SourceLocation getBeginLoc() const; + + /// Retrieve the location of the end of this + /// nested-name-specifier. + inline SourceLocation getEndLoc() const; + + /// Retrieve the location of the beginning of this + /// component of the nested-name-specifier. + inline SourceLocation getLocalBeginLoc() const; + + /// Retrieve the location of the end of this component of the + /// nested-name-specifier. + inline SourceLocation getLocalEndLoc() const; + + /// For a nested-name-specifier that refers to a namespace, + /// retrieve the namespace and its prefix. + /// + /// For example, if this instance refers to a nested-name-specifier + /// \c \::std::chrono::, the prefix is \c \::std::. Note that the + /// returned prefix may be empty, if this is the first component of + /// the nested-name-specifier. + inline NamespaceAndPrefixLoc castAsNamespaceAndPrefix() const; + inline NamespaceAndPrefixLoc getAsNamespaceAndPrefix() const; + + /// For a nested-name-specifier that refers to a type, + /// retrieve the type with source-location information. + inline TypeLoc castAsTypeLoc() const; + inline TypeLoc getAsTypeLoc() const; + + /// Determines the data length for the entire + /// nested-name-specifier. + inline unsigned getDataLength() const; + + friend bool operator==(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) { + return X.Qualifier == Y.Qualifier && X.Data == Y.Data; + } + + friend bool operator!=(NestedNameSpecifierLoc X, NestedNameSpecifierLoc Y) { + return !(X == Y); + } +}; + +struct NamespaceAndPrefixLoc { + const NamespaceBaseDecl *Namespace = nullptr; + NestedNameSpecifierLoc Prefix; + + explicit operator bool() const { return Namespace != nullptr; } +}; + +/// Class that aids in the construction of nested-name-specifiers along +/// with source-location information for all of the components of the +/// nested-name-specifier. +class NestedNameSpecifierLocBuilder { + /// The current representation of the nested-name-specifier we're + /// building. + NestedNameSpecifier Representation = std::nullopt; + + /// Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. + char *Buffer = nullptr; + + /// The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize = 0; + + /// The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity = 0; + + void PushTrivial(ASTContext &Context, NestedNameSpecifier Qualifier, + SourceRange R); + +public: + NestedNameSpecifierLocBuilder() = default; + NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); + + NestedNameSpecifierLocBuilder & + operator=(const NestedNameSpecifierLocBuilder &Other); + + ~NestedNameSpecifierLocBuilder() { + if (BufferCapacity) + free(Buffer); + } + + /// Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier getRepresentation() const { return Representation; } + + /// Make a nested-name-specifier of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Make(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); + + /// Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, const NamespaceBaseDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// Turns this (empty) nested-name-specifier into '__super' + /// nested-name-specifier. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param RD The declaration of the class in which nested-name-specifier + /// appeared. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc); + + /// Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier Qualifier, + SourceRange R) { + Representation = Qualifier; + BufferSize = 0; + PushTrivial(Context, Qualifier, R); + } + + /// Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// Retrieve the source range covered by this nested-name-specifier. + inline SourceRange getSourceRange() const LLVM_READONLY; + + /// Retrieve a nested-name-specifier with location information, + /// copied into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; + + /// Retrieve a nested-name-specifier with location + /// information based on the information in this builder. + /// + /// This loc will contain references to the builder's internal data and may + /// be invalidated by any change to the builder. + NestedNameSpecifierLoc getTemporary() const { + return NestedNameSpecifierLoc(Representation, Buffer); + } + + /// Clear out this builder, and prepare it to build another + /// nested-name-specifier with source-location information. + void Clear() { + Representation = std::nullopt; + BufferSize = 0; + } + + /// Retrieve the underlying buffer. + /// + /// \returns A pair containing a pointer to the buffer of source-location + /// data and the size of the source-location data that resides in that + /// buffer. + std::pair getBuffer() const { + return std::make_pair(Buffer, BufferSize); + } +}; + +/// Insertion operator for diagnostics. This allows sending +/// NestedNameSpecifiers into a diagnostic with <<. +inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, + NestedNameSpecifier NNS) { + DB.AddTaggedVal(reinterpret_cast(NNS.getAsVoidPointer()), + DiagnosticsEngine::ak_nestednamespec); + return DB; +} + +} // namespace clang + +namespace llvm { + +template <> struct PointerLikeTypeTraits { + static void *getAsVoidPointer(clang::NestedNameSpecifier P) { + return P.getAsVoidPointer(); + } + static clang::NestedNameSpecifier getFromVoidPointer(const void *P) { + return clang::NestedNameSpecifier::getFromVoidPointer(P); + } + static constexpr int NumLowBitsAvailable = + clang::NestedNameSpecifier::NumLowBitsAvailable; +}; + +} // namespace llvm + +#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIERBASE_H diff --git a/clang/include/clang/AST/ODRHash.h b/clang/include/clang/AST/ODRHash.h index 11f917a1a4634..ae3fab697786a 100644 --- a/clang/include/clang/AST/ODRHash.h +++ b/clang/include/clang/AST/ODRHash.h @@ -93,7 +93,7 @@ class ODRHash { void AddQualType(QualType T); void AddStmt(const Stmt *S); void AddIdentifierInfo(const IdentifierInfo *II); - void AddNestedNameSpecifier(const NestedNameSpecifier *NNS); + void AddNestedNameSpecifier(NestedNameSpecifier NNS); void AddDependentTemplateName(const DependentTemplateStorage &Name); void AddTemplateName(TemplateName Name); void AddDeclarationNameInfo(DeclarationNameInfo NameInfo, diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 0438e4dfbafac..5b10127526e4e 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -127,9 +127,8 @@ def LValuePathSerializationHelper : PropertyType<"APValue::LValuePathSerializationHelper"> { let BufferElementTypes = [ LValuePathEntry ]; } -def NestedNameSpecifier : PropertyType<"NestedNameSpecifier *">; -def NestedNameSpecifierKind : - EnumPropertyType<"NestedNameSpecifier::SpecifierKind">; +def NestedNameSpecifier : PropertyType<"NestedNameSpecifier">; +def NestedNameSpecifierKind : EnumPropertyType<"NestedNameSpecifier::Kind">; def OverloadedOperatorKind : EnumPropertyType; def Qualifiers : PropertyType; def QualType : DefaultValuePropertyType; diff --git a/clang/include/clang/AST/QualTypeNames.h b/clang/include/clang/AST/QualTypeNames.h index daa86cda2d992..9f5cf045d1d4c 100644 --- a/clang/include/clang/AST/QualTypeNames.h +++ b/clang/include/clang/AST/QualTypeNames.h @@ -87,6 +87,16 @@ std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, /// specifier "::" should be prepended or not. QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix = false); + +/// Get the fully qualified name for the declared context of a declaration. +/// +/// \param[in] Ctx - the ASTContext to be used. +/// \param[in] Decl - the declaration for which to get the fully qualified name. +/// \param[in] WithGlobalNsPrefix - If true, then the global namespace +/// specifier "::" will be prepended to the fully qualified name. +NestedNameSpecifier +getFullyQualifiedDeclaredContext(const ASTContext &Ctx, const Decl *Decl, + bool WithGlobalNsPrefix = false); } // end namespace TypeName } // end namespace clang #endif // LLVM_CLANG_AST_QUALTYPENAMES_H diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 05134422797b3..248b89200eace 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -242,7 +242,7 @@ template class RecursiveASTVisitor { /// Recursively visit a C++ nested-name-specifier. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS); /// Recursively visit a C++ nested-name-specifier with location /// information. @@ -787,46 +787,43 @@ bool RecursiveASTVisitor::TraverseDecl(Decl *D) { template bool RecursiveASTVisitor::TraverseNestedNameSpecifier( - NestedNameSpecifier *NNS) { - if (!NNS) + NestedNameSpecifier NNS) { + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: return true; - - if (NNS->getPrefix()) - TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::Namespace: + TRY_TO(TraverseNestedNameSpecifier(NNS.getAsNamespaceAndPrefix().Prefix)); + return true; + case NestedNameSpecifier::Kind::Type: { + auto *T = const_cast(NNS.getAsType()); + TRY_TO(TraverseNestedNameSpecifier(T->getPrefix())); + TRY_TO(TraverseType(QualType(T, 0), /*TraverseQualifier=*/false)); return true; - - case NestedNameSpecifier::TypeSpec: - TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); } - - return true; + } + llvm_unreachable("unhandled kind"); } template bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc( NestedNameSpecifierLoc NNS) { - if (!NNS) + switch (NNS.getNestedNameSpecifier().getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: return true; - - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - TRY_TO(TraverseNestedNameSpecifierLoc(Prefix)); - - switch (NNS.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::Namespace: + TRY_TO( + TraverseNestedNameSpecifierLoc(NNS.castAsNamespaceAndPrefix().Prefix)); return true; - - case NestedNameSpecifier::TypeSpec: - TRY_TO(TraverseTypeLoc(NNS.getTypeLoc())); - break; + case NestedNameSpecifier::Kind::Type: { + TypeLoc TL = NNS.castAsTypeLoc(); + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getPrefix())); + TRY_TO(TraverseTypeLoc(TL, /*TraverseQualifier=*/false)); + return true; + } } return true; @@ -1011,10 +1008,11 @@ DEF_TRAVERSE_TYPE(RValueReferenceType, { TRY_TO(TraverseType(T->getPointeeType())); }) DEF_TRAVERSE_TYPE(MemberPointerType, { - TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); - if (T->isSugared()) - TRY_TO(TraverseType( - QualType(T->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0))); + NestedNameSpecifier Qualifier = + T->isSugared() ? cast(T->getCanonicalTypeUnqualified()) + ->getQualifier() + : T->getQualifier(); + TRY_TO(TraverseNestedNameSpecifier(Qualifier)); TRY_TO(TraverseType(T->getPointeeType())); }) @@ -1279,8 +1277,10 @@ DEF_TRAVERSE_TYPE(PredefinedSugarType, {}) } template -bool -RecursiveASTVisitor::TraverseQualifiedTypeLoc(QualifiedTypeLoc TL) { +bool RecursiveASTVisitor::TraverseQualifiedTypeLoc( + QualifiedTypeLoc TL, bool TraverseQualifier) { + assert(TraverseQualifier && + "Qualifiers should never occur within NestedNameSpecifiers"); // Move this over to the 'main' typeloc tree. Note that this is a // move -- we pretend that we were really looking at the unqualified // typeloc all along -- rather than a recursion, so we don't follow diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index 2050c4c7eddef..69481e85d87fa 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_AST_TEMPLATEBASE_H #include "clang/AST/DependenceFlags.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" @@ -478,31 +478,25 @@ class TemplateArgument { /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { -private: struct TemplateTemplateArgLocInfo { - // FIXME: We'd like to just use the qualifier in the TemplateName, - // but template arguments get canonicalized too quickly. - NestedNameSpecifier *Qualifier; void *QualifierLocData; + SourceLocation TemplateKwLoc; SourceLocation TemplateNameLoc; SourceLocation EllipsisLoc; }; - llvm::PointerUnion - Pointer; - TemplateTemplateArgLocInfo *getTemplate() const { return cast(Pointer); } -public: TemplateArgumentLocInfo() {} TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; } TemplateArgumentLocInfo(Expr *E) { Pointer = E; } // Ctx is used for allocation -- this case is unusually large and also rare, // so we store the payload out-of-line. - TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, + TemplateArgumentLocInfo(ASTContext &Ctx, SourceLocation TemplateKwLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc); @@ -512,10 +506,8 @@ struct TemplateArgumentLocInfo { Expr *getAsExpr() const { return cast(Pointer); } - NestedNameSpecifierLoc getTemplateQualifierLoc() const { - const auto *Template = getTemplate(); - return NestedNameSpecifierLoc(Template->Qualifier, - Template->QualifierLocData); + SourceLocation getTemplateKwLoc() const { + return getTemplate()->TemplateKwLoc; } SourceLocation getTemplateNameLoc() const { @@ -562,14 +554,10 @@ class TemplateArgumentLoc { } TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument, + SourceLocation TemplateKWLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, - SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), - LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) { - assert(Argument.getKind() == TemplateArgument::Template || - Argument.getKind() == TemplateArgument::TemplateExpansion); - } + SourceLocation EllipsisLoc = SourceLocation()); /// - Fetches the primary location of the argument. SourceLocation getLocation() const { @@ -618,13 +606,15 @@ class TemplateArgumentLoc { return LocInfo.getAsExpr(); } - NestedNameSpecifierLoc getTemplateQualifierLoc() const { + SourceLocation getTemplateKWLoc() const { if (Argument.getKind() != TemplateArgument::Template && Argument.getKind() != TemplateArgument::TemplateExpansion) - return NestedNameSpecifierLoc(); - return LocInfo.getTemplateQualifierLoc(); + return SourceLocation(); + return LocInfo.getTemplateKwLoc(); } + NestedNameSpecifierLoc getTemplateQualifierLoc() const; + SourceLocation getTemplateNameLoc() const { if (Argument.getKind() != TemplateArgument::Template && Argument.getKind() != TemplateArgument::TemplateExpansion) diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h index 63949f898f6a2..37ea401a0045a 100644 --- a/clang/include/clang/AST/TemplateName.h +++ b/clang/include/clang/AST/TemplateName.h @@ -14,7 +14,7 @@ #define LLVM_CLANG_AST_TEMPLATENAME_H #include "clang/AST/DependenceFlags.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/UnsignedOrNone.h" @@ -335,10 +335,18 @@ class TemplateName { /// structure, if any. QualifiedTemplateName *getAsQualifiedTemplateName() const; + /// Retrieve the underlying qualified template name, + /// looking through underlying nodes. + QualifiedTemplateName *getAsAdjustedQualifiedTemplateName() const; + /// Retrieve the underlying dependent template name /// structure, if any. DependentTemplateName *getAsDependentTemplateName() const; + // Retrieve the qualifier stored in either a underlying DependentTemplateName + // or QualifiedTemplateName. + NestedNameSpecifier getQualifier() const; + /// Retrieve the using shadow declaration through which the underlying /// template declaration is introduced, if any. UsingShadowDecl *getAsUsingShadowDecl() const; @@ -503,7 +511,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// "template" keyword is always redundant in this case (otherwise, /// the template name would be a dependent name and we would express /// this name with DependentTemplateName). - llvm::PointerIntPair Qualifier; + llvm::PointerIntPair Qualifier; /// The underlying template name, it is either /// 1) a Template -- a template declaration that this qualified name refers @@ -512,7 +520,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// using-shadow declaration. TemplateName UnderlyingTemplate; - QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, + QualifiedTemplateName(NestedNameSpecifier NNS, bool TemplateKeyword, TemplateName Template) : Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) { assert(UnderlyingTemplate.getKind() == TemplateName::Template || @@ -521,7 +529,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { public: /// Return the nested name specifier that qualifies this name. - NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + NestedNameSpecifier getQualifier() const { return Qualifier.getPointer(); } /// Whether the template name was prefixed by the "template" /// keyword. @@ -534,9 +542,9 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier NNS, bool TemplateKeyword, TemplateName TN) { - ID.AddPointer(NNS); + NNS.Profile(ID); ID.AddBoolean(TemplateKeyword); ID.AddPointer(TN.getAsVoidPointer()); } @@ -585,18 +593,18 @@ class DependentTemplateStorage { /// /// The bit stored in this qualifier describes whether the \c Name field /// was preceeded by a template keyword. - llvm::PointerIntPair Qualifier; + llvm::PointerIntPair Qualifier; /// The dependent template name. IdentifierOrOverloadedOperator Name; public: - DependentTemplateStorage(NestedNameSpecifier *Qualifier, + DependentTemplateStorage(NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name, bool HasTemplateKeyword); /// Return the nested name specifier that qualifies this name. - NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } + NestedNameSpecifier getQualifier() const { return Qualifier.getPointer(); } IdentifierOrOverloadedOperator getName() const { return Name; } @@ -609,10 +617,10 @@ class DependentTemplateStorage { Profile(ID, getQualifier(), getName(), hasTemplateKeyword()); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, + static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier NNS, IdentifierOrOverloadedOperator Name, bool HasTemplateKeyword) { - ID.AddPointer(NNS); + NNS.Profile(ID); ID.AddBoolean(HasTemplateKeyword); Name.Profile(ID); } diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 1917a8ac29f05..6d2795111685a 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -211,7 +211,7 @@ class TextNodeDumper void dumpAccessSpecifier(AccessSpecifier AS); void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C); void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK); - void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS); + void dumpNestedNameSpecifier(NestedNameSpecifier NNS); void dumpConceptReference(const ConceptReference *R); void dumpTemplateArgument(const TemplateArgument &TA); void dumpBareTemplateName(TemplateName TN); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 07eab228358f8..c4c23c835ebc2 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -18,7 +18,7 @@ #define LLVM_CLANG_AST_TYPE_H #include "clang/AST/DependenceFlags.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/AttrKinds.h" @@ -2957,6 +2957,11 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { /// qualifiers from the outermost type. const ArrayType *castAsArrayTypeUnsafe() const; + /// If this type represents a qualified-id, this returns its nested name + /// specifier. For example, for the qualified-id "foo::bar::baz", this returns + /// "foo::bar". Returns null if this type represents an unqualified-id. + NestedNameSpecifier getPrefix() const; + /// Determine whether this type had the specified attribute applied to it /// (looking through top-level type sugar). bool hasAttr(attr::Kind AK) const; @@ -3634,12 +3639,12 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { /// The class of which the pointee is a member. Must ultimately be a /// CXXRecordType, but could be a typedef or a template parameter too. - NestedNameSpecifier *Qualifier; + NestedNameSpecifier Qualifier; - MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier, + MemberPointerType(QualType Pointee, NestedNameSpecifier Qualifier, QualType CanonicalPtr) : Type(MemberPointer, CanonicalPtr, - (toTypeDependence(Qualifier->getDependence()) & + (toTypeDependence(Qualifier.getDependence()) & ~TypeDependence::VariablyModified) | Pointee->getDependence()), PointeeType(Pointee), Qualifier(Qualifier) {} @@ -3659,7 +3664,7 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { return !PointeeType->isFunctionProtoType(); } - NestedNameSpecifier *getQualifier() const { return Qualifier; } + NestedNameSpecifier getQualifier() const { return Qualifier; } /// Note: this can trigger extra deserialization when external AST sources are /// used. Prefer `getCXXRecordDecl()` unless you really need the most recent /// decl. @@ -3678,7 +3683,7 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode { } static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, - const NestedNameSpecifier *Qualifier, + const NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls); static bool classof(const Type *T) { @@ -6463,14 +6468,9 @@ class InjectedClassNameType final : public TagType { InjectedClassNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, - bool IsInjected, CanQualType CanonicalInjectedTST, - const Type *CanonicalType); - - QualType CanonicalInjectedTST; + bool IsInjected, const Type *CanonicalType); public: - CanQualType getCanonicalInjectedTST() const; - CXXRecordDecl *getOriginalDecl() const { return reinterpret_cast(TagType::getOriginalDecl()); } @@ -7281,24 +7281,24 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these /// The nested name specifier containing the qualifier. - NestedNameSpecifier *NNS; + NestedNameSpecifier NNS; /// The type that this typename specifier refers to. const IdentifierInfo *Name; - DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier NNS, const IdentifierInfo *Name, QualType CanonType) : TypeWithKeyword(Keyword, DependentName, CanonType, TypeDependence::DependentInstantiation | - toTypeDependence(NNS->getDependence())), + (NNS ? toTypeDependence(NNS.getDependence()) + : TypeDependence::Dependent)), NNS(NNS), Name(Name) { - assert(NNS); assert(Name); } public: /// Retrieve the qualification on this type. - NestedNameSpecifier *getQualifier() const { return NNS; } + NestedNameSpecifier getQualifier() const { return NNS; } /// Retrieve the identifier that terminates this type name. /// For example, "type" in "typename T::type". @@ -7314,9 +7314,9 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, const IdentifierInfo *Name) { + NestedNameSpecifier NNS, const IdentifierInfo *Name) { ID.AddInteger(llvm::to_underlying(Keyword)); - ID.AddPointer(NNS); + NNS.Profile(ID); ID.AddPointer(Name); } @@ -8867,8 +8867,8 @@ inline bool Type::isIntegerType() const { if (const EnumType *ET = dyn_cast(CanonicalType)) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - return IsEnumDeclComplete(ET->getDecl()) && - !IsEnumDeclScoped(ET->getDecl()); + return IsEnumDeclComplete(ET->getOriginalDecl()) && + !IsEnumDeclScoped(ET->getOriginalDecl()); } return isBitIntType(); } @@ -8926,7 +8926,7 @@ inline bool Type::isScalarType() const { if (const EnumType *ET = dyn_cast(CanonicalType)) // Enums are scalar types, but only if they are defined. Incomplete enums // are not treated as scalar types. - return IsEnumDeclComplete(ET->getDecl()); + return IsEnumDeclComplete(ET->getOriginalDecl()); return isa(CanonicalType) || isa(CanonicalType) || isa(CanonicalType) || @@ -8942,7 +8942,7 @@ inline bool Type::isIntegralOrEnumerationType() const { // Check for a complete enum type; incomplete enum types are not properly an // enumeration type in the sense required here. if (const auto *ET = dyn_cast(CanonicalType)) - return IsEnumDeclComplete(ET->getDecl()); + return IsEnumDeclComplete(ET->getOriginalDecl()); return isBitIntType(); } diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 5394687f3b372..934aa14c4c1b6 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -16,7 +16,7 @@ #include "clang/AST/ASTConcept.h" #include "clang/AST/DeclarationName.h" -#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/NestedNameSpecifierBase.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" @@ -193,6 +193,21 @@ class TypeLoc { /// Get the SourceLocation of the template keyword (if any). SourceLocation getTemplateKeywordLoc() const; + /// If this type represents a qualified-id, this returns it's nested name + /// specifier. For example, for the qualified-id "foo::bar::baz", this returns + /// "foo::bar". Returns null if this type represents an unqualified-id. + NestedNameSpecifierLoc getPrefix() const; + + /// This returns the position of the type after any elaboration, such as the + /// 'struct' keyword, and name qualifiers. This will the 'template' keyword if + /// present, or the name location otherwise. + SourceLocation getNonPrefixBeginLoc() const; + + /// This returns the position of the type after any elaboration, such as the + /// 'struct' keyword. This may be the position of the name qualifiers, + /// 'template' keyword, or the name location otherwise. + SourceLocation getNonElaboratedBeginLoc() const; + /// Initializes this to state that every location in this /// type is the given location. /// @@ -1520,7 +1535,7 @@ class MemberPointerTypeLoc : public PointerLikeTypeLocgetQualifier()) { + if (NestedNameSpecifier Qualifier = getTypePtr()->getQualifier()) { NestedNameSpecifierLocBuilder Builder; Builder.MakeTrivial(Context, Qualifier, Loc); setQualifierLoc(Builder.getWithLocInContext(Context)); diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 08c898f7758ec..cbd931cabd806 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -222,6 +222,19 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher typeAliasDecl; +/// \brief Matches shadow declarations introduced into a scope by a +/// (resolved) using declaration. +/// +/// Given +/// \code +/// namespace n { int f; } +/// namespace declToImport { using n::f; } +/// \endcode +/// usingShadowDecl() +/// matches \code f \endcode +extern const internal::VariadicDynCastAllOfMatcher + usingShadowDecl; + /// Matches type alias template declarations. /// /// typeAliasTemplateDecl() matches @@ -3740,7 +3753,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless; /// Matcher, Matcher, Matcher, /// Matcher, Matcher, /// Matcher, Matcher, -/// Matcher +/// Matcher, Matcher inline internal::PolymorphicMatcher< internal::HasDeclarationMatcher, void(internal::HasDeclarationSupportedTypes), internal::Matcher> @@ -4375,7 +4388,13 @@ AST_POLYMORPHIC_MATCHER_P(throughUsingDecl, AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, UsingType), internal::Matcher, Inner) { - const NamedDecl *FoundDecl = Node.getFoundDecl(); + const NamedDecl *FoundDecl; + if constexpr (std::is_same_v) { + FoundDecl = Node.getDecl(); + } else { + static_assert(std::is_same_v); + FoundDecl = Node.getFoundDecl(); + } if (const UsingShadowDecl *UsingDecl = dyn_cast(FoundDecl)) return Inner.matches(*UsingDecl, Finder, Builder); return false; @@ -7004,37 +7023,6 @@ AST_POLYMORPHIC_MATCHER_P2( InnerMatcher.matches(Args[Index], Finder, Builder); } -/// Matches C or C++ elaborated `TypeLoc`s. -/// -/// Given -/// \code -/// struct s {}; -/// struct s ss; -/// \endcode -/// elaboratedTypeLoc() -/// matches the `TypeLoc` of the variable declaration of `ss`. -extern const internal::VariadicDynCastAllOfMatcher - elaboratedTypeLoc; - -/// Matches elaborated `TypeLoc`s that have a named `TypeLoc` matching -/// `InnerMatcher`. -/// -/// Given -/// \code -/// template -/// class C {}; -/// class C c; -/// -/// class D {}; -/// class D d; -/// \endcode -/// elaboratedTypeLoc(hasNamedTypeLoc(templateSpecializationTypeLoc())); -/// matches the `TypeLoc` of the variable declaration of `c`, but not `d`. -AST_MATCHER_P(ElaboratedTypeLoc, hasNamedTypeLoc, internal::Matcher, - InnerMatcher) { - return InnerMatcher.matches(Node.getNamedTypeLoc(), Finder, Builder); -} - /// Matches type \c bool. /// /// Given @@ -7301,7 +7289,7 @@ extern const AstTypeMatcher decltypeType; AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType)); -/// Matches \c DecltypeType or \c UsingType nodes to find the underlying type. +/// Matches \c QualType nodes to find the underlying type. /// /// Given /// \code @@ -7311,10 +7299,13 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, /// decltypeType(hasUnderlyingType(isInteger())) /// matches the type of "a" /// -/// Usable as: Matcher, Matcher -AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType, - AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType, - UsingType)); +/// Usable as: Matcher +AST_MATCHER_P(Type, hasUnderlyingType, internal::Matcher, Inner) { + QualType QT = Node.getLocallyUnqualifiedSingleStepDesugaredType(); + if (QT == QualType(&Node, 0)) + return false; + return Inner.matches(QT, Finder, Builder); +} /// Matches \c FunctionType nodes. /// @@ -7593,27 +7584,7 @@ extern const AstTypeMatcher recordType; /// and \c c. extern const AstTypeMatcher tagType; -/// Matches types specified with an elaborated type keyword or with a -/// qualified name. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// class C {}; -/// -/// class C c; -/// N::M::D d; -/// \endcode -/// -/// \c elaboratedType() matches the type of the variable declarations of both -/// \c c and \c d. -extern const AstTypeMatcher elaboratedType; - -/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, +/// Matches Types whose qualifier, a NestedNameSpecifier, /// matches \c InnerMatcher if the qualifier exists. /// /// Given @@ -7628,34 +7599,14 @@ extern const AstTypeMatcher elaboratedType; /// /// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))) /// matches the type of the variable declaration of \c d. -AST_MATCHER_P(ElaboratedType, hasQualifier, - internal::Matcher, InnerMatcher) { - if (const NestedNameSpecifier *Qualifier = Node.getQualifier()) - return InnerMatcher.matches(*Qualifier, Finder, Builder); +AST_MATCHER_P(Type, hasQualifier, internal::Matcher, + InnerMatcher) { + if (NestedNameSpecifier Qualifier = Node.getPrefix()) + return InnerMatcher.matches(Qualifier, Finder, Builder); return false; } -/// Matches ElaboratedTypes whose named type matches \c InnerMatcher. -/// -/// Given -/// \code -/// namespace N { -/// namespace M { -/// class D {}; -/// } -/// } -/// N::M::D d; -/// \endcode -/// -/// \c elaboratedType(namesType(recordType( -/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable -/// declaration of \c d. -AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher, - InnerMatcher) { - return InnerMatcher.matches(Node.getNamedType(), Finder, Builder); -} - /// Matches types specified through a using declaration. /// /// Given @@ -7824,7 +7775,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD( /// matches "A::" AST_MATCHER_P(NestedNameSpecifier, specifiesType, internal::Matcher, InnerMatcher) { - if (!Node.getAsType()) + if (Node.getKind() != NestedNameSpecifier::Kind::Type) return false; return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); } @@ -7842,8 +7793,12 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType, /// matches "A::" AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, internal::Matcher, InnerMatcher) { - return Node && Node.getNestedNameSpecifier()->getAsType() && - InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); + if (!Node) + return false; + TypeLoc TL = Node.getAsTypeLoc(); + if (!TL) + return false; + return InnerMatcher.matches(TL, Finder, Builder); } /// Matches on the prefix of a \c NestedNameSpecifier. @@ -7858,10 +7813,21 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, internal::Matcher, InnerMatcher, 0) { - const NestedNameSpecifier *NextNode = Node.getPrefix(); + NestedNameSpecifier NextNode = std::nullopt; + switch (Node.getKind()) { + case NestedNameSpecifier::Kind::Namespace: + NextNode = Node.getAsNamespaceAndPrefix().Prefix; + break; + case NestedNameSpecifier::Kind::Type: + NextNode = Node.getAsType()->getPrefix(); + break; + default: + break; + } + if (!NextNode) return false; - return InnerMatcher.matches(*NextNode, Finder, Builder); + return InnerMatcher.matches(NextNode, Finder, Builder); } /// Matches on the prefix of a \c NestedNameSpecifierLoc. @@ -7876,7 +7842,12 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, internal::Matcher, InnerMatcher, 1) { - NestedNameSpecifierLoc NextNode = Node.getPrefix(); + NestedNameSpecifierLoc NextNode; + if (TypeLoc TL = Node.getAsTypeLoc()) + NextNode = TL.getPrefix(); + else + NextNode = Node.getAsNamespaceAndPrefix().Prefix; + if (!NextNode) return false; return InnerMatcher.matches(NextNode, Finder, Builder); @@ -7894,9 +7865,13 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, /// matches "ns::" AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, internal::Matcher, InnerMatcher) { - if (auto *NS = dyn_cast_if_present(Node.getAsNamespace())) - return InnerMatcher.matches(*NS, Finder, Builder); - return false; + if (Node.getKind() != NestedNameSpecifier::Kind::Namespace) + return false; + const auto *Namespace = + dyn_cast(Node.getAsNamespaceAndPrefix().Namespace); + if (!Namespace) + return false; + return InnerMatcher.matches(*Namespace, Finder, Builder); } /// Matches attributes. diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 5df2294792552..1ab6f11a23e12 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1017,10 +1017,7 @@ class HasDeclarationMatcher : public MatcherInterface { // First, for any types that have a declaration, extract the declaration and // match on it. if (const auto *S = dyn_cast(&Node)) { - return matchesDecl(S->getDecl(), Finder, Builder); - } - if (const auto *S = dyn_cast(&Node)) { - return matchesDecl(S->getDecl(), Finder, Builder); + return matchesDecl(S->getOriginalDecl(), Finder, Builder); } if (const auto *S = dyn_cast(&Node)) { return matchesDecl(S->getDecl(), Finder, Builder); @@ -1031,6 +1028,9 @@ class HasDeclarationMatcher : public MatcherInterface { if (const auto *S = dyn_cast(&Node)) { return matchesDecl(S->getDecl(), Finder, Builder); } + if (const auto *S = dyn_cast(&Node)) { + return matchesDecl(S->getDecl(), Finder, Builder); + } if (const auto *S = dyn_cast(&Node)) { return matchesDecl(S->getInterface(), Finder, Builder); } @@ -1066,12 +1066,6 @@ class HasDeclarationMatcher : public MatcherInterface { Builder); } - // FIXME: We desugar elaborated types. This makes the assumption that users - // do never want to match on whether a type is elaborated - there are - // arguments for both sides; for now, continue desugaring. - if (const auto *S = dyn_cast(&Node)) { - return matchesSpecialized(S->desugar(), Finder, Builder); - } // Similarly types found via using declarations. // These are *usually* meaningless sugar, and this matches the historical // behavior prior to the introduction of UsingType. @@ -1211,8 +1205,8 @@ using AdaptativeDefaultToTypes = /// All types that are supported by HasDeclarationMatcher above. using HasDeclarationSupportedTypes = TypeList; @@ -1789,7 +1783,7 @@ class LocMatcher : public MatcherInterface { private: static DynTypedNode extract(const NestedNameSpecifierLoc &Loc) { - return DynTypedNode::create(*Loc.getNestedNameSpecifier()); + return DynTypedNode::create(Loc.getNestedNameSpecifier()); } }; diff --git a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h index 8c7ee86d15c06..a404b06cd62ca 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ASTOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/ASTOps.h @@ -112,8 +112,14 @@ class AnalysisASTVisitor : public DynamicRecursiveASTVisitor { // fields that are only used in these. // Note: The operand of the `noexcept` operator is an unevaluated operand, but // nevertheless it appears in the Clang CFG, so we don't exclude it here. - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) override { return true; } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc) override { return true; } + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc, + bool TraverseQualifier) override { + return true; + } + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc, + bool TraverseQualifier) override { + return true; + } bool TraverseCXXTypeidExpr(CXXTypeidExpr *TIE) override { if (TIE->isPotentiallyEvaluated()) return DynamicRecursiveASTVisitor::TraverseCXXTypeidExpr(TIE); diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index 4ac744459031e..4859225ef4ced 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -440,9 +440,8 @@ class DeclarationFragmentsBuilder { DeclarationFragments &); /// Build DeclarationFragments for a NestedNameSpecifier. - static DeclarationFragments getFragmentsForNNS(const NestedNameSpecifier *, - ASTContext &, - DeclarationFragments &); + static DeclarationFragments + getFragmentsForNNS(NestedNameSpecifier, ASTContext &, DeclarationFragments &); /// Build DeclarationFragments for Qualifiers. static DeclarationFragments getFragmentsForQualifiers(const Qualifiers quals); diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h index 2dd27593778c7..c26f4e33d289c 100644 --- a/clang/include/clang/Sema/CodeCompleteConsumer.h +++ b/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -162,7 +162,8 @@ SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); /// Determine the type that this declaration will have if it is used /// as a type or in an expression. -QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND); +QualType getDeclUsageType(ASTContext &C, NestedNameSpecifier Qualifier, + const NamedDecl *ND); /// Determine the priority to be given to a macro code completion result /// with the given name. @@ -867,7 +868,7 @@ class CodeCompletionResult { /// If the result should have a nested-name-specifier, this is it. /// When \c QualifierIsInformative, the nested-name-specifier is /// informative rather than required. - NestedNameSpecifier *Qualifier = nullptr; + NestedNameSpecifier Qualifier = std::nullopt; /// If this Decl was unshadowed by using declaration, this can store a /// pointer to the UsingShadowDecl which was used in the unshadowing process. @@ -882,7 +883,7 @@ class CodeCompletionResult { /// Build a result that refers to a declaration. CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority, - NestedNameSpecifier *Qualifier = nullptr, + NestedNameSpecifier Qualifier = std::nullopt, bool QualifierIsInformative = false, bool Accessible = true, std::vector FixIts = std::vector()) diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index e5680813e74de..c1a99a1fddc80 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -91,12 +91,11 @@ class CXXScopeSpec { } /// Retrieve the representation of the nested-name-specifier. - NestedNameSpecifier *getScopeRep() const { + NestedNameSpecifier getScopeRep() const { return Builder.getRepresentation(); } - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'type::'. + /// Make a nested-name-specifier of the form 'type::'. /// /// \param Context The AST context in which this nested-name-specifier /// resides. @@ -106,21 +105,7 @@ class CXXScopeSpec { /// \param TL The TypeLoc that describes the type preceding the '::'. /// /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); - - /// Extend the current nested-name-specifier by another - /// nested-name-specifier component of the form 'identifier::'. - /// - /// \param Context The AST context in which this nested-name-specifier - /// resides. - /// - /// \param Identifier The identifier. - /// - /// \param IdentifierLoc The location of the identifier. - /// - /// \param ColonColonLoc The location of the trailing '::'. - void Extend(ASTContext &Context, IdentifierInfo *Identifier, - SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + void Make(ASTContext &Context, TypeLoc TL, SourceLocation ColonColonLoc); /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace::'. @@ -154,8 +139,9 @@ class CXXScopeSpec { /// name. /// /// \param ColonColonLoc The location of the trailing '::'. - void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, - SourceLocation SuperLoc, SourceLocation ColonColonLoc); + void MakeMicrosoftSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, + SourceLocation ColonColonLoc); /// Make a new nested-name-specifier from incomplete source-location /// information. @@ -163,7 +149,7 @@ class CXXScopeSpec { /// FIXME: This routine should be used very, very rarely, in cases where we /// need to synthesize a nested-name-specifier. Most code should instead use /// \c Adopt() with a proper \c NestedNameSpecifierLoc. - void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + void MakeTrivial(ASTContext &Context, NestedNameSpecifier Qualifier, SourceRange R); /// Adopt an existing nested-name-specifier (with source-range @@ -189,14 +175,14 @@ class CXXScopeSpec { SourceLocation getLastQualifierNameLoc() const; /// No scope specifier. - bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; } + bool isEmpty() const { return Range.isInvalid() && !getScopeRep(); } /// A scope specifier is present, but may be valid or invalid. bool isNotEmpty() const { return !isEmpty(); } /// An error occurred during parsing of the scope specifier. - bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; } + bool isInvalid() const { return Range.isValid() && !getScopeRep(); } /// A scope specifier is present, and it refers to a real scope. - bool isValid() const { return getScopeRep() != nullptr; } + bool isValid() const { return bool(getScopeRep()); } /// Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { @@ -209,7 +195,7 @@ class CXXScopeSpec { /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). - bool isSet() const { return getScopeRep() != nullptr; } + bool isSet() const { return bool(getScopeRep()); } void clear() { Range = SourceRange(); diff --git a/clang/include/clang/Sema/HeuristicResolver.h b/clang/include/clang/Sema/HeuristicResolver.h index e193c0bc14cd9..71588bee92d16 100644 --- a/clang/include/clang/Sema/HeuristicResolver.h +++ b/clang/include/clang/Sema/HeuristicResolver.h @@ -67,8 +67,7 @@ class HeuristicResolver { // Try to heuristically resolve a dependent nested name specifier // to the type it likely denotes. Note that *dependent* name specifiers always // denote types, not namespaces. - QualType - resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS) const; + QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS) const; // Perform an imprecise lookup of a dependent name in `RD`. // This function does not follow strict semantic rules and should be used diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h index 3a8050f9a0a3d..4a3df781b5a58 100644 --- a/clang/include/clang/Sema/ParsedTemplate.h +++ b/clang/include/clang/Sema/ParsedTemplate.h @@ -48,8 +48,8 @@ namespace clang { /// /// \param Arg the template type argument or non-type template argument. /// \param Loc the location of the type. - ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) - : Kind(Kind), Arg(Arg), Loc(Loc) { } + ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation NameLoc) + : Kind(Kind), Arg(Arg), NameLoc(NameLoc) {} /// Create a template template argument. /// @@ -60,11 +60,11 @@ namespace clang { /// argument refers. /// /// \param TemplateLoc the location of the template name. - ParsedTemplateArgument(const CXXScopeSpec &SS, - ParsedTemplateTy Template, - SourceLocation TemplateLoc) - : Kind(ParsedTemplateArgument::Template), - Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {} + ParsedTemplateArgument(SourceLocation TemplateKwLoc, const CXXScopeSpec &SS, + ParsedTemplateTy Template, SourceLocation NameLoc) + : Kind(ParsedTemplateArgument::Template), + Arg(Template.getAsOpaquePtr()), SS(SS), TemplateKwLoc(TemplateKwLoc), + NameLoc(NameLoc) {} /// Determine whether the given template argument is invalid. bool isInvalid() const { return Arg == nullptr; } @@ -91,7 +91,10 @@ namespace clang { } /// Retrieve the location of the template argument. - SourceLocation getLocation() const { return Loc; } + SourceLocation getTemplateKwLoc() const { return TemplateKwLoc; } + + /// Retrieve the location of the template argument. + SourceLocation getNameLoc() const { return NameLoc; } /// Retrieve the nested-name-specifier that precedes the template /// name in a template template argument. @@ -128,8 +131,11 @@ namespace clang { /// argument. CXXScopeSpec SS; - /// the location of the template argument. - SourceLocation Loc; + /// the location of the template keyword. + SourceLocation TemplateKwLoc; + + /// the location of the template name. + SourceLocation NameLoc; /// The ellipsis location that can accompany a template template /// argument (turning it into a template template argument expansion). diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5211373367677..1dfc276147fd4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3225,7 +3225,7 @@ class Sema final : public SemaBase { /// current instantiation (C++0x [temp.dep.type]p1). /// /// \param NNS a dependent nested name specifier. - CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); + CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier NNS); /// The parser has parsed a global nested-name-specifier '::'. /// @@ -3262,7 +3262,7 @@ class Sema final : public SemaBase { /// (e.g., Base::), perform name lookup for that identifier as a /// nested-name-specifier within the given scope, and return the result of /// that name lookup. - NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); + NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier NNS); /// Keeps information about an identifier in a nested-name-spec. /// @@ -3581,8 +3581,8 @@ class Sema final : public SemaBase { /// Returns the TypeDeclType for the given type declaration, /// as ASTContext::getTypeDeclType would, but /// performs the required semantic checks for name lookup of said entity. - QualType getTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, - TypeDecl *TD, SourceLocation NameLoc); + void checkTypeDeclType(DeclContext *LookupCtx, DiagCtorKind DCK, TypeDecl *TD, + SourceLocation NameLoc); /// If the identifier refers to a type name within this scope, /// return the declaration of that type. @@ -7618,7 +7618,7 @@ class Sema final : public SemaBase { /// "real" base class is checked as appropriate when checking the access of /// the member name. ExprResult PerformObjectMemberConversion(Expr *From, - NestedNameSpecifier *Qualifier, + NestedNameSpecifier Qualifier, NamedDecl *FoundDecl, NamedDecl *Member); @@ -10210,7 +10210,7 @@ class Sema final : public SemaBase { ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj, FunctionDecl *Fun); ExprResult PerformImplicitObjectArgumentInitialization( - Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, + Expr *From, NestedNameSpecifier Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method); /// PerformContextuallyConvertToBool - Perform a contextual conversion @@ -11618,13 +11618,16 @@ class Sema final : public SemaBase { void NoteAllFoundTemplates(TemplateName Name); - QualType CheckTemplateIdType(TemplateName Template, + QualType CheckTemplateIdType(ElaboratedTypeKeyword Keyword, + TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs); TypeResult - ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - TemplateTy Template, const IdentifierInfo *TemplateII, + ActOnTemplateIdType(Scope *S, ElaboratedTypeKeyword ElaboratedKeyword, + SourceLocation ElaboratedKeywordLoc, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, TemplateTy Template, + const IdentifierInfo *TemplateII, SourceLocation TemplateIILoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, bool IsCtorOrDtorName = false, bool IsClassName = false, @@ -11858,8 +11861,8 @@ class Sema final : public SemaBase { /// argument, substitute into that default template argument and /// return the corresponding template argument. TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable( - TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, Decl *Param, + TemplateDecl *Template, SourceLocation TemplateKWLoc, + SourceLocation TemplateNameLoc, SourceLocation RAngleLoc, Decl *Param, ArrayRef SugaredConverted, ArrayRef CanonicalConverted, bool &HasDefaultArg); @@ -13762,8 +13765,9 @@ class Sema final : public SemaBase { SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); TemplateName - SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, - SourceLocation Loc, + SubstTemplateName(SourceLocation TemplateKWLoc, + NestedNameSpecifierLoc &QualifierLoc, TemplateName Name, + SourceLocation NameLoc, const MultiLevelTemplateArgumentList &TemplateArgs); bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC, @@ -15179,14 +15183,6 @@ class Sema final : public SemaBase { return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser); } - /// Retrieve a version of the type 'T' that is elaborated by Keyword, - /// qualified by the nested-name-specifier contained in SS, and that is - /// (re)declared by OwnedTagDecl, which is nullptr if this is not a - /// (re)declaration. - QualType getElaboratedType(ElaboratedTypeKeyword Keyword, - const CXXScopeSpec &SS, QualType T, - TagDecl *OwnedTagDecl = nullptr); - // Returns the underlying type of a decltype with the given expression. QualType getDecltypeForExpr(Expr *E); diff --git a/clang/include/clang/Sema/SemaInternal.h b/clang/include/clang/Sema/SemaInternal.h index 42c9469e44e53..f7c67c15379f1 100644 --- a/clang/include/clang/Sema/SemaInternal.h +++ b/clang/include/clang/Sema/SemaInternal.h @@ -209,7 +209,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { class NamespaceSpecifierSet { struct SpecifierInfo { DeclContext* DeclCtx; - NestedNameSpecifier* NameSpecifier; + NestedNameSpecifier NameSpecifier; unsigned EditDistance; }; @@ -229,9 +229,9 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { static DeclContextList buildContextChain(DeclContext *Start); unsigned buildNestedNameSpecifier(DeclContextList &DeclChain, - NestedNameSpecifier *&NNS); + NestedNameSpecifier &NNS); - public: + public: NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec); @@ -276,7 +276,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { }; void addName(StringRef Name, NamedDecl *ND, - NestedNameSpecifier *NNS = nullptr, bool isKeyword = false); + NestedNameSpecifier NNS = std::nullopt, bool isKeyword = false); /// Find any visible decls for the given typo correction candidate. /// If none are found, it to the set of candidates for which qualified lookups diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index 09de164297e7b..1d780c45efd55 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -57,15 +57,15 @@ class TypoCorrection { static const unsigned CallbackDistanceWeight = 150U; TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl, - NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0, - unsigned QualifierDistance = 0) + NestedNameSpecifier NNS = std::nullopt, + unsigned CharDistance = 0, unsigned QualifierDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), CharDistance(CharDistance), QualifierDistance(QualifierDistance) { if (NameDecl) CorrectionDecls.push_back(NameDecl); } - TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr, + TypoCorrection(NamedDecl *Name, NestedNameSpecifier NNS = std::nullopt, unsigned CharDistance = 0) : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), CharDistance(CharDistance) { @@ -73,7 +73,7 @@ class TypoCorrection { CorrectionDecls.push_back(Name); } - TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr, + TypoCorrection(DeclarationName Name, NestedNameSpecifier NNS = std::nullopt, unsigned CharDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), CharDistance(CharDistance) {} @@ -88,13 +88,13 @@ class TypoCorrection { } /// Gets the NestedNameSpecifier needed to use the typo correction - NestedNameSpecifier *getCorrectionSpecifier() const { + NestedNameSpecifier getCorrectionSpecifier() const { return CorrectionNameSpec; } - void setCorrectionSpecifier(NestedNameSpecifier *NNS) { + void setCorrectionSpecifier(NestedNameSpecifier NNS) { CorrectionNameSpec = NNS; - ForceSpecifierReplacement = (NNS != nullptr); + ForceSpecifierReplacement = !!NNS; } void WillReplaceSpecifier(bool ForceReplacement) { @@ -264,7 +264,7 @@ class TypoCorrection { // Results. DeclarationName CorrectionName; - NestedNameSpecifier *CorrectionNameSpec = nullptr; + NestedNameSpecifier CorrectionNameSpec = std::nullopt; SmallVector CorrectionDecls; unsigned CharDistance = 0; unsigned QualifierDistance = 0; @@ -282,8 +282,9 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr, - NestedNameSpecifier *TypoNNS = nullptr) + explicit CorrectionCandidateCallback( + const IdentifierInfo *Typo = nullptr, + NestedNameSpecifier TypoNNS = std::nullopt) : Typo(Typo), TypoNNS(TypoNNS) {} virtual ~CorrectionCandidateCallback() = default; @@ -320,7 +321,7 @@ class CorrectionCandidateCallback { virtual std::unique_ptr clone() = 0; void setTypoName(const IdentifierInfo *II) { Typo = II; } - void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } + void setTypoNNS(NestedNameSpecifier NNS) { TypoNNS = NNS; } // Flags for context-dependent keywords. WantFunctionLikeCasts is only // used/meaningful when WantCXXNamedCasts is false. @@ -346,13 +347,13 @@ class CorrectionCandidateCallback { } const IdentifierInfo *Typo; - NestedNameSpecifier *TypoNNS; + NestedNameSpecifier TypoNNS; }; class DefaultFilterCCC final : public CorrectionCandidateCallback { public: explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr, - NestedNameSpecifier *TypoNNS = nullptr) + NestedNameSpecifier TypoNNS = std::nullopt) : CorrectionCandidateCallback(Typo, TypoNNS) {} std::unique_ptr clone() override { @@ -366,7 +367,7 @@ template class DeclFilterCCC final : public CorrectionCandidateCallback { public: explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr, - NestedNameSpecifier *TypoNNS = nullptr) + NestedNameSpecifier TypoNNS = std::nullopt) : CorrectionCandidateCallback(Typo, TypoNNS) {} bool ValidateCandidate(const TypoCorrection &candidate) override { diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 1472497ff5e7e..aed1b7d309001 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -223,7 +223,7 @@ class ASTRecordReader void readQualifierInfo(QualifierInfo &Info); /// Return a nested name specifier, advancing Idx. - // NestedNameSpecifier *readNestedNameSpecifier(); (inherited) + // NestedNameSpecifier readNestedNameSpecifier(); (inherited) NestedNameSpecifierLoc readNestedNameSpecifierLoc(); diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h index ee005ec287708..9849ea6b395ab 100644 --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -247,8 +247,7 @@ class ASTRecordWriter void AddTypeLoc(TypeLoc TL); /// Emits a template argument location info. - void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - const TemplateArgumentLocInfo &Arg); + void AddTemplateArgumentLocInfo(const TemplateArgumentLoc &Arg); /// Emits a template argument location. void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg); @@ -280,7 +279,7 @@ class ASTRecordWriter void AddQualifierInfo(const QualifierInfo &Info); /// Emit a nested name specifier. - void AddNestedNameSpecifier(NestedNameSpecifier *NNS) { + void AddNestedNameSpecifier(NestedNameSpecifier NNS) { writeNestedNameSpecifier(NNS); } diff --git a/clang/include/clang/Tooling/Refactoring/Lookup.h b/clang/include/clang/Tooling/Refactoring/Lookup.h index dcb40b7eee66c..fe0df8656bce1 100644 --- a/clang/include/clang/Tooling/Refactoring/Lookup.h +++ b/clang/include/clang/Tooling/Refactoring/Lookup.h @@ -38,8 +38,7 @@ namespace tooling { /// \param ReplacementString The replacement nested name. Must be fully /// qualified including a leading "::". /// \returns The new name to be inserted in place of the current nested name. -std::string replaceNestedName(const NestedNameSpecifier *Use, - SourceLocation UseLoc, +std::string replaceNestedName(NestedNameSpecifier Use, SourceLocation UseLoc, const DeclContext *UseContext, const NamedDecl *FromDecl, StringRef ReplacementString); diff --git a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index 271232e66626e..319569fd5ab33 100644 --- a/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/clang/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -108,19 +108,21 @@ class RecursiveSymbolVisitor bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken(TL.getBeginLoc(), 0, SM, LangOpts); - return visit(TL.getTypedefNameDecl(), TL.getBeginLoc(), TypeEndLoc); + return visit(TL.getDecl(), TL.getBeginLoc(), TypeEndLoc); } - bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { + bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) { // The base visitor will visit NNSL prefixes, so we should only look at // the current NNS. - if (NNS) { - const auto *ND = dyn_cast_if_present( - NNS.getNestedNameSpecifier()->getAsNamespace()); - if (!visit(ND, NNS.getLocalBeginLoc(), NNS.getLocalEndLoc())) + if (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Namespace) { + const auto *ND = dyn_cast( + Qualifier.getAsNamespaceAndPrefix().Namespace); + if (!visit(ND, QualifierLoc.getLocalBeginLoc(), + QualifierLoc.getLocalEndLoc())) return false; } - return BaseType::TraverseNestedNameSpecifierLoc(NNS); + return BaseType::TraverseNestedNameSpecifierLoc(QualifierLoc); } bool VisitDesignatedInitExpr(const DesignatedInitExpr *E) { diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index ee3dc84479fd9..2d62209bbc28c 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -902,8 +902,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, } case APValue::Struct: { Out << '{'; - const RecordDecl *RD = Ty->castAs()->getDecl(); bool First = true; + const RecordDecl *RD = + Ty->castAs()->getOriginalDecl()->getDefinitionOrSelf(); if (unsigned N = getStructNumBases()) { const CXXRecordDecl *CD = cast(RD); CXXRecordDecl::base_class_const_iterator BI = CD->bases_begin(); diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index 2243ac035115f..d658890e076c2 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -14,6 +14,7 @@ #include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ExprConcepts.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "llvm/ADT/StringExtras.h" @@ -92,10 +93,16 @@ ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, FoundDecl, NamedConcept, ArgsAsWritten); } +SourceLocation ConceptReference::getBeginLoc() const { + // Note that if the qualifier is null the template KW must also be null. + if (auto QualifierLoc = getNestedNameSpecifierLoc()) + return QualifierLoc.getBeginLoc(); + return getConceptNameInfo().getBeginLoc(); +} + void ConceptReference::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { - if (NestedNameSpec) - NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); + NestedNameSpec.getNestedNameSpecifier().print(OS, Policy); ConceptName.printName(OS, Policy); if (hasExplicitTemplateArgs()) { OS << "<"; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 3f95baf901ca7..95dd42681d870 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -654,7 +654,7 @@ comments::FullComment *ASTContext::getCommentForDecl( // does not have one of its own. QualType QT = TD->getUnderlyingType(); if (const auto *TT = QT->getAs()) - if (const Decl *TD = TT->getDecl()) + if (const Decl *TD = TT->getOriginalDecl()) if (comments::FullComment *FC = getCommentForDecl(TD, PP)) return cloneFullComment(FC, D); } @@ -1933,10 +1933,12 @@ TypeInfoChars ASTContext::getTypeInfoDataSizeInChars(QualType T) const { // of a base-class subobject. We decide whether that's possible // during class layout, so here we can just trust the layout results. if (getLangOpts().CPlusPlus) { - if (const auto *RT = T->getAs(); - RT && !RT->getDecl()->isInvalidDecl()) { - const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl()); - Info.Width = layout.getDataSize(); + if (const auto *RT = T->getAs()) { + const auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (!RD->isInvalidDecl()) { + const ASTRecordLayout &layout = getASTRecordLayout(RD); + Info.Width = layout.getDataSize(); + } } } @@ -2003,8 +2005,9 @@ bool ASTContext::isPromotableIntegerType(QualType T) const { // Enumerated types are promotable to their compatible integer types // (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2). if (const auto *ET = T->getAs()) { - if (T->isDependentType() || ET->getDecl()->getPromotionType().isNull() || - ET->getDecl()->isScoped()) + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (T->isDependentType() || ED->getPromotionType().isNull() || + ED->isScoped()) return false; return true; @@ -2472,15 +2475,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Record: case Type::Enum: { const auto *TT = cast(T); + const TagDecl *TD = TT->getOriginalDecl()->getDefinitionOrSelf(); - if (TT->getDecl()->isInvalidDecl()) { + if (TD->isInvalidDecl()) { Width = 8; Align = 8; break; } - if (const auto *ET = dyn_cast(TT)) { - const EnumDecl *ED = ET->getDecl(); + if (isa(TT)) { + const EnumDecl *ED = cast(TD); TypeInfo Info = getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType()); if (unsigned AttrAlign = ED->getMaxAlignment()) { @@ -2615,8 +2619,7 @@ unsigned ASTContext::getTypeUnadjustedAlign(const Type *T) const { unsigned UnadjustedAlign; if (const auto *RT = T->getAs()) { - const RecordDecl *RD = RT->getDecl(); - const ASTRecordLayout &Layout = getASTRecordLayout(RD); + const ASTRecordLayout &Layout = getASTRecordLayout(RT->getOriginalDecl()); UnadjustedAlign = toBits(Layout.getUnadjustedAlignment()); } else if (const auto *ObjCI = T->getAs()) { const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -2692,7 +2695,7 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; if (const auto *RT = T->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // When used as part of a typedef, or together with a 'packed' attribute, // the 'aligned' attribute can be used to decrease alignment. Note that the @@ -2715,7 +2718,10 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (const auto *CT = T->getAs()) T = CT->getElementType().getTypePtr(); if (const auto *ET = T->getAs()) - T = ET->getDecl()->getIntegerType().getTypePtr(); + T = ET->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType() + .getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || T->isSpecificBuiltinType(BuiltinType::ULongLong) || @@ -3042,7 +3048,8 @@ bool ASTContext::hasUniqueObjectRepresentations( return !ABI->getMemberPointerInfo(MPT).HasPadding; if (Ty->isRecordType()) { - const RecordDecl *Record = Ty->castAs()->getDecl(); + const RecordDecl *Record = + Ty->castAs()->getOriginalDecl()->getDefinitionOrSelf(); if (Record->isInvalidDecl()) return false; @@ -3415,7 +3422,10 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, // type, or an unsigned integer type. // // So we have to treat enum types as integers. - QualType UnderlyingType = cast(T)->getDecl()->getIntegerType(); + QualType UnderlyingType = cast(T) + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType(); return encodeTypeForFunctionPointerAuth( Ctx, OS, UnderlyingType.isNull() ? Ctx.IntTy : UnderlyingType); } @@ -3559,7 +3569,8 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, llvm_unreachable("should never get here"); } case Type::Record: { - const RecordDecl *RD = T->castAs()->getDecl(); + const RecordDecl *RD = + T->castAs()->getOriginalDecl()->getDefinitionOrSelf(); const IdentifierInfo *II = RD->getIdentifier(); // In C++, an immediate typedef of an anonymous struct or union @@ -4154,14 +4165,13 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { } QualType ASTContext::getMemberPointerType(QualType T, - NestedNameSpecifier *Qualifier, + NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const { if (!Qualifier) { assert(Cls && "At least one of Qualifier or Cls must be provided"); - Qualifier = NestedNameSpecifier::Create(*this, /*Prefix=*/nullptr, - getTypeDeclType(Cls).getTypePtr()); + Qualifier = NestedNameSpecifier(getCanonicalTagType(Cls).getTypePtr()); } else if (!Cls) { - Cls = Qualifier->getAsRecordDecl(); + Cls = Qualifier.getAsRecordDecl(); } // Unique pointers, to guarantee there is only one pointer of a particular // structure. @@ -4173,12 +4183,11 @@ QualType ASTContext::getMemberPointerType(QualType T, MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); - NestedNameSpecifier *CanonicalQualifier = [&] { + NestedNameSpecifier CanonicalQualifier = [&] { if (!Cls) - return getCanonicalNestedNameSpecifier(Qualifier); - NestedNameSpecifier *R = NestedNameSpecifier::Create( - *this, /*Prefix=*/nullptr, Cls->getCanonicalDecl()->getTypeForDecl()); - assert(R == getCanonicalNestedNameSpecifier(R)); + return Qualifier.getCanonical(); + NestedNameSpecifier R(getCanonicalTagType(Cls).getTypePtr()); + assert(R.isCanonical()); return R; }(); // If the pointee or class type isn't canonical, this won't be a canonical @@ -5449,12 +5458,8 @@ TagType *ASTContext::getTagTypeInternal(ElaboratedTypeKeyword Keyword, return T; } case Type::InjectedClassName: { - CanQualType CanonicalInjectedTST = - cast(TD)->getCanonicalTemplateSpecializationType( - *this); - auto *T = - new (Mem) InjectedClassNameType(Keyword, Qualifier, TD, IsInjected, - CanonicalInjectedTST, CanonicalType); + auto *T = new (Mem) InjectedClassNameType(Keyword, Qualifier, TD, + IsInjected, CanonicalType); assert(reinterpret_cast(T) == reinterpret_cast(static_cast(T)) && "TagType must be the first base of InjectedClassNameType"); @@ -6092,7 +6097,7 @@ getCanonicalElaboratedTypeKeyword(ElaboratedTypeKeyword Keyword) { } QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, + NestedNameSpecifier NNS, const IdentifierInfo *Name) const { llvm::FoldingSetNodeID ID; DependentNameType::Profile(ID, Keyword, NNS, Name); @@ -6104,7 +6109,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, ElaboratedTypeKeyword CanonKeyword = getCanonicalElaboratedTypeKeyword(Keyword); - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + NestedNameSpecifier CanonNNS = NNS.getCanonical(); QualType Canon; if (CanonKeyword != Keyword || CanonNNS != NNS) { @@ -6142,13 +6147,13 @@ QualType ASTContext::getDependentTemplateSpecializationType( T_iter != DependentTemplateSpecializationTypes.end()) return QualType(T_iter->getSecond(), 0); - NestedNameSpecifier *NNS = Name.getQualifier(); + NestedNameSpecifier NNS = Name.getQualifier(); QualType Canon; if (!IsCanonical) { ElaboratedTypeKeyword CanonKeyword = getCanonicalElaboratedTypeKeyword(Keyword); - NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); + NestedNameSpecifier CanonNNS = NNS.getCanonical(); bool AnyNonCanonArgs = false; auto CanonArgs = ::getCanonicalTemplateArguments(*this, Args, AnyNonCanonArgs); @@ -6163,7 +6168,7 @@ QualType ASTContext::getDependentTemplateSpecializationType( } else { assert(Keyword == getCanonicalElaboratedTypeKeyword(Keyword)); assert(Name.hasTemplateKeyword()); - assert(NNS == getCanonicalNestedNameSpecifier(NNS)); + assert(NNS.isCanonical()); #ifndef NDEBUG for (const auto &Arg : Args) assert(Arg.structurallyEquals(getCanonicalTemplateArgument(Arg))); @@ -7208,8 +7213,8 @@ bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2, *RD2 = T2MPType->getMostRecentCXXRecordDecl(); RD1 != RD2 && RD1->getCanonicalDecl() != RD2->getCanonicalDecl()) return false; - if (getCanonicalNestedNameSpecifier(T1MPType->getQualifier()) != - getCanonicalNestedNameSpecifier(T2MPType->getQualifier())) + if (T1MPType->getQualifier().getCanonical() != + T2MPType->getQualifier().getCanonical()) return false; T1 = T1MPType->getPointeeType(); T2 = T2MPType->getPointeeType(); @@ -7366,9 +7371,8 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name, case TemplateName::DependentTemplate: { DependentTemplateName *DTN = Name.getAsDependentTemplateName(); assert(DTN && "Non-dependent template names must refer to template decls."); - NestedNameSpecifier *Qualifier = DTN->getQualifier(); - NestedNameSpecifier *CanonQualifier = - getCanonicalNestedNameSpecifier(Qualifier); + NestedNameSpecifier Qualifier = DTN->getQualifier(); + NestedNameSpecifier CanonQualifier = Qualifier.getCanonical(); if (Qualifier != CanonQualifier || !DTN->hasTemplateKeyword()) return getDependentTemplateName({CanonQualifier, DTN->getName(), /*HasTemplateKeyword=*/true}); @@ -7585,38 +7589,40 @@ bool ASTContext::isSameDefaultTemplateArgument(const NamedDecl *X, return hasSameTemplateName(TAX.getAsTemplate(), TAY.getAsTemplate()); } -static bool isSameQualifier(const NestedNameSpecifier *X, - const NestedNameSpecifier *Y) { - if (X->getKind() != Y->getKind()) +static bool isSameQualifier(const NestedNameSpecifier X, + const NestedNameSpecifier Y) { + if (X == Y) + return true; + if (!X || !Y) + return false; + + auto Kind = X.getKind(); + if (Kind != Y.getKind()) return false; // FIXME: For namespaces and types, we're permitted to check that the entity // is named via the same tokens. We should probably do so. - switch (X->getKind()) { - case NestedNameSpecifier::Identifier: - if (X->getAsIdentifier() != Y->getAsIdentifier()) - return false; - break; - case NestedNameSpecifier::Namespace: - if (!declaresSameEntity(X->getAsNamespace(), Y->getAsNamespace())) + switch (Kind) { + case NestedNameSpecifier::Kind::Namespace: { + auto [NamespaceX, PrefixX] = X.getAsNamespaceAndPrefix(); + auto [NamespaceY, PrefixY] = Y.getAsNamespaceAndPrefix(); + if (!declaresSameEntity(NamespaceX->getNamespace(), + NamespaceY->getNamespace())) return false; - break; - case NestedNameSpecifier::TypeSpec: - if (X->getAsType()->getCanonicalTypeInternal() != - Y->getAsType()->getCanonicalTypeInternal()) + return isSameQualifier(PrefixX, PrefixY); + } + case NestedNameSpecifier::Kind::Type: { + const auto *TX = X.getAsType(), *TY = Y.getAsType(); + if (TX->getCanonicalTypeInternal() != TY->getCanonicalTypeInternal()) return false; - break; - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + return isSameQualifier(TX->getPrefix(), TY->getPrefix()); + } + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: return true; } - - // Recurse into earlier portion of NNS, if any. - auto *PX = X->getPrefix(); - auto *PY = Y->getPrefix(); - if (PX && PY) - return isSameQualifier(PX, PY); - return !PX && !PY; + llvm_unreachable("unhandled qualifier kind"); } static bool hasSameCudaAttrs(const FunctionDecl *A, const FunctionDecl *B) { @@ -8009,63 +8015,6 @@ bool ASTContext::isSameTemplateArgument(const TemplateArgument &Arg1, llvm_unreachable("Unhandled template argument kind"); } -NestedNameSpecifier * -ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { - if (!NNS) - return nullptr; - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - // Canonicalize the prefix but keep the identifier the same. - return NestedNameSpecifier::Create(*this, - getCanonicalNestedNameSpecifier(NNS->getPrefix()), - NNS->getAsIdentifier()); - - case NestedNameSpecifier::Namespace: - // A namespace is canonical; build a nested-name-specifier with - // this namespace and no prefix. - return NestedNameSpecifier::Create( - *this, nullptr, NNS->getAsNamespace()->getNamespace()->getFirstDecl()); - - // The difference between TypeSpec and TypeSpecWithTemplate is that the - // latter will have the 'template' keyword when printed. - case NestedNameSpecifier::TypeSpec: { - const Type *T = getCanonicalType(NNS->getAsType()); - - // If we have some kind of dependent-named type (e.g., "typename T::type"), - // break it apart into its prefix and identifier, then reconsititute those - // as the canonical nested-name-specifier. This is required to canonicalize - // a dependent nested-name-specifier involving typedefs of dependent-name - // types, e.g., - // typedef typename T::type T1; - // typedef typename T1::type T2; - if (const auto *DNT = T->getAs()) - return NestedNameSpecifier::Create(*this, DNT->getQualifier(), - DNT->getIdentifier()); - if (const auto *DTST = T->getAs()) { - const DependentTemplateStorage &DTN = DTST->getDependentTemplateName(); - QualType NewT = getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, - {/*NNS=*/nullptr, DTN.getName(), /*HasTemplateKeyword=*/true}, - DTST->template_arguments(), /*IsCanonical=*/true); - assert(NewT.isCanonical()); - NestedNameSpecifier *Prefix = DTN.getQualifier(); - if (!Prefix) - Prefix = getCanonicalNestedNameSpecifier(NNS->getPrefix()); - return NestedNameSpecifier::Create(*this, Prefix, NewT.getTypePtr()); - } - return NestedNameSpecifier::Create(*this, nullptr, T); - } - - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - // The global specifier and __super specifer are canonical and unique. - return NNS; - } - - llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); -} - const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the non-qualified case efficiently. if (!T.hasLocalQualifiers()) { @@ -8384,7 +8333,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { assert(!Promotable.isNull()); assert(isPromotableIntegerType(Promotable)); if (const auto *ET = Promotable->getAs()) - return ET->getDecl()->getPromotionType(); + return ET->getOriginalDecl()->getDefinitionOrSelf()->getPromotionType(); if (const auto *BT = Promotable->getAs()) { // C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t @@ -8443,8 +8392,9 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const { static const Type *getIntegerTypeForEnum(const EnumType *ET) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) - return ET->getDecl()->getIntegerType().getTypePtr(); + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (ED->isComplete() && !ED->isScoped()) + return ED->getIntegerType().getTypePtr(); return nullptr; } @@ -8605,7 +8555,7 @@ void ASTContext::setCFConstantStringType(QualType T) { const auto *TD = T->castAs(); CFConstantStringTypeDecl = cast(TD->getDecl()); const auto *TagType = TD->castAs(); - CFConstantStringTagDecl = TagType->getDecl(); + CFConstantStringTagDecl = TagType->getOriginalDecl()->getDefinitionOrSelf(); } QualType ASTContext::getBlockDescriptorType() const { @@ -9317,7 +9267,7 @@ static char getObjCEncodingForPrimitiveType(const ASTContext *C, } static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { - EnumDecl *Enum = ET->getDecl(); + EnumDecl *Enum = ET->getOriginalDecl()->getDefinitionOrSelf(); // The encoding of an non-fixed enum type is always 'i', regardless of size. if (!Enum->isFixed()) @@ -9486,13 +9436,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, return; } } else if (const auto *RTy = PointeeTy->getAs()) { + const IdentifierInfo *II = RTy->getOriginalDecl()->getIdentifier(); // GCC binary compat: Need to convert "struct objc_class *" to "#". - if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) { + if (II == &Idents.get("objc_class")) { S += '#'; return; } // GCC binary compat: Need to convert "struct objc_object *" to "@". - if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_object")) { + if (II == &Idents.get("objc_object")) { S += '@'; return; } @@ -9557,7 +9508,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, return; case Type::Record: { - RecordDecl *RDecl = cast(CT)->getDecl(); + RecordDecl *RDecl = cast(CT)->getOriginalDecl(); S += RDecl->isUnion() ? '(' : '{'; // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { @@ -10470,7 +10421,7 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const { /// Retrieve the template name that represents a qualified /// template name such as \c std::vector. -TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, +TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier Qualifier, bool TemplateKeyword, TemplateName Template) const { assert(Template.getKind() == TemplateName::Template || @@ -11455,7 +11406,7 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, bool OfBlockPointer, bool Unqualified) { if (const RecordType *UT = T->getAsUnionType()) { - RecordDecl *UD = UT->getDecl(); + RecordDecl *UD = UT->getOriginalDecl()->getMostRecentDecl(); if (UD->hasAttr()) { for (const auto *I : UD->fields()) { QualType ET = I->getType().getUnqualifiedType(); @@ -11687,7 +11638,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Look at the converted type of enum types, since that is the type used // to pass enum values. if (const auto *Enum = paramTy->getAs()) { - paramTy = Enum->getDecl()->getIntegerType(); + paramTy = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (paramTy.isNull()) return {}; } @@ -11719,7 +11671,8 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET, // a signed integer type, or an unsigned integer type. // Compatibility is based on the underlying type, not the promotion // type. - QualType underlyingType = ET->getDecl()->getIntegerType(); + QualType underlyingType = + ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (underlyingType.isNull()) return {}; if (Context.hasSameType(underlyingType, other)) @@ -12278,7 +12231,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { unsigned ASTContext::getIntWidth(QualType T) const { if (const auto *ET = T->getAs()) - T = ET->getDecl()->getIntegerType(); + T = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (T->isBooleanType()) return 1; if (const auto *EIT = T->getAs()) @@ -12304,7 +12257,7 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { // For enums, get the underlying integer type of the enum, and let the general // integer type signchanging code handle it. if (const auto *ETy = T->getAs()) - T = ETy->getDecl()->getIntegerType(); + T = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); switch (T->castAs()->getKind()) { case BuiltinType::Char_U: @@ -12378,7 +12331,7 @@ QualType ASTContext::getCorrespondingSignedType(QualType T) const { // For enums, get the underlying integer type of the enum, and let the general // integer type signchanging code handle it. if (const auto *ETy = T->getAs()) - T = ETy->getDecl()->getIntegerType(); + T = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); switch (T->castAs()->getKind()) { case BuiltinType::Char_S: @@ -13842,163 +13795,101 @@ static auto getCommonTemplateArguments(const ASTContext &Ctx, } template -static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y) { - return X->getKeyword() == Y->getKeyword() ? X->getKeyword() - : ElaboratedTypeKeyword::None; +static ElaboratedTypeKeyword getCommonTypeKeyword(const T *X, const T *Y, + bool IsSame) { + ElaboratedTypeKeyword KX = X->getKeyword(), KY = Y->getKeyword(); + if (KX == KY) + return KX; + KX = getCanonicalElaboratedTypeKeyword(KX); + assert(!IsSame || KX == getCanonicalElaboratedTypeKeyword(KY)); + return KX; } /// Returns a NestedNameSpecifier which has only the common sugar /// present in both NNS1 and NNS2. -static NestedNameSpecifier *getCommonNNS(ASTContext &Ctx, - NestedNameSpecifier *NNS1, - NestedNameSpecifier *NNS2, - bool IsSame) { +static NestedNameSpecifier getCommonNNS(const ASTContext &Ctx, + NestedNameSpecifier NNS1, + NestedNameSpecifier NNS2, bool IsSame) { // If they are identical, all sugar is common. if (NNS1 == NNS2) return NNS1; - // IsSame implies both NNSes are equivalent. - NestedNameSpecifier *Canon = Ctx.getCanonicalNestedNameSpecifier(NNS1); - if (Canon != Ctx.getCanonicalNestedNameSpecifier(NNS2)) { + // IsSame implies both Qualifiers are equivalent. + NestedNameSpecifier Canon = NNS1.getCanonical(); + if (Canon != NNS2.getCanonical()) { assert(!IsSame && "Should be the same NestedNameSpecifier"); // If they are not the same, there is nothing to unify. - // FIXME: It would be useful here if we could represent a canonically - // empty NNS, which is not identical to an empty-as-written NNS. - return nullptr; + return std::nullopt; } - NestedNameSpecifier *R = nullptr; - NestedNameSpecifier::SpecifierKind K1 = NNS1->getKind(), K2 = NNS2->getKind(); - switch (K1) { - case NestedNameSpecifier::SpecifierKind::Identifier: { - assert(K2 == NestedNameSpecifier::SpecifierKind::Identifier); - IdentifierInfo *II = NNS1->getAsIdentifier(); - assert(II == NNS2->getAsIdentifier()); - // For an identifier, the prefixes are significant, so they must be the - // same. - NestedNameSpecifier *P = ::getCommonNNS(Ctx, NNS1->getPrefix(), - NNS2->getPrefix(), /*IsSame=*/true); - R = NestedNameSpecifier::Create(Ctx, P, II); - break; - } - case NestedNameSpecifier::SpecifierKind::Namespace: { - assert(K2 == NestedNameSpecifier::SpecifierKind::Namespace); - // The prefixes for namespaces are not significant, its declaration - // identifies it uniquely. - NestedNameSpecifier *P = - ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), - /*IsSame=*/false); - NamespaceBaseDecl *Namespace1 = NNS1->getAsNamespace(), - *Namespace2 = NNS2->getAsNamespace(); + NestedNameSpecifier R = std::nullopt; + NestedNameSpecifier::Kind Kind = NNS1.getKind(); + assert(Kind == NNS2.getKind()); + switch (Kind) { + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix(); + auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix(); auto Kind = Namespace1->getKind(); if (Kind != Namespace2->getKind() || (Kind == Decl::NamespaceAlias && !declaresSameEntity(Namespace1, Namespace2))) { - R = NestedNameSpecifier::Create( - Ctx, P, + R = NestedNameSpecifier( + Ctx, ::getCommonDeclChecked(Namespace1->getNamespace(), - Namespace2->getNamespace())); + Namespace2->getNamespace()), + /*Prefix=*/std::nullopt); break; } - R = NestedNameSpecifier::Create( - Ctx, P, ::getCommonDeclChecked(Namespace1, Namespace2)); + // The prefixes for namespaces are not significant, its declaration + // identifies it uniquely. + NestedNameSpecifier Prefix = ::getCommonNNS(Ctx, Prefix1, Prefix2, + /*IsSame=*/false); + R = NestedNameSpecifier(Ctx, ::getCommonDeclChecked(Namespace1, Namespace2), + Prefix); break; } - case NestedNameSpecifier::SpecifierKind::TypeSpec: { - // FIXME: See comment below, on Super case. - if (K2 == NestedNameSpecifier::SpecifierKind::Super) - return Ctx.getCanonicalNestedNameSpecifier(NNS1); - - assert(K2 == NestedNameSpecifier::SpecifierKind::TypeSpec); - - const Type *T1 = NNS1->getAsType(), *T2 = NNS2->getAsType(); - if (T1 == T2) { - // If the types are indentical, then only the prefixes differ. - // A well-formed NNS never has these types, as they have - // special normalized forms. - assert((!isa(T1))); - // Only for a DependentTemplateSpecializationType the prefix - // is actually significant. A DependentName, which would be another - // plausible case, cannot occur here, as explained above. - bool IsSame = isa(T1); - NestedNameSpecifier *P = - ::getCommonNNS(Ctx, NNS1->getPrefix(), NNS2->getPrefix(), IsSame); - R = NestedNameSpecifier::Create(Ctx, P, T1); - break; - } - // TODO: Try to salvage the original prefix. - // If getCommonSugaredType removed any top level sugar, the original prefix - // is not applicable anymore. + case NestedNameSpecifier::Kind::Type: { + const Type *T1 = NNS1.getAsType(), *T2 = NNS2.getAsType(); const Type *T = Ctx.getCommonSugaredType(QualType(T1, 0), QualType(T2, 0), /*Unqualified=*/true) .getTypePtr(); - - // A NestedNameSpecifier has special normalization rules for certain types. - switch (T->getTypeClass()) { - case Type::Elaborated: { - // An ElaboratedType is stripped off, it's Qualifier becomes the prefix. - auto *ET = cast(T); - R = NestedNameSpecifier::Create(Ctx, ET->getQualifier(), - ET->getNamedType().getTypePtr()); - break; - } - case Type::DependentName: { - // A DependentName is turned into an Identifier NNS. - auto *DN = cast(T); - R = NestedNameSpecifier::Create(Ctx, DN->getQualifier(), - DN->getIdentifier()); - break; - } - case Type::DependentTemplateSpecialization: { - // A DependentTemplateSpecializationType loses it's Qualifier, which - // is turned into the prefix. - auto *DTST = cast(T); - const DependentTemplateStorage &DTN = DTST->getDependentTemplateName(); - DependentTemplateStorage NewDTN(/*Qualifier=*/nullptr, DTN.getName(), - DTN.hasTemplateKeyword()); - T = Ctx.getDependentTemplateSpecializationType(DTST->getKeyword(), NewDTN, - DTST->template_arguments()) - .getTypePtr(); - R = NestedNameSpecifier::Create(Ctx, DTN.getQualifier(), T); - break; - } - default: - R = NestedNameSpecifier::Create(Ctx, /*Prefix=*/nullptr, T); - break; - } + R = NestedNameSpecifier(T); break; } - case NestedNameSpecifier::SpecifierKind::Super: + case NestedNameSpecifier::Kind::MicrosoftSuper: { // FIXME: Can __super even be used with data members? // If it's only usable in functions, we will never see it here, // unless we save the qualifiers used in function types. // In that case, it might be possible NNS2 is a type, // in which case we should degrade the result to // a CXXRecordType. - return Ctx.getCanonicalNestedNameSpecifier(NNS1); - case NestedNameSpecifier::SpecifierKind::Global: - // The global NNS is a singleton. - assert(K2 == NestedNameSpecifier::SpecifierKind::Global && - "Global NNS cannot be equivalent to any other kind"); - llvm_unreachable("Global NestedNameSpecifiers did not compare equal"); - } - assert(Ctx.getCanonicalNestedNameSpecifier(R) == Canon); + R = NestedNameSpecifier(getCommonDeclChecked(NNS1.getAsMicrosoftSuper(), + NNS2.getAsMicrosoftSuper())); + break; + } + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + // These are singletons. + llvm_unreachable("singletons did not compare equal"); + } + assert(R.getCanonical() == Canon); return R; } template -static NestedNameSpecifier *getCommonQualifier(ASTContext &Ctx, const T *X, - const T *Y, bool IsSame) { +static NestedNameSpecifier getCommonQualifier(const ASTContext &Ctx, const T *X, + const T *Y, bool IsSame) { return ::getCommonNNS(Ctx, X->getQualifier(), Y->getQualifier(), IsSame); } template -static QualType getCommonElementType(ASTContext &Ctx, const T *X, const T *Y) { +static QualType getCommonElementType(const ASTContext &Ctx, const T *X, + const T *Y) { return Ctx.getCommonSugaredType(X->getElementType(), Y->getElementType()); } template -static QualType getCommonArrayElementType(ASTContext &Ctx, const T *X, +static QualType getCommonArrayElementType(const ASTContext &Ctx, const T *X, Qualifiers &QX, const T *Y, Qualifiers &QY) { QualType EX = X->getElementType(), EY = Y->getElementType(); @@ -14363,13 +14254,15 @@ static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X, getCommonElementType(Ctx, VX, VY), getCommonSizeExpr(Ctx, VX, VY), getCommonAttrLoc(VX, VY), VX->getVectorKind()); } + case Type::Enum: + case Type::Record: case Type::InjectedClassName: { - const auto *IX = cast(X), - *IY = cast(Y); - return Ctx.getInjectedClassNameType( - getCommonDeclChecked(IX->getDecl(), IY->getDecl()), - Ctx.getCommonSugaredType(IX->getInjectedSpecializationType(), - IY->getInjectedSpecializationType())); + const auto *TX = cast(X), *TY = cast(Y); + return Ctx.getTagType( + ::getCommonTypeKeyword(TX, TY, /*IsSame=*/false), + ::getCommonQualifier(Ctx, TX, TY, /*IsSame=*/false), + ::getCommonDeclChecked(TX->getOriginalDecl(), TY->getOriginalDecl()), + /*OwnedTag=*/false); } case Type::TemplateSpecialization: { const auto *TX = cast(X), diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index 6049bfb64ebbe..d7fd411ab464c 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -196,7 +196,8 @@ break; \ // Don't desugar through the primary typedef of an anonymous type. if (const TagType *UTT = Underlying->getAs()) if (const TypedefType *QTT = dyn_cast(QT)) - if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) + if (UTT->getOriginalDecl()->getTypedefNameForAnonDecl() == + QTT->getDecl()) break; // Record that we actually looked through an opaque type here. @@ -457,13 +458,12 @@ void clang::FormatASTNodeDiagnosticArgument( ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); break; } - case DiagnosticsEngine::ak_nestednamespec: { - NestedNameSpecifier *NNS = reinterpret_cast(Val); - NNS->print(OS, Context.getPrintingPolicy(), + case DiagnosticsEngine::ak_nestednamespec: + NestedNameSpecifier::getFromVoidPointer(reinterpret_cast(Val)) + .print(OS, Context.getPrintingPolicy(), /*ResolveTemplateArguments=*/false, /*PrintFinalScopeResOp=*/false); break; - } case DiagnosticsEngine::ak_declcontext: { DeclContext *DC = reinterpret_cast (Val); assert(DC && "Should never have a null declaration context"); @@ -1153,7 +1153,7 @@ class TemplateDiff { return nullptr; const ClassTemplateSpecializationDecl *CTSD = - dyn_cast(RT->getDecl()); + dyn_cast(RT->getOriginalDecl()); if (!CTSD) return nullptr; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index e5d4b103a6475..315ead9ef0105 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2157,7 +2157,7 @@ Error ASTNodeImporter::ImportDeclParts( const Type *LeafT = getLeafPointeeType(P->getType().getCanonicalType().getTypePtr()); auto *RT = dyn_cast(LeafT); - if (RT && RT->getDecl() == D) { + if (RT && RT->getOriginalDecl() == D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); return make_error(ASTImportError::UnsupportedConstruct); @@ -2410,8 +2410,8 @@ Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From, const RecordType *RecordTo = ToType->getAs(); if (RecordFrom && RecordTo) { - FromRecordDecl = RecordFrom->getDecl(); - ToRecordDecl = RecordTo->getDecl(); + FromRecordDecl = RecordFrom->getOriginalDecl(); + ToRecordDecl = RecordTo->getOriginalDecl(); } } @@ -3207,7 +3207,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (auto *Typedef = dyn_cast(FoundDecl)) { if (const auto *Tag = Typedef->getUnderlyingType()->getAs()) - FoundDecl = Tag->getDecl(); + FoundDecl = Tag->getOriginalDecl(); } if (auto *FoundEnum = dyn_cast(FoundDecl)) { @@ -3338,7 +3338,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Decl *Found = FoundDecl; if (auto *Typedef = dyn_cast(Found)) { if (const auto *Tag = Typedef->getUnderlyingType()->getAs()) - Found = Tag->getDecl(); + Found = Tag->getOriginalDecl(); } if (auto *FoundRecord = dyn_cast(Found)) { @@ -3759,11 +3759,12 @@ class IsTypeDeclaredInsideVisitor } std::optional VisitTagType(const TagType *T) { - if (auto *Spec = dyn_cast(T->getDecl())) + if (auto *Spec = + dyn_cast(T->getOriginalDecl())) for (const auto &Arg : Spec->getTemplateArgs().asArray()) if (checkTemplateArgument(Arg)) return true; - return isAncestorDeclContextOf(ParentDC, T->getDecl()); + return isAncestorDeclContextOf(ParentDC, T->getOriginalDecl()); } std::optional VisitPointerType(const PointerType *T) { @@ -9971,46 +9972,34 @@ Expected ASTImporter::Import(Stmt *FromS) { return ToSOrErr; } -Expected -ASTImporter::Import(NestedNameSpecifier *FromNNS) { - if (!FromNNS) - return nullptr; - - NestedNameSpecifier *Prefix = nullptr; - if (Error Err = importInto(Prefix, FromNNS->getPrefix())) - return std::move(Err); - - switch (FromNNS->getKind()) { - case NestedNameSpecifier::Identifier: - assert(FromNNS->getAsIdentifier() && "NNS should contain identifier."); - return NestedNameSpecifier::Create(ToContext, Prefix, - Import(FromNNS->getAsIdentifier())); - - case NestedNameSpecifier::Namespace: - if (ExpectedDecl NSOrErr = Import(FromNNS->getAsNamespace())) { - return NestedNameSpecifier::Create(ToContext, Prefix, - cast(*NSOrErr)); - } else +Expected ASTImporter::Import(NestedNameSpecifier FromNNS) { + switch (FromNNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + return FromNNS; + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = FromNNS.getAsNamespaceAndPrefix(); + auto NSOrErr = Import(Namespace); + if (!NSOrErr) return NSOrErr.takeError(); - - case NestedNameSpecifier::Global: - return NestedNameSpecifier::GlobalSpecifier(ToContext); - - case NestedNameSpecifier::Super: - if (ExpectedDecl RDOrErr = Import(FromNNS->getAsRecordDecl())) - return NestedNameSpecifier::SuperSpecifier(ToContext, - cast(*RDOrErr)); + auto PrefixOrErr = Import(Prefix); + if (!PrefixOrErr) + return PrefixOrErr.takeError(); + return NestedNameSpecifier(ToContext, cast(*NSOrErr), + *PrefixOrErr); + } + case NestedNameSpecifier::Kind::MicrosoftSuper: + if (ExpectedDecl RDOrErr = Import(FromNNS.getAsMicrosoftSuper())) + return NestedNameSpecifier(cast(*RDOrErr)); else return RDOrErr.takeError(); - - case NestedNameSpecifier::TypeSpec: - if (ExpectedTypePtr TyOrErr = Import(FromNNS->getAsType())) { - return NestedNameSpecifier::Create(ToContext, Prefix, *TyOrErr); + case NestedNameSpecifier::Kind::Type: + if (ExpectedTypePtr TyOrErr = Import(FromNNS.getAsType())) { + return NestedNameSpecifier(*TyOrErr); } else { return TyOrErr.takeError(); } } - llvm_unreachable("Invalid nested name specifier kind"); } @@ -10024,64 +10013,62 @@ ASTImporter::Import(NestedNameSpecifierLoc FromNNS) { // serialization in reverse order. while (NNS) { NestedNames.push_back(NNS); - NNS = NNS.getPrefix(); + NNS = NNS.getAsNamespaceAndPrefix().Prefix; } NestedNameSpecifierLocBuilder Builder; while (!NestedNames.empty()) { NNS = NestedNames.pop_back_val(); - NestedNameSpecifier *Spec = nullptr; + NestedNameSpecifier Spec = std::nullopt; if (Error Err = importInto(Spec, NNS.getNestedNameSpecifier())) return std::move(Err); - NestedNameSpecifier::SpecifierKind Kind = Spec->getKind(); + NestedNameSpecifier::Kind Kind = Spec.getKind(); SourceLocation ToLocalBeginLoc, ToLocalEndLoc; - if (Kind != NestedNameSpecifier::Super) { + if (Kind != NestedNameSpecifier::Kind::MicrosoftSuper) { if (Error Err = importInto(ToLocalBeginLoc, NNS.getLocalBeginLoc())) return std::move(Err); - if (Kind != NestedNameSpecifier::Global) + if (Kind != NestedNameSpecifier::Kind::Global) if (Error Err = importInto(ToLocalEndLoc, NNS.getLocalEndLoc())) return std::move(Err); } switch (Kind) { - case NestedNameSpecifier::Identifier: - Builder.Extend(getToContext(), Spec->getAsIdentifier(), ToLocalBeginLoc, - ToLocalEndLoc); - break; - - case NestedNameSpecifier::Namespace: - Builder.Extend(getToContext(), Spec->getAsNamespace(), ToLocalBeginLoc, - ToLocalEndLoc); + case NestedNameSpecifier::Kind::Namespace: + Builder.Extend(getToContext(), Spec.getAsNamespaceAndPrefix().Namespace, + ToLocalBeginLoc, ToLocalEndLoc); break; - case NestedNameSpecifier::TypeSpec: { + case NestedNameSpecifier::Kind::Type: { SourceLocation ToTLoc; - if (Error Err = importInto(ToTLoc, NNS.getTypeLoc().getBeginLoc())) + if (Error Err = importInto(ToTLoc, NNS.castAsTypeLoc().getBeginLoc())) return std::move(Err); TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo( - QualType(Spec->getAsType(), 0), ToTLoc); - Builder.Extend(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc); + QualType(Spec.getAsType(), 0), ToTLoc); + Builder.Make(getToContext(), TSI->getTypeLoc(), ToLocalEndLoc); break; } - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: Builder.MakeGlobal(getToContext(), ToLocalBeginLoc); break; - case NestedNameSpecifier::Super: { + case NestedNameSpecifier::Kind::MicrosoftSuper: { auto ToSourceRangeOrErr = Import(NNS.getSourceRange()); if (!ToSourceRangeOrErr) return ToSourceRangeOrErr.takeError(); - Builder.MakeSuper(getToContext(), Spec->getAsRecordDecl(), - ToSourceRangeOrErr->getBegin(), - ToSourceRangeOrErr->getEnd()); + Builder.MakeMicrosoftSuper(getToContext(), Spec.getAsMicrosoftSuper(), + ToSourceRangeOrErr->getBegin(), + ToSourceRangeOrErr->getEnd()); + break; + } + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } - } } return Builder.getWithLocInContext(getToContext()); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index fff912d6b83cd..096bc6c8ca5b3 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -110,8 +110,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, const TemplateArgumentLoc &Arg1, const TemplateArgumentLoc &Arg2); static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - NestedNameSpecifier *NNS1, - NestedNameSpecifier *NNS2); + NestedNameSpecifier NNS1, + NestedNameSpecifier NNS2); static bool IsStructurallyEquivalent(const IdentifierInfo *Name1, const IdentifierInfo *Name2); @@ -579,35 +579,30 @@ static bool IsStructurallyEquivalent(const IdentifierInfo *Name1, /// Determine whether two nested-name-specifiers are equivalent. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, - NestedNameSpecifier *NNS1, - NestedNameSpecifier *NNS2) { - if (NNS1->getKind() != NNS2->getKind()) - return false; - - NestedNameSpecifier *Prefix1 = NNS1->getPrefix(), - *Prefix2 = NNS2->getPrefix(); - if ((bool)Prefix1 != (bool)Prefix2) - return false; - - if (Prefix1) - if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2)) - return false; - - switch (NNS1->getKind()) { - case NestedNameSpecifier::Identifier: - return IsStructurallyEquivalent(NNS1->getAsIdentifier(), - NNS2->getAsIdentifier()); - case NestedNameSpecifier::Namespace: - return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(), - NNS2->getAsNamespace()); - case NestedNameSpecifier::TypeSpec: - return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0), - QualType(NNS2->getAsType(), 0)); - case NestedNameSpecifier::Global: + NestedNameSpecifier NNS1, + NestedNameSpecifier NNS2) { + auto Kind = NNS1.getKind(); + if (Kind != NNS2.getKind()) + return false; + switch (Kind) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: return true; - case NestedNameSpecifier::Super: - return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(), - NNS2->getAsRecordDecl()); + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace1, Prefix1] = NNS1.getAsNamespaceAndPrefix(); + auto [Namespace2, Prefix2] = NNS2.getAsNamespaceAndPrefix(); + if (!IsStructurallyEquivalent(Context, + const_cast(Namespace1), + const_cast(Namespace2))) + return false; + return IsStructurallyEquivalent(Context, Prefix1, Prefix2); + } + case NestedNameSpecifier::Kind::Type: + return IsStructurallyEquivalent(Context, QualType(NNS1.getAsType(), 0), + QualType(NNS2.getAsType(), 0)); + case NestedNameSpecifier::Kind::MicrosoftSuper: + return IsStructurallyEquivalent(Context, NNS1.getAsMicrosoftSuper(), + NNS2.getAsMicrosoftSuper()); } return false; } @@ -615,9 +610,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, const DependentTemplateStorage &S1, const DependentTemplateStorage &S2) { - if (NestedNameSpecifier *NNS1 = S1.getQualifier(), *NNS2 = S2.getQualifier(); - !NNS1 != !NNS2 || - (NNS1 && !IsStructurallyEquivalent(Context, NNS1, NNS2))) + if (!IsStructurallyEquivalent(Context, S1.getQualifier(), S2.getQualifier())) return false; IdentifierOrOverloadedOperator IO1 = S1.getName(), IO2 = S2.getName(); @@ -885,10 +878,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // Treat the enumeration as its underlying type and use the builtin type // class comparison. if (T1->getTypeClass() == Type::Enum) { - T1 = T1->getAs()->getDecl()->getIntegerType(); + T1 = T1->getAs()->getOriginalDecl()->getIntegerType(); assert(T2->isBuiltinType() && !T1.isNull()); // Sanity check } else if (T2->getTypeClass() == Type::Enum) { - T2 = T2->getAs()->getDecl()->getIntegerType(); + T2 = T2->getAs()->getOriginalDecl()->getIntegerType(); assert(T1->isBuiltinType() && !T2.isNull()); // Sanity check } TC = Type::Builtin; @@ -1544,8 +1537,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, // types if (Field1->isAnonymousStructOrUnion() && Field2->isAnonymousStructOrUnion()) { - RecordDecl *D1 = Field1->getType()->castAs()->getDecl(); - RecordDecl *D2 = Field2->getType()->castAs()->getDecl(); + RecordDecl *D1 = Field1->getType()->castAs()->getOriginalDecl(); + RecordDecl *D2 = Field2->getType()->castAs()->getOriginalDecl(); return IsStructurallyEquivalent(Context, D1, D2); } @@ -2613,7 +2606,7 @@ StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) { // struct { ... } A; QualType FieldType = F->getType(); if (const auto *RecType = dyn_cast(FieldType)) { - const RecordDecl *RecDecl = RecType->getDecl(); + const RecordDecl *RecDecl = RecType->getOriginalDecl(); if (RecDecl->getDeclContext() == Owner && !RecDecl->getIdentifier()) { if (Context.hasSameType(FieldType, AnonTy)) break; diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index 99916f523aa95..d2f7fdbbad04d 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -194,8 +194,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS, else if (const NestedNameSpecifier *NNS = get()) NNS->print(OS, PP); else if (const NestedNameSpecifierLoc *NNSL = get()) { - if (const NestedNameSpecifier *NNS = NNSL->getNestedNameSpecifier()) - NNS->print(OS, PP); + if (NestedNameSpecifier NNS = NNSL->getNestedNameSpecifier()) + NNS.print(OS, PP); else OS << "(empty NestedNameSpecifierLoc)"; } else if (const QualType *QT = get()) @@ -234,13 +234,39 @@ void DynTypedNode::dump(llvm::raw_ostream &OS, OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; } -SourceRange DynTypedNode::getSourceRange() const { +SourceRange DynTypedNode::getSourceRange(bool IncludeQualifier) const { if (const CXXCtorInitializer *CCI = get()) return CCI->getSourceRange(); if (const NestedNameSpecifierLoc *NNSL = get()) return NNSL->getSourceRange(); - if (const TypeLoc *TL = get()) - return TL->getSourceRange(); + if (const TypeLoc *TL = get()) { + if (IncludeQualifier) + return TL->getSourceRange(); + switch (TL->getTypeLocClass()) { + case TypeLoc::DependentName: + return TL->castAs().getNameLoc(); + case TypeLoc::TemplateSpecialization: { + auto T = TL->castAs(); + return SourceRange(T.getTemplateNameLoc(), T.getEndLoc()); + } + case TypeLoc::DependentTemplateSpecialization: { + auto T = TL->castAs(); + return SourceRange(T.getTemplateNameLoc(), T.getEndLoc()); + } + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + return TL->castAs().getNameLoc(); + case TypeLoc::Typedef: + return TL->castAs().getNameLoc(); + case TypeLoc::UnresolvedUsing: + return TL->castAs().getNameLoc(); + case TypeLoc::Using: + return TL->castAs().getNameLoc(); + default: + return TL->getSourceRange(); + } + } if (const Decl *D = get()) return D->getSourceRange(); if (const Stmt *S = get()) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index f656687f9fb1f..839e39f6c0c9a 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -553,9 +553,10 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) { // Possibly diagnose casts to enum types if the target type does not // have a fixed size. if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) { - if (const auto *ET = CE->getType().getCanonicalType()->castAs(); - !ET->getDecl()->isFixed()) { - if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE)) + const auto *ET = CE->getType().getCanonicalType()->castAs(); + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isFixed()) { + if (!this->emitCheckEnumValue(*FromT, ED, CE)) return false; } } @@ -4589,7 +4590,7 @@ const RecordType *Compiler::getRecordTy(QualType Ty) { template Record *Compiler::getRecord(QualType Ty) { if (const auto *RecordTy = getRecordTy(Ty)) - return getRecord(RecordTy->getDecl()); + return getRecord(RecordTy->getOriginalDecl()->getDefinitionOrSelf()); return nullptr; } diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp index f7f528c4e6484..43d30a1b5651d 100644 --- a/clang/lib/AST/ByteCode/Context.cpp +++ b/clang/lib/AST/ByteCode/Context.cpp @@ -365,7 +365,7 @@ OptPrimType Context::classify(QualType T) const { } if (const auto *ET = T->getAs()) { - const auto *D = ET->getDecl(); + const auto *D = ET->getOriginalDecl()->getDefinitionOrSelf(); if (!D->isComplete()) return std::nullopt; return classify(D->getIntegerType()); diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index c835bd4fb6088..addda44ac717a 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2754,7 +2754,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, const RecordType *RT = CurrentType->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); @@ -2787,7 +2787,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, const RecordType *RT = CurrentType->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); @@ -2799,7 +2799,8 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, return false; // Add the offset to the base. - Result += RL.getBaseClassOffset(cast(BaseRT->getDecl())); + Result += RL.getBaseClassOffset(cast( + BaseRT->getOriginalDecl()->getDefinitionOrSelf())); break; } case OffsetOfNode::Identifier: diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index febd2cba5b422..4d70ae5974d44 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -689,7 +689,7 @@ std::optional Pointer::toRValue(const Context &Ctx, assert(Record && "Missing record descriptor"); bool Ok = true; - if (RT->getDecl()->isUnion()) { + if (RT->getOriginalDecl()->isUnion()) { const FieldDecl *ActiveField = nullptr; APValue Value; for (const auto &F : Record->fields()) { diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 4daa4ab0d02f9..ee9e8f24522b6 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -325,7 +325,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { const auto *RT = Spec.getType()->getAs(); if (!RT) return nullptr; - const RecordDecl *BD = RT->getDecl(); + const RecordDecl *BD = RT->getOriginalDecl()->getDefinitionOrSelf(); const Record *BR = getOrCreateRecord(BD); const Descriptor *Desc = GetBaseDesc(BD, BR); @@ -342,7 +342,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { if (!RT) return nullptr; - const RecordDecl *BD = RT->getDecl(); + const RecordDecl *BD = RT->getOriginalDecl()->getDefinitionOrSelf(); const Record *BR = getOrCreateRecord(BD); const Descriptor *Desc = GetBaseDesc(BD, BR); @@ -399,7 +399,8 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, // Classes and structures. if (const auto *RT = Ty->getAs()) { - if (const auto *Record = getOrCreateRecord(RT->getDecl())) + if (const auto *Record = + getOrCreateRecord(RT->getOriginalDecl()->getDefinitionOrSelf())) return allocateDescriptor(D, Record, MDSize, IsConst, IsTemporary, IsMutable, IsVolatile); return allocateDescriptor(D, MDSize); diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp index 1d4ac7103cb76..a7934ccb4e55e 100644 --- a/clang/lib/AST/ByteCode/Record.cpp +++ b/clang/lib/AST/ByteCode/Record.cpp @@ -51,7 +51,7 @@ const Record::Base *Record::getBase(const RecordDecl *FD) const { const Record::Base *Record::getBase(QualType T) const { if (auto *RT = T->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); return BaseMap.lookup(RD); } return nullptr; diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index f0376168e43a2..e4b77edc063dc 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -132,8 +132,8 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const { if (!Ty) return false; - CXXRecordDecl *Base = - cast_if_present(Ty->getDecl()->getDefinition()); + CXXRecordDecl *Base = cast_if_present( + Ty->getOriginalDecl()->getDefinition()); if (!Base || (Base->isDependentContext() && !Base->isCurrentInstantiation(Record))) { @@ -256,7 +256,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, BaseSpec.getType()->getAs(); if (!TST) { if (auto *RT = BaseSpec.getType()->getAs()) - BaseRecord = cast(RT->getDecl()); + BaseRecord = cast(RT->getOriginalDecl()) + ->getDefinitionOrSelf(); } else { TemplateName TN = TST->getTemplateName(); if (auto *TD = @@ -336,7 +337,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, CXXRecordDecl *VBase = nullptr; if (const RecordType *Record = PE.Base->getType()->getAs()) - VBase = cast(Record->getDecl()); + VBase = cast(Record->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!VBase) break; @@ -348,7 +350,8 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback BaseMatches, CXXRecordDecl *HidingClass = nullptr; if (const RecordType *Record = HidingP.back().Base->getType()->getAs()) - HidingClass = cast(Record->getDecl()); + HidingClass = cast(Record->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!HidingClass) break; @@ -468,7 +471,8 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, for (const auto &Base : RD->bases()) { if (const RecordType *RT = Base.getType()->getAs()) { - const CXXRecordDecl *BaseDecl = cast(RT->getDecl()); + const CXXRecordDecl *BaseDecl = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (!BaseDecl->isPolymorphic()) continue; diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index b492df98e0ac8..e0cf0deb12bd2 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -500,9 +500,8 @@ ExprDependence clang::computeDependence(OMPIteratorExpr *E) { ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) { auto Deps = ExprDependence::None; - if (auto *NNS = E->getQualifier()) - Deps |= toExprDependence(NNS->getDependence() & - ~NestedNameSpecifierDependence::Dependent); + Deps |= toExprDependence(E->getQualifier().getDependence() & + ~NestedNameSpecifierDependence::Dependent); if (auto *FirstArg = E->getTemplateArgs()) { unsigned NumArgs = E->getNumTemplateArgs(); @@ -673,9 +672,8 @@ ExprDependence clang::computeDependence(MemberExpr *E) { auto D = E->getBase()->getDependence(); D |= getDependenceInExpr(E->getMemberNameInfo()); - if (auto *NNS = E->getQualifier()) - D |= toExprDependence(NNS->getDependence() & - ~NestedNameSpecifierDependence::Dependent); + D |= toExprDependence(E->getQualifier().getDependence() & + ~NestedNameSpecifierDependence::Dependent); for (const auto &A : E->template_arguments()) D |= toExprDependence(A.getArgument().getDependence()); @@ -783,9 +781,8 @@ ExprDependence clang::computeDependence(CXXPseudoDestructorExpr *E) { if (auto *ST = E->getScopeTypeInfo()) D |= turnTypeToValueDependence( toExprDependenceAsWritten(ST->getType()->getDependence())); - if (auto *Q = E->getQualifier()) - D |= toExprDependence(Q->getDependence() & - ~NestedNameSpecifierDependence::Dependent); + D |= toExprDependence(E->getQualifier().getDependence() & + ~NestedNameSpecifierDependence::Dependent); return D; } @@ -801,9 +798,8 @@ clang::computeDependence(OverloadExpr *E, bool KnownDependent, if (KnownContainsUnexpandedParameterPack) Deps |= ExprDependence::UnexpandedPack; Deps |= getDependenceInExpr(E->getNameInfo()); - if (auto *Q = E->getQualifier()) - Deps |= toExprDependence(Q->getDependence() & - ~NestedNameSpecifierDependence::Dependent); + Deps |= toExprDependence(E->getQualifier().getDependence() & + ~NestedNameSpecifierDependence::Dependent); for (auto *D : E->decls()) { if (D->getDeclContext()->isDependentContext() || isa(D) || isa(D)) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 7eafdc7572f23..12fe5516883eb 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1883,18 +1883,13 @@ bool NamedDecl::declarationReplaces(const NamedDecl *OldD, // Using declarations can be replaced if they import the same name from the // same context. - if (const auto *UD = dyn_cast(this)) { - ASTContext &Context = getASTContext(); - return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) == - Context.getCanonicalNestedNameSpecifier( - cast(OldD)->getQualifier()); - } - if (const auto *UUVD = dyn_cast(this)) { - ASTContext &Context = getASTContext(); - return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) == - Context.getCanonicalNestedNameSpecifier( - cast(OldD)->getQualifier()); - } + if (const auto *UD = dyn_cast(this)) + return UD->getQualifier().getCanonical() == + + cast(OldD)->getQualifier().getCanonical(); + if (const auto *UUVD = dyn_cast(this)) + return UUVD->getQualifier().getCanonical() == + cast(OldD)->getQualifier().getCanonical(); if (isRedeclarable(getKind())) { if (getCanonicalDecl() != OldD->getCanonicalDecl()) @@ -2864,7 +2859,8 @@ VarDecl::needsDestruction(const ASTContext &Ctx) const { bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { assert(hasInit() && "Expect initializer to check for flexible array init"); auto *Ty = getType()->getAs(); - if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + if (!Ty || + !Ty->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return false; auto *List = dyn_cast(getInit()->IgnoreParens()); if (!List) @@ -2879,7 +2875,10 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { assert(hasInit() && "Expect initializer to check for flexible array init"); auto *Ty = getType()->getAs(); - if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember()) + if (!Ty) + return CharUnits::Zero(); + const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + if (!Ty || !RD->hasFlexibleArrayMember()) return CharUnits::Zero(); auto *List = dyn_cast(getInit()->IgnoreParens()); if (!List || List->getNumInits() == 0) @@ -2991,7 +2990,10 @@ bool ParmVarDecl::isDestroyedInCallee() const { // FIXME: isParamDestroyedInCallee() should probably imply // isDestructedType() const auto *RT = getType()->getAs(); - if (RT && RT->getDecl()->isParamDestroyedInCallee() && + if (RT && + RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->isParamDestroyedInCallee() && getType().isDestructedType()) return true; @@ -3502,7 +3504,7 @@ bool FunctionDecl::isUsableAsGlobalAllocationFunctionInConstantEvaluation( while (const auto *TD = T->getAs()) T = TD->getDecl()->getUnderlyingType(); const IdentifierInfo *II = - T->castAs()->getDecl()->getIdentifier(); + T->castAs()->getOriginalDecl()->getIdentifier(); if (II && II->isStr("__hot_cold_t")) Consume(); } @@ -4653,7 +4655,7 @@ bool FieldDecl::isAnonymousStructOrUnion() const { return false; if (const auto *Record = getType()->getAs()) - return Record->getDecl()->isAnonymousStructOrUnion(); + return Record->getOriginalDecl()->isAnonymousStructOrUnion(); return false; } @@ -4713,7 +4715,7 @@ bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { const auto *RT = getType()->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl()->getDefinition(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); if (!RD) { assert(isInvalidDecl() && "valid field has incomplete type"); return false; @@ -5138,7 +5140,7 @@ bool RecordDecl::isOrContainsUnion() const { if (const RecordDecl *Def = getDefinition()) { for (const FieldDecl *FD : Def->fields()) { const RecordType *RT = FD->getType()->getAs(); - if (RT && RT->getDecl()->isOrContainsUnion()) + if (RT && RT->getOriginalDecl()->isOrContainsUnion()) return true; } } @@ -5270,8 +5272,9 @@ const FieldDecl *RecordDecl::findFirstNamedDataMember() const { return I; if (const auto *RT = I->getType()->getAs()) - if (const FieldDecl *NamedDataMember = - RT->getDecl()->findFirstNamedDataMember()) + if (const FieldDecl *NamedDataMember = RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->findFirstNamedDataMember()) return NamedDataMember; } @@ -5633,14 +5636,14 @@ void TypedefNameDecl::anchor() {} TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { if (auto *TT = getTypeSourceInfo()->getType()->getAs()) { - auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl(); + auto *OwningTypedef = TT->getOriginalDecl()->getTypedefNameForAnonDecl(); auto *ThisTypedef = this; if (AnyRedecl && OwningTypedef) { OwningTypedef = OwningTypedef->getCanonicalDecl(); ThisTypedef = ThisTypedef->getCanonicalDecl(); } if (OwningTypedef == ThisTypedef) - return TT->getDecl(); + return TT->getOriginalDecl()->getDefinitionOrSelf(); } return nullptr; @@ -5649,7 +5652,7 @@ TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { bool TypedefNameDecl::isTransparentTagSlow() const { auto determineIsTransparent = [&]() { if (auto *TT = getUnderlyingType()->getAs()) { - if (auto *TD = TT->getDecl()) { + if (auto *TD = TT->getOriginalDecl()) { if (TD->getName() != getName()) return false; SourceLocation TTLoc = getLocation(); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 174c18d3724d2..50b1a1d000090 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -217,7 +217,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (BaseType->isDependentType()) continue; auto *BaseClassDecl = - cast(BaseType->castAs()->getDecl()); + cast(BaseType->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // C++2a [class]p7: // A standard-layout class is a class that: @@ -1207,7 +1208,7 @@ void CXXRecordDecl::addedMember(Decl *D) { bool IsZeroSize = Field->isZeroSize(Context); if (const auto *RecordTy = T->getAs()) { - auto *FieldRec = cast(RecordTy->getDecl()); + auto *FieldRec = cast(RecordTy->getOriginalDecl()); if (FieldRec->getDefinition()) { addedClassSubobject(FieldRec); @@ -1914,7 +1915,8 @@ static void CollectVisibleConversions( = CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier()); bool BaseInVirtual = InVirtual || I.isVirtual(); - auto *Base = cast(RT->getDecl()); + auto *Base = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess, *HiddenTypes, Output, VOutput, HiddenVBaseCs); } @@ -1952,9 +1954,11 @@ static void CollectVisibleConversions(ASTContext &Context, const auto *RT = I.getType()->getAs(); if (!RT) continue; - CollectVisibleConversions(Context, cast(RT->getDecl()), - I.isVirtual(), I.getAccessSpecifier(), - HiddenTypes, Output, VBaseCs, HiddenVBaseCs); + CollectVisibleConversions( + Context, + cast(RT->getOriginalDecl())->getDefinitionOrSelf(), + I.isVirtual(), I.getAccessSpecifier(), HiddenTypes, Output, VBaseCs, + HiddenVBaseCs); } // Add any unhidden conversions provided by virtual bases. @@ -2307,8 +2311,8 @@ bool CXXRecordDecl::mayBeAbstract() const { return false; for (const auto &B : bases()) { - const auto *BaseDecl = - cast(B.getType()->castAs()->getDecl()); + const auto *BaseDecl = cast( + B.getType()->castAs()->getOriginalDecl()); if (BaseDecl->isAbstract()) return true; } @@ -2471,7 +2475,8 @@ CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD, const RecordType *RT = I.getType()->getAs(); if (!RT) continue; - const auto *Base = cast(RT->getDecl()); + const auto *Base = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (CXXMethodDecl *D = this->getCorrespondingMethodInClass(Base)) AddFinalOverrider(D); } diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index dc4457b4e449b..196057f7b45a4 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -708,11 +708,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto += D->getQualifiedNameAsString(); } else { llvm::raw_string_ostream OS(Proto); - if (!Policy.SuppressScope) { - if (const NestedNameSpecifier *NS = D->getQualifier()) { - NS->print(OS, Policy); - } - } + if (!Policy.SuppressScope) + D->getQualifier().print(OS, Policy); D->getNameInfo().printName(OS, Policy); } diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp index ae5fcf6e86adf..6c7b995d57567 100644 --- a/clang/lib/AST/DeclarationName.cpp +++ b/clang/lib/AST/DeclarationName.cpp @@ -115,12 +115,12 @@ static void printCXXConstructorDestructorName(QualType ClassType, Policy.adjustForCPlusPlus(); if (const RecordType *ClassRec = ClassType->getAs()) { - ClassRec->getDecl()->printName(OS, Policy); + ClassRec->getOriginalDecl()->printName(OS, Policy); return; } if (Policy.SuppressTemplateArgsInCXXConstructors) { if (auto *InjTy = ClassType->getAs()) { - InjTy->getDecl()->printName(OS, Policy); + InjTy->getOriginalDecl()->printName(OS, Policy); return; } } @@ -184,7 +184,7 @@ void DeclarationName::print(raw_ostream &OS, OS << "operator "; QualType Type = getCXXNameType(); if (const RecordType *Rec = Type->getAs()) { - OS << *Rec->getDecl(); + OS << *Rec->getOriginalDecl(); return; } // We know we're printing C++ here, ensure we print 'bool' properly. diff --git a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp index f5c42b8fec1bc..8821cd332e918 100644 --- a/clang/lib/AST/DynamicRecursiveASTVisitor.cpp +++ b/clang/lib/AST/DynamicRecursiveASTVisitor.cpp @@ -176,7 +176,7 @@ template struct Impl : RecursiveASTVisitor> { return Visitor.TraverseLambdaCapture(LE, C, Init); } - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { + bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) { return Visitor.TraverseNestedNameSpecifier(NNS); } @@ -301,7 +301,6 @@ FORWARD_TO_BASE(TraverseAttr, Attr, *) FORWARD_TO_BASE(TraverseConstructorInitializer, CXXCtorInitializer, *) FORWARD_TO_BASE(TraverseDecl, Decl, *) FORWARD_TO_BASE(TraverseStmt, Stmt, *) -FORWARD_TO_BASE(TraverseNestedNameSpecifier, NestedNameSpecifier, *) FORWARD_TO_BASE(TraverseTemplateInstantiations, ClassTemplateDecl, *) FORWARD_TO_BASE(TraverseTemplateInstantiations, VarTemplateDecl, *) FORWARD_TO_BASE(TraverseTemplateInstantiations, FunctionTemplateDecl, *) @@ -318,8 +317,22 @@ FORWARD_TO_BASE_EXACT(TraverseTemplateArgument, const TemplateArgument &) FORWARD_TO_BASE_EXACT(TraverseTemplateArguments, ArrayRef) FORWARD_TO_BASE_EXACT(TraverseTemplateArgumentLoc, const TemplateArgumentLoc &) FORWARD_TO_BASE_EXACT(TraverseTemplateName, TemplateName) -FORWARD_TO_BASE_EXACT(TraverseType, QualType) -FORWARD_TO_BASE_EXACT(TraverseTypeLoc, TypeLoc) +FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifier, NestedNameSpecifier) + +template +bool DynamicRecursiveASTVisitorBase::TraverseType( + QualType T, bool TraverseQualifier) { + return Impl(*this).RecursiveASTVisitor>::TraverseType( + T, TraverseQualifier); +} + +template +bool DynamicRecursiveASTVisitorBase::TraverseTypeLoc( + TypeLoc TL, bool TraverseQualifier) { + return Impl(*this).RecursiveASTVisitor>::TraverseTypeLoc( + TL, TraverseQualifier); +} + FORWARD_TO_BASE_EXACT(TraverseTypeConstraint, const TypeConstraint *) FORWARD_TO_BASE_EXACT(TraverseObjCProtocolLoc, ObjCProtocolLoc) FORWARD_TO_BASE_EXACT(TraverseNestedNameSpecifierLoc, NestedNameSpecifierLoc) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 5bccce27c7dda..7cac655ef151c 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -75,8 +75,7 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const { return nullptr; const RecordType *Ty = DerivedType->castAs(); - Decl *D = Ty->getDecl(); - return cast(D); + return cast(Ty->getOriginalDecl())->getDefinitionOrSelf(); } const Expr *Expr::skipRValueSubobjectAdjustments( @@ -92,7 +91,9 @@ const Expr *Expr::skipRValueSubobjectAdjustments( E->getType()->isRecordType()) { E = CE->getSubExpr(); const auto *Derived = - cast(E->getType()->castAs()->getDecl()); + cast( + E->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); Adjustments.push_back(SubobjectAdjustment(CE, Derived)); continue; } @@ -2031,7 +2032,8 @@ CXXBaseSpecifier **CastExpr::path_buffer() { const FieldDecl *CastExpr::getTargetFieldForToUnionCast(QualType unionType, QualType opType) { - auto RD = unionType->castAs()->getDecl(); + auto RD = + unionType->castAs()->getOriginalDecl()->getDefinitionOrSelf(); return getTargetFieldForToUnionCast(RD, opType); } @@ -3407,7 +3409,10 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; - RecordDecl *RD = ILE->getType()->castAs()->getDecl(); + RecordDecl *RD = ILE->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); // In C++17, bases were added to the list of members used by aggregate // initialization. @@ -4050,8 +4055,10 @@ Expr::isNullPointerConstant(ASTContext &Ctx, return NPCK_CXX11_nullptr; if (const RecordType *UT = getType()->getAsUnionType()) - if (!Ctx.getLangOpts().CPlusPlus11 && - UT && UT->getDecl()->hasAttr()) + if (!Ctx.getLangOpts().CPlusPlus11 && UT && + UT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr()) if (const CompoundLiteralExpr *CLE = dyn_cast(this)){ const Expr *InitExpr = CLE->getInitializer(); if (const InitListExpr *ILE = dyn_cast(InitExpr)) diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 74ce7fb5c7164..97ae4a07f32aa 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1687,10 +1687,9 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() { // It can't be dependent: after all, we were actually able to do the // lookup. CXXRecordDecl *Record = nullptr; - auto *NNS = getQualifier(); - if (NNS && NNS->getKind() != NestedNameSpecifier::Super) { - const Type *T = getQualifier()->getAsType(); - assert(T && "qualifier in member expression does not name type"); + if (NestedNameSpecifier Qualifier = getQualifier(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Type) { + const Type *T = getQualifier().getAsType(); Record = T->getAsCXXRecordDecl(); assert(Record && "qualifier in member expression does not name record"); } diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp index ac0e566fe6e72..36f910da49bfb 100644 --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -41,10 +41,10 @@ ConceptSpecializationExpr::ConceptSpecializationExpr( assert(!Loc->getNestedNameSpecifierLoc() || (!Loc->getNestedNameSpecifierLoc() .getNestedNameSpecifier() - ->isInstantiationDependent() && + .isInstantiationDependent() && !Loc->getNestedNameSpecifierLoc() .getNestedNameSpecifier() - ->containsUnexpandedParameterPack())); + .containsUnexpandedParameterPack())); assert((!isValueDependent() || isInstantiationDependent()) && "should not be value-dependent"); } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index aa16ad41ba2e1..5cf2b9a0355ab 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2623,7 +2623,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, Value.getUnionValue(), Kind, Value.getUnionField(), CheckedTemps); } if (Value.isStruct()) { - RecordDecl *RD = Type->castAs()->getDecl(); + RecordDecl *RD = + Type->castAs()->getOriginalDecl()->getDefinitionOrSelf(); if (const CXXRecordDecl *CD = dyn_cast(RD)) { unsigned BaseIndex = 0; for (const CXXBaseSpecifier &BS : CD->bases()) { @@ -4109,7 +4110,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, } // Next subobject is a class, struct or union field. - RecordDecl *RD = ObjType->castAs()->getDecl(); + RecordDecl *RD = ObjType->castAs()->getOriginalDecl(); if (RD->isUnion()) { const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || @@ -7794,7 +7795,8 @@ class BufferToAPValueConverter { } std::optional visit(const EnumType *Ty, CharUnits Offset) { - QualType RepresentationType = Ty->getDecl()->getIntegerType(); + QualType RepresentationType = + Ty->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); assert(!RepresentationType.isNull() && "enum forward decl should be caught by Sema"); const auto *AsBuiltin = @@ -8589,8 +8591,10 @@ class ExprEvaluatorBase const FieldDecl *FD = dyn_cast(E->getMemberDecl()); if (!FD) return Error(E); assert(!FD->getType()->isReferenceType() && "prvalue reference?"); - assert(BaseTy->castAs()->getDecl()->getCanonicalDecl() == - FD->getParent()->getCanonicalDecl() && "record / field mismatch"); + assert( + BaseTy->castAs()->getOriginalDecl()->getCanonicalDecl() == + FD->getParent()->getCanonicalDecl() && + "record / field mismatch"); // Note: there is no lvalue base here. But this case should only ever // happen in C or in C++98, where we cannot be evaluating a constexpr @@ -8817,8 +8821,10 @@ class LValueExprEvaluatorBase const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast(E->getMemberDecl())) { - assert(BaseTy->castAs()->getDecl()->getCanonicalDecl() == - FD->getParent()->getCanonicalDecl() && "record / field mismatch"); + assert( + BaseTy->castAs()->getOriginalDecl()->getCanonicalDecl() == + FD->getParent()->getCanonicalDecl() && + "record / field mismatch"); (void)BaseTy; if (!HandleLValueMember(this->Info, E, Result, FD)) return false; @@ -10818,7 +10824,8 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, } bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) { - const RecordDecl *RD = T->castAs()->getDecl(); + const RecordDecl *RD = + T->castAs()->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; if (RD->isUnion()) { // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the @@ -10887,8 +10894,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) { bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr( const Expr *ExprToVisit, ArrayRef Args) { - const RecordDecl *RD = - ExprToVisit->getType()->castAs()->getDecl(); + const RecordDecl *RD = ExprToVisit->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(RD); auto *CXXRD = dyn_cast(RD); @@ -11116,7 +11125,10 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( Result = APValue(APValue::UninitStruct(), 0, 2); Array.moveInto(Result.getStructField(0)); - RecordDecl *Record = E->getType()->castAs()->getDecl(); + RecordDecl *Record = E->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); RecordDecl::field_iterator Field = Record->field_begin(); assert(Field != Record->field_end() && Info.Ctx.hasSameType(Field->getType()->getPointeeType(), @@ -12907,7 +12919,10 @@ static bool convertUnsignedAPIntToCharUnits(const llvm::APInt &Int, static void addFlexibleArrayMemberInitSize(EvalInfo &Info, const QualType &T, const LValue &LV, CharUnits &Size) { if (!T.isNull() && T->isStructureType() && - T->getAsStructureType()->getDecl()->hasFlexibleArrayMember()) + T->getAsStructureType() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) if (const auto *V = LV.getLValueBase().dyn_cast()) if (const auto *VD = dyn_cast(V)) if (VD->hasInit()) @@ -15154,7 +15169,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); - RecordDecl *RD = RT->getDecl(); + RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); unsigned i = MemberDecl->getFieldIndex(); @@ -15176,7 +15191,7 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { const RecordType *RT = CurrentType->getAs(); if (!RT) return Error(OOE); - RecordDecl *RD = RT->getDecl(); + RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isInvalidDecl()) return false; const ASTRecordLayout &RL = Info.Ctx.getASTRecordLayout(RD); @@ -15187,7 +15202,8 @@ bool IntExprEvaluator::VisitOffsetOfExpr(const OffsetOfExpr *OOE) { return Error(OOE); // Add the offset to the base. - Result += RL.getBaseClassOffset(cast(BaseRT->getDecl())); + Result += RL.getBaseClassOffset(cast( + BaseRT->getOriginalDecl()->getDefinitionOrSelf())); break; } } @@ -15366,7 +15382,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { if (Info.Ctx.getLangOpts().CPlusPlus && DestType->isEnumeralType()) { const EnumType *ET = dyn_cast(DestType.getCanonicalType()); - const EnumDecl *ED = ET->getDecl(); + const EnumDecl *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); // Check that the value is within the range of the enumeration values. // // This corressponds to [expr.static.cast]p10 which says: diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 112b756d2be1a..502a3e6b145e3 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -417,10 +417,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { // If the enum is incomplete we know nothing about the underlying type. // Assume that it's 'int'. Do not use the underlying type for a scoped // enumeration. - if (!ETy->getDecl()->isComplete()) + const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) return NoMatch; if (ETy->isUnscopedEnumerationType()) - argTy = ETy->getDecl()->getIntegerType(); + argTy = ED->getIntegerType(); } if (const auto *BT = argTy->getAs()) { @@ -466,10 +467,11 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { // If the enum is incomplete we know nothing about the underlying type. // Assume that it's 'int'. Do not use the underlying type for a scoped // enumeration as that needs an exact match. - if (!ETy->getDecl()->isComplete()) + const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) argTy = C.IntTy; else if (ETy->isUnscopedEnumerationType()) - argTy = ETy->getDecl()->getIntegerType(); + argTy = ED->getIntegerType(); } if (argTy->isSaturatedFixedPointType()) diff --git a/clang/lib/AST/InheritViz.cpp b/clang/lib/AST/InheritViz.cpp index 822fbc2ca78e8..c03492c64b161 100644 --- a/clang/lib/AST/InheritViz.cpp +++ b/clang/lib/AST/InheritViz.cpp @@ -89,8 +89,8 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { Out << " \"];\n"; // Display the base classes. - const auto *Decl = - static_cast(Type->castAs()->getDecl()); + const auto *Decl = static_cast( + Type->castAs()->getOriginalDecl()); for (const auto &Base : Decl->bases()) { QualType CanonBaseType = Context.getCanonicalType(Base.getType()); diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 6ceedd657fe7e..43a8bcd9443ff 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -42,10 +42,10 @@ namespace { /// /// Returns the name of anonymous union VarDecl or nullptr if it is not found. static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) { - const RecordType *RT = VD.getType()->getAs(); - assert(RT && "type of VarDecl is expected to be RecordType."); - assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union."); - if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) { + const auto *RT = VD.getType()->castAs(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + assert(RD->isUnion() && "RecordType is expected to be a union."); + if (const FieldDecl *FD = RD->findFirstNamedDataMember()) { return FD->getIdentifier(); } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index f75ed4fc9b094..a7380a19e3607 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -463,9 +463,7 @@ class CXXNameMangler { void mangleVendorType(StringRef Name); private: - bool mangleSubstitution(const NamedDecl *ND); - bool mangleSubstitution(NestedNameSpecifier *NNS); bool mangleSubstitution(QualType T); bool mangleSubstitution(TemplateName Template); bool mangleSubstitution(uintptr_t Ptr); @@ -479,21 +477,15 @@ class CXXNameMangler { addSubstitution(reinterpret_cast(ND)); } - void addSubstitution(NestedNameSpecifier *NNS) { - NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); - - addSubstitution(reinterpret_cast(NNS)); - } void addSubstitution(QualType T); void addSubstitution(TemplateName Template); void addSubstitution(uintptr_t Ptr); // Destructive copy substitutions from other mangler. void extendSubstitutions(CXXNameMangler* Other); - void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, + void mangleUnresolvedPrefix(NestedNameSpecifier Qualifier, bool recursive = false); - void mangleUnresolvedName(NestedNameSpecifier *qualifier, - DeclarationName name, + void mangleUnresolvedName(NestedNameSpecifier Qualifier, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, unsigned KnownArity = UnknownArity); @@ -542,7 +534,7 @@ class CXXNameMangler { void mangleNestedNameWithClosurePrefix(GlobalDecl GD, const NamedDecl *PrefixND, const AbiTagList *AdditionalAbiTags); - void manglePrefix(NestedNameSpecifier *qualifier); + void manglePrefix(NestedNameSpecifier Qualifier); void manglePrefix(const DeclContext *DC, bool NoFunction=false); void manglePrefix(QualType type); void mangleTemplatePrefix(GlobalDecl GD, bool NoFunction=false); @@ -588,12 +580,10 @@ class CXXNameMangler { void mangleMemberExprBase(const Expr *base, bool isArrow); void mangleMemberExpr(const Expr *base, bool isArrow, - NestedNameSpecifier *qualifier, - NamedDecl *firstQualifierLookup, - DeclarationName name, + NestedNameSpecifier Qualifier, + NamedDecl *firstQualifierLookup, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - unsigned knownArity); + unsigned NumTemplateArgs, unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); void mangleRequirement(SourceLocation RequiresExprLoc, @@ -1360,7 +1350,7 @@ void CXXNameMangler::manglePrefix(QualType type) { /// /// \param recursive - true if this is being called recursively, /// i.e. if there is more prefix "to the right". -void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, +void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier Qualifier, bool recursive) { // x, ::x @@ -1377,8 +1367,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // ::= [gs] sr + E // - switch (qualifier->getKind()) { - case NestedNameSpecifier::Global: + switch (Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); + + case NestedNameSpecifier::Kind::Global: Out << "gs"; // We want an 'sr' unless this is the entire NNS. @@ -1388,27 +1381,29 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, // We never want an 'E' here. return; - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::MicrosoftSuper: llvm_unreachable("Can't mangle __super specifier"); - case NestedNameSpecifier::Namespace: - if (qualifier->getPrefix()) - mangleUnresolvedPrefix(qualifier->getPrefix(), + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = Qualifier.getAsNamespaceAndPrefix(); + if (Prefix) + mangleUnresolvedPrefix(Prefix, /*recursive*/ true); else Out << "sr"; - mangleSourceNameWithAbiTags(qualifier->getAsNamespace()); + mangleSourceNameWithAbiTags(Namespace); break; + } - case NestedNameSpecifier::TypeSpec: { - const Type *type = qualifier->getAsType(); + case NestedNameSpecifier::Kind::Type: { + const Type *type = Qualifier.getAsType(); // We only want to use an unresolved-type encoding if this is one of: // - a decltype // - a template type parameter // - a template template parameter with arguments // In all of these cases, we should have no prefix. - if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) { + if (NestedNameSpecifier Prefix = type->getPrefix()) { mangleUnresolvedPrefix(Prefix, /*recursive=*/true); } else { @@ -1421,18 +1416,6 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, break; } - - case NestedNameSpecifier::Identifier: - // Member expressions can have these without prefixes. - if (qualifier->getPrefix()) - mangleUnresolvedPrefix(qualifier->getPrefix(), - /*recursive*/ true); - else - Out << "sr"; - - mangleSourceName(qualifier->getAsIdentifier()); - // An Identifier has no type information, so we can't emit abi tags for it. - break; } // If this was the innermost part of the NNS, and we fell out to @@ -1444,10 +1427,11 @@ void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier, /// Mangle an unresolved-name, which is generally used for names which /// weren't resolved to specific entities. void CXXNameMangler::mangleUnresolvedName( - NestedNameSpecifier *qualifier, DeclarationName name, + NestedNameSpecifier Qualifier, DeclarationName name, const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, unsigned knownArity) { - if (qualifier) mangleUnresolvedPrefix(qualifier); + if (Qualifier) + mangleUnresolvedPrefix(Qualifier); switch (name.getNameKind()) { // ::= case DeclarationName::Identifier: @@ -1596,7 +1580,10 @@ void CXXNameMangler::mangleUnqualifiedName( if (const VarDecl *VD = dyn_cast(ND)) { // We must have an anonymous union or struct declaration. - const RecordDecl *RD = VD->getType()->castAs()->getDecl(); + const RecordDecl *RD = VD->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); // Itanium C++ ABI 5.1.2: // @@ -2182,49 +2169,22 @@ void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) { Lambda->getLambdaStaticInvoker()); } -void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) { - switch (qualifier->getKind()) { - case NestedNameSpecifier::Global: +void CXXNameMangler::manglePrefix(NestedNameSpecifier Qualifier) { + switch (Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: // nothing return; - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::MicrosoftSuper: llvm_unreachable("Can't mangle __super specifier"); - case NestedNameSpecifier::Namespace: - mangleName(qualifier->getAsNamespace()->getNamespace()); - return; - - case NestedNameSpecifier::TypeSpec: - if (NestedNameSpecifier *Prefix = qualifier->getPrefix()) { - const auto *DTST = - cast(qualifier->getAsType()); - QualType NewT = getASTContext().getDependentTemplateSpecializationType( - DTST->getKeyword(), - {Prefix, DTST->getDependentTemplateName().getName(), - /*HasTemplateKeyword=*/true}, - DTST->template_arguments(), /*IsCanonical=*/true); - manglePrefix(NewT); - return; - } - manglePrefix(QualType(qualifier->getAsType(), 0)); + case NestedNameSpecifier::Kind::Namespace: + mangleName(Qualifier.getAsNamespaceAndPrefix().Namespace->getNamespace()); return; - case NestedNameSpecifier::Identifier: - // Clang 14 and before did not consider this substitutable. - bool Clang14Compat = isCompatibleWith(LangOptions::ClangABI::Ver14); - if (!Clang14Compat && mangleSubstitution(qualifier)) - return; - - // Member expressions can have these without prefixes, but that - // should end up in mangleUnresolvedPrefix instead. - assert(qualifier->getPrefix()); - manglePrefix(qualifier->getPrefix()); - - mangleSourceName(qualifier->getAsIdentifier()); - - if (!Clang14Compat) - addSubstitution(qualifier); + case NestedNameSpecifier::Kind::Type: + manglePrefix(QualType(Qualifier.getAsType(), 0)); return; } @@ -2284,8 +2244,7 @@ void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { if (!Clang11Compat && mangleSubstitution(Template)) return; - if (NestedNameSpecifier *Qualifier = Dependent->getQualifier()) - manglePrefix(Qualifier); + manglePrefix(Dependent->getQualifier()); if (Clang11Compat && mangleSubstitution(Template)) return; @@ -2540,7 +2499,8 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Enum: case Type::Record: - mangleSourceNameWithAbiTags(cast(Ty)->getDecl()); + mangleSourceNameWithAbiTags( + cast(Ty)->getOriginalDecl()->getDefinitionOrSelf()); break; case Type::TemplateSpecialization: { @@ -2601,8 +2561,9 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, } case Type::InjectedClassName: - mangleSourceNameWithAbiTags( - cast(Ty)->getDecl()); + mangleSourceNameWithAbiTags(cast(Ty) + ->getOriginalDecl() + ->getDefinitionOrSelf()); break; case Type::DependentName: @@ -3850,7 +3811,7 @@ void CXXNameMangler::mangleType(const RecordType *T) { mangleType(static_cast(T)); } void CXXNameMangler::mangleType(const TagType *T) { - mangleName(T->getDecl()); + mangleName(T->getOriginalDecl()->getDefinitionOrSelf()); } // ::= @@ -3887,16 +3848,10 @@ void CXXNameMangler::mangleType(const IncompleteArrayType *T) { // ::= M void CXXNameMangler::mangleType(const MemberPointerType *T) { Out << 'M'; - if (auto *RD = T->getMostRecentCXXRecordDecl()) { + if (auto *RD = T->getMostRecentCXXRecordDecl()) mangleCXXRecordDecl(RD); - } else { - NestedNameSpecifier *NNS = T->getQualifier(); - if (auto *II = NNS->getAsIdentifier()) - mangleType(getASTContext().getDependentNameType( - ElaboratedTypeKeyword::None, NNS->getPrefix(), II)); - else - manglePrefix(NNS); - } + else + mangleType(QualType(T->getQualifier().getAsType(), 0)); QualType PointeeType = T->getPointeeType(); if (const FunctionProtoType *FPT = dyn_cast(PointeeType)) { mangleType(FPT); @@ -4483,7 +4438,8 @@ void CXXNameMangler::mangleType(const InjectedClassNameType *T) { // Mangle injected class name types as if the user had written the // specialization out fully. It may not actually be possible to see // this mangling, though. - mangleType(T->getCanonicalInjectedTST()); + mangleType(T->getOriginalDecl()->getCanonicalTemplateSpecializationType( + getASTContext())); } void CXXNameMangler::mangleType(const TemplateSpecializationType *T) { @@ -4759,7 +4715,7 @@ void CXXNameMangler::mangleIntegerLiteral(QualType T, void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) { // Ignore member expressions involving anonymous unions. while (const auto *RT = Base->getType()->getAs()) { - if (!RT->getDecl()->isAnonymousStructOrUnion()) + if (!RT->getOriginalDecl()->isAnonymousStructOrUnion()) break; const auto *ME = dyn_cast(Base); if (!ME) @@ -4780,9 +4736,8 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) { } /// Mangles a member expression. -void CXXNameMangler::mangleMemberExpr(const Expr *base, - bool isArrow, - NestedNameSpecifier *qualifier, +void CXXNameMangler::mangleMemberExpr(const Expr *base, bool isArrow, + NestedNameSpecifier Qualifier, NamedDecl *firstQualifierLookup, DeclarationName member, const TemplateArgumentLoc *TemplateArgs, @@ -5242,7 +5197,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, const auto *PDE = cast(E); if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); - NestedNameSpecifier *Qualifier = PDE->getQualifier(); + NestedNameSpecifier Qualifier = PDE->getQualifier(); if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { if (Qualifier) { mangleUnresolvedPrefix(Qualifier, @@ -7018,14 +6973,6 @@ bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) { return mangleSubstitution(reinterpret_cast(ND)); } -bool CXXNameMangler::mangleSubstitution(NestedNameSpecifier *NNS) { - assert(NNS->getKind() == NestedNameSpecifier::Identifier && - "mangleSubstitution(NestedNameSpecifier *) is only used for " - "identifier nested name specifiers."); - NNS = Context.getASTContext().getCanonicalNestedNameSpecifier(NNS); - return mangleSubstitution(reinterpret_cast(NNS)); -} - /// Determine whether the given type has any qualifiers that are relevant for /// substitutions. static bool hasMangledSubstitutionQualifiers(QualType T) { @@ -7036,7 +6983,7 @@ static bool hasMangledSubstitutionQualifiers(QualType T) { bool CXXNameMangler::mangleSubstitution(QualType T) { if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs()) - return mangleSubstitution(RT->getDecl()); + return mangleSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf()); } uintptr_t TypePtr = reinterpret_cast(T.getAsOpaquePtr()); @@ -7077,7 +7024,7 @@ bool CXXNameMangler::isSpecializedAs(QualType S, llvm::StringRef Name, return false; const ClassTemplateSpecializationDecl *SD = - dyn_cast(RT->getDecl()); + dyn_cast(RT->getOriginalDecl()); if (!SD || !SD->getIdentifier()->isStr(Name)) return false; @@ -7207,7 +7154,7 @@ bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { void CXXNameMangler::addSubstitution(QualType T) { if (!hasMangledSubstitutionQualifiers(T)) { if (const RecordType *RT = T->getAs()) { - addSubstitution(RT->getDecl()); + addSubstitution(RT->getOriginalDecl()->getDefinitionOrSelf()); return; } } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index fdbd4479bb995..b3f12a1cce2ec 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -395,8 +395,8 @@ llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { const CXXBaseSpecifier *Base = *I; - const auto *RD = - cast(Base->getType()->castAs()->getDecl()); + const auto *RD = cast( + Base->getType()->castAs()->getOriginalDecl()); llvm::json::Object Val{{"name", RD->getName()}}; if (Base->isVirtual()) @@ -816,7 +816,7 @@ void JSONNodeDumper::VisitTemplateSpecializationType( void JSONNodeDumper::VisitInjectedClassNameType( const InjectedClassNameType *ICNT) { - JOS.attribute("decl", createBareDeclRef(ICNT->getDecl())); + JOS.attribute("decl", createBareDeclRef(ICNT->getOriginalDecl())); } void JSONNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { @@ -898,9 +898,9 @@ void JSONNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD) { void JSONNodeDumper::VisitUsingDecl(const UsingDecl *UD) { std::string Name; - if (const NestedNameSpecifier *NNS = UD->getQualifier()) { + if (NestedNameSpecifier Qualifier = UD->getQualifier()) { llvm::raw_string_ostream SOS(Name); - NNS->print(SOS, UD->getASTContext().getPrintingPolicy()); + Qualifier.print(SOS, UD->getASTContext().getPrintingPolicy()); } Name += UD->getNameAsString(); JOS.attribute("name", Name); diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index a78bf24792d23..241c7c35fcc83 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -3246,11 +3246,11 @@ void MicrosoftCXXNameMangler::mangleTagTypeKind(TagTypeKind TTK) { } void MicrosoftCXXNameMangler::mangleType(const EnumType *T, Qualifiers, SourceRange) { - mangleType(cast(T)->getDecl()); + mangleType(cast(T)->getOriginalDecl()->getDefinitionOrSelf()); } void MicrosoftCXXNameMangler::mangleType(const RecordType *T, Qualifiers, SourceRange) { - mangleType(cast(T)->getDecl()); + mangleType(cast(T)->getOriginalDecl()->getDefinitionOrSelf()); } void MicrosoftCXXNameMangler::mangleType(const TagDecl *TD) { mangleTagTypeKind(TD->getTagKind()); diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp index 872983f553e19..c6af91f5c0083 100644 --- a/clang/lib/AST/NestedNameSpecifier.cpp +++ b/clang/lib/AST/NestedNameSpecifier.cpp @@ -34,250 +34,67 @@ using namespace clang; -NestedNameSpecifier * -NestedNameSpecifier::FindOrInsert(const ASTContext &Context, - const NestedNameSpecifier &Mockup) { +const NamespaceAndPrefixStorage * +NestedNameSpecifier::MakeNamespaceAndPrefixStorage( + const ASTContext &Ctx, const NamespaceBaseDecl *Namespace, + NestedNameSpecifier Prefix) { llvm::FoldingSetNodeID ID; - Mockup.Profile(ID); + NamespaceAndPrefixStorage::Profile(ID, Namespace, Prefix); void *InsertPos = nullptr; - NestedNameSpecifier *NNS - = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); - if (!NNS) { - NNS = - new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup); - Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); + NamespaceAndPrefixStorage *S = + Ctx.NamespaceAndPrefixStorages.FindNodeOrInsertPos(ID, InsertPos); + if (!S) { + S = new (Ctx, alignof(NamespaceAndPrefixStorage)) + NamespaceAndPrefixStorage(Namespace, Prefix); + Ctx.NamespaceAndPrefixStorages.InsertNode(S, InsertPos); } - - return NNS; -} - -NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const IdentifierInfo *II) { - assert(II && "Identifier cannot be NULL"); - assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); - - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredIdentifier); - Mockup.Specifier = const_cast(II); - return FindOrInsert(Context, Mockup); -} - -NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const NamespaceBaseDecl *NS) { - assert(NS && "Namespace cannot be NULL"); - assert((!Prefix || - (Prefix->getAsType() == nullptr && - Prefix->getAsIdentifier() == nullptr)) && - "Broken nested name specifier"); - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredDecl); - Mockup.Specifier = const_cast(NS); - return FindOrInsert(Context, Mockup); -} - -NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, - NestedNameSpecifier *Prefix, - const Type *T) { - assert(T && "Type cannot be NULL"); - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(Prefix); - Mockup.Prefix.setInt(StoredTypeSpec); - Mockup.Specifier = const_cast(T); - return FindOrInsert(Context, Mockup); -} - -NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context, - const IdentifierInfo *II) { - assert(II && "Identifier cannot be NULL"); - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(nullptr); - Mockup.Prefix.setInt(StoredIdentifier); - Mockup.Specifier = const_cast(II); - return FindOrInsert(Context, Mockup); -} - -NestedNameSpecifier * -NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { - if (!Context.GlobalNestedNameSpecifier) - Context.GlobalNestedNameSpecifier = - new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(); - return Context.GlobalNestedNameSpecifier; -} - -NestedNameSpecifier * -NestedNameSpecifier::SuperSpecifier(const ASTContext &Context, - CXXRecordDecl *RD) { - NestedNameSpecifier Mockup; - Mockup.Prefix.setPointer(nullptr); - Mockup.Prefix.setInt(StoredDecl); - Mockup.Specifier = RD; - return FindOrInsert(Context, Mockup); + return S; } -NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { - if (!Specifier) - return Global; - - switch (Prefix.getInt()) { - case StoredIdentifier: - return Identifier; - - case StoredDecl: { - NamedDecl *ND = static_cast(Specifier); - return isa(ND) ? Super : Namespace; - } - - case StoredTypeSpec: - return TypeSpec; - } - - llvm_unreachable("Invalid NNS Kind!"); -} - -/// Retrieve the namespace or namespace alias stored in this nested name -/// specifier. -NamespaceBaseDecl *NestedNameSpecifier::getAsNamespace() const { - if (Prefix.getInt() == StoredDecl) - return dyn_cast(static_cast(Specifier)); - - return nullptr; -} - -/// Retrieve the record declaration stored in this nested name specifier. -CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { - switch (Prefix.getInt()) { - case StoredIdentifier: - return nullptr; - - case StoredDecl: - return dyn_cast(static_cast(Specifier)); - - case StoredTypeSpec: - return getAsType()->getAsCXXRecordDecl(); +bool NestedNameSpecifier::isFullyQualified() const { + switch (getKind()) { + case NestedNameSpecifier::Kind::Global: + return true; + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::MicrosoftSuper: + return false; + case NestedNameSpecifier::Kind::Namespace: + return getAsNamespaceAndPrefix().Prefix.isFullyQualified(); + case NestedNameSpecifier::Kind::Type: + return getAsType()->getPrefix().isFullyQualified(); } - llvm_unreachable("Invalid NNS Kind!"); } NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const { switch (getKind()) { - case Identifier: { - // Identifier specifiers always represent dependent types - auto F = NestedNameSpecifierDependence::Dependent | - NestedNameSpecifierDependence::Instantiation; - // Prefix can contain unexpanded template parameters. - if (getPrefix()) - return F | getPrefix()->getDependence(); - return F; - } - - case Namespace: - case Global: - return NestedNameSpecifierDependence::None; - - case Super: { - CXXRecordDecl *RD = static_cast(Specifier); - for (const auto &Base : RD->bases()) - if (Base.getType()->isDependentType()) - // FIXME: must also be instantiation-dependent. - return NestedNameSpecifierDependence::Dependent; + case Kind::Null: + case Kind::Global: + case Kind::Namespace: return NestedNameSpecifierDependence::None; + case Kind::MicrosoftSuper: { + CXXRecordDecl *RD = getAsMicrosoftSuper(); + return RD->isDependentContext() + ? NestedNameSpecifierDependence::DependentInstantiation | + NestedNameSpecifierDependence::Dependent + : NestedNameSpecifierDependence::None; } - - case TypeSpec: { - NestedNameSpecifierDependence Dep = - toNestedNameSpecifierDependendence(getAsType()->getDependence()); - if (NestedNameSpecifier *Prefix = getPrefix()) - Dep |= - Prefix->getDependence() & ~NestedNameSpecifierDependence::Dependent; - return Dep; - } + case Kind::Type: + return toNestedNameSpecifierDependence(getAsType()->getDependence()); } llvm_unreachable("Invalid NNS Kind!"); } -bool NestedNameSpecifier::isDependent() const { - return getDependence() & NestedNameSpecifierDependence::Dependent; -} - -bool NestedNameSpecifier::isInstantiationDependent() const { - return getDependence() & NestedNameSpecifierDependence::Instantiation; -} - -bool NestedNameSpecifier::containsUnexpandedParameterPack() const { - return getDependence() & NestedNameSpecifierDependence::UnexpandedPack; -} - -bool NestedNameSpecifier::containsErrors() const { - return getDependence() & NestedNameSpecifierDependence::Error; -} - -const Type * -NestedNameSpecifier::translateToType(const ASTContext &Context) const { - NestedNameSpecifier *Prefix = getPrefix(); - switch (getKind()) { - case SpecifierKind::Identifier: - return Context - .getDependentNameType(ElaboratedTypeKeyword::None, Prefix, - getAsIdentifier()) - .getTypePtr(); - case SpecifierKind::TypeSpec: { - const Type *T = getAsType(); - switch (T->getTypeClass()) { - case Type::DependentTemplateSpecialization: { - const auto *DT = cast(T); - const DependentTemplateStorage &DTN = DT->getDependentTemplateName(); - return Context - .getDependentTemplateSpecializationType( - ElaboratedTypeKeyword::None, - {Prefix, DTN.getName(), DTN.hasTemplateKeyword()}, - DT->template_arguments()) - .getTypePtr(); - } - case Type::Record: - case Type::TemplateSpecialization: - case Type::Using: - case Type::Enum: - case Type::Typedef: - case Type::UnresolvedUsing: - return Context - .getElaboratedType(ElaboratedTypeKeyword::None, Prefix, - QualType(T, 0)) - .getTypePtr(); - default: - assert(Prefix == nullptr && "unexpected type with elaboration"); - return T; - } - } - case SpecifierKind::Global: - case SpecifierKind::Namespace: - case SpecifierKind::Super: - // These are not representable as types. - return nullptr; - } - llvm_unreachable("Unhandled SpecifierKind enum"); -} - /// Print this nested name specifier to the given output /// stream. void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, bool ResolveTemplateArguments, bool PrintFinalScopeResOp) const { - if (getPrefix()) - getPrefix()->print(OS, Policy); - switch (getKind()) { - case Identifier: - OS << getAsIdentifier()->getName(); - break; - - case Namespace: { - NamespaceBaseDecl *Namespace = getAsNamespace(); + case Kind::Namespace: { + auto [Namespace, Prefix] = getAsNamespaceAndPrefix(); + Prefix.print(OS, Policy); if (const auto *NS = dyn_cast(Namespace)) { assert(!NS->isAnonymousNamespace()); OS << NS->getName(); @@ -286,134 +103,49 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, } break; } - - case Global: + case Kind::Global: OS << "::"; return; - - case Super: + case Kind::MicrosoftSuper: OS << "__super"; break; - - case TypeSpec: { + case Kind::Type: { PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressScope = true; InnerPolicy.SuppressTagKeyword = true; QualType(getAsType(), 0).print(OS, InnerPolicy); break; } + case Kind::Null: + return; } - if (PrintFinalScopeResOp) OS << "::"; } -LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { - dump(llvm::errs(), LO); +LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream *OS, + const LangOptions *LO) const { + print(OS ? *OS : llvm::errs(), LO ? *LO : LangOptions()); } -LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } - +LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { + dump(/*OS=*/nullptr, &LO); +} LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { - LangOptions LO; - dump(OS, LO); + dump(&OS); } - LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, const LangOptions &LO) const { - print(OS, PrintingPolicy(LO)); -} - -unsigned -NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { - assert(Qualifier && "Expected a non-NULL qualifier"); - - // Location of the trailing '::'. - unsigned Length = sizeof(SourceLocation::UIntTy); - - switch (Qualifier->getKind()) { - case NestedNameSpecifier::Global: - // Nothing more to add. - break; - - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Super: - // The location of the identifier or namespace name. - Length += sizeof(SourceLocation::UIntTy); - break; - - case NestedNameSpecifier::TypeSpec: - // The "void*" that points at the TypeLoc data. - // Note: the 'template' keyword is part of the TypeLoc. - Length += sizeof(void *); - break; - } - - return Length; -} - -unsigned -NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { - unsigned Length = 0; - for (; Qualifier; Qualifier = Qualifier->getPrefix()) - Length += getLocalDataLength(Qualifier); - return Length; -} - -/// Load a (possibly unaligned) source location from a given address -/// and offset. -static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { - SourceLocation::UIntTy Raw; - memcpy(&Raw, static_cast(Data) + Offset, sizeof(Raw)); - return SourceLocation::getFromRawEncoding(Raw); + dump(&OS, &LO); } -/// Load a (possibly unaligned) pointer from a given address and -/// offset. -static void *LoadPointer(void *Data, unsigned Offset) { - void *Result; - memcpy(&Result, static_cast(Data) + Offset, sizeof(void*)); - return Result; -} - -SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { +SourceLocation NestedNameSpecifierLoc::getBeginLoc() const { if (!Qualifier) - return SourceRange(); - - unsigned Offset = getDataLength(Qualifier->getPrefix()); - switch (Qualifier->getKind()) { - case NestedNameSpecifier::Global: - return LoadSourceLocation(Data, Offset); - - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Super: - return SourceRange( - LoadSourceLocation(Data, Offset), - LoadSourceLocation(Data, Offset + sizeof(SourceLocation::UIntTy))); - - case NestedNameSpecifier::TypeSpec: { - // The "void*" that points at the TypeLoc data. - // Note: the 'template' keyword is part of the TypeLoc. - void *TypeData = LoadPointer(Data, Offset); - TypeLoc TL(Qualifier->getAsType(), TypeData); - return SourceRange(TL.getBeginLoc(), - LoadSourceLocation(Data, Offset + sizeof(void*))); - } - } + return SourceLocation(); - llvm_unreachable("Invalid NNS Kind!"); -} - -TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { - if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec) - return TypeLoc(); - - // The "void*" that points at the TypeLoc data. - unsigned Offset = getDataLength(Qualifier->getPrefix()); - void *TypeData = LoadPointer(Data, Offset); - return TypeLoc(Qualifier->getAsType(), TypeData); + NestedNameSpecifierLoc First = *this; + while (NestedNameSpecifierLoc Prefix = First.getAsNamespaceAndPrefix().Prefix) + First = Prefix; + return First.getLocalSourceRange().getBegin(); } static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, @@ -515,10 +247,10 @@ operator=(const NestedNameSpecifierLocBuilder &Other) { return *this; } -void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL, - SourceLocation ColonColonLoc) { - Representation = - NestedNameSpecifier::Create(Context, Representation, TL.getTypePtr()); +void NestedNameSpecifierLocBuilder::Make(ASTContext &Context, TypeLoc TL, + SourceLocation ColonColonLoc) { + assert(!Representation); + Representation = NestedNameSpecifier(TL.getTypePtr()); // Push source-location info into the buffer. SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); @@ -526,23 +258,10 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL, } void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, - IdentifierInfo *Identifier, - SourceLocation IdentifierLoc, - SourceLocation ColonColonLoc) { - Representation = NestedNameSpecifier::Create(Context, Representation, - Identifier); - - // Push source-location info into the buffer. - SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); - SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); -} - -void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, - NamespaceBaseDecl *Namespace, + const NamespaceBaseDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc) { - Representation = NestedNameSpecifier::Create(Context, Representation, - Namespace); + Representation = NestedNameSpecifier(Context, Namespace, Representation); // Push source-location info into the buffer. SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); @@ -552,60 +271,48 @@ void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc) { assert(!Representation && "Already have a nested-name-specifier!?"); - Representation = NestedNameSpecifier::GlobalSpecifier(Context); + Representation = NestedNameSpecifier::getGlobal(); // Push source-location info into the buffer. SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } -void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, - CXXRecordDecl *RD, - SourceLocation SuperLoc, - SourceLocation ColonColonLoc) { - Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); +void NestedNameSpecifierLocBuilder::MakeMicrosoftSuper( + ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc, + SourceLocation ColonColonLoc) { + Representation = NestedNameSpecifier(RD); // Push source-location info into the buffer. SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); } -void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, - NestedNameSpecifier *Qualifier, +void NestedNameSpecifierLocBuilder::PushTrivial(ASTContext &Context, + NestedNameSpecifier Qualifier, SourceRange R) { - Representation = Qualifier; - // Construct bogus (but well-formed) source information for the // nested-name-specifier. - BufferSize = 0; - SmallVector Stack; - for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) - Stack.push_back(NNS); - while (!Stack.empty()) { - NestedNameSpecifier *NNS = Stack.pop_back_val(); - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Namespace: - SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); - break; - - case NestedNameSpecifier::TypeSpec: { - TypeSourceInfo *TSInfo - = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), - R.getBegin()); - SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, - BufferCapacity); - break; - } - - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - break; - } - - // Save the location of the '::'. - SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), - Buffer, BufferSize, BufferCapacity); + switch (Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: + return; + case NestedNameSpecifier::Kind::Namespace: { + auto [_1, Prefix] = Qualifier.getAsNamespaceAndPrefix(); + PushTrivial(Context, Prefix, R.getBegin()); + SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); + break; + } + case NestedNameSpecifier::Kind::Type: { + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo( + QualType(Qualifier.getAsType(), 0), R.getBegin()); + SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, + BufferCapacity); + break; + } + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: + break; } + SaveSourceLocation(R.getEnd(), Buffer, BufferSize, BufferCapacity); } void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 9812d26a61f05..fb95f58092c49 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -111,34 +111,28 @@ void ODRHash::AddDeclarationNameInfoImpl(DeclarationNameInfo NameInfo) { } } -void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - assert(NNS && "Expecting non-null pointer."); - const auto *Prefix = NNS->getPrefix(); - AddBoolean(Prefix); - if (Prefix) { - AddNestedNameSpecifier(Prefix); - } - auto Kind = NNS->getKind(); - ID.AddInteger(Kind); +void ODRHash::AddNestedNameSpecifier(NestedNameSpecifier NNS) { + auto Kind = NNS.getKind(); + ID.AddInteger(llvm::to_underlying(Kind)); switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierInfo(NNS->getAsIdentifier()); - break; - case NestedNameSpecifier::Namespace: - AddDecl(NNS->getAsNamespace()); + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix(); + AddDecl(Namespace); + AddNestedNameSpecifier(Prefix); break; - case NestedNameSpecifier::TypeSpec: - AddType(NNS->getAsType()); + } + case NestedNameSpecifier::Kind::Type: + AddType(NNS.getAsType()); break; - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: break; } } void ODRHash::AddDependentTemplateName(const DependentTemplateStorage &Name) { - if (NestedNameSpecifier *NNS = Name.getQualifier()) - AddNestedNameSpecifier(NNS); + AddNestedNameSpecifier(Name.getQualifier()); if (IdentifierOrOverloadedOperator IO = Name.getName(); const IdentifierInfo *II = IO.getIdentifier()) AddIdentifierInfo(II); @@ -156,8 +150,7 @@ void ODRHash::AddTemplateName(TemplateName Name) { break; case TemplateName::QualifiedTemplate: { QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName(); - if (NestedNameSpecifier *NNS = QTN->getQualifier()) - AddNestedNameSpecifier(NNS); + AddNestedNameSpecifier(QTN->getQualifier()); AddBoolean(QTN->hasTemplateKeyword()); AddTemplateName(QTN->getUnderlyingTemplate()); break; @@ -889,11 +882,8 @@ class ODRTypeVisitor : public TypeVisitor { } } - void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) { - Hash.AddBoolean(NNS); - if (NNS) { - Hash.AddNestedNameSpecifier(NNS); - } + void AddNestedNameSpecifier(NestedNameSpecifier NNS) { + Hash.AddNestedNameSpecifier(NNS); } void AddIdentifierInfo(const IdentifierInfo *II) { @@ -1069,7 +1059,7 @@ class ODRTypeVisitor : public TypeVisitor { } void VisitInjectedClassNameType(const InjectedClassNameType *T) { - AddDecl(T->getDecl()); + AddDecl(T->getOriginalDecl()->getDefinitionOrSelf()); VisitType(T); } diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index de8b5996818de..588b0dcc6d7b8 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -2350,17 +2350,16 @@ void OMPClausePrinter::VisitOMPReductionClause(OMPReductionClause *Node) { if (Node->getModifierLoc().isValid()) OS << getOpenMPSimpleClauseTypeName(OMPC_reduction, Node->getModifier()) << ", "; - NestedNameSpecifier *QualifierLoc = + NestedNameSpecifier Qualifier = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { + if (!Qualifier && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); + Qualifier.print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; @@ -2373,17 +2372,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause( OMPTaskReductionClause *Node) { if (!Node->varlist_empty()) { OS << "task_reduction("; - NestedNameSpecifier *QualifierLoc = + NestedNameSpecifier Qualifier = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { + if (!Qualifier && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); + Qualifier.print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; @@ -2395,17 +2393,16 @@ void OMPClausePrinter::VisitOMPTaskReductionClause( void OMPClausePrinter::VisitOMPInReductionClause(OMPInReductionClause *Node) { if (!Node->varlist_empty()) { OS << "in_reduction("; - NestedNameSpecifier *QualifierLoc = + NestedNameSpecifier Qualifier = Node->getQualifierLoc().getNestedNameSpecifier(); OverloadedOperatorKind OOK = Node->getNameInfo().getName().getCXXOverloadedOperator(); - if (QualifierLoc == nullptr && OOK != OO_None) { + if (!Qualifier && OOK != OO_None) { // Print reduction identifier in C format OS << getOperatorSpelling(OOK); } else { // Use C++ format - if (QualifierLoc != nullptr) - QualifierLoc->print(OS, Policy); + Qualifier.print(OS, Policy); OS << Node->getNameInfo(); } OS << ":"; @@ -2508,10 +2505,9 @@ template static void PrintMapper(raw_ostream &OS, T *Node, const PrintingPolicy &Policy) { OS << '('; - NestedNameSpecifier *MapperNNS = + NestedNameSpecifier MapperNNS = Node->getMapperQualifierLoc().getNestedNameSpecifier(); - if (MapperNNS) - MapperNNS->print(OS, Policy); + MapperNNS.print(OS, Policy); OS << Node->getMapperIdInfo() << ')'; } diff --git a/clang/lib/AST/ParentMapContext.cpp b/clang/lib/AST/ParentMapContext.cpp index 68dfe4d5d22cb..acc011cb2faa4 100644 --- a/clang/lib/AST/ParentMapContext.cpp +++ b/clang/lib/AST/ParentMapContext.cpp @@ -438,10 +438,12 @@ class ParentMapContext::ParentMap::ASTVisitor DeclNode, DeclNode, [&] { return VisitorBase::TraverseDecl(DeclNode); }, &Map.PointerParents); } - bool TraverseTypeLoc(TypeLoc TypeLocNode) { + bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) { return TraverseNode( TypeLocNode, DynTypedNode::create(TypeLocNode), - [&] { return VisitorBase::TraverseTypeLoc(TypeLocNode); }, + [&] { + return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier); + }, &Map.OtherParents); } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLocNode) { diff --git a/clang/lib/AST/PrintfFormatString.cpp b/clang/lib/AST/PrintfFormatString.cpp index bcd44f0a85eed..687160c6116be 100644 --- a/clang/lib/AST/PrintfFormatString.cpp +++ b/clang/lib/AST/PrintfFormatString.cpp @@ -794,7 +794,7 @@ bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, // If it's an enum, get its underlying type. if (const EnumType *ETy = QT->getAs()) - QT = ETy->getDecl()->getIntegerType(); + QT = ETy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); const BuiltinType *BT = QT->getAs(); if (!BT) { diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index c77e3dd281b3a..ee7fec3372fcf 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -24,10 +24,9 @@ namespace TypeName { /// is requested. /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace /// specifier "::" should be prepended or not. -static NestedNameSpecifier *createNestedNameSpecifier( - const ASTContext &Ctx, - const NamespaceDecl *Namesp, - bool WithGlobalNsPrefix); +static NestedNameSpecifier +createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namesp, + bool WithGlobalNsPrefix); /// Create a NestedNameSpecifier for TagDecl and its enclosing /// scopes. @@ -39,22 +38,24 @@ static NestedNameSpecifier *createNestedNameSpecifier( /// qualified names. /// \param[in] WithGlobalNsPrefix - Indicate whether the global namespace /// specifier "::" should be prepended or not. -static NestedNameSpecifier *createNestedNameSpecifier( - const ASTContext &Ctx, const TypeDecl *TD, - bool FullyQualify, bool WithGlobalNsPrefix); +static NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx, + const TypeDecl *TD, + bool FullyQualify, + bool WithGlobalNsPrefix); -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Decl *decl, - bool FullyQualified, bool WithGlobalNsPrefix); +static NestedNameSpecifier +createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *decl, + bool FullyQualified, + bool WithGlobalNsPrefix); -static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( - const ASTContext &Ctx, NestedNameSpecifier *scope, bool WithGlobalNsPrefix); +static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier( + const ASTContext &Ctx, NestedNameSpecifier NNS, bool WithGlobalNsPrefix); static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, TemplateName &TName, bool WithGlobalNsPrefix) { bool Changed = false; - NestedNameSpecifier *NNS = nullptr; + NestedNameSpecifier NNS = std::nullopt; TemplateDecl *ArgTDecl = TName.getAsTemplateDecl(); // ArgTDecl won't be NULL because we asserted that this isn't a @@ -65,13 +66,13 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx, if (QTName && !QTName->hasTemplateKeyword() && (NNS = QTName->getQualifier())) { - NestedNameSpecifier *QNNS = getFullyQualifiedNestedNameSpecifier( - Ctx, NNS, WithGlobalNsPrefix); + NestedNameSpecifier QNNS = + getFullyQualifiedNestedNameSpecifier(Ctx, NNS, WithGlobalNsPrefix); if (QNNS != NNS) { Changed = true; NNS = QNNS; } else { - NNS = nullptr; + NNS = std::nullopt; } } else { NNS = createNestedNameSpecifierForScopeOf( @@ -116,76 +117,81 @@ static bool getFullyQualifiedTemplateArgument(const ASTContext &Ctx, } static const Type *getFullyQualifiedTemplateType(const ASTContext &Ctx, - const Type *TypePtr, + const TagType *TSTRecord, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier Qualifier, bool WithGlobalNsPrefix) { - // DependentTemplateTypes exist within template declarations and - // definitions. Therefore we shouldn't encounter them at the end of - // a translation unit. If we do, the caller has made an error. - assert(!isa(TypePtr)); - // In case of template specializations, iterate over the arguments - // and fully qualify them as well. - if (const auto *TST = dyn_cast(TypePtr)) { - bool MightHaveChanged = false; - SmallVector FQArgs; - // Cheap to copy and potentially modified by - // getFullyQualifedTemplateArgument. - for (TemplateArgument Arg : TST->template_arguments()) { - MightHaveChanged |= getFullyQualifiedTemplateArgument( - Ctx, Arg, WithGlobalNsPrefix); - FQArgs.push_back(Arg); - } + // We are asked to fully qualify and we have a Record Type, + // which can point to a template instantiation with no sugar in any of + // its template argument, however we still need to fully qualify them. + + const auto *TD = TSTRecord->getOriginalDecl(); + const auto *TSTDecl = dyn_cast(TD); + if (!TSTDecl) + return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false) + .getTypePtr(); + + const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs(); + + bool MightHaveChanged = false; + SmallVector FQArgs; + for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) { + // cheap to copy and potentially modified by + // getFullyQualifedTemplateArgument + TemplateArgument Arg(TemplateArgs[I]); + MightHaveChanged |= + getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix); + FQArgs.push_back(Arg); + } - // If a fully qualified arg is different from the unqualified arg, - // allocate new type in the AST. - if (MightHaveChanged) { - QualType QT = Ctx.getTemplateSpecializationType( - TST->getTemplateName(), FQArgs, - /*CanonicalArgs=*/{}, TST->desugar()); - // getTemplateSpecializationType returns a fully qualified - // version of the specialization itself, so no need to qualify - // it. - return QT.getTypePtr(); - } - } else if (const auto *TSTRecord = dyn_cast(TypePtr)) { - // We are asked to fully qualify and we have a Record Type, - // which can point to a template instantiation with no sugar in any of - // its template argument, however we still need to fully qualify them. - - if (const auto *TSTDecl = - dyn_cast(TSTRecord->getDecl())) { - const TemplateArgumentList &TemplateArgs = TSTDecl->getTemplateArgs(); - - bool MightHaveChanged = false; - SmallVector FQArgs; - for (unsigned int I = 0, E = TemplateArgs.size(); I != E; ++I) { - // cheap to copy and potentially modified by - // getFullyQualifedTemplateArgument - TemplateArgument Arg(TemplateArgs[I]); - MightHaveChanged |= getFullyQualifiedTemplateArgument( - Ctx, Arg, WithGlobalNsPrefix); - FQArgs.push_back(Arg); - } + if (!MightHaveChanged) + return Ctx.getTagType(Keyword, Qualifier, TD, /*OwnsTag=*/false) + .getTypePtr(); + // If a fully qualified arg is different from the unqualified arg, + // allocate new type in the AST. + TemplateName TN = Ctx.getQualifiedTemplateName( + Qualifier, /*TemplateKeyword=*/false, + TemplateName(TSTDecl->getSpecializedTemplate())); + QualType QT = Ctx.getTemplateSpecializationType( + Keyword, TN, FQArgs, + /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal()); + // getTemplateSpecializationType returns a fully qualified + // version of the specialization itself, so no need to qualify + // it. + return QT.getTypePtr(); +} - // If a fully qualified arg is different from the unqualified arg, - // allocate new type in the AST. - if (MightHaveChanged) { - TemplateName TN(TSTDecl->getSpecializedTemplate()); - QualType QT = Ctx.getTemplateSpecializationType( - TN, FQArgs, - /*CanonicalArgs=*/{}, TSTRecord->getCanonicalTypeInternal()); - // getTemplateSpecializationType returns a fully qualified - // version of the specialization itself, so no need to qualify - // it. - return QT.getTypePtr(); - } - } +static const Type * +getFullyQualifiedTemplateType(const ASTContext &Ctx, + const TemplateSpecializationType *TST, + bool WithGlobalNsPrefix) { + TemplateName TName = TST->getTemplateName(); + bool MightHaveChanged = + getFullyQualifiedTemplateName(Ctx, TName, WithGlobalNsPrefix); + SmallVector FQArgs; + // Cheap to copy and potentially modified by + // getFullyQualifedTemplateArgument. + for (TemplateArgument Arg : TST->template_arguments()) { + MightHaveChanged |= + getFullyQualifiedTemplateArgument(Ctx, Arg, WithGlobalNsPrefix); + FQArgs.push_back(Arg); } - return TypePtr; + + if (!MightHaveChanged) + return TST; + + QualType NewQT = + Ctx.getTemplateSpecializationType(TST->getKeyword(), TName, FQArgs, + /*CanonicalArgs=*/{}, TST->desugar()); + // getTemplateSpecializationType returns a fully qualified + // version of the specialization itself, so no need to qualify + // it. + return NewQT.getTypePtr(); } -static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D, - bool FullyQualify, - bool WithGlobalNsPrefix) { +static NestedNameSpecifier createOuterNNS(const ASTContext &Ctx, const Decl *D, + bool FullyQualify, + bool WithGlobalNsPrefix) { const DeclContext *DC = D->getDeclContext(); if (const auto *NS = dyn_cast(DC)) { while (NS && NS->isInline()) { @@ -195,71 +201,63 @@ static NestedNameSpecifier *createOuterNNS(const ASTContext &Ctx, const Decl *D, if (NS && NS->getDeclName()) { return createNestedNameSpecifier(Ctx, NS, WithGlobalNsPrefix); } - return nullptr; // no starting '::', no anonymous - } else if (const auto *TD = dyn_cast(DC)) { - return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix); - } else if (const auto *TDD = dyn_cast(DC)) { - return createNestedNameSpecifier( - Ctx, TDD, FullyQualify, WithGlobalNsPrefix); - } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { - return NestedNameSpecifier::GlobalSpecifier(Ctx); + return std::nullopt; // no starting '::', no anonymous } - return nullptr; // no starting '::' if |WithGlobalNsPrefix| is false + if (const auto *TD = dyn_cast(DC)) + return createNestedNameSpecifier(Ctx, TD, FullyQualify, WithGlobalNsPrefix); + if (const auto *TDD = dyn_cast(DC)) + return createNestedNameSpecifier(Ctx, TDD, FullyQualify, + WithGlobalNsPrefix); + if (WithGlobalNsPrefix && DC->isTranslationUnit()) + return NestedNameSpecifier::getGlobal(); + return std::nullopt; // no starting '::' if |WithGlobalNsPrefix| is false } /// Return a fully qualified version of this name specifier. -static NestedNameSpecifier *getFullyQualifiedNestedNameSpecifier( - const ASTContext &Ctx, NestedNameSpecifier *Scope, - bool WithGlobalNsPrefix) { - switch (Scope->getKind()) { - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - // Already fully qualified - return Scope; - case NestedNameSpecifier::Namespace: - return TypeName::createNestedNameSpecifier( - Ctx, Scope->getAsNamespace()->getNamespace(), WithGlobalNsPrefix); - case NestedNameSpecifier::Identifier: - // A function or some other construct that makes it un-namable - // at the end of the TU. Skip the current component of the name, - // but use the name of it's prefix. - return getFullyQualifiedNestedNameSpecifier( - Ctx, Scope->getPrefix(), WithGlobalNsPrefix); - case NestedNameSpecifier::TypeSpec: { - const Type *Type = Scope->getAsType(); - // Find decl context. - const TagDecl *TD = nullptr; - if (const TagType *TagDeclType = Type->getAs()) { - TD = TagDeclType->getDecl(); - } else { - TD = Type->getAsCXXRecordDecl(); - } - if (TD) { - return TypeName::createNestedNameSpecifier(Ctx, TD, - true /*FullyQualified*/, - WithGlobalNsPrefix); - } else if (const auto *TDD = dyn_cast(Type)) { - return TypeName::createNestedNameSpecifier(Ctx, TDD->getDecl(), - true /*FullyQualified*/, - WithGlobalNsPrefix); - } +static NestedNameSpecifier getFullyQualifiedNestedNameSpecifier( + const ASTContext &Ctx, NestedNameSpecifier Scope, bool WithGlobalNsPrefix) { + switch (Scope.getKind()) { + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("can't fully qualify the empty nested name specifier"); + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: + // Already fully qualified + return Scope; + case NestedNameSpecifier::Kind::Namespace: + return TypeName::createNestedNameSpecifier( + Ctx, Scope.getAsNamespaceAndPrefix().Namespace->getNamespace(), + WithGlobalNsPrefix); + case NestedNameSpecifier::Kind::Type: { + const Type *Type = Scope.getAsType(); + // Find decl context. + const TypeDecl *TD; + if (const TagType *TagDeclType = Type->getAs()) + TD = TagDeclType->getOriginalDecl(); + else if (const auto *D = dyn_cast(Type)) + TD = D->getDecl(); + else return Scope; - } + return TypeName::createNestedNameSpecifier(Ctx, TD, /*FullyQualify=*/true, + WithGlobalNsPrefix); + } } llvm_unreachable("bad NNS kind"); } /// Create a nested name specifier for the declaring context of /// the type. -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Decl *Decl, - bool FullyQualified, bool WithGlobalNsPrefix) { +static NestedNameSpecifier +createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Decl *Decl, + bool FullyQualified, + bool WithGlobalNsPrefix) { assert(Decl); const DeclContext *DC = Decl->getDeclContext()->getRedeclContext(); const auto *Outer = dyn_cast(DC); const auto *OuterNS = dyn_cast(DC); - if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) { + if (OuterNS && OuterNS->isAnonymousNamespace()) + OuterNS = dyn_cast(OuterNS->getParent()); + if (Outer) { if (const auto *CxxDecl = dyn_cast(DC)) { if (ClassTemplateDecl *ClassTempl = CxxDecl->getDescribedClassTemplate()) { @@ -288,76 +286,80 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( Ctx, TD, FullyQualified, WithGlobalNsPrefix); } else if (isa(Outer)) { // Context is the TU. Nothing needs to be done. - return nullptr; + return std::nullopt; } else { // Decl's context was neither the TU, a namespace, nor a // TagDecl, which means it is a type local to a scope, and not // accessible at the end of the TU. - return nullptr; + return std::nullopt; } } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { - return NestedNameSpecifier::GlobalSpecifier(Ctx); + return NestedNameSpecifier::getGlobal(); } - return nullptr; + return std::nullopt; } /// Create a nested name specifier for the declaring context of /// the type. -static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( - const ASTContext &Ctx, const Type *TypePtr, - bool FullyQualified, bool WithGlobalNsPrefix) { - if (!TypePtr) return nullptr; +static NestedNameSpecifier +createNestedNameSpecifierForScopeOf(const ASTContext &Ctx, const Type *TypePtr, + bool FullyQualified, + bool WithGlobalNsPrefix) { + if (!TypePtr) + return std::nullopt; Decl *Decl = nullptr; // There are probably other cases ... if (const auto *TDT = dyn_cast(TypePtr)) { Decl = TDT->getDecl(); } else if (const auto *TagDeclType = dyn_cast(TypePtr)) { - Decl = TagDeclType->getDecl(); + Decl = TagDeclType->getOriginalDecl(); } else if (const auto *TST = dyn_cast(TypePtr)) { Decl = TST->getTemplateName().getAsTemplateDecl(); } else { Decl = TypePtr->getAsCXXRecordDecl(); } - if (!Decl) return nullptr; + if (!Decl) + return std::nullopt; return createNestedNameSpecifierForScopeOf( Ctx, Decl, FullyQualified, WithGlobalNsPrefix); } -NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, - const NamespaceDecl *Namespace, - bool WithGlobalNsPrefix) { +static NestedNameSpecifier +createNestedNameSpecifier(const ASTContext &Ctx, const NamespaceDecl *Namespace, + bool WithGlobalNsPrefix) { while (Namespace && Namespace->isInline()) { // Ignore inline namespace; Namespace = dyn_cast(Namespace->getDeclContext()); } - if (!Namespace) return nullptr; + if (!Namespace) + return std::nullopt; - bool FullyQualified = true; // doesn't matter, DeclContexts are namespaces - return NestedNameSpecifier::Create( - Ctx, - createOuterNNS(Ctx, Namespace, FullyQualified, WithGlobalNsPrefix), - Namespace); + bool FullyQualify = true; // doesn't matter, DeclContexts are namespaces + return NestedNameSpecifier( + Ctx, Namespace, + createOuterNNS(Ctx, Namespace, FullyQualify, WithGlobalNsPrefix)); } -NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, - const TypeDecl *TD, - bool FullyQualify, - bool WithGlobalNsPrefix) { - const Type *TypePtr = TD->getTypeForDecl(); - if (isa(TypePtr) || - isa(TypePtr)) { +NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx, + const TypeDecl *TD, + bool FullyQualify, + bool WithGlobalNsPrefix) { + const Type *TypePtr = Ctx.getTypeDeclType(TD).getTypePtr(); + if (auto *RD = dyn_cast(TypePtr)) { // We are asked to fully qualify and we have a Record Type (which // may point to a template specialization) or Template // Specialization Type. We need to fully qualify their arguments. - - TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix); + TypePtr = getFullyQualifiedTemplateType( + Ctx, RD, ElaboratedTypeKeyword::None, + createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), + WithGlobalNsPrefix); + } else if (auto *TST = dyn_cast(TypePtr)) { + TypePtr = getFullyQualifiedTemplateType(Ctx, TST, WithGlobalNsPrefix); } - - return NestedNameSpecifier::Create( - Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), TypePtr); + return NestedNameSpecifier(TypePtr); } /// Return the fully qualified type, including fully-qualified @@ -381,7 +383,7 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, Qualifiers Quals = QT.getQualifiers(); // Fully qualify the pointee and class types. QT = getFullyQualifiedType(QT->getPointeeType(), Ctx, WithGlobalNsPrefix); - NestedNameSpecifier *Qualifier = getFullyQualifiedNestedNameSpecifier( + NestedNameSpecifier Qualifier = getFullyQualifiedNestedNameSpecifier( Ctx, MPT->getQualifier(), WithGlobalNsPrefix); QT = Ctx.getMemberPointerType(QT, Qualifier, MPT->getMostRecentCXXRecordDecl()); @@ -489,5 +491,12 @@ std::string getFullyQualifiedName(QualType QT, return FQQT.getAsString(Policy); } +NestedNameSpecifier getFullyQualifiedDeclaredContext(const ASTContext &Ctx, + const Decl *Decl, + bool WithGlobalNsPrefix) { + return createNestedNameSpecifierForScopeOf(Ctx, Decl, /*FullyQualified=*/true, + WithGlobalNsPrefix); +} + } // end namespace TypeName } // end namespace clang diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index ad1d31a39cea6..f1f21f426f944 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2012,8 +2012,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, } else if (const BuiltinType *BTy = BaseTy->getAs()) { performBuiltinTypeAlignmentUpgrade(BTy); } else if (const RecordType *RT = BaseTy->getAs()) { - const RecordDecl *RD = RT->getDecl(); - assert(RD && "Expected non-null RecordDecl."); + const RecordDecl *RD = RT->getOriginalDecl(); const ASTRecordLayout &FieldRecord = Context.getASTRecordLayout(RD); PreferredAlign = FieldRecord.getPreferredAlignment(); } @@ -2714,7 +2713,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( else { if (auto RT = FD->getType()->getBaseElementTypeUnsafe()->getAs()) { - auto const &Layout = Context.getASTRecordLayout(RT->getDecl()); + auto const &Layout = Context.getASTRecordLayout(RT->getOriginalDecl()); EndsWithZeroSizedObject = Layout.endsWithZeroSizedObject(); FieldRequiredAlignment = std::max(FieldRequiredAlignment, Layout.getRequiredAlignment()); @@ -3697,8 +3696,8 @@ static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, // Recursively dump fields of record type. if (auto RT = Field->getType()->getAs()) { - DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel, - Field->getName().data(), + DumpRecordLayout(OS, RT->getOriginalDecl()->getDefinitionOrSelf(), C, + FieldOffset, IndentLevel, Field->getName().data(), /*PrintSizeInfo=*/false, /*IncludeVirtualBases=*/true); continue; diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index 1227edd47d13d..31c001d025fea 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -432,9 +432,10 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, // If it's an enum, get its underlying type. if (const EnumType *ETy = PT->getAs()) { // Don't try to fix incomplete enums. - if (!ETy->getDecl()->isComplete()) + const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) return false; - PT = ETy->getDecl()->getIntegerType(); + PT = ED->getIntegerType(); } const BuiltinType *BT = PT->getAs(); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index a2c77883df419..afccba8778fd2 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -454,10 +454,7 @@ void StmtPrinter::VisitMSDependentExistsStmt(MSDependentExistsStmt *Node) { else OS << "__if_not_exists ("; - if (NestedNameSpecifier *Qualifier - = Node->getQualifierLoc().getNestedNameSpecifier()) - Qualifier->print(OS, Policy); - + Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy); OS << Node->getNameInfo() << ") "; PrintRawCompoundStmt(Node->getSubStmt()); @@ -1309,8 +1306,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { TPOD->printAsExpr(OS, Policy); return; } - if (NestedNameSpecifier *Qualifier = Node->getQualifier()) - Qualifier->print(OS, Policy); + Node->getQualifier().print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; @@ -1359,8 +1355,7 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) { void StmtPrinter::VisitDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *Node) { - if (NestedNameSpecifier *Qualifier = Node->getQualifier()) - Qualifier->print(OS, Policy); + Node->getQualifier().print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getNameInfo(); @@ -1777,8 +1772,7 @@ void StmtPrinter::VisitMemberExpr(MemberExpr *Node) { if (FD->isAnonymousStructOrUnion()) return; - if (NestedNameSpecifier *Qualifier = Node->getQualifier()) - Qualifier->print(OS, Policy); + Node->getQualifier().print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); @@ -2176,9 +2170,7 @@ void StmtPrinter::VisitMSPropertyRefExpr(MSPropertyRefExpr *Node) { OS << "->"; else OS << "."; - if (NestedNameSpecifier *Qualifier = - Node->getQualifierLoc().getNestedNameSpecifier()) - Qualifier->print(OS, Policy); + Node->getQualifierLoc().getNestedNameSpecifier().print(OS, Policy); OS << Node->getPropertyDecl()->getDeclName(); } @@ -2570,8 +2562,7 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr( PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); } - if (NestedNameSpecifier *Qualifier = Node->getQualifier()) - Qualifier->print(OS, Policy); + Node->getQualifier().print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); @@ -2584,8 +2575,7 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { PrintExpr(Node->getBase()); OS << (Node->isArrow() ? "->" : "."); } - if (NestedNameSpecifier *Qualifier = Node->getQualifier()) - Qualifier->print(OS, Policy); + Node->getQualifier().print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); @@ -2676,8 +2666,7 @@ void StmtPrinter::VisitCXXParenListInitExpr(CXXParenListInitExpr *Node) { void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc(); - if (NNS) - NNS.getNestedNameSpecifier()->print(OS, Policy); + NNS.getNestedNameSpecifier().print(OS, Policy); if (E->getTemplateKWLoc().isValid()) OS << "template "; OS << E->getFoundDecl()->getName(); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 0297f9c38dee3..5fee88458527c 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -65,7 +65,7 @@ namespace { /// Visit a nested-name-specifier that occurs within an expression /// or statement. - virtual void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) = 0; + virtual void VisitNestedNameSpecifier(NestedNameSpecifier NNS) = 0; /// Visit a template name that occurs within an expression or /// statement. @@ -167,10 +167,10 @@ namespace { ID.AddPointer(II); } - void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { + void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override { if (Canonical) - NNS = Context.getCanonicalNestedNameSpecifier(NNS); - ID.AddPointer(NNS); + NNS = NNS.getCanonical(); + NNS.Profile(ID); } void VisitTemplateName(TemplateName Name) override { @@ -226,11 +226,10 @@ namespace { void VisitTemplateName(TemplateName Name) override { Hash.AddTemplateName(Name); } - void VisitNestedNameSpecifier(NestedNameSpecifier *NNS) override { - ID.AddBoolean(NNS); - if (NNS) { + void VisitNestedNameSpecifier(NestedNameSpecifier NNS) override { + ID.AddBoolean(bool(NNS)); + if (NNS) Hash.AddNestedNameSpecifier(NNS); - } } }; } diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index 7a0f74051d880..76050ceeb35a7 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -57,7 +57,7 @@ static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out, if (Policy.UseEnumerators) { if (const EnumType *ET = T->getAs()) { - for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) { + for (const EnumConstantDecl *ECD : ET->getOriginalDecl()->enumerators()) { // In Sema::CheckTemplateArugment, enum template arguments value are // extended to the size of the integer underlying the enum type. This // may create a size difference between the enum value and template @@ -596,6 +596,29 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, // TemplateArgumentLoc Implementation //===----------------------------------------------------------------------===// +TemplateArgumentLoc::TemplateArgumentLoc(ASTContext &Ctx, + const TemplateArgument &Argument, + SourceLocation TemplateKWLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateNameLoc, + SourceLocation EllipsisLoc) + : Argument(Argument), + LocInfo(Ctx, TemplateKWLoc, QualifierLoc, TemplateNameLoc, EllipsisLoc) { + assert(Argument.getKind() == TemplateArgument::Template || + Argument.getKind() == TemplateArgument::TemplateExpansion); + assert(QualifierLoc.getNestedNameSpecifier() == + Argument.getAsTemplateOrTemplatePattern().getQualifier()); +} + +NestedNameSpecifierLoc TemplateArgumentLoc::getTemplateQualifierLoc() const { + if (Argument.getKind() != TemplateArgument::Template && + Argument.getKind() != TemplateArgument::TemplateExpansion) + return NestedNameSpecifierLoc(); + return NestedNameSpecifierLoc( + Argument.getAsTemplateOrTemplatePattern().getQualifier(), + LocInfo.getTemplate()->QualifierLocData); +} + SourceRange TemplateArgumentLoc::getSourceRange() const { switch (Argument.getKind()) { case TemplateArgument::Expression: @@ -702,10 +725,11 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, } clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( - ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { + ASTContext &Ctx, SourceLocation TemplateKWLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, + SourceLocation EllipsisLoc) { TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo; - Template->Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template->TemplateKwLoc = TemplateKWLoc; Template->QualifierLocData = QualifierLoc.getOpaqueData(); Template->TemplateNameLoc = TemplateNameLoc; Template->EllipsisLoc = EllipsisLoc; diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 5b7abc4d038a9..c171516c38c10 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -289,10 +289,30 @@ QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const { return dyn_cast_if_present(Storage); } +QualifiedTemplateName * +TemplateName::getAsAdjustedQualifiedTemplateName() const { + for (std::optional Cur = *this; Cur; + Cur = Cur->desugar(/*IgnoreDeduced=*/true)) + if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName()) + return N; + return nullptr; +} + DependentTemplateName *TemplateName::getAsDependentTemplateName() const { return Storage.dyn_cast(); } +NestedNameSpecifier TemplateName::getQualifier() const { + for (std::optional Cur = *this; Cur; + Cur = Cur->desugar(/*IgnoreDeduced=*/true)) { + if (DependentTemplateName *N = Cur->getAsDependentTemplateName()) + return N->getQualifier(); + if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName()) + return N->getQualifier(); + } + return std::nullopt; +} + UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { if (Decl *D = Storage.dyn_cast()) if (UsingShadowDecl *USD = dyn_cast(D)) @@ -303,24 +323,21 @@ UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const { } DependentTemplateStorage::DependentTemplateStorage( - NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name, + NestedNameSpecifier Qualifier, IdentifierOrOverloadedOperator Name, bool HasTemplateKeyword) : Qualifier(Qualifier, HasTemplateKeyword), Name(Name) { - assert((!Qualifier || Qualifier->isDependent()) && + assert((!Qualifier || Qualifier.isDependent()) && "Qualifier must be dependent"); } TemplateNameDependence DependentTemplateStorage::getDependence() const { - auto D = TemplateNameDependence::DependentInstantiation; - if (NestedNameSpecifier *Qualifier = getQualifier()) - D |= toTemplateNameDependence(Qualifier->getDependence()); - return D; + return toTemplateNameDependence(getQualifier().getDependence()) | + TemplateNameDependence::DependentInstantiation; } void DependentTemplateStorage::print(raw_ostream &OS, const PrintingPolicy &Policy) const { - if (NestedNameSpecifier *NNS = getQualifier()) - NNS->print(OS, Policy); + getQualifier().print(OS, Policy); if (hasTemplateKeyword()) OS << "template "; @@ -363,16 +380,13 @@ TemplateNameDependence TemplateName::getDependence() const { case NameKind::QualifiedTemplate: { QualifiedTemplateName *S = getAsQualifiedTemplateName(); TemplateNameDependence D = S->getUnderlyingTemplate().getDependence(); - if (NestedNameSpecifier *NNS = S->getQualifier()) - D |= toTemplateNameDependence(NNS->getDependence()); + D |= toTemplateNameDependence(S->getQualifier().getDependence()); return D; } case NameKind::DependentTemplate: { DependentTemplateName *S = getAsDependentTemplateName(); - auto D = TemplateNameDependence::DependentInstantiation; - if (NestedNameSpecifier *Qualifier = S->getQualifier()) - D |= toTemplateNameDependence(Qualifier->getDependence()); - return D; + return toTemplateNameDependence(S->getQualifier().getDependence()) | + TemplateNameDependence::DependentInstantiation; } case NameKind::SubstTemplateTemplateParm: { auto *S = getAsSubstTemplateTemplateParm(); @@ -434,18 +448,20 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, Template = cast(Template->getCanonicalDecl()); if (handleAnonymousTTP(Template, OS)) return; - if (Qual == Qualified::None) + if (Qual == Qualified::None || Policy.SuppressScope) { OS << *Template; - else - Template->printQualifiedName(OS, Policy); + } else { + PrintingPolicy NestedNamePolicy = Policy; + NestedNamePolicy.SuppressUnwrittenScope = true; + Template->printQualifiedName(OS, NestedNamePolicy); + } } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { if (Policy.PrintAsCanonical) { QTN->getUnderlyingTemplate().print(OS, Policy, Qual); return; } - if (NestedNameSpecifier *NNS = QTN->getQualifier(); - Qual != Qualified::None && NNS) - NNS->print(OS, Policy); + if (Qual != Qualified::None) + QTN->getQualifier().print(OS, Policy); if (QTN->hasTemplateKeyword()) OS << "template "; diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index edc705fa25a5f..085616049373e 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1037,35 +1037,34 @@ void clang::TextNodeDumper::dumpTemplateSpecializationKind( } } -void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *NNS) { +void clang::TextNodeDumper::dumpNestedNameSpecifier(NestedNameSpecifier NNS) { if (!NNS) return; AddChild([=] { OS << "NestedNameSpecifier"; - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - OS << " Identifier"; - OS << " '" << NNS->getAsIdentifier()->getName() << "'"; - break; - case NestedNameSpecifier::Namespace: + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix(); OS << " "; // "Namespace" is printed as the decl kind. - dumpBareDeclRef(NNS->getAsNamespace()); + dumpBareDeclRef(Namespace); + dumpNestedNameSpecifier(Prefix); break; - case NestedNameSpecifier::TypeSpec: + } + case NestedNameSpecifier::Kind::Type: OS << " TypeSpec"; - dumpType(QualType(NNS->getAsType(), 0)); + dumpType(QualType(NNS.getAsType(), 0)); break; - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: OS << " Global"; break; - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::MicrosoftSuper: OS << " Super"; break; + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } - - dumpNestedNameSpecifier(NNS->getPrefix()); }); } @@ -1401,8 +1400,8 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { if (!First) OS << " -> "; - const auto *RD = - cast(Base->getType()->castAs()->getDecl()); + const auto *RD = cast( + Base->getType()->castAs()->getOriginalDecl()); if (Base->isVirtual()) OS << "virtual "; @@ -2213,7 +2212,7 @@ void TextNodeDumper::VisitTemplateSpecializationType( void TextNodeDumper::VisitInjectedClassNameType( const InjectedClassNameType *T) { - dumpDeclRef(T->getDecl()); + dumpDeclRef(T->getOriginalDecl()); } void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) { @@ -2804,8 +2803,7 @@ void TextNodeDumper::VisitTemplateTemplateParmDecl( void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) { OS << ' '; - if (D->getQualifier()) - D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + D->getQualifier().print(OS, D->getASTContext().getPrintingPolicy()); OS << D->getDeclName(); dumpNestedNameSpecifier(D->getQualifier()); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 94eb608be83e0..c382e58cb07c4 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -113,10 +113,10 @@ const IdentifierInfo *QualType::getBaseTypeIdentifier() const { return DNT->getIdentifier(); if (ty->isPointerOrReferenceType()) return ty->getPointeeType().getBaseTypeIdentifier(); - else if (ty->isRecordType()) - ND = ty->castAs()->getDecl(); + if (ty->isRecordType()) + ND = ty->castAs()->getOriginalDecl(); else if (ty->isEnumeralType()) - ND = ty->castAs()->getDecl(); + ND = ty->castAs()->getOriginalDecl(); else if (ty->getTypeClass() == Type::Typedef) ND = ty->castAs()->getDecl(); else if (ty->isArrayType()) @@ -673,13 +673,13 @@ const Type *Type::getUnqualifiedDesugaredType() const { bool Type::isClassType() const { if (const auto *RT = getAs()) - return RT->getDecl()->isClass(); + return RT->getOriginalDecl()->isClass(); return false; } bool Type::isStructureType() const { if (const auto *RT = getAs()) - return RT->getDecl()->isStruct(); + return RT->getOriginalDecl()->isStruct(); return false; } @@ -687,7 +687,7 @@ bool Type::isStructureTypeWithFlexibleArrayMember() const { const auto *RT = getAs(); if (!RT) return false; - const auto *Decl = RT->getDecl(); + const auto *Decl = RT->getOriginalDecl()->getDefinitionOrSelf(); if (!Decl->isStruct()) return false; return Decl->hasFlexibleArrayMember(); @@ -695,19 +695,21 @@ bool Type::isStructureTypeWithFlexibleArrayMember() const { bool Type::isObjCBoxableRecordType() const { if (const auto *RT = getAs()) - return RT->getDecl()->hasAttr(); + return RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasAttr(); return false; } bool Type::isInterfaceType() const { if (const auto *RT = getAs()) - return RT->getDecl()->isInterface(); + return RT->getOriginalDecl()->isInterface(); return false; } bool Type::isStructureOrClassType() const { if (const auto *RT = getAs()) { - RecordDecl *RD = RT->getDecl(); + RecordDecl *RD = RT->getOriginalDecl(); return RD->isStruct() || RD->isClass() || RD->isInterface(); } return false; @@ -721,7 +723,7 @@ bool Type::isVoidPointerType() const { bool Type::isUnionType() const { if (const auto *RT = getAs()) - return RT->getDecl()->isUnion(); + return RT->getOriginalDecl()->isUnion(); return false; } @@ -738,7 +740,7 @@ bool Type::isComplexIntegerType() const { bool Type::isScopedEnumeralType() const { if (const auto *ET = getAs()) - return ET->getDecl()->isScoped(); + return ET->getOriginalDecl()->isScoped(); return false; } @@ -772,13 +774,13 @@ QualType Type::getPointeeType() const { const RecordType *Type::getAsStructureType() const { // If this is directly a structure type, return it. if (const auto *RT = dyn_cast(this)) { - if (RT->getDecl()->isStruct()) + if (RT->getOriginalDecl()->isStruct()) return RT; } // If the canonical form of this type isn't the right kind, reject it. if (const auto *RT = dyn_cast(CanonicalType)) { - if (!RT->getDecl()->isStruct()) + if (!RT->getOriginalDecl()->isStruct()) return nullptr; // If this is a typedef for a structure type, strip the typedef off without @@ -791,13 +793,13 @@ const RecordType *Type::getAsStructureType() const { const RecordType *Type::getAsUnionType() const { // If this is directly a union type, return it. if (const auto *RT = dyn_cast(this)) { - if (RT->getDecl()->isUnion()) + if (RT->getOriginalDecl()->isUnion()) return RT; } // If the canonical form of this type isn't the right kind, reject it. if (const auto *RT = dyn_cast(CanonicalType)) { - if (!RT->getDecl()->isUnion()) + if (!RT->getOriginalDecl()->isUnion()) return nullptr; // If this is a typedef for a union type, strip the typedef off without @@ -1920,25 +1922,32 @@ const CXXRecordDecl *Type::getPointeeCXXRecordDecl() const { return nullptr; if (const auto *RT = PointeeType->getAs()) - return dyn_cast(RT->getDecl()); + return dyn_cast( + RT->getOriginalDecl()->getDefinitionOrSelf()); return nullptr; } CXXRecordDecl *Type::getAsCXXRecordDecl() const { - return dyn_cast_or_null(getAsTagDecl()); + const auto *TT = dyn_cast(CanonicalType); + if (!isa_and_present(TT)) + return nullptr; + auto *TD = TT->getOriginalDecl(); + if (!isa(TT) && !isa(TD)) + return nullptr; + return cast(TD)->getDefinitionOrSelf(); } RecordDecl *Type::getAsRecordDecl() const { - return dyn_cast_or_null(getAsTagDecl()); + const auto *TT = dyn_cast(CanonicalType); + if (!isa_and_present(TT)) + return nullptr; + return cast(TT->getOriginalDecl())->getDefinitionOrSelf(); } TagDecl *Type::getAsTagDecl() const { - if (const auto *TT = getAs()) - return TT->getDecl(); - if (const auto *Injected = getAs()) - return Injected->getDecl(); - + if (const auto *TT = dyn_cast(CanonicalType)) + return TT->getOriginalDecl()->getDefinitionOrSelf(); return nullptr; } @@ -1950,6 +1959,35 @@ Type::getAsNonAliasTemplateSpecializationType() const { return TST; } +NestedNameSpecifier Type::getPrefix() const { + switch (getTypeClass()) { + case Type::DependentName: + return cast(this)->getQualifier(); + case Type::TemplateSpecialization: { + QualifiedTemplateName *S = cast(this) + ->getTemplateName() + .getAsAdjustedQualifiedTemplateName(); + return S ? S->getQualifier() : std::nullopt; + } + case Type::DependentTemplateSpecialization: + return cast(this) + ->getDependentTemplateName() + .getQualifier(); + case Type::Enum: + case Type::Record: + case Type::InjectedClassName: + return cast(this)->getQualifier(); + case Type::Typedef: + return cast(this)->getQualifier(); + case Type::UnresolvedUsing: + return cast(this)->getQualifier(); + case Type::Using: + return cast(this)->getQualifier(); + default: + return std::nullopt; + } +} + bool Type::hasAttr(attr::Kind AK) const { const Type *Cur = this; while (const auto *AT = Cur->getAs()) { @@ -2109,7 +2147,7 @@ bool Type::isIntegralType(const ASTContext &Ctx) const { // Complete enum types are integral in C. if (!Ctx.getLangOpts().CPlusPlus) if (const auto *ET = dyn_cast(CanonicalType)) - return ET->getDecl()->isComplete(); + return IsEnumDeclComplete(ET->getOriginalDecl()); return isBitIntType(); } @@ -2126,7 +2164,7 @@ bool Type::isIntegralOrUnscopedEnumerationType() const { bool Type::isUnscopedEnumerationType() const { if (const auto *ET = dyn_cast(CanonicalType)) - return !ET->getDecl()->isScoped(); + return !ET->getOriginalDecl()->isScoped(); return false; } @@ -2211,8 +2249,10 @@ bool Type::isSignedIntegerType() const { if (const EnumType *ET = dyn_cast(CanonicalType)) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) - return ET->getDecl()->getIntegerType()->isSignedIntegerType(); + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete() || ED->isScoped()) + return false; + return ED->getIntegerType()->isSignedIntegerType(); } if (const auto *IT = dyn_cast(CanonicalType)) @@ -2227,9 +2267,12 @@ bool Type::isSignedIntegerOrEnumerationType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->isSignedInteger(); - if (const auto *ET = dyn_cast(CanonicalType); - ET && ET->getDecl()->isComplete()) - return ET->getDecl()->getIntegerType()->isSignedIntegerType(); + if (const auto *ET = dyn_cast(CanonicalType)) { + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) + return false; + return ED->getIntegerType()->isSignedIntegerType(); + } if (const auto *IT = dyn_cast(CanonicalType)) return IT->isSigned(); @@ -2256,8 +2299,10 @@ bool Type::isUnsignedIntegerType() const { if (const auto *ET = dyn_cast(CanonicalType)) { // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) - return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete() || ED->isScoped()) + return false; + return ED->getIntegerType()->isUnsignedIntegerType(); } if (const auto *IT = dyn_cast(CanonicalType)) @@ -2272,9 +2317,12 @@ bool Type::isUnsignedIntegerOrEnumerationType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->isUnsignedInteger(); - if (const auto *ET = dyn_cast(CanonicalType); - ET && ET->getDecl()->isComplete()) - return ET->getDecl()->getIntegerType()->isUnsignedIntegerType(); + if (const auto *ET = dyn_cast(CanonicalType)) { + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + if (!ED->isComplete()) + return false; + return ED->getIntegerType()->isUnsignedIntegerType(); + } if (const auto *IT = dyn_cast(CanonicalType)) return IT->isUnsigned(); @@ -2323,8 +2371,10 @@ bool Type::isRealType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Ibm128; - if (const auto *ET = dyn_cast(CanonicalType)) - return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); + if (const auto *ET = dyn_cast(CanonicalType)) { + const auto *ED = ET->getOriginalDecl(); + return !ED->isScoped() && ED->getDefinitionOrSelf()->isComplete(); + } return isBitIntType(); } @@ -2332,14 +2382,16 @@ bool Type::isArithmeticType() const { if (const auto *BT = dyn_cast(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Ibm128; - if (const auto *ET = dyn_cast(CanonicalType)) + if (const auto *ET = dyn_cast(CanonicalType)) { // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. // // C++0x: Enumerations are not arithmetic types. For now, just return // false for scoped enumerations since that will disable any // unwanted implicit conversions. - return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete(); + const auto *ED = ET->getOriginalDecl(); + return !ED->isScoped() && ED->getDefinitionOrSelf()->isComplete(); + } return isa(CanonicalType) || isBitIntType(); } @@ -2347,8 +2399,8 @@ bool Type::hasBooleanRepresentation() const { if (const auto *VT = dyn_cast(CanonicalType)) return VT->getElementType()->isBooleanType(); if (const auto *ET = dyn_cast(CanonicalType)) { - return ET->getDecl()->isComplete() && - ET->getDecl()->getIntegerType()->isBooleanType(); + const auto *ED = ET->getOriginalDecl()->getDefinitionOrSelf(); + return ED->isComplete() && ED->getIntegerType()->isBooleanType(); } if (const auto *IT = dyn_cast(CanonicalType)) return IT->getNumBits() == 1; @@ -2380,7 +2432,10 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { } else if (isa(T)) { return STK_MemberPointer; } else if (isa(T)) { - assert(cast(T)->getDecl()->isComplete()); + assert(cast(T) + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->isComplete()); return STK_Integral; } else if (const auto *CT = dyn_cast(T)) { if (CT->getElementType()->isRealFloatingType()) @@ -2404,7 +2459,8 @@ Type::ScalarTypeKind Type::getScalarTypeKind() const { /// includes union types. bool Type::isAggregateType() const { if (const auto *Record = dyn_cast(CanonicalType)) { - if (const auto *ClassDecl = dyn_cast(Record->getDecl())) + if (const auto *ClassDecl = dyn_cast( + Record->getOriginalDecl()->getDefinitionOrSelf())) return ClassDecl->isAggregate(); return true; @@ -2438,7 +2494,8 @@ bool Type::isIncompleteType(NamedDecl **Def) const { // be completed. return isVoidType(); case Enum: { - EnumDecl *EnumD = cast(CanonicalType)->getDecl(); + EnumDecl *EnumD = + cast(CanonicalType)->getOriginalDecl()->getDefinitionOrSelf(); if (Def) *Def = EnumD; return !EnumD->isComplete(); @@ -2446,13 +2503,17 @@ bool Type::isIncompleteType(NamedDecl **Def) const { case Record: { // A tagged type (struct/union/enum/class) is incomplete if the decl is a // forward declaration, but not a full definition (C99 6.2.5p22). - RecordDecl *Rec = cast(CanonicalType)->getDecl(); + RecordDecl *Rec = cast(CanonicalType) + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (Def) *Def = Rec; return !Rec->isCompleteDefinition(); } case InjectedClassName: { - CXXRecordDecl *Rec = cast(CanonicalType)->getDecl(); + CXXRecordDecl *Rec = cast(CanonicalType) + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (!Rec->isBeingDefined()) return false; if (Def) @@ -2734,9 +2795,9 @@ bool QualType::isCXX98PODType(const ASTContext &Context) const { return true; case Type::Record: - if (const auto *ClassDecl = - dyn_cast(cast(CanonicalType)->getDecl())) - return ClassDecl->isPOD(); + if (const auto *ClassDecl = dyn_cast( + cast(CanonicalType)->getOriginalDecl())) + return ClassDecl->getDefinitionOrSelf()->isPOD(); // C struct/union is POD. return true; @@ -2777,7 +2838,8 @@ bool QualType::isTrivialType(const ASTContext &Context) const { if (CanonicalType->isScalarType() || CanonicalType->isVectorType()) return true; if (const auto *RT = CanonicalType->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) { + if (const auto *ClassDecl = + dyn_cast(RT->getOriginalDecl())) { // C++20 [class]p6: // A trivial class is a class that is trivially copyable, and // has one or more eligible default constructors such that each is @@ -2836,14 +2898,17 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type, return true; if (const auto *RT = CanonicalType->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) { + if (const auto *ClassDecl = + dyn_cast(RT->getOriginalDecl())) { if (IsCopyConstructible) { return ClassDecl->isTriviallyCopyConstructible(); } else { return ClassDecl->isTriviallyCopyable(); } } - return !RT->getDecl()->isNonTrivialToPrimitiveCopy(); + return !RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->isNonTrivialToPrimitiveCopy(); } // No other types can match. return false; @@ -2933,7 +2998,9 @@ QualType::PrimitiveDefaultInitializeKind QualType::isNonTrivialToPrimitiveDefaultInitialize() const { if (const auto *RT = getTypePtr()->getBaseElementTypeUnsafe()->getAs()) - if (RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) + if (RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->isNonTrivialToPrimitiveDefaultInitialize()) return PDIK_Struct; switch (getQualifiers().getObjCLifetime()) { @@ -2949,7 +3016,9 @@ QualType::isNonTrivialToPrimitiveDefaultInitialize() const { QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const { if (const auto *RT = getTypePtr()->getBaseElementTypeUnsafe()->getAs()) - if (RT->getDecl()->isNonTrivialToPrimitiveCopy()) + if (RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->isNonTrivialToPrimitiveCopy()) return PCK_Struct; Qualifiers Qs = getQualifiers(); @@ -3017,8 +3086,8 @@ bool Type::isLiteralType(const ASTContext &Ctx) const { // -- all non-static data members and base classes of literal types // // We resolve DR1361 by ignoring the second bullet. - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) - return ClassDecl->isLiteral(); + if (const auto *ClassDecl = dyn_cast(RT->getOriginalDecl())) + return ClassDecl->getDefinitionOrSelf()->isLiteral(); return true; } @@ -3071,8 +3140,8 @@ bool Type::isStandardLayoutType() const { if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; if (const auto *RT = BaseTy->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) - if (!ClassDecl->isStandardLayout()) + if (const auto *ClassDecl = dyn_cast(RT->getOriginalDecl())) + if (!ClassDecl->getDefinitionOrSelf()->isStandardLayout()) return false; // Default to 'true' for non-C++ class types. @@ -3114,7 +3183,9 @@ bool QualType::isCXX11PODType(const ASTContext &Context) const { if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true; if (const auto *RT = BaseTy->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) { + if (const auto *ClassDecl = + dyn_cast(RT->getOriginalDecl())) { + ClassDecl = ClassDecl->getDefinitionOrSelf(); // C++11 [class]p10: // A POD struct is a non-union class that is both a trivial class [...] if (!ClassDecl->isTrivial()) @@ -3154,8 +3225,9 @@ bool Type::isNothrowT() const { bool Type::isAlignValT() const { if (const auto *ET = getAs()) { - IdentifierInfo *II = ET->getDecl()->getIdentifier(); - if (II && II->isStr("align_val_t") && ET->getDecl()->isInStdNamespace()) + const auto *ED = ET->getOriginalDecl(); + IdentifierInfo *II = ED->getIdentifier(); + if (II && II->isStr("align_val_t") && ED->isInStdNamespace()) return true; } return false; @@ -3163,8 +3235,9 @@ bool Type::isAlignValT() const { bool Type::isStdByteType() const { if (const auto *ET = getAs()) { - IdentifierInfo *II = ET->getDecl()->getIdentifier(); - if (II && II->isStr("byte") && ET->getDecl()->isInStdNamespace()) + const auto *ED = ET->getOriginalDecl(); + IdentifierInfo *II = ED->getIdentifier(); + if (II && II->isStr("byte") && ED->isInStdNamespace()) return true; } return false; @@ -4312,8 +4385,10 @@ bool RecordType::hasConstFields() const { unsigned NextToCheckIndex = 0; while (RecordTypeList.size() > NextToCheckIndex) { - for (FieldDecl *FD : - RecordTypeList[NextToCheckIndex]->getDecl()->fields()) { + for (FieldDecl *FD : RecordTypeList[NextToCheckIndex] + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) { QualType FieldTy = FD->getType(); if (FieldTy.isConstQualified()) return true; @@ -4331,15 +4406,9 @@ bool RecordType::hasConstFields() const { InjectedClassNameType::InjectedClassNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool IsInjected, - CanQualType CanonicalInjectedTST, const Type *CanonicalType) : TagType(TypeClass::InjectedClassName, Keyword, Qualifier, TD, - /*OwnsTag=*/false, IsInjected, CanonicalType), - CanonicalInjectedTST(CanonicalInjectedTST) {} - -CanQualType InjectedClassNameType::getCanonicalInjectedTST() const { - return CanQualType::CreateUnsafe(CanonicalInjectedTST); -} + /*OwnsTag=*/false, IsInjected, CanonicalType) {} AttributedType::AttributedType(QualType canon, const Attr *attr, QualType modified, QualType equivalent) @@ -4784,7 +4853,8 @@ static CachedProperties computeCachedProperties(const Type *T) { case Type::Record: case Type::Enum: { - const TagDecl *Tag = cast(T)->getDecl(); + const TagDecl *Tag = + cast(T)->getOriginalDecl()->getDefinitionOrSelf(); // C++ [basic.link]p8: // - it is a class or enumeration type that is named (or has a name @@ -4893,7 +4963,8 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { case Type::Record: case Type::Enum: - return getDeclLinkageAndVisibility(cast(T)->getDecl()); + return getDeclLinkageAndVisibility( + cast(T)->getOriginalDecl()->getDefinitionOrSelf()); case Type::Complex: return computeTypeLinkageInfo(cast(T)->getElementType()); @@ -5096,7 +5167,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { llvm_unreachable("unknown builtin type"); case Type::Record: { - const RecordDecl *RD = cast(type)->getDecl(); + const RecordDecl *RD = cast(type)->getOriginalDecl(); // For template specializations, look only at primary template attributes. // This is a consistent regardless of whether the instantiation is known. if (const auto *CTSD = dyn_cast(RD)) @@ -5294,14 +5365,18 @@ bool Type::isCARCBridgableType() const { /// Check if the specified type is the CUDA device builtin surface type. bool Type::isCUDADeviceBuiltinSurfaceType() const { if (const auto *RT = getAs()) - return RT->getDecl()->hasAttr(); + return RT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr(); return false; } /// Check if the specified type is the CUDA device builtin texture type. bool Type::isCUDADeviceBuiltinTextureType() const { if (const auto *RT = getAs()) - return RT->getDecl()->hasAttr(); + return RT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr(); return false; } @@ -5374,7 +5449,7 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { } if (const auto *RT = type->getBaseElementTypeUnsafe()->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl(); if (const auto *CXXRD = dyn_cast(RD)) { /// Check if this is a C++ object with a non-trivial destructor. if (CXXRD->hasDefinition() && !CXXRD->hasTrivialDestructor()) @@ -5392,16 +5467,16 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { bool MemberPointerType::isSugared() const { CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(), - *D2 = getQualifier()->getAsRecordDecl(); + *D2 = getQualifier().getAsRecordDecl(); assert(!D1 == !D2); return D1 != D2 && D1->getCanonicalDecl() != D2->getCanonicalDecl(); } void MemberPointerType::Profile(llvm::FoldingSetNodeID &ID, QualType Pointee, - const NestedNameSpecifier *Qualifier, + const NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) { ID.AddPointer(Pointee.getAsOpaquePtr()); - ID.AddPointer(Qualifier); + Qualifier.Profile(ID); if (Cls) ID.AddPointer(Cls->getCanonicalDecl()); } diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 8704b7466a4f5..fbe8772924465 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -303,9 +303,8 @@ bool TypeSpecTypeLoc::isKind(const TypeLoc &TL) { } bool TagTypeLoc::isDefinition() const { - TagDecl *D = getDecl(); - return D->isCompleteDefinition() && - (D->getIdentifier() == nullptr || D->getLocation() == getNameLoc()); + return getTypePtr()->isTagOwned() && + getOriginalDecl()->isCompleteDefinition(); } // Reimplemented to account for GNU/C++ extension @@ -472,6 +471,134 @@ TypeLoc TypeLoc::findExplicitQualifierLoc() const { return {}; } +NestedNameSpecifierLoc TypeLoc::getPrefix() const { + switch (getTypeLocClass()) { + case TypeLoc::DependentName: + return castAs().getQualifierLoc(); + case TypeLoc::TemplateSpecialization: + return castAs().getQualifierLoc(); + case TypeLoc::DependentTemplateSpecialization: + return castAs().getQualifierLoc(); + case TypeLoc::DeducedTemplateSpecialization: + return castAs().getQualifierLoc(); + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + return castAs().getQualifierLoc(); + case TypeLoc::Typedef: + return castAs().getQualifierLoc(); + case TypeLoc::UnresolvedUsing: + return castAs().getQualifierLoc(); + case TypeLoc::Using: + return castAs().getQualifierLoc(); + default: + return NestedNameSpecifierLoc(); + } +} + +SourceLocation TypeLoc::getNonPrefixBeginLoc() const { + switch (getTypeLocClass()) { + case TypeLoc::TemplateSpecialization: { + auto TL = castAs(); + SourceLocation Loc = TL.getTemplateKeywordLoc(); + if (!Loc.isValid()) + Loc = TL.getTemplateNameLoc(); + return Loc; + } + case TypeLoc::DependentTemplateSpecialization: { + auto TL = castAs(); + SourceLocation Loc = TL.getTemplateKeywordLoc(); + if (!Loc.isValid()) + Loc = TL.getTemplateNameLoc(); + return Loc; + } + case TypeLoc::DeducedTemplateSpecialization: { + auto TL = castAs(); + SourceLocation Loc = TL.getTemplateKeywordLoc(); + if (!Loc.isValid()) + Loc = TL.getTemplateNameLoc(); + return Loc; + } + case TypeLoc::DependentName: + return castAs().getNameLoc(); + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + return castAs().getNameLoc(); + case TypeLoc::Typedef: + return castAs().getNameLoc(); + case TypeLoc::UnresolvedUsing: + return castAs().getNameLoc(); + case TypeLoc::Using: + return castAs().getNameLoc(); + default: + return getBeginLoc(); + } +} + +SourceLocation TypeLoc::getNonElaboratedBeginLoc() const { + // For elaborated types (e.g. `struct a::A`) we want the portion after the + // `struct` but including the namespace qualifier, `a::`. + switch (getTypeLocClass()) { + case TypeLoc::Qualified: + return castAs() + .getUnqualifiedLoc() + .getNonElaboratedBeginLoc(); + case TypeLoc::TemplateSpecialization: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getTemplateNameLoc(); + } + case TypeLoc::DependentTemplateSpecialization: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getTemplateNameLoc(); + } + case TypeLoc::DeducedTemplateSpecialization: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getTemplateNameLoc(); + } + case TypeLoc::DependentName: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getNameLoc(); + } + case TypeLoc::Enum: + case TypeLoc::Record: + case TypeLoc::InjectedClassName: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getNameLoc(); + } + case TypeLoc::Typedef: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getNameLoc(); + } + case TypeLoc::UnresolvedUsing: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getNameLoc(); + } + case TypeLoc::Using: { + auto T = castAs(); + if (NestedNameSpecifierLoc QualifierLoc = T.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return T.getNameLoc(); + } + default: + return getBeginLoc(); + } +} + void ObjCTypeParamTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { setNameLoc(Loc); @@ -545,9 +672,9 @@ static void initializeElaboratedKeyword(TL T, SourceLocation Loc) { : SourceLocation()); } -static NestedNameSpecifierLoc -initializeQualifier(ASTContext &Context, NestedNameSpecifier *Qualifier, - SourceLocation Loc) { +static NestedNameSpecifierLoc initializeQualifier(ASTContext &Context, + NestedNameSpecifier Qualifier, + SourceLocation Loc) { if (!Qualifier) return NestedNameSpecifierLoc(); NestedNameSpecifierLocBuilder Builder; diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index f8082ab5b0db9..ce5870e2da690 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1640,9 +1640,11 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) { void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) { // Print the preferred name if we have one for this type. if (Policy.UsePreferredNames) { - for (const auto *PNA : T->getDecl()->specific_attrs()) { + for (const auto *PNA : T->getOriginalDecl() + ->getMostRecentDecl() + ->specific_attrs()) { if (!declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(), - T->getDecl())) + T->getOriginalDecl())) continue; // Find the outermost typedef or alias template. QualType T = PNA->getTypedefType(); diff --git a/clang/lib/AST/VTTBuilder.cpp b/clang/lib/AST/VTTBuilder.cpp index de011848a721e..85101aee97e66 100644 --- a/clang/lib/AST/VTTBuilder.cpp +++ b/clang/lib/AST/VTTBuilder.cpp @@ -64,7 +64,9 @@ void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { continue; const auto *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); CharUnits BaseOffset = Base.getBaseOffset() + @@ -90,7 +92,9 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, for (const auto &I : RD->bases()) { const auto *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Itanium C++ ABI 2.6.2: // Secondary virtual pointers are present for all bases with either @@ -154,7 +158,9 @@ void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) { for (const auto &I : RD->bases()) { const auto *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Check if this is a virtual base. if (I.isVirtual()) { diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 0001745a6ff22..6cec526ba8443 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -313,10 +313,12 @@ ComputeReturnAdjustmentBaseOffset(ASTContext &Context, } const CXXRecordDecl *DerivedRD = - cast(cast(CanDerivedReturnType)->getDecl()); + cast( + cast(CanDerivedReturnType)->getOriginalDecl()) + ->getDefinitionOrSelf(); - const CXXRecordDecl *BaseRD = - cast(cast(CanBaseReturnType)->getDecl()); + const CXXRecordDecl *BaseRD = cast( + cast(CanBaseReturnType)->getOriginalDecl()); return ComputeBaseOffset(Context, BaseRD, DerivedRD); } diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 6d0ba0b7907a1..d43d1aec71b29 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -122,15 +122,15 @@ class MatchChildASTVisitor else if (const Stmt *S = DynNode.get()) traverse(*S); else if (const NestedNameSpecifier *NNS = - DynNode.get()) + DynNode.get()) traverse(*NNS); else if (const NestedNameSpecifierLoc *NNSLoc = DynNode.get()) traverse(*NNSLoc); else if (const QualType *Q = DynNode.get()) - traverse(*Q); + traverse(*Q, /*TraverseQualifier=*/true); else if (const TypeLoc *T = DynNode.get()) - traverse(*T); + traverse(*T, /*TraverseQualifier=*/true); else if (const auto *C = DynNode.get()) traverse(*C); else if (const TemplateArgumentLoc *TALoc = @@ -194,7 +194,7 @@ class MatchChildASTVisitor } // We assume that the QualType and the contained type are on the same // hierarchy level. Thus, we try to match either of them. - bool TraverseType(QualType TypeNode) { + bool TraverseType(QualType TypeNode, bool TraverseQualifier = true) { if (TypeNode.isNull()) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -202,11 +202,11 @@ class MatchChildASTVisitor if (!match(*TypeNode)) return false; // The QualType is matched inside traverse. - return traverse(TypeNode); + return traverse(TypeNode, TraverseQualifier); } // We assume that the TypeLoc, contained QualType and contained Type all are // on the same hierarchy level. Thus, we try to match all of them. - bool TraverseTypeLoc(TypeLoc TypeLocNode) { + bool TraverseTypeLoc(TypeLoc TypeLocNode, bool TraverseQualifier = true) { if (TypeLocNode.isNull()) return true; ScopedIncrement ScopedDepth(&CurrentDepth); @@ -217,17 +217,17 @@ class MatchChildASTVisitor if (!match(TypeLocNode.getType())) return false; // The TypeLoc is matched inside traverse. - return traverse(TypeLocNode); + return traverse(TypeLocNode, TraverseQualifier); } - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { + bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS) { ScopedIncrement ScopedDepth(&CurrentDepth); - return (NNS == nullptr) || traverse(*NNS); + return !NNS || traverse(NNS); } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { if (!NNS) return true; ScopedIncrement ScopedDepth(&CurrentDepth); - if (!match(*NNS.getNestedNameSpecifier())) + if (!match(NNS.getNestedNameSpecifier())) return false; return traverse(NNS); } @@ -340,15 +340,14 @@ class MatchChildASTVisitor bool baseTraverse(const Stmt &StmtNode) { return VisitorBase::TraverseStmt(const_cast(&StmtNode)); } - bool baseTraverse(QualType TypeNode) { - return VisitorBase::TraverseType(TypeNode); + bool baseTraverse(QualType TypeNode, bool TraverseQualifier) { + return VisitorBase::TraverseType(TypeNode, TraverseQualifier); } - bool baseTraverse(TypeLoc TypeLocNode) { - return VisitorBase::TraverseTypeLoc(TypeLocNode); + bool baseTraverse(TypeLoc TypeLocNode, bool TraverseQualifier) { + return VisitorBase::TraverseTypeLoc(TypeLocNode, TraverseQualifier); } - bool baseTraverse(const NestedNameSpecifier &NNS) { - return VisitorBase::TraverseNestedNameSpecifier( - const_cast(&NNS)); + bool baseTraverse(NestedNameSpecifier NNS) { + return VisitorBase::TraverseNestedNameSpecifier(NNS); } bool baseTraverse(NestedNameSpecifierLoc NNS) { return VisitorBase::TraverseNestedNameSpecifierLoc(NNS); @@ -396,13 +395,13 @@ class MatchChildASTVisitor // Traverses the subtree rooted at 'Node'; returns true if the // traversal should continue after this function returns. - template - bool traverse(const T &Node) { + template + bool traverse(const T &Node, Args &&...args) { static_assert(IsBaseType::value, "traverse can only be instantiated with base type"); if (!match(Node)) return false; - return baseTraverse(Node); + return baseTraverse(Node, std::forward(args)...); } const DynTypedMatcher *const Matcher; @@ -501,9 +500,9 @@ class MatchASTVisitor : public RecursiveASTVisitor, bool TraverseDecl(Decl *DeclNode); bool TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue = nullptr); - bool TraverseType(QualType TypeNode); - bool TraverseTypeLoc(TypeLoc TypeNode); - bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); + bool TraverseType(QualType TypeNode, bool TraverseQualifier = true); + bool TraverseTypeLoc(TypeLoc TypeNode, bool TraverseQualifier = true); + bool TraverseNestedNameSpecifier(NestedNameSpecifier NNS); bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit); bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL); @@ -577,13 +576,13 @@ class MatchASTVisitor : public RecursiveASTVisitor, const auto *T = Proto.getTypePtr(); for (const auto &E : T->exceptions()) - TraverseType(E); + TraverseType(E, /*TraverseQualifier=*/true); if (Expr *NE = T->getNoexceptExpr()) TraverseStmt(NE, Queue); if (LE->hasExplicitResultType()) - TraverseTypeLoc(Proto.getReturnLoc()); + TraverseTypeLoc(Proto.getReturnLoc(), /*TraverseQualifier=*/true); TraverseStmt( const_cast(LE->getTrailingRequiresClause().ConstraintExpr)); } @@ -1289,33 +1288,42 @@ class MatchASTVisitor : public RecursiveASTVisitor, if (Aliases == TypeAliases.end()) return false; - if (const auto *ElaboratedTypeNode = - llvm::dyn_cast(TypeNode)) { - if (ElaboratedTypeNode->isSugared() && Aliases->second.size() > 1) { - const auto &DesugaredTypeName = - ElaboratedTypeNode->desugar().getAsString(); + auto matches = [&](const TypedefNameDecl *Alias) { + BoundNodesTreeBuilder Result(*Builder); + if (Matcher.matches(*Alias, this, &Result)) { + *Builder = std::move(Result); + return true; + } + return false; + }; - for (const TypedefNameDecl *Alias : Aliases->second) { - if (Alias->getName() != DesugaredTypeName) { - continue; - } + if (const auto *T = TypeNode->getAs()) { + const auto *TD = T->getDecl()->getCanonicalDecl(); - BoundNodesTreeBuilder Result(*Builder); - if (Matcher.matches(*Alias, this, &Result)) { - *Builder = std::move(Result); - return true; - } + // Prioritize exact matches. + SmallVector NonExactMatches; + for (const TypedefNameDecl *Alias : Aliases->second) { + if (!declaresSameEntity(TD, Alias)) { + NonExactMatches.push_back(Alias); + continue; } + if (matches(Alias)) + return true; } - } - for (const TypedefNameDecl *Alias : Aliases->second) { - BoundNodesTreeBuilder Result(*Builder); - if (Matcher.matches(*Alias, this, &Result)) { - *Builder = std::move(Result); - return true; + for (const TypedefNameDecl *Alias : NonExactMatches) { + BoundNodesTreeBuilder Result(*Builder); + if (Matcher.matches(*Alias, this, &Result)) { + *Builder = std::move(Result); + return true; + } } + return false; } + + for (const TypedefNameDecl *Alias : Aliases->second) + if (matches(Alias)) + return true; return false; } @@ -1506,12 +1514,14 @@ bool MatchASTVisitor::TraverseStmt(Stmt *StmtNode, DataRecursionQueue *Queue) { return RecursiveASTVisitor::TraverseStmt(StmtNode, Queue); } -bool MatchASTVisitor::TraverseType(QualType TypeNode) { +bool MatchASTVisitor::TraverseType(QualType TypeNode, bool TraverseQualifier) { match(TypeNode); - return RecursiveASTVisitor::TraverseType(TypeNode); + return RecursiveASTVisitor::TraverseType(TypeNode, + TraverseQualifier); } -bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { +bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode, + bool TraverseQualifier) { // The RecursiveASTVisitor only visits types if they're not within TypeLocs. // We still want to find those types via matchers, so we match them here. Note // that the TypeLocs are structurally a shadow-hierarchy to the expressed @@ -1519,11 +1529,12 @@ bool MatchASTVisitor::TraverseTypeLoc(TypeLoc TypeLocNode) { // each TypeLoc. match(TypeLocNode); match(TypeLocNode.getType()); - return RecursiveASTVisitor::TraverseTypeLoc(TypeLocNode); + return RecursiveASTVisitor::TraverseTypeLoc( + TypeLocNode, TraverseQualifier); } -bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier *NNS) { - match(*NNS); +bool MatchASTVisitor::TraverseNestedNameSpecifier(NestedNameSpecifier NNS) { + match(NNS); return RecursiveASTVisitor::TraverseNestedNameSpecifier(NNS); } @@ -1537,7 +1548,7 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( // We only match the nested name specifier here (as opposed to traversing it) // because the traversal is already done in the parallel "Loc"-hierarchy. if (NNS.hasQualifier()) - match(*NNS.getNestedNameSpecifier()); + match(NNS.getNestedNameSpecifier()); return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(NNS); } diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 80dc888811657..653b3810cb68b 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -755,6 +755,8 @@ const internal::VariadicDynCastAllOfMatcher typedefDecl; const internal::VariadicDynCastAllOfMatcher typedefNameDecl; const internal::VariadicDynCastAllOfMatcher typeAliasDecl; +const internal::VariadicDynCastAllOfMatcher + usingShadowDecl; const internal::VariadicDynCastAllOfMatcher typeAliasTemplateDecl; const internal::VariadicAllOfMatcher decl; @@ -808,8 +810,6 @@ const internal::VariadicDynCastAllOfMatcher const internal::VariadicDynCastAllOfMatcher templateSpecializationTypeLoc; -const internal::VariadicDynCastAllOfMatcher - elaboratedTypeLoc; const internal::VariadicDynCastAllOfMatcher unaryExprOrTypeTraitExpr; @@ -1103,7 +1103,6 @@ const AstTypeMatcher templateSpecializationType; const AstTypeMatcher unaryTransformType; const AstTypeMatcher recordType; const AstTypeMatcher tagType; -const AstTypeMatcher elaboratedType; const AstTypeMatcher usingType; const AstTypeMatcher substTemplateTypeParmType; const AstTypeMatcher templateTypeParmType; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 562df715e08ae..7f6a6aaed1734 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -235,8 +235,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(designatorCountIs); REGISTER_MATCHER(doStmt); REGISTER_MATCHER(eachOf); - REGISTER_MATCHER(elaboratedType); - REGISTER_MATCHER(elaboratedTypeLoc); REGISTER_MATCHER(usingType); REGISTER_MATCHER(enumConstantDecl); REGISTER_MATCHER(enumDecl); @@ -341,7 +339,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasMemberName); REGISTER_MATCHER(hasMethod); REGISTER_MATCHER(hasName); - REGISTER_MATCHER(hasNamedTypeLoc); REGISTER_MATCHER(hasNullSelector); REGISTER_MATCHER(hasObjectExpression); REGISTER_MATCHER(hasOperands); @@ -503,7 +500,6 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(memberHasSameNameAsBoundNode); REGISTER_MATCHER(memberPointerType); REGISTER_MATCHER(namedDecl); - REGISTER_MATCHER(namesType); REGISTER_MATCHER(namespaceAliasDecl); REGISTER_MATCHER(namespaceDecl); REGISTER_MATCHER(nestedNameSpecifier); @@ -593,6 +589,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(typeLoc); REGISTER_MATCHER(typedefDecl); REGISTER_MATCHER(typedefNameDecl); + REGISTER_MATCHER(usingShadowDecl); REGISTER_MATCHER(typedefType); REGISTER_MATCHER(unaryExprOrTypeTraitExpr); REGISTER_MATCHER(unaryOperator); diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 256ea18284189..f14cb43e47dd4 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -532,9 +532,11 @@ void Environment::initialize() { } else if (auto *FieldBeingInitialized = dyn_cast(Parent->getLambdaContextDecl())) { // This is in a field initializer, rather than a method. + const RecordDecl *RD = FieldBeingInitialized->getParent(); + const ASTContext &Ctx = RD->getASTContext(); + CanQualType T = Ctx.getCanonicalTagType(RD); setThisPointeeStorageLocation( - cast(createObject(QualType( - FieldBeingInitialized->getParent()->getTypeForDecl(), 0)))); + cast(createObject(T))); } else { assert(false && "Unexpected this-capturing lambda context."); } diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index c9fd9cc6bd855..026d0308921a5 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1929,7 +1929,9 @@ void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D, assert(inserted.second && "Are we visiting the same expression again?"); if (isa(Exp)) Self = Placeholder; - if (TagT->getDecl()->hasAttr()) + if (TagT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr()) Scp = CapabilityExpr(Placeholder, Exp->getType(), /*Neg=*/false); } diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index ddbd0a9ca904b..f560dd8ae1dd1 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -84,8 +84,8 @@ static std::pair classifyCapability(QualType QT) { // which it is. The type should either be a record or a typedef, or a pointer // or reference thereof. if (const auto *RT = QT->getAs()) { - if (const auto *RD = RT->getDecl()) - return classifyCapability(*RD); + if (const auto *RD = RT->getOriginalDecl()) + return classifyCapability(*RD->getDefinitionOrSelf()); } else if (const auto *TT = QT->getAs()) { if (const auto *TD = TT->getDecl()) return classifyCapability(*TD); diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index f4ead3dbe9087..1521ada90b7ce 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -182,18 +182,22 @@ class MatchDescendantVisitor : public DynamicRecursiveASTVisitor { return DynamicRecursiveASTVisitor::TraverseUnaryExprOrTypeTraitExpr(Node); } - bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) override { + bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node, + bool TraverseQualifier) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseTypeOfExprTypeLoc( + Node, TraverseQualifier); } - bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) override { + bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node, + bool TraverseQualifier) override { // Unevaluated context. if (ignoreUnevaluatedContext) return true; - return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc(Node); + return DynamicRecursiveASTVisitor::TraverseDecltypeTypeLoc( + Node, TraverseQualifier); } bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) override { diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index 3ef430e19ebd3..1604ad5bf589e 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -68,7 +68,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, return false; Members *= NElements; } else if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return false; diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 0a612d3461dc2..79dbe70a0c8eb 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -29,7 +29,7 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); ASTContext &Context = getContext(); if (const auto *EIT = Ty->getAs()) @@ -53,7 +53,7 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > @@ -105,13 +105,12 @@ llvm::Type *CodeGen::getVAListElementType(CodeGenFunction &CGF) { CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(const RecordType *RT, CGCXXABI &CXXABI) { - const CXXRecordDecl *RD = dyn_cast(RT->getDecl()); - if (!RD) { - if (!RT->getDecl()->canPassInRegisters()) - return CGCXXABI::RAA_Indirect; - return CGCXXABI::RAA_Default; - } - return CXXABI.getRecordArgABI(RD); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *CXXRD = dyn_cast(RD)) + return CXXABI.getRecordArgABI(CXXRD); + if (!RD->canPassInRegisters()) + return CGCXXABI::RAA_Indirect; + return CGCXXABI::RAA_Default; } CGCXXABI::RecordArgABI CodeGen::getRecordArgABI(QualType T, CGCXXABI &CXXABI) { @@ -125,20 +124,21 @@ bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, const ABIInfo &Info) { QualType Ty = FI.getReturnType(); - if (const auto *RT = Ty->getAs()) - if (!isa(RT->getDecl()) && - !RT->getDecl()->canPassInRegisters()) { + if (const auto *RT = Ty->getAs()) { + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (!isa(RD) && !RD->canPassInRegisters()) { FI.getReturnInfo() = Info.getNaturalAlignIndirect( Ty, Info.getDataLayout().getAllocaAddrSpace()); return true; } + } return CXXABI.classifyReturnType(FI); } QualType CodeGen::useFirstFieldIfTransparentUnion(QualType Ty) { if (const RecordType *UT = Ty->getAsUnionType()) { - const RecordDecl *UD = UT->getDecl(); + const RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); if (UD->hasAttr()) { assert(!UD->field_empty() && "sema created an empty transparent union"); return UD->field_begin()->getType(); @@ -276,7 +276,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, // according to the Itanium ABI. The exception applies only to records, // not arrays of records, so we must also check whether we stripped off an // array type above. - if (isa(RT->getDecl()) && + if (isa(RT->getOriginalDecl()) && (WasArray || (!AsIfNoUniqueAddr && !FD->hasAttr()))) return false; @@ -288,7 +288,7 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays, const RecordType *RT = T->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return false; @@ -320,7 +320,7 @@ bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) { if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { @@ -344,7 +344,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { if (!RT) return nullptr; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return nullptr; @@ -463,7 +463,7 @@ bool CodeGen::isRecordWithSIMDVectorType(ASTContext &Context, QualType Ty) { const RecordType *RT = Ty->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 0e80522536e15..cfeba6f25ac62 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -425,7 +425,8 @@ static bool isSafeForCXXConstantCapture(QualType type) { // Only records can be unsafe. if (!recordType) return true; - const auto *record = cast(recordType->getDecl()); + const auto *record = + cast(recordType->getOriginalDecl())->getDefinitionOrSelf(); // Maintain semantics for classes with non-trivial dtors or copy ctors. if (!record->hasTrivialDestructor()) return false; diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index dd26be74e561b..c7f4bf8a21354 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -1131,7 +1131,8 @@ void CGNVCUDARuntime::handleVarRegistration(const VarDecl *D, // Builtin surfaces and textures and their template arguments are // also registered with CUDA runtime. const auto *TD = cast( - D->getType()->castAs()->getDecl()); + D->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); const TemplateArgumentList &Args = TD->getTemplateArgs(); if (TD->hasAttr()) { assert(Args.size() == 2 && diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index 78a7b021855b7..f9aff893eb0f0 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -83,8 +83,9 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { if (I.isVirtual()) continue; // Skip base classes with trivial destructors. - const auto *Base = - cast(I.getType()->castAs()->getDecl()); + const auto *Base = cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (Base->hasTrivialDestructor()) continue; // If we've already found a base class with a non-trivial @@ -277,18 +278,18 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, /// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making /// indirect call to virtual functions. It makes the call through indexing /// into the vtable. -CGCallee -CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, - NestedNameSpecifier *Qual, - llvm::Type *Ty) { - assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) && +CGCallee CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD, + NestedNameSpecifier Qual, + llvm::Type *Ty) { + assert(Qual.getKind() == NestedNameSpecifier::Kind::Type && "BuildAppleKextVirtualCall - bad Qual kind"); - const Type *QTy = Qual->getAsType(); + const Type *QTy = Qual.getAsType(); QualType T = QualType(QTy, 0); const RecordType *RT = T->getAs(); assert(RT && "BuildAppleKextVirtualCall - Qual type must be record"); - const auto *RD = cast(RT->getDecl()); + const auto *RD = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (const auto *DD = dyn_cast(MD)) return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD); diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index d42e0bb814a88..cca675838644e 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -52,7 +52,7 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( const auto *RD = MPT->getMostRecentCXXRecordDecl(); ThisPtrForCall = - CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); + CGF.getAsNaturalPointerTo(This, CGF.getContext().getCanonicalTagType(RD)); const FunctionProtoType *FPT = MPT->getPointeeType()->getAs(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( @@ -106,7 +106,7 @@ CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { llvm::Constant *CGCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { return GetBogusMemberPointer(CGM.getContext().getMemberPointerType( - MD->getType(), /*Qualifier=*/nullptr, MD->getParent())); + MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent())); } llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 6e0c2c11a9f3b..b959982809911 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -125,16 +125,16 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { /// calling a method pointer. CanQualType CodeGenTypes::DeriveThisType(const CXXRecordDecl *RD, const CXXMethodDecl *MD) { - QualType RecTy; + CanQualType RecTy; if (RD) - RecTy = Context.getTagDeclType(RD)->getCanonicalTypeInternal(); + RecTy = Context.getCanonicalTagType(RD); else RecTy = Context.VoidTy; if (MD) - RecTy = Context.getAddrSpaceQualType( - RecTy, MD->getMethodQualifiers().getAddressSpace()); - return Context.getPointerType(CanQualType::CreateUnsafe(RecTy)); + RecTy = CanQualType::CreateUnsafe(Context.getAddrSpaceQualType( + RecTy, MD->getMethodQualifiers().getAddressSpace())); + return Context.getPointerType(RecTy); } /// Returns the canonical formal type of the given C++ method. @@ -1008,7 +1008,7 @@ getTypeExpansion(QualType Ty, const ASTContext &Context) { if (const RecordType *RT = Ty->getAs()) { SmallVector Bases; SmallVector Fields; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); assert(!RD->hasFlexibleArrayMember() && "Cannot expand structure with flexible array."); if (RD->isUnion()) { @@ -1895,7 +1895,7 @@ bool CodeGenModule::MayDropFunctionReturn(const ASTContext &Context, // complex destructor or a non-trivially copyable type. if (const RecordType *RT = ReturnType.getCanonicalType()->getAs()) { - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) + if (const auto *ClassDecl = dyn_cast(RT->getOriginalDecl())) return ClassDecl->hasTrivialDestructor(); } return ReturnType.isTriviallyCopyableType(Context); @@ -2870,7 +2870,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, // (e.g., Obj-C ARC-managed structs, MSVC callee-destroyed objects). if (!ParamType.isDestructedType() || !ParamType->isRecordType() || ParamType->castAs() - ->getDecl() + ->getOriginalDecl() + ->getDefinitionOrSelf() ->isParamDestroyedInCallee()) Attrs.addAttribute(llvm::Attribute::DeadOnReturn); } @@ -3828,7 +3829,7 @@ static void setUsedBits(CodeGenModule &CGM, const RecordType *RTy, int Offset, SmallVectorImpl &Bits) { ASTContext &Context = CGM.getContext(); int CharWidth = Context.getCharWidth(); - const RecordDecl *RD = RTy->getDecl()->getDefinition(); + const RecordDecl *RD = RTy->getOriginalDecl()->getDefinition(); const ASTRecordLayout &ASTLayout = Context.getASTRecordLayout(RD); const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(RD); @@ -4289,7 +4290,10 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, // Deactivate the cleanup for the callee-destructed param that was pushed. if (type->isRecordType() && !CurFuncIsThunk && - type->castAs()->getDecl()->isParamDestroyedInCallee() && + type->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->isParamDestroyedInCallee() && param->needsDestruction(getContext())) { EHScopeStack::stable_iterator cleanup = CalleeDestructedParamCleanups.lookup(cast(param)); @@ -4882,8 +4886,10 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, // In the Microsoft C++ ABI, aggregate arguments are destructed by the callee. // However, we still have to push an EH-only cleanup in case we unwind before // we make it to the call. - if (type->isRecordType() && - type->castAs()->getDecl()->isParamDestroyedInCallee()) { + if (type->isRecordType() && type->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->isParamDestroyedInCallee()) { // If we're using inalloca, use the argument memory. Otherwise, use a // temporary. AggValueSlot Slot = args.isUsingInAlloca() diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 4a465e6526da0..e9a92ae0f01cb 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -181,7 +181,9 @@ CharUnits CodeGenModule::computeNonVirtualBaseClassOffset( const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const auto *BaseDecl = - cast(Base->getType()->castAs()->getDecl()); + cast( + Base->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Add the offset. Offset += Layout.getBaseClassOffset(BaseDecl); @@ -301,7 +303,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( // and hence will not require any further steps. if ((*Start)->isVirtual()) { VBase = cast( - (*Start)->getType()->castAs()->getDecl()); + (*Start)->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); ++Start; } @@ -326,7 +329,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::Type *PtrTy = llvm::PointerType::get( CGM.getLLVMContext(), Value.getType()->getPointerAddressSpace()); - QualType DerivedTy = getContext().getRecordType(Derived); + CanQualType DerivedTy = getContext().getCanonicalTagType(Derived); CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived); // If the static offset is zero and we don't have a virtual step, @@ -401,8 +404,7 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, bool NullCheckValue) { assert(PathBegin != PathEnd && "Base path should not be empty!"); - QualType DerivedTy = - getContext().getCanonicalType(getContext().getTagDeclType(Derived)); + CanQualType DerivedTy = getContext().getCanonicalTagType(Derived); llvm::Type *DerivedValueTy = ConvertType(DerivedTy); llvm::Value *NonVirtualOffset = @@ -559,7 +561,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, const Type *BaseType = BaseInit->getBaseClass(); const auto *BaseClassDecl = - cast(BaseType->castAs()->getDecl()); + cast(BaseType->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); bool isBaseVirtual = BaseInit->isBaseVirtual(); @@ -638,7 +641,7 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, QualType FieldType = Field->getType(); llvm::Value *ThisPtr = CGF.LoadCXXThis(); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); + CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl); LValue LHS; // If a base constructor is being emitted, create an LValue that has the @@ -974,7 +977,7 @@ namespace { } CharUnits MemcpySize = getMemcpySize(FirstByteOffset); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); + CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl); Address ThisPtr = CGF.LoadCXXThisAddress(); LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy); LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField); @@ -1122,7 +1125,7 @@ namespace { void pushEHDestructors() { Address ThisPtr = CGF.LoadCXXThisAddress(); - QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl); + CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl); LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy); for (unsigned i = 0; i < AggregatedInits.size(); ++i) { @@ -1265,7 +1268,8 @@ namespace { static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) { const Type *BaseType = BaseInit->getBaseClass(); const auto *BaseClassDecl = - cast(BaseType->castAs()->getDecl()); + cast(BaseType->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); return BaseClassDecl->isDynamicClass(); } @@ -1374,7 +1378,9 @@ HasTrivialDestructorBody(ASTContext &Context, continue; const CXXRecordDecl *NonVirtualBase = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!HasTrivialDestructorBody(Context, NonVirtualBase, MostDerivedClassDecl)) return false; @@ -1383,8 +1389,10 @@ HasTrivialDestructorBody(ASTContext &Context, if (BaseClassDecl == MostDerivedClassDecl) { // Check virtual bases. for (const auto &I : BaseClassDecl->vbases()) { - const CXXRecordDecl *VirtualBase = - cast(I.getType()->castAs()->getDecl()); + const auto *VirtualBase = + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!HasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl)) return false; @@ -1404,7 +1412,8 @@ FieldHasTrivialDestructorBody(ASTContext &Context, if (!RT) return true; - CXXRecordDecl *FieldClassDecl = cast(RT->getDecl()); + auto *FieldClassDecl = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); // The destructor for an implicit anonymous union member is never invoked. if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) @@ -1588,7 +1597,7 @@ namespace { const CXXRecordDecl *ClassDecl = Dtor->getParent(); CGF.EmitDeleteCall(Dtor->getOperatorDelete(), LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); + CGF.getContext().getCanonicalTagType(ClassDecl)); } }; @@ -1606,7 +1615,7 @@ namespace { const CXXRecordDecl *ClassDecl = Dtor->getParent(); CGF.EmitDeleteCall(Dtor->getOperatorDelete(), LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); + CGF.getContext().getCanonicalTagType(ClassDecl)); assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() == ReturnAfterDelete && "unexpected value for ReturnAfterDelete"); @@ -1647,7 +1656,8 @@ namespace { void Emit(CodeGenFunction &CGF, Flags flags) override { // Find the address of the field. Address thisValue = CGF.LoadCXXThisAddress(); - QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent()); + CanQualType RecordTy = + CGF.getContext().getCanonicalTagType(field->getParent()); LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy); LValue LV = CGF.EmitLValueForField(ThisLV, field); assert(LV.isSimple()); @@ -1870,7 +1880,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, const CXXRecordDecl *ClassDecl = DD->getParent(); EmitDeleteCall(DD->getOperatorDelete(), LoadThisForDtorDelete(*this, DD), - getContext().getTagDeclType(ClassDecl)); + getContext().getCanonicalTagType(ClassDecl)); EmitBranchThroughCleanup(ReturnBlock); } else { EHStack.pushCleanup(NormalAndEHCleanup); @@ -1898,7 +1908,9 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, // the reverse order. for (const auto &Base : ClassDecl->vbases()) { auto *BaseClassDecl = - cast(Base.getType()->castAs()->getDecl()); + cast( + Base.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (BaseClassDecl->hasTrivialDestructor()) { // Under SanitizeMemoryUseAfterDtor, poison the trivial base class @@ -1964,7 +1976,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, // Anonymous union members do not have their destructors called. const RecordType *RT = type->getAsUnionType(); - if (RT && RT->getDecl()->isAnonymousStructOrUnion()) + if (RT && RT->getOriginalDecl()->isAnonymousStructOrUnion()) continue; CleanupKind cleanupKind = getCleanupKind(dtorKind); @@ -2057,7 +2069,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // // Note that these are complete objects and so we don't need to // use the non-virtual size or alignment. - QualType type = getContext().getTypeDeclType(ctor->getParent()); + CanQualType type = getContext().getCanonicalTagType(ctor->getParent()); CharUnits eltAlignment = arrayBase.getAlignment() .alignmentOfArrayElement(getContext().getTypeSizeInChars(type)); @@ -2119,7 +2131,8 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, Address addr, QualType type) { const RecordType *rtype = type->castAs(); - const CXXRecordDecl *record = cast(rtype->getDecl()); + const auto *record = + cast(rtype->getOriginalDecl())->getDefinitionOrSelf(); const CXXDestructorDecl *dtor = record->getDestructor(); assert(!dtor->isTrivial()); CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, @@ -2158,7 +2171,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const Expr *Arg = E->getArg(0); LValue Src = EmitLValue(Arg); - QualType DestTy = getContext().getTypeDeclType(D->getParent()); + CanQualType DestTy = getContext().getCanonicalTagType(D->getParent()); LValue Dest = MakeAddrLValue(This, DestTy); EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap()); return; @@ -2210,7 +2223,8 @@ void CodeGenFunction::EmitCXXConstructorCall( if (!NewPointerIsChecked) EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, - getContext().getRecordType(ClassDecl), CharUnits::Zero()); + getContext().getCanonicalTagType(ClassDecl), + CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { assert(Args.size() == 1 && "trivial default ctor with args"); @@ -2226,7 +2240,7 @@ void CodeGenFunction::EmitCXXConstructorCall( Address Src = makeNaturalAddressForPointer( Args[1].getRValue(*this).getScalarVal(), SrcTy); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); - QualType DestTy = getContext().getTypeDeclType(ClassDecl); + CanQualType DestTy = getContext().getCanonicalTagType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap); return; @@ -2638,8 +2652,9 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base, // Traverse bases. for (const auto &I : RD->bases()) { - auto *BaseDecl = - cast(I.getType()->castAs()->getDecl()); + auto *BaseDecl = cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Ignore classes without a vtable. if (!BaseDecl->isDynamicClass()) @@ -2772,7 +2787,7 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD, // Don't insert type test assumes if we are forcing public // visibility. !CGM.AlwaysHasLTOVisibilityPublic(RD)) { - QualType Ty = QualType(RD->getTypeForDecl(), 0); + CanQualType Ty = CGM.getContext().getCanonicalTagType(RD); llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty); llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); @@ -2839,7 +2854,8 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (!ClassTy) return; - const CXXRecordDecl *ClassDecl = cast(ClassTy->getDecl()); + const auto *ClassDecl = + cast(ClassTy->getOriginalDecl())->getDefinitionOrSelf(); if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass()) return; @@ -2896,8 +2912,8 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, EmitSanitizerStatReport(SSK); - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); + CanQualType T = CGM.getContext().getCanonicalTagType(RD); + llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T); llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD); llvm::Value *TypeTest = Builder.CreateCall( @@ -2906,7 +2922,7 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Constant *StaticData[] = { llvm::ConstantInt::get(Int8Ty, TCK), EmitCheckSourceLocation(Loc), - EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)), + EmitCheckTypeDescriptor(T), }; auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD); @@ -2956,8 +2972,8 @@ llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad( EmitSanitizerStatReport(llvm::SanStat_CFI_VCall); - llvm::Metadata *MD = - CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); + CanQualType T = CGM.getContext().getCanonicalTagType(RD); + llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(T); llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD); auto CheckedLoadIntrinsic = CGM.getVTables().useRelativeLayout() @@ -3039,7 +3055,8 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { // Start building arguments for forwarding call CallArgList CallArgs; - QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); + CanQualType ThisType = + getContext().getPointerType(getContext().getCanonicalTagType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); @@ -3066,8 +3083,8 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { // Start building arguments for forwarding call CallArgList CallArgs; - QualType LambdaType = getContext().getRecordType(Lambda); - QualType ThisType = getContext().getPointerType(LambdaType); + CanQualType LambdaType = getContext().getCanonicalTagType(Lambda); + CanQualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); @@ -3118,8 +3135,8 @@ void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) { // Forward %this argument. CallArgList CallArgs; - QualType LambdaType = getContext().getRecordType(MD->getParent()); - QualType ThisType = getContext().getPointerType(LambdaType); + CanQualType LambdaType = getContext().getCanonicalTagType(MD->getParent()); + CanQualType ThisType = getContext().getPointerType(LambdaType); llvm::Value *ThisArg = CurFn->getArg(0); CallArgs.add(RValue::get(ThisArg), ThisType); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 2b469f2e265b4..994bdbdae860f 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -366,7 +366,7 @@ llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context, if (const auto *RDecl = dyn_cast(Context)) if (!RDecl->isDependentType()) - return getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), + return getOrCreateType(CGM.getContext().getCanonicalTagType(RDecl), TheCU->getFile()); return Default; } @@ -1285,7 +1285,7 @@ static bool needsTypeIdentifier(const TagDecl *TD, CodeGenModule &CGM, static SmallString<256> getTypeIdentifier(const TagType *Ty, CodeGenModule &CGM, llvm::DICompileUnit *TheCU) { SmallString<256> Identifier; - const TagDecl *TD = Ty->getDecl(); + const TagDecl *TD = Ty->getOriginalDecl()->getDefinitionOrSelf(); if (!needsTypeIdentifier(TD, CGM, TheCU)) return Identifier; @@ -1321,8 +1321,8 @@ static llvm::dwarf::Tag getTagForRecord(const RecordDecl *RD) { llvm::DICompositeType * CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, llvm::DIScope *Ctx) { - const RecordDecl *RD = Ty->getDecl(); - if (llvm::DIType *T = getTypeOrNull(CGM.getContext().getRecordType(RD))) + const RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); + if (llvm::DIType *T = getTypeOrNull(QualType(Ty, 0))) return cast(T); llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); const unsigned Line = @@ -2015,6 +2015,8 @@ void CGDebugInfo::CollectRecordNestedType( const TypeDecl *TD, SmallVectorImpl &elements) { QualType Ty = CGM.getContext().getTypeDeclType(TD); // Injected class names are not considered nested records. + // FIXME: Is this supposed to be testing for injected class name declarations + // instead? if (isa(Ty)) return; SourceLocation Loc = TD->getLocation(); @@ -2356,7 +2358,9 @@ void CGDebugInfo::CollectCXXBasesAux( const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (const auto &BI : Bases) { const auto *Base = - cast(BI.getType()->castAs()->getDecl()); + cast( + BI.getType()->castAs()->getOriginalDecl()) + ->getDefinition(); if (!SeenTypes.insert(Base).second) continue; auto *BaseTy = getOrCreateType(BI.getType(), Unit); @@ -2825,12 +2829,12 @@ void CGDebugInfo::addHeapAllocSiteMetadata(llvm::CallBase *CI, void CGDebugInfo::completeType(const EnumDecl *ED) { if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly) return; - QualType Ty = CGM.getContext().getEnumType(ED); + CanQualType Ty = CGM.getContext().getCanonicalTagType(ED); void *TyPtr = Ty.getAsOpaquePtr(); auto I = TypeCache.find(TyPtr); if (I == TypeCache.end() || !cast(I->second)->isForwardDecl()) return; - llvm::DIType *Res = CreateTypeDefinition(Ty->castAs()); + llvm::DIType *Res = CreateTypeDefinition(dyn_cast(Ty)); assert(!Res->isForwardDecl()); TypeCache[TyPtr].reset(Res); } @@ -2900,7 +2904,7 @@ void CGDebugInfo::completeClassData(const RecordDecl *RD) { void CGDebugInfo::completeClass(const RecordDecl *RD) { if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly) return; - QualType Ty = CGM.getContext().getRecordType(RD); + CanQualType Ty = CGM.getContext().getCanonicalTagType(RD); void *TyPtr = Ty.getAsOpaquePtr(); auto I = TypeCache.find(TyPtr); if (I != TypeCache.end() && !cast(I->second)->isForwardDecl()) @@ -2909,7 +2913,7 @@ void CGDebugInfo::completeClass(const RecordDecl *RD) { // We want the canonical definition of the structure to not // be the typedef. Since that would lead to circular typedef // metadata. - auto [Res, PrefRes] = CreateTypeDefinition(Ty->castAs()); + auto [Res, PrefRes] = CreateTypeDefinition(dyn_cast(Ty)); assert(!Res->isForwardDecl()); TypeCache[TyPtr].reset(Res); } @@ -3013,14 +3017,14 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) return; - QualType Ty = CGM.getContext().getRecordType(RD); + CanQualType Ty = CGM.getContext().getCanonicalTagType(RD); llvm::DIType *T = getTypeOrNull(Ty); if (T && T->isForwardDecl()) completeClassData(RD); } llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); + RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); llvm::DIType *T = cast_or_null(getTypeOrNull(QualType(Ty, 0))); if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) { @@ -3048,7 +3052,7 @@ llvm::DIType *CGDebugInfo::GetPreferredNameType(const CXXRecordDecl *RD, std::pair CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); + RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. llvm::DIFile *DefUnit = getOrCreateFile(RD->getLocation()); @@ -3070,7 +3074,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Push the struct on region stack. LexicalBlockStack.emplace_back(&*FwdDecl); - RegionMap[Ty->getDecl()].reset(FwdDecl); + RegionMap[RD].reset(FwdDecl); // Convert all the elements. SmallVector EltTys; @@ -3092,7 +3096,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); - RegionMap.erase(Ty->getDecl()); + RegionMap.erase(RD); llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); DBuilder.replaceArrays(FwdDecl, Elements); @@ -3101,7 +3105,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { FwdDecl = llvm::MDNode::replaceWithPermanent(llvm::TempDICompositeType(FwdDecl)); - RegionMap[Ty->getDecl()].reset(FwdDecl); + RegionMap[RD].reset(FwdDecl); if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::LLDB) if (auto *PrefDI = GetPreferredNameType(CXXDecl, DefUnit)) @@ -3651,8 +3655,9 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, } } - llvm::DIType *ClassType = getOrCreateType( - QualType(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0), U); + CanQualType T = + CGM.getContext().getCanonicalTagType(Ty->getMostRecentCXXRecordDecl()); + llvm::DIType *ClassType = getOrCreateType(T, U); if (Ty->isMemberDataPointerType()) return DBuilder.createMemberPointerType( getOrCreateType(Ty->getPointeeType(), U), ClassType, Size, /*Align=*/0, @@ -3687,17 +3692,21 @@ llvm::DIType *CGDebugInfo::CreateType(const HLSLInlineSpirvType *Ty, return nullptr; } -llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { - const EnumDecl *ED = Ty->getDecl(); +static auto getEnumInfo(CodeGenModule &CGM, llvm::DICompileUnit *TheCU, + const EnumType *Ty) { + const EnumDecl *ED = Ty->getOriginalDecl()->getDefinitionOrSelf(); uint64_t Size = 0; uint32_t Align = 0; - if (!ED->getTypeForDecl()->isIncompleteType()) { - Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); + if (ED->isComplete()) { + Size = CGM.getContext().getTypeSize(QualType(Ty, 0)); Align = getDeclAlignIfRequired(ED, CGM.getContext()); } + return std::make_tuple(ED, Size, Align, getTypeIdentifier(Ty, CGM, TheCU)); +} - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); +llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { + auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty); bool isImportedFromModule = DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition(); @@ -3732,15 +3741,7 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { } llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) { - const EnumDecl *ED = Ty->getDecl(); - uint64_t Size = 0; - uint32_t Align = 0; - if (!ED->getTypeForDecl()->isIncompleteType()) { - Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); - Align = getDeclAlignIfRequired(ED, CGM.getContext()); - } - - SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU); + auto [ED, Size, Align, Identifier] = getEnumInfo(CGM, TheCU, Ty); SmallVector Enumerators; ED = ED->getDefinition(); @@ -3815,6 +3816,11 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { switch (T->getTypeClass()) { default: return C.getQualifiedType(T.getTypePtr(), Quals); + case Type::Enum: + case Type::Record: + case Type::InjectedClassName: + return C.getQualifiedType(T->getCanonicalTypeUnqualified().getTypePtr(), + Quals); case Type::TemplateSpecialization: { const auto *Spec = cast(T); if (Spec->isTypeAlias()) @@ -3843,11 +3849,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::CountAttributed: T = cast(T)->desugar(); break; - case Type::Elaborated: - T = cast(T)->getNamedType(); - break; case Type::Using: - T = cast(T)->getUnderlyingType(); + T = cast(T)->desugar(); break; case Type::Paren: T = cast(T)->getInnerType(); @@ -3906,7 +3909,8 @@ void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) { completeClassData(&D); // In case this type has no member function definitions being emitted, ensure // it is retained - RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr()); + RetainedTypes.push_back( + CGM.getContext().getCanonicalTagType(&D).getAsOpaquePtr()); } llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { @@ -4051,7 +4055,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Adjusted: case Type::Decayed: case Type::DeducedTemplateSpecialization: - case Type::Elaborated: case Type::Using: case Type::Paren: case Type::MacroQualified: @@ -4094,7 +4097,7 @@ CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty) { // TODO: Currently used for context chains when limiting debug info. llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { - RecordDecl *RD = Ty->getDecl(); + RecordDecl *RD = Ty->getOriginalDecl()->getDefinitionOrSelf(); // Get overall information about the record type for the debug info. StringRef RDName = getClassName(RD); @@ -4111,7 +4114,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { // If we ended up creating the type during the context chain construction, // just return that. auto *T = cast_or_null( - getTypeOrNull(CGM.getContext().getRecordType(RD))); + getTypeOrNull(CGM.getContext().getCanonicalTagType(RD))); if (T && (!T->isForwardDecl() || !RD->getDefinition())) return T; @@ -4181,7 +4184,7 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { break; } - RegionMap[Ty->getDecl()].reset(RealDecl); + RegionMap[RD].reset(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); if (const auto *TSpecial = dyn_cast(RD)) @@ -4205,8 +4208,8 @@ void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD, else break; } - ContainingType = getOrCreateType(QualType(PBase->getTypeForDecl(), 0), - getOrCreateFile(RD->getLocation())); + CanQualType T = CGM.getContext().getCanonicalTagType(PBase); + ContainingType = getOrCreateType(T, getOrCreateFile(RD->getLocation())); } else if (RD->isDynamicClass()) ContainingType = RealDecl; @@ -4412,9 +4415,10 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { // we would otherwise do to get a type for a pointee. (forward declarations in // limited debug info, full definitions (if the type definition is available) // in unlimited debug info) - if (const auto *TD = dyn_cast(D)) - return getOrCreateType(CGM.getContext().getTypeDeclType(TD), - getOrCreateFile(TD->getLocation())); + if (const auto *TD = dyn_cast(D)) { + QualType Ty = CGM.getContext().getTypeDeclType(TD); + return getOrCreateType(Ty, getOrCreateFile(TD->getLocation())); + } auto I = DeclCache.find(D->getCanonicalDecl()); if (I != DeclCache.end()) { @@ -5076,7 +5080,7 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, } else if (const auto *RT = dyn_cast(VD->getType())) { // If VD is an anonymous union then Storage represents value for // all union fields. - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion() && RD->isAnonymousStructOrUnion()) { // GDB has trouble finding local variables in anonymous unions, so we emit // artificial local variables for each of the members. @@ -5536,7 +5540,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, cast_or_null(blockDecl->getNonClosureContext())) type = Method->getThisType(); else if (auto *RDecl = dyn_cast(blockDecl->getParent())) - type = QualType(RDecl->getTypeForDecl(), 0); + type = CGM.getContext().getCanonicalTagType(RDecl); else llvm_unreachable("unexpected block declcontext"); @@ -5626,8 +5630,9 @@ llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( // Ignore unnamed fields, but recurse into anonymous records. if (FieldName.empty()) { if (const auto *RT = dyn_cast(Field->getType())) - GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName, - Var, DContext); + GVE = + CollectAnonRecordDecls(RT->getOriginalDecl()->getDefinitionOrSelf(), + Unit, LineNo, LinkageName, Var, DContext); continue; } // Use VarDecl's Tag, Scope and Line number. @@ -5646,7 +5651,7 @@ static bool ReferencesAnonymousEntity(RecordType *RT) { // But so long as it's not one of those, it doesn't matter if some sub-type // of the record (a template parameter) can't be reconstituted - because the // un-reconstitutable type itself will carry its own name. - const auto *RD = dyn_cast(RT->getDecl()); + const auto *RD = dyn_cast(RT->getOriginalDecl()); if (!RD) return false; if (!RD->getIdentifier()) @@ -5705,15 +5710,15 @@ struct ReconstitutableType : public RecursiveASTVisitor { } return true; } - bool TraverseEnumType(EnumType *ET) { + bool TraverseEnumType(EnumType *ET, bool = false) { // Unnamed enums can't be reconstituted due to a lack of column info we // produce in the DWARF, so we can't get Clang's full name back. - if (const auto *ED = dyn_cast(ET->getDecl())) { + if (const auto *ED = dyn_cast(ET->getOriginalDecl())) { if (!ED->getIdentifier()) { Reconstitutable = false; return false; } - if (!ED->isExternallyVisible()) { + if (!ED->getDefinitionOrSelf()->isExternallyVisible()) { Reconstitutable = false; return false; } @@ -5726,7 +5731,7 @@ struct ReconstitutableType : public RecursiveASTVisitor { Reconstitutable &= !FT->getNoReturnAttr(); return Reconstitutable; } - bool VisitRecordType(RecordType *RT) { + bool VisitRecordType(RecordType *RT, bool = false) { if (ReferencesAnonymousEntity(RT)) { Reconstitutable = false; return false; @@ -5909,7 +5914,8 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, // variable for each member of the anonymous union so that it's possible // to find the name of any field in the union. if (T->isUnionType() && DeclName.empty()) { - const RecordDecl *RD = T->castAs()->getDecl(); + const RecordDecl *RD = + T->castAs()->getOriginalDecl()->getDefinitionOrSelf(); assert(RD->isAnonymousStructOrUnion() && "unnamed non-anonymous struct or union?"); GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext); @@ -5956,8 +5962,6 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { if (const auto *ECD = dyn_cast(VD)) { const auto *ED = cast(ECD->getDeclContext()); - assert(isa(ED->getTypeForDecl()) && "Enum without EnumType?"); - if (CGM.getCodeGenOpts().EmitCodeView) { // If CodeView, emit enums as global variables, unless they are defined // inside a class. We do this because MSVC doesn't emit S_CONSTANTs for @@ -5969,10 +5973,9 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { // If not CodeView, emit DW_TAG_enumeration_type if necessary. For // example: for "enum { ZERO };", a DW_TAG_enumeration_type is created the // first time `ZERO` is referenced in a function. - llvm::DIType *EDTy = - getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit); - assert (EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type); - (void)EDTy; + CanQualType T = CGM.getContext().getCanonicalTagType(ED); + [[maybe_unused]] llvm::DIType *EDTy = getOrCreateType(T, Unit); + assert(EDTy->getTag() == llvm::dwarf::DW_TAG_enumeration_type); return; } } @@ -5991,7 +5994,7 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { // FIXME: This is probably unnecessary, since Ty should reference RD // through its scope. RetainedTypes.push_back( - CGM.getContext().getRecordType(RD).getAsOpaquePtr()); + CGM.getContext().getCanonicalTagType(RD).getAsOpaquePtr()); return; } diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 0cade0d4379e2..9df1220c78623 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -113,12 +113,14 @@ void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) { case Decl::CXXRecord: // struct/union/class X; [C++] if (CGDebugInfo *DI = getDebugInfo()) if (cast(D).getDefinition()) - DI->EmitAndRetainType(getContext().getRecordType(cast(&D))); + DI->EmitAndRetainType( + getContext().getCanonicalTagType(cast(&D))); return; case Decl::Enum: // enum X; if (CGDebugInfo *DI = getDebugInfo()) if (cast(D).getDefinition()) - DI->EmitAndRetainType(getContext().getEnumType(cast(&D))); + DI->EmitAndRetainType( + getContext().getCanonicalTagType(cast(&D))); return; case Decl::Function: // void X(); case Decl::EnumConstant: // enum ? { X = ? } @@ -1568,7 +1570,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { ; if (const RecordType *RecordTy = Ty->getAs()) { - const auto *RD = RecordTy->getDecl(); + const auto *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); const auto *CXXRD = dyn_cast(RD); if ((CXXRD && !CXXRD->hasTrivialDestructor()) || RD->isNonTrivialToPrimitiveDestroy()) { @@ -2727,7 +2729,10 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Don't push a cleanup in a thunk for a method that will also emit a // cleanup. if (Ty->isRecordType() && !CurFuncIsThunk && - Ty->castAs()->getDecl()->isParamDestroyedInCallee()) { + Ty->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->isParamDestroyedInCallee()) { if (QualType::DestructionKind DtorKind = D.needsDestruction(getContext())) { assert((DtorKind == QualType::DK_cxx_destructor || diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index f1affef756df5..d5df6dd3e303c 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -408,9 +408,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, if (const RecordType *RT = E->getType()->getBaseElementTypeUnsafe()->getAs()) { // Get the destructor for the reference temporary. - if (auto *ClassDecl = dyn_cast(RT->getDecl()); + if (auto *ClassDecl = dyn_cast(RT->getOriginalDecl()); ClassDecl && !ClassDecl->hasTrivialDestructor()) - ReferenceTemporaryDtor = ClassDecl->getDestructor(); + ReferenceTemporaryDtor = + ClassDecl->getDefinitionOrSelf()->getDestructor(); } if (!ReferenceTemporaryDtor) @@ -1204,9 +1205,10 @@ llvm::Value *CodeGenFunction::GetCountedByFieldExprGEP( return nullptr; Indices.push_back(Builder.getInt32(0)); - return Builder.CreateInBoundsGEP( - ConvertType(QualType(RD->getTypeForDecl(), 0)), Res, - RecIndicesTy(llvm::reverse(Indices)), "counted_by.gep"); + CanQualType T = CGM.getContext().getCanonicalTagType(RD); + return Builder.CreateInBoundsGEP(ConvertType(T), Res, + RecIndicesTy(llvm::reverse(Indices)), + "counted_by.gep"); } /// This method is typically called in contexts where we can't generate @@ -1754,9 +1756,11 @@ static bool isConstantEmittableObjectType(QualType type) { // Otherwise, all object types satisfy this except C++ classes with // mutable subobjects or non-trivial copy/destroy behavior. if (const auto *RT = dyn_cast(type)) - if (const auto *RD = dyn_cast(RT->getDecl())) + if (const auto *RD = dyn_cast(RT->getOriginalDecl())) { + RD = RD->getDefinitionOrSelf(); if (RD->hasMutableFields() || !RD->isTrivial()) return false; + } return true; } @@ -1917,8 +1921,10 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty, llvm::APInt &Min, llvm::APInt &End, bool StrictEnums, bool IsBool) { const EnumType *ET = Ty->getAs(); - bool IsRegularCPlusPlusEnum = CGF.getLangOpts().CPlusPlus && StrictEnums && - ET && !ET->getDecl()->isFixed(); + const EnumDecl *ED = + ET ? ET->getOriginalDecl()->getDefinitionOrSelf() : nullptr; + bool IsRegularCPlusPlusEnum = + CGF.getLangOpts().CPlusPlus && StrictEnums && ET && !ED->isFixed(); if (!IsBool && !IsRegularCPlusPlusEnum) return false; @@ -1926,7 +1932,6 @@ static bool getRangeForType(CodeGenFunction &CGF, QualType Ty, Min = llvm::APInt(CGF.getContext().getTypeSize(Ty), 0); End = llvm::APInt(CGF.getContext().getTypeSize(Ty), 2); } else { - const EnumDecl *ED = ET->getDecl(); ED->getValueRange(End, Min); } return true; @@ -4302,7 +4307,9 @@ static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) { const auto *PointeeT = PtrT->getPointeeType() ->getUnqualifiedDesugaredType(); if (const auto *RecT = dyn_cast(PointeeT)) - return RecT->getDecl()->hasAttr(); + return RecT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr(); return false; } @@ -5068,10 +5075,12 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, Address Base = GetAddressOfBaseClass( LambdaLV.getAddress(), ThisTy, BasePathArray.begin(), BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation()); - LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0}); + CanQualType T = getContext().getCanonicalTagType(LambdaTy); + LambdaLV = MakeAddrLValue(Base, T); } } else { - QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); + CanQualType LambdaTagType = + getContext().getCanonicalTagType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); } return EmitLValueForField(LambdaLV, Field); @@ -5196,7 +5205,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field, } } else { llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateRecordType( - getContext().getRecordType(rec), rec->getLocation()); + getContext().getCanonicalTagType(rec), rec->getLocation()); Addr = Builder.CreatePreserveStructAccessIndex( Addr, Idx, getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo); @@ -5658,7 +5667,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_DerivedToBase: { const auto *DerivedClassTy = E->getSubExpr()->getType()->castAs(); - auto *DerivedClassDecl = cast(DerivedClassTy->getDecl()); + auto *DerivedClassDecl = + cast(DerivedClassTy->getOriginalDecl()) + ->getDefinitionOrSelf(); LValue LV = EmitLValue(E->getSubExpr()); Address This = LV.getAddress(); @@ -5678,7 +5689,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { return EmitAggExprToLValue(E); case CK_BaseToDerived: { const auto *DerivedClassTy = E->getType()->castAs(); - auto *DerivedClassDecl = cast(DerivedClassTy->getDecl()); + auto *DerivedClassDecl = + cast(DerivedClassTy->getOriginalDecl()) + ->getDefinitionOrSelf(); LValue LV = EmitLValue(E->getSubExpr()); @@ -6733,7 +6746,7 @@ void CodeGenFunction::FlattenAccessAndType( WorkList.emplace_back(CAT->getElementType(), IdxListCopy); } } else if (const auto *RT = dyn_cast(T)) { - const RecordDecl *Record = RT->getDecl(); + const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf(); assert(!Record->isUnion() && "Union types not supported in flat cast."); const CXXRecordDecl *CXXD = dyn_cast(Record); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index e2f11b86b2053..04e125c54b1ca 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -272,7 +272,7 @@ bool AggExprEmitter::TypeRequiresGCollection(QualType T) { if (!RecordTy) return false; // Don't mess with non-trivial C++ types. - RecordDecl *Record = RecordTy->getDecl(); + RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); if (isa(Record) && (cast(Record)->hasNonTrivialCopyConstructor() || !cast(Record)->hasTrivialDestructor())) @@ -424,7 +424,10 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { Ctx.getAsConstantArrayType(E->getSubExpr()->getType()); assert(ArrayType && "std::initializer_list constructed from non-array"); - RecordDecl *Record = E->getType()->castAs()->getDecl(); + RecordDecl *Record = E->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); RecordDecl::field_iterator Field = Record->field_begin(); assert(Field != Record->field_end() && Ctx.hasSameType(Field->getType()->getPointeeType(), @@ -1806,7 +1809,10 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // the disadvantage is that the generated code is more difficult for // the optimizer, especially with bitfields. unsigned NumInitElements = InitExprs.size(); - RecordDecl *record = ExprToVisit->getType()->castAs()->getDecl(); + RecordDecl *record = ExprToVisit->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); // We'll need to enter cleanup scopes in case any of the element // initializers throws an exception. @@ -2116,7 +2122,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // referencee. InitListExprs for unions and arrays can't have references. if (const RecordType *RT = E->getType()->getAs()) { if (!RT->isUnionType()) { - RecordDecl *SD = RT->getDecl(); + RecordDecl *SD = RT->getOriginalDecl()->getDefinitionOrSelf(); CharUnits NumNonZeroBytes = CharUnits::Zero(); unsigned ILEElement = 0; @@ -2168,7 +2174,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E, if (CGF.getLangOpts().CPlusPlus) if (const RecordType *RT = CGF.getContext() .getBaseElementType(E->getType())->getAs()) { - const CXXRecordDecl *RD = cast(RT->getDecl()); + const CXXRecordDecl *RD = cast(RT->getOriginalDecl()); if (RD->hasUserDeclaredConstructor()) return; } @@ -2289,7 +2295,8 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { - CXXRecordDecl *Record = cast(RT->getDecl()); + auto *Record = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); assert((Record->hasTrivialCopyConstructor() || Record->hasTrivialCopyAssignment() || Record->hasTrivialMoveConstructor() || @@ -2373,7 +2380,7 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { // fall through } else if (const RecordType *RecordTy = Ty->getAs()) { - RecordDecl *Record = RecordTy->getDecl(); + RecordDecl *Record = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); if (Record->hasObjectMember()) { CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); @@ -2382,7 +2389,9 @@ void CodeGenFunction::EmitAggregateCopy(LValue Dest, LValue Src, QualType Ty, } else if (Ty->isArrayType()) { QualType BaseType = getContext().getBaseElementType(Ty); if (const RecordType *RecordTy = BaseType->getAs()) { - if (RecordTy->getDecl()->hasObjectMember()) { + if (RecordTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasObjectMember()) { CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestPtr, SrcPtr, SizeVal); return; diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 49d5d8acbe331..57d7eecc62ee1 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -181,7 +181,7 @@ static CXXRecordDecl *getCXXRecord(const Expr *E) { if (const PointerType *PTy = T->getAs()) T = PTy->getPointeeType(); const RecordType *Ty = T->castAs(); - return cast(Ty->getDecl()); + return cast(Ty->getOriginalDecl())->getDefinitionOrSelf(); } // Note: This function also emit constructor calls to support a MSVC @@ -206,7 +206,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, } bool HasQualifier = ME->hasQualifier(); - NestedNameSpecifier *Qualifier = HasQualifier ? ME->getQualifier() : nullptr; + NestedNameSpecifier Qualifier = ME->getQualifier(); bool IsArrow = ME->isArrow(); const Expr *Base = ME->getBase(); @@ -217,7 +217,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, - bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow, + bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow, const Expr *Base, llvm::CallBase **CallOrInvoke) { assert(isa(CE) || isa(CE)); @@ -361,7 +361,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (sanitizePerformTypeCheck()) EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, This.emitRawPointer(*this), - C.getRecordType(CalleeDecl->getParent()), + C.getCanonicalTagType(CalleeDecl->getParent()), /*Alignment=*/CharUnits::Zero(), SkippedChecks); // C++ [class.virtual]p12: @@ -461,9 +461,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(); - EmitTypeCheck( - TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), - QualType(MPT->getMostRecentCXXRecordDecl()->getTypeForDecl(), 0)); + CanQualType ClassType = CGM.getContext().getCanonicalTagType(RD); + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), + ClassType); // Get the member function pointer. llvm::Value *MemFnPtr = EmitScalarExpr(MemFnExpr); @@ -476,8 +476,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, CallArgList Args; - QualType ThisType = - getContext().getPointerType(getContext().getTagDeclType(RD)); + QualType ThisType = getContext().getPointerType(ClassType); // Push the this ptr. Args.add(RValue::get(ThisPtrForCall), ThisType); @@ -498,7 +497,7 @@ RValue CodeGenFunction::EmitCXXOperatorMemberCallExpr( assert(MD->isImplicitObjectMemberFunction() && "Trying to emit a member call expr on a static method!"); return EmitCXXMemberOrOperatorMemberCallExpr( - E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/nullptr, + E, MD, ReturnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt, /*IsArrow=*/false, E->getArg(0), CallOrInvoke); } @@ -1237,11 +1236,12 @@ void CodeGenFunction::EmitNewArrayInitializer( // usually use memset. if (auto *ILE = dyn_cast(Init)) { if (const RecordType *RType = ILE->getType()->getAs()) { - if (RType->getDecl()->isStruct()) { + const RecordDecl *RD = RType->getOriginalDecl()->getDefinitionOrSelf(); + if (RD->isStruct()) { unsigned NumElements = 0; - if (auto *CXXRD = dyn_cast(RType->getDecl())) + if (auto *CXXRD = dyn_cast(RD)) NumElements = CXXRD->getNumBases(); - for (auto *Field : RType->getDecl()->fields()) + for (auto *Field : RD->fields()) if (!Field->isUnnamedBitField()) ++NumElements; // FIXME: Recurse into nested InitListExprs. @@ -1687,9 +1687,11 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { QualType AlignValT = sizeType; if (allocatorType->getNumParams() > IndexOfAlignArg) { AlignValT = allocatorType->getParamType(IndexOfAlignArg); - assert(getContext().hasSameUnqualifiedType( - AlignValT->castAs()->getDecl()->getIntegerType(), - sizeType) && + assert(getContext().hasSameUnqualifiedType(AlignValT->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType(), + sizeType) && "wrong type for alignment parameter"); ++ParamsToSkip; } else { @@ -1972,7 +1974,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // destructor is virtual, we'll just emit the vcall and return. const CXXDestructorDecl *Dtor = nullptr; if (const RecordType *RT = ElementType->getAs()) { - CXXRecordDecl *RD = cast(RT->getDecl()); + auto *RD = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (RD->hasDefinition() && !RD->hasTrivialDestructor()) { Dtor = RD->getDestructor(); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 715bd392f59f7..a96c1518d2a1d 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -714,7 +714,10 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, } bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) { - RecordDecl *RD = ILE->getType()->castAs()->getDecl(); + RecordDecl *RD = ILE->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); unsigned FieldNo = -1; @@ -977,7 +980,8 @@ bool ConstStructBuilder::DoZeroInitPadding(const ASTRecordLayout &Layout, llvm::Constant *ConstStructBuilder::Finalize(QualType Type) { Type = Type.getNonReferenceType(); - RecordDecl *RD = Type->castAs()->getDecl(); + RecordDecl *RD = + Type->castAs()->getOriginalDecl()->getDefinitionOrSelf(); llvm::Type *ValTy = CGM.getTypes().ConvertType(Type); return Builder.build(ValTy, RD->hasFlexibleArrayMember()); } @@ -1000,7 +1004,8 @@ llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter, ConstantAggregateBuilder Const(Emitter.CGM); ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero()); - const RecordDecl *RD = ValTy->castAs()->getDecl(); + const RecordDecl *RD = + ValTy->castAs()->getOriginalDecl()->getDefinitionOrSelf(); const CXXRecordDecl *CD = dyn_cast(RD); if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero())) return nullptr; @@ -1506,7 +1511,9 @@ class ConstExprEmitter llvm::Type *ValTy = CGM.getTypes().ConvertType(destType); bool HasFlexibleArray = false; if (const auto *RT = destType->getAs()) - HasFlexibleArray = RT->getDecl()->hasFlexibleArrayMember(); + HasFlexibleArray = RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember(); return Const.build(ValTy, HasFlexibleArray); } @@ -2640,7 +2647,9 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, } const CXXRecordDecl *base = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Ignore empty bases. if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) || @@ -2679,8 +2688,10 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM, // Fill in the virtual bases, if we're working with the complete object. if (CXXR && asCompleteObject) { for (const auto &I : CXXR->vbases()) { - const CXXRecordDecl *base = - cast(I.getType()->castAs()->getDecl()); + const auto *base = + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Ignore empty bases. if (isEmptyRecordForLayout(CGM.getContext(), I.getType())) @@ -2746,7 +2757,9 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { } if (const RecordType *RT = T->getAs()) - return ::EmitNullConstant(*this, RT->getDecl(), /*complete object*/ true); + return ::EmitNullConstant(*this, + RT->getOriginalDecl()->getDefinitionOrSelf(), + /*complete object*/ true); assert(T->isMemberDataPointerType() && "Should only see pointers to data members here!"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7eed4eec5b041..155b80df36715 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -3515,7 +3515,9 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); - RecordDecl *RD = CurrentType->castAs()->getDecl(); + RecordDecl *RD = CurrentType->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); // Compute the index of the field in its parent. @@ -3548,15 +3550,16 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { continue; } - RecordDecl *RD = CurrentType->castAs()->getDecl(); - const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); + const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout( + CurrentType->castAs()->getOriginalDecl()); // Save the element type. CurrentType = ON.getBase()->getType(); // Compute the offset to the base. auto *BaseRT = CurrentType->castAs(); - auto *BaseRD = cast(BaseRT->getDecl()); + auto *BaseRD = + cast(BaseRT->getOriginalDecl())->getDefinitionOrSelf(); CharUnits OffsetInt = RL.getBaseClassOffset(BaseRD); Offset = llvm::ConstantInt::get(ResultType, OffsetInt.getQuantity()); break; diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 918cb3e38448d..9b3ef6aafd05f 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -179,8 +179,7 @@ static const clang::HLSLAttributedResourceType * createBufferHandleType(const HLSLBufferDecl *BufDecl) { ASTContext &AST = BufDecl->getASTContext(); QualType QT = AST.getHLSLAttributedResourceType( - AST.HLSLResourceTy, - QualType(BufDecl->getLayoutStruct()->getTypeForDecl(), 0), + AST.HLSLResourceTy, AST.getCanonicalTagType(BufDecl->getLayoutStruct()), HLSLAttributedResourceType::Attributes(ResourceClass::CBuffer)); return cast(QT.getTypePtr()); } diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index e0983ef256e71..1b941fff8b644 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -39,7 +39,8 @@ template struct StructVisitor { template void visitStructFields(QualType QT, CharUnits CurStructOffset, Ts... Args) { - const RecordDecl *RD = QT->castAs()->getDecl(); + const RecordDecl *RD = + QT->castAs()->getOriginalDecl()->getDefinitionOrSelf(); // Iterate over the fields of the struct. for (const FieldDecl *FD : RD->fields()) { @@ -464,7 +465,8 @@ template struct GenFuncBase { if (WrongType) { std::string FuncName = std::string(F->getName()); - SourceLocation Loc = QT->castAs()->getDecl()->getLocation(); + SourceLocation Loc = + QT->castAs()->getOriginalDecl()->getLocation(); CGM.Error(Loc, "special function " + FuncName + " for non-trivial C struct has incorrect type"); return nullptr; @@ -560,7 +562,8 @@ struct GenBinaryFunc : CopyStructVisitor, if (FD->isZeroLengthBitField()) return; - QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0); + CanQualType RT = + this->CGF->getContext().getCanonicalTagType(FD->getParent()); llvm::Type *Ty = this->CGF->ConvertType(RT); Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset); LValue DstBase = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 24b6ce7c1c70d..b5f17b812222a 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1000,7 +1000,9 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, // Compute whether the ivar has strong members. if (CGM.getLangOpts().getGC()) if (const RecordType *recordType = ivarType->getAs()) - HasStrong = recordType->getDecl()->hasObjectMember(); + HasStrong = recordType->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasObjectMember(); // We can never access structs with object members with a native // access, because we need to use write barriers. This is what diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 8c66176942cb5..eb4904050ae0f 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2495,7 +2495,7 @@ void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, CharUnits BytePos, bool &HasUnion, bool ByrefLayout) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); SmallVector Fields(RD->fields()); llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); const llvm::StructLayout *RecLayout = @@ -3354,7 +3354,8 @@ static bool hasWeakMember(QualType type) { } if (auto recType = type->getAs()) { - for (auto *field : recType->getDecl()->fields()) { + for (auto *field : + recType->getOriginalDecl()->getDefinitionOrSelf()->fields()) { if (hasWeakMember(field->getType())) return true; } @@ -5184,7 +5185,7 @@ CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, } void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a union, remember that we had one, because it might mess // up the ordering of layout entries. @@ -5670,7 +5671,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) nullptr, false, ICIS_NoInit)); RD->completeDefinition(); - SuperCTy = Ctx.getTagDeclType(RD); + SuperCTy = Ctx.getCanonicalTagType(RD); SuperPtrCTy = Ctx.getPointerType(SuperCTy); SuperTy = cast(Types.ConvertType(SuperCTy)); @@ -6016,7 +6017,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper( false, ICIS_NoInit)); RD->completeDefinition(); - MessageRefCTy = Ctx.getTagDeclType(RD); + MessageRefCTy = Ctx.getCanonicalTagType(RD); MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); MessageRefTy = cast(Types.ConvertType(MessageRefCTy)); diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 6e2f32022a01e..cbf99534d2ce6 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -440,7 +440,9 @@ void CGObjCRuntime::destroyCalleeDestroyedArguments(CodeGenFunction &CGF, } else { QualType QT = param->getType(); auto *RT = QT->getAs(); - if (RT && RT->getDecl()->isParamDestroyedInCallee()) { + if (RT && RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->isParamDestroyedInCallee()) { RValue RV = I->getRValue(CGF); QualType::DestructionKind DtorKind = QT.isDestructedType(); switch (DtorKind) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 91237cfe3a372..3eba33f8ebe43 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2915,7 +2915,7 @@ createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, addFieldToRecordDecl(C, UD, KmpInt32Ty); addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); UD->completeDefinition(); - QualType KmpCmplrdataTy = C.getRecordType(UD); + CanQualType KmpCmplrdataTy = C.getCanonicalTagType(UD); RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); RD->startDefinition(); addFieldToRecordDecl(C, RD, C.VoidPtrTy); @@ -2950,7 +2950,7 @@ createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, RD->startDefinition(); addFieldToRecordDecl(C, RD, KmpTaskTQTy); if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) - addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); + addFieldToRecordDecl(C, RD, C.getCanonicalTagType(PrivateRD)); RD->completeDefinition(); return RD; } @@ -3582,7 +3582,7 @@ static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); KmpAffinityInfoRD->completeDefinition(); - KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); + KmpTaskAffinityInfoTy = C.getCanonicalTagType(KmpAffinityInfoRD); } } @@ -3640,7 +3640,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, // Build type kmp_task_t (if not built yet). if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { if (SavedKmpTaskloopTQTy.isNull()) { - SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( + SavedKmpTaskloopTQTy = C.getCanonicalTagType(createKmpTaskTRecordDecl( CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); } KmpTaskTQTy = SavedKmpTaskloopTQTy; @@ -3650,7 +3650,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && "Expected taskloop, task or target directive"); if (SavedKmpTaskTQTy.isNull()) { - SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( + SavedKmpTaskTQTy = C.getCanonicalTagType(createKmpTaskTRecordDecl( CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); } KmpTaskTQTy = SavedKmpTaskTQTy; @@ -3659,7 +3659,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, // Build particular struct kmp_task_t for the given task. const RecordDecl *KmpTaskTWithPrivatesQTyRD = createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); - QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); + CanQualType KmpTaskTWithPrivatesQTy = + C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD); QualType KmpTaskTWithPrivatesPtrQTy = C.getPointerType(KmpTaskTWithPrivatesQTy); llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.Builder.getPtrTy(0); @@ -3914,7 +3915,10 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, // Fill the data in the resulting kmp_task_t record. // Copy shareds if there are any. Address KmpTaskSharedsPtr = Address::invalid(); - if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { + if (!SharedsTy->getAsStructureType() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->field_empty()) { KmpTaskSharedsPtr = Address( CGF.EmitLoadOfScalar( CGF.EmitLValueForField( @@ -3944,8 +3948,11 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, enum { Priority = 0, Destructors = 1 }; // Provide pointer to function with destructors for privates. auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); - const RecordDecl *KmpCmplrdataUD = - (*FI)->getType()->getAsUnionType()->getDecl(); + const RecordDecl *KmpCmplrdataUD = (*FI) + ->getType() + ->getAsUnionType() + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (NeedsCleanup) { llvm::Value *DestructorFn = emitDestructorsFunction( CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, @@ -4015,7 +4022,7 @@ static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); KmpDependInfoRD->completeDefinition(); - KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); + KmpDependInfoTy = C.getCanonicalTagType(KmpDependInfoRD); } } @@ -5714,7 +5721,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( const FieldDecl *FlagsFD = addFieldToRecordDecl( C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); RD->completeDefinition(); - QualType RDType = C.getRecordType(RD); + CanQualType RDType = C.getCanonicalTagType(RD); unsigned Size = Data.ReductionVars.size(); llvm::APInt ArraySize(/*numBits=*/64, Size); QualType ArrayRDType = @@ -10703,7 +10710,7 @@ static unsigned evaluateCDTSize(const FunctionDecl *FD, unsigned Offset = 0; if (const auto *MD = dyn_cast(FD)) { if (ParamAttrs[Offset].Kind == Vector) - CDT = C.getPointerType(C.getRecordType(MD->getParent())); + CDT = C.getPointerType(C.getCanonicalTagType(MD->getParent())); ++Offset; } if (CDT.isNull()) { @@ -11285,7 +11292,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, addFieldToRecordDecl(C, RD, Int64Ty); addFieldToRecordDecl(C, RD, Int64Ty); RD->completeDefinition(); - KmpDimTy = C.getRecordType(RD); + KmpDimTy = C.getCanonicalTagType(RD); } else { RD = cast(KmpDimTy->getAsTagDecl()); } @@ -11781,7 +11788,7 @@ Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); FiredField = addFieldToRecordDecl(C, RD, C.CharTy); RD->completeDefinition(); - NewType = C.getRecordType(RD); + NewType = C.getCanonicalTagType(RD); Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 04c91920c9b7e..cff1071dd1c2e 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -769,7 +769,7 @@ void CGOpenMPRuntimeGPU::emitKernelDeinit(CodeGenFunction &CGF, "_openmp_teams_reduction_type_$_", RecordDecl::TagKind::Union); StaticRD->startDefinition(); for (const RecordDecl *TeamReductionRec : TeamsReductions) { - QualType RecTy = C.getRecordType(TeamReductionRec); + CanQualType RecTy = C.getCanonicalTagType(TeamReductionRec); auto *Field = FieldDecl::Create( C, StaticRD, SourceLocation(), SourceLocation(), nullptr, RecTy, C.getTrivialTypeSourceInfo(RecTy, SourceLocation()), @@ -779,7 +779,7 @@ void CGOpenMPRuntimeGPU::emitKernelDeinit(CodeGenFunction &CGF, StaticRD->addDecl(Field); } StaticRD->completeDefinition(); - QualType StaticTy = C.getRecordType(StaticRD); + CanQualType StaticTy = C.getCanonicalTagType(StaticRD); llvm::Type *LLVMReductionsBufferTy = CGM.getTypes().ConvertTypeForMem(StaticTy); const auto &DL = CGM.getModule().getDataLayout(); diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index dcef01a5eb6d3..1a5ffb5eb33f8 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -531,7 +531,7 @@ llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, llvm::Type *Ty) { QualType FT = FD->getType(); - FT = getContext().getMemberPointerType(FT, /*Qualifier=*/nullptr, + FT = getContext().getMemberPointerType(FT, /*Qualifier=*/std::nullopt, cast(FD)->getParent()); return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 1a8c6f015bda1..031ef73214e76 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -3279,7 +3279,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { LValue CodeGenFunction::InitCapturedStruct(const CapturedStmt &S) { const RecordDecl *RD = S.getCapturedRecordDecl(); - QualType RecordTy = getContext().getRecordType(RD); + CanQualType RecordTy = getContext().getCanonicalTagType(RD); // Initialize the captured struct. LValue SlotLV = @@ -3359,7 +3359,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { // Initialize variable-length arrays. LValue Base = MakeNaturalAlignRawAddrLValue( - CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); + CapturedStmtInfo->getContextValue(), Ctx.getCanonicalTagType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 5822e0f6db89a..f6a0ca574a191 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -5273,7 +5273,8 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // Emit outlined function for task construct. const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); Address CapturedStruct = GenerateCapturedStmtArgument(*CS); - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); + CanQualType SharedsTy = + getContext().getCanonicalTagType(CS->getCapturedRecordDecl()); auto I = CS->getCapturedDecl()->param_begin(); auto PartId = std::next(I); auto TaskT = std::next(I, 4); @@ -5507,7 +5508,8 @@ void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) { // Emit outlined function for task construct. const CapturedStmt *CS = S.getCapturedStmt(OMPD_task); Address CapturedStruct = GenerateCapturedStmtArgument(*CS); - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); + CanQualType SharedsTy = + getContext().getCanonicalTagType(CS->getCapturedRecordDecl()); const Expr *IfCond = nullptr; for (const auto *C : S.getClausesOfKind()) { if (C->getNameModifier() == OMPD_unknown || @@ -7890,7 +7892,8 @@ void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) { OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false); CapturedStruct = GenerateCapturedStmtArgument(*CS); } - QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl()); + CanQualType SharedsTy = + getContext().getCanonicalTagType(CS->getCapturedRecordDecl()); const Expr *IfCond = nullptr; for (const auto *C : S.getClausesOfKind()) { if (C->getNameModifier() == OMPD_unknown || diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 0b6e830e0d557..e14e883a55ac5 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -971,7 +971,7 @@ llvm::GlobalVariable *CodeGenVTables::GenerateConstructionVTable( VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); llvm::Constant *RTTI = CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getTagDeclType(Base.getBase())); + CGM.getContext().getCanonicalTagType(Base.getBase())); // Create and set the initializer. ConstantInitBuilder builder(CGM); @@ -1382,8 +1382,8 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, AP.second.AddressPointIndex, {}}; llvm::raw_string_ostream Stream(N.TypeName); - getCXXABI().getMangleContext().mangleCanonicalTypeName( - QualType(N.Base->getTypeForDecl(), 0), Stream); + CanQualType T = getContext().getCanonicalTagType(N.Base); + getCXXABI().getMangleContext().mangleCanonicalTypeName(T, Stream); AddressPoints.push_back(std::move(N)); } @@ -1404,7 +1404,7 @@ void CodeGenModule::EmitVTableTypeMetadata(const CXXRecordDecl *RD, continue; llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( Context.getMemberPointerType(Comps[I].getFunctionDecl()->getType(), - /*Qualifier=*/nullptr, AP.Base)); + /*Qualifier=*/std::nullopt, AP.Base)); VTable->addTypeMetadata((ComponentWidth * I).getQuantity(), MD); } } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index ab345a598c4e8..d077ee50856b7 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2223,7 +2223,9 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { // Ignore empty classes in C++. if (getLangOpts().CPlusPlus) { if (const RecordType *RT = Ty->getAs()) { - if (cast(RT->getDecl())->isEmpty()) + if (cast(RT->getOriginalDecl()) + ->getDefinitionOrSelf() + ->isEmpty()) return; } } @@ -2494,10 +2496,6 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::PredefinedSugar: llvm_unreachable("type class is never variably-modified!"); - case Type::Elaborated: - type = cast(ty)->getNamedType(); - break; - case Type::Adjusted: type = cast(ty)->getAdjustedType(); break; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index bf16d727bac04..84be42244d39c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2972,7 +2972,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// member. bool hasVolatileMember(QualType T) { if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = cast(RT->getDecl()); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); return RD->hasVolatileMember(); } return false; @@ -4552,7 +4552,7 @@ class CodeGenFunction : public CodeGenTypeCache { ArrayRef args); CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD, - NestedNameSpecifier *Qual, llvm::Type *Ty); + NestedNameSpecifier Qual, llvm::Type *Ty); CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, @@ -4657,7 +4657,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::CallBase **CallOrInvoke = nullptr); RValue EmitCXXMemberOrOperatorMemberCallExpr( const CallExpr *CE, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue, - bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow, + bool HasQualifier, NestedNameSpecifier Qualifier, bool IsArrow, const Expr *Base, llvm::CallBase **CallOrInvoke); // Compute the object pointer. Address EmitCXXMemberDataPointerAddress( diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 834b1c067d84c..2541a441c7d59 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2793,7 +2793,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, for (const CXXRecordDecl *Base : getMostBaseClasses(MD->getParent())) { llvm::Metadata *Id = CreateMetadataIdentifierForType(Context.getMemberPointerType( - MD->getType(), /*Qualifier=*/nullptr, Base)); + MD->getType(), /*Qualifier=*/std::nullopt, Base)); F->addTypeMetadata(0, Id); } } @@ -4152,9 +4152,11 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Check if T is a class type with a destructor that's not dllimport. static bool HasNonDllImportDtor(QualType T) { if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs()) - if (CXXRecordDecl *RD = dyn_cast(RT->getDecl())) + if (auto *RD = dyn_cast(RT->getOriginalDecl())) { + RD = RD->getDefinitionOrSelf(); if (RD->getDestructor() && !RD->getDestructor()->hasAttr()) return true; + } return false; } @@ -6029,7 +6031,7 @@ static bool isVarDeclStrongDefinition(const ASTContext &Context, return true; if (const auto *RT = VarType->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); for (const FieldDecl *FD : RD->fields()) { if (FD->isBitField()) continue; @@ -6738,7 +6740,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() { } D->completeDefinition(); - ObjCFastEnumerationStateType = Context.getTagDeclType(D); + ObjCFastEnumerationStateType = Context.getCanonicalTagType(D); } return ObjCFastEnumerationStateType; @@ -7248,7 +7250,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { CXXRecordDecl *CRD = cast(D); if (CGDebugInfo *DI = getModuleDebugInfo()) { if (CRD->hasDefinition()) - DI->EmitAndRetainType(getContext().getRecordType(cast(D))); + DI->EmitAndRetainType( + getContext().getCanonicalTagType(cast(D))); if (auto *ES = D->getASTContext().getExternalSource()) if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) DI->completeUnusedClass(*CRD); @@ -7467,20 +7470,23 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::Typedef: case Decl::TypeAlias: // using foo = bar; [C++11] if (CGDebugInfo *DI = getModuleDebugInfo()) - DI->EmitAndRetainType( - getContext().getTypedefType(cast(D))); + DI->EmitAndRetainType(getContext().getTypedefType( + ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, + cast(D))); break; case Decl::Record: if (CGDebugInfo *DI = getModuleDebugInfo()) if (cast(D)->getDefinition()) - DI->EmitAndRetainType(getContext().getRecordType(cast(D))); + DI->EmitAndRetainType( + getContext().getCanonicalTagType(cast(D))); break; case Decl::Enum: if (CGDebugInfo *DI = getModuleDebugInfo()) if (cast(D)->getDefinition()) - DI->EmitAndRetainType(getContext().getEnumType(cast(D))); + DI->EmitAndRetainType( + getContext().getCanonicalTagType(cast(D))); break; case Decl::HLSLBuffer: @@ -7934,8 +7940,8 @@ bool CodeGenModule::NeedAllVtablesTypeId() const { void CodeGenModule::AddVTableTypeMetadata(llvm::GlobalVariable *VTable, CharUnits Offset, const CXXRecordDecl *RD) { - llvm::Metadata *MD = - CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); + CanQualType T = getContext().getCanonicalTagType(RD); + llvm::Metadata *MD = CreateMetadataIdentifierForType(T); VTable->addTypeMetadata(Offset.getQuantity(), MD); if (CodeGenOpts.SanitizeCfiCrossDso) diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 90eafe26b548a..bd2442f01cc50 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -143,7 +143,7 @@ static bool TypeHasMayAlias(QualType QTy) { /// Check if the given type is a valid base type to be used in access tags. static bool isValidBaseType(QualType QTy) { if (const RecordType *TTy = QTy->getAs()) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); + const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); // Incomplete types are not valid base access types. if (!RD) return false; @@ -311,7 +311,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // This also covers anonymous structs and unions, which have a different // compatibility rule, but it doesn't matter because you can never have a // pointer to an anonymous struct or union. - if (!RT->getDecl()->getDeclName()) + if (!RT->getOriginalDecl()->getDeclName()) return getAnyPtr(PtrDepth); // For non-builtin types use the mangled name of the canonical type. @@ -333,14 +333,15 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) { // Enum types are distinct types. In C++ they have "underlying types", // however they aren't related for TBAA. if (const EnumType *ETy = dyn_cast(Ty)) { + const EnumDecl *ED = ETy->getOriginalDecl()->getDefinitionOrSelf(); if (!Features.CPlusPlus) - return getTypeInfo(ETy->getDecl()->getIntegerType()); + return getTypeInfo(ED->getIntegerType()); // In C++ mode, types have linkage, so we can rely on the ODR and // on their mangled names, if they're external. // TODO: Is there a way to get a program-wide unique name for a // decl with local linkage or no linkage? - if (!ETy->getDecl()->isExternallyVisible()) + if (!ED->isExternallyVisible()) return getChar(); SmallString<256> OutName; @@ -433,7 +434,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset, llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag)); return true; } - const RecordDecl *RD = TTy->getDecl()->getDefinition(); + const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); if (RD->hasFlexibleArrayMember()) return false; @@ -514,7 +515,7 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) { llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { if (auto *TTy = dyn_cast(Ty)) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); + const RecordDecl *RD = TTy->getOriginalDecl()->getDefinition(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); using TBAAStructField = llvm::MDBuilder::TBAAStructField; SmallVector Fields; diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index c98503e4bbd26..f2a0a649a88fd 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -229,12 +229,13 @@ bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) { /// UpdateCompletedType - When we find the full definition for a TagDecl, /// replace the 'opaque' type we previously made for it if applicable. void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { + CanQualType T = CGM.getContext().getCanonicalTagType(TD); // If this is an enum being completed, then we flush all non-struct types from // the cache. This allows function types and other things that may be derived // from the enum to be recomputed. if (const EnumDecl *ED = dyn_cast(TD)) { // Only flush the cache if we've actually already converted this type. - if (TypeCache.count(ED->getTypeForDecl())) { + if (TypeCache.count(T->getTypePtr())) { // Okay, we formed some types based on this. We speculated that the enum // would be lowered to i32, so we only need to flush the cache if this // didn't happen. @@ -255,7 +256,7 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { // Only complete it if we converted it already. If we haven't converted it // yet, we'll just do it lazily. - if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr())) + if (RecordDeclTypes.count(T.getTypePtr())) ConvertRecordDeclType(RD); // If necessary, provide the full definition of a type only used with a @@ -265,7 +266,7 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { } void CodeGenTypes::RefreshTypeCacheForClass(const CXXRecordDecl *RD) { - QualType T = Context.getRecordType(RD); + CanQualType T = Context.getCanonicalTagType(RD); T = Context.getCanonicalType(T); const Type *Ty = T.getTypePtr(); @@ -311,11 +312,11 @@ llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(QualType QFT) { // Force conversion of all the relevant record types, to make sure // we re-convert the FunctionType when appropriate. if (const RecordType *RT = FT->getReturnType()->getAs()) - ConvertRecordDeclType(RT->getDecl()); + ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); if (const FunctionProtoType *FPT = dyn_cast(FT)) for (unsigned i = 0, e = FPT->getNumParams(); i != e; i++) if (const RecordType *RT = FPT->getParamType(i)->getAs()) - ConvertRecordDeclType(RT->getDecl()); + ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); SkippedLayout = true; @@ -373,7 +374,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { // RecordTypes are cached and processed specially. if (const RecordType *RT = dyn_cast(Ty)) - return ConvertRecordDeclType(RT->getDecl()); + return ConvertRecordDeclType(RT->getOriginalDecl()->getDefinitionOrSelf()); llvm::Type *CachedType = nullptr; auto TCI = TypeCache.find(Ty); @@ -699,7 +700,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { break; case Type::Enum: { - const EnumDecl *ED = cast(Ty)->getDecl(); + const EnumDecl *ED = + cast(Ty)->getOriginalDecl()->getDefinitionOrSelf(); if (ED->isCompleteDefinition() || ED->isFixed()) return ConvertType(ED->getIntegerType()); // Return a placeholder 'i32' type. This can be changed later when the @@ -725,8 +727,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case Type::MemberPointer: { auto *MPTy = cast(Ty); if (!getCXXABI().isMemberPointerConvertible(MPTy)) { - auto *C = MPTy->getMostRecentCXXRecordDecl()->getTypeForDecl(); - auto Insertion = RecordsWithOpaqueMemberPointers.try_emplace(C); + CanQualType T = CGM.getContext().getCanonicalTagType( + MPTy->getMostRecentCXXRecordDecl()); + auto Insertion = + RecordsWithOpaqueMemberPointers.try_emplace(T.getTypePtr()); if (Insertion.second) Insertion.first->second = llvm::StructType::create(getLLVMContext()); ResultType = Insertion.first->second; @@ -789,7 +793,7 @@ bool CodeGenModule::isPaddedAtomicType(const AtomicType *type) { llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { // TagDecl's are not necessarily unique, instead use the (clang) // type connected to the decl. - const Type *Key = Context.getTagDeclType(RD).getTypePtr(); + const Type *Key = Context.getCanonicalTagType(RD).getTypePtr(); llvm::StructType *&Entry = RecordDeclTypes[Key]; @@ -810,7 +814,10 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { if (const CXXRecordDecl *CRD = dyn_cast(RD)) { for (const auto &I : CRD->bases()) { if (I.isVirtual()) continue; - ConvertRecordDeclType(I.getType()->castAs()->getDecl()); + ConvertRecordDeclType(I.getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf()); } } @@ -830,7 +837,7 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { /// getCGRecordLayout - Return record layout info for the given record decl. const CGRecordLayout & CodeGenTypes::getCGRecordLayout(const RecordDecl *RD) { - const Type *Key = Context.getTagDeclType(RD).getTypePtr(); + const Type *Key = Context.getCanonicalTagType(RD).getTypePtr(); auto I = CGRecordLayouts.find(Key); if (I != CGRecordLayouts.end()) @@ -869,7 +876,7 @@ bool CodeGenTypes::isZeroInitializable(QualType T) { // Records are non-zero-initializable if they contain any // non-zero-initializable subobjects. if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); return isZeroInitializable(RD); } diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp index 1ed33894b15aa..ac56dda74abb7 100644 --- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp +++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp @@ -101,7 +101,8 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( const RecordType *RT = RecordTypes.back(); RecordTypes.pop_back(); - for (const auto *FD : RT->getDecl()->fields()) { + for (const auto *FD : + RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { assert((!PackOffsets || Index < PackOffsets->size()) && "number of elements in layout struct does not match number of " "packoffset annotations"); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 5ffc1edb9986f..4ed3775f156c9 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -831,7 +831,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) { llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType( getContext().getMemberPointerType(MPT->getPointeeType(), - /*Qualifier=*/nullptr, + /*Qualifier=*/std::nullopt, Base->getCanonicalDecl())); llvm::Value *TypeId = llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD); @@ -1241,7 +1241,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, if (const CXXMethodDecl *MD = dyn_cast(MPD)) { llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment); QualType SrcType = getContext().getMemberPointerType( - MD->getType(), /*Qualifier=*/nullptr, MD->getParent()); + MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent()); return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM); } @@ -1397,8 +1397,9 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // to pass to the deallocation function. // Grab the vtable pointer as an intptr_t*. - auto *ClassDecl = - cast(ElementType->castAs()->getDecl()); + auto *ClassDecl = cast( + ElementType->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.UnqualPtrTy, ClassDecl); // Track back to entry -2 and pull out the offset there. @@ -1484,7 +1485,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { // trivial destructor (or isn't a record), we just pass null. llvm::Constant *Dtor = nullptr; if (const RecordType *RecordTy = ThrowType->getAs()) { - CXXRecordDecl *Record = cast(RecordTy->getDecl()); + CXXRecordDecl *Record = + cast(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); if (!Record->hasTrivialDestructor()) { // __cxa_throw is declared to take its destructor as void (*)(void *). We // must match that if function pointers can be authenticated with a @@ -1611,7 +1613,8 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy) { auto *ClassDecl = - cast(SrcRecordTy->castAs()->getDecl()); + cast(SrcRecordTy->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy, ClassDecl); @@ -1784,7 +1787,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy) { auto *ClassDecl = - cast(SrcRecordTy->castAs()->getDecl()); + cast(SrcRecordTy->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); llvm::Value *OffsetToTop; if (CGM.getItaniumVTableContext().isRelativeLayout()) { // Get the vtable pointer. @@ -2037,7 +2041,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, const VTableLayout &VTLayout = VTContext.getVTableLayout(RD); llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD); llvm::Constant *RTTI = - CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD)); + CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD)); // Create and set the initializer. ConstantInitBuilder builder(CGM); @@ -3776,7 +3780,8 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, if (!Context.getLangOpts().RTTI) return false; if (const RecordType *RecordTy = dyn_cast(Ty)) { - const CXXRecordDecl *RD = cast(RecordTy->getDecl()); + const CXXRecordDecl *RD = + cast(RecordTy->getOriginalDecl())->getDefinitionOrSelf(); if (!RD->hasDefinition()) return false; @@ -3810,7 +3815,9 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, /// IsIncompleteClassType - Returns whether the given record type is incomplete. static bool IsIncompleteClassType(const RecordType *RecordTy) { - return !RecordTy->getDecl()->isCompleteDefinition(); + return !RecordTy->getOriginalDecl() + ->getDefinitionOrSelf() + ->isCompleteDefinition(); } /// ContainsIncompleteClassType - Returns whether the given type contains an @@ -3836,9 +3843,7 @@ static bool ContainsIncompleteClassType(QualType Ty) { if (const MemberPointerType *MemberPointerTy = dyn_cast(Ty)) { // Check if the class type is incomplete. - const auto *ClassType = cast( - MemberPointerTy->getMostRecentCXXRecordDecl()->getTypeForDecl()); - if (IsIncompleteClassType(ClassType)) + if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition()) return true; return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); @@ -3867,8 +3872,9 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { return false; // Check that the class is dynamic iff the base is. - auto *BaseDecl = - cast(Base->getType()->castAs()->getDecl()); + auto *BaseDecl = cast( + Base->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!BaseDecl->isEmpty() && BaseDecl->isDynamicClass() != RD->isDynamicClass()) return false; @@ -3947,7 +3953,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty, case Type::Record: { const CXXRecordDecl *RD = - cast(cast(Ty)->getDecl()); + cast(cast(Ty)->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!RD->hasDefinition() || !RD->getNumBases()) { VTableName = ClassTypeInfo; @@ -4069,7 +4076,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, return llvm::GlobalValue::LinkOnceODRLinkage; if (const RecordType *Record = dyn_cast(Ty)) { - const CXXRecordDecl *RD = cast(Record->getDecl()); + const CXXRecordDecl *RD = + cast(Record->getOriginalDecl())->getDefinitionOrSelf(); if (RD->hasAttr()) return llvm::GlobalValue::WeakODRLinkage; if (CGM.getTriple().isWindowsItaniumEnvironment()) @@ -4233,7 +4241,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( case Type::Record: { const CXXRecordDecl *RD = - cast(cast(Ty)->getDecl()); + cast(cast(Ty)->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!RD->hasDefinition() || !RD->getNumBases()) { // We don't need to emit any fields. break; @@ -4280,7 +4289,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( if (CGM.getTarget().hasPS4DLLImportExport() && GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) { if (const RecordType *RecordTy = dyn_cast(Ty)) { - const CXXRecordDecl *RD = cast(RecordTy->getDecl()); + const CXXRecordDecl *RD = cast(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf(); if (RD->hasAttr() || CXXRecordNonInlineHasAttr(RD)) GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass; @@ -4384,8 +4394,9 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, unsigned Flags = 0; - auto *BaseDecl = - cast(Base->getType()->castAs()->getDecl()); + auto *BaseDecl = cast( + Base->getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (Base->isVirtual()) { // Mark the virtual base as seen. @@ -4485,7 +4496,9 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType())); auto *BaseDecl = - cast(Base.getType()->castAs()->getDecl()); + cast( + Base.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); int64_t OffsetFlags = 0; @@ -4575,9 +4588,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { // attributes of the type pointed to. unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); - const auto *ClassType = - cast(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl()); - if (IsIncompleteClassType(ClassType)) + const auto *RD = Ty->getMostRecentCXXRecordDecl(); + if (!RD->hasDefinition()) Flags |= PTI_ContainingClassIncomplete; llvm::Type *UnsignedIntLTy = @@ -4595,8 +4607,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { // __context is a pointer to an abi::__class_type_info corresponding to the // class type containing the member pointed to // (e.g., the "A" in "int A::*"). - Fields.push_back( - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0))); + CanQualType T = CGM.getContext().getCanonicalTagType(RD); + Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(T)); } llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { @@ -5176,7 +5188,7 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) { .getDecl()); llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD); QualType funcType = CGM.getContext().getMemberPointerType( - MD->getType(), /*Qualifier=*/nullptr, MD->getParent()); + MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent()); return CGM.getMemberFunctionPointer(thunk, funcType); } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index e8d2451a7dd5c..88f0648660965 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -876,7 +876,8 @@ MicrosoftCXXABI::getRecordArgABI(const CXXRecordDecl *RD) const { // it indirectly. Prior to MSVC version 19.14, passing overaligned // arguments was not supported and resulted in a compiler error. In 19.14 // and later versions, such arguments are now passed indirectly. - TypeInfo Info = getContext().getTypeInfo(RD->getTypeForDecl()); + TypeInfo Info = + getContext().getTypeInfo(getContext().getCanonicalTagType(RD)); if (Info.isAlignRequired() && Info.Align > 4) return RAA_Indirect; @@ -2924,15 +2925,15 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, if (!FD) FD = cast(*cast(MPD)->chain_begin()); const CXXRecordDecl *RD = cast(FD->getParent()); - RD = RD->getMostRecentNonInjectedDecl(); + RD = RD->getMostRecentDecl(); C = EmitMemberDataPointer(RD, FieldOffset); } if (!MemberPointerPath.empty()) { const CXXRecordDecl *SrcRD = cast(MPD->getDeclContext()); const MemberPointerType *SrcTy = - Ctx.getMemberPointerType(DstTy->getPointeeType(), /*Qualifier=*/nullptr, - SrcRD) + Ctx.getMemberPointerType(DstTy->getPointeeType(), + /*Qualifier=*/std::nullopt, SrcRD) ->castAs(); bool DerivedMember = MP.isMemberPointerToDerivedMember(); @@ -2969,7 +2970,7 @@ MicrosoftCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { assert(MD->isInstance() && "Member function must not be static!"); CharUnits NonVirtualBaseAdjustment = CharUnits::Zero(); - const CXXRecordDecl *RD = MD->getParent()->getMostRecentNonInjectedDecl(); + const CXXRecordDecl *RD = MD->getParent()->getMostRecentDecl(); CodeGenTypes &Types = CGM.getTypes(); unsigned VBTableIndex = 0; @@ -3690,7 +3691,7 @@ struct MSRTTIBuilder { MSRTTIBuilder(MicrosoftCXXABI &ABI, const CXXRecordDecl *RD) : CGM(ABI.CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()), Module(CGM.getModule()), RD(RD), - Linkage(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), + Linkage(getLinkageForRTTI(CGM.getContext().getCanonicalTagType(RD))), ABI(ABI) {} llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); @@ -3864,7 +3865,7 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) { // Initialize the BaseClassDescriptor. llvm::Constant *Fields[] = { ABI.getImageRelativeConstant( - ABI.getAddrOfRTTIDescriptor(Context.getTypeDeclType(Class.RD))), + ABI.getAddrOfRTTIDescriptor(Context.getCanonicalTagType(Class.RD))), llvm::ConstantInt::get(CGM.IntTy, Class.NumBases), llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase), llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset), @@ -3911,7 +3912,7 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) { llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), ABI.getImageRelativeConstant( - CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))), + CGM.GetAddrOfRTTIDescriptor(Context.getCanonicalTagType(RD))), ABI.getImageRelativeConstant(getClassHierarchyDescriptor()), ABI.getImageRelativeConstant(COL), }; @@ -4082,7 +4083,7 @@ MicrosoftCXXABI::getAddrOfCXXCtorClosure(const CXXConstructorDecl *CD, const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCtorClosure(CD, CT); llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); const CXXRecordDecl *RD = CD->getParent(); - QualType RecordTy = getContext().getRecordType(RD); + CanQualType RecordTy = getContext().getCanonicalTagType(RD); llvm::Function *ThunkFn = llvm::Function::Create( ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule()); ThunkFn->setCallingConv(static_cast( @@ -4318,7 +4319,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) { // Turn our record back into a pointer if the exception object is a // pointer. - QualType RTTITy = QualType(Class.RD->getTypeForDecl(), 0); + CanQualType RTTITy = Context.getCanonicalTagType(Class.RD); if (IsPointer) RTTITy = Context.getPointerType(RTTITy); CatchableTypes.insert(getCatchableType(RTTITy, Class.OffsetInVBase, @@ -4469,8 +4470,8 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { std::pair MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, const CXXRecordDecl *RD) { - std::tie(This, std::ignore, RD) = - performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0)); + CanQualType T = CGF.getContext().getCanonicalTagType(RD); + std::tie(This, std::ignore, RD) = performBaseAdjustment(CGF, This, T); return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; } diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 10f9f20bca313..de58e0d95a866 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -66,9 +66,9 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { // Record types. if (auto recType = type->getAs()) { - addTypedData(recType->getDecl(), begin); + addTypedData(recType->getOriginalDecl(), begin); - // Array types. + // Array types. } else if (type->isArrayType()) { // Incomplete array types (flexible array members?) don't provide // data to lay out, and the other cases shouldn't be possible. @@ -814,7 +814,7 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn) { unsigned IndirectAS = CGM.getDataLayout().getAllocaAddrSpace(); if (auto recordType = dyn_cast(type)) { - auto record = recordType->getDecl(); + auto record = recordType->getOriginalDecl(); auto &layout = CGM.getContext().getASTRecordLayout(record); if (mustPassRecordIndirectly(CGM, record)) @@ -822,7 +822,8 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, /*AddrSpace=*/IndirectAS, /*byval=*/false); SwiftAggLowering lowering(CGM); - lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout); + lowering.addTypedData(recordType->getOriginalDecl(), CharUnits::Zero(), + layout); lowering.finish(); return classifyExpandedType(lowering, forReturn, layout.getAlignment(), diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index b82c46966cf0b..289f8a9dcf211 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -375,7 +375,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, if (!passAsAggregateType(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > 128) @@ -496,7 +496,7 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, const RecordType *RT = Ty->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { for (const auto &I : CXXRD->bases()) if (!Self(Self, I.getType())) @@ -548,7 +548,8 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, if (!passAsAggregateType(RetTy)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 128) @@ -744,7 +745,7 @@ bool AArch64ABIInfo::passAsPureScalableType( return false; // Pure scalable types are never unions and never contain unions. - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) return false; diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 47a552a7bf495..41bccbb5721b2 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -96,7 +96,7 @@ unsigned AMDGPUABIInfo::numRegsForType(QualType Ty) const { } if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); assert(!RD->hasFlexibleArrayMember()); for (const FieldDecl *Field : RD->fields()) { @@ -153,7 +153,7 @@ ABIArgInfo AMDGPUABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const RecordType *RT = RetTy->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return DefaultABIInfo::classifyReturnType(RetTy); } @@ -246,7 +246,7 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic, return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return DefaultABIInfo::classifyArgumentType(Ty); } diff --git a/clang/lib/CodeGen/Targets/ARC.cpp b/clang/lib/CodeGen/Targets/ARC.cpp index c8db7e8f9706e..ace524e1976d9 100644 --- a/clang/lib/CodeGen/Targets/ARC.cpp +++ b/clang/lib/CodeGen/Targets/ARC.cpp @@ -106,13 +106,14 @@ ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32; if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. - if (RT && RT->getDecl()->hasFlexibleArrayMember()) + if (RT && + RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectByValue(Ty); // Ignore empty structs/unions. diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index 68f9e01856486..532ba4cead244 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -383,7 +383,7 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) { - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); } if (const auto *EIT = Ty->getAs()) @@ -516,7 +516,7 @@ static bool isIntegerLikeType(QualType Ty, ASTContext &Context, if (!RT) return false; // Ignore records with flexible arrays. - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return false; @@ -593,7 +593,8 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, if (!isAggregateTypeForABI(RetTy)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 64) @@ -718,7 +719,7 @@ bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { return false; return containsAnyFP16Vectors(AT->getElementType()); } else if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) diff --git a/clang/lib/CodeGen/Targets/BPF.cpp b/clang/lib/CodeGen/Targets/BPF.cpp index 880a891083c3a..87d50e671d251 100644 --- a/clang/lib/CodeGen/Targets/BPF.cpp +++ b/clang/lib/CodeGen/Targets/BPF.cpp @@ -48,7 +48,7 @@ class BPFABIInfo : public DefaultABIInfo { } if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); ASTContext &Context = getContext(); if (const auto *EIT = Ty->getAs()) @@ -70,7 +70,8 @@ class BPFABIInfo : public DefaultABIInfo { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); ASTContext &Context = getContext(); if (const auto *EIT = RetTy->getAs()) diff --git a/clang/lib/CodeGen/Targets/CSKY.cpp b/clang/lib/CodeGen/Targets/CSKY.cpp index ef26d483a180a..7e5a16f30727f 100644 --- a/clang/lib/CodeGen/Targets/CSKY.cpp +++ b/clang/lib/CodeGen/Targets/CSKY.cpp @@ -116,7 +116,7 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // All integral types are promoted to XLen width, unless passed on the // stack. diff --git a/clang/lib/CodeGen/Targets/Hexagon.cpp b/clang/lib/CodeGen/Targets/Hexagon.cpp index 2976657360650..0c423429eda4f 100644 --- a/clang/lib/CodeGen/Targets/Hexagon.cpp +++ b/clang/lib/CodeGen/Targets/Hexagon.cpp @@ -98,7 +98,7 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty, if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); uint64_t Size = getContext().getTypeSize(Ty); if (Size <= 64) @@ -161,7 +161,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { if (!isAggregateTypeForABI(RetTy)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (Size > 64 && RetTy->isBitIntType()) return getNaturalAlignIndirect( diff --git a/clang/lib/CodeGen/Targets/Lanai.cpp b/clang/lib/CodeGen/Targets/Lanai.cpp index 6f75bd54a8ef2..08cb36034f6fd 100644 --- a/clang/lib/CodeGen/Targets/Lanai.cpp +++ b/clang/lib/CodeGen/Targets/Lanai.cpp @@ -102,7 +102,8 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. - if (RT && RT->getDecl()->hasFlexibleArrayMember()) + if (RT && + RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectResult(Ty, /*ByVal=*/true, State); // Ignore empty structs/unions. @@ -125,7 +126,7 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, // Treat an enum type as its underlying type. if (const auto *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); bool InReg = shouldUseInReg(Ty, State); diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 7640f3779816a..af863e6101e2c 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -150,7 +150,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( // Non-zero-length arrays of empty records make the struct ineligible to be // passed via FARs in C++. if (const auto *RTy = EltTy->getAs()) { - if (ArraySize != 0 && isa(RTy->getDecl()) && + if (ArraySize != 0 && isa(RTy->getOriginalDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; } @@ -169,7 +169,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( // copy constructor are not eligible for the FP calling convention. if (getRecordArgABI(Ty, CGT.getCXXABI())) return false; - const RecordDecl *RD = RTy->getDecl(); + const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf(); if (isEmptyRecord(getContext(), Ty, true, true) && (!RD->isUnion() || !isa(RD))) return true; @@ -181,7 +181,9 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { for (const CXXBaseSpecifier &B : CXXRD->bases()) { const auto *BDecl = - cast(B.getType()->castAs()->getDecl()); + cast( + B.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); if (!detectFARsEligibleStructHelper( B.getType(), CurOff + Layout.getBaseClassOffset(BDecl), Field1Ty, Field1Off, Field2Ty, Field2Off)) @@ -369,7 +371,7 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // All integral types are promoted to GRLen width. if (Size < GRLen && Ty->isIntegralOrEnumerationType()) diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp index c025f7312959c..e12a34ce07bbe 100644 --- a/clang/lib/CodeGen/Targets/Mips.cpp +++ b/clang/lib/CodeGen/Targets/Mips.cpp @@ -161,7 +161,7 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const { return llvm::StructType::get(getVMContext(), ArgList); } - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); assert(!(TySize % 8) && "Size of structure must be multiple of 8."); @@ -242,7 +242,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Make sure we pass indirectly things that are too large. if (const auto *EIT = Ty->getAs()) @@ -265,7 +265,7 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { SmallVector RTList; if (RT && RT->isStructureOrClassType()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); unsigned FieldCnt = Layout.getFieldCount(); @@ -333,7 +333,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Make sure we pass indirectly things that are too large. if (const auto *EIT = RetTy->getAs()) diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 82bdfe2666b52..e874617796f86 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -133,7 +133,7 @@ bool NVPTXABIInfo::isUnsupportedType(QualType T) const { const auto *RT = T->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // If this is a C++ record, check the bases first. if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) @@ -174,7 +174,7 @@ ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect()); @@ -183,7 +183,7 @@ ABIArgInfo NVPTXABIInfo::classifyReturnType(QualType RetTy) const { ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Return aggregates type as indirect by value if (isAggregateTypeForABI(Ty)) { diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 4df4c9f3c3475..38e76399299ec 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -154,7 +154,7 @@ class AIXTargetCodeGenInfo : public TargetCodeGenInfo { bool AIXABIInfo::isPromotableTypeForABI(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Promotable integer types are required to be promoted by the ABI. if (getContext().isPromotableIntegerType(Ty)) @@ -295,7 +295,9 @@ void AIXTargetCodeGenInfo::setTargetAttributes( unsigned Alignment = Context.toBits(Context.getDeclAlign(D)) / 8; const auto *Ty = VarD->getType().getTypePtr(); const RecordDecl *RDecl = - Ty->isRecordType() ? Ty->getAs()->getDecl() : nullptr; + Ty->isRecordType() + ? Ty->getAs()->getOriginalDecl()->getDefinitionOrSelf() + : nullptr; bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage(); auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) { @@ -707,7 +709,7 @@ bool PPC64_SVR4_ABIInfo::isPromotableTypeForABI(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Promotable integer types are required to be promoted by the ABI. if (isPromotableIntegerTypeForABI(Ty)) diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index a7f92981cfbd4..e42bd6c025e7a 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -228,7 +228,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, // Non-zero-length arrays of empty records make the struct ineligible for // the FP calling convention in C++. if (const auto *RTy = EltTy->getAs()) { - if (ArraySize != 0 && isa(RTy->getDecl()) && + if (ArraySize != 0 && isa(RTy->getOriginalDecl()) && isEmptyRecord(getContext(), EltTy, true, true)) return false; } @@ -250,7 +250,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, return false; if (isEmptyRecord(getContext(), Ty, true, true)) return true; - const RecordDecl *RD = RTy->getDecl(); + const RecordDecl *RD = RTy->getOriginalDecl()->getDefinitionOrSelf(); // Unions aren't eligible unless they're empty (which is caught above). if (RD->isUnion()) return false; @@ -259,7 +259,9 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { for (const CXXBaseSpecifier &B : CXXRD->bases()) { const auto *BDecl = - cast(B.getType()->castAs()->getDecl()); + cast( + B.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); CharUnits BaseOff = Layout.getBaseClassOffset(BDecl); bool Ret = detectFPCCEligibleStructHelper(B.getType(), CurOff + BaseOff, Field1Ty, Field1Off, Field2Ty, @@ -673,7 +675,7 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (!isAggregateTypeForABI(Ty) && !Ty->isVectorType()) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // All integral types are promoted to XLen width if (Size < XLen && Ty->isIntegralOrEnumerationType()) { diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index d952c6e117607..237aea755fa29 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -119,7 +119,7 @@ ABIArgInfo SPIRVABIInfo::classifyReturnType(QualType RetTy) const { return DefaultABIInfo::classifyReturnType(RetTy); if (const RecordType *RT = RetTy->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return DefaultABIInfo::classifyReturnType(RetTy); } @@ -187,7 +187,7 @@ ABIArgInfo SPIRVABIInfo::classifyArgumentType(QualType Ty) const { RAA == CGCXXABI::RAA_DirectInMemory); if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return DefaultABIInfo::classifyArgumentType(Ty); } @@ -432,7 +432,7 @@ static llvm::Type *getInlineSpirvType(CodeGenModule &CGM, case SpirvOperandKind::TypeId: { QualType TypeOperand = Operand.getResultType(); if (auto *RT = TypeOperand->getAs()) { - auto *RD = RT->getDecl(); + auto *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); assert(RD->isCompleteDefinition() && "Type completion should have been required in Sema"); diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index 9642196b78c63..1547bed7ea8b2 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -238,7 +238,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Integer types smaller than a register are extended. if (Size < 64 && Ty->isIntegerType()) diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 6ea6c7a546436..38cc4d39126be 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -146,7 +146,7 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo { bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); // Promotable integer types are required to be promoted by the ABI. if (ABIInfo::isPromotableIntegerTypeForABI(Ty)) @@ -211,7 +211,7 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { const RecordType *RT = Ty->getAs(); if (RT && RT->isStructureOrClassType()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); QualType Found; // If this is a C++ record, check the bases first. @@ -455,7 +455,7 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { if (const RecordType *RT = Ty->getAs()) { // Structures with flexible arrays have variable length, so really // fail the size test above. - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->hasFlexibleArrayMember()) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); @@ -526,7 +526,7 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty, return true; if (const auto *RecordTy = Ty->getAs()) { - const RecordDecl *RD = RecordTy->getDecl(); + const RecordDecl *RD = RecordTy->getOriginalDecl()->getDefinitionOrSelf(); if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) if (CXXRD->hasDefinition()) for (const auto &I : CXXRD->bases()) diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index 9217c78a540a3..ac8dcd2a0540a 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -118,7 +118,8 @@ ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const { const RecordType *RT = Ty->getAs(); assert(RT); bool HasBitField = false; - for (auto *Field : RT->getDecl()->fields()) { + for (auto *Field : + RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { if (Field->isBitField()) { HasBitField = true; break; diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index abb91486e7ee6..d3431aae0431c 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -359,7 +359,8 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, // Structure types are passed in register if all fields would be // passed in a register. - for (const auto *FD : RT->getDecl()->fields()) { + for (const auto *FD : + RT->getOriginalDecl()->getDefinitionOrSelf()->fields()) { // Empty fields are ignored. if (isEmptyField(Context, FD, true)) continue; @@ -429,9 +430,9 @@ bool X86_32ABIInfo::canExpandIndirectArgument(QualType Ty) const { const RecordType *RT = Ty->getAs(); if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); uint64_t Size = 0; - if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); + if (const auto *CXXRD = dyn_cast(RD)) { if (!IsWin32StructABI) { // On non-Windows, we have to conservatively match our old bitcode // prototypes in order to be ABI-compatible at the bitcode level. @@ -509,7 +510,9 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, if (isAggregateTypeForABI(RetTy)) { if (const RecordType *RT = RetTy->getAs()) { // Structures with flexible arrays are always indirect. - if (RT->getDecl()->hasFlexibleArrayMember()) + if (RT->getOriginalDecl() + ->getDefinitionOrSelf() + ->hasFlexibleArrayMember()) return getIndirectReturnResult(RetTy, State); } @@ -554,7 +557,7 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 64) @@ -796,7 +799,8 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (isAggregateTypeForABI(Ty)) { // Structures with flexible arrays are always indirect. // FIXME: This should not be byval! - if (RT && RT->getDecl()->hasFlexibleArrayMember()) + if (RT && + RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getIndirectResult(Ty, true, State); // Ignore empty structs/unions on non-Windows. @@ -831,7 +835,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, unsigned AlignInBits = 0; if (RT) { const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(RT->getDecl()); + getContext().getASTRecordLayout(RT->getOriginalDecl()); AlignInBits = getContext().toBits(Layout.getRequiredAlignment()); } else if (TI.isAlignRequired()) { AlignInBits = TI.Align; @@ -883,7 +887,7 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); bool InReg = shouldPrimitiveUseInReg(Ty, State); @@ -1847,7 +1851,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, if (const EnumType *ET = Ty->getAs()) { // Classify the underlying integer type. - classify(ET->getDecl()->getIntegerType(), OffsetBase, Lo, Hi, isNamedArg); + classify(ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(), + OffsetBase, Lo, Hi, isNamedArg); return; } @@ -2053,7 +2058,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, if (getRecordArgABI(RT, getCXXABI())) return; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); // Assume variable sized types are passed in memory. if (RD->hasFlexibleArrayMember()) @@ -2070,7 +2075,9 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, assert(!I.isVirtual() && !I.getType()->isDependentType() && "Unexpected base class!"); const auto *Base = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // Classify this field. // @@ -2184,7 +2191,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const { if (!isAggregateTypeForABI(Ty)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (Ty->isBitIntType()) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); @@ -2226,7 +2233,7 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, !Ty->isBitIntType()) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect()); @@ -2347,7 +2354,7 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, } if (const RecordType *RT = Ty->getAs()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); // If this is a C++ record, check the bases first. @@ -2356,7 +2363,9 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, assert(!I.isVirtual() && !I.getType()->isDependentType() && "Unexpected base class!"); const auto *Base = - cast(I.getType()->castAs()->getDecl()); + cast( + I.getType()->castAs()->getOriginalDecl()) + ->getDefinitionOrSelf(); // If the base is after the span we care about, ignore it. unsigned BaseOffset = Context.toBits(Layout.getBaseClassOffset(Base)); @@ -2637,7 +2646,8 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy) const { if (Hi == NoClass && isa(ResType)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) - RetTy = EnumTy->getDecl()->getIntegerType(); + RetTy = + EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (RetTy->isIntegralOrEnumerationType() && isPromotableIntegerTypeForABI(RetTy)) @@ -2787,7 +2797,7 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, if (Hi == NoClass && isa(ResType)) { // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); if (Ty->isIntegralOrEnumerationType() && isPromotableIntegerTypeForABI(Ty)) @@ -2866,14 +2876,15 @@ ABIArgInfo X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, unsigned &NeededSSE, unsigned &MaxVectorWidth) const { - auto RT = Ty->getAs(); - assert(RT && "classifyRegCallStructType only valid with struct types"); + auto *RD = cast(Ty.getCanonicalType()) + ->getOriginalDecl() + ->getDefinitionOrSelf(); - if (RT->getDecl()->hasFlexibleArrayMember()) + if (RD->hasFlexibleArrayMember()) return getIndirectReturnResult(Ty); // Sum up bases - if (auto CXXRD = dyn_cast(RT->getDecl())) { + if (auto CXXRD = dyn_cast(RD)) { if (CXXRD->isDynamicClass()) { NeededInt = NeededSSE = 0; return getIndirectReturnResult(Ty); @@ -2889,7 +2900,7 @@ X86_64ABIInfo::classifyRegCallStructTypeImpl(QualType Ty, unsigned &NeededInt, } // Sum up members - for (const auto *FD : RT->getDecl()->fields()) { + for (const auto *FD : RD->fields()) { QualType MTy = FD->getType(); if (MTy->isRecordType() && !MTy->isUnionType()) { if (classifyRegCallStructTypeImpl(MTy, NeededInt, NeededSSE, @@ -3313,7 +3324,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, return ABIArgInfo::getIgnore(); if (const EnumType *EnumTy = Ty->getAs()) - Ty = EnumTy->getDecl()->getIntegerType(); + Ty = EnumTy->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); TypeInfo Info = getContext().getTypeInfo(Ty); uint64_t Width = Info.Width; @@ -3327,7 +3338,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, RAA == CGCXXABI::RAA_DirectInMemory); } - if (RT->getDecl()->hasFlexibleArrayMember()) + if (RT->getOriginalDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember()) return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); } diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index b7824bde5f55a..aa6947b1d956b 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -379,7 +379,7 @@ static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, // We collect all encoded fields and order as necessary. bool IsRecursive = false; - const RecordDecl *RD = RT->getDecl()->getDefinition(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); if (RD && !RD->field_empty()) { // An incomplete TypeString stub is placed in the cache for this RecordType // so that recursive calls to this RecordType will use it whilst building a @@ -428,7 +428,7 @@ static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, Enc += "){"; // We collect all encoded enumerations and order them alphanumerically. - if (const EnumDecl *ED = ET->getDecl()->getDefinition()) { + if (const EnumDecl *ED = ET->getOriginalDecl()->getDefinition()) { SmallVector FE; for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) { diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 51a6f6b779e77..541af6d587174 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -205,45 +205,39 @@ DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) { // Build declaration fragments for NNS recursively so that we have the USR for // every part in a qualified name, and also leaves the actual underlying type // cleaner for its own fragment. -DeclarationFragments -DeclarationFragmentsBuilder::getFragmentsForNNS(const NestedNameSpecifier *NNS, - ASTContext &Context, - DeclarationFragments &After) { +DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNNS( + NestedNameSpecifier NNS, ASTContext &Context, DeclarationFragments &After) { DeclarationFragments Fragments; - if (NNS->getPrefix()) - Fragments.append(getFragmentsForNNS(NNS->getPrefix(), Context, After)); - - switch (NNS->getKind()) { - case NestedNameSpecifier::Identifier: - Fragments.append(NNS->getAsIdentifier()->getName(), - DeclarationFragments::FragmentKind::Identifier); - break; + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + return Fragments; - case NestedNameSpecifier::Namespace: { - const NamespaceBaseDecl *NS = NNS->getAsNamespace(); - if (const auto *Namespace = dyn_cast(NS); - Namespace && Namespace->isAnonymousNamespace()) + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = NNS.getAsNamespaceAndPrefix(); + Fragments.append(getFragmentsForNNS(Prefix, Context, After)); + if (const auto *NS = dyn_cast(Namespace); + NS && NS->isAnonymousNamespace()) return Fragments; SmallString<128> USR; - index::generateUSRForDecl(NS, USR); - Fragments.append(NS->getName(), - DeclarationFragments::FragmentKind::Identifier, USR, NS); + index::generateUSRForDecl(Namespace, USR); + Fragments.append(Namespace->getName(), + DeclarationFragments::FragmentKind::Identifier, USR, + Namespace); break; } - case NestedNameSpecifier::Global: + case NestedNameSpecifier::Kind::Global: // The global specifier `::` at the beginning. No stored value. break; - case NestedNameSpecifier::Super: + case NestedNameSpecifier::Kind::MicrosoftSuper: // Microsoft's `__super` specifier. Fragments.append("__super", DeclarationFragments::FragmentKind::Keyword); break; - case NestedNameSpecifier::TypeSpec: { - const Type *T = NNS->getAsType(); + case NestedNameSpecifier::Kind::Type: { // FIXME: Handle C++ template specialization type - Fragments.append(getFragmentsForType(T, Context, After)); + Fragments.append(getFragmentsForType(NNS.getAsType(), Context, After)); break; } } @@ -273,26 +267,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( return Fragments; } - // An ElaboratedType is a sugar for types that are referred to using an - // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a - // qualified name, e.g., `N::M::type`, or both. - if (const ElaboratedType *ET = dyn_cast(T)) { - ElaboratedTypeKeyword Keyword = ET->getKeyword(); - if (Keyword != ElaboratedTypeKeyword::None) { - Fragments - .append(ElaboratedType::getKeywordName(Keyword), - DeclarationFragments::FragmentKind::Keyword) - .appendSpace(); - } - - if (const NestedNameSpecifier *NNS = ET->getQualifier()) - Fragments.append(getFragmentsForNNS(NNS, Context, After)); - - // After handling the elaborated keyword or qualified name, build - // declaration fragments for the desugared underlying type. - return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); - } - // If the type is a typedefed type, get the underlying TypedefNameDecl for a // direct reference to the typedef instead of the wrapped type. @@ -303,7 +277,18 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( TypedefUnderlyingTypeResolver TypedefResolver(Context); std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); - if (T->isObjCIdType()) { + if (ElaboratedTypeKeyword Keyword = TypedefTy->getKeyword(); + Keyword != ElaboratedTypeKeyword::None) { + Fragments + .append(KeywordHelpers::getKeywordName(Keyword), + DeclarationFragments::FragmentKind::Keyword) + .appendSpace(); + } + + Fragments.append( + getFragmentsForNNS(TypedefTy->getQualifier(), Context, After)); + + if (TypedefTy->isObjCIdType()) { return Fragments.append(Decl->getName(), DeclarationFragments::FragmentKind::Keyword); } @@ -396,14 +381,26 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( if (const TemplateSpecializationType *TemplSpecTy = dyn_cast(T)) { - const auto TemplName = TemplSpecTy->getTemplateName(); + if (ElaboratedTypeKeyword Keyword = TemplSpecTy->getKeyword(); + Keyword != ElaboratedTypeKeyword::None) + Fragments + .append(KeywordHelpers::getKeywordName(Keyword), + DeclarationFragments::FragmentKind::Keyword) + .appendSpace(); + + auto TemplName = TemplSpecTy->getTemplateName(); std::string Str; raw_string_ostream Stream(Str); TemplName.print(Stream, Context.getPrintingPolicy(), TemplateName::Qualified::AsWritten); SmallString<64> USR(""); + if (const auto *QTN = TemplName.getAsQualifiedTemplateName()) { + Fragments.append(getFragmentsForNNS(QTN->getQualifier(), Context, After)); + TemplName = QTN->getUnderlyingTemplate(); + } if (const auto *TemplDecl = TemplName.getAsTemplateDecl()) index::generateUSRForDecl(TemplDecl, USR); + // FIXME: Handle other kinds of TemplateNames. return Fragments .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR) @@ -413,14 +410,19 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( .append(">", DeclarationFragments::FragmentKind::Text); } - // Everything we care about has been handled now, reduce to the canonical - // unqualified base type. - QualType Base = T->getCanonicalTypeUnqualified(); - // If the base type is a TagType (struct/interface/union/class/enum), let's // get the underlying Decl for better names and USRs. - if (const TagType *TagTy = dyn_cast(Base)) { - const TagDecl *Decl = TagTy->getDecl(); + if (const TagType *TagTy = dyn_cast(T)) { + if (ElaboratedTypeKeyword Keyword = TagTy->getKeyword(); + Keyword != ElaboratedTypeKeyword::None) + Fragments + .append(KeywordHelpers::getKeywordName(Keyword), + DeclarationFragments::FragmentKind::Keyword) + .appendSpace(); + + Fragments.append(getFragmentsForNNS(TagTy->getQualifier(), Context, After)); + + const TagDecl *Decl = TagTy->getOriginalDecl(); // Anonymous decl, skip this fragment. if (Decl->getName().empty()) return Fragments.append("{ ... }", @@ -432,6 +434,10 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( TagUSR, Decl); } + // Everything we care about has been handled now, reduce to the canonical + // unqualified base type. + QualType Base = T->getCanonicalTypeUnqualified(); + // If the base type is an ObjCInterfaceType, use the underlying // ObjCInterfaceDecl for the true USR. if (const auto *ObjCIT = dyn_cast(Base)) { diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp index 41e4e0cf1795f..5adbbc6d1c34c 100644 --- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp +++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp @@ -26,7 +26,7 @@ TypedefUnderlyingTypeResolver::getUnderlyingTypeDecl(QualType Type) const { if (TypedefTy) TypeDecl = TypedefTy->getDecl(); if (const TagType *TagTy = Type->getAs()) { - TypeDecl = TagTy->getDecl(); + TypeDecl = TagTy->getOriginalDecl(); } else if (const ObjCInterfaceType *ObjCITy = Type->getAs()) { TypeDecl = ObjCITy->getDecl(); diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp index ab8a35a189250..67c8761511e0c 100644 --- a/clang/lib/Frontend/ASTConsumers.cpp +++ b/clang/lib/Frontend/ASTConsumers.cpp @@ -97,6 +97,7 @@ namespace { Out << "Not a DeclContext\n"; } else if (OutputKind == Print) { PrintingPolicy Policy(D->getASTContext().getLangOpts()); + Policy.IncludeTagDefinition = true; D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); } else if (OutputKind != None) { D->dump(Out, OutputKind == DumpFull, OutputFormat); @@ -112,8 +113,10 @@ namespace { // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups. if (auto *VD = dyn_cast(InnerD)) VD->getType().dump(Out, VD->getASTContext()); - if (auto *TD = dyn_cast(InnerD)) - TD->getTypeForDecl()->dump(Out, TD->getASTContext()); + if (auto *TD = dyn_cast(InnerD)) { + const ASTContext &Ctx = TD->getASTContext(); + Ctx.getTypeDeclType(TD)->dump(Out, Ctx); + } } } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index a4078257a889f..03b08cdabe39e 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -396,7 +396,7 @@ void ASTUnit::CacheCodeCompletionResults() { // Keep track of the type of this completion in an ASTContext-agnostic // way. - QualType UsageType = getDeclUsageType(*Ctx, R.Declaration); + QualType UsageType = getDeclUsageType(*Ctx, R.Qualifier, R.Declaration); if (UsageType.isNull()) { CachedResult.TypeClass = STC_Void; CachedResult.Type = 0; diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index adc33b3abd822..9a699c3c896de 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -59,7 +59,7 @@ class TypeIndexer : public RecursiveASTVisitor { bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { SourceLocation Loc = TL.getNameLoc(); - TypedefNameDecl *ND = TL.getTypedefNameDecl(); + TypedefNameDecl *ND = TL.getDecl(); if (ND->isTransparentTag()) { TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl(); return IndexCtx.handleReference(Underlying, Loc, Parent, @@ -117,7 +117,7 @@ class TypeIndexer : public RecursiveASTVisitor { } bool VisitTagTypeLoc(TagTypeLoc TL) { - TagDecl *D = TL.getDecl(); + TagDecl *D = TL.getOriginalDecl(); if (!IndexCtx.shouldIndexFunctionLocalSymbols() && D->getParentFunctionOrMethod()) return true; @@ -172,7 +172,8 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + bool TraverseTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL, + bool TraverseQualifier) { if (!WalkUpFromTemplateSpecializationTypeLoc(TL)) return false; if (!TraverseTemplateName(TL.getTypePtr()->getTemplateName())) @@ -202,11 +203,6 @@ class TypeIndexer : public RecursiveASTVisitor { return true; } - bool VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - return IndexCtx.handleReference(TL.getDecl(), TL.getNameLoc(), Parent, - ParentDC, SymbolRoleSet(), Relations); - } - bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { std::vector Symbols = IndexCtx.getResolver()->resolveDependentNameType(TL.getTypePtr()); @@ -248,32 +244,28 @@ void IndexingContext::indexTypeLoc(TypeLoc TL, TypeIndexer(*this, Parent, DC, isBase, isIBType).TraverseTypeLoc(TL); } -void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, - const NamedDecl *Parent, - const DeclContext *DC) { - if (!NNS) - return; - - if (NestedNameSpecifierLoc Prefix = NNS.getPrefix()) - indexNestedNameSpecifierLoc(Prefix, Parent, DC); - +void IndexingContext::indexNestedNameSpecifierLoc( + NestedNameSpecifierLoc QualifierLoc, const NamedDecl *Parent, + const DeclContext *DC) { if (!DC) DC = Parent->getLexicalDeclContext(); - SourceLocation Loc = NNS.getLocalBeginLoc(); - - switch (NNS.getNestedNameSpecifier()->getKind()) { - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: + switch (NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier(); + Qualifier.getKind()) { + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::MicrosoftSuper: break; - case NestedNameSpecifier::Namespace: - handleReference(NNS.getNestedNameSpecifier()->getAsNamespace(), - Loc, Parent, DC, SymbolRoleSet()); + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = QualifierLoc.castAsNamespaceAndPrefix(); + indexNestedNameSpecifierLoc(Prefix, Parent, DC); + handleReference(Namespace, QualifierLoc.getLocalBeginLoc(), Parent, DC, + SymbolRoleSet()); break; + } - case NestedNameSpecifier::TypeSpec: - indexTypeLoc(NNS.getTypeLoc(), Parent, DC); + case NestedNameSpecifier::Kind::Type: + indexTypeLoc(QualifierLoc.castAsTypeLoc(), Parent, DC); break; } } diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 6a884f7be00e1..6bdddcc6967c9 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -653,14 +653,14 @@ bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { } static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts, - NestedNameSpecifier *NNS) { + NestedNameSpecifier NNS) { // FIXME: Encode the qualifier, don't just print it. PrintingPolicy PO(LangOpts); PO.SuppressTagKeyword = true; PO.SuppressUnwrittenScope = true; PO.ConstantArraySizeAsWritten = false; PO.AnonymousTagLocations = false; - NNS->print(Out, PO); + NNS.print(Out, PO); } void USRGenerator::VisitType(QualType T) { @@ -910,9 +910,14 @@ void USRGenerator::VisitType(QualType T) { continue; } if (const TagType *TT = T->getAs()) { - Out << '$'; - VisitTagDecl(TT->getDecl()); - return; + if (const auto *ICNT = dyn_cast(TT)) { + T = ICNT->getOriginalDecl()->getCanonicalTemplateSpecializationType( + Ctx); + } else { + Out << '$'; + VisitTagDecl(TT->getOriginalDecl()); + return; + } } if (const ObjCInterfaceType *OIT = T->getAs()) { Out << '$'; @@ -945,10 +950,6 @@ void USRGenerator::VisitType(QualType T) { Out << ':' << DNT->getIdentifier()->getName(); return; } - if (const InjectedClassNameType *InjT = T->getAs()) { - T = InjT->getInjectedSpecializationType(); - continue; - } if (const auto *VT = T->getAs()) { Out << (T->isExtVectorType() ? ']' : '['); Out << VT->getNumElements(); diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index 487be2c300887..f12e04069817b 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -424,7 +424,7 @@ std::string InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const { SmallString<256> Name; raw_svector_ostream NameStream(Name); - MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream); + MC->mangleCXXRTTIName(MC->getASTContext().getCanonicalTagType(D), NameStream); return getBackendMangledName(Name); } @@ -432,7 +432,7 @@ InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const { std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const { SmallString<256> Name; raw_svector_ostream NameStream(Name); - MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream); + MC->mangleCXXRTTI(MC->getASTContext().getCanonicalTagType(D), NameStream); return getBackendMangledName(Name); } @@ -543,8 +543,8 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, } for (const auto &It : D->bases()) { - const CXXRecordDecl *Base = - cast(It.getType()->castAs()->getDecl()); + const CXXRecordDecl *Base = cast( + It.getType()->castAs()->getOriginalDecl()); const auto BaseAccess = getAccessForDecl(Base); if (!BaseAccess) continue; diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp index 0ea6274b79cba..4f5f43e1b3ade 100644 --- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp +++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp @@ -66,10 +66,10 @@ static std::string QualTypeToString(ASTContext &Ctx, QualType QT) { const QualType NonRefTy = QT.getNonReferenceType(); if (const auto *TTy = llvm::dyn_cast(NonRefTy)) - return DeclTypeToString(NonRefTy, TTy->getDecl()); + return DeclTypeToString(NonRefTy, TTy->getOriginalDecl()); if (const auto *TRy = dyn_cast(NonRefTy)) - return DeclTypeToString(NonRefTy, TRy->getDecl()); + return DeclTypeToString(NonRefTy, TRy->getOriginalDecl()); const QualType Canon = NonRefTy.getCanonicalType(); @@ -105,7 +105,7 @@ static std::string EnumToString(const Value &V) { const EnumType *EnumTy = DesugaredTy.getNonReferenceType()->getAs(); assert(EnumTy && "Fail to cast to enum type"); - EnumDecl *ED = EnumTy->getDecl(); + EnumDecl *ED = EnumTy->getOriginalDecl()->getDefinitionOrSelf(); uint64_t Data = V.convertTo(); bool IsFirst = true; llvm::APSInt AP = Ctx.MakeIntValue(Data, DesugaredTy); @@ -666,7 +666,7 @@ __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, VRef.setPtr(va_arg(args, void *)); } else { if (const auto *ET = QT->getAs()) - QT = ET->getDecl()->getIntegerType(); + QT = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); switch (QT->castAs()->getKind()) { default: llvm_unreachable("unknown type kind!"); diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp index be2ab5587a980..84ba508e9cbc8 100644 --- a/clang/lib/Interpreter/Value.cpp +++ b/clang/lib/Interpreter/Value.cpp @@ -102,7 +102,7 @@ static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT) { return Value::K_Void; if (const auto *ET = QT->getAs()) - QT = ET->getDecl()->getIntegerType(); + QT = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); const auto *BT = QT->getAs(); if (!BT || BT->isNullPtrType()) @@ -149,9 +149,9 @@ Value::Value(const Interpreter *In, void *Ty) : Interp(In), OpaqueType(Ty) { } if (const auto *RT = DtorTy->getAs()) { if (CXXRecordDecl *CXXRD = - llvm::dyn_cast(RT->getDecl())) { + llvm::dyn_cast(RT->getOriginalDecl())) { if (llvm::Expected Addr = - Interp.CompileDtorCall(CXXRD)) + Interp.CompileDtorCall(CXXRD->getDefinitionOrSelf())) DtorF = reinterpret_cast(Addr->getValue()); else llvm::logAllUnhandledErrors(Addr.takeError(), llvm::errs()); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index bc8841c68b42c..3214e6f5fad2d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -591,7 +591,7 @@ bool Parser::ParseUsingDeclarator(DeclaratorContext Context, NextToken().isRegularKeywordAttribute() || NextToken().is(tok::kw___attribute)) && D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && - D.SS.getScopeRep()->getKind() != NestedNameSpecifier::Namespace) { + D.SS.getScopeRep().getKind() != NestedNameSpecifier::Kind::Namespace) { SourceLocation IdLoc = ConsumeToken(); ParsedType Type = Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 8dce2268082d9..8605ba2cdb49b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -195,9 +195,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier( if (DS.getTypeSpecType() == DeclSpec::TST_error) return false; - QualType Type = Actions.ActOnPackIndexingType( - DS.getRepAsType().get(), DS.getPackIndexingExpr(), DS.getBeginLoc(), - DS.getEllipsisLoc()); + QualType Pattern = Sema::GetTypeFromParser(DS.getRepAsType()); + QualType Type = + Actions.ActOnPackIndexingType(Pattern, DS.getPackIndexingExpr(), + DS.getBeginLoc(), DS.getEllipsisLoc()); if (Type.isNull()) return false; @@ -2355,8 +2356,10 @@ bool Parser::ParseUnqualifiedIdTemplateId( // Constructor and destructor names. TypeResult Type = Actions.ActOnTemplateIdType( - getCurScope(), SS, TemplateKWLoc, Template, Name, NameLoc, LAngleLoc, - TemplateArgsPtr, RAngleLoc, /*IsCtorOrDtorName=*/true); + getCurScope(), ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, TemplateKWLoc, Template, + Name, NameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc, + /*IsCtorOrDtorName=*/true); if (Type.isInvalid()) return true; diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 0277dfb5aac13..0c1cd8c2d75c8 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1128,12 +1128,14 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { - TypeResult Type = ArgsInvalid - ? TypeError() - : Actions.ActOnTemplateIdType( - getCurScope(), SS, TemplateKWLoc, Template, - TemplateName.Identifier, TemplateNameLoc, - LAngleLoc, TemplateArgsPtr, RAngleLoc); + TypeResult Type = + ArgsInvalid + ? TypeError() + : Actions.ActOnTemplateIdType( + getCurScope(), ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, TemplateKWLoc, + Template, TemplateName.Identifier, TemplateNameLoc, LAngleLoc, + TemplateArgsPtr, RAngleLoc); Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Type); @@ -1194,10 +1196,11 @@ void Parser::AnnotateTemplateIdTokenAsType( TemplateId->isInvalid() ? TypeError() : Actions.ActOnTemplateIdType( - getCurScope(), SS, TemplateId->TemplateKWLoc, - TemplateId->Template, TemplateId->Name, - TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, - TemplateArgsPtr, TemplateId->RAngleLoc, + getCurScope(), ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc, /*IsCtorOrDtorName=*/false, IsClassName, AllowImplicitTypename); // Create the new "type" annotation token. Tok.setKind(tok::annot_typename); @@ -1263,7 +1266,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Name, /*ObjectType=*/nullptr, /*EnteringContext=*/false, Template)) - Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); + Result = ParsedTemplateArgument(TemplateKWLoc, SS, Template, + Name.StartLocation); } } else if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) || Tok.is(tok::annot_non_type)) { @@ -1300,7 +1304,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { TNK == TNK_Var_template || TNK == TNK_Concept_template) { // We have an id-expression that refers to a class template or // (C++0x) alias template. - Result = ParsedTemplateArgument(SS, Template, Name.StartLocation); + Result = ParsedTemplateArgument(/*TemplateKwLoc=*/SourceLocation(), SS, + Template, Name.StartLocation); } } } diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp index 2a731a18ea82a..82f2294ff5bb7 100644 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1328,7 +1328,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); - if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) { + if (SS.getScopeRep().isDependent()) { RevertingTentativeParsingAction PA(*this); ConsumeAnnotationToken(); ConsumeToken(); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a8cfe202c5214..e57a789251a5b 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1774,9 +1774,9 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC, /// An Objective-C object type followed by '<' is a specialization of /// a parameterized class type or a protocol-qualified type. ParsedType Ty = Classification.getType(); + QualType T = Actions.GetTypeFromParser(Ty); if (getLangOpts().ObjC && NextToken().is(tok::less) && - (Ty.get()->isObjCObjectType() || - Ty.get()->isObjCObjectPointerType())) { + (T->isObjCObjectType() || T->isObjCObjectPointerType())) { // Consume the name. SourceLocation IdentifierLoc = ConsumeToken(); SourceLocation NewEndLoc; @@ -2032,11 +2032,12 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec( if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); + QualType T = Actions.GetTypeFromParser(Ty); + /// An Objective-C object type followed by '<' is a specialization of /// a parameterized class type or a protocol-qualified type. if (getLangOpts().ObjC && NextToken().is(tok::less) && - (Ty.get()->isObjCObjectType() || - Ty.get()->isObjCObjectPointerType())) { + (T->isObjCObjectType() || T->isObjCObjectPointerType())) { // Consume the name. SourceLocation IdentifierLoc = ConsumeToken(); SourceLocation NewEndLoc; diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index fdb630221889b..dd418f71861dc 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(CE->getCallee()->IgnoreParenImpCasts())) { - if (NestedNameSpecifier *NNS = DRE->getQualifier()) { - if (NNS->getKind() == NestedNameSpecifier::TypeSpec && - isa(NNS->getAsType())) { + dyn_cast(CE->getCallee()->IgnoreParenImpCasts())) + if (NestedNameSpecifier NNS = DRE->getQualifier(); + NNS.getKind() == NestedNameSpecifier::Kind::Type) + if (isa_and_nonnull(NNS.getAsType())) continue; - } - } - } const CXXMemberCallExpr *MCE = dyn_cast(CE); if (!MCE || isa(MCE->getImplicitObjectArgument()) || diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index f0f1d66f66e93..8756ce5f0d850 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 87f9ae07550c2..806800cb7b213 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 Attrs, diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index 36c4add20b225..098b72692bd3a 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -64,7 +64,7 @@ class BuiltinTypeDeclBuilder { BuiltinTypeDeclBuilder &addSimpleTemplateParams(ArrayRef 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 6874d30516f8f..9c56dd356421e 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -44,7 +44,7 @@ class HeuristicResolverImpl { resolveDependentNameType(const DependentNameType *DNT); std::vector resolveTemplateSpecializationType( const DependentTemplateSpecializationType *DTST); - QualType resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS); + QualType resolveNestedNameSpecifierToType(NestedNameSpecifier NNS); QualType getPointeeType(QualType T); std::vector lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, @@ -101,9 +101,8 @@ QualType resolveDeclsToType(const std::vector &Decls, ASTContext &Ctx) { if (Decls.size() != 1) // Names an overload set -- just bail. return QualType(); - if (const auto *TD = dyn_cast(Decls[0])) { - return Ctx.getTypeDeclType(TD); - } + if (const auto *TD = dyn_cast(Decls[0])) + return Ctx.getCanonicalTypeDeclType(TD); if (const auto *VD = dyn_cast(Decls[0])) { return VD->getType(); } @@ -139,8 +138,7 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) { T = T->getCanonicalTypeInternal().getTypePtr(); } - if (auto *TT = T->getAs()) { - 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(TD)) { @@ -151,11 +149,6 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) { return TD; } - if (const auto *ICNT = T->getAs()) - T = ICNT->getInjectedSpecializationType().getTypePtrOrNull(); - if (!T) - return nullptr; - TemplateName TN = getReferencedTemplateName(T); if (TN.isNull()) return nullptr; @@ -292,7 +285,7 @@ std::vector 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 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(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 HeuristicResolver::lookupDependentName( diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index cfb2f6013fb1f..12e5c658e7f3a 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1883,9 +1883,10 @@ class DeferredDiagnosticsEmitter for (const FieldDecl *FD : RD->fields()) { QualType FT = FD->getType(); if (const auto *RT = FT->getAs()) - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) - if (ClassDecl->hasDefinition()) - if (CXXDestructorDecl *MemberDtor = ClassDecl->getDestructor()) + if (const auto *ClassDecl = + dyn_cast(RT->getOriginalDecl())) + if (const auto *Def = ClassDecl->getDefinition()) + if (CXXDestructorDecl *MemberDtor = Def->getDestructor()) asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor); } @@ -1893,9 +1894,10 @@ class DeferredDiagnosticsEmitter for (const auto &Base : RD->bases()) { QualType BaseType = Base.getType(); if (const auto *RT = BaseType->getAs()) - if (const auto *BaseDecl = dyn_cast(RT->getDecl())) - if (BaseDecl->hasDefinition()) - if (CXXDestructorDecl *BaseDtor = BaseDecl->getDestructor()) + if (const auto *BaseDecl = + dyn_cast(RT->getOriginalDecl())) + if (const auto *Def = BaseDecl->getDefinition()) + if (CXXDestructorDecl *BaseDtor = Def->getDestructor()) asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor); } } @@ -1908,9 +1910,10 @@ class DeferredDiagnosticsEmitter VD->needsDestruction(S.Context)) { QualType VT = VD->getType(); if (const auto *RT = VT->getAs()) - if (const auto *ClassDecl = dyn_cast(RT->getDecl())) - if (ClassDecl->hasDefinition()) - if (CXXDestructorDecl *Dtor = ClassDecl->getDestructor()) + if (const auto *ClassDecl = + dyn_cast(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 83a07a23f3414..ba560d3c52340 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()) { - RD = cast(RT->getDecl()); - } else if (const InjectedClassNameType *IT - = T->getAs()) { - 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()) - return MatchesFriend(S, EC, cast(RT->getDecl())); + return MatchesFriend( + S, EC, + cast(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()) { - RD = cast(RT->getDecl()); - } else if (const InjectedClassNameType *IT - = T->getAs()) { - 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(D)) PrevDecl = TND->getPreviousDecl(); else if (TagDecl *TD = dyn_cast(D)) { - if (auto *RD = dyn_cast(D); + if (const auto *RD = dyn_cast(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(); - CXXRecordDecl *NamingClass = cast(RT->getDecl()); + CXXRecordDecl *NamingClass = + cast(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 68a698fea1815..1c48b3ca86fbe 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(T)) { - D = TT->getDecl(); + D = TT->getOriginalDecl()->getDefinitionOrSelf(); } else if (isa(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(TyPtr)) { - TagDecl *TD = TT->getDecl(); + TagDecl *TD = TT->getOriginalDecl()->getDefinitionOrSelf(); DiagnoseDeclAvailability(TD, Range); } else if (const auto *TD = dyn_cast(TyPtr)) { diff --git a/clang/lib/Sema/SemaBPF.cpp b/clang/lib/Sema/SemaBPF.cpp index 7c00084d62dd9..6428435ed9d2a 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()) { - if (!RT->getDecl()->getDeclName().isEmpty()) + if (!RT->getOriginalDecl()->getDeclName().isEmpty()) return true; } else if (const auto *ET = Ty->getAs()) { - 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 24cb8c369790b..fbf64d3d57050 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(BaseType->getDecl()); + CXXRecordDecl *BaseClassDecl = + cast(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(FieldType->getDecl()); + CXXRecordDecl *FieldRecDecl = + cast(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 6ac04837708f6..45de8ff3ba264 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(Ty)) { - CXXRecordDecl *Record = cast(RecordTy->getDecl()); - if (Record->isCurrentInstantiation(CurContext)) - return Record; - - return nullptr; - } else if (isa(Ty)) - return cast(Ty)->getDecl(); - else + const TagType *TagTy = dyn_cast(T->getCanonicalTypeInternal()); + if (!isa_and_present(TagTy)) return nullptr; + auto *RD = + cast(TagTy->getOriginalDecl())->getDefinitionOrSelf(); + if (isa(TagTy) || + RD->isCurrentInstantiation(CurContext)) + return RD; + return nullptr; } DeclContext *Sema::computeDeclContext(QualType T) { if (!T->isDependentType()) - if (const TagType *Tag = T->getAs()) - 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()) { + } else if (const auto *RecordT = dyn_cast(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( + NNS.getAsNamespaceAndPrefix().Namespace->getNamespace()); - case NestedNameSpecifier::TypeSpec: { - const TagType *Tag = NNS->getAsType()->getAs(); - 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(SD)); - if (T->isDependentType()) - return true; if (const TypedefNameDecl *TD = dyn_cast(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(SD)) { + if (TD->isDependentType()) + return true; + } else if (Context.getCanonicalTypeDeclType(cast(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(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(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(OuterDecl) || !isa(SD) || !Context.hasSameType( - Context.getTypeDeclType(cast(OuterDecl)), - Context.getTypeDeclType(cast(SD))))) { + Context.getCanonicalTypeDeclType(cast(OuterDecl)), + Context.getCanonicalTypeDeclType(cast(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(SD)) @@ -637,50 +652,44 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, return false; } - QualType T = - Context.getTypeDeclType(cast(SD->getUnderlyingDecl())); - - if (T->isEnumeralType()) + const auto *TD = cast(SD->getUnderlyingDecl()); + if (isa(TD)) Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); + QualType T; TypeLocBuilder TLB; if (const auto *USD = dyn_cast(SD)) { - T = Context.getUsingType(USD, T); - TLB.pushTypeSpec(T).setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - InjectedClassNameTypeLoc InjectedTL - = TLB.push(T); - InjectedTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - RecordTypeLoc RecordTL = TLB.push(T); - RecordTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - TypedefTypeLoc TypedefTL = TLB.push(T); - TypedefTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - EnumTypeLoc EnumTL = TLB.push(T); - EnumTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - TemplateTypeParmTypeLoc TemplateTypeTL - = TLB.push(T); - TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - UnresolvedUsingTypeLoc UnresolvedTL - = TLB.push(T); - UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - SubstTemplateTypeParmTypeLoc TL - = TLB.push(T); - TL.setNameLoc(IdInfo.IdentifierLoc); - } else if (isa(T)) { - SubstTemplateTypeParmPackTypeLoc TL - = TLB.push(T); - TL.setNameLoc(IdInfo.IdentifierLoc); + T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + USD); + TLB.push(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), + IdInfo.IdentifierLoc); + } else if (const auto *Tag = dyn_cast(TD)) { + T = Context.getTagType(ElaboratedTypeKeyword::None, SS.getScopeRep(), Tag, + /*OwnsTag=*/false); + auto TTL = TLB.push(T); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); + TTL.setNameLoc(IdInfo.IdentifierLoc); + } else if (auto *TN = dyn_cast(TD)) { + T = Context.getTypedefType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + TN); + TLB.push(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(SemaRef.Context), + IdInfo.IdentifierLoc); + } else if (auto *UD = dyn_cast(TD)) { + T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), UD); + TLB.push(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(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(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()) { + QualType T; + if (auto *TN = dyn_cast(TD)) { + T = Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TN); + } else { + // FIXME: Enumerate the possibilities here. + assert(!isa(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()) { 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()) { + if (!T->isDependentType() && !isa(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(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(Type.getTypePtr())->getPattern(), DS.getBeginLoc()); PackIndexingTypeLoc PIT = TLB.push(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(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()) { + if (!T->isDependentType() && !isa(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(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(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(CurContext) || isa(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 01252a4bc69c6..da43848a1a7d0 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(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()) { - 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(); - 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(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() || DestTy->getAs()) { + if (isa(SrcTy.getCanonicalType()) || + isa(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(); - - 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()) { + 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 3c4511ba26330..9ecee18661340 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()) { + UT && UT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr()) { if (const auto *CLE = dyn_cast(Expr)) if (const auto *ILE = dyn_cast(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()->getDecl(); + const EnumDecl *ED = Type->castAs() + ->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(RT->getDecl()); - if (!RD || !RD->getDefinition()) + CXXRecordDecl *RD = dyn_cast(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(decl)) @@ -8328,7 +8335,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, bool IsScopedEnum = false; QualType IntendedTy = ExprTy; if (auto EnumTy = ExprTy->getAs()) { - 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(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()->getDecl()->fields()) + for (const FieldDecl *FD : FT->castAs() + ->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()->getDecl()->fields()) + for (const FieldDecl *FD : FT->castAs() + ->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(T)) - T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr(); + T = ET->getOriginalDecl() + ->getDefinitionOrSelf() + ->getIntegerType() + .getDesugaredType(C) + .getTypePtr(); } else if (const auto *ET = dyn_cast(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(T)) T = AT->getValueType().getTypePtr(); if (const EnumType *ET = dyn_cast(T)) - T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr(); + T = C.getCanonicalType( + ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType()) + .getTypePtr(); if (const auto *EIT = dyn_cast(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()->getDecl(); + EnumDecl *BitfieldEnumDecl = BitfieldType->castAs() + ->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(); } 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()) if (const EnumType *TargetEnum = Target->getAs()) - 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(T1)->getDecl(), - cast(T2)->getDecl()); + return isLayoutCompatible( + C, cast(T1)->getOriginalDecl()->getDefinitionOrSelf(), + cast(T2)->getOriginalDecl()->getDefinitionOrSelf()); } else if (TC1 == Type::Record) { if (!T1->isStandardLayoutType() || !T2->isStandardLayoutType()) return false; - return isLayoutCompatible(C, - cast(T1)->getDecl(), - cast(T2)->getDecl()); + return isLayoutCompatible( + C, cast(T1)->getOriginalDecl()->getDefinitionOrSelf(), + cast(T2)->getOriginalDecl()->getDefinitionOrSelf()); } return false; @@ -15592,7 +15617,9 @@ void Sema::RefersToMemberWithReducedAlignment( return; if (ME->isArrow()) BaseType = BaseType->getPointeeType(); - RecordDecl *RD = BaseType->castAs()->getDecl(); + RecordDecl *RD = BaseType->castAs() + ->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() || FDI->getParent()->hasAttr()) { 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 0de55800ccdd1..e4f276086af25 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 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(Parent)) - Result = NestedNameSpecifier::Create( - Context, Result, Context.getTypeDeclType(TD).getTypePtr()); + Result = NestedNameSpecifier(Context, Namespace, Result); + } else if (const auto *TD = dyn_cast(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(ND)) - return C.getTypeDeclType(Type); + return C.getTypeDeclType(ElaboratedTypeKeyword::None, Qualifier, Type); if (const auto *Iface = dyn_cast(ND)) return C.getObjCInterfaceType(Iface); @@ -951,7 +954,9 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { else if (const auto *Method = dyn_cast(ND)) T = Method->getSendResultType(); else if (const auto *Enumerator = dyn_cast(ND)) - T = C.getTypeDeclType(cast(Enumerator->getDeclContext())); + T = C.getTagType(ElaboratedTypeKeyword::None, Qualifier, + cast(Enumerator->getDeclContext()), + /*OwnsTag=*/false); else if (const auto *Property = dyn_cast(ND)) T = Property->getType(); else if (const auto *Value = dyn_cast(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(Ctx)) R.Qualifier = - NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt); else if (const TagDecl *Tag = dyn_cast(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(Ctx)) R.Qualifier = - NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); + NestedNameSpecifier(SemaRef.Context, Namespace, std::nullopt); else if (const auto *Tag = dyn_cast(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 @@ class CodeCompletionDeclConsumer : public VisibleDeclConsumer { 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(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(ND)) { - T = Context.getTypeDeclType(cast(Enumerator->getDeclContext())); - T = clang::TypeName::getFullyQualifiedType(T, Context); + T = Context.getCanonicalTagType( + cast(Enumerator->getDeclContext())); } else if (isa(ND)) { /* Do nothing: ignore unresolved using declarations*/ } else if (const auto *Ivar = dyn_cast(ND)) { @@ -3021,7 +3032,7 @@ static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo, if (!SuppressBlock) { if (TypedefTypeLoc TypedefTL = TL.getAsAdjusted()) { 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()) - Record = cast(RecordTy->getDecl()); - else if (const auto *InjectedTy = Ty->getAs()) - 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 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()->getDecl(); - if (auto *Def = Enum->getDefinition()) - Enum = Def; + EnumDecl *Enum = Data.PreferredType->castAs() + ->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 @@ class ConceptInfo { // 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 @@ class ConceptInfo { // 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(NNST)) + addType(DNT->getIdentifier()); + } } // FIXME: also handle T::foo::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(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()->getDecl(); - if (EnumDecl *Def = Enum->getDefinition()) - Enum = Def; + EnumDecl *Enum = + type->castAs()->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(NNS->getAsType())) { + if (NNS.getKind() == NestedNameSpecifier::Kind::Type) { + if (const auto *TTPT = dyn_cast(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(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(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(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 d193a33f22393..cc03616e0dfe1 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(ReturnType.getCanonicalType().getTypePtr()); - checkDeclNoexcept(cast(T->getDecl())->getDestructor(), + checkDeclNoexcept(cast(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 b5eb825eb52cc..cb59782b83304 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(LookupCtx); auto *FoundRD = dyn_cast(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()) - BaseRD = BaseTT->getAsCXXRecordDecl(); - else if (auto *TST = Base.getType()->getAs()) { + const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl(); + if (BaseRD) { + } else if (auto *TST = dyn_cast( + 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(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(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(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(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(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + NameLoc); + } else if (auto *Tag = dyn_cast(TD)) { + T = Context.getTagType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, Tag, + /*OwnsTag=*/false); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + auto TL = TLB.push(T); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS ? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc()); + TL.setNameLoc(NameLoc); + } else if (auto *TN = dyn_cast(TD); + TN && !isa(TN)) { + T = Context.getTypedefType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, TN); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + TLB.push(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + NameLoc); + } else if (auto *UD = dyn_cast(TD)) { + T = Context.getUnresolvedUsingType(ElaboratedTypeKeyword::None, + SS ? SS->getScopeRep() : std::nullopt, + UD); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + TLB.push(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc(), + NameLoc); + } else { + T = Context.getTypeDeclType(TD); + if (!WantNontrivialTypeSourceInfo) + return ParsedType::make(T); + if (isa(T)) + TLB.push(T).setNameLoc(NameLoc); + else + TLB.pushTypeSpec(T).setNameLoc(NameLoc); + } + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + if (ObjCInterfaceDecl *IDecl = dyn_cast(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(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(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(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(DC); if (ND && !ND->isInline() && !ND->isAnonymousNamespace()) - return NestedNameSpecifier::Create(Context, nullptr, ND); + return NestedNameSpecifier(Context, ND, std::nullopt); if (auto *RD = dyn_cast(DC)) - return NestedNameSpecifier::Create(Context, nullptr, - RD->getTypeForDecl()); + return NestedNameSpecifier(Context.getCanonicalTagType(RD)->getTypePtr()); if (isa(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(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(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 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, } auto BuildTypeFor = [&](TypeDecl *Type, NamedDecl *Found) { - QualType T = Context.getTypeDeclType(Type); - if (const auto *USD = dyn_cast(Found)) - T = Context.getUsingType(USD, T); - return buildNamedType(*this, &SS, T, NameLoc); + QualType T; + TypeLocBuilder TLB; + if (const auto *USD = dyn_cast(Found)) { + T = Context.getUsingType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + USD); + TLB.push(T).set(/*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameLoc); + } else { + T = Context.getTypeDeclType(ElaboratedTypeKeyword::None, SS.getScopeRep(), + Type); + if (isa(T)) { + auto TTL = TLB.push(T); + TTL.setElaboratedKeywordLoc(SourceLocation()); + TTL.setQualifierLoc(SS.getWithLocInContext(Context)); + TTL.setNameLoc(NameLoc); + } else if (isa(T)) { + TLB.push(T).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameLoc); + } else if (isa(T)) { + TLB.push(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()) { - const TagDecl *Tag = TT->getDecl(); + if (const TagDecl *Tag = Ty->getAsTagDecl()) { if (Tag->hasAttr()) 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()) { - const TagDecl *Tag = TT->getDecl(); + if (const TagDecl *Tag = Ty->getAsTagDecl()) { if (Tag->hasAttr()) 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(New)) Ty = VD->getType(); else - Ty = S.Context.getTagDeclType(cast(New)); + Ty = S.Context.getCanonicalTagType(cast(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(D)) - return TD->getDefinition(); + if (const TagDecl *TD = dyn_cast(D)) { + if (const auto *Def = TD->getDefinition(); Def && !Def->isBeingDefined()) + return Def; + return nullptr; + } if (const VarDecl *VD = dyn_cast(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(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(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(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(Cur)))) + !Context.hasSameType( + Name.getCXXNameType(), + Context.getCanonicalTagType(cast(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()) { - // 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()) { - // 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(); + 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().getQualifierLoc().getAsTypeLoc(); + break; + case TypeLoc::DependentTemplateSpecialization: { + auto TST = TL.castAs(); + 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()->getDecl(); + const RecordDecl *PD = + PT->castAs()->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()->getDecl(); + RD = FieldRecTy->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); } else { RD = cast(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; 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()->getDecl(); + const RecordDecl *RD = + QT->castAs()->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()->getDecl(); + const RecordDecl *RD = + QT->castAs()->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()->getDecl(); + const RecordDecl *RD = + QT->castAs()->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()) { - CXXRecordDecl *CXXRecord = cast(Record->getDecl()); + CXXRecordDecl *CXXRecord = + cast(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(PrevDecl)) { - if (const TagType *TT = TD->getUnderlyingType()->getAs()) { - 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(PrevDecl); + RD && RD->isInjectedClassName()) { + // If lookup found the injected class name, the previous declaration is + // the class being injected into. + PrevDecl = cast(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(Def)) - IsExplicitSpecializationAfterInstantiation = - RD->getTemplateSpecializationKind() != - TSK_ExplicitSpecialization; - else if (EnumDecl *ED = dyn_cast(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(Def)) + IsExplicitSpecializationAfterInstantiation = + RD->getTemplateSpecializationKind() != + TSK_ExplicitSpecialization; + else if (EnumDecl *ED = dyn_cast(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 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, (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 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, // 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 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, 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()) { - CXXRecordDecl* RDecl = cast(RT->getDecl()); + CXXRecordDecl *RDecl = cast(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()) { - CXXRecordDecl *RDecl = cast(RT->getDecl()); + CXXRecordDecl *RDecl = + cast(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()) { - 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()) { - 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()->getDecl()->hasObjectMember()) + if (BaseType->isRecordType() && BaseType->castAs() + ->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()) { - 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 Elements, Scope *S, const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast(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 f5f18b06c2fff..7a185106e4c6e 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(RT->getDecl()); + return checkRecordDeclForAttr( + 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(RT->getDecl()); + return checkRecordDeclForAttr( + 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()) { - RecordDecl *UD = UT->getDecl(); + RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + if (UD->hasAttr()) { 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(S.Context.getTypedefType( + ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, + S.Context.getObjCInstanceTypeDecl())); if (Ty->getAs() == Instancetype) if (auto *OMD = dyn_cast(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(D); if (TD && TD->getUnderlyingType()->isUnionType()) - RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); + RD = TD->getUnderlyingType() + ->getAsUnionType() + ->getOriginalDecl() + ->getDefinitionOrSelf(); else RD = dyn_cast(D); @@ -4507,7 +4514,7 @@ void Sema::CheckAlignasUnderalignment(Decl *D) { if (const auto *VD = dyn_cast(D)) { UnderlyingTy = DiagTy = VD->getType(); } else { - UnderlyingTy = DiagTy = Context.getTagDeclType(cast(D)); + UnderlyingTy = DiagTy = Context.getCanonicalTagType(cast(D)); if (const auto *ED = dyn_cast(D)) UnderlyingTy = ED->getIntegerType(); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index f5b4614576086..0477d37cac4c5 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(); 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. 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(); @@ -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 Bindings, const auto *RD = cast_or_null(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(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()->getDecl(); + const RecordDecl *RD = Field->getType() + ->castAs() + ->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()) { - const CXXRecordDecl *RD = cast(Record->getDecl()); + const CXXRecordDecl *RD = cast(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()) { auto *TempSpec = cast( - 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(); - TL.getNamedTypeLoc().castAs().setNameLoc(IdLoc); - TL.setElaboratedKeywordLoc(SourceLocation()); - TL.setQualifierLoc(SS.getWithLocInContext(Context)); + + TypeLocBuilder TLB; + if (const auto *TD = dyn_cast(TyD)) { + BaseType = Context.getTagType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TD, /*OwnsTag=*/false); + auto TL = TLB.push(BaseType); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(IdLoc); + } else if (auto *TN = dyn_cast(TyD)) { + BaseType = Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TN); + TLB.push(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 &IdealInits) { if (const RecordType *RT = Field->getType()->getAs()) { - 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()) 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(); if (!BaseType) continue; - CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl()); + CXXRecordDecl *BaseClassDecl = + cast(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()) { - CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl()); + CXXRecordDecl *FieldRecDecl = + cast(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 @@ class DefaultedComparisonAnalyzer 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()) { 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()) { - 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 @@ struct FindHiddenVirtualMethod { /// 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()->getDecl(); + RecordDecl *BaseRecord = Specifier->getType() + ->castAs() + ->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()) if (!RT->isDependentType() && - !cast(RT->getDecl())->canPassInRegisters()) { + !cast(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()) 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 Arguments; - { - const TemplateSpecializationType *TST = - SugaredType->getAsNonAliasTemplateSpecializationType(); - if (!TST) - if (const auto *ICN = SugaredType->getAs()) - TST = ICN->getInjectedTST(); - if (TST) { - Template = dyn_cast_or_null( - TST->getTemplateName().getAsTemplateDecl()); - Arguments = TST->template_arguments(); - } else if (const RecordType *RT = SugaredType->getAs()) { - ClassTemplateSpecializationDecl *Specialization = - dyn_cast(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( + TST->getTemplateName().getAsTemplateDecl()); + Arguments = TST->template_arguments(); + } else if (const auto *TT = SugaredType->getAs()) { + 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(BUD); bool IsVirtualBase = isVirtualDirectBase(cast(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 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback { 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 @@ class UsingValidatorCCC final : public CorrectionCandidateCallback { 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(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(CurContext))); + Context.getCanonicalTagType(cast(CurContext))); } LookupQualifiedName(R, LookupContext); @@ -13220,7 +13239,7 @@ NamedDecl *Sema::BuildUsingDeclaration( // constructor. auto *CurClass = cast(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(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(D) && !isa(D) && !isa(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(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(RT->getDecl()); + auto *BaseClass = + cast(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()) { - visitClassSubobject(cast(RT->getDecl()), FD, - FD->getType().getCVRQualifiers()); + visitClassSubobject( + cast(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()->getDecl()->hasObjectMember(); + bool NeedsCollectableMemCpy = E->isRecordType() && E->castAs() + ->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()) { - CXXRecordDecl *ClassDecl = cast(RecordTy->getDecl()); + CXXRecordDecl *ClassDecl = + cast(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() && 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() && 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(Record->getDecl()); + CXXRecordDecl *ClassDecl = + cast(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(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(T)) { - DependentNameTypeLoc TL = - TSI->getTypeLoc().castAs(); - TL.setElaboratedKeywordLoc(TagLoc); - TL.setQualifierLoc(QualifierLoc); - TL.setNameLoc(NameLoc); - } else { - ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs(); - TL.setElaboratedKeywordLoc(TagLoc); - TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs().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()) { - 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(I.getType()->castAs()->getDecl()); + const auto *Base = cast( + I.getType()->castAs()->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 bbd104909956f..88ed83eca243e 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(PrevDecl)) { + dyn_cast_or_null(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->castAs()->getInterface()) { SuperClassDecl = dyn_cast(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(type)) return true; return false; @@ -1589,7 +1588,9 @@ void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers( unsigned diagID; // unused QualType type; if (auto *actualTypeDecl = dyn_cast(typeDecl)) - type = Context.getTypeDeclType(actualTypeDecl); + type = + Context.getTypeDeclType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, actualTypeDecl); else type = Context.getObjCInterfaceType(cast(typeDecl)); TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc); @@ -3231,8 +3232,10 @@ static bool tryMatchRecordTypes(ASTContext &Context, assert(lt && rt && lt != rt); if (!isa(lt) || !isa(rt)) return false; - RecordDecl *left = cast(lt)->getDecl(); - RecordDecl *right = cast(rt)->getDecl(); + RecordDecl *left = + cast(lt)->getOriginalDecl()->getDefinitionOrSelf(); + RecordDecl *right = + cast(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(); - 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()) { - 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()) { - CXXRecordDecl *RD = cast(RecordTy->getDecl()); + CXXRecordDecl *RD = cast(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 0a6cea8869c14..94413b5b92d22 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()->isBeingDefined()) && + if (!(PointeeT->isRecordType() && PointeeT->castAs() + ->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 6793d6da85cb1..85320396fd17a 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()->getDecl()->hasNameForLinkage() || - !R->castAs()->getDecl()->hasNameForLinkage()) { + else if (!L->castAs()->getOriginalDecl()->hasNameForLinkage() || + !R->castAs()->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(DC)) { if (ExplicitTemplateArgs) { if (LookupTemplateName( - R, S, SS, Context.getRecordType(cast(DC)), + R, S, SS, Context.getCanonicalTagType(cast(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( 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()) { - QualType Ty = Context.getTypeDeclType(TD); - QualType ET = getElaboratedType(ElaboratedTypeKeyword::None, SS, Ty); + QualType ET; + TypeLocBuilder TLB; + if (auto *TagD = dyn_cast(TD)) { + ET = SemaRef.Context.getTagType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TagD, + /*OwnsTag=*/false); + auto TL = TLB.push(ET); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameInfo.getLoc()); + } else if (auto *TypedefD = dyn_cast(TD)) { + ET = SemaRef.Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TypedefD); + TLB.push(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(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(Member->getDeclContext()); if (!RD) return From; @@ -3002,7 +3009,7 @@ Sema::PerformObjectMemberConversion(Expr *From, QualType FromType = From->getType(); bool PointerConversions = false; if (isa(Member)) { - DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + DestRecordType = Context.getCanonicalTagType(RD); auto FromPtrType = FromType->getAs(); 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(), 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(Ty)->getNamedType(); - break; case Type::Adjusted: T = cast(Ty)->getOriginalType(); break; @@ -5877,7 +5881,7 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) { return DRE->hasQualifier(); } if (auto *OVL = dyn_cast(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(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()) { // C99 6.5.15p3 if (const RecordType *RHSRT = RHSTy->getAs()) - 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()) + if (!UT) + return AssignConvertType::Incompatible; + + RecordDecl *UD = UT->getOriginalDecl()->getDefinitionOrSelf(); + if (!UD->hasAttr()) 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()) - 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()->getDecl()->getIntegerType(); + QualType IntType = LHSStrippedType->castAs() + ->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()) - 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()) { - 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(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 9c5554173d262..29c9c47d4504c 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(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(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()) { 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(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(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(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()) { - CXXRecordDecl *RecordD = cast(RecordT->getDecl()); + CXXRecordDecl *RecordD = cast(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(DC)); + CanQualType ClassTy = Context.getCanonicalTagType(cast(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(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(AllocElemType->castAs()->getDecl()); + auto *RD = cast( + AllocElemType->castAs()->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); @@ -3606,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}; @@ -3640,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: @@ -4063,7 +4071,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, : diag::warn_delete_incomplete, Ex.get())) { if (const RecordType *RT = PointeeElem->getAs()) - PointeeRD = cast(RT->getDecl()); + PointeeRD = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); } } @@ -4587,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(FD); CastKind = CK_ConstructorConversion; @@ -4831,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()->getDecl()->isFixed() && + assert(FromType->castAs() + ->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, @@ -5383,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(); @@ -6197,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); @@ -6370,7 +6384,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return QualType(); Steps.emplace_back(Step::MemberPointer, - Context.getTypeDeclType(Cls).getTypePtr()); + Context.getCanonicalTagType(Cls).getTypePtr()); continue; } @@ -6649,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(RT->getDecl()); + CXXRecordDecl *RD = + cast(RT->getOriginalDecl())->getDefinitionOrSelf(); if (RD->isInvalidDecl() || RD->isDependentContext()) return E; @@ -7256,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; @@ -7309,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(); @@ -7518,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()) { - 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 5dca509d46fdb..4a31a139eaf4f 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 e0662d82914f4..03b5c79cf70e3 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()) { - 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(ND)) T = Context.getObjCInterfaceType(Class); else if (TypeDecl *Type = dyn_cast(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()) { - for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) { + for (auto *Redecl : + RT->getOriginalDecl()->getMostRecentDecl()->redecls()) { if (auto *attr = Redecl->getAttr()) return attr; } diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 1592862416bf9..8590ee831084f 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -1352,11 +1352,15 @@ class Analyzer { 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 17f17f8114373..b4bbe022a12c4 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()) { 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); @@ -366,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()) { @@ -451,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(); } } @@ -501,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()); } @@ -1836,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(); @@ -3389,7 +3389,7 @@ bool SemaHLSL::ContainsBitField(QualType BaseTy) { continue; } if (const auto *RT = dyn_cast(T)) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (RD->isUnion()) continue; @@ -3909,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( @@ -3957,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 1dd38c0ef6773..d7cca4bc65d2c 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()) - 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()) { - 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()->getDecl(); + RecordDecl *structDecl = + DeclType->castAs()->getOriginalDecl()->getDefinitionOrSelf(); int InitializableMembers = 0; if (auto *CXXRD = dyn_cast(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()) - return RT->getDecl(); - if (const auto *Inject = DeclType->getAs()) - 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()->getDecl(); + auto *ParentRD = Entity.getParent() + ->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); CXXRecordDecl *CXXRD = cast(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()->getDecl(); + auto *ParentRD = Entity.getParent() + ->getType() + ->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); if (CXXRecordDecl *CXXRD = dyn_cast(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(Info.FoundDecl->getDeclContext())); + CanQualType ClassT = Ctx.getCanonicalTagType( + cast(Info.FoundDecl->getDeclContext())); return Ctx.hasSameUnqualifiedType(ParmT, ClassT); } @@ -4537,8 +4535,8 @@ static void TryConstructorInitialization(Sema &S, const RecordType *DestRecordType = DestType->getAs(); assert(DestRecordType && "Constructor initialization requires record type"); - CXXRecordDecl *DestRecordDecl - = cast(DestRecordType->getDecl()); + auto *DestRecordDecl = cast(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(); 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(T1RecordType->getDecl()); + auto *T1RecordDecl = cast(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(T2RecordType->getDecl()); + auto *T2RecordDecl = cast(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()) { - if (CXXRecordDecl *ClassDecl = dyn_cast(RT->getDecl())) { + if (CXXRecordDecl *ClassDecl = + dyn_cast(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()) { bool IsUnion = RT->isUnionType(); - const CXXRecordDecl *RD = cast(RT->getDecl()); + const auto *RD = + cast(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()) { // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. - CXXRecordDecl *DestRecordDecl - = cast(DestRecordType->getDecl()); + auto *DestRecordDecl = + cast(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(SourceRecordType->getDecl()); + auto *SourceRecordDecl = + cast(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()) - Class = cast(Record->getDecl()); + Class = + cast(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(Record->getDecl())); + DeclContext::lookup_result Ctors = S.LookupConstructors( + cast(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()) { - CXXDestructorDecl *Destructor - = S.LookupDestructor(cast(Record->getDecl())); + CXXDestructorDecl *Destructor = + S.LookupDestructor(cast(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() - ->getDecl(); + << (InheritedFrom ? 2 + : Constructor->isImplicit() ? 1 + : 0) + << S.Context.getCanonicalTagType(Constructor->getParent()) + << /*base=*/0 << Entity.getType() << InheritedFrom; + + RecordDecl *BaseDecl = Entity.getBaseSpecifier() + ->getType() + ->castAs() + ->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()) - 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(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(Entity.getDecl()); @@ -10157,7 +10168,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( auto *RD = cast(Pattern->getTemplatedDecl()); if (!(RD->getDefinition() && RD->isAggregate())) return; - QualType Ty = Context.getRecordType(RD); + QualType Ty = Context.getCanonicalTagType(RD); SmallVector ElementTypes; InitListChecker CheckInitList(*this, Entity, ListInit, Ty, ElementTypes); @@ -10297,8 +10308,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( case OR_No_Viable_Function: { CXXRecordDecl *Primary = cast(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 bc3c4b0addeba..0d891fc08c207 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()) { - return ET->getDecl(); + return ET->getOriginalDecl()->getDefinitionOrSelf(); } // Otherwise, nope. @@ -759,7 +759,7 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(isa(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 dc73dedfb5598..e28492b579564 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(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(); 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(); 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()) - 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(LookupCtx) || - LookupCtx->isDependentContext() || - cast(LookupCtx)->isCompleteDefinition() || - cast(LookupCtx)->isBeingDefined()) && - "Declaration context must already be complete!"); + if (const auto *TD = dyn_cast(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(ND->getUnderlyingDecl())) { - QualType T = Context.getTypeDeclType(TD); - return T.getCanonicalType().getAsOpaquePtr(); - } + if (const TypeDecl *TD = dyn_cast(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() || - ObjectType->castAs()->isBeingDefined()) && + ObjectType->castAs() + ->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( - BaseSpec.getType()->castAs()->getDecl()); + CXXRecordDecl *RD = + cast( + BaseSpec.getType()->castAs()->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(BaseType->getDecl()); + CXXRecordDecl *BaseDecl = cast(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(cast(T)->getDecl()); + cast(cast(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(T)->getDecl(); + // FIXME: This should use the original decl. + EnumDecl *Enum = + cast(T)->getOriginalDecl()->getDefinitionOrSelf(); DeclContext *Ctx = Enum->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast(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 @@ class LookupVisibleHelper { const auto *Record = BaseType->getAs(); 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 &Identifiers) { - if (NestedNameSpecifier *Prefix = NNS->getPrefix()) - getNestedNameSpecifierIdentifiers(Prefix, Identifiers); - else + NestedNameSpecifier NNS, + SmallVectorImpl &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(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(T); + getNestedNameSpecifierIdentifiers(DT->getQualifier(), Identifiers); + Identifiers.push_back(DT->getIdentifier()); + return; + } + case Type::TemplateSpecialization: { + TemplateName Name = + cast(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(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(T) + ->getReplacementType() + .getTypePtr(); + continue; + case Type::TemplateTypeParm: + Identifiers.push_back(cast(T)->getIdentifier()); + return; + case Type::Decltype: + return; + case Type::Enum: + case Type::Record: + case Type::InjectedClassName: { + auto *TT = cast(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getOriginalDecl()->getIdentifier()); + return; + } + case Type::Typedef: { + auto *TT = cast(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getDecl()->getIdentifier()); + return; + } + case Type::Using: { + auto *TT = cast(T); + getNestedNameSpecifierIdentifiers(TT->getQualifier(), Identifiers); + Identifiers.push_back(TT->getDecl()->getIdentifier()); + return; + } + case Type::UnresolvedUsing: { + auto *TT = cast(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(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(C)) { - NNS = NestedNameSpecifier::Create(Context, NNS, ND); + NNS = NestedNameSpecifier(Context, ND, NNS); ++NumSpecifiers; } else if (auto *RD = dyn_cast_or_null(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 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/SemaObjC.cpp b/clang/lib/Sema/SemaObjC.cpp index bde00bdf458a7..8d8d5e87afe73 100644 --- a/clang/lib/Sema/SemaObjC.cpp +++ b/clang/lib/Sema/SemaObjC.cpp @@ -1407,7 +1407,8 @@ SemaObjC::ObjCSubscriptKind SemaObjC::CheckSubscriptingKind(Expr *FromE) { int NoIntegrals = 0, NoObjCIdPointers = 0; SmallVector ConversionDecls; - for (NamedDecl *D : cast(RecordTy->getDecl()) + for (NamedDecl *D : cast(RecordTy->getOriginalDecl()) + ->getDefinitionOrSelf() ->getVisibleConversionFunctions()) { if (CXXConversionDecl *Conversion = dyn_cast(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 9dbb1d28aa722..bf6c364e40cc4 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(); - 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/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2c5d97c3064ac..7d800c446b595 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(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()) { // 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 76e189d536849..d593d1d74d73d 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()) - 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(From->IgnoreParens())) { assert(cast(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()) + 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()) + 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()) { // 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(ToRecordType->getDecl())) { + } else if (auto *ToRecordDecl = + dyn_cast(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()) { - if (CXXRecordDecl *FromRecordDecl - = dyn_cast(FromRecordType->getDecl())) { + if (auto *FromRecordDecl = + dyn_cast(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()->getDecl(); + EnumDecl *Enum = + FromType->castAs()->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(T2->castAs()->getDecl()); + auto *T2RecordDecl = + cast(T2->castAs()->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(RecordTy->getDecl())->getVisibleConversionFunctions(); + const auto &Conversions = cast(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()) - if (auto *RD = dyn_cast(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()) - if (auto *RD = dyn_cast(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()) ObjectType = FromPtrType->getPointeeType(); const auto *ConversionContext = - cast(ObjectType->castAs()->getDecl()); + cast(ObjectType->castAs()->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()) { + bool IsComplete = isCompleteType(OpLoc, T1); + CXXRecordDecl *T1RD = + cast(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(TyRec->getDecl()); + auto *ClassDecl = + cast(TyRec->getOriginalDecl())->getDefinitionOrSelf(); for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) { if (isa(D)) D = cast(D)->getTargetDecl(); @@ -10199,7 +10206,7 @@ class BuiltinOperatorOverloadBuilder { if (S.getLangOpts().CPlusPlus11) { for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) { - if (!EnumTy->castAs()->getDecl()->isScoped()) + if (!EnumTy->castAs()->getOriginalDecl()->isScoped()) continue; if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second) @@ -10955,9 +10962,9 @@ bool clang::isBetterOverloadCandidate( isa(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(NakedMemExpr)) { MemExpr = cast(NakedMemExpr); Method = cast(MemExpr->getMemberDecl()); @@ -16346,7 +16353,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, const auto *Record = Object.get()->getType()->castAs(); 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(Record->getDecl())->getVisibleConversionFunctions(); + const auto &Conversions = cast(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()->getDecl()); + LookupQualifiedName(R, Base->getType() + ->castAs() + ->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(SubExpr.get()) && "fixed to something other than a decl ref"); - NestedNameSpecifier *Qualifier = + NestedNameSpecifier Qualifier = cast(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 d5c83aedb3008..7c82e540a9194 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()->getDecl()->fields()) { + for (const FieldDecl *FD : ArgType->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf() + ->fields()) { if (const auto *AA = FD->getAttr()) { CharUnits Alignment = getASTContext().toCharUnitsFromBits( AA->getAlignment(getASTContext())); diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 4683c81bd1c60..dd25336539816 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(T)) - Loc = TT->getDecl()->getLocation(); + Loc = TT->getOriginalDecl()->getLocation(); else if (const ObjCInterfaceType *ObjCIT = dyn_cast(T)) Loc = ObjCIT->getDecl()->getLocation(); return Loc; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index a5f92020f49f8..efc0b35792613 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(); CalleeType.This = - Context.getTypeDeclType(MPT->getMostRecentCXXRecordDecl()); + Context.getCanonicalTagType(MPT->getMostRecentCXXRecordDecl()); CalleeType.Func = MPT->getPointeeType()->castAs(); CalleeType.MemberType = FuncType::ft_pointer_to_member; } else if (isa(CalleeExpr)) { @@ -1254,7 +1254,7 @@ static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S, dyn_cast(CaseExpr->IgnoreParenImpCasts())) { if (const VarDecl *VD = dyn_cast(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 @@ class LocalTypedefNameReferencer : public DynamicRecursiveASTVisitor { Sema &S; }; bool LocalTypedefNameReferencer::VisitRecordType(RecordType *RT) { - auto *R = dyn_cast(RT->getDecl()); + auto *R = dyn_cast(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() && RetValExp) { if (const auto *RT = dyn_cast(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 4507a21a4c111..cd8b98c7444eb 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(); } else if (TypeDecl *TD = dyn_cast(FoundDecl)) - RT = TD->getTypeForDecl()->getAs(); + RT = Context.getTypeDeclType(TD)->getAs(); else if (FieldDecl *TD = dyn_cast(FoundDecl)) RT = TD->getType()->getAs(); 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 4000beff7dc49..a99222c5ed55f 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()) if (const auto *RT = PT->getPointeeType()->getAs()) - 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()) { if (const auto *RT = PtrTy->getPointeeType()->getAs()) { - 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 2d8fdb5b766fc..3441613e1acc6 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 = 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() || - ObjectType->castAs()->isBeingDefined()) && + ObjectType->castAs() + ->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(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()) { - SS.Adopt(ET.getQualifierLoc()); - TL = ET.getNamedTypeLoc(); - } - if (auto DTST = TL.getAs()) { 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 NestedTypes; QualType T; - if (SS.getScopeRep()) { - if (CXXRecordDecl *Record - = dyn_cast_or_null(computeDeclContext(SS, true))) - T = Context.getTypeDeclType(Record); + if (NestedNameSpecifier Qualifier = SS.getScopeRep(); + Qualifier.getKind() == NestedNameSpecifier::Kind::Type) { + if (CXXRecordDecl *Record = + dyn_cast_or_null(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()) { - 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()){ - 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()) { // 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(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 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()) { bool Literal = false; SourceLocation LiteralLoc; - if (isInVkNamespace(RT) && RT->getDecl()->getName() == "Literal") { - auto SpecDecl = dyn_cast(RT->getDecl()); + if (isInVkNamespace(RT) && RT->getOriginalDecl()->getName() == "Literal") { + auto SpecDecl = + dyn_cast(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(RT->getDecl()); + RT->getOriginalDecl()->getName() == "integral_constant") { + auto SpecDecl = + dyn_cast(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 Converted, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs) { +static QualType checkBuiltinTemplateIdType( + Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD, + ArrayRef 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 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 @@ class FailedBooleanConditionPrinterHelper : public PrinterHelper { 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(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(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(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(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())); 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(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(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(ElTy); - ElabTL.setElaboratedKeywordLoc(SourceLocation()); - if (!ElabTL.isEmpty()) - ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); - return CreateParsedType(ElTy, TLB.getTypeSourceInfo(Context, ElTy)); + TLB.push(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(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()) { - 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(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(Result); - ElabTL.setElaboratedKeywordLoc(TagLoc); - ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + TLB.push(Result).set( + TagLoc, SS.getWithLocInContext(Context), TemplateKWLoc, TemplateLoc, + TemplateArgs); return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } @@ -5055,7 +5039,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 +5327,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 SugaredConverted, ArrayRef CanonicalConverted, NestedNameSpecifierLoc &QualifierLoc) { @@ -5361,25 +5346,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 SugaredConverted, ArrayRef CanonicalConverted, bool &HasDefaultArg) { HasDefaultArg = false; @@ -5390,8 +5367,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 +5381,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 +5394,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 +5411,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()) { - if (ETLoc.getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None) - return TemplateArgumentLoc(); + auto TagLoc = TLoc.getAs(); + 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()) - 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()) - if (auto *CTSD = - dyn_cast(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 +5974,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 +6119,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 +6264,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 +6288,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType( const InjectedClassNameType* T) { - return VisitTagDecl(T->getDecl()); + return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf()); } bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( @@ -6331,10 +6298,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 +6344,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 +6364,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 +7340,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()) - IntegerType = Enum->getDecl()->getIntegerType(); + IntegerType = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); Value = Value.extOrTrunc(IntegerType->isBitIntType() ? Context.getIntWidth(IntegerType) : Context.getTypeSize(IntegerType)); @@ -7480,7 +7439,8 @@ ExprResult Sema::CheckTemplateArgument(NamedDecl *Param, QualType ParamType, QualType IntegerType = ParamType; if (const EnumType *Enum = IntegerType->getAs()) { - IntegerType = Enum->getDecl()->getIntegerType(); + IntegerType = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); } if (ParamType->isBooleanType()) { @@ -7903,10 +7863,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument( assert(VD->getDeclContext()->isRecord() && (isa(VD) || isa(VD) || isa(VD))); - QualType ClassType - = Context.getTypeDeclType(cast(VD->getDeclContext())); - NestedNameSpecifier *Qualifier = - NestedNameSpecifier::Create(Context, nullptr, ClassType.getTypePtr()); + CanQualType ClassType = + Context.getCanonicalTagType(cast(VD->getDeclContext())); + NestedNameSpecifier Qualifier(ClassType.getTypePtr()); SS.MakeTrivial(Context, Qualifier, Loc); } @@ -7998,7 +7957,7 @@ static Expr *BuildExpressionFromIntegralTemplateArgumentValue( // type of literal for it. QualType T = OrigT; if (const EnumType *ET = OrigT->getAs()) - T = ET->getDecl()->getIntegerType(); + T = ET->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); Expr *E; if (T->isAnyCharacterType()) { @@ -8881,7 +8840,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 +8855,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 +8884,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } // Create a new class template partial specialization declaration node. - ClassTemplatePartialSpecializationDecl *PrevPartial - = cast_or_null(PrevDecl); + ClassTemplatePartialSpecializationDecl *PrevPartial = + cast_or_null(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 +8928,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 +8991,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 +10038,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 +10045,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(T)) - return true; - + for (NestedNameSpecifier NNS = SS.getScopeRep(); + NNS.getKind() == NestedNameSpecifier::Kind::Type; + /**/) { + const Type *T = NNS.getAsType(); + if (isa(T)) + return true; + NNS = T->getPrefix(); + } return false; } @@ -10448,7 +10407,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 +10954,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 +11066,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 +11077,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, TypeLocBuilder Builder; TemplateSpecializationTypeLoc SpecTL = Builder.push(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(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 +11092,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(); + + // FIXME: Look through sugar. + auto EnableIfTSTLoc = + NNS.castAsTypeLoc().getAs(); if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0) return false; const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr(); @@ -11192,19 +11145,33 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, if (T.isNull()) return QualType(); - *TSI = Context.CreateTypeSourceInfo(T); + TypeLocBuilder TLB; if (isa(T)) { - DependentNameTypeLoc TL = - (*TSI)->getTypeLoc().castAs(); + auto TL = TLB.push(T); TL.setElaboratedKeywordLoc(KeywordLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IILoc); - } else { - ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs(); + } else if (isa(T)) { + auto TL = TLB.push(T); + TL.setElaboratedKeywordLoc(KeywordLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(IILoc); + } else if (isa(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(T)) { + auto TL = TLB.push(T); TL.setElaboratedKeywordLoc(KeywordLoc); TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs().setNameLoc(IILoc); + TL.setNameLoc(IILoc); + } else if (isa(T)) { + TLB.push(T).set(KeywordLoc, QualifierLoc, IILoc); + } else { + TLB.push(T).set(KeywordLoc, QualifierLoc, IILoc); } + *TSI = TLB.getTypeSourceInfo(Context, T); return T; } @@ -11227,7 +11194,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 +11276,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, &II); case LookupResultKind::Found: + // FXIME: Missing support for UsingShadowDecl on this path? if (TypeDecl *Type = dyn_cast(Result.getFoundDecl())) { // C++ [class.qual]p2: // In a lookup in which function names are not ignored and the @@ -11324,15 +11292,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(Type)) { + assert(Keyword == ElaboratedTypeKeyword::Typename); + assert(!QualifierLoc); + Keyword = ElaboratedTypeKeyword::None; + } + return Context.getTypeDeclType( + Keyword, QualifierLoc.getNestedNameSpecifier(), Type); } // C++ [dcl.type.simple]p2: @@ -11342,22 +11315,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 2bf4139c1928b..3aa808e165bb6 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 &Deduced, bool *HasDeducedAnyParam) { - QualType UP = P; - if (const auto *IP = P->getAs()) - UP = IP->getInjectedSpecializationType(); - - assert(isa(UP.getCanonicalType())); - const TemplateSpecializationType *TP = ::getLastTemplateSpecType(UP); - TemplateName TNP = TP->getTemplateName(); + TemplateName TNP; + ArrayRef PResolved; + if (isa(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() + ->template_arguments(); + } else { + const auto *TT = P->castAs(); + 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 PResolved = - TP->getCanonicalTypeInternal() - ->castAs() - ->template_arguments(); - - QualType UA = A; - std::optional NNS; - // Treat an injected-class-name as its underlying template-id. - if (const auto *Elaborated = A->getAs()) { - NNS = Elaborated->getQualifier(); - } else if (const auto *Injected = A->getAs()) { - UA = Injected->getInjectedSpecializationType(); - NNS = nullptr; - } - // Check whether the template argument is a dependent template-id. - if (isa(UA.getCanonicalType())) { - const TemplateSpecializationType *SA = ::getLastTemplateSpecType(UA); + if (isa(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(); - const auto *SA = - RA ? dyn_cast(RA->getDecl()) : nullptr; - if (!SA) { + const auto *TA = A->getAs(); + 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 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(TD)) { // Use the InjectedClassNameType. - PType = Context.getTypeDeclType(CTD->getTemplatedDecl()); + PType = Context.getCanonicalTagType(CTD->getTemplatedDecl()); } else if (const auto *AliasTemplate = dyn_cast(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(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(FTD->getTemplatedDecl()); if (IsDeductionGuide) { if (auto *Injected = P->getAs()) - P = Injected->getCanonicalInjectedTST(); + 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()) - T1 = Injected->getCanonicalInjectedTST(); + T1 = Injected->getOriginalDecl()->getCanonicalTemplateSpecializationType( + S.Context); if (auto *Injected = T2->getAs()) - T2 = Injected->getCanonicalInjectedTST(); + 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(T)->getInjectedSpecializationType(); + T = cast(T) + ->getOriginalDecl() + ->getCanonicalTemplateSpecializationType(Ctx); [[fallthrough]]; case Type::TemplateSpecialization: { diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 9be1c9c356cb2..604591408728c 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -105,22 +105,21 @@ class ExtractTypeForDeductionGuide 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(Template.getAsTemplateDecl())) - return Base::RebuildTemplateSpecializationType(Template, TemplateNameLoc, - TemplateArgs); + return Base::RebuildTemplateSpecializationType( + Keyword, Template, TemplateNameLoc, TemplateArgs); auto *TATD = cast(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 @@ class ExtractTypeForDeductionGuide 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 @@ class ExtractTypeForDeductionGuide // }; // }; if (OuterInstantiationArgs && InDependentContext && - TL.getTypePtr()->isInstantiationDependentType()) { + T->isInstantiationDependentType()) { Decl = cast_if_present( TypedefNameInstantiator->InstantiateTypedefNameDecl( OrigDecl, /*IsTypeAlias=*/isa(OrigDecl))); @@ -180,10 +180,17 @@ class ExtractTypeForDeductionGuide MaterializedTypedefs.push_back(Decl); } - QualType TDTy = Context.getTypedefType(Decl); - TypedefTypeLoc TypedefTL = TLB.push(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(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 @@ struct ConvertConstructorToDeductionGuideTransform { // 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(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 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> 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 AliasRhsTemplateArgs; if (const auto *TST = RhsType->getAs()) { @@ -1048,12 +1056,11 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, // The (trailing) return type of the deduction guide. const TemplateSpecializationType *FReturnType = RType->getAs(); - if (const auto *InjectedCNT = RType->getAs()) + if (const auto *ICNT = RType->getAs()) // implicitly-generated deduction guide. - FReturnType = InjectedCNT->getInjectedTST(); - else if (const auto *ET = RType->getAs()) - // explicit deduction guide. - FReturnType = ET->getNamedType()->getAsNonAliasTemplateSpecializationType(); + FReturnType = cast( + 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 0d96d18de2d85..5e8dfd19fd6fa 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()) { - ArrayRef Arguments = TSTy->template_arguments(); - // Prefer template arguments from the injected-class-type if possible. - // For example, - // ```cpp - // template struct S { - // template void foo(); - // }; - // template template - // ^^^^^^^^^^^^^ InjectedTemplateArgs - // They're of kind TemplateArgument::Pack, not of - // TemplateArgument::Type. - // void S::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(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(Ty); + if (!TSTy) + continue; - NNS = NNS->getPrefix(); + ArrayRef Arguments = TSTy->template_arguments(); + // Prefer template arguments from the injected-class-type if possible. + // For example, + // ```cpp + // template struct S { + // template void foo(); + // }; + // template template + // ^^^^^^^^^^^^^ InjectedTemplateArgs + // They're of kind TemplateArgument::Pack, not of + // TemplateArgument::Type. + // void S::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(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()) { - 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(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(TransformDecl(Loc, D)); if (const TagType *Tag = T->getAs()) - 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()) { - 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(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 87ec4f75863fe..f02a295220efb 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()) { - TagDecl *oldTag = oldTagType->getDecl(); + TagDecl *oldTag = oldTagType->getOriginalDecl(); if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) { - TagDecl *newTag = DI->getType()->castAs()->getDecl(); + TagDecl *newTag = DI->getType()->castAs()->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(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(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(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( - 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(Result); + TagTypeLoc NewTL = TLB.push(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(ParentDC)) { if (!Spec->isDependentContext()) { - QualType T = Context.getTypeDeclType(Spec); + CanQualType T = Context.getCanonicalTagType(Spec); const RecordType *Tag = T->getAs(); assert(Tag && "type of non-dependent record is not a RecordType"); - if (Tag->isBeingDefined()) + auto *TagDecl = + cast(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(ParentDC)); + << D->getDeclName() + << Context.getCanonicalTagType(cast(ParentDC)); Diag(D->getLocation(), diag::note_non_instantiated_member_here); } else if (EnumConstantDecl *ED = dyn_cast(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(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 d2baa2efb6121..377f2ed3552d3 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 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 1289bede3f192..0985b5b565dab 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()) - 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()) - 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()) { // 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()) { - 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(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()); + 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()); + 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()); + 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()) { - ElaboratedTypeLoc ElabTL = OldTL.castAs(); - TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc() - .castAs(); - TL.copy(NamedTL); - } else { - TL.copy(OldTL.castAs()); - assert(TL.getRAngleLoc() == OldTL.castAs().getRAngleLoc()); - } - + TL.copy(OldTL.castAs()); + assert(TL.getRAngleLoc() == + OldTL.castAs().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()) { - 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()); + } void VisitTagTypeLoc(TagTypeLoc TL) { + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = nullptr; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(TInfo->getTypeLoc().castAs()); + 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(Desugared)) { Desugared = TT->desugar(); continue; - } else if (const ElaboratedType *ET = dyn_cast(Desugared)) { - Desugared = ET->desugar(); - continue; } const AttributedType *AT = dyn_cast(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()) { - 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()) { 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()) { + if (const auto *MPTy = dyn_cast(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(RT->getDecl()); + const CXXRecordDecl *RD = + cast(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()) - 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()->getDecl(); - assert(ED && "EnumType has no EnumDecl"); + EnumDecl *ED = BaseType->castAs()->getOriginalDecl(); S.DiagnoseUseOfDecl(ED, Loc); diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1d8687e4bf1c1..9b9dd172003a0 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(RT->getDecl()); + CXXRecordDecl *RD = + cast(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(rhsRecord->getDecl()) - ->isDerivedFrom(cast(lhsRecord->getDecl())); + return cast(rhsRecord->getOriginalDecl()) + ->isDerivedFrom(cast(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(DerivedRecord->getDecl()) - ->isVirtuallyDerivedFrom(cast(BaseRecord->getDecl())); + return cast(DerivedRecord->getOriginalDecl()) + ->isVirtuallyDerivedFrom( + cast(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(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(); + const auto *Ts = Qualifier.getAsType()->getAs(); if (!Ts) return std::nullopt; const TemplateDecl *D = Ts->getTemplateName().getAsTemplateDecl(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 385e9ea6c4e24..1863e7f97e3f1 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -591,12 +591,12 @@ class TreeTransform { /// 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. /// @@ -1153,7 +1153,7 @@ class TreeTransform { 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, @@ -4587,7 +4587,7 @@ NestedNameSpecifierLoc TreeTransform::TransformNestedNameSpecifierLoc( auto insertNNS = [&Qualifiers](NestedNameSpecifierLoc NNS) { for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; - Qualifier = Qualifier.getPrefix()) + Qualifier = Qualifier.getAsNamespaceAndPrefix().Prefix) Qualifiers.push_back(Qualifier); }; insertNNS(NNS); @@ -4595,76 +4595,87 @@ NestedNameSpecifierLoc TreeTransform::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(); - case NestedNameSpecifier::Namespace: { + switch (QNNS.getKind()) { + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); + + case NestedNameSpecifier::Kind::Namespace: { auto *NS = cast(getDerived().TransformDecl( - Q.getLocalBeginLoc(), QNNS->getAsNamespace())); + Q.getLocalBeginLoc(), const_cast( + 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(getDerived().TransformDecl( - SourceLocation(), QNNS->getAsRecordDecl())); - SS.MakeSuper(SemaRef.Context, RD, Q.getBeginLoc(), Q.getEndLoc()); + case NestedNameSpecifier::Kind::MicrosoftSuper: { + CXXRecordDecl *RD = cast_or_null( + 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()) { + 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(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()) { - 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(); - 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. @@ -4750,30 +4761,32 @@ template TemplateName TreeTransform::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 -TemplateName -TreeTransform::TransformTemplateName(CXXScopeSpec &SS, - TemplateName Name, - SourceLocation NameLoc, - QualType ObjectType, - NamedDecl *FirstQualifierInScope, - bool AllowInjectedClassName) { +template +TemplateName TreeTransform::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(getDerived().TransformDecl(NameLoc, Template)); @@ -4781,41 +4794,67 @@ TreeTransform::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(getDerived().TransformDecl(NameLoc, Template)); if (!TransTemplate) return TemplateName(); + CXXScopeSpec SS; return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false, TransTemplate); } @@ -4918,17 +4957,10 @@ bool TreeTransform::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, Input.getTemplateKWLoc(), @@ -6632,23 +6664,38 @@ QualType TreeTransform::TransformFunctionNoProtoType( template QualType TreeTransform::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(Result)) + TLB.push(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); + else + TLB.push(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); return Result; } @@ -6656,25 +6703,37 @@ template QualType TreeTransform::TransformUsingType(TypeLocBuilder &TLB, UsingTypeLoc TL) { const UsingType *T = TL.getTypePtr(); + bool Changed = false; - auto *Found = cast_or_null(getDerived().TransformDecl( - TL.getLocalSourceRange().getBegin(), T->getFoundDecl())); - if (!Found) + NestedNameSpecifierLoc QualifierLoc = TL.getQualifierLoc(); + if (NestedNameSpecifierLoc OldQualifierLoc = QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return QualType(); + Changed |= QualifierLoc != OldQualifierLoc; + } + + auto *D = cast_or_null( + 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(Result).set(TL.getElaboratedKeywordLoc(), QualifierLoc, + TL.getNameLoc()); return Result; } @@ -6682,23 +6741,34 @@ template QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { const TypedefType *T = TL.getTypePtr(); - TypedefNameDecl *Typedef - = cast_or_null(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( + 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(Result); - NewTL.setNameLoc(TL.getNameLoc()); - + TLB.push(Result).set(TL.getElaboratedKeywordLoc(), + QualifierLoc, TL.getNameLoc()); return Result; } @@ -6934,9 +7004,10 @@ QualType TreeTransform::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(); @@ -7313,9 +7384,16 @@ QualType TreeTransform::TransformAutoType(TypeLocBuilder &TLB, template QualType TreeTransform::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()); @@ -7550,15 +7628,22 @@ QualType TreeTransform::TransformDependentNameType( return TransformDependentNameType(TLB, TL, false); } -template +template QualType TreeTransform::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(), @@ -7592,33 +7677,34 @@ QualType TreeTransform::TransformDependentNameType( return Result; } -template -QualType TreeTransform:: - 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 +QualType TreeTransform::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL) { + return getDerived().TransformDependentTemplateSpecializationType( + TLB, TL, QualType(), nullptr, false); } template QualType TreeTransform::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>({TL, 0}, {TL, TL.getNumArgs()}); @@ -7635,43 +7721,27 @@ QualType TreeTransform::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(Result)) { - QualType NamedT = ElabT->getNamedType(); - - // Copy information relevant to the template specialization. - TemplateSpecializationTypeLoc NamedTL - = TLB.push(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(Result); - NewTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); - NewTL.setQualifierLoc(QualifierLoc); + QualifierLoc = SS.getWithLocInContext(SemaRef.Context); + if (isa(Result)) { + TLB.push(Result).set( + TL.getElaboratedKeywordLoc(), QualifierLoc, TL.getTemplateKeywordLoc(), + TL.getTemplateNameLoc(), NewTemplateArgs); } else { - assert(isa(Result)); - DependentTemplateSpecializationTypeLoc SpecTL - = TLB.push(Result); + auto SpecTL = TLB.push(Result); SpecTL.setElaboratedKeywordLoc(TL.getElaboratedKeywordLoc()); SpecTL.setQualifierLoc(QualifierLoc); SpecTL.setTemplateKeywordLoc(TL.getTemplateKeywordLoc()); @@ -14159,7 +14229,7 @@ TreeTransform::TransformCXXTypeidExpr(CXXTypeidExpr *E) { auto EvalCtx = Sema::ExpressionEvaluationContext::Unevaluated; if (E->isGLValue()) if (auto *RecordT = Op->getType()->getAs()) - if (cast(RecordT->getDecl())->isPolymorphic()) + if (cast(RecordT->getOriginalDecl())->isPolymorphic()) EvalCtx = SemaRef.ExprEvalContexts.back().Context; EnterExpressionEvaluationContext Unevaluated(SemaRef, EvalCtx, @@ -14399,7 +14469,8 @@ TreeTransform::TransformCXXNewExpr(CXXNewExpr *E) { QualType ElementType = SemaRef.Context.getBaseElementType(E->getAllocatedType()); if (const RecordType *RecordT = ElementType->getAs()) { - CXXRecordDecl *Record = cast(RecordT->getDecl()); + CXXRecordDecl *Record = cast(RecordT->getOriginalDecl()) + ->getDefinitionOrSelf(); if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) { SemaRef.MarkFunctionReferenced(E->getBeginLoc(), Destructor); } @@ -14469,7 +14540,9 @@ TreeTransform::TransformCXXDeleteExpr(CXXDeleteExpr *E) { QualType Destroyed = SemaRef.Context.getBaseElementType( E->getDestroyedType()); if (const RecordType *DestroyedRec = Destroyed->getAs()) { - CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); + CXXRecordDecl *Record = + cast(DestroyedRec->getOriginalDecl()) + ->getDefinitionOrSelf(); SemaRef.MarkFunctionReferenced(E->getBeginLoc(), SemaRef.LookupDestructor(Record)); } diff --git a/clang/lib/Sema/UsedDeclVisitor.h b/clang/lib/Sema/UsedDeclVisitor.h index 580d702f96fe5..ad475ab0f42ae 100644 --- a/clang/lib/Sema/UsedDeclVisitor.h +++ b/clang/lib/Sema/UsedDeclVisitor.h @@ -71,9 +71,10 @@ class UsedDeclVisitor : public EvaluatedExprVisitor { if (!DestroyedOrNull.isNull()) { QualType Destroyed = S.Context.getBaseElementType(DestroyedOrNull); if (const RecordType *DestroyedRec = Destroyed->getAs()) { - CXXRecordDecl *Record = cast(DestroyedRec->getDecl()); - if (Record->getDefinition()) - asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Record)); + CXXRecordDecl *Record = + cast(DestroyedRec->getOriginalDecl()); + if (auto *Def = Record->getDefinition()) + asImpl().visitUsedDecl(E->getBeginLoc(), S.LookupDestructor(Def)); } } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ed0ec9e357618..e8dddda584a9b 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5500,7 +5500,7 @@ void ASTReader::InitializeContext() { Error("Invalid FILE type in AST file"); return; } - Context.setFILEDecl(Tag->getDecl()); + Context.setFILEDecl(Tag->getOriginalDecl()); } } } @@ -5521,7 +5521,7 @@ void ASTReader::InitializeContext() { Error("Invalid jmp_buf type in AST file"); return; } - Context.setjmp_bufDecl(Tag->getDecl()); + Context.setjmp_bufDecl(Tag->getOriginalDecl()); } } } @@ -5539,7 +5539,7 @@ void ASTReader::InitializeContext() { else { const TagType *Tag = Sigjmp_bufType->getAs(); assert(Tag && "Invalid sigjmp_buf type in AST file"); - Context.setsigjmp_bufDecl(Tag->getDecl()); + Context.setsigjmp_bufDecl(Tag->getOriginalDecl()); } } } @@ -5574,7 +5574,7 @@ void ASTReader::InitializeContext() { else { const TagType *Tag = Ucontext_tType->getAs(); assert(Tag && "Invalid ucontext_t type in AST file"); - Context.setucontext_tDecl(Tag->getDecl()); + Context.setucontext_tDecl(Tag->getOriginalDecl()); } } } @@ -7226,6 +7226,7 @@ class TypeLocReader : public TypeLocVisitor { void VisitFunctionTypeLoc(FunctionTypeLoc); void VisitArrayTypeLoc(ArrayTypeLoc); + void VisitTagTypeLoc(TagTypeLoc TL); }; } // namespace clang @@ -7372,15 +7373,24 @@ void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { } void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); + SourceLocation ElaboratedKeywordLoc = readSourceLocation(); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(); + SourceLocation NameLoc = readSourceLocation(); + TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc); } void TypeLocReader::VisitUsingTypeLoc(UsingTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); + SourceLocation ElaboratedKeywordLoc = readSourceLocation(); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(); + SourceLocation NameLoc = readSourceLocation(); + TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc); } void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); + SourceLocation ElaboratedKeywordLoc = readSourceLocation(); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(); + SourceLocation NameLoc = readSourceLocation(); + TL.set(ElaboratedKeywordLoc, QualifierLoc, NameLoc); } void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { @@ -7434,17 +7444,27 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { + TL.setElaboratedKeywordLoc(readSourceLocation()); + TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); TL.setTemplateNameLoc(readSourceLocation()); } -void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { +void TypeLocReader::VisitTagTypeLoc(TagTypeLoc TL) { + TL.setElaboratedKeywordLoc(readSourceLocation()); + TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); TL.setNameLoc(readSourceLocation()); } -void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); +void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { + VisitTagTypeLoc(TL); } +void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + VisitTagTypeLoc(TL); +} + +void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); } + void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { TL.setAttr(ReadAttr()); } @@ -7482,14 +7502,18 @@ void TypeLocReader::VisitSubstTemplateTypeParmPackTypeLoc( void TypeLocReader::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { - TL.setTemplateKeywordLoc(readSourceLocation()); - TL.setTemplateNameLoc(readSourceLocation()); - TL.setLAngleLoc(readSourceLocation()); - TL.setRAngleLoc(readSourceLocation()); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, - Reader.readTemplateArgumentLocInfo( - TL.getTypePtr()->template_arguments()[i].getKind())); + SourceLocation ElaboratedKeywordLoc = readSourceLocation(); + NestedNameSpecifierLoc QualifierLoc = ReadNestedNameSpecifierLoc(); + SourceLocation TemplateKeywordLoc = readSourceLocation(); + SourceLocation NameLoc = readSourceLocation(); + SourceLocation LAngleLoc = readSourceLocation(); + SourceLocation RAngleLoc = readSourceLocation(); + TL.set(ElaboratedKeywordLoc, QualifierLoc, TemplateKeywordLoc, NameLoc, + LAngleLoc, RAngleLoc); + MutableArrayRef Args = TL.getArgLocInfos(); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + Args[I] = Reader.readTemplateArgumentLocInfo( + TL.getTypePtr()->template_arguments()[I].getKind()); } void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { @@ -7497,15 +7521,6 @@ void TypeLocReader::VisitParenTypeLoc(ParenTypeLoc TL) { TL.setRParenLoc(readSourceLocation()); } -void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - TL.setElaboratedKeywordLoc(readSourceLocation()); - TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); -} - -void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); -} - void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { TL.setElaboratedKeywordLoc(readSourceLocation()); TL.setQualifierLoc(ReadNestedNameSpecifierLoc()); @@ -7962,18 +7977,15 @@ ASTRecordReader::readTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) { return readExpr(); case TemplateArgument::Type: return readTypeSourceInfo(); - case TemplateArgument::Template: { - NestedNameSpecifierLoc QualifierLoc = - readNestedNameSpecifierLoc(); - SourceLocation TemplateNameLoc = readSourceLocation(); - return TemplateArgumentLocInfo(getASTContext(), QualifierLoc, - TemplateNameLoc, SourceLocation()); - } + case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: { + SourceLocation TemplateKWLoc = readSourceLocation(); NestedNameSpecifierLoc QualifierLoc = readNestedNameSpecifierLoc(); SourceLocation TemplateNameLoc = readSourceLocation(); - SourceLocation EllipsisLoc = readSourceLocation(); - return TemplateArgumentLocInfo(getASTContext(), QualifierLoc, + SourceLocation EllipsisLoc = Kind == TemplateArgument::TemplateExpansion + ? readSourceLocation() + : SourceLocation(); + return TemplateArgumentLocInfo(getASTContext(), TemplateKWLoc, QualifierLoc, TemplateNameLoc, EllipsisLoc); } case TemplateArgument::Null: @@ -9586,12 +9598,6 @@ void ASTReader::AssignedLambdaNumbering(CXXRecordDecl *Lambda) { CXXRecordDecl *Previous = cast(Iter->second)->getMostRecentDecl(); Lambda->setPreviousDecl(Previous); - // FIXME: It will be best to use the Previous type when we creating the - // lambda directly. But that requires us to get the lambda context decl and - // lambda index before creating the lambda, which needs a drastic change in - // the parser. - const_cast(Lambda->TypeForDecl->CanonicalType) = - Previous->TypeForDecl->CanonicalType; return; } @@ -10107,41 +10113,37 @@ ASTRecordReader::readNestedNameSpecifierLoc() { for (unsigned I = 0; I != N; ++I) { auto Kind = readNestedNameSpecifierKind(); switch (Kind) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = readIdentifier(); - SourceRange Range = readSourceRange(); - Builder.Extend(Context, II, Range.getBegin(), Range.getEnd()); - break; - } - - case NestedNameSpecifier::Namespace: { + case NestedNameSpecifier::Kind::Namespace: { auto *NS = readDeclAs(); SourceRange Range = readSourceRange(); Builder.Extend(Context, NS, Range.getBegin(), Range.getEnd()); break; } - case NestedNameSpecifier::TypeSpec: { + case NestedNameSpecifier::Kind::Type: { TypeSourceInfo *T = readTypeSourceInfo(); if (!T) return NestedNameSpecifierLoc(); SourceLocation ColonColonLoc = readSourceLocation(); - Builder.Extend(Context, T->getTypeLoc(), ColonColonLoc); + Builder.Make(Context, T->getTypeLoc(), ColonColonLoc); break; } - case NestedNameSpecifier::Global: { + case NestedNameSpecifier::Kind::Global: { SourceLocation ColonColonLoc = readSourceLocation(); Builder.MakeGlobal(Context, ColonColonLoc); break; } - case NestedNameSpecifier::Super: { + case NestedNameSpecifier::Kind::MicrosoftSuper: { CXXRecordDecl *RD = readDeclAs(); SourceRange Range = readSourceRange(); - Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd()); + Builder.MakeMicrosoftSuper(Context, RD, Range.getBegin(), Range.getEnd()); break; } + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } } @@ -10537,12 +10539,7 @@ void ASTReader::finishPendingActions() { // happen now, after the redeclaration chains have been fully wired. for (Decl *D : PendingDefinitions) { if (TagDecl *TD = dyn_cast(D)) { - if (const TagType *TagT = dyn_cast(TD->getTypeForDecl())) { - // Make sure that the TagType points at the definition. - const_cast(TagT)->decl = TD; - } - - if (auto RD = dyn_cast(D)) { + if (auto *RD = dyn_cast(TD)) { for (auto *R = getMostRecentExistingDecl(RD); R; R = R->getPreviousDecl()) { assert((R == D) == diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 2c7beb431170e..6b35b205079e5 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -538,7 +538,11 @@ void ASTDeclReader::Visit(Decl *D) { if (auto *TD = dyn_cast(D)) { // We have a fully initialized TypeDecl. Read its type now. - TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); + if (isa(TD)) + assert(DeferredTypeID == 0 && + "Deferred type not used for TagDecls and Typedefs"); + else + TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull()); // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. @@ -695,7 +699,8 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { VisitNamedDecl(TD); TD->setLocStart(readSourceLocation()); // Delay type reading until after we have fully initialized the decl. - DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); + if (!isa(TD)) + DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); } RedeclarableResult ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { @@ -2237,15 +2242,6 @@ RedeclarableResult ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // Merged when we merge the template. auto *Template = readDeclAs(); D->TemplateOrInstantiation = Template; - if (!Template->getTemplatedDecl()) { - // We've not actually loaded the ClassTemplateDecl yet, because we're - // currently being loaded as its pattern. Rely on it to set up our - // TypeForDecl (see VisitClassTemplateDecl). - // - // Beware: we do not yet know our canonical declaration, and may still - // get merged once the surrounding class template has got off the ground. - DeferredTypeID = 0; - } break; } case CXXRecMemberSpecialization: { @@ -2479,14 +2475,6 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/false); ReadSpecializations(*Loc.F, D, Loc.F->DeclsCursor, /*IsPartial=*/true); } - - if (D->getTemplatedDecl()->TemplateOrInstantiation) { - // We were loaded before our templated declaration was. We've not set up - // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct - // it now. - Reader.getContext().getInjectedClassNameType( - D->getTemplatedDecl(), D->getInjectedClassNameSpecialization()); - } } void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c072acd4b0420..9faf107f64751 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -345,6 +345,7 @@ class TypeLocWriter : public TypeLocVisitor { void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); + void VisitTagTypeLoc(TagTypeLoc TL); }; } // namespace @@ -490,14 +491,20 @@ void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { } void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitUsingTypeLoc(UsingTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getNameLoc()); } void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getNameLoc()); } @@ -564,17 +571,27 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getTemplateNameLoc()); } -void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { +void TypeLocWriter::VisitTagTypeLoc(TagTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getNameLoc()); } -void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { - addSourceLocation(TL.getNameLoc()); +void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { + VisitTagTypeLoc(TL); +} + +void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + VisitTagTypeLoc(TL); } +void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); } + void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddAttr(TL.getAttr()); } @@ -612,13 +629,14 @@ void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc( void TypeLocWriter::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { + addSourceLocation(TL.getElaboratedKeywordLoc()); + Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); addSourceLocation(TL.getTemplateKeywordLoc()); addSourceLocation(TL.getTemplateNameLoc()); addSourceLocation(TL.getLAngleLoc()); addSourceLocation(TL.getRAngleLoc()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(), - TL.getArgLoc(i).getLocInfo()); + Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i)); } void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) { @@ -630,15 +648,6 @@ void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { addSourceLocation(TL.getExpansionLoc()); } -void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - addSourceLocation(TL.getElaboratedKeywordLoc()); - Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); -} - -void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - addSourceLocation(TL.getNameLoc()); -} - void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { addSourceLocation(TL.getElaboratedKeywordLoc()); Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc()); @@ -654,8 +663,7 @@ void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc( addSourceLocation(TL.getLAngleLoc()); addSourceLocation(TL.getRAngleLoc()); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(), - TL.getArgLoc(I).getLocInfo()); + Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I)); } void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { @@ -1038,7 +1046,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(TYPE_OBJC_INTERFACE); RECORD(TYPE_OBJC_OBJECT_POINTER); RECORD(TYPE_DECLTYPE); - RECORD(TYPE_ELABORATED); RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM); RECORD(TYPE_UNRESOLVED_USING); RECORD(TYPE_INJECTED_CLASS_NAME); @@ -6769,22 +6776,22 @@ void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) { } void ASTRecordWriter::AddTemplateArgumentLocInfo( - TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg) { - switch (Kind) { + const TemplateArgumentLoc &Arg) { + const TemplateArgumentLocInfo &Info = Arg.getLocInfo(); + switch (auto K = Arg.getArgument().getKind()) { case TemplateArgument::Expression: - AddStmt(Arg.getAsExpr()); + AddStmt(Info.getAsExpr()); break; case TemplateArgument::Type: - AddTypeSourceInfo(Arg.getAsTypeSourceInfo()); + AddTypeSourceInfo(Info.getAsTypeSourceInfo()); break; case TemplateArgument::Template: - AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); - AddSourceLocation(Arg.getTemplateNameLoc()); - break; case TemplateArgument::TemplateExpansion: + AddSourceLocation(Arg.getTemplateKWLoc()); AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc()); AddSourceLocation(Arg.getTemplateNameLoc()); - AddSourceLocation(Arg.getTemplateEllipsisLoc()); + if (K == TemplateArgument::TemplateExpansion) + AddSourceLocation(Arg.getTemplateEllipsisLoc()); break; case TemplateArgument::Null: case TemplateArgument::Integral: @@ -6807,7 +6814,7 @@ void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) { if (InfoHasSameExpr) return; // Avoid storing the same expr twice. } - AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo()); + AddTemplateArgumentLocInfo(Arg); } void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { @@ -7065,49 +7072,50 @@ void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) { AddTemplateParameterList(Info.TemplParamLists[i]); } -void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { +void ASTRecordWriter::AddNestedNameSpecifierLoc( + NestedNameSpecifierLoc QualifierLoc) { // Nested name specifiers usually aren't too long. I think that 8 would // typically accommodate the vast majority. SmallVector NestedNames; // Push each of the nested-name-specifiers's onto a stack for // serialization in reverse order. - while (NNS) { - NestedNames.push_back(NNS); - NNS = NNS.getPrefix(); + while (QualifierLoc) { + NestedNames.push_back(QualifierLoc); + QualifierLoc = QualifierLoc.getAsNamespaceAndPrefix().Prefix; } Record->push_back(NestedNames.size()); while(!NestedNames.empty()) { - NNS = NestedNames.pop_back_val(); - NestedNameSpecifier::SpecifierKind Kind - = NNS.getNestedNameSpecifier()->getKind(); - Record->push_back(Kind); + QualifierLoc = NestedNames.pop_back_val(); + NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier(); + NestedNameSpecifier::Kind Kind = Qualifier.getKind(); + Record->push_back(llvm::to_underlying(Kind)); switch (Kind) { - case NestedNameSpecifier::Identifier: - AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier()); - AddSourceRange(NNS.getLocalSourceRange()); + case NestedNameSpecifier::Kind::Namespace: + AddDeclRef(Qualifier.getAsNamespaceAndPrefix().Namespace); + AddSourceRange(QualifierLoc.getLocalSourceRange()); break; - case NestedNameSpecifier::Namespace: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace()); - AddSourceRange(NNS.getLocalSourceRange()); + case NestedNameSpecifier::Kind::Type: { + TypeLoc TL = QualifierLoc.castAsTypeLoc(); + AddTypeRef(TL.getType()); + AddTypeLoc(TL); + AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd()); break; + } - case NestedNameSpecifier::TypeSpec: - AddTypeRef(NNS.getTypeLoc().getType()); - AddTypeLoc(NNS.getTypeLoc()); - AddSourceLocation(NNS.getLocalSourceRange().getEnd()); + case NestedNameSpecifier::Kind::Global: + AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd()); break; - case NestedNameSpecifier::Global: - AddSourceLocation(NNS.getLocalSourceRange().getEnd()); + case NestedNameSpecifier::Kind::MicrosoftSuper: + AddDeclRef(Qualifier.getAsMicrosoftSuper()); + AddSourceRange(QualifierLoc.getLocalSourceRange()); break; - case NestedNameSpecifier::Super: - AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl()); - AddSourceRange(NNS.getLocalSourceRange()); - break; + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } } } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 6fd25b9e0a9ec..ec3dda1fcdf48 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -524,7 +524,7 @@ void ASTDeclWriter::VisitDecl(Decl *D) { // bits actually. However, if we changed the order to be 0x0f, then we can // store it as 0b001111, which takes 6 bits only now. DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3); - DeclBits.addBit(D->isReferenced()); + DeclBits.addBit(D->isThisDeclarationReferenced()); DeclBits.addBit(D->isUsed(false)); DeclBits.addBits(D->getAccess(), /*BitWidth=*/2); DeclBits.addBit(D->isImplicit()); @@ -601,7 +601,8 @@ void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { VisitNamedDecl(D); Record.AddSourceLocation(D->getBeginLoc()); - Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); + if (!isa(D)) + Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); } void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { @@ -2561,7 +2562,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp( @@ -2607,7 +2607,6 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // AnonDeclNumber // TypeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref // TagDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace Abv->Add(BitCodeAbbrevOp( diff --git a/clang/lib/Serialization/TemplateArgumentHasher.cpp b/clang/lib/Serialization/TemplateArgumentHasher.cpp index c56138e8893c1..3e8ffea78c2f1 100644 --- a/clang/lib/Serialization/TemplateArgumentHasher.cpp +++ b/clang/lib/Serialization/TemplateArgumentHasher.cpp @@ -320,7 +320,7 @@ class TypeVisitorHelper : public TypeVisitor { void VisitMemberPointerType(const MemberPointerType *T) { AddQualType(T->getPointeeType()); - AddType(T->getQualifier()->getAsType()); + AddType(T->getQualifier().getAsType()); if (auto *RD = T->getMostRecentCXXRecordDecl()) AddDecl(RD->getCanonicalDecl()); } @@ -358,7 +358,7 @@ class TypeVisitorHelper : public TypeVisitor { AddQualType(T->getReplacementType()); } - void VisitTagType(const TagType *T) { AddDecl(T->getDecl()); } + void VisitTagType(const TagType *T) { AddDecl(T->getOriginalDecl()); } void VisitRecordType(const RecordType *T) { VisitTagType(T); } void VisitEnumType(const EnumType *T) { VisitTagType(T); } @@ -379,10 +379,6 @@ class TypeVisitorHelper : public TypeVisitor { void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); } - void VisitElaboratedType(const ElaboratedType *T) { - AddQualType(T->getNamedType()); - } - void VisitUnaryTransformType(const UnaryTransformType *T) { AddQualType(T->getUnderlyingType()); AddQualType(T->getBaseType()); diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 23935647a5826..731e506a5d259 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -250,7 +250,7 @@ class FindUninitializedField { bool Find(const TypedValueRegion *R) { QualType T = R->getValueType(); if (const RecordType *RT = T->getAsStructureType()) { - const RecordDecl *RD = RT->getDecl()->getDefinition(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); assert(RD && "Referred record has no definition"); for (const auto *I : RD->fields()) { if (I->isUnnamedBitField()) diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 0b52c9bd8ac2a..90c6537d71d9d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -53,7 +53,7 @@ static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize, if (!RT) return false; - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); RecordDecl::field_iterator Iter(RD->field_begin()); RecordDecl::field_iterator End(RD->field_end()); const FieldDecl *Last = nullptr; diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 4982cd59b0a4a..cee744aecb686 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -245,7 +245,7 @@ static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, assert(MD); ASTContext &Ctx = C.getASTContext(); - QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent())); + CanQualType Ty = Ctx.getPointerType(Ctx.getCanonicalTagType(MD->getParent())); ProgramStateRef State = C.getState(); State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubClassed=*/false); diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp index 355e82e465e82..054b2e96bd13b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -148,7 +148,8 @@ void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE, // If the isEnumeralType() returned true, then the declaration must exist // even if it is a stub declaration. It is up to the getDeclValuesForEnum() // function to handle this. - const EnumDecl *ED = T->castAs()->getDecl(); + const EnumDecl *ED = + T->castAs()->getOriginalDecl()->getDefinitionOrSelf(); // [[clang::flag_enum]] annotated enums are by definition should be ignored. if (ED->hasAttr()) diff --git a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 1cb3848cfed2a..828b6f91d81c2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -47,9 +47,6 @@ static bool InNamespace(const Decl *D, StringRef NS) { } static bool IsStdString(QualType T) { - if (const ElaboratedType *QT = T->getAs()) - T = QT->getNamedType(); - const TypedefType *TT = T->getAs(); if (!TT) return false; @@ -201,7 +198,7 @@ static bool IsPartOfAST(const CXXRecordDecl *R) { for (const auto &BS : R->bases()) { QualType T = BS.getType(); if (const RecordType *baseT = T->getAs()) { - CXXRecordDecl *baseD = cast(baseT->getDecl()); + CXXRecordDecl *baseD = cast(baseT->getOriginalDecl()); if (IsPartOfAST(baseD)) return true; } @@ -247,7 +244,7 @@ void ASTFieldVisitor::Visit(FieldDecl *D) { ReportError(T); if (const RecordType *RT = T->getAs()) { - const RecordDecl *RD = RT->getDecl()->getDefinition(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinition(); for (auto *I : RD->fields()) Visit(I); } diff --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp index 0aea981252259..b1a7cd7620424 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -148,7 +148,9 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call, QualType T = ArgE->getType(); const RecordType *UT = T->getAsUnionType(); - if (!UT || !UT->getDecl()->hasAttr()) + if (!UT || !UT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr()) continue; auto CSV = DV->getAs(); diff --git a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp index 7927967093dcb..b5e32495235aa 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp @@ -114,10 +114,7 @@ bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const { if (AT->getAttrKind() == attr::TypeNonNull) return true; Ty = AT->getModifiedType(); - } else if (const auto *ET = dyn_cast(T)) { - const auto *TT = dyn_cast(ET->getNamedType()); - if (!TT) - return false; + } else if (const auto *TT = dyn_cast(T)) { Ty = TT->getDecl()->getUnderlyingType(); // It is sufficient for any intermediate typedef // to be classified const. diff --git a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp index f217520d8f4a0..68ab22a44e7b6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp @@ -197,9 +197,9 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D, BugReporter &BR) const { // Currently this matches CoreFoundation opaque pointer typedefs. auto CSuspiciousNumberObjectExprM = expr(ignoringParenImpCasts( - expr(hasType(elaboratedType(namesType(typedefType( + expr(hasType(typedefType( hasDeclaration(anyOf(typedefDecl(hasName("CFNumberRef")), - typedefDecl(hasName("CFBooleanRef"))))))))) + typedefDecl(hasName("CFBooleanRef"))))))) .bind("c_object"))); // Currently this matches XNU kernel number-object pointers. @@ -238,8 +238,7 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D, // The .bind here is in order to compose the error message more accurately. auto ObjCSuspiciousScalarBooleanTypeM = - qualType(elaboratedType(namesType( - typedefType(hasDeclaration(typedefDecl(hasName("BOOL"))))))) + qualType(typedefType(hasDeclaration(typedefDecl(hasName("BOOL"))))) .bind("objc_bool_type"); // The .bind here is in order to compose the error message more accurately. @@ -252,8 +251,8 @@ void NumberObjectConversionChecker::checkASTCodeBody(const Decl *D, // for storing pointers. auto SuspiciousScalarNumberTypeM = qualType(hasCanonicalType(isInteger()), - unless(elaboratedType(namesType(typedefType(hasDeclaration( - typedefDecl(matchesName("^::u?intptr_t$")))))))) + unless(typedefType( + hasDeclaration(typedefDecl(matchesName("^::u?intptr_t$")))))) .bind("int_type"); auto SuspiciousScalarTypeM = diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index d4efbdd54fc22..7ef659518ab1b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -104,7 +104,7 @@ class PaddingChecker : public Checker> { // There is not enough excess padding to trigger a warning. return; } - reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder); + reportRecord(ASTContext, RD, BaselinePad, OptimalPad, OptimalFieldsOrder); } /// Look for arrays of overly padded types. If the padding of the @@ -123,7 +123,7 @@ class PaddingChecker : public Checker> { return; // TODO: Recurse into the fields to see if they have excess padding. - visitRecord(RT->getDecl(), Elts); + visitRecord(RT->getOriginalDecl()->getDefinitionOrSelf(), Elts); } bool shouldSkipDecl(const RecordDecl *RD) const { @@ -159,9 +159,7 @@ class PaddingChecker : public Checker> { return true; // Can't layout a template, so skip it. We do still layout the // instantiations though. - if (CXXRD->getTypeForDecl()->isDependentType()) - return true; - if (CXXRD->getTypeForDecl()->isInstantiationDependentType()) + if (CXXRD->isDependentType()) return true; } // How do you reorder fields if you haven't got any? @@ -306,14 +304,14 @@ class PaddingChecker : public Checker> { } void reportRecord( - const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad, + const ASTContext &Ctx, const RecordDecl *RD, CharUnits BaselinePad, + CharUnits OptimalPad, const SmallVector &OptimalFieldsOrder) const { SmallString<100> Buf; llvm::raw_svector_ostream Os(Buf); Os << "Excessive padding in '"; - Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers(), - LangOptions()) - << "'"; + QualType(Ctx.getCanonicalTagType(RD)).print(Os, LangOptions()); + Os << "'"; if (auto *TSD = dyn_cast(RD)) { // TODO: make this show up better in the console output and in diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp index 52b3d1e95942c..844447f59f7f6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -1589,7 +1589,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // and we have a TypedefDecl with the name 'FILE'. for (Decl *D : LookupRes) if (auto *TD = dyn_cast(D)) - return ACtx.getTypeDeclType(TD).getCanonicalType(); + return ACtx.getCanonicalTypeDeclType(TD); // Find the first TypeDecl. // There maybe cases when a function has the same name as a struct. @@ -1597,7 +1597,7 @@ void StdLibraryFunctionsChecker::initFunctionSummaries( // int stat(const char *restrict path, struct stat *restrict buf); for (Decl *D : LookupRes) if (auto *TD = dyn_cast(D)) - return ACtx.getTypeDeclType(TD).getCanonicalType(); + return ACtx.getCanonicalTypeDeclType(TD); return std::nullopt; } } lookupTy(ACtx); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index 72199af2f80a5..36c12582a5787 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -181,10 +181,6 @@ template static bool isPtrOfType(const clang::QualType T, Predicate Pred) { QualType type = T; while (!type.isNull()) { - if (auto *elaboratedT = type->getAs()) { - type = elaboratedT->desugar(); - continue; - } if (auto *SpecialT = type->getAs()) { auto *Decl = SpecialT->getTemplateName().getAsTemplateDecl(); return Decl && Pred(Decl->getNameAsString()); @@ -248,13 +244,15 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) { const RecordType *RT = PointeeQT->getAs(); if (!RT) { if (TD->hasAttr() || TD->hasAttr()) { - if (auto *Type = TD->getTypeForDecl()) - RecordlessTypes.insert(Type); + RecordlessTypes.insert(TD->getASTContext() + .getTypedefType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, TD) + .getTypePtr()); } return; } - for (auto *Redecl : RT->getDecl()->getMostRecentDecl()->redecls()) { + for (auto *Redecl : RT->getOriginalDecl()->getMostRecentDecl()->redecls()) { if (Redecl->getAttr() || Redecl->getAttr()) { CFPointees.insert(RT); @@ -266,21 +264,10 @@ void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) { bool RetainTypeChecker::isUnretained(const QualType QT, bool ignoreARC) { if (ento::cocoa::isCocoaObjectRef(QT) && (!IsARCEnabled || ignoreARC)) return true; - auto CanonicalType = QT.getCanonicalType(); - auto PointeeType = CanonicalType->getPointeeType(); - auto *RT = dyn_cast_or_null(PointeeType.getTypePtrOrNull()); - if (!RT) { - auto *Type = QT.getTypePtrOrNull(); - while (Type) { - if (RecordlessTypes.contains(Type)) - return true; - auto *ET = dyn_cast_or_null(Type); - if (!ET) - break; - Type = ET->desugar().getTypePtrOrNull(); - } - } - return RT && CFPointees.contains(RT); + if (auto *RT = dyn_cast_or_null( + QT.getCanonicalType()->getPointeeType().getTypePtrOrNull())) + return CFPointees.contains(RT); + return RecordlessTypes.contains(QT.getTypePtr()); } std::optional isUnretained(const QualType T, bool IsARCEnabled) { @@ -306,7 +293,7 @@ std::optional isUnretained(const QualType T, bool IsARCEnabled) { auto *Record = PointeeType->getAsStructureType(); if (!Record) return false; - auto *Decl = Record->getDecl(); + auto *Decl = Record->getOriginalDecl(); if (!Decl) return false; auto TypeName = Decl->getName(); diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp index 98c587d62978b..6f3a280971cb8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp @@ -113,10 +113,6 @@ class DerefFuncDeleteExprVisitor auto CastType = Cast->getType(); if (auto *PtrType = dyn_cast(CastType)) { auto PointeeType = PtrType->getPointeeType(); - while (auto *ET = dyn_cast(PointeeType)) { - if (ET->isSugared()) - PointeeType = ET->desugar(); - } if (auto *ParmType = dyn_cast(PointeeType)) { if (ArgList) { auto ParmIndex = ParmType->getIndex(); @@ -125,13 +121,13 @@ class DerefFuncDeleteExprVisitor return true; } } else if (auto *RD = dyn_cast(PointeeType)) { - if (RD->getDecl() == ClassDecl) + if (declaresSameEntity(RD->getOriginalDecl(), ClassDecl)) return true; } else if (auto *ST = dyn_cast(PointeeType)) { auto Type = ST->getReplacementType(); if (auto *RD = dyn_cast(Type)) { - if (RD->getDecl() == ClassDecl) + if (declaresSameEntity(RD->getOriginalDecl(), ClassDecl)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 34fcb9b64d555..180056cf68b64 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -89,7 +89,7 @@ static bool isCallback(QualType T) { T = T->getPointeeType(); if (const RecordType *RT = T->getAsStructureType()) { - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); for (const auto *I : RD->fields()) { QualType FieldT = I->getType(); if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType()) @@ -391,7 +391,9 @@ bool CallEvent::isVariadic(const Decl *D) { static bool isTransparentUnion(QualType T) { const RecordType *UT = T->getAsUnionType(); - return UT && UT->getDecl()->hasAttr(); + return UT && UT->getOriginalDecl() + ->getMostRecentDecl() + ->hasAttr(); } // In some cases, symbolic cases should be transformed before we associate @@ -843,7 +845,7 @@ void CXXInstanceCall::getInitialStackFrameContents( if (MD->getCanonicalDecl() != getDecl()->getCanonicalDecl()) { ASTContext &Ctx = SVB.getContext(); const CXXRecordDecl *Class = MD->getParent(); - QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); + CanQualType Ty = Ctx.getPointerType(Ctx.getCanonicalTagType(Class)); // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager. std::optional V = @@ -854,7 +856,8 @@ void CXXInstanceCall::getInitialStackFrameContents( // Fall back to a generic pointer cast for this-value. const CXXMethodDecl *StaticMD = cast(getDecl()); const CXXRecordDecl *StaticClass = StaticMD->getParent(); - QualType StaticTy = Ctx.getPointerType(Ctx.getRecordType(StaticClass)); + CanQualType StaticTy = + Ctx.getPointerType(Ctx.getCanonicalTagType(StaticClass)); ThisVal = SVB.evalCast(ThisVal, Ty, StaticTy); } else ThisVal = *V; diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 0058a0ddfb0df..5f271963e3d09 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -192,11 +192,11 @@ QualType ObjCIvarRegion::getValueType() const { } QualType CXXBaseObjectRegion::getValueType() const { - return QualType(getDecl()->getTypeForDecl(), 0); + return getContext().getCanonicalTagType(getDecl()); } QualType CXXDerivedObjectRegion::getValueType() const { - return QualType(getDecl()->getTypeForDecl(), 0); + return getContext().getCanonicalTagType(getDecl()); } QualType ParamVarRegion::getValueType() const { diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index 388034b087789..02375b0c3469a 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2453,7 +2453,8 @@ NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B, SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R) { - const RecordDecl *RD = R->getValueType()->castAs()->getDecl(); + const RecordDecl *RD = + R->getValueType()->castAs()->getOriginalDecl(); if (!RD->getDefinition()) return UnknownVal(); @@ -2844,7 +2845,7 @@ RegionStoreManager::bindStruct(LimitedRegionBindingsConstRef B, assert(T->isStructureOrClassType()); const RecordType* RT = T->castAs(); - const RecordDecl *RD = RT->getDecl(); + const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf(); if (!RD->isCompleteDefinition()) return B; diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 2276c452cce76..a6f4463852a9b 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -320,8 +320,8 @@ loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D, /// Return a memory region for the 'this' object reference. loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D, const StackFrameContext *SFC) { - const Type *T = D->getTypeForDecl(); - QualType PT = getContext().getPointerType(QualType(T, 0)); + CanQualType PT = + getContext().getPointerType(getContext().getCanonicalTagType(D)); return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC)); } diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp index 5f7153cd53ac2..d70a679cc8dd0 100644 --- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp +++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp @@ -246,7 +246,7 @@ struct PreorderVisitor : public RecursiveASTVisitor { PostTraverse(SavedState); return true; } - bool TraverseType(QualType T) { return true; } + bool TraverseType(QualType T, bool TraverseQualifier = true) { return true; } bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { if (isNodeExcluded(Tree.AST.getSourceManager(), Init)) return true; @@ -428,11 +428,12 @@ std::string SyntaxTree::Impl::getDeclValue(const Decl *D) const { Value += getRelativeName(N) + ";"; if (auto *T = dyn_cast(D)) return Value + T->getUnderlyingType().getAsString(TypePP) + ";"; - if (auto *T = dyn_cast(D)) - if (T->getTypeForDecl()) - Value += - T->getTypeForDecl()->getCanonicalTypeInternal().getAsString(TypePP) + - ";"; + if (auto *T = dyn_cast(D)) { + const ASTContext &Ctx = T->getASTContext(); + Value += + Ctx.getTypeDeclType(T)->getCanonicalTypeInternal().getAsString(TypePP) + + ";"; + } if (auto *U = dyn_cast(D)) return std::string(U->getNominatedNamespace()->getName()); if (auto *A = dyn_cast(D)) { diff --git a/clang/lib/Tooling/Refactoring/Lookup.cpp b/clang/lib/Tooling/Refactoring/Lookup.cpp index 757fba0404e62..dedde860516ab 100644 --- a/clang/lib/Tooling/Refactoring/Lookup.cpp +++ b/clang/lib/Tooling/Refactoring/Lookup.cpp @@ -108,16 +108,6 @@ static StringRef getBestNamespaceSubstr(const DeclContext *DeclA, } } -/// Check if the name specifier begins with a written "::". -static bool isFullyQualified(const NestedNameSpecifier *NNS) { - while (NNS) { - if (NNS->getKind() == NestedNameSpecifier::Global) - return true; - NNS = NNS->getPrefix(); - } - return false; -} - // Adds more scope specifier to the spelled name until the spelling is not // ambiguous. A spelling is ambiguous if the resolution of the symbol is // ambiguous. For example, if QName is "::y::bar", the spelling is "y::bar", and @@ -182,7 +172,7 @@ static std::string disambiguateSpellingInScope(StringRef Spelling, return Disambiguated; } -std::string tooling::replaceNestedName(const NestedNameSpecifier *Use, +std::string tooling::replaceNestedName(NestedNameSpecifier Use, SourceLocation UseLoc, const DeclContext *UseContext, const NamedDecl *FromDecl, @@ -217,7 +207,7 @@ std::string tooling::replaceNestedName(const NestedNameSpecifier *Use, // We work backwards (from most specific possible namespace to least // specific). StringRef Suggested = getBestNamespaceSubstr(UseContext, ReplacementString, - isFullyQualified(Use)); + Use.isFullyQualified()); return disambiguateSpellingInScope(Suggested, ReplacementString, *UseContext, UseLoc); diff --git a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp index 8eff77861f753..d9444110d421c 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp @@ -107,45 +107,83 @@ class USRLocFindingASTVisitor }; SourceLocation StartLocationForType(TypeLoc TL) { + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); + // For elaborated types (e.g. `struct a::A`) we want the portion after the - // `struct` but including the namespace qualifier, `a::`. - if (auto ElaboratedTypeLoc = TL.getAs()) { - NestedNameSpecifierLoc NestedNameSpecifier = - ElaboratedTypeLoc.getQualifierLoc(); - if (NestedNameSpecifier.getNestedNameSpecifier()) - return NestedNameSpecifier.getBeginLoc(); - TL = TL.getNextTypeLoc(); + // `struct`, including the namespace qualifier, `a::`. + switch (TL.getTypeLocClass()) { + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + case TypeLoc::Enum: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getNameLoc(); + } + case TypeLoc::Typedef: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getNameLoc(); + } + case TypeLoc::UnresolvedUsing: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getNameLoc(); + } + case TypeLoc::Using: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getNameLoc(); + } + case TypeLoc::TemplateSpecialization: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getTemplateNameLoc(); + } + case TypeLoc::DeducedTemplateSpecialization: { + auto DTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = DTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return DTL.getTemplateNameLoc(); + } + case TypeLoc::DependentName: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getNameLoc(); + } + case TypeLoc::DependentTemplateSpecialization: { + auto TTL = TL.castAs(); + if (NestedNameSpecifierLoc QualifierLoc = TTL.getQualifierLoc()) + return QualifierLoc.getBeginLoc(); + return TTL.getTemplateNameLoc(); + } + default: + llvm_unreachable("unhandled TypeLoc class"); } - return TL.getBeginLoc(); } SourceLocation EndLocationForType(TypeLoc TL) { - // Dig past any namespace or keyword qualifications. - while (TL.getTypeLocClass() == TypeLoc::Elaborated || - TL.getTypeLocClass() == TypeLoc::Qualified) - TL = TL.getNextTypeLoc(); + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); // The location for template specializations (e.g. Foo) includes the // templated types in its location range. We want to restrict this to just // before the `<` character. - if (TL.getTypeLocClass() == TypeLoc::TemplateSpecialization) { - return TL.castAs() - .getLAngleLoc() - .getLocWithOffset(-1); - } + if (auto TTL = TL.getAs()) + return TTL.getLAngleLoc().getLocWithOffset(-1); return TL.getEndLoc(); } -NestedNameSpecifier *GetNestedNameForType(TypeLoc TL) { - // Dig past any keyword qualifications. - while (TL.getTypeLocClass() == TypeLoc::Qualified) - TL = TL.getNextTypeLoc(); - - // For elaborated types (e.g. `struct a::A`) we want the portion after the - // `struct` but including the namespace qualifier, `a::`. - if (auto ElaboratedTypeLoc = TL.getAs()) - return ElaboratedTypeLoc.getQualifierLoc().getNestedNameSpecifier(); - return nullptr; +NestedNameSpecifier GetNestedNameForType(TypeLoc TL) { + if (auto QTL = TL.getAs()) + TL = QTL.getUnqualifiedLoc(); + return TL.getPrefix().getNestedNameSpecifier(); } // Find all locations identified by the given USRs for rename. @@ -168,14 +206,14 @@ class RenameLocFinder : public RecursiveASTVisitor { const NamedDecl *FromDecl; // The declaration in which the nested name is contained (can be nullptr). const Decl *Context; - // The nested name being replaced (can be nullptr). - const NestedNameSpecifier *Specifier; + // The nested name being replaced. + NestedNameSpecifier Specifier; // Determine whether the prefix qualifiers of the NewName should be ignored. // Normally, we set it to true for the symbol declaration and definition to // avoid adding prefix qualifiers. // For example, if it is true and NewName is "a::b::foo", then the symbol // occurrence which the RenameInfo points to will be renamed to "foo". - bool IgnorePrefixQualifers; + bool IgnorePrefixQualifiers; }; bool VisitNamedDecl(const NamedDecl *Decl) { @@ -203,8 +241,8 @@ class RenameLocFinder : public RecursiveASTVisitor { EndLoc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, - /*IgnorePrefixQualifers=*/true}; + /*Specifier=*/std::nullopt, + /*IgnorePrefixQualifiers=*/true}; RenameInfos.push_back(Info); } } @@ -217,10 +255,10 @@ class RenameLocFinder : public RecursiveASTVisitor { auto EndLoc = Expr->getMemberLoc(); if (isInUSRSet(Decl)) { RenameInfos.push_back({StartLoc, EndLoc, - /*FromDecl=*/nullptr, - /*Context=*/nullptr, - /*Specifier=*/nullptr, - /*IgnorePrefixQualifiers=*/true}); + /*FromDecl=*/nullptr, + /*Context=*/nullptr, + /*Specifier=*/std::nullopt, + /*IgnorePrefixQualifiers=*/true}); } return true; } @@ -235,7 +273,7 @@ class RenameLocFinder : public RecursiveASTVisitor { RenameInfos.push_back({StartLoc, EndLoc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, + /*Specifier=*/std::nullopt, /*IgnorePrefixQualifiers=*/true}); } } @@ -257,7 +295,7 @@ class RenameLocFinder : public RecursiveASTVisitor { RenameInfos.push_back({Loc, Loc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, + /*Specifier=*/std::nullopt, /*IgnorePrefixQualifiers=*/true}); } } @@ -288,7 +326,7 @@ class RenameLocFinder : public RecursiveASTVisitor { RenameInfos.push_back({EndLoc, EndLoc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, + /*Specifier=*/std::nullopt, /*IgnorePrefixQualifiers=*/true}); return true; } @@ -332,7 +370,7 @@ class RenameLocFinder : public RecursiveASTVisitor { Decl, getClosestAncestorDecl(*Expr), Expr->getQualifier(), - /*IgnorePrefixQualifers=*/false}; + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } @@ -350,18 +388,18 @@ class RenameLocFinder : public RecursiveASTVisitor { } bool VisitNestedNameSpecifierLocations(NestedNameSpecifierLoc NestedLoc) { - if (!NestedLoc.getNestedNameSpecifier()->getAsType()) + TypeLoc TL = NestedLoc.getAsTypeLoc(); + if (!TL) return true; - if (const auto *TargetDecl = - getSupportedDeclFromTypeLoc(NestedLoc.getTypeLoc())) { + if (const auto *TargetDecl = getSupportedDeclFromTypeLoc(TL)) { if (isInUSRSet(TargetDecl)) { RenameInfo Info = {NestedLoc.getBeginLoc(), - EndLocationForType(NestedLoc.getTypeLoc()), + EndLocationForType(TL), TargetDecl, getClosestAncestorDecl(NestedLoc), - NestedLoc.getNestedNameSpecifier()->getPrefix(), - /*IgnorePrefixQualifers=*/false}; + /*Specifier=*/std::nullopt, + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } } @@ -411,7 +449,7 @@ class RenameLocFinder : public RecursiveASTVisitor { TargetDecl, getClosestAncestorDecl(Loc), GetNestedNameForType(Loc), - /*IgnorePrefixQualifers=*/false}; + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } return true; @@ -421,33 +459,17 @@ class RenameLocFinder : public RecursiveASTVisitor { // Handle specific template class specialiation cases. if (const auto *TemplateSpecType = dyn_cast(Loc.getType())) { - TypeLoc TargetLoc = Loc; - if (!ParentTypeLoc.isNull()) { - if (llvm::isa(ParentTypeLoc.getType())) - TargetLoc = ParentTypeLoc; - } - if (isInUSRSet(TemplateSpecType->getTemplateName().getAsTemplateDecl())) { - TypeLoc TargetLoc = Loc; - // FIXME: Find a better way to handle this case. - // For the qualified template class specification type like - // "ns::Foo" in "ns::Foo& f();", we want the parent typeLoc - // (ElaboratedType) of the TemplateSpecializationType in order to - // catch the prefix qualifiers "ns::". - if (!ParentTypeLoc.isNull() && - llvm::isa(ParentTypeLoc.getType())) - TargetLoc = ParentTypeLoc; - - auto StartLoc = StartLocationForType(TargetLoc); - auto EndLoc = EndLocationForType(TargetLoc); + auto StartLoc = StartLocationForType(Loc); + auto EndLoc = EndLocationForType(Loc); if (IsValidEditLoc(Context.getSourceManager(), StartLoc)) { RenameInfo Info = { StartLoc, EndLoc, TemplateSpecType->getTemplateName().getAsTemplateDecl(), - getClosestAncestorDecl(DynTypedNode::create(TargetLoc)), - GetNestedNameForType(TargetLoc), - /*IgnorePrefixQualifers=*/false}; + getClosestAncestorDecl(DynTypedNode::create(Loc)), + GetNestedNameForType(Loc), + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } } @@ -469,12 +491,7 @@ class RenameLocFinder : public RecursiveASTVisitor { const NamedDecl *getSupportedDeclFromTypeLoc(TypeLoc Loc) { if (const auto* TT = Loc.getType()->getAs()) return TT->getDecl(); - if (const auto *RD = Loc.getType()->getAsCXXRecordDecl()) - return RD; - if (const auto *ED = - llvm::dyn_cast_or_null(Loc.getType()->getAsTagDecl())) - return ED; - return nullptr; + return Loc.getType()->getAsTagDecl(); } // Get the closest ancester which is a declaration of a given AST node. @@ -549,7 +566,7 @@ createRenameAtomicChanges(llvm::ArrayRef USRs, for (const auto &RenameInfo : Finder.getRenameInfos()) { std::string ReplacedName = NewName.str(); - if (RenameInfo.IgnorePrefixQualifers) { + if (RenameInfo.IgnorePrefixQualifiers) { // Get the name without prefix qualifiers from NewName. size_t LastColonPos = NewName.find_last_of(':'); if (LastColonPos != std::string::npos) diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index eb9fa7a7fa1e8..546161cee33f4 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -918,97 +918,91 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return true; } - // FIXME: Fix `NestedNameSpecifierLoc::getLocalSourceRange` for the - // `DependentTemplateSpecializationType` case. - /// Given a nested-name-specifier return the range for the last name - /// specifier. - /// - /// e.g. `std::T::template X::` => `template X::` - SourceRange getLocalSourceRange(const NestedNameSpecifierLoc &NNSLoc) { - auto SR = NNSLoc.getLocalSourceRange(); - - // The method `NestedNameSpecifierLoc::getLocalSourceRange` *should* - // return the desired `SourceRange`, but there is a corner case. For a - // `DependentTemplateSpecializationType` this method returns its - // qualifiers as well, in other words in the example above this method - // returns `T::template X::` instead of only `template X::` - if (auto TL = NNSLoc.getTypeLoc()) { - if (auto DependentTL = - TL.getAs()) { - // The 'template' keyword is always present in dependent template - // specializations. Except in the case of incorrect code - // TODO: Treat the case of incorrect code. - SR.setBegin(DependentTL.getTemplateKeywordLoc()); - } - } - - return SR; - } - - syntax::NodeKind getNameSpecifierKind(const NestedNameSpecifier &NNS) { - switch (NNS.getKind()) { - case NestedNameSpecifier::Global: - return syntax::NodeKind::GlobalNameSpecifier; - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::Identifier: - return syntax::NodeKind::IdentifierNameSpecifier; - case NestedNameSpecifier::TypeSpec: { - const auto *NNSType = NNS.getAsType(); - assert(NNSType); - if (isa(NNSType)) - return syntax::NodeKind::DecltypeNameSpecifier; - if (isa( - NNSType)) - return syntax::NodeKind::SimpleTemplateNameSpecifier; - return syntax::NodeKind::IdentifierNameSpecifier; - } - default: - // FIXME: Support Microsoft's __super - llvm::report_fatal_error("We don't yet support the __super specifier", - true); - } + syntax::NameSpecifier *buildIdentifier(SourceRange SR, + bool DropBack = false) { + auto NameSpecifierTokens = Builder.getRange(SR).drop_back(DropBack); + assert(NameSpecifierTokens.size() == 1); + Builder.markChildToken(NameSpecifierTokens.begin(), + syntax::NodeRole::Unknown); + auto *NS = new (allocator()) syntax::IdentifierNameSpecifier; + Builder.foldNode(NameSpecifierTokens, NS, nullptr); + return NS; + } + + syntax::NameSpecifier *buildSimpleTemplateName(SourceRange SR) { + auto NameSpecifierTokens = Builder.getRange(SR); + // TODO: Build `SimpleTemplateNameSpecifier` children and implement + // accessors to them. + // Be aware, we cannot do that simply by calling `TraverseTypeLoc`, + // some `TypeLoc`s have inside them the previous name specifier and + // we want to treat them independently. + auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier; + Builder.foldNode(NameSpecifierTokens, NS, nullptr); + return NS; } syntax::NameSpecifier * buildNameSpecifier(const NestedNameSpecifierLoc &NNSLoc) { assert(NNSLoc.hasQualifier()); - auto NameSpecifierTokens = - Builder.getRange(getLocalSourceRange(NNSLoc)).drop_back(); - switch (getNameSpecifierKind(*NNSLoc.getNestedNameSpecifier())) { - case syntax::NodeKind::GlobalNameSpecifier: + switch (NNSLoc.getNestedNameSpecifier().getKind()) { + case NestedNameSpecifier::Kind::Global: return new (allocator()) syntax::GlobalNameSpecifier; - case syntax::NodeKind::IdentifierNameSpecifier: { - assert(NameSpecifierTokens.size() == 1); - Builder.markChildToken(NameSpecifierTokens.begin(), - syntax::NodeRole::Unknown); - auto *NS = new (allocator()) syntax::IdentifierNameSpecifier; - Builder.foldNode(NameSpecifierTokens, NS, nullptr); - return NS; - } - case syntax::NodeKind::SimpleTemplateNameSpecifier: { - // TODO: Build `SimpleTemplateNameSpecifier` children and implement - // accessors to them. - // Be aware, we cannot do that simply by calling `TraverseTypeLoc`, - // some `TypeLoc`s have inside them the previous name specifier and - // we want to treat them independently. - auto *NS = new (allocator()) syntax::SimpleTemplateNameSpecifier; - Builder.foldNode(NameSpecifierTokens, NS, nullptr); - return NS; - } - case syntax::NodeKind::DecltypeNameSpecifier: { - const auto TL = NNSLoc.getTypeLoc().castAs(); - if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(TL)) - return nullptr; - auto *NS = new (allocator()) syntax::DecltypeNameSpecifier; - // TODO: Implement accessor to `DecltypeNameSpecifier` inner - // `DecltypeTypeLoc`. - // For that add mapping from `TypeLoc` to `syntax::Node*` then: - // Builder.markChild(TypeLoc, syntax::NodeRole); - Builder.foldNode(NameSpecifierTokens, NS, nullptr); - return NS; + + case NestedNameSpecifier::Kind::Namespace: + return buildIdentifier(NNSLoc.getLocalSourceRange(), /*DropBack=*/true); + + case NestedNameSpecifier::Kind::Type: { + TypeLoc TL = NNSLoc.castAsTypeLoc(); + switch (TL.getTypeLocClass()) { + case TypeLoc::Record: + case TypeLoc::InjectedClassName: + case TypeLoc::Enum: + return buildIdentifier(TL.castAs().getNameLoc()); + case TypeLoc::Typedef: + return buildIdentifier(TL.castAs().getNameLoc()); + case TypeLoc::UnresolvedUsing: + return buildIdentifier( + TL.castAs().getNameLoc()); + case TypeLoc::Using: + return buildIdentifier(TL.castAs().getNameLoc()); + case TypeLoc::DependentName: + return buildIdentifier(TL.castAs().getNameLoc()); + case TypeLoc::TemplateSpecialization: { + auto TST = TL.castAs(); + SourceLocation BeginLoc = TST.getTemplateKeywordLoc(); + if (BeginLoc.isInvalid()) + BeginLoc = TST.getTemplateNameLoc(); + return buildSimpleTemplateName({BeginLoc, TST.getEndLoc()}); + } + case TypeLoc::DependentTemplateSpecialization: { + auto DT = TL.castAs(); + SourceLocation BeginLoc = DT.getTemplateKeywordLoc(); + if (BeginLoc.isInvalid()) + BeginLoc = DT.getTemplateNameLoc(); + return buildSimpleTemplateName({BeginLoc, DT.getEndLoc()}); + } + case TypeLoc::Decltype: { + const auto DTL = TL.castAs(); + if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc( + DTL, /*TraverseQualifier=*/true)) + return nullptr; + auto *NS = new (allocator()) syntax::DecltypeNameSpecifier; + // TODO: Implement accessor to `DecltypeNameSpecifier` inner + // `DecltypeTypeLoc`. + // For that add mapping from `TypeLoc` to `syntax::Node*` then: + // Builder.markChild(TypeLoc, syntax::NodeRole); + Builder.foldNode(Builder.getRange(DTL.getLocalSourceRange()), NS, + nullptr); + return NS; + } + default: + return buildIdentifier(TL.getLocalSourceRange()); + } } default: - llvm_unreachable("getChildKind() does not return this value"); + // FIXME: Support Microsoft's __super + llvm::report_fatal_error("We don't yet support the __super specifier", + true); } } @@ -1019,12 +1013,16 @@ class BuildTreeVisitor : public RecursiveASTVisitor { bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc QualifierLoc) { if (!QualifierLoc) return true; - for (auto It = QualifierLoc; It; It = It.getPrefix()) { + for (auto It = QualifierLoc; It; /**/) { auto *NS = buildNameSpecifier(It); if (!NS) return false; Builder.markChild(NS, syntax::NodeRole::ListElement); Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter); + if (TypeLoc TL = It.getAsTypeLoc()) + It = TL.getPrefix(); + else + It = It.getAsNamespaceAndPrefix().Prefix; } Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), new (allocator()) syntax::NestedNameSpecifier, @@ -1328,7 +1326,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { // FIXME: Deleting the `TraverseParenTypeLoc` override doesn't change test // results. Find test coverage or remove it. - bool TraverseParenTypeLoc(ParenTypeLoc L) { + bool TraverseParenTypeLoc(ParenTypeLoc L, bool TraverseQualifier) { // We reverse order of traversal to get the proper syntax structure. if (!WalkUpFromParenTypeLoc(L)) return false; @@ -1391,7 +1389,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return WalkUpFromFunctionTypeLoc(L); } - bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L) { + bool TraverseMemberPointerTypeLoc(MemberPointerTypeLoc L, + bool TraverseQualifier) { // In the source code "void (Y::*mp)()" `MemberPointerTypeLoc` corresponds // to "Y::*" but it points to a `ParenTypeLoc` that corresponds to // "(Y::*mp)" We thus reverse the order of traversal to get the proper diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp b/clang/lib/Tooling/Transformer/RangeSelector.cpp index 00f4611ddb5d4..171c786bc366f 100644 --- a/clang/lib/Tooling/Transformer/RangeSelector.cpp +++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp @@ -222,14 +222,10 @@ RangeSelector transformer::name(std::string ID) { return CharSourceRange::getTokenRange(L, L); } if (const auto *T = Node.get()) { - TypeLoc Loc = *T; - auto ET = Loc.getAs(); - if (!ET.isNull()) - Loc = ET.getNamedTypeLoc(); - if (auto SpecLoc = Loc.getAs(); + if (auto SpecLoc = T->getAs(); !SpecLoc.isNull()) return CharSourceRange::getTokenRange(SpecLoc.getTemplateNameLoc()); - return CharSourceRange::getTokenRange(Loc.getSourceRange()); + return CharSourceRange::getTokenRange(T->getSourceRange()); } return typeError(ID, Node.getNodeKind(), "DeclRefExpr, NamedDecl, CXXCtorInitializer, TypeLoc"); diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl index 1c8b9c10f5a98..76de39ca4b60e 100644 --- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl @@ -91,21 +91,21 @@ RESOURCE Buffer; // Default constructor -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void ()' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void ()' inline // CHECK-NEXT: CompoundStmt // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: AlwaysInlineAttr // Constructor from binding -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline // CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} range 'int' @@ -114,12 +114,12 @@ RESOURCE Buffer; // CHECK-NEXT: CompoundStmt {{.*}} // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int' @@ -129,7 +129,7 @@ RESOURCE Buffer; // Constructor from implicit binding -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, int, unsigned int, unsigned int, const char *)' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void (unsigned int, int, unsigned int, unsigned int, const char *)' inline // CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} range 'int' // CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int' @@ -138,12 +138,12 @@ RESOURCE Buffer; // CHECK-NEXT: CompoundStmt {{.*}} // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int' // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int' @@ -166,7 +166,7 @@ RESOURCE Buffer; // CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SUBSCRIPT-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-SUBSCRIPT-SAME: ' lvalue .__handle {{.*}} -// CHECK-SUBSCRIPT-NEXT: CXXThisExpr {{.*}} 'const [[RESOURCE]]' lvalue implicit this +// CHECK-SUBSCRIPT-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-SUBSCRIPT-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-SUBSCRIPT-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -183,7 +183,7 @@ RESOURCE Buffer; // CHECK-SUBSCRIPT-UAV-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-SUBSCRIPT-UAV-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-SUBSCRIPT-UAV-SAME: ' lvalue .__handle {{.*}} -// CHECK-SUBSCRIPT-UAV-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-SUBSCRIPT-UAV-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-SUBSCRIPT-UAV-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-SUBSCRIPT-UAV-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -204,7 +204,7 @@ RESOURCE Buffer; // CHECK-LOAD-SAME{LITERAL}: [[hlsl::resource_class( // CHECK-LOAD-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-LOAD-SAME: ' lvalue .__handle {{.*}} -// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-LOAD-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-LOAD-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-LOAD-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -220,7 +220,7 @@ RESOURCE Buffer; // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-COUNTER-NEXT: CXXThisExpr {{.*}} 'RWStructuredBuffer' lvalue implicit this +// CHECK-COUNTER-NEXT: CXXThisExpr {{.*}} 'hlsl::RWStructuredBuffer' lvalue implicit this // CHECK-COUNTER-NEXT: IntegerLiteral {{.*}} 'int' 1 // CHECK-COUNTER-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -236,7 +236,7 @@ RESOURCE Buffer; // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-COUNTER-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-COUNTER-NEXT: CXXThisExpr {{.*}} 'RWStructuredBuffer' lvalue implicit this +// CHECK-COUNTER-NEXT: CXXThisExpr {{.*}} 'hlsl::RWStructuredBuffer' lvalue implicit this // CHECK-COUNTER-NEXT: IntegerLiteral {{.*}} 'int' -1 // CHECK-COUNTER-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -254,7 +254,7 @@ RESOURCE Buffer; // CHECK-APPEND-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-APPEND-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-APPEND-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-APPEND-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-APPEND-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-APPEND-NEXT: CallExpr {{.*}} 'unsigned int' // CHECK-APPEND-NEXT: ImplicitCastExpr {{.*}} // CHECK-APPEND-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept' @@ -262,7 +262,7 @@ RESOURCE Buffer; // CHECK-APPEND-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-APPEND-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-APPEND-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-APPEND-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-APPEND-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-APPEND-NEXT: IntegerLiteral {{.*}} 'int' 1 // CHECK-APPEND-NEXT: DeclRefExpr {{.*}} 'element_type' ParmVar {{.*}} 'value' 'element_type' @@ -279,7 +279,7 @@ RESOURCE Buffer; // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-CONSUME-NEXT: CallExpr {{.*}} 'unsigned int' // CHECK-CONSUME-NEXT: ImplicitCastExpr {{.*}} // CHECK-CONSUME-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_buffer_update_counter' 'unsigned int (...) noexcept' @@ -287,7 +287,7 @@ RESOURCE Buffer; // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::raw_buffer]] // CHECK-CONSUME-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]' lvalue .__handle -// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-CONSUME-NEXT: IntegerLiteral {{.*}} 'int' -1 // CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl index d6b88e276762e..936a060a305cd 100644 --- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl +++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl @@ -66,21 +66,21 @@ RESOURCE Buffer; // Default constructor -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void ()' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void ()' inline // CHECK-NEXT: CompoundStmt // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_uninitializedhandle' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: AlwaysInlineAttr // Constructor from binding -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void (unsigned int, unsigned int, int, unsigned int, const char *)' inline // CHECK-NEXT: ParmVarDecl {{.*}} registerNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} range 'int' @@ -89,12 +89,12 @@ RESOURCE Buffer; // CHECK-NEXT: CompoundStmt {{.*}} // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_handlefrombinding' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'registerNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int' @@ -104,7 +104,7 @@ RESOURCE Buffer; // Constructor from implicit binding -// CHECK: CXXConstructorDecl {{.*}} [[RESOURCE]] 'void (unsigned int, int, unsigned int, unsigned int, const char *)' inline +// CHECK: CXXConstructorDecl {{.*}} hlsl::[[RESOURCE]] 'void (unsigned int, int, unsigned int, unsigned int, const char *)' inline // CHECK-NEXT: ParmVarDecl {{.*}} spaceNo 'unsigned int' // CHECK-NEXT: ParmVarDecl {{.*}} range 'int' // CHECK-NEXT: ParmVarDecl {{.*}} index 'unsigned int' @@ -113,12 +113,12 @@ RESOURCE Buffer; // CHECK-NEXT: CompoundStmt {{.*}} // CHECK-NEXT: BinaryOperator {{.*}} '=' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: CallExpr {{.*}} '__hlsl_resource_t // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_handlefromimplicitbinding' // CHECK-NEXT: MemberExpr {{.*}} lvalue .__handle -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'spaceNo' 'unsigned int' // CHECK-NEXT: DeclRefExpr {{.*}} 'int' ParmVar {{.*}} 'range' 'int' // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'index' 'unsigned int' @@ -141,7 +141,7 @@ RESOURCE Buffer; // CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-SAME: ' lvalue .__handle {{.*}} -// CHECK-NEXT: CXXThisExpr {{.*}} 'const [[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'const hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -157,7 +157,7 @@ RESOURCE Buffer; // CHECK-UAV-SAME{LITERAL}: [[hlsl::resource_class(UAV)]] // CHECK-UAV-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-UAV-SAME: ' lvalue .__handle {{.*}} -// CHECK-UAV-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-UAV-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-UAV-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-UAV-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline @@ -176,7 +176,7 @@ RESOURCE Buffer; // CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] // CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] // CHECK-SAME: ' lvalue .__handle {{.*}} -// CHECK-NEXT: CXXThisExpr {{.*}} '[[RESOURCE]]' lvalue implicit this +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this // CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int' // CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline diff --git a/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl b/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl index 2f08531000f32..1c5e06789c3e4 100644 --- a/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl +++ b/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl @@ -63,9 +63,9 @@ namespace NS2 { // CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 2]]:11 cbuffer CB2 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer cbuffer CB2 { - // CHECK: VarDecl {{.*}} foo0 'hlsl_constant ::Foo':'hlsl_constant Foo' + // CHECK: VarDecl {{.*}} foo0 'hlsl_constant ::Foo' ::Foo foo0; - // CHECK: VarDecl {{.*}} foo1 'hlsl_constant Foo':'hlsl_constant NS2::Foo' + // CHECK: VarDecl {{.*}} foo1 'hlsl_constant Foo' Foo foo1; // CHECK: VarDecl {{.*}} foo2 'hlsl_constant NS1::Foo' NS1::Foo foo2; diff --git a/clang/test/AST/HLSL/vector-constructors.hlsl b/clang/test/AST/HLSL/vector-constructors.hlsl index 31d8dd0fdac8e..fd43a7dcbfcca 100644 --- a/clang/test/AST/HLSL/vector-constructors.hlsl +++ b/clang/test/AST/HLSL/vector-constructors.hlsl @@ -88,10 +88,10 @@ void entry() { // CHECK-NEXT: InitListExpr // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .f {{.*}} -// CHECK-NEXT: DeclRefExpr {{.*}} 'struct S':'S' lvalue Var {{.*}} 's' 'struct S':'S' +// CHECK-NEXT: DeclRefExpr {{.*}} 'struct S' lvalue Var {{.*}} 's' 'struct S' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} 'float' lvalue .f {{.*}} -// CHECK-NEXT: DeclRefExpr {{.*}} 'struct S':'S' lvalue Var {{.*}} 's' 'struct S':'S' +// CHECK-NEXT: DeclRefExpr {{.*}} 'struct S' lvalue Var {{.*}} 's' 'struct S' struct T { operator float() const { return 1.0f; } @@ -105,12 +105,12 @@ void entry() { // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} '' .operator float {{.*}} // CHECK-NEXT: ImplicitCastExpr {{.*}} 'const T' lvalue -// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T':'T' lvalue Var {{.*}} 't' 'struct T':'T' +// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T' lvalue Var {{.*}} 't' 'struct T' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: CXXMemberCallExpr {{.*}} 'float' // CHECK-NEXT: MemberExpr {{.*}} '' .operator float {{.*}} // CHECK-NEXT: ImplicitCastExpr {{.*}} 'const T' lvalue -// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T':'T' lvalue Var {{.*}} 't' 'struct T':'T' +// CHECK-NEXT: DeclRefExpr {{.*}} 'struct T' lvalue Var {{.*}} 't' 'struct T' typedef float2 second_level_of_typedefs; second_level_of_typedefs foo6 = float2(1.0f, 2.0f); diff --git a/clang/test/AST/arm-mfp8.cpp b/clang/test/AST/arm-mfp8.cpp index 195c734fc753e..b1fa04a3a79c1 100644 --- a/clang/test/AST/arm-mfp8.cpp +++ b/clang/test/AST/arm-mfp8.cpp @@ -49,7 +49,7 @@ class C1 { } }; -//CHECK: | |-CXXRecordDecl {{.*}} referenced class C1 +//CHECK: | |-CXXRecordDecl {{.*}} class C1 //CHECK-NEXT: | |-FieldDecl {{.*}} f1c '__mfp8' //CHECK-NEXT: | |-VarDecl {{.*}} f2c 'const __mfp8' static //CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile __mfp8' diff --git a/clang/test/AST/ast-dump-color.cpp b/clang/test/AST/ast-dump-color.cpp index 87797f6bffc5b..2e60e760283de 100644 --- a/clang/test/AST/ast-dump-color.cpp +++ b/clang/test/AST/ast-dump-color.cpp @@ -82,15 +82,15 @@ struct Invalid { //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'const Mutex &'[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (Mutex &&)'[[RESET]] inline{{ .*$}} //CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'Mutex &&'[[RESET]]{{$}} -//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] -//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}} -//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] -//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}} +//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex'[[RESET]] +//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}} +//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex'[[RESET]] +//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:26:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] TestExpr[[RESET]] [[Green]]'int'[[RESET]] //CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}} -//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] non_odr_use_unevaluated{{$}} +//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex'[[RESET]] non_odr_use_unevaluated{{$}} //CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:1[[RESET]], [[Yellow]]line:30:1[[RESET]]> [[Yellow]]line:28:8[[RESET]] struct[[CYAN]] Invalid[[RESET]] definition -//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit referenced struct[[CYAN]] Invalid[[RESET]] +//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit struct[[CYAN]] Invalid[[RESET]] //CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:29:3[[RESET]], [[Yellow]]col:42[[RESET]]> [[Yellow]]col:29[[RESET]] invalid[[CYAN]] Invalid[[RESET]] [[Green]]'void (int)'[[RESET]] //CHECK: {{^}}[[Blue]]| | |-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:37[[RESET]], [[Yellow]][[RESET]]> [[Yellow]]col:42[[RESET]] invalid [[Green]]'int'[[RESET]] //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[BLUE]]NoInlineAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:18[[RESET]]> @@ -100,5 +100,5 @@ struct Invalid { //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'const Invalid &'[[RESET]] //CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit constexpr[[CYAN]] Invalid[[RESET]] [[Green]]'void (Invalid &&)'[[RESET]] inline default trivial noexcept-unevaluated 0x{{[0-9a-fA-F]*}} //CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] [[Green]]'Invalid &&'[[RESET]] -//CHECK: {{^}}[[Blue]]`-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:30:3[[RESET]]> [[Yellow]]col:3[[RESET]][[CYAN]] Invalid[[RESET]] [[Green]]'struct Invalid':'Invalid'[[RESET]] -//CHECK: {{^}}[[Blue]] `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'struct Invalid':'Invalid'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]] +//CHECK: {{^}}[[Blue]]`-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:30:3[[RESET]]> [[Yellow]]col:3[[RESET]][[CYAN]] Invalid[[RESET]] [[Green]]'struct Invalid'[[RESET]] +//CHECK: {{^}}[[Blue]] `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'struct Invalid'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]] diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index f39a4cee518ce..781fb9f28cb8d 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -39,15 +39,14 @@ Out2::AInner t(1.0); // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent // CHECK-NEXT: | | | `-name: 'Out2::AInner' // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}} -// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent -// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent -// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified -// CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} -// CHECK-NEXT: | | `-TemplateArgument type 'Y' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y' -// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' -// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 -// CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y' +// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent +// CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified +// CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} +// CHECK-NEXT: | | `-TemplateArgument type 'Y' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y' +// CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 +// CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y' // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (Y) -> Inner' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'Y' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation @@ -188,9 +187,9 @@ void foo() { // CHECK-NEXT: | | | |-ImplicitConceptSpecializationDecl {{.*}} // CHECK-NEXT: | | | | |-TemplateArgument type 'type-parameter-0-2' // CHECK-NEXT: | | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2 -// CHECK-NEXT: | | | | `-TemplateArgument pack '>' -// CHECK-NEXT: | | | | `-TemplateArgument type 'Packs' -// CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'Packs' dependent +// CHECK-NEXT: | | | | `-TemplateArgument pack '>' +// CHECK-NEXT: | | | | `-TemplateArgument type 'GH124715::Packs' +// CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'GH124715::Packs' dependent // CHECK-NEXT: | | | | |-name: 'GH124715::Packs' // CHECK-NEXT: | | | | | `-ClassTemplateDecl {{.*}} Packs // CHECK-NEXT: | | | | `-TemplateArgument pack '' diff --git a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp index fc86aeb3e5ec3..09a274aa46422 100644 --- a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp +++ b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp @@ -33,5 +33,5 @@ struct B { operator A(this B); }; A a = A(B{}); -// CHECK: CallExpr 0x{{[^ ]*}} 'A':'GH130272::A' +// CHECK: CallExpr 0x{{[^ ]*}} 'A' } diff --git a/clang/test/AST/ast-dump-decl-json.c b/clang/test/AST/ast-dump-decl-json.c index ec2d75ba7195d..b84ddf93f44c3 100644 --- a/clang/test/AST/ast-dump-decl-json.c +++ b/clang/test/AST/ast-dump-decl-json.c @@ -585,7 +585,6 @@ void testParmVarDecl(int TestParmVarDecl); // CHECK-NEXT: }, // CHECK-NEXT: "name": "e", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "enum TestEnumDeclAnon::(unnamed at {{.*}}:31:3)", // CHECK-NEXT: "qualType": "enum (unnamed enum at {{.*}}:31:3)" // CHECK-NEXT: } // CHECK-NEXT: } @@ -777,7 +776,6 @@ void testParmVarDecl(int TestParmVarDecl); // CHECK-NEXT: }, // CHECK-NEXT: "name": "testRecordDeclAnon1", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "struct TestRecordDeclAnon1::(unnamed at {{.*}}:46:3)", // CHECK-NEXT: "qualType": "struct (unnamed struct at {{.*}}:46:3)" // CHECK-NEXT: } // CHECK-NEXT: } @@ -1204,7 +1202,6 @@ void testParmVarDecl(int TestParmVarDecl); // CHECK-NEXT: }, // CHECK-NEXT: "name": "y", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "enum (unnamed at {{.*}}:69:29)", // CHECK-NEXT: "qualType": "enum (unnamed enum at {{.*}}:69:29)" // CHECK-NEXT: } // CHECK-NEXT: }, diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp index 08d8fba795daa..dca0e9b9ca10a 100644 --- a/clang/test/AST/ast-dump-decl.cpp +++ b/clang/test/AST/ast-dump-decl.cpp @@ -35,9 +35,9 @@ namespace testVarDeclNRVO { // CHECK: FunctionDecl{{.*}} TestFuncNRVO 'A ()' // CHECK-NEXT: `-CompoundStmt // CHECK-NEXT: |-DeclStmt -// CHECK-NEXT: | `-VarDecl{{.*}} TestVarDeclNRVO 'A':'testVarDeclNRVO::A' nrvo callinit +// CHECK-NEXT: | `-VarDecl{{.*}} TestVarDeclNRVO 'A' nrvo callinit // CHECK-NEXT: | `-CXXConstructExpr -// CHECK-NEXT: `-ReturnStmt{{.*}} nrvo_candidate(Var {{.*}} 'TestVarDeclNRVO' 'A':'testVarDeclNRVO::A') +// CHECK-NEXT: `-ReturnStmt{{.*}} nrvo_candidate(Var {{.*}} 'TestVarDeclNRVO' 'A') void testParmVarDeclInit(int TestParmVarDeclInit = 0); // CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int' @@ -131,8 +131,8 @@ namespace testCXXRecordDecl { // CHECK-NEXT: CopyAssignment simple non_trivial has_const_param // CHECK-NEXT: MoveAssignment exists simple non_trivial // CHECK-NEXT: Destructor simple irrelevant trivial -// CHECK-NEXT: virtual private 'A':'testCXXRecordDecl::A' -// CHECK-NEXT: public 'B':'testCXXRecordDecl::B' +// CHECK-NEXT: virtual private 'A' +// CHECK-NEXT: public 'B' // CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl // CHECK-NEXT: FieldDecl @@ -269,7 +269,7 @@ namespace testFunctionTemplateDecl { // CHECK-NEXT: |-TemplateArgument type 'testFunctionTemplateDecl::B' // CHECK-NEXT: | `-RecordType 0{{.+}} 'testFunctionTemplateDecl::B' // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'B' - // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:41 'B':'testFunctionTemplateDecl::B' + // CHECK-NEXT: `-ParmVarDecl 0x{{.+}} col:41 'B' namespace testClassTemplateDecl { @@ -330,8 +330,8 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | | `-Destructor irrelevant non_trivial user_declared{{$}} // CHECK-NEXT: | |-CXXRecordDecl 0x{{.+}} col:30 implicit referenced class TestClassTemplate{{$}} // CHECK-NEXT: | |-AccessSpecDecl 0x{{.+}} col:3 public{{$}} -// CHECK-NEXT: | |-CXXConstructorDecl 0x[[#%x,TEMPLATE_CONSTRUCTOR_DECL:]] col:5 TestClassTemplate 'void ()'{{$}} -// CHECK-NEXT: | |-CXXDestructorDecl 0x[[#%x,TEMPLATE_DESTRUCTOR_DECL:]] col:5 ~TestClassTemplate 'void ()' not_selected{{$}} +// CHECK-NEXT: | |-CXXConstructorDecl 0x[[#%x,TEMPLATE_CONSTRUCTOR_DECL:]] col:5 testClassTemplateDecl::TestClassTemplate 'void ()'{{$}} +// CHECK-NEXT: | |-CXXDestructorDecl 0x[[#%x,TEMPLATE_DESTRUCTOR_DECL:]] col:5 ~testClassTemplateDecl::TestClassTemplate 'void ()' not_selected{{$}} // CHECK-NEXT: | |-CXXMethodDecl 0x[[#%x,TEMPLATE_METHOD_DECL:]] col:9 j 'int ()'{{$}} // CHECK-NEXT: | `-FieldDecl 0x{{.+}} col:9 i 'int'{{$}} // CHECK-NEXT: |-ClassTemplateSpecializationDecl 0x{{.+}} line:[[@LINE-56]]:30 class TestClassTemplate definition implicit_instantiation{{$}} @@ -343,7 +343,7 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | | |-MoveAssignment{{$}} // CHECK-NEXT: | | `-Destructor non_trivial user_declared{{$}} // CHECK-NEXT: | |-TemplateArgument type 'testClassTemplateDecl::A'{{$}} -// CHECK-NEXT: | | `-RecordType 0{{.+}} 'testClassTemplateDecl::A'{{$}} +// CHECK-NEXT: | | `-RecordType 0{{.+}} 'testClassTemplateDecl::A' canonical{{$}} // CHECK-NEXT: | | `-CXXRecord 0x{{.+}} 'A'{{$}} // CHECK-NEXT: | |-CXXRecordDecl 0x{{.+}} col:30 implicit class TestClassTemplate{{$}} // CHECK-NEXT: | |-AccessSpecDecl 0x{{.+}} col:3 public{{$}} @@ -366,7 +366,7 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit{{$}} // CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit{{$}} // CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::B'{{$}} -// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::B'{{$}} +// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::B' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'B'{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:20 implicit class TestClassTemplate{{$}} // CHECK-NEXT: `-FieldDecl 0x{{.+}} col:9 j 'int'{{$}} @@ -380,7 +380,7 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | |-MoveAssignment{{$}} // CHECK-NEXT: | `-Destructor non_trivial user_declared{{$}} // CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::C'{{$}} -// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::C'{{$}} +// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::C' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'C'{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:30 implicit class TestClassTemplate{{$}} // CHECK-NEXT: |-AccessSpecDecl 0x{{.+}} col:3 public{{$}} @@ -398,7 +398,7 @@ namespace testClassTemplateDecl { // CHECK-NEXT: | |-MoveAssignment{{$}} // CHECK-NEXT: | `-Destructor non_trivial user_declared{{$}} // CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::D'{{$}} -// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::D'{{$}} +// CHECK-NEXT: | `-RecordType 0{{.+}} 'testClassTemplateDecl::D' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'D'{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:30 implicit class TestClassTemplate{{$}} // CHECK-NEXT: |-AccessSpecDecl 0x{{.+}} col:3 public{{$}} @@ -432,7 +432,7 @@ namespace testClassTemplateDecl { // CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-0'{{$}} // CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0{{$}} // CHECK-NEXT: |-TemplateArgument type 'testClassTemplateDecl::A'{{$}} -// CHECK-NEXT: | `-RecordType 0x{{.+}} 'testClassTemplateDecl::A'{{$}} +// CHECK-NEXT: | `-RecordType 0x{{.+}} 'testClassTemplateDecl::A' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'A'{{$}} // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} col:21 referenced typename depth 0 index 0 T1{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:31 implicit class TestClassTemplatePartial{{$}} @@ -605,7 +605,7 @@ namespace testCanonicalTemplate { // CHECK-NEXT: | `-ParmVarDecl 0x{{.*}} col:51 'T'{{$}} // CHECK-NEXT: `-FunctionDecl 0x{{.*}} col:29 used TestFunctionTemplate 'void (testCanonicalTemplate::A)' implicit_instantiation{{$}} // CHECK-NEXT: |-TemplateArgument type 'testCanonicalTemplate::A'{{$}} - // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A'{{$}} + // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'A'{{$}} // CHECK-NEXT: `-ParmVarDecl 0x{{.*}} col:51 'testCanonicalTemplate::A'{{$}} @@ -644,7 +644,7 @@ namespace testCanonicalTemplate { // CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit{{$}} // CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit{{$}} // CHECK-NEXT: |-TemplateArgument type 'testCanonicalTemplate::A'{{$}} - // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A'{{$}} + // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'A'{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:31 implicit class TestClassTemplate{{$}} // CHECK-NEXT: |-FriendDecl 0x{{.+}} col:40{{$}} @@ -677,7 +677,7 @@ namespace testCanonicalTemplate { // CHECK-NEXT: | |-MoveAssignment exists simple trivial needs_implicit{{$}} // CHECK-NEXT: | `-Destructor simple irrelevant trivial needs_implicit{{$}} // CHECK-NEXT: |-TemplateArgument type 'testCanonicalTemplate::A'{{$}} - // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A'{{$}} + // CHECK-NEXT: | `-RecordType 0x{{.+}} 'testCanonicalTemplate::A' canonical{{$}} // CHECK-NEXT: | `-CXXRecord 0x{{.+}} 'A'{{$}} // CHECK-NEXT: |-CXXRecordDecl 0x{{.+}} col:31 implicit class TestClassTemplate2{{$}} // CHECK-NEXT: |-CXXConstructorDecl 0x{{.+}} col:31 implicit used constexpr TestClassTemplate2 'void () noexcept' inline default trivial{{$}} @@ -721,7 +721,7 @@ namespace testCanonicalTemplate { // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} col:25 referenced typename depth 0 index 0 T{{$}} // CHECK-NEXT: |-VarDecl 0x{{.+}} col:43 TestVarTemplate 'const T' static{{$}} // CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}} - // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}} + // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'S'{{$}} // CHECK-NEXT: | |-TemplateArgument type 'int'{{$}} // CHECK-NEXT: | | `-BuiltinType 0x{{.+}} 'int'{{$}} // CHECK-NEXT: | `-InitListExpr 0x{{.+}} 'int'{{$}} @@ -735,13 +735,13 @@ namespace testCanonicalTemplate { // CHECK: VarTemplateDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-24]]:3, line:[[@LINE-23]]:34> col:14 TestVarTemplate{{$}} // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} col:21 referenced typename depth 0 index 0 T{{$}} // CHECK-NEXT: |-VarDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} col:14 TestVarTemplate 'const T' cinit{{$}} - // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}} + // CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'S'{{$}} // CHECK-NEXT: | `-InitListExpr 0x{{.+}} 'void'{{$}} // CHECK-NEXT: |-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}} // CHECK-NEXT: `-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}} // CHECK: VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-32]]:3, line:[[@LINE-31]]:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}} - // CHECK-NEXT: |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}} + // CHECK-NEXT: |-NestedNameSpecifier TypeSpec 'S'{{$}} // CHECK-NEXT: |-TemplateArgument type 'int'{{$}} // CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'int'{{$}} // CHECK-NEXT: `-InitListExpr 0x{{.+}} 'int'{{$}} @@ -901,7 +901,7 @@ template class TestFriendDecl { // CHECK: CXXRecord{{.*}} TestFriendDecl // CHECK-NEXT: FriendDecl // CHECK-NEXT: FunctionDecl{{.*}} foo -// CHECK-NEXT: FriendDecl{{.*}} 'class A':'A' +// CHECK-NEXT: FriendDecl{{.*}} 'class A' // CHECK-NEXT: CXXRecordDecl{{.*}} class A // CHECK-NEXT: FriendDecl{{.*}} 'T' diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 11026c9d302f0..6293f8cb3fe0e 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -7962,7 +7962,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", @@ -7988,7 +7987,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -8142,7 +8140,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -8395,7 +8392,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", @@ -8421,7 +8417,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -8720,7 +8715,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", @@ -8746,7 +8740,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -8900,7 +8893,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -9032,7 +9024,6 @@ void TestNonADLCall3() { // CHECK-NEXT: "isUsed": true, // CHECK-NEXT: "name": "x", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "init": "call", @@ -9053,7 +9044,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", @@ -9155,7 +9145,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "prvalue", @@ -9181,7 +9170,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "const NS::X", // CHECK-NEXT: "qualType": "const X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -9203,7 +9191,6 @@ void TestNonADLCall3() { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: }, // CHECK-NEXT: "valueCategory": "lvalue", @@ -9212,7 +9199,6 @@ void TestNonADLCall3() { // CHECK-NEXT: "kind": "VarDecl", // CHECK-NEXT: "name": "x", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "NS::X", // CHECK-NEXT: "qualType": "X" // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 6fd429d1500a4..7a686b28d80d1 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -219,13 +219,10 @@ void PostfixExpressions(S a, S *p, U *r) { // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} '' .~S 0x{{[^ ]*}} // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'S' lvalue ParmVar 0x{{[^ ]*}} 'a' 'S' - // FIXME: similarly, there is no way to distinguish the construct below from - // the p->~S() case. p->::S::~S(); // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} 'void' // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} '' ->~S 0x{{[^ ]*}} - // CHECK-NEXT: NestedNameSpecifier TypeSpec 'S' - // CHECK-NEXT: NestedNameSpecifier Global + // CHECK-NEXT: NestedNameSpecifier TypeSpec '::S' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'S *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'S *' @@ -597,5 +594,5 @@ struct S { void f() { S(S(0, 1)); } -// CHECK: CXXTemporaryObjectExpr {{.*}} 'S':'GH143711::S' 'void (int, int)' +// CHECK: CXXTemporaryObjectExpr {{.*}} 'S' 'void (int, int)' } diff --git a/clang/test/AST/ast-dump-for-range-lifetime.cpp b/clang/test/AST/ast-dump-for-range-lifetime.cpp index ee046be19ab63..c330342f3328e 100644 --- a/clang/test/AST/ast-dump-for-range-lifetime.cpp +++ b/clang/test/AST/ast-dump-for-range-lifetime.cpp @@ -24,14 +24,14 @@ void test1() { // CHECK-NEXT: | |-<<>> // CHECK-NEXT: | |-DeclStmt {{.*}} // CHECK-NEXT: | | `-VarDecl {{.*}} implicit used __range1 'const A &' cinit - // CHECK-NEXT: | | `-ExprWithCleanups {{.*}} 'const A':'const P2718R0::A' lvalue - // CHECK-NEXT: | | `-CallExpr {{.*}} 'const A':'const P2718R0::A' lvalue + // CHECK-NEXT: | | `-ExprWithCleanups {{.*}} 'const A' lvalue + // CHECK-NEXT: | | `-CallExpr {{.*}} 'const A' lvalue // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const A &(*)(const A &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const A &(const A &)' lvalue Function {{.*}} 'f1' 'const A &(const A &)' - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'const A &' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'const A &' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CallExpr {{.*}} 'A' // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'A (*)()' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'A ()' lvalue Function {{.*}} 'g' 'A ()' for (auto e : f1(g())) @@ -56,11 +56,11 @@ void test2() { // CHECK-NEXT: | | `-CallExpr {{.*}} 'const A *' // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const A *(*)(const A &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const A *(const A &)' lvalue Function {{.*}} 'g' 'const A *(const A &)' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' lvalue - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const B':'const P2718R0::B' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const B':'const P2718R0::B' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'B':'P2718R0::B' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'B':'P2718R0::B' 'void () noexcept(false)' zeroing + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A' lvalue + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const B' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const B' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'B' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'B' 'void () noexcept(false)' zeroing for (auto e : f(g(B()))) bar(e); } @@ -82,9 +82,9 @@ void test3() { // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' // CHECK-NEXT: | |-CXXStaticCastExpr {{.*}} 'void' static_cast - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : static_cast(LockGuard()), v) LockGuard guard; @@ -96,9 +96,9 @@ void test3() { // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : (void)LockGuard(), v) LockGuard guard; @@ -109,9 +109,9 @@ void test3() { // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'int (&)[3]' cinit // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'int[3]' lvalue // CHECK-NEXT: | `-BinaryOperator {{.*}} 'int[3]' lvalue ',' - // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'LockGuard' xvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : LockGuard(), v) LockGuard guard; @@ -130,12 +130,12 @@ void test4() { // CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]' - // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const A':'const P2718R0::A' lvalue has rewritten init - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' - for (auto e : default_arg_fn()) + // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const A' lvalue has rewritten init + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'A' 'void ()' + for (auto e : default_arg_fn()) bar(e); } @@ -158,43 +158,43 @@ void test5() { // CHECK-NEXT: | `-CallExpr {{.*}} 'int[3]' lvalue // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'int (&(*)(const A &))[3]' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'int (&(const A &))[3]' lvalue Function {{.*}} 'default_arg_fn' 'int (&(const A &))[3]' - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' - // CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' + // CHECK-NEXT: | `-CallExpr {{.*}} 'A' // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)' - // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' - // CHECK-NEXT: | | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'A' + // CHECK-NEXT: | | `-CallExpr {{.*}} 'A' // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)' - // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' - // CHECK-NEXT: | | | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'A' + // CHECK-NEXT: | | | `-CallExpr {{.*}} 'A' // CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'A (*)(const A &, const DefaultA &)' // CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'A (const A &, const DefaultA &)' lvalue Function {{.*}} 'foo' 'A (const A &, const DefaultA &)' - // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const A':'const P2718R0::A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' - // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' - // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A':'P2718R0::A' 'void ()' - // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' - // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' - // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' + // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const A' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const A' + // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'A' + // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'A' 'void ()' + // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' + // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' + // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' for (auto e : default_arg_fn(foo(foo(foo(A()))))) bar(e); } @@ -210,40 +210,40 @@ void test6() { // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-DeclStmt {{.*}} // CHECK-NEXT: | `-VarDecl {{.*}} col:17 implicit used __range1 'C &&' cinit - // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'C':'P2718R0::C' xvalue - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'C':'P2718R0::C' xvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C' - // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)' + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'C' xvalue + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'C' xvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'C' + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'C' 'void (int, const C &, const DefaultA &)' // CHECK-NEXT: | |-IntegerLiteral {{.*}}'int' 0 - // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C' - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)' + // CHECK-NEXT: | |-MaterializeTemporaryExpr {{.*}} 'const C' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const C' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'C' + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'C' 'void (int, const C &, const DefaultA &)' // CHECK-NEXT: | | |-IntegerLiteral {{.*}} 'int' 0 - // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' - // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C' - // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void (int, const C &, const DefaultA &)' + // CHECK-NEXT: | | |-MaterializeTemporaryExpr {{.*}} 'const C' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const C' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'C' + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'C' 'void (int, const C &, const DefaultA &)' // CHECK-NEXT: | | | |-IntegerLiteral {{.*}} 'int' 0 - // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const C':'const P2718R0::C' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const C':'const P2718R0::C' - // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'C':'P2718R0::C' - // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C':'P2718R0::C' 'void ()' - // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' - // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' - // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA':'const P2718R0::DefaultA' lvalue has rewritten init - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA':'const P2718R0::DefaultA' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA':'P2718R0::DefaultA' 'void ()' + // CHECK-NEXT: | | | |-MaterializeTemporaryExpr {{.*}} 'const C' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} 'const C' + // CHECK-NEXT: | | | | `-CXXBindTemporaryExpr {{.*}} 'C' + // CHECK-NEXT: | | | | `-CXXTemporaryObjectExpr {{.*}} 'C' 'void ()' + // CHECK-NEXT: | | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' + // CHECK-NEXT: | | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' + // CHECK-NEXT: | `-CXXDefaultArgExpr {{.*}} <> 'const DefaultA' lvalue has rewritten init + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const DefaultA' lvalue extended by Var {{.*}} '__range1' 'C &&' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const DefaultA' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'DefaultA' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'DefaultA' 'void ()' for (auto e : C(0, C(0, C(0, C())))) bar(e); } @@ -255,28 +255,28 @@ void test7() { // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-DeclStmt {{.*}} // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'A &&' cinit - // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'A':'P2718R0::A' xvalue - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'A' xvalue + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CallExpr {{.*}} 'A' // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'A (*)()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'A ()' lvalue Function {{.*}} 'g' 'A ()' for (auto e : g().r().g().r().g().r().g()) @@ -324,11 +324,11 @@ void test9() { // CHECK-NEXT: | `-CallExpr {{.*}} 'const A *' // CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'const A *(*)(const A &)' // CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const A *(const A &)' lvalue Function {{.*}} 'dg2' 'const A *(const A &)' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A':'const P2718R0::A' lvalue - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const B':'const P2718R0::B' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const B':'const P2718R0::B' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'B':'P2718R0::B' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'B':'P2718R0::B' 'void () noexcept(false)' zeroing + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A' lvalue + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const B' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const B' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'B' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXTemporaryObjectExpr {{.*}} 'B' 'void () noexcept(false)' zeroing for (auto e : df2(dg2(B()))) bar(e); } @@ -348,10 +348,10 @@ void test10() { // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : static_cast(df1(LockGuard())), v) LockGuard guard; @@ -366,10 +366,10 @@ void test10() { // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : (void)df1(LockGuard()), v) LockGuard guard; @@ -384,17 +384,17 @@ void test10() { // CHECK-NEXT: | | |-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue // CHECK-NEXT: | | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' // CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') - // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' - // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} 'const LockGuard' + // CHECK-NEXT: | | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | | `-CallExpr {{.*}} 'const P2718R0::LockGuard' lvalue // CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} 'const P2718R0::LockGuard &(*)(const P2718R0::LockGuard &)' // CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' lvalue Function {{.*}} 'df1' 'const P2718R0::LockGuard &(const P2718R0::LockGuard &)' (FunctionTemplate {{.*}} 'df1') - // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' - // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard':'const P2718R0::LockGuard' - // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' (CXXTemporary {{.*}}) - // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard':'P2718R0::LockGuard' 'void ()' + // CHECK-NEXT: | | `-MaterializeTemporaryExpr {{.*}} 'const LockGuard' lvalue extended by Var {{.*}} '__range1' 'int (&)[3]' + // CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} 'const LockGuard' + // CHECK-NEXT: | | `-CXXBindTemporaryExpr {{.*}} 'LockGuard' (CXXTemporary {{.*}}) + // CHECK-NEXT: | | `-CXXTemporaryObjectExpr {{.*}} 'LockGuard' 'void ()' // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[3]' lvalue Var {{.*}} 'v' 'int[3]' for ([[maybe_unused]] int x : df1(LockGuard()), df1(LockGuard()), v) LockGuard guard; @@ -403,7 +403,7 @@ void test10() { // Test default argument && dependent context template int (&default_arg_fn2(const T & = T()))[3]; void test11() { - for (auto e : default_arg_fn2()) + for (auto e : default_arg_fn2()) bar(e); } @@ -422,24 +422,24 @@ void test13() { // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-DeclStmt {{.*}} // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'A &&' cinit - // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'A':'P2718R0::A' xvalue - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'A' xvalue + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A':'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A':'P2718R0::A' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'A' xvalue extended by Var {{.*}} '__range1' 'A &&' + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' // CHECK-NEXT: | `-MemberExpr {{.*}} '' .g {{.*}} - // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A':'P2718R0::A' lvalue + // CHECK-NEXT: | `-CXXMemberCallExpr {{.*}} 'A' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} '' .r {{.*}} // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'P2718R0::A' xvalue extended by Var {{.*}} '__range1' 'A &&' // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'P2718R0::A' (CXXTemporary {{.*}}) @@ -474,17 +474,17 @@ void test14() { // CHECK-NEXT: | `-VarDecl {{.*}} implicit used __range1 'const int (&)[1]' cinit // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'const int[1]' lvalue // CHECK-NEXT: | `-MemberExpr {{.*}} 'const int[1]' lvalue .arr {{.*}} - // CHECK-NEXT: | `-MemberExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue .a {{.*}} - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14':'P2718R0::B14' xvalue extended by Var {{.*}} '__range1' 'const int (&)[1]' - // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14':'P2718R0::B14' functional cast to B14 - // CHECK-NEXT: | `-InitListExpr {{.*}} 'B14':'P2718R0::B14' + // CHECK-NEXT: | `-MemberExpr {{.*}} 'const A14' lvalue .a {{.*}} + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14' xvalue extended by Var {{.*}} '__range1' 'const int (&)[1]' + // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14' functional cast to B14 + // CHECK-NEXT: | `-InitListExpr {{.*}} 'B14' // CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0 - // CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue has rewritten init - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue extended by Var {{.*}} '__range1' 'const int (&)[1]' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14':'const P2718R0::A14' - // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14':'P2718R0::A14' functional cast to A14 - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14':'P2718R0::A14' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-InitListExpr {{.*}} 'A14':'P2718R0::A14' + // CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14' lvalue has rewritten init + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14' lvalue extended by Var {{.*}} '__range1' 'const int (&)[1]' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14' + // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14' functional cast to A14 + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-InitListExpr {{.*}} 'A14' // CHECK-NEXT: | `-InitListExpr {{.*}} 'int[1]' // CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0 for (auto &&x : B14{0}.a.arr) { exit(0); } @@ -493,17 +493,17 @@ void test14() { // CHECK-NEXT: |-<<>> // CHECK-NEXT: |-DeclStmt {{.*}} // CHECK-NEXT: | `-VarDecl {{.*}} col:19 implicit used __range1 'B14 &&' cinit - // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'B14':'P2718R0::B14' xvalue - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14':'P2718R0::B14' xvalue extended by Var {{.*}} '__range1' 'B14 &&' - // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14':'P2718R0::B14' functional cast to B14 - // CHECK-NEXT: | `-InitListExpr {{.*}} 'B14':'P2718R0::B14' + // CHECK-NEXT: | `-ExprWithCleanups {{.*}} 'B14' xvalue + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'B14' xvalue extended by Var {{.*}} '__range1' 'B14 &&' + // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'B14' functional cast to B14 + // CHECK-NEXT: | `-InitListExpr {{.*}} 'B14' // CHECK-NEXT: | |-IntegerLiteral {{.*}} 'int' 0 - // CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue has rewritten init - // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14':'const P2718R0::A14' lvalue extended by Var {{.*}} '__range1' 'B14 &&' - // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14':'const P2718R0::A14' - // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14':'P2718R0::A14' functional cast to A14 - // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14':'P2718R0::A14' (CXXTemporary {{.*}}) - // CHECK-NEXT: | `-InitListExpr {{.*}} 'A14':'P2718R0::A14' + // CHECK-NEXT: | `-CXXDefaultInitExpr {{.*}} 'const A14' lvalue has rewritten init + // CHECK-NEXT: | `-MaterializeTemporaryExpr {{.*}} 'const A14' lvalue extended by Var {{.*}} '__range1' 'B14 &&' + // CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'const A14' + // CHECK-NEXT: | `-CXXFunctionalCastExpr {{.*}} 'A14' functional cast to A14 + // CHECK-NEXT: | `-CXXBindTemporaryExpr {{.*}} 'A14' (CXXTemporary {{.*}}) + // CHECK-NEXT: | `-InitListExpr {{.*}} 'A14' // CHECK-NEXT: | `-InitListExpr {{.*}} 'int[1]' // CHECK-NEXT: | `-IntegerLiteral {{.*}} 'int' 0 for (auto &&x : B14{0}) { exit(0); } diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp b/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp index 1937a5d1c3eb3..9584e77b9e414 100644 --- a/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp @@ -192,12 +192,12 @@ int test(float &&f, short &&s) { // CHECK-NEXT: | | `-CompoundStmt [[ADDR_44:0x[a-z0-9]*]] // CHECK-NEXT: | | |-DeclStmt [[ADDR_45:0x[a-z0-9]*]] // CHECK-NEXT: | | | `-TypedefDecl [[ADDR_46:0x[a-z0-9]*]] col:48 referenced _Up 'typename remove_reference::type':'float' -// CHECK-NEXT: | | | `-ElaboratedType [[ADDR_47:0x[a-z0-9]*]] 'typename remove_reference::type' sugar -// CHECK-NEXT: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'remove_reference::type' sugar -// CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type' -// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar class depth 0 index 0 _Tp -// CHECK-NEXT: | | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference' -// CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float' +// CHECK-NEXT: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'typename remove_reference::type' sugar typename +// CHECK-NEXT: | | | |-NestedNameSpecifier TypeSpec 'remove_reference' +// CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type' +// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference' +// CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float' // CHECK-NEXT: | | `-ReturnStmt [[ADDR_49:0x[a-z0-9]*]] // CHECK-NEXT: | | `-CXXStaticCastExpr [[ADDR_50:0x[a-z0-9]*]] '_Up':'float' xvalue static_cast<_Up &&> // CHECK-NEXT: | | `-DeclRefExpr [[ADDR_51:0x[a-z0-9]*]] 'float' {{.*}}ParmVar [[ADDR_43]] '__t' 'float &' @@ -209,12 +209,12 @@ int test(float &&f, short &&s) { // CHECK-NEXT: | `-CompoundStmt [[ADDR_54:0x[a-z0-9]*]] // CHECK-NEXT: | |-DeclStmt [[ADDR_55:0x[a-z0-9]*]] // CHECK-NEXT: | | `-TypedefDecl [[ADDR_56:0x[a-z0-9]*]] col:48 referenced _Up 'typename remove_reference::type':'short' -// CHECK-NEXT: | | `-ElaboratedType [[ADDR_57:0x[a-z0-9]*]] 'typename remove_reference::type' sugar -// CHECK-NEXT: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'remove_reference::type' sugar -// CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar class depth 0 index 0 _Tp -// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference' -// CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short' +// CHECK-NEXT: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'typename remove_reference::type' sugar typename +// CHECK-NEXT: | | |-NestedNameSpecifier TypeSpec 'remove_reference' +// CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference' +// CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short' // CHECK-NEXT: | `-ReturnStmt [[ADDR_59:0x[a-z0-9]*]] // CHECK-NEXT: | `-CXXStaticCastExpr [[ADDR_60:0x[a-z0-9]*]] '_Up':'short' xvalue static_cast<_Up &&> // CHECK-NEXT: | `-DeclRefExpr [[ADDR_61:0x[a-z0-9]*]] 'short' {{.*}}ParmVar [[ADDR_53]] '__t' 'short &' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp index ad269506042c8..44d1cb462cd58 100644 --- a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_3.cpp @@ -54,7 +54,7 @@ int test() { // CHECK-NEXT: | | | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param // CHECK-NEXT: | | | |-MoveAssignment exists simple trivial needs_implicit // CHECK-NEXT: | | | `-Destructor simple irrelevant trivial {{(constexpr )?}}needs_implicit -// CHECK-NEXT: | | |-CXXRecordDecl [[ADDR_3:0x[a-z0-9]*]] col:30 implicit referenced struct S +// CHECK-NEXT: | | |-CXXRecordDecl [[ADDR_3:0x[a-z0-9]*]] col:30 implicit struct S // CHECK-NEXT: | | `-CXXConstructorDecl [[ADDR_4:0x[a-z0-9]*]] col:3 S 'void (int, T *)' // CHECK-NEXT: | | |-ParmVarDecl [[ADDR_5:0x[a-z0-9]*]] col:8 'int' // CHECK-NEXT: | | |-ParmVarDecl [[ADDR_6:0x[a-z0-9]*]] col:13 'T *' diff --git a/clang/test/AST/ast-dump-record-definition-data-json.cpp b/clang/test/AST/ast-dump-record-definition-data-json.cpp index c119089def716..e35bec78c6847 100644 --- a/clang/test/AST/ast-dump-record-definition-data-json.cpp +++ b/clang/test/AST/ast-dump-record-definition-data-json.cpp @@ -2516,7 +2516,6 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isReferenced": true, // CHECK-NEXT: "name": "IsTrivial", // CHECK-NEXT: "tagUsed": "struct" // CHECK-NEXT: }, @@ -2646,7 +2645,6 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isReferenced": true, // CHECK-NEXT: "name": "IsNotTrivial", // CHECK-NEXT: "tagUsed": "struct" // CHECK-NEXT: }, @@ -3980,7 +3978,6 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isReferenced": true, // CHECK-NEXT: "name": "HasUserDeclaredConstructor", // CHECK-NEXT: "tagUsed": "struct" // CHECK-NEXT: }, @@ -4234,7 +4231,6 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isReferenced": true, // CHECK-NEXT: "name": "HasConstexprNonCopyMoveConstructor", // CHECK-NEXT: "tagUsed": "struct" // CHECK-NEXT: }, @@ -4381,7 +4377,6 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isReferenced": true, // CHECK-NEXT: "name": "HasNoConstexprNonCopyMoveConstructor", // CHECK-NEXT: "tagUsed": "struct" // CHECK-NEXT: }, diff --git a/clang/test/AST/ast-dump-records-json.cpp b/clang/test/AST/ast-dump-records-json.cpp index 7efdcb0b61318..941c6a675448a 100644 --- a/clang/test/AST/ast-dump-records-json.cpp +++ b/clang/test/AST/ast-dump-records-json.cpp @@ -795,7 +795,6 @@ struct Derived6 : virtual public Bases... { // CHECK-NEXT: }, // CHECK-NEXT: "name": "b", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "C::(unnamed struct at {{.*}}:16:3)", // CHECK-NEXT: "qualType": "struct (unnamed struct at {{.*}}:16:3)" // CHECK-NEXT: } // CHECK-NEXT: }, @@ -2072,7 +2071,6 @@ struct Derived6 : virtual public Bases... { // CHECK-NEXT: }, // CHECK-NEXT: "name": "b", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "G::(unnamed struct at {{.*}}:50:3)", // CHECK-NEXT: "qualType": "struct (unnamed struct at {{.*}}:50:3)" // CHECK-NEXT: } // CHECK-NEXT: }, diff --git a/clang/test/AST/ast-dump-records.c b/clang/test/AST/ast-dump-records.c index f4a540f3fa872..1dc175c4a8560 100644 --- a/clang/test/AST/ast-dump-records.c +++ b/clang/test/AST/ast-dump-records.c @@ -47,7 +47,7 @@ struct C { int a; // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:9 a 'int' } b; - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-5]]:3)':'struct C::(unnamed at {{.*}}:[[@LINE-5]]:3)' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-5]]:3)' union { // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:3 union definition @@ -122,15 +122,13 @@ union E { }; union G { - // CHECK: RecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:7 union G definition + // CHECK: RecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:7 union G definition struct { // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:3 struct definition int a; // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:9 a 'int' } b; - // FIXME: note that it talks about 'struct G' below; the same happens in - // other cases with union G as well. - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-7]]:3)':'struct G::(unnamed at {{.*}}:[[@LINE-7]]:3)' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-5]]:3)' union { // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:3 union definition diff --git a/clang/test/AST/ast-dump-records.cpp b/clang/test/AST/ast-dump-records.cpp index e9b37b73002dd..edd13ba1c6f12 100644 --- a/clang/test/AST/ast-dump-records.cpp +++ b/clang/test/AST/ast-dump-records.cpp @@ -72,7 +72,7 @@ struct C { int a; // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:9 a 'int' } b; - // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-12]]:3)':'C::(unnamed struct at {{.*}}:[[@LINE-12]]:3)' + // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-12]]:3)' union { // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:3 union definition @@ -179,7 +179,7 @@ union E { }; union G { - // CHECK: CXXRecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:7 union G definition + // CHECK: CXXRecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:7 union G definition // CHECK-NEXT: DefinitionData pass_in_registers aggregate standard_layout trivially_copyable pod trivial literal // CHECK-NEXT: DefaultConstructor exists trivial needs_implicit // CHECK-NEXT: CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param @@ -202,9 +202,7 @@ union G { int a; // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} col:9 a 'int' } b; - // FIXME: note that it talks about 'struct G' below; the same happens in - // other cases with union G as well. - // CHECK: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-15]]:3)':'G::(unnamed struct at {{.*}}:[[@LINE-15]]:3)' + // CHECK: FieldDecl 0x{{[^ ]*}} col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-13]]:3)' union { // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} line:[[@LINE-1]]:3 union definition diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp index a8e30f1759e9f..060ae3b62b6f8 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -128,7 +128,7 @@ void test2(Foo2 f) { // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f' // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 f.func(1); - // CHECK: RecoveryExpr {{.*}} 'ForwardClass':'Foo2::ForwardClass' + // CHECK: RecoveryExpr {{.*}} 'ForwardClass' // CHECK-NEXT: `-MemberExpr {{.*}} '' .createFwd // CHECK-NEXT: `-DeclRefExpr {{.*}} 'f' f.createFwd(); @@ -292,8 +292,8 @@ union U { // CHECK: FunctionDecl {{.*}} foo 'void ()' // CHECK-NEXT: `-CompoundStmt {{.*}} // CHECK-NEXT: `-DeclStmt {{.*}} -// CHECK-NEXT: `-VarDecl {{.*}} g 'U':'GH112560::U' listinit -// CHECK-NEXT: `-InitListExpr {{.*}} 'U':'GH112560::U' contains-errors field Field {{.*}} 'f' 'int' +// CHECK-NEXT: `-VarDecl {{.*}} g 'U' listinit +// CHECK-NEXT: `-InitListExpr {{.*}} 'U' contains-errors field Field {{.*}} 'f' 'int' // CHECK-NEXT: `-CXXDefaultInitExpr {{.*}} 'int' contains-errors has rewritten init // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors diff --git a/clang/test/AST/ast-dump-stmt-json.cpp b/clang/test/AST/ast-dump-stmt-json.cpp index a8f113ce6a3d4..ee99ab832c89f 100644 --- a/clang/test/AST/ast-dump-stmt-json.cpp +++ b/clang/test/AST/ast-dump-stmt-json.cpp @@ -224,7 +224,55 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "void ()" // CHECK-NEXT: } -// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 125, +// CHECK-NEXT: "line": 4, +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 120, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 137, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "function", +// CHECK-NEXT: "mangledName": "_ZN1n8functionEv", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void ()" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CompoundStmt", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 136, +// CHECK-NEXT: "col": 17, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 137, +// CHECK-NEXT: "col": 18, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } @@ -279,7 +327,37 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "int" // CHECK-NEXT: } -// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VarDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 143, +// CHECK-NEXT: "line": 5, +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 139, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 3 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 143, +// CHECK-NEXT: "col": 5, +// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "Variable", +// CHECK-NEXT: "mangledName": "_ZN1n8VariableE", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } @@ -1869,6 +1947,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: ] // CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": {}, @@ -1936,6 +2015,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: ] // CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": {}, @@ -2086,6 +2166,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: ] // CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": {}, @@ -2153,6 +2234,7 @@ void TestDependentGenericSelectionExpr(Ty T) { // CHECK-NEXT: ] // CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionTemplateDecl", // CHECK-NEXT: "loc": { diff --git a/clang/test/AST/ast-dump-stmt.m b/clang/test/AST/ast-dump-stmt.m index e0fc16b3fa825..b68f5b6bd1d3f 100644 --- a/clang/test/AST/ast-dump-stmt.m +++ b/clang/test/AST/ast-dump-stmt.m @@ -55,4 +55,4 @@ id TestCompoundLiteral(id a) { // CHECK: FunctionDecl{{.*}}TestCompoundLiteral // CHECK: ExprWithCleanups // CHECK-NEXT: cleanup CompoundLiteralExpr -// CHECK: CompoundLiteralExpr{{.*}}'S' lvalue + // CHECK: CompoundLiteralExpr{{.*}}'S':'struct S' lvalue diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index d5228d4667304..ba3e405eb18aa 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -115,8 +115,7 @@ template struct C { }; using type2 = typename C::type1; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 type2 'typename C::type1':'void (int)' -// CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C::type1' sugar -// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias +// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'typename C::type1' sugar alias // CHECK-NEXT: name: 'C::type1':'PR55886::C::type1' qualified // CHECK-NEXT: NestedNameSpecifier TypeSpec 'C':'PR55886::C' // CHECK-NEXT: TypeAliasTemplateDecl {{.+}} type1 diff --git a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp index cc9a82cb7bfff..3e0877f131e94 100644 --- a/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp +++ b/clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp @@ -537,28 +537,17 @@ int main() // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "ElaboratedType", +// CHECK-NEXT: "kind": "InjectedClassNameType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "integral_constant<_Ty, _Val>" // CHECK-NEXT: }, // CHECK-NEXT: "isDependent": true, // CHECK-NEXT: "isInstantiationDependent": true, -// CHECK-NEXT: "inner": [ -// CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "InjectedClassNameType", -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "integral_constant<_Ty, _Val>" -// CHECK-NEXT: }, -// CHECK-NEXT: "isDependent": true, -// CHECK-NEXT: "isInstantiationDependent": true, -// CHECK-NEXT: "decl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CXXRecordDecl", -// CHECK-NEXT: "name": "integral_constant" -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: ] +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "integral_constant" +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: }, @@ -885,71 +874,60 @@ int main() // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "ElaboratedType", +// CHECK-NEXT: "kind": "TemplateSpecializationType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "integral_constant" // CHECK-NEXT: }, // CHECK-NEXT: "isDependent": true, // CHECK-NEXT: "isInstantiationDependent": true, +// CHECK-NEXT: "templateName": "integral_constant", // CHECK-NEXT: "inner": [ // CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "TemplateSpecializationType", +// CHECK-NEXT: "kind": "TemplateArgument", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "integral_constant" +// CHECK-NEXT: "qualType": "bool" // CHECK-NEXT: }, -// CHECK-NEXT: "isDependent": true, -// CHECK-NEXT: "isInstantiationDependent": true, -// CHECK-NEXT: "templateName": "integral_constant", // CHECK-NEXT: "inner": [ // CHECK-NEXT: { -// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "bool" -// CHECK-NEXT: }, -// CHECK-NEXT: "inner": [ -// CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "BuiltinType", -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "bool" -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: ] -// CHECK-NEXT: }, +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "kind": "TemplateArgument", +// CHECK-NEXT: "isExpr": true, +// CHECK-NEXT: "inner": [ // CHECK-NEXT: { -// CHECK-NEXT: "kind": "TemplateArgument", -// CHECK-NEXT: "isExpr": true, -// CHECK-NEXT: "inner": [ -// CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "DeclRefExpr", -// CHECK-NEXT: "range": { -// CHECK-NEXT: "begin": { -// CHECK-NEXT: "offset": 554, -// CHECK-NEXT: "col": 47, -// CHECK-NEXT: "tokLen": 4 -// CHECK-NEXT: }, -// CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": 554, -// CHECK-NEXT: "col": 47, -// CHECK-NEXT: "tokLen": 4 -// CHECK-NEXT: } -// CHECK-NEXT: }, -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "bool" -// CHECK-NEXT: }, -// CHECK-NEXT: "valueCategory": "prvalue", -// CHECK-NEXT: "referencedDecl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "NonTypeTemplateParmDecl", -// CHECK-NEXT: "name": "_Val", -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "bool" -// CHECK-NEXT: } -// CHECK-NEXT: } +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "DeclRefExpr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 554, +// CHECK-NEXT: "col": 47, +// CHECK-NEXT: "tokLen": 4 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 554, +// CHECK-NEXT: "col": 47, +// CHECK-NEXT: "tokLen": 4 // CHECK-NEXT: } -// CHECK-NEXT: ] +// CHECK-NEXT: }, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: }, +// CHECK-NEXT: "valueCategory": "prvalue", +// CHECK-NEXT: "referencedDecl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "NonTypeTemplateParmDecl", +// CHECK-NEXT: "name": "_Val", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "bool" +// CHECK-NEXT: } +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-template-name.cpp b/clang/test/AST/ast-dump-template-name.cpp index acacdac857954..7f085086ab6a3 100644 --- a/clang/test/AST/ast-dump-template-name.cpp +++ b/clang/test/AST/ast-dump-template-name.cpp @@ -11,13 +11,12 @@ namespace qualified { // CHECK: Dumping qualified::TestQualified: // CHECK-NEXT: TypeAliasDecl -// CHECK-NEXT: `-ElaboratedType -// CHECK-NEXT: `-TemplateSpecializationType -// CHECK-NEXT: |-name: 'N' qualified -// CHECK-NEXT: | `-TypeAliasTemplateDecl {{.+}} N{{$}} -// CHECK-NEXT: |-TemplateArgument template 'foo::A':'qualified::foo::A' qualified{{$}} -// CHECK-NEXT: | |-NestedNameSpecifier Namespace 0x{{.+}} 'foo'{{$}} -// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}} +// CHECK-NEXT: `-TemplateSpecializationType +// CHECK-NEXT: |-name: 'N' qualified +// CHECK-NEXT: | `-TypeAliasTemplateDecl {{.+}} N{{$}} +// CHECK-NEXT: |-TemplateArgument template 'foo::A':'qualified::foo::A' qualified{{$}} +// CHECK-NEXT: | |-NestedNameSpecifier Namespace 0x{{.+}} 'foo'{{$}} +// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}} namespace dependent { template struct B { @@ -27,12 +26,11 @@ namespace dependent { // CHECK: Dumping dependent::B::TestDependent: // CHECK-NEXT: TypeAliasDecl -// CHECK-NEXT: `-ElaboratedType -// CHECK-NEXT: `-TemplateSpecializationType -// CHECK-NEXT: |-name: 'N' qualified -// CHECK-NEXT: | `-TypeAliasTemplateDecl -// CHECK-NEXT: |-TemplateArgument template 'T::template X':'type-parameter-0-0::template X' dependent{{$}} -// CHECK-NEXT: | `-NestedNameSpecifier TypeSpec 'T'{{$}} +// CHECK-NEXT: `-TemplateSpecializationType +// CHECK-NEXT: |-name: 'N' qualified +// CHECK-NEXT: | `-TypeAliasTemplateDecl +// CHECK-NEXT: |-TemplateArgument template 'T::template X':'type-parameter-0-0::template X' dependent{{$}} +// CHECK-NEXT: | `-NestedNameSpecifier TypeSpec 'T'{{$}} namespace subst { template struct A; @@ -46,15 +44,14 @@ namespace subst { // CHECK: Dumping subst::TestSubst: // CHECK-NEXT: TypeAliasDecl -// CHECK-NEXT: `-ElaboratedType -// CHECK-NEXT: `-TypedefType -// CHECK-NEXT: |-TypeAlias -// CHECK-NEXT: `-ElaboratedType -// CHECK-NEXT: `-TemplateSpecializationType -// CHECK-NEXT: |-name: 'C':'subst::B::C' qualified -// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} C -// CHECK-NEXT: |-TemplateArgument template 'subst::A' subst index 0 -// CHECK-NEXT: | |-parameter: TemplateTemplateParmDecl {{.+}} depth 0 index 0 TT{{$}} -// CHECK-NEXT: | |-associated ClassTemplateSpecialization {{.+}} 'B'{{$}} -// CHECK-NEXT: | `-replacement: -// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}} +// CHECK-NEXT: `-TypedefType +// CHECK-NEXT: |-NestedNameSpecifier TypeSpec 'B':'subst::B' +// CHECK-NEXT: |-TypeAlias +// CHECK-NEXT: `-TemplateSpecializationType +// CHECK-NEXT: |-name: 'C':'subst::B::C' qualified +// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} C +// CHECK-NEXT: |-TemplateArgument template 'subst::A' subst index 0 +// CHECK-NEXT: | |-parameter: TemplateTemplateParmDecl {{.+}} depth 0 index 0 TT{{$}} +// CHECK-NEXT: | |-associated ClassTemplateSpecialization {{.+}} 'B'{{$}} +// CHECK-NEXT: | `-replacement: +// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A{{$}} diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp index b504accb927dc..b42aa6220e9fc 100644 --- a/clang/test/AST/ast-dump-templates.cpp +++ b/clang/test/AST/ast-dump-templates.cpp @@ -171,10 +171,11 @@ namespace TestDependentMemberPointer { // DUMP-NEXT: | `-BuiltinType {{.+}} 'int' // DUMP-NEXT: |-TypeAliasDecl {{.+}} Y 'int U::test::*'{{$}} // DUMP-NEXT: | `-MemberPointerType {{.+}} 'int U::test::*' dependent +// DUMP-NEXT: | |-DependentNameType {{.+}} 'U::test' dependent // DUMP-NEXT: | `-BuiltinType {{.+}} 'int' // DUMP-NEXT: `-TypeAliasDecl {{.+}} Z 'int U::template V::*'{{$}} // DUMP-NEXT: `-MemberPointerType {{.+}} 'int U::template V::*' dependent -// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'template V' dependent +// DUMP-NEXT: |-DependentTemplateSpecializationType {{.+}} 'U::template V' dependent // DUMP-NEXT: `-BuiltinType {{.+}} 'int' } // namespace TestDependentMemberPointer @@ -186,14 +187,14 @@ namespace TestPartialSpecNTTP { template struct Template2, U3> {}; // DUMP: ClassTemplatePartialSpecializationDecl {{.+}} struct Template2 -// DUMP: |-TemplateArgument type 'Template1' -// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'Template1' dependent +// DUMP: |-TemplateArgument type 'TestPartialSpecNTTP::Template1' +// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'TestPartialSpecNTTP::Template1' dependent // DUMP-NEXT: | |-name: 'TestPartialSpecNTTP::Template1' // DUMP-NEXT: | | `-ClassTemplateDecl {{.+}} Template1 // DUMP-NEXT: | |-TemplateArgument type 'type-parameter-0-0' // DUMP-NEXT: | | `-TemplateTypeParmType {{.+}} 'type-parameter-0-0' dependent depth 0 index 0 // DUMP-NEXT: | `-TemplateArgument expr canonical 'value-parameter-0-1' -// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'TA2' 'bool' +// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U2' 'bool' // DUMP-NEXT: |-TemplateArgument expr canonical 'value-parameter-0-2' // DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U3' 'bool' // DUMP-NEXT: |-TemplateTypeParmDecl {{.+}} referenced class depth 0 index 0 U1 @@ -204,8 +205,8 @@ namespace TestPartialSpecNTTP { template struct Template2, U3> {}; // DUMP: ClassTemplatePartialSpecializationDecl {{.+}} struct Template2 definition explicit_specialization -// DUMP: |-TemplateArgument type 'Template1' -// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'Template1' dependent +// DUMP: |-TemplateArgument type 'TestPartialSpecNTTP::Template1' +// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'TestPartialSpecNTTP::Template1' dependent // DUMP-NEXT: | |-name: 'TestPartialSpecNTTP::Template1' // DUMP-NEXT: | | `-ClassTemplateDecl {{.+}} Template1 // DUMP-NEXT: | |-TemplateArgument type 'type-parameter-0-0' @@ -621,7 +622,6 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: } // JSON-NEXT: }, // JSON-NEXT: "isImplicit": true, -// JSON-NEXT: "isReferenced": true, // JSON-NEXT: "name": "foo", // JSON-NEXT: "tagUsed": "struct" // JSON-NEXT: }, @@ -4109,7 +4109,7 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "isImplicit": true, // JSON-NEXT: "name": "", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "auto () -> A" +// JSON-NEXT: "qualType": "auto () -> test3::A" // JSON-NEXT: } // JSON-NEXT: } // JSON-NEXT: ] @@ -4185,7 +4185,7 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "isImplicit": true, // JSON-NEXT: "name": "", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "auto (A) -> A" +// JSON-NEXT: "qualType": "auto (test3::A) -> test3::A" // JSON-NEXT: }, // JSON-NEXT: "inner": [ // JSON-NEXT: { @@ -4209,7 +4209,7 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: } // JSON-NEXT: }, // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "A" +// JSON-NEXT: "qualType": "test3::A" // JSON-NEXT: } // JSON-NEXT: } // JSON-NEXT: ] @@ -6630,8 +6630,8 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6356, -// JSON-NEXT: "line": 179, +// JSON-NEXT: "offset": 6425, +// JSON-NEXT: "line": 180, // JSON-NEXT: "col": 1, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -6889,6 +6889,15 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "inner": [ // JSON-NEXT: { // JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "DependentNameType", +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "U::test" +// JSON-NEXT: }, +// JSON-NEXT: "isDependent": true, +// JSON-NEXT: "isInstantiationDependent": true +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "BuiltinType", // JSON-NEXT: "type": { // JSON-NEXT: "qualType": "int" @@ -6938,7 +6947,7 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "DependentTemplateSpecializationType", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "template V" +// JSON-NEXT: "qualType": "U::template V" // JSON-NEXT: }, // JSON-NEXT: "isDependent": true, // JSON-NEXT: "isInstantiationDependent": true @@ -6964,20 +6973,20 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NamespaceDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6409, -// JSON-NEXT: "line": 181, +// JSON-NEXT: "offset": 6478, +// JSON-NEXT: "line": 182, // JSON-NEXT: "col": 11, // JSON-NEXT: "tokLen": 19 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6399, +// JSON-NEXT: "offset": 6468, // JSON-NEXT: "col": 1, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 9184, -// JSON-NEXT: "line": 221, +// JSON-NEXT: "offset": 9336, +// JSON-NEXT: "line": 222, // JSON-NEXT: "col": 1, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -6988,19 +6997,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "ClassTemplateDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6532, -// JSON-NEXT: "line": 183, +// JSON-NEXT: "offset": 6601, +// JSON-NEXT: "line": 184, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6494, +// JSON-NEXT: "offset": 6563, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 8 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6543, +// JSON-NEXT: "offset": 6612, // JSON-NEXT: "col": 52, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7011,18 +7020,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateTypeParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6510, +// JSON-NEXT: "offset": 6579, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6504, +// JSON-NEXT: "offset": 6573, // JSON-NEXT: "col": 13, // JSON-NEXT: "tokLen": 5 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6510, +// JSON-NEXT: "offset": 6579, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: } @@ -7036,18 +7045,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6520, +// JSON-NEXT: "offset": 6589, // JSON-NEXT: "col": 29, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6515, +// JSON-NEXT: "offset": 6584, // JSON-NEXT: "col": 24, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6520, +// JSON-NEXT: "offset": 6589, // JSON-NEXT: "col": 29, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: } @@ -7063,18 +7072,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6532, +// JSON-NEXT: "offset": 6601, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6525, +// JSON-NEXT: "offset": 6594, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6543, +// JSON-NEXT: "offset": 6612, // JSON-NEXT: "col": 52, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7137,18 +7146,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6532, +// JSON-NEXT: "offset": 6601, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6525, +// JSON-NEXT: "offset": 6594, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6532, +// JSON-NEXT: "offset": 6601, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: } @@ -7165,19 +7174,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "ClassTemplateDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6586, -// JSON-NEXT: "line": 184, +// JSON-NEXT: "offset": 6655, +// JSON-NEXT: "line": 185, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6548, +// JSON-NEXT: "offset": 6617, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 8 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6597, +// JSON-NEXT: "offset": 6666, // JSON-NEXT: "col": 52, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7188,18 +7197,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateTypeParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6564, +// JSON-NEXT: "offset": 6633, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6558, +// JSON-NEXT: "offset": 6627, // JSON-NEXT: "col": 13, // JSON-NEXT: "tokLen": 5 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6564, +// JSON-NEXT: "offset": 6633, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: } @@ -7213,18 +7222,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6574, +// JSON-NEXT: "offset": 6643, // JSON-NEXT: "col": 29, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6569, +// JSON-NEXT: "offset": 6638, // JSON-NEXT: "col": 24, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6574, +// JSON-NEXT: "offset": 6643, // JSON-NEXT: "col": 29, // JSON-NEXT: "tokLen": 3 // JSON-NEXT: } @@ -7240,18 +7249,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6586, +// JSON-NEXT: "offset": 6655, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6579, +// JSON-NEXT: "offset": 6648, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6597, +// JSON-NEXT: "offset": 6666, // JSON-NEXT: "col": 52, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7314,18 +7323,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6586, +// JSON-NEXT: "offset": 6655, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6579, +// JSON-NEXT: "offset": 6648, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6586, +// JSON-NEXT: "offset": 6655, // JSON-NEXT: "col": 41, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: } @@ -7342,21 +7351,21 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "ClassTemplatePartialSpecializationDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6650, -// JSON-NEXT: "line": 187, +// JSON-NEXT: "offset": 6719, +// JSON-NEXT: "line": 188, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6603, -// JSON-NEXT: "line": 186, +// JSON-NEXT: "offset": 6672, +// JSON-NEXT: "line": 187, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 8 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6684, -// JSON-NEXT: "line": 187, +// JSON-NEXT: "offset": 6753, +// JSON-NEXT: "line": 188, // JSON-NEXT: "col": 44, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7418,14 +7427,14 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: { // JSON-NEXT: "kind": "TemplateArgument", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "Template1" +// JSON-NEXT: "qualType": "TestPartialSpecNTTP::Template1" // JSON-NEXT: }, // JSON-NEXT: "inner": [ // JSON-NEXT: { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateSpecializationType", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "Template1" +// JSON-NEXT: "qualType": "TestPartialSpecNTTP::Template1" // JSON-NEXT: }, // JSON-NEXT: "isDependent": true, // JSON-NEXT: "isInstantiationDependent": true, @@ -7463,15 +7472,14 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "kind": "DeclRefExpr", // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6520, -// JSON-NEXT: "line": 183, -// JSON-NEXT: "col": 29, -// JSON-NEXT: "tokLen": 3 +// JSON-NEXT: "offset": 6743, +// JSON-NEXT: "col": 34, +// JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6520, -// JSON-NEXT: "col": 29, -// JSON-NEXT: "tokLen": 3 +// JSON-NEXT: "offset": 6743, +// JSON-NEXT: "col": 34, +// JSON-NEXT: "tokLen": 2 // JSON-NEXT: } // JSON-NEXT: }, // JSON-NEXT: "type": { @@ -7481,7 +7489,7 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "referencedDecl": { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", -// JSON-NEXT: "name": "TA2", +// JSON-NEXT: "name": "U2", // JSON-NEXT: "type": { // JSON-NEXT: "qualType": "bool" // JSON-NEXT: } @@ -7503,13 +7511,12 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "kind": "DeclRefExpr", // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6679, -// JSON-NEXT: "line": 187, +// JSON-NEXT: "offset": 6748, // JSON-NEXT: "col": 39, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6679, +// JSON-NEXT: "offset": 6748, // JSON-NEXT: "col": 39, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7533,19 +7540,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateTypeParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6619, -// JSON-NEXT: "line": 186, +// JSON-NEXT: "offset": 6688, +// JSON-NEXT: "line": 187, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6613, +// JSON-NEXT: "offset": 6682, // JSON-NEXT: "col": 13, // JSON-NEXT: "tokLen": 5 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6619, +// JSON-NEXT: "offset": 6688, // JSON-NEXT: "col": 19, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7560,18 +7567,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6628, +// JSON-NEXT: "offset": 6697, // JSON-NEXT: "col": 28, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6623, +// JSON-NEXT: "offset": 6692, // JSON-NEXT: "col": 23, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6628, +// JSON-NEXT: "offset": 6697, // JSON-NEXT: "col": 28, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7588,18 +7595,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6637, +// JSON-NEXT: "offset": 6706, // JSON-NEXT: "col": 37, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6632, +// JSON-NEXT: "offset": 6701, // JSON-NEXT: "col": 32, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6637, +// JSON-NEXT: "offset": 6706, // JSON-NEXT: "col": 37, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7616,19 +7623,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 6650, -// JSON-NEXT: "line": 187, +// JSON-NEXT: "offset": 6719, +// JSON-NEXT: "line": 188, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 6643, +// JSON-NEXT: "offset": 6712, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 6650, +// JSON-NEXT: "offset": 6719, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: } @@ -7643,21 +7650,21 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "ClassTemplatePartialSpecializationDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 7925, -// JSON-NEXT: "line": 205, +// JSON-NEXT: "offset": 8035, +// JSON-NEXT: "line": 206, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7875, -// JSON-NEXT: "line": 204, +// JSON-NEXT: "offset": 7985, +// JSON-NEXT: "line": 205, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 8 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7959, -// JSON-NEXT: "line": 205, +// JSON-NEXT: "offset": 8069, +// JSON-NEXT: "line": 206, // JSON-NEXT: "col": 44, // JSON-NEXT: "tokLen": 1 // JSON-NEXT: } @@ -7719,14 +7726,14 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: { // JSON-NEXT: "kind": "TemplateArgument", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "Template1" +// JSON-NEXT: "qualType": "TestPartialSpecNTTP::Template1" // JSON-NEXT: }, // JSON-NEXT: "inner": [ // JSON-NEXT: { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateSpecializationType", // JSON-NEXT: "type": { -// JSON-NEXT: "qualType": "Template1" +// JSON-NEXT: "qualType": "TestPartialSpecNTTP::Template1" // JSON-NEXT: }, // JSON-NEXT: "isDependent": true, // JSON-NEXT: "isInstantiationDependent": true, @@ -7764,12 +7771,12 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "kind": "DeclRefExpr", // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7949, +// JSON-NEXT: "offset": 8059, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7949, +// JSON-NEXT: "offset": 8059, // JSON-NEXT: "col": 34, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7803,12 +7810,12 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "kind": "DeclRefExpr", // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7954, +// JSON-NEXT: "offset": 8064, // JSON-NEXT: "col": 39, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7954, +// JSON-NEXT: "offset": 8064, // JSON-NEXT: "col": 39, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7832,19 +7839,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "TemplateTypeParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 7894, -// JSON-NEXT: "line": 204, +// JSON-NEXT: "offset": 8004, +// JSON-NEXT: "line": 205, // JSON-NEXT: "col": 22, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7885, +// JSON-NEXT: "offset": 7995, // JSON-NEXT: "col": 13, // JSON-NEXT: "tokLen": 8 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7894, +// JSON-NEXT: "offset": 8004, // JSON-NEXT: "col": 22, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7859,18 +7866,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 7903, +// JSON-NEXT: "offset": 8013, // JSON-NEXT: "col": 31, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7898, +// JSON-NEXT: "offset": 8008, // JSON-NEXT: "col": 26, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7903, +// JSON-NEXT: "offset": 8013, // JSON-NEXT: "col": 31, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7887,18 +7894,18 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "NonTypeTemplateParmDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 7912, +// JSON-NEXT: "offset": 8022, // JSON-NEXT: "col": 40, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7907, +// JSON-NEXT: "offset": 8017, // JSON-NEXT: "col": 35, // JSON-NEXT: "tokLen": 4 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7912, +// JSON-NEXT: "offset": 8022, // JSON-NEXT: "col": 40, // JSON-NEXT: "tokLen": 2 // JSON-NEXT: } @@ -7915,19 +7922,19 @@ namespace TestPartialSpecNTTP { // JSON-NEXT: "id": "0x{{.*}}", // JSON-NEXT: "kind": "CXXRecordDecl", // JSON-NEXT: "loc": { -// JSON-NEXT: "offset": 7925, -// JSON-NEXT: "line": 205, +// JSON-NEXT: "offset": 8035, +// JSON-NEXT: "line": 206, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: }, // JSON-NEXT: "range": { // JSON-NEXT: "begin": { -// JSON-NEXT: "offset": 7918, +// JSON-NEXT: "offset": 8028, // JSON-NEXT: "col": 3, // JSON-NEXT: "tokLen": 6 // JSON-NEXT: }, // JSON-NEXT: "end": { -// JSON-NEXT: "offset": 7925, +// JSON-NEXT: "offset": 8035, // JSON-NEXT: "col": 10, // JSON-NEXT: "tokLen": 9 // JSON-NEXT: } diff --git a/clang/test/AST/ast-dump-traits.cpp b/clang/test/AST/ast-dump-traits.cpp index 72d2a2ae8603e..b844fd6bcc49c 100644 --- a/clang/test/AST/ast-dump-traits.cpp +++ b/clang/test/AST/ast-dump-traits.cpp @@ -40,9 +40,8 @@ void test_unary_expr_or_type_trait() { // CHECK-NEXT: | | `-EnumDecl {{.*}} col:8{{( imported)?}} referenced E // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_enum -// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'E' sugar -// CHECK-NEXT: | | `-EnumType {{.*}} 'E' -// CHECK-NEXT: | | `-Enum {{.*}} 'E' +// CHECK-NEXT: | | `-EnumType {{.*}} 'E' +// CHECK-NEXT: | | `-Enum {{.*}} 'E' // CHECK-NEXT: | |-CStyleCastExpr {{.*}} 'void' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_same // CHECK-NEXT: | | |-BuiltinType {{.*}} 'int' diff --git a/clang/test/AST/ast-dump-types-json.cpp b/clang/test/AST/ast-dump-types-json.cpp index cc4d4d9a64872..aac602780e8c0 100644 --- a/clang/test/AST/ast-dump-types-json.cpp +++ b/clang/test/AST/ast-dump-types-json.cpp @@ -51,30 +51,20 @@ using ::TestUsingShadowDeclType; // CHECK-NEXT: }, // CHECK-NEXT: "name": "TestElaboratedType1", // CHECK-NEXT: "type": { -// CHECK-NEXT: "desugaredQualType": "T", // CHECK-NEXT: "qualType": "struct T" // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "ElaboratedType", +// CHECK-NEXT: "kind": "RecordType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "struct T" // CHECK-NEXT: }, -// CHECK-NEXT: "inner": [ -// CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "RecordType", -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "T" -// CHECK-NEXT: }, -// CHECK-NEXT: "decl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CXXRecordDecl", -// CHECK-NEXT: "name": "T" -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: ] +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "T" +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } @@ -108,25 +98,16 @@ using ::TestUsingShadowDeclType; // CHECK-NEXT: "inner": [ // CHECK-NEXT: { // CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "ElaboratedType", +// CHECK-NEXT: "kind": "RecordType", // CHECK-NEXT: "type": { // CHECK-NEXT: "qualType": "NS::S" // CHECK-NEXT: }, // CHECK-NEXT: "qualifier": "NS::", -// CHECK-NEXT: "inner": [ -// CHECK-NEXT: { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "RecordType", -// CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "NS::S" -// CHECK-NEXT: }, -// CHECK-NEXT: "decl": { -// CHECK-NEXT: "id": "0x{{.*}}", -// CHECK-NEXT: "kind": "CXXRecordDecl", -// CHECK-NEXT: "name": "S" -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: ] +// CHECK-NEXT: "decl": { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "CXXRecordDecl", +// CHECK-NEXT: "name": "S" +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } @@ -538,7 +519,39 @@ using ::TestUsingShadowDeclType; // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ // CHECK-NEXT: { -// CHECK-NEXT: "id": "0x0" +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "TypedefDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "offset": 506, +// CHECK-NEXT: "line": 23, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 23 +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 494, +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "tokLen": 7 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "offset": 506, +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "tokLen": 23 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "TestUsingShadowDeclType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "BuiltinType", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "int" +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: ] // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK-NEXT: } diff --git a/clang/test/AST/ast-dump-using-template.cpp b/clang/test/AST/ast-dump-using-template.cpp index 2c9584966e843..a5a0e4d07d683 100644 --- a/clang/test/AST/ast-dump-using-template.cpp +++ b/clang/test/AST/ast-dump-using-template.cpp @@ -19,40 +19,36 @@ using ns::S2; template using A = S; // CHECK: TypeAliasDecl -// CHECK-NEXT: `-ElaboratedType {{.*}} 'S' sugar dependent -// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S' dependent -// CHECK-NEXT: |-name: 'S':'ns::S' qualified -// CHECK-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S' +// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S' dependent +// CHECK-NEXT: |-name: 'S':'ns::S' qualified +// CHECk-NEXT: | |-UsingShadowDecl {{.+}} ClassTemplate {{.+}} 'S' // TemplateName in TemplateArgument. template