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/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 971ce541d4831..e4960ec660b90 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -90,7 +90,7 @@ def UnaryTransformType : TypeNode, NeverCanonicalUnlessDependent; def TagType : TypeNode; def RecordType : TypeNode, LeafType; def EnumType : TypeNode, LeafType; -def ElaboratedType : TypeNode, NeverCanonical; +def InjectedClassNameType : TypeNode, AlwaysDependent, LeafType; def AttributedType : TypeNode, NeverCanonical; def BTFTagAttributedType : TypeNode, NeverCanonical; def HLSLAttributedResourceType : TypeNode; @@ -102,7 +102,6 @@ def TemplateSpecializationType : TypeNode, NeverCanonicalUnlessDependent; def DeducedType : TypeNode; def AutoType : TypeNode; def DeducedTemplateSpecializationType : TypeNode; -def InjectedClassNameType : TypeNode, AlwaysDependent, LeafType; def DependentNameType : TypeNode, AlwaysDependent; def DependentTemplateSpecializationType : TypeNode, AlwaysDependent; def PackExpansionType : TypeNode, AlwaysDependent; 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..39db57bc8f866 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::'. @@ -163,7 +148,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 +174,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 +194,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 b331acbe606b7..1655c855d119e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3218,7 +3218,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 '::'. /// @@ -3255,7 +3255,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. /// @@ -3574,8 +3574,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); @@ -10196,7 +10196,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 @@ -11603,13 +11603,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, @@ -11838,8 +11841,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); @@ -13738,8 +13741,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, @@ -15155,14 +15159,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 4d0da1102bb59..c6287f4c76a11 100644 --- a/clang/include/clang/Sema/SemaInternal.h +++ b/clang/include/clang/Sema/SemaInternal.h @@ -208,7 +208,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer { class NamespaceSpecifierSet { struct SpecifierInfo { DeclContext* DeclCtx; - NestedNameSpecifier* NameSpecifier; + NestedNameSpecifier NameSpecifier; unsigned EditDistance; }; @@ -228,9 +228,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); @@ -275,7 +275,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/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index 613eb6af2005a..8af32db4c0b39 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -32,7 +32,6 @@ TYPE_BIT_CODE(Enum, ENUM, 20) TYPE_BIT_CODE(ObjCInterface, OBJC_INTERFACE, 21) TYPE_BIT_CODE(ObjCObjectPointer, OBJC_OBJECT_POINTER, 22) TYPE_BIT_CODE(Decltype, DECLTYPE, 23) -TYPE_BIT_CODE(Elaborated, ELABORATED, 24) TYPE_BIT_CODE(SubstTemplateTypeParm, SUBST_TEMPLATE_TYPE_PARM, 25) TYPE_BIT_CODE(UnresolvedUsing, UNRESOLVED_USING, 26) TYPE_BIT_CODE(InjectedClassName, INJECTED_CLASS_NAME, 27) 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/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 80e7c8eff671a..5037b75542925 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1875,7 +1875,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 ac47b12cc8d72..8ffff91eb1216 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -181,18 +181,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 d981d69913632..b5d5f46dc5b5d 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 0bceecec6e555..3b36554a9389b 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); @@ -2863,7 +2863,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, // 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); } @@ -3820,7 +3821,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); @@ -4281,7 +4282,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)); @@ -4877,8 +4881,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 e24c68ed02865..69a0286ee4758 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; } @@ -1294,7 +1294,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; @@ -1330,8 +1330,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 = @@ -2024,6 +2024,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(); @@ -2365,7 +2367,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); @@ -2831,12 +2835,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); } @@ -2906,7 +2910,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()) @@ -2915,7 +2919,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); } @@ -3019,14 +3023,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())) { @@ -3054,7 +3058,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()); @@ -3076,7 +3080,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; @@ -3098,7 +3102,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); @@ -3107,7 +3111,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)) @@ -3654,8 +3658,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, @@ -3690,17 +3695,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(); @@ -3735,15 +3744,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(); @@ -3818,6 +3819,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()) @@ -3846,11 +3852,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(); @@ -3909,7 +3912,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) { @@ -4054,7 +4058,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: @@ -4097,7 +4100,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); @@ -4114,7 +4117,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; @@ -4184,7 +4187,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)) @@ -4208,8 +4211,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; @@ -4415,9 +4418,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()) { @@ -5079,7 +5083,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. @@ -5539,7 +5543,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"); @@ -5629,8 +5633,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. @@ -5649,7 +5654,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()) @@ -5708,15 +5713,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; } @@ -5729,7 +5734,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; @@ -5912,7 +5917,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); @@ -5959,8 +5965,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 @@ -5972,10 +5976,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; } } @@ -5994,7 +5997,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 04f13c7d7a6a3..55155ada9b9c7 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 = ? } @@ -1567,7 +1569,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 85c768807572f..1b1f6a98988ef 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -397,9 +397,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) @@ -1198,9 +1199,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 @@ -1748,9 +1750,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; } @@ -1911,8 +1915,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; @@ -1920,7 +1926,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; @@ -4266,7 +4271,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; } @@ -5032,10 +5039,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); @@ -5160,7 +5169,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); @@ -5622,7 +5631,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(); @@ -5642,7 +5653,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()); @@ -6700,7 +6713,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 cad6731173700..2c1081d665231 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())) @@ -428,7 +428,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(), @@ -1810,7 +1813,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. @@ -2120,7 +2126,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; @@ -2172,7 +2178,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; } @@ -2293,7 +2299,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() || @@ -2377,7 +2384,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); @@ -2386,7 +2393,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 359e30cb8f5cd..a92b89def6433 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 44931d0481e26..0318f85a344d7 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 a47d1cc22980d..65c708022fc09 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -186,8 +186,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 ce2dd4d76368a..29067bf956c7b 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 = @@ -10640,7 +10647,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()) { @@ -11222,7 +11229,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()); } @@ -11718,7 +11725,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 e25b6948d30f8..0e746ddfe13a2 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 e0650067b9547..28d518a52cfe7 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -3270,7 +3270,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 = @@ -3350,7 +3350,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 6c32c98cec011..c33c215c03e01 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2974,7 +2974,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; @@ -4560,7 +4560,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, @@ -4665,7 +4665,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 236cc3d9e8907..709614e828f0a 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; } @@ -6028,7 +6030,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; @@ -6737,7 +6739,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() { } D->completeDefinition(); - ObjCFastEnumerationStateType = Context.getTagDeclType(D); + ObjCFastEnumerationStateType = Context.getCanonicalTagType(D); } return ObjCFastEnumerationStateType; @@ -7247,7 +7249,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); @@ -7466,20 +7469,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: @@ -7933,8 +7939,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 a02a009158d12..3dc0859cc5d51 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 f4a99467010af..f0f7b97c624f7 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -826,7 +826,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); @@ -1236,7 +1236,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); } @@ -1392,8 +1392,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. @@ -1479,7 +1480,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 @@ -1606,7 +1608,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); @@ -1763,7 +1766,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. @@ -2016,7 +2020,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); @@ -3755,7 +3759,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; @@ -3789,7 +3794,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 @@ -3815,9 +3822,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()); @@ -3846,8 +3851,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; @@ -3926,7 +3932,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; @@ -4048,7 +4055,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()) @@ -4212,7 +4220,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; @@ -4259,7 +4268,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; @@ -4363,8 +4373,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. @@ -4464,7 +4475,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; @@ -4554,9 +4567,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 = @@ -4574,8 +4586,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) { @@ -5155,7 +5167,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 a181559834296..977c9a27a6ad6 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -870,7 +870,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; @@ -2918,15 +2919,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(); @@ -2963,7 +2964,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; @@ -3684,7 +3685,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); @@ -3858,7 +3859,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), @@ -3905,7 +3906,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), }; @@ -4076,7 +4077,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( @@ -4312,7 +4313,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, @@ -4463,8 +4464,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 e3232b61a693c..1fab9e402ee7f 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..d3d549c0127bf 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::Super: // 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 67ed17bdd7b5d..b2579c427ec44 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..8868aea53f10b 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::Super: 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..9e69ca567e80c 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,13 @@ 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->getCanonicalInjectedTST(); + } else { + Out << '$'; + VisitTagDecl(TT->getOriginalDecl()); + return; + } } if (const ObjCInterfaceType *OIT = T->getAs()) { Out << '$'; @@ -945,10 +949,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 34ffd62da85e4..e1b25f7387bcd 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.getULongLong(); 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 31392d1dd8d4b..b096d5ee296de 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 9a04bf298c0ac..004cb40445eab 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -1109,12 +1109,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); @@ -1175,10 +1177,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); @@ -1243,7 +1246,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)) { // We may have a (non-dependent) template name. @@ -1264,7 +1268,8 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_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 b58100c635677..6cbc48102bf73 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 ff50b3f83908c..14ccf4d67e6ba 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; @@ -2031,11 +2031,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 d1400cbfc884d..94b1099c4bb90 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..cc385abc3059d 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) { @@ -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 56608e990fd50..48ec4a48b9e63 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1882,9 +1882,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); } @@ -1892,9 +1893,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); } } @@ -1907,9 +1909,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 8c6a17301fba6..778941c128bdd 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 @@ -1011,7 +1011,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..fefcfdcdb3fd4 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::Super: + return NNS.getAsSuper(); + + 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); } @@ -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::Super: // 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 5e523fe887318..47ebf83bf0f50 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -603,7 +603,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; @@ -2288,7 +2288,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)) @@ -3315,7 +3315,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); @@ -5172,7 +5174,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)); }()) { @@ -7788,8 +7792,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(), @@ -7798,7 +7805,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)) @@ -8325,7 +8332,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, @@ -8361,7 +8369,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); } } } @@ -9619,7 +9629,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, @@ -9664,7 +9677,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, @@ -9945,8 +9961,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); @@ -9959,7 +9976,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); @@ -10465,10 +10482,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()) { @@ -10510,7 +10531,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()); @@ -11482,7 +11505,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. @@ -11519,7 +11544,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 @@ -12585,8 +12610,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; @@ -15110,10 +15135,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())) && @@ -15122,6 +15146,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; @@ -15226,16 +15251,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; @@ -15589,7 +15614,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; @@ -15634,7 +15661,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. @@ -15664,9 +15691,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 a43ac9eb7610d..99492cea4e6c2 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; @@ -4498,12 +4507,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())) @@ -4912,14 +4921,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 @@ -5051,9 +5060,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, @@ -5177,7 +5186,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); @@ -5191,7 +5201,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); @@ -5603,15 +5614,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; } @@ -5620,10 +5634,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); @@ -5769,7 +5788,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). @@ -6176,9 +6195,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 @@ -6879,8 +6897,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; } @@ -6894,14 +6912,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; @@ -7026,7 +7043,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(); } @@ -7813,7 +7830,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) @@ -8404,7 +8422,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); @@ -8580,7 +8599,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); @@ -8696,9 +8716,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); } } @@ -8764,9 +8784,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); } } @@ -8878,9 +8898,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, @@ -8915,7 +8935,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); } @@ -9015,7 +9036,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 @@ -10031,7 +10053,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 14403e65e8f42..c589547f48410 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.setElaboratedKWLoc(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::Super: + 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) @@ -5016,7 +5062,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; @@ -5224,9 +5270,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) @@ -5754,7 +5800,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); @@ -5774,7 +5820,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(); @@ -5837,7 +5883,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 = @@ -5956,14 +6002,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; @@ -6251,8 +6297,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; @@ -6272,36 +6319,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; } @@ -9040,9 +9099,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)) { @@ -9728,7 +9786,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?"); @@ -9756,7 +9815,9 @@ static void checkIsValidOpenCLKernelParameter( "Unexpected type."); const Type *FieldRecTy = FieldTy->getPointeeOrArrayElementType(); - RD = FieldRecTy->castAs()->getDecl(); + RD = FieldRecTy->castAs() + ->getOriginalDecl() + ->getDefinitionOrSelf(); } else { RD = cast(Next); } @@ -10763,7 +10824,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() || @@ -12267,11 +12328,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(); @@ -13275,7 +13336,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; @@ -13341,7 +13403,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; @@ -13406,7 +13469,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; @@ -14379,7 +14443,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. @@ -17478,6 +17544,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 @@ -17943,8 +18010,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())) { @@ -17954,6 +18020,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; } } @@ -18077,78 +18152,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; + } } } @@ -18319,14 +18395,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; } @@ -18407,7 +18483,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); } } @@ -18439,7 +18516,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) @@ -18555,14 +18632,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"); @@ -18992,7 +19067,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 @@ -19058,7 +19133,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 @@ -19381,7 +19457,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; } @@ -19539,7 +19615,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); @@ -19565,9 +19643,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 @@ -19598,8 +19677,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()) @@ -19632,7 +19713,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); @@ -20398,7 +20481,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 78f4804202ddc..e4f28357a4903 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()) @@ -3766,7 +3768,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()) @@ -4360,7 +4364,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); @@ -4713,7 +4720,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 45c7178c6965d..813cf42862353 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"); @@ -2942,8 +2937,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 @@ -2964,13 +2979,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(); @@ -2986,11 +2994,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; @@ -3001,7 +3008,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 @@ -3079,8 +3086,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); @@ -4482,9 +4489,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; @@ -5876,7 +5880,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 0edfd6015cbd9..7cb9960823c2a 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::Super: + 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); @@ -3593,7 +3601,7 @@ FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc, DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Delete); FunctionDecl *OperatorDelete = nullptr; - QualType DeallocType = Context.getRecordType(RD); + CanQualType DeallocType = Context.getCanonicalTagType(RD); ImplicitDeallocationParameters IDP = { DeallocType, ShouldUseTypeAwareOperatorNewOrDelete(), AlignedAllocationMode::No, SizedDeallocationMode::No}; @@ -3627,7 +3635,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, Found.suppressDiagnostics(); if (!isAlignedAllocation(IDP.PassAlignment) && - hasNewExtendedAlignment(*this, Context.getRecordType(RD))) + hasNewExtendedAlignment(*this, Context.getCanonicalTagType(RD))) IDP.PassAlignment = AlignedAllocationMode::Yes; // C++17 [expr.delete]p10: @@ -4050,7 +4058,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(); } } @@ -4574,7 +4583,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; @@ -4818,7 +4827,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, @@ -5370,16 +5382,18 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } + // FIXME: use sugared type from member pointer. + CanQualType RHSClassType = Context.getCanonicalTagType(RHSClass); CXXCastPath BasePath; if (CheckDerivedToBaseConversion( - LHSType, QualType(RHSClass->getTypeForDecl(), 0), Loc, + LHSType, RHSClassType, Loc, SourceRange(LHS.get()->getBeginLoc(), RHS.get()->getEndLoc()), &BasePath)) return QualType(); // Cast LHS to type of use. - QualType UseType = Context.getQualifiedType(RHSClass->getTypeForDecl(), - LHSType.getQualifiers()); + QualType UseType = + Context.getQualifiedType(RHSClassType, LHSType.getQualifiers()); if (isIndirect) UseType = Context.getPointerType(UseType); ExprValueKind VK = isIndirect ? VK_PRValue : LHS.get()->getValueKind(); @@ -6184,7 +6198,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, case Pointer: return Ctx.getPointerType(T); case MemberPointer: - return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr, + return Ctx.getMemberPointerType(T, /*Qualifier=*/std::nullopt, ClassOrBound->getAsCXXRecordDecl()); case ObjCPointer: return Ctx.getObjCObjectPointerType(T); @@ -6357,7 +6371,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return QualType(); Steps.emplace_back(Step::MemberPointer, - Context.getTypeDeclType(Cls).getTypePtr()); + Context.getCanonicalTagType(Cls).getTypePtr()); continue; } @@ -6636,7 +6650,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; @@ -7243,16 +7258,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(S, - SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, - TemplateId->Name, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - /*IsCtorOrDtorName*/true); + TypeResult T = ActOnTemplateIdType( + S, ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, + /*IsCtorOrDtorName*/ true); if (T.isInvalid() || !T.get()) { // Recover by assuming we had the right type all along. DestructedType = ObjectType; @@ -7296,16 +7308,13 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - TypeResult T = ActOnTemplateIdType(S, - SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, - TemplateId->Name, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - /*IsCtorOrDtorName*/true); + TypeResult T = ActOnTemplateIdType( + S, ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, TemplateId->Name, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, + /*IsCtorOrDtorName*/ true); if (T.isInvalid() || !T.get()) { // Recover by dropping this type. ScopeType = QualType(); @@ -7505,7 +7514,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 9276554bebf9d..59f9c675c726d 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -233,7 +233,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); @@ -372,7 +372,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()) { @@ -457,7 +457,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(); } } @@ -507,8 +507,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()); } @@ -1808,7 +1808,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(); @@ -3361,7 +3361,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; @@ -3877,7 +3877,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( @@ -3925,7 +3926,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 1c6f292454ed6..98f0679d86337 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 8bde18f64f80b..d665a24560012 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::Super) + return LookupInSuper(R, Qualifier.getAsSuper()); + 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::Super) + return LookupInSuper(R, Qualifier.getAsSuper()); } 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::Super: 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 0f39a9817ce7f..27951c9105411 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 4ecc9b0d4c5c8..ac108221683ea 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 @@ -18612,10 +18614,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 5dd5b495480d9..c02e205dc9cde 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 3e03cb4bd5f99..76b705e7ad4a2 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 f85826aecadf3..8bfb9f8b1b99b 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -801,7 +801,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)) { @@ -1257,7 +1257,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; @@ -1287,11 +1287,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)) @@ -1604,9 +1604,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, @@ -1719,6 +1721,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (!hasCasesNotInSwitch) SS->setAllEnumCasesCovered(); } + enum_out:; } if (BodyStmt) @@ -1748,7 +1751,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; @@ -3709,7 +3712,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; @@ -3928,7 +3931,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; } } @@ -4619,7 +4622,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); @@ -4661,9 +4665,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); @@ -4683,7 +4688,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 698d1270be634..4cff3a443ae5f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -291,7 +291,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); } @@ -363,9 +363,8 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, // The code is missing a 'template' keyword prior to the dependent template // name. - NestedNameSpecifier *Qualifier = (NestedNameSpecifier *)SS->getScopeRep(); SuggestedTemplate = TemplateTy::make(Context.getDependentTemplateName( - {Qualifier, &II, /*HasTemplateKeyword=*/false})); + {SS->getScopeRep(), &II, /*HasTemplateKeyword=*/false})); Diag(IILoc, diag::err_template_kw_missing) << SuggestedTemplate.get() << FixItHint::CreateInsertion(IILoc, "template "); @@ -397,7 +396,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 @@ -797,9 +798,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) @@ -907,7 +908,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); } @@ -924,9 +925,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()); } } @@ -967,15 +968,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); @@ -2106,11 +2104,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( @@ -2139,12 +2137,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 && @@ -2635,11 +2627,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 { @@ -2676,8 +2668,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 @@ -2700,14 +2696,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(); @@ -2726,12 +2722,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 @@ -2779,9 +2776,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; @@ -2789,8 +2787,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; @@ -2800,7 +2799,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())) @@ -3100,7 +3099,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, @@ -3108,7 +3108,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( @@ -3122,7 +3123,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(); @@ -3235,7 +3236,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; @@ -3252,8 +3253,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(); @@ -3264,8 +3266,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(); @@ -3287,11 +3290,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()) { @@ -3338,7 +3340,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); } @@ -3375,14 +3377,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; @@ -3494,7 +3498,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(); @@ -3559,7 +3563,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 @@ -3610,6 +3615,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()) @@ -3677,8 +3694,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)) { @@ -3717,16 +3734,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 = + cast(ICNT)->getCanonicalInjectedTST(); - 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; } @@ -3768,7 +3784,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 { @@ -3779,7 +3795,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, @@ -3827,7 +3844,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; } @@ -3838,11 +3855,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; @@ -3858,8 +3876,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; @@ -3903,12 +3922,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); @@ -3919,30 +3938,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, @@ -3989,24 +3995,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"); @@ -4022,21 +4018,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)); } @@ -4958,7 +4942,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: @@ -5246,8 +5230,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) { @@ -5264,25 +5249,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; @@ -5293,8 +5270,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; @@ -5307,8 +5284,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; @@ -5320,17 +5297,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 @@ -5338,33 +5314,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, @@ -5897,8 +5864,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) { @@ -6042,7 +6009,7 @@ namespace { #include "clang/AST/TypeNodes.inc" bool VisitTagDecl(const TagDecl *Tag); - bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + bool VisitNestedNameSpecifier(NestedNameSpecifier NNS); }; } // end anonymous namespace @@ -6187,11 +6154,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( @@ -6211,7 +6178,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType( const InjectedClassNameType* T) { - return VisitTagDecl(T->getDecl()); + return VisitTagDecl(T->getOriginalDecl()->getDefinitionOrSelf()); } bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( @@ -6221,10 +6188,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( @@ -6270,11 +6234,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; } @@ -6291,20 +6254,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::Super: 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!"); } @@ -7265,7 +7223,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // 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)); @@ -7363,7 +7322,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType IntegerType = ParamType; if (const EnumType *Enum = IntegerType->getAs()) { - IntegerType = Enum->getDecl()->getIntegerType(); + IntegerType = + Enum->getOriginalDecl()->getDefinitionOrSelf()->getIntegerType(); } if (ParamType->isBooleanType()) { @@ -7726,10 +7686,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); } @@ -7821,7 +7780,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()) { @@ -8690,7 +8649,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. @@ -8706,18 +8664,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: @@ -8739,13 +8693,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()) { @@ -8784,7 +8737,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) @@ -8847,6 +8800,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 @@ -9885,9 +9845,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 @@ -9895,12 +9852,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; } @@ -10255,7 +10214,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; } @@ -10802,7 +10761,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; @@ -10914,7 +10873,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; @@ -10922,18 +10884,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); } @@ -10947,11 +10899,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(); @@ -10999,19 +10952,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.setElaboratedKWLoc(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; } @@ -11034,7 +11001,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); @@ -11116,6 +11083,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 @@ -11131,15 +11099,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: @@ -11149,22 +11122,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 e1a975bcfb3e1..2506f0d0c7df5 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -613,38 +613,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. @@ -678,34 +669,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) { @@ -2110,26 +2103,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), @@ -2853,13 +2839,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: @@ -3077,8 +3061,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. @@ -3435,7 +3420,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 { @@ -4105,7 +4090,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(); @@ -5061,10 +5046,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.setElaboratedKWLoc(TL.getElaboratedKWLoc()); NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setQualifierLoc(TL.getQualifierLoc()); return Result; } @@ -6379,8 +6366,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); @@ -6389,9 +6376,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); @@ -6675,19 +6661,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 @@ -6761,7 +6741,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; } @@ -6879,7 +6859,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, } case Type::InjectedClassName: - T = cast(T)->getInjectedSpecializationType(); + T = cast(T)->getCanonicalInjectedTST(); [[fallthrough]]; case Type::TemplateSpecialization: { diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 9be1c9c356cb2..c8ac720dbe632 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,10 @@ 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->getCanonicalInjectedTST()); 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 20bac0e56b195..1e01723fbc93f 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,18 @@ 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->getCanonicalInjectedTST()); + TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc()); } return Type; } @@ -2050,7 +2045,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; @@ -2083,41 +2078,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()) { @@ -2164,6 +2128,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); } @@ -2182,9 +2152,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 @@ -3160,10 +3130,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()); } @@ -4558,14 +4524,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 e2c3cdcd536bc..755cbb6e4547d 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->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; } @@ -6920,7 +6908,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 @@ -6986,16 +6975,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; } } @@ -7041,8 +7031,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, @@ -7057,7 +7047,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 572dbf2e7393f..b518400b60c7e 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()); } @@ -515,8 +520,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; @@ -644,7 +648,7 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, return ParsedTemplateArgument(); return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), - Arg.getLocation()); + Arg.getNameLoc()); } case ParsedTemplateArgument::NonType: { @@ -653,12 +657,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) @@ -1105,8 +1109,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; } @@ -1290,9 +1293,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 7dbd4bb0ed125..05ab55c6d304c 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; @@ -3462,7 +3461,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); } } @@ -3655,11 +3654,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) @@ -3967,7 +3977,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 && @@ -5103,7 +5114,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 @@ -5321,7 +5332,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() == @@ -5900,7 +5911,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()); @@ -5931,16 +5984,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 || @@ -5989,24 +6035,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; @@ -6065,7 +6093,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) { @@ -7031,9 +7081,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) @@ -9172,11 +9219,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; } @@ -9314,7 +9359,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; @@ -9354,10 +9399,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; @@ -9494,10 +9539,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()) @@ -9552,7 +9597,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 @@ -9630,15 +9676,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"); @@ -9649,7 +9686,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); } @@ -9815,8 +9852,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/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 10aedb68fcd9d..11d7749e57d83 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5501,7 +5501,7 @@ void ASTReader::InitializeContext() { Error("Invalid FILE type in AST file"); return; } - Context.setFILEDecl(Tag->getDecl()); + Context.setFILEDecl(Tag->getOriginalDecl()); } } } @@ -5522,7 +5522,7 @@ void ASTReader::InitializeContext() { Error("Invalid jmp_buf type in AST file"); return; } - Context.setjmp_bufDecl(Tag->getDecl()); + Context.setjmp_bufDecl(Tag->getOriginalDecl()); } } } @@ -5540,7 +5540,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()); } } } @@ -5575,7 +5575,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()); } } } @@ -7227,6 +7227,7 @@ class TypeLocReader : public TypeLocVisitor { void VisitFunctionTypeLoc(FunctionTypeLoc); void VisitArrayTypeLoc(ArrayTypeLoc); + void VisitTagTypeLoc(TagTypeLoc TL); }; } // namespace clang @@ -7373,15 +7374,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) { @@ -7435,17 +7445,27 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { + TL.setElaboratedKWLoc(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()); } @@ -7483,14 +7503,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) { @@ -7498,15 +7522,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()); @@ -7963,18 +7978,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: @@ -9583,12 +9595,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; } @@ -10104,41 +10110,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::Super: { CXXRecordDecl *RD = readDeclAs(); SourceRange Range = readSourceRange(); Builder.MakeSuper(Context, RD, Range.getBegin(), Range.getEnd()); break; } + + case NestedNameSpecifier::Kind::Null: + llvm_unreachable("unexpected null nested name specifier"); } } @@ -10534,12 +10536,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 bd84a9741d01b..922440e949756 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) { @@ -2236,15 +2241,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: { @@ -2478,14 +2474,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 a6957e54b66f1..81ac79655e52b 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.getElaboratedKWLoc()); + 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); @@ -6772,22 +6779,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: @@ -6810,7 +6817,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) { @@ -7068,49 +7075,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::Super: + AddDeclRef(Qualifier.getAsSuper()); + 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 e414910469a64..1ce75eba525b1 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) { @@ -2560,7 +2561,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( @@ -2606,7 +2606,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 3e68373028b10..37117b55abd12 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/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 9412d9735ef82..4d2bfc0a07532 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1420,79 +1420,25 @@ bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) { llvm_unreachable("Invalid DeclarationName::Kind!"); } -bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range) { - // FIXME: This whole routine is a hack to work around the lack of proper - // source information in nested-name-specifiers (PR5791). Since we do have - // a beginning source location, we can visit the first component of the - // nested-name-specifier, if it's a single-token component. - if (!NNS) - return false; - - // Get the first component in the nested-name-specifier. - while (NestedNameSpecifier *Prefix = NNS->getPrefix()) - NNS = Prefix; - - switch (NNS->getKind()) { - case NestedNameSpecifier::Namespace: - return Visit( - MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(), TU)); - - case NestedNameSpecifier::TypeSpec: { - // If the type has a form where we know that the beginning of the source - // range matches up with a reference cursor. Visit the appropriate reference - // cursor. - const Type *T = NNS->getAsType(); - if (const TypedefType *Typedef = dyn_cast(T)) - return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU)); - if (const TagType *Tag = dyn_cast(T)) - return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU)); - if (const TemplateSpecializationType *TST = - dyn_cast(T)) - return VisitTemplateName(TST->getTemplateName(), Range.getBegin()); - break; - } - - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Super: - break; - } - - return false; -} - bool CursorVisitor::VisitNestedNameSpecifierLoc( NestedNameSpecifierLoc Qualifier) { - SmallVector Qualifiers; - for (; Qualifier; Qualifier = Qualifier.getPrefix()) - Qualifiers.push_back(Qualifier); - - while (!Qualifiers.empty()) { - NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); - NestedNameSpecifier *NNS = Q.getNestedNameSpecifier(); - switch (NNS->getKind()) { - case NestedNameSpecifier::Namespace: - if (Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), - Q.getLocalBeginLoc(), TU))) - return true; - - break; - - case NestedNameSpecifier::TypeSpec: - if (Visit(Q.getTypeLoc())) - return true; - - break; - - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Identifier: - case NestedNameSpecifier::Super: - break; - } + NestedNameSpecifier NNS = Qualifier.getNestedNameSpecifier(); + switch (NNS.getKind()) { + case NestedNameSpecifier::Kind::Namespace: { + auto [Namespace, Prefix] = Qualifier.castAsNamespaceAndPrefix(); + if (VisitNestedNameSpecifierLoc(Prefix)) + return true; + return Visit( + MakeCursorNamespaceRef(Namespace, Qualifier.getLocalBeginLoc(), TU)); } - - return false; + case NestedNameSpecifier::Kind::Type: + return Visit(Qualifier.castAsTypeLoc()); + case NestedNameSpecifier::Kind::Null: + case NestedNameSpecifier::Kind::Global: + case NestedNameSpecifier::Kind::Super: + return false; + } + llvm_unreachable("unexpected nested name specifier kind"); } bool CursorVisitor::VisitTemplateParameters( @@ -1515,16 +1461,23 @@ bool CursorVisitor::VisitTemplateParameters( return false; } -bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) { +bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation NameLoc, + NestedNameSpecifierLoc NNS) { switch (Name.getKind()) { + case TemplateName::QualifiedTemplate: { + const QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName(); + assert(QTN->getQualifier() == NNS.getNestedNameSpecifier()); + if (VisitNestedNameSpecifierLoc(NNS)) + return true; + return VisitTemplateName(QTN->getUnderlyingTemplate(), NameLoc, /*NNS=*/{}); + } case TemplateName::Template: case TemplateName::UsingTemplate: - case TemplateName::QualifiedTemplate: // FIXME: Visit nested-name-specifier. - return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU)); + return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), NameLoc, TU)); case TemplateName::OverloadedTemplate: // Visit the overloaded template set. - if (Visit(MakeCursorOverloadedDeclRef(Name, Loc, TU))) + if (Visit(MakeCursorOverloadedDeclRef(Name, NameLoc, TU))) return true; return false; @@ -1533,17 +1486,19 @@ bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) { // FIXME: Visit DeclarationName? return false; - case TemplateName::DependentTemplate: - // FIXME: Visit nested-name-specifier. - return false; + case TemplateName::DependentTemplate: { + assert(Name.getAsDependentTemplateName()->getQualifier() == + NNS.getNestedNameSpecifier()); + return VisitNestedNameSpecifierLoc(NNS); + } case TemplateName::SubstTemplateTemplateParm: return Visit(MakeCursorTemplateRef( - Name.getAsSubstTemplateTemplateParm()->getParameter(), Loc, TU)); + Name.getAsSubstTemplateTemplateParm()->getParameter(), NameLoc, TU)); case TemplateName::SubstTemplateTemplateParmPack: return Visit(MakeCursorTemplateRef( - Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc, + Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), NameLoc, TU)); case TemplateName::DeducedTemplate: @@ -1587,11 +1542,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (VisitNestedNameSpecifierLoc(TAL.getTemplateQualifierLoc())) - return true; - return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(), - TAL.getTemplateNameLoc()); + TAL.getTemplateNameLoc(), + TAL.getTemplateQualifierLoc()); } llvm_unreachable("Invalid TemplateArgument::Kind!"); @@ -1669,7 +1622,10 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU)); + if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + return true; + + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } bool CursorVisitor::VisitPredefinedSugarTypeLoc(PredefinedSugarTypeLoc TL) { @@ -1677,14 +1633,20 @@ bool CursorVisitor::VisitPredefinedSugarTypeLoc(PredefinedSugarTypeLoc TL) { } bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { + if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + return true; + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { + if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + return true; + if (TL.isDefinition()) - return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest)); + return Visit(MakeCXCursor(TL.getOriginalDecl(), TU, RegionOfInterest)); - return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); + return Visit(MakeCursorTypeRef(TL.getOriginalDecl(), TL.getNameLoc(), TU)); } bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { @@ -1763,7 +1725,10 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { } bool CursorVisitor::VisitUsingTypeLoc(UsingTypeLoc TL) { - auto *underlyingDecl = TL.getUnderlyingType()->getAsTagDecl(); + if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + return true; + + auto *underlyingDecl = TL.getTypePtr()->desugar()->getAsTagDecl(); if (underlyingDecl) { return Visit(MakeCursorTypeRef(underlyingDecl, TL.getNameLoc(), TU)); } @@ -1826,7 +1791,7 @@ bool CursorVisitor::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { bool CursorVisitor::VisitDeducedTemplateSpecializationTypeLoc( DeducedTemplateSpecializationTypeLoc TL) { if (VisitTemplateName(TL.getTypePtr()->getTemplateName(), - TL.getTemplateNameLoc())) + TL.getTemplateNameLoc(), TL.getQualifierLoc())) return true; return false; @@ -1836,7 +1801,7 @@ bool CursorVisitor::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { // Visit the template name. if (VisitTemplateName(TL.getTypePtr()->getTemplateName(), - TL.getTemplateNameLoc())) + TL.getTemplateNameLoc(), TL.getQualifierLoc())) return true; // Visit the template arguments. @@ -1871,8 +1836,7 @@ bool CursorVisitor::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { - // Visit the nested-name-specifier, if there is one. - if (TL.getQualifierLoc() && VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) + if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) return true; // Visit the template arguments. @@ -1883,13 +1847,6 @@ bool CursorVisitor::VisitDependentTemplateSpecializationTypeLoc( return false; } -bool CursorVisitor::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - if (VisitNestedNameSpecifierLoc(TL.getQualifierLoc())) - return true; - - return Visit(TL.getNamedTypeLoc()); -} - bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { return Visit(TL.getPatternLoc()); } @@ -1908,7 +1865,7 @@ bool CursorVisitor::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) { } bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); + return Visit(MakeCursorTypeRef(TL.getOriginalDecl(), TL.getNameLoc(), TU)); } bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) { @@ -2065,7 +2022,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob { public: NestedNameSpecifierLocVisit(NestedNameSpecifierLoc Qualifier, CXCursor parent) : VisitorJob(parent, VisitorJob::NestedNameSpecifierLocVisitKind, - Qualifier.getNestedNameSpecifier(), + Qualifier.getNestedNameSpecifier().getAsVoidPointer(), Qualifier.getOpaqueData()) {} static bool classof(const VisitorJob *VJ) { @@ -2074,8 +2031,7 @@ class NestedNameSpecifierLocVisit : public VisitorJob { NestedNameSpecifierLoc get() const { return NestedNameSpecifierLoc( - const_cast( - static_cast(data[0])), + NestedNameSpecifier::getFromVoidPointer(data[0]), const_cast(data[1])); } }; @@ -5360,9 +5316,13 @@ CXString clang_getCursorSpelling(CXCursor C) { case CXCursor_TypeRef: { const TypeDecl *Type = getCursorTypeRef(C).first; assert(Type && "Missing type decl"); + const ASTContext &Ctx = getCursorContext(C); + QualType T = Ctx.getTypeDeclType(Type); - return cxstring::createDup( - getCursorContext(C).getTypeDeclType(Type).getAsString()); + PrintingPolicy Policy = Ctx.getPrintingPolicy(); + Policy.FullyQualifiedName = true; + Policy.SuppressTagKeyword = false; + return cxstring::createDup(T.getAsString(Policy)); } case CXCursor_TemplateRef: { const TemplateDecl *Template = getCursorTemplateRef(C).first; diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp index 8f6729b83ffa0..1636e1e5e0a7b 100644 --- a/clang/tools/libclang/CIndexCodeCompletion.cpp +++ b/clang/tools/libclang/CIndexCodeCompletion.cpp @@ -616,7 +616,7 @@ namespace { if (!baseType.isNull()) { // Get the declaration for a class/struct/union/enum type if (const TagType *Tag = baseType->getAs()) - D = Tag->getDecl(); + D = Tag->getOriginalDecl(); // Get the @interface declaration for a (possibly-qualified) Objective-C // object pointer type, e.g., NSString* else if (const ObjCObjectPointerType *ObjPtr = @@ -628,7 +628,7 @@ namespace { // Get the class for a C++ injected-class-name else if (const InjectedClassNameType *Injected = baseType->getAs()) - D = Injected->getDecl(); + D = Injected->getOriginalDecl(); } if (D != nullptr) { diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index a6301daa672c3..3c4062410eac1 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1332,16 +1332,10 @@ CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) { TypeLoc TL = Type->getTypeLoc(); SourceLocation Loc = TL.getBeginLoc(); - if (const ElaboratedType *ElabT = Ty->getAs()) { - Ty = ElabT->getNamedType(); - ElaboratedTypeLoc ElabTL = TL.castAs(); - Loc = ElabTL.getNamedTypeLoc().getBeginLoc(); - } - if (const TypedefType *Typedef = Ty->getAs()) return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU); if (const TagType *Tag = Ty->getAs()) - return MakeCursorTypeRef(Tag->getDecl(), Loc, TU); + return MakeCursorTypeRef(Tag->getOriginalDecl(), Loc, TU); if (const TemplateTypeParmType *TemplP = Ty->getAs()) return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU); diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index f0d92e8c40124..941e39a582758 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -357,7 +357,7 @@ CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, TST = T->getAs()) { BaseD = TST->getTemplateName().getAsTemplateDecl(); } else if (const RecordType *RT = T->getAs()) { - BaseD = RT->getDecl(); + BaseD = RT->getOriginalDecl(); } if (BaseD) @@ -389,13 +389,22 @@ SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc( if (QualifiedTypeLoc QL = TL.getAs()) TL = QL.getUnqualifiedLoc(); - if (ElaboratedTypeLoc EL = TL.getAs()) - return EL.getNamedTypeLoc().getBeginLoc(); - if (DependentNameTypeLoc DL = TL.getAs()) - return DL.getNameLoc(); - if (DependentTemplateSpecializationTypeLoc DTL = - TL.getAs()) - return DTL.getTemplateNameLoc(); + // FIXME: Factor this out, a lot of TypeLoc users seem to need a generic + // TypeLoc::getNameLoc() + if (auto TTL = TL.getAs()) + return TTL.getNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getTemplateNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getTemplateNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getNameLoc(); + if (auto TTL = TL.getAs()) + return TTL.getNameLoc(); return Loc; } diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index e7864e6d62e4d..11d02d8088918 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -118,7 +118,6 @@ static CXTypeKind GetTypeKind(QualType T) { TKCASE(ExtVector); TKCASE(MemberPointer); TKCASE(Auto); - TKCASE(Elaborated); TKCASE(Pipe); TKCASE(Attributed); TKCASE(BTFTagAttributed); @@ -225,6 +224,11 @@ FindTemplateArgumentTypeAt(ArrayRef TA, unsigned index) { return std::nullopt; } +static CXType getTypeDeclType(const ASTContext &Context, CXTranslationUnit TU, + const TypeDecl *TD) { + return MakeCXType(Context.getTypeDeclType(TD), TU); +} + CXType clang_getCursorType(CXCursor C) { using namespace cxcursor; @@ -244,7 +248,7 @@ CXType clang_getCursorType(CXCursor C) { return MakeCXType(QualType(), TU); if (const TypeDecl *TD = dyn_cast(D)) - return MakeCXType(Context.getTypeDeclType(TD), TU); + return getTypeDeclType(Context, TU, TD); if (const ObjCInterfaceDecl *ID = dyn_cast(D)) return MakeCXType(Context.getObjCInterfaceType(ID), TU); if (const DeclaratorDecl *DD = dyn_cast(D)) @@ -271,11 +275,8 @@ CXType clang_getCursorType(CXCursor C) { return MakeCXType(T, TU); } - case CXCursor_TypeRef: { - QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first); - return MakeCXType(T, TU); - - } + case CXCursor_TypeRef: + return getTypeDeclType(Context, TU, getCursorTypeRef(C).first); case CXCursor_CXXBaseSpecifier: return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU); @@ -545,11 +546,11 @@ CXCursor clang_getTypeDeclaration(CXType CT) { break; case Type::Record: case Type::Enum: - D = cast(TP)->getDecl(); + D = cast(TP)->getOriginalDecl(); break; case Type::TemplateSpecialization: if (const RecordType *Record = TP->getAs()) - D = Record->getDecl(); + D = Record->getOriginalDecl(); else D = cast(TP)->getTemplateName() .getAsTemplateDecl(); @@ -563,14 +564,10 @@ CXCursor clang_getTypeDeclaration(CXType CT) { break; case Type::InjectedClassName: - D = cast(TP)->getDecl(); + D = cast(TP)->getOriginalDecl(); break; - // FIXME: Template type parameters! - - case Type::Elaborated: - TP = cast(TP)->getNamedType().getTypePtrOrNull(); - goto try_again; + // FIXME: Template type parameters! default: break; @@ -990,7 +987,7 @@ CXType clang_Type_getClassType(CXType CT) { const Type *TP = T.getTypePtrOrNull(); if (TP && TP->getTypeClass() == Type::MemberPointer) { - ET = Ctx.getTypeDeclType( + ET = Ctx.getCanonicalTagType( cast(TP)->getMostRecentCXXRecordDecl()); } return MakeCXType(ET, GetTU(CT)); @@ -1040,7 +1037,7 @@ static long long visitRecordForValidation(const RecordDecl *RD) { return CXTypeLayoutError_Dependent; // recurse if (const RecordType *ChildType = I->getType()->getAs()) { - if (const RecordDecl *Child = ChildType->getDecl()) { + if (const RecordDecl *Child = ChildType->getOriginalDecl()) { long long ret = visitRecordForValidation(Child); if (ret < 0) return ret; @@ -1390,10 +1387,9 @@ unsigned clang_Cursor_isInlineNamespace(CXCursor C) { CXType clang_Type_getNamedType(CXType CT){ QualType T = GetQualType(CT); - const Type *TP = T.getTypePtrOrNull(); - if (TP && TP->getTypeClass() == Type::Elaborated) - return MakeCXType(cast(TP)->getNamedType(), GetTU(CT)); + if (!T.isNull() && T->getPrefix()) + return MakeCXType(T, GetTU(CT)); return MakeCXType(QualType(), GetTU(CT)); } diff --git a/clang/tools/libclang/CursorVisitor.h b/clang/tools/libclang/CursorVisitor.h index 949b73908c315..d5ab699756988 100644 --- a/clang/tools/libclang/CursorVisitor.h +++ b/clang/tools/libclang/CursorVisitor.h @@ -255,12 +255,12 @@ class CursorVisitor : public DeclVisitor, // Name visitor bool VisitDeclarationNameInfo(DeclarationNameInfo Name); - bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range); bool VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); // Template visitors bool VisitTemplateParameters(const TemplateParameterList *Params); - bool VisitTemplateName(TemplateName Name, SourceLocation Loc); + bool VisitTemplateName(TemplateName Name, SourceLocation NameLoc, + NestedNameSpecifierLoc NNS); bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL); // Type visitors