From 365a3337f6ce53c1e35ad438faef379a357eefc1 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Sat, 12 Apr 2025 23:01:12 -0300 Subject: [PATCH] [PATCH 2/6] [clang] Improve nested name specifier AST representation Other changes --- .../bindings/python/tests/cindex/test_type.py | 2 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 117 ++--- .../clang/ASTMatchers/ASTMatchersInternal.h | 18 +- .../clang/Analysis/FlowSensitive/ASTOps.h | 10 +- clang/include/clang/Sema/DeclSpec.h | 24 +- clang/include/clang/Sema/ParsedTemplate.h | 26 +- clang/include/clang/Sema/Sema.h | 25 +- .../clang/Serialization/ASTRecordWriter.h | 3 +- clang/lib/ASTMatchers/ASTMatchFinder.cpp | 73 +-- clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 5 +- clang/lib/ASTMatchers/Dynamic/Registry.cpp | 5 +- .../FlowSensitive/DataflowEnvironment.cpp | 6 +- clang/lib/Analysis/UnsafeBufferUsage.cpp | 12 +- clang/lib/CodeGen/CGCXXABI.cpp | 4 +- clang/lib/CodeGen/CGCall.cpp | 10 +- clang/lib/CodeGen/CGClass.cpp | 52 +- clang/lib/CodeGen/CGDebugInfo.cpp | 95 ++-- clang/lib/CodeGen/CGDecl.cpp | 6 +- clang/lib/CodeGen/CGExpr.cpp | 16 +- clang/lib/CodeGen/CGExprCXX.cpp | 13 +- clang/lib/CodeGen/CGHLSLRuntime.cpp | 3 +- clang/lib/CodeGen/CGNonTrivialStruct.cpp | 3 +- clang/lib/CodeGen/CGObjCMac.cpp | 4 +- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 23 +- clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 4 +- clang/lib/CodeGen/CGPointerAuth.cpp | 2 +- clang/lib/CodeGen/CGStmt.cpp | 4 +- clang/lib/CodeGen/CGStmtOpenMP.cpp | 9 +- clang/lib/CodeGen/CGVTables.cpp | 8 +- clang/lib/CodeGen/CodeGenFunction.cpp | 4 - clang/lib/CodeGen/CodeGenModule.cpp | 22 +- clang/lib/CodeGen/CodeGenTypes.cpp | 17 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 21 +- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 25 +- clang/lib/CodeGen/Targets/X86.cpp | 2 +- clang/lib/ExtractAPI/DeclarationFragments.cpp | 68 +-- clang/lib/Frontend/ASTConsumers.cpp | 7 +- clang/lib/Frontend/ASTUnit.cpp | 2 +- clang/lib/Index/IndexTypeSourceInfo.cpp | 10 +- clang/lib/Index/USRGeneration.cpp | 4 - clang/lib/InstallAPI/Visitor.cpp | 4 +- clang/lib/Parse/ParseExprCXX.cpp | 13 +- clang/lib/Parse/ParseTemplate.cpp | 29 +- clang/lib/Parse/Parser.cpp | 9 +- clang/lib/Sema/DeclSpec.cpp | 6 +- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 23 +- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h | 2 +- clang/lib/Sema/HeuristicResolver.cpp | 13 +- clang/lib/Sema/SemaAccess.cpp | 35 +- clang/lib/Sema/SemaCXXScopeSpec.cpp | 217 ++++---- clang/lib/Sema/SemaCast.cpp | 6 +- clang/lib/Sema/SemaChecking.cpp | 28 +- clang/lib/Sema/SemaCodeComplete.cpp | 86 ++-- clang/lib/Sema/SemaCoroutine.cpp | 31 +- clang/lib/Sema/SemaDecl.cpp | 463 ++++++++++-------- clang/lib/Sema/SemaDeclAttr.cpp | 6 +- clang/lib/Sema/SemaDeclCXX.cpp | 382 +++++++-------- clang/lib/Sema/SemaDeclObjC.cpp | 15 +- clang/lib/Sema/SemaExceptionSpec.cpp | 5 +- clang/lib/Sema/SemaExpr.cpp | 68 +-- clang/lib/Sema/SemaExprCXX.cpp | 101 ++-- clang/lib/Sema/SemaExprMember.cpp | 7 +- clang/lib/Sema/SemaExprObjC.cpp | 6 +- clang/lib/Sema/SemaFunctionEffects.cpp | 8 +- clang/lib/Sema/SemaHLSL.cpp | 8 +- clang/lib/Sema/SemaInit.cpp | 73 ++- clang/lib/Sema/SemaLambda.cpp | 6 +- clang/lib/Sema/SemaLookup.cpp | 51 +- clang/lib/Sema/SemaOpenMP.cpp | 6 +- clang/lib/Sema/SemaOverload.cpp | 93 ++-- clang/lib/Sema/SemaStmt.cpp | 18 +- clang/lib/Sema/SemaStmtAsm.cpp | 4 +- clang/lib/Sema/SemaTemplate.cpp | 318 ++++++------ clang/lib/Sema/SemaTemplateDeduction.cpp | 117 +++-- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 45 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 67 +-- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 57 +-- clang/lib/Sema/SemaTemplateVariadic.cpp | 39 +- clang/lib/Sema/SemaType.cpp | 148 +++--- clang/lib/Sema/SemaTypeTraits.cpp | 12 +- clang/lib/Serialization/ASTReader.cpp | 74 +-- clang/lib/Serialization/ASTReaderDecl.cpp | 26 +- clang/lib/Serialization/ASTWriter.cpp | 59 ++- clang/lib/Serialization/ASTWriterDecl.cpp | 7 +- .../Serialization/TemplateArgumentHasher.cpp | 6 +- .../Checkers/DynamicTypePropagation.cpp | 2 +- .../Checkers/LLVMConventionsChecker.cpp | 3 - .../NonnullGlobalConstantsChecker.cpp | 5 +- .../NumberObjectConversionChecker.cpp | 11 +- .../Checkers/PaddingChecker.cpp | 14 +- .../Checkers/StdLibraryFunctionsChecker.cpp | 4 +- .../Checkers/WebKit/PtrTypesSemantics.cpp | 29 +- .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 4 - clang/lib/StaticAnalyzer/Core/CallEvent.cpp | 5 +- clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 4 +- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 4 +- clang/lib/Tooling/ASTDiff/ASTDiff.cpp | 13 +- clang/lib/Tooling/Refactoring/Lookup.cpp | 2 +- .../Refactoring/Rename/USRLocFinder.cpp | 57 +-- clang/lib/Tooling/Syntax/BuildTree.cpp | 5 +- .../lib/Tooling/Transformer/RangeSelector.cpp | 8 +- clang/tools/libclang/CIndex.cpp | 30 +- clang/tools/libclang/CXCursor.cpp | 6 - clang/tools/libclang/CXIndexDataConsumer.cpp | 23 +- clang/tools/libclang/CXType.cpp | 28 +- 105 files changed, 1886 insertions(+), 1932 deletions(-) diff --git a/clang/bindings/python/tests/cindex/test_type.py b/clang/bindings/python/tests/cindex/test_type.py index 34081bb88f3dd..cc101beca8cc5 100644 --- a/clang/bindings/python/tests/cindex/test_type.py +++ b/clang/bindings/python/tests/cindex/test_type.py @@ -63,7 +63,7 @@ def test_a_struct(self): self.assertIsNotNone(fields[1].translation_unit) self.assertEqual(fields[1].spelling, "b") self.assertFalse(fields[1].type.is_const_qualified()) - self.assertEqual(fields[1].type.kind, TypeKind.ELABORATED) + self.assertEqual(fields[1].type.kind, TypeKind.TYPEDEF) self.assertEqual(fields[1].type.get_canonical().kind, TypeKind.INT) self.assertEqual(fields[1].type.get_declaration().spelling, "I") self.assertEqual(fields[1].type.get_typedef_name(), "I") diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 08c898f7758ec..02d79b7488f82 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 diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 5df2294792552..f074bc5fed2cc 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; 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/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index e5680813e74de..797ef9b601ebc 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -106,21 +106,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::'. @@ -189,14 +175,14 @@ class CXXScopeSpec { SourceLocation getLastQualifierNameLoc() const; /// No scope specifier. - bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; } + bool isEmpty() const { return Range.isInvalid() && !getScopeRep(); } /// A scope specifier is present, but may be valid or invalid. bool isNotEmpty() const { return !isEmpty(); } /// An error occurred during parsing of the scope specifier. - bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; } + bool isInvalid() const { return Range.isValid() && !getScopeRep(); } /// A scope specifier is present, and it refers to a real scope. - bool isValid() const { return getScopeRep() != nullptr; } + bool isValid() const { return bool(getScopeRep()); } /// Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { @@ -209,7 +195,7 @@ class CXXScopeSpec { /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). - bool isSet() const { return getScopeRep() != nullptr; } + bool isSet() const { return bool(getScopeRep()); } void clear() { Range = SourceRange(); diff --git a/clang/include/clang/Sema/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..24dccffcd5675 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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. @@ -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); @@ -15155,14 +15158,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/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h index ee005ec287708..97178a4aa980c 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); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 6d0ba0b7907a1..b0fa7f4c95719 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -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); @@ -396,13 +396,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; @@ -577,13 +577,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 +1289,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 +1515,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 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/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/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..82216e8a748a3 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. diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 4a465e6526da0..e6437a6865fd3 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -326,7 +326,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 +401,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 = @@ -638,7 +637,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 +973,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 +1121,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) { @@ -1588,7 +1587,7 @@ namespace { const CXXRecordDecl *ClassDecl = Dtor->getParent(); CGF.EmitDeleteCall(Dtor->getOperatorDelete(), LoadThisForDtorDelete(CGF, Dtor), - CGF.getContext().getTagDeclType(ClassDecl)); + CGF.getContext().getCanonicalTagType(ClassDecl)); } }; @@ -1606,7 +1605,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 +1646,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 +1870,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); @@ -2057,7 +2057,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)); @@ -2158,7 +2158,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 +2210,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 +2227,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; @@ -2772,7 +2773,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); @@ -2896,8 +2897,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 +2907,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 +2957,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 +3040,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 +3068,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 +3120,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..d7918e8d3449a 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; } @@ -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(); @@ -2831,12 +2833,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 +2908,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 +2917,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,7 +3021,7 @@ 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); @@ -3076,7 +3078,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 +3100,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 +3109,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 +3656,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 +3693,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 +3742,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 +3817,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 +3850,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 +3910,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 +4056,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: @@ -4114,7 +4115,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 +4185,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 +4209,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 +4416,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()) { @@ -5539,7 +5541,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"); @@ -5708,7 +5710,7 @@ 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())) { @@ -5729,7 +5731,7 @@ struct ReconstitutableType : public RecursiveASTVisitor { Reconstitutable &= !FT->getNoReturnAttr(); return Reconstitutable; } - bool VisitRecordType(RecordType *RT) { + bool VisitRecordType(RecordType *RT, bool = false) { if (ReferencesAnonymousEntity(RT)) { Reconstitutable = false; return false; @@ -5959,8 +5961,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 +5972,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 +5993,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..6e0d55059cfeb 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 = ? } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 85c768807572f..f865ba5eb13a4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1198,9 +1198,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 @@ -1920,7 +1921,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; @@ -5032,10 +5032,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 +5162,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); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 359e30cb8f5cd..e4791faaf187e 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -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); } 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..8529ec4190d13 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -560,7 +560,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/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 8c66176942cb5..14273dd2e5e12 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -5670,7 +5670,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 +6016,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/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index ce2dd4d76368a..7276b74a43ebb 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); @@ -4015,7 +4016,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 +5715,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 +10641,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 +11223,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 +11719,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..1f03472d91a0f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2494,10 +2494,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/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 236cc3d9e8907..52a8e3fec539d 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); } } @@ -6737,7 +6737,7 @@ QualType CodeGenModule::getObjCFastEnumerationStateType() { } D->completeDefinition(); - ObjCFastEnumerationStateType = Context.getTagDeclType(D); + ObjCFastEnumerationStateType = Context.getCanonicalTagType(D); } return ObjCFastEnumerationStateType; @@ -7247,7 +7247,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 +7467,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 +7937,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/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index c98503e4bbd26..d0209e03808ee 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(); @@ -725,8 +726,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 +792,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]; @@ -830,7 +833,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()) diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index f4a99467010af..25f06050e59e7 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); } @@ -2016,7 +2016,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); @@ -3815,9 +3815,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()); @@ -4554,9 +4552,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 +4571,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 +5152,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/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index abb91486e7ee6..1d0645751480d 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2889,7 +2889,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, diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 51a6f6b779e77..63118d6bd5f12 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -273,26 +273,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 +283,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 +387,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 +416,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 +440,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/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..bb4ff93be0397 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, @@ -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()); diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp index 6a884f7be00e1..16dcf88cbded8 100644 --- a/clang/lib/Index/USRGeneration.cpp +++ b/clang/lib/Index/USRGeneration.cpp @@ -945,10 +945,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..5a5eba2ca10d6 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); } 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/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/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index f0f1d66f66e93..3ea5aa55c1e94 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); 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..5bd5d15c6709c 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -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; diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 83a07a23f3414..576074a1f4aeb 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; @@ -671,11 +668,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 +1066,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 +1095,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 +1123,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 +1278,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 +1634,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 +1723,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 +1771,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); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 6ac04837708f6..8e055aacf5b27 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); } @@ -118,12 +115,12 @@ 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(); } @@ -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; @@ -493,7 +487,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 +604,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 +618,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 +642,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 +721,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 +756,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 +814,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 +842,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 +890,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()); @@ -875,7 +907,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 +933,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; } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 01252a4bc69c6..41277a25410ef 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -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()) || diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5e523fe887318..223e2bc8a4a57 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)) @@ -7798,7 +7798,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)) @@ -8361,7 +8361,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); } } } @@ -9959,7 +9961,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); @@ -15110,10 +15112,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 +15123,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; @@ -15634,7 +15636,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 +15666,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..443cb146c0ff3 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -951,7 +951,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 +1055,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 +1072,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); } @@ -1664,7 +1665,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 +1691,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 +1748,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 +2015,6 @@ static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, Policy.AnonymousTagLocations = false; Policy.SuppressStrongLifetime = true; Policy.SuppressUnwrittenScope = true; - Policy.SuppressScope = true; Policy.CleanUglifiedParameters = true; return Policy; } @@ -2925,8 +2929,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 +3025,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; } @@ -3391,7 +3395,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 +3524,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; @@ -5177,7 +5179,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 +5194,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); @@ -5769,7 +5773,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). @@ -7026,7 +7030,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 +7817,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 +8409,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 +8586,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 +8703,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 +8771,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 +8885,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 +8922,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 +9023,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 +10040,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..6f09a7cbb6e64 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, @@ -1083,9 +1078,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..b8a49b324d9b2 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, @@ -530,20 +489,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' @@ -786,7 +803,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)) { @@ -1156,10 +1173,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 +2050,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 +2110,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 +2168,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 +2547,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 +2556,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 +2597,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 +2783,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 +2954,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 +5060,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; @@ -5754,7 +5798,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 +5818,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 +5881,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 +6000,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 +6295,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 +6317,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; } - } while ((SpecLoc = SpecLoc.getPrefix())); + 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; + } + 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 +9097,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)) { @@ -10763,7 +10819,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 +12323,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(); @@ -17478,6 +17534,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 +18000,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 +18010,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 +18142,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 +18385,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 +18473,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 +18506,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 +18622,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"); @@ -20398,7 +20463,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..efc99868c80d9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3766,7 +3766,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()) @@ -4713,7 +4715,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..7519fa91bd631 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( @@ -2666,7 +2676,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); @@ -3050,7 +3062,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 +3217,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 +4258,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 +4494,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 +4558,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 +4689,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 +4716,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 +4782,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 +4802,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 +5106,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 +5116,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 +5419,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); @@ -5928,16 +5956,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 +6078,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 +6892,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 +7024,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 +7047,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 +7202,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 +7358,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(), @@ -7782,9 +7807,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 +7844,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 +8303,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 +9004,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 +9027,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 +9058,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 +9511,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 +9937,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 +10270,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 +10318,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 +10337,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; @@ -10626,7 +10651,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 +11081,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 +11455,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 +11723,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 +12029,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 +12169,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 +12302,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) { @@ -12584,7 +12593,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 +12878,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 { @@ -13051,7 +13060,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 +13163,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 +13229,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 +13375,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; } @@ -13410,7 +13415,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 = @@ -14003,7 +14008,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 +14139,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 +14424,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); @@ -15042,9 +15045,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 +15306,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 +15317,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 +15403,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 +15695,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 +15706,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 +15798,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 +15945,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); @@ -16639,10 +16646,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 +16689,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 +16729,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 +17961,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 +18280,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 +18787,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())) diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index bbd104909956f..d228f432f0e1b 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); 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..feaf1749c842f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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()); @@ -2831,8 +2828,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 +2938,28 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( } if (const TypeDecl *TD = R.getAsSingle()) { - QualType Ty = Context.getTypeDeclType(TD); - QualType ET = getElaboratedType(ElaboratedTypeKeyword::None, SS, Ty); + QualType ET; + TypeLocBuilder TLB; + if (auto *TagD = dyn_cast(TD)) { + ET = SemaRef.Context.getTagType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TagD, + /*OwnsTag=*/false); + auto TL = TLB.push(ET); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameInfo.getLoc()); + } else if (auto *TypedefD = dyn_cast(TD)) { + ET = SemaRef.Context.getTypedefType(ElaboratedTypeKeyword::None, + SS.getScopeRep(), TypedefD); + TLB.push(ET).set( + /*ElaboratedKeywordLoc=*/SourceLocation(), + SS.getWithLocInContext(Context), NameInfo.getLoc()); + } else { + // FIXME: What else can appear here? + ET = SemaRef.Context.getTypeDeclType(TD); + TLB.pushTypeSpec(ET).setNameLoc(NameInfo.getLoc()); + assert(SS.isEmpty()); + } // Diagnose a missing typename if this resolved unambiguously to a type in // a dependent context. If we can recover with a type, downgrade this to @@ -2964,13 +2980,6 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( D << FixItHint::CreateInsertion(Loc, "typename "); // Recover by pretending this was an elaborated type. - TypeLocBuilder TLB; - TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc()); - - ElaboratedTypeLoc QTL = TLB.push(ET); - QTL.setElaboratedKeywordLoc(SourceLocation()); - QTL.setQualifierLoc(SS.getWithLocInContext(Context)); - *RecoveryTSI = TLB.getTypeSourceInfo(Context, ET); return ExprEmpty(); @@ -3001,7 +3010,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 @@ -4482,9 +4491,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 +5882,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; } @@ -12457,7 +12463,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())); @@ -16211,8 +16217,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() @@ -16923,7 +16929,7 @@ ExprResult Sema::ActOnSourceLocExpr(SourceLocIdentKind Kind, return ExprError(); } ResultTy = Context.getPointerType( - Context.getRecordType(StdSourceLocationImplDecl).withConst()); + Context.getCanonicalTagType(StdSourceLocationImplDecl).withConst()); break; } @@ -21239,16 +21245,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..da17134bf39a6 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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)); } } @@ -374,7 +373,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 +418,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 +435,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; @@ -659,7 +660,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 +1215,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 +1245,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 +1733,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 +1861,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; } @@ -2505,7 +2506,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 +2967,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) @@ -3426,7 +3427,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 +3484,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 +3594,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 +3628,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: @@ -4574,7 +4575,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; @@ -5370,16 +5371,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 +6187,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 +6360,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, return QualType(); Steps.emplace_back(Step::MemberPointer, - Context.getTypeDeclType(Cls).getTypePtr()); + Context.getCanonicalTagType(Cls).getTypePtr()); continue; } @@ -7243,16 +7246,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 +7296,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(); 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..b8d548d3416d8 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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 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..f8012c450973d 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -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()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1c6f292454ed6..345a23ae99511 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); @@ -1140,14 +1139,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) { @@ -1442,7 +1433,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 +2311,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 +2880,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 +4328,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); } @@ -8808,8 +8799,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,24 +9199,26 @@ 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); @@ -9233,7 +9226,7 @@ bool InitializationSequence::Diagnose(Sema &S, = Entity.getType()->getAs()) S.Diag(Record->getDecl()->getLocation(), diag::note_previous_decl) - << S.Context.getTagDeclType(Record->getDecl()); + << S.Context.getCanonicalTagType(Record->getOriginalDecl()); } break; } @@ -9300,11 +9293,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 +10150,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 +10290,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..56bebb213e3e9 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; @@ -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..b00f61d9c00f6 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(); } @@ -2731,7 +2729,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, @@ -2772,10 +2772,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 +3103,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 @@ -3438,7 +3440,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 +3647,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); } @@ -4853,7 +4855,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 +4866,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); } @@ -5463,7 +5464,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/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 4ecc9b0d4c5c8..738692755a0ab 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 diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5dd5b495480d9..7ce6c52fc4f7a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1268,7 +1268,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 +1471,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 +2292,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 && @@ -2679,8 +2678,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 +3345,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(); @@ -3658,8 +3656,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; @@ -5934,7 +5931,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. @@ -7160,7 +7157,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 +7179,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 +7401,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 +8157,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; }; @@ -9009,8 +9002,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; @@ -10955,9 +10948,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 +14856,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 +15018,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 +15401,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 +15871,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(); @@ -16541,7 +16534,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 @@ -16686,7 +16679,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(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f85826aecadf3..aa03d36bb69f2 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; @@ -1719,6 +1719,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (!hasCasesNotInSwitch) SS->setAllEnumCasesCovered(); } + enum_out:; } if (BodyStmt) @@ -4619,7 +4620,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 +4663,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 +4686,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..ceca15dd3e388 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) @@ -919,7 +919,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(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 698d1270be634..68f637fd8eab2 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -397,7 +397,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 +799,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 +909,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 +926,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 +969,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); @@ -2139,12 +2138,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 +2628,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 +2669,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 @@ -3100,7 +3097,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 +3106,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 +3121,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(); @@ -3287,11 +3286,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 +3336,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 +3373,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 +3494,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 +3559,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 +3611,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 +3690,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 +3730,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 +3780,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 +3791,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 +3840,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 +3851,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; @@ -3903,12 +3917,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 +3933,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,18 +3990,8 @@ 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); @@ -4022,21 +4013,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)); } @@ -5293,8 +5272,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 +5286,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; @@ -5897,8 +5876,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) { @@ -6270,11 +6249,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; } @@ -8690,7 +8668,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 +8683,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: @@ -8784,7 +8757,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 +8820,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 +9865,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 @@ -10255,7 +10232,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; } @@ -10914,7 +10891,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 +10902,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); } @@ -10999,19 +10969,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; } @@ -11116,6 +11100,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 +11116,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 +11139,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..902b97e99cc8a 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) { @@ -2853,13 +2846,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 +3068,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 +3427,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 +4097,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 +5053,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 +6373,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 +6383,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); @@ -6761,7 +6754,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 +6872,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..037001a0b2bbc 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))); @@ -327,7 +327,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 +593,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 +957,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 +974,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 +1049,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..163994c17caa6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1165,7 +1165,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() @@ -1649,22 +1649,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; } @@ -2083,37 +2079,6 @@ 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, @@ -2182,9 +2147,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 +3125,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()); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e2c3cdcd536bc..76da4deab1e9c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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, @@ -3907,7 +3897,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 +4809,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 +4846,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; } @@ -5754,11 +5739,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, 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 +6909,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,13 +6976,12 @@ 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()) 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(); @@ -7041,8 +7030,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 +7046,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..3d301624eb366 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: { @@ -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 { @@ -3462,7 +3459,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, if (DiagID != 0) { SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID) - << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + << SemaRef.Context.getCanonicalTagType(OwnedTagDecl); D.setInvalidType(true); } } @@ -5103,7 +5100,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 @@ -5900,7 +5897,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 +5970,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 +6021,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 +6079,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 +7067,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 +9205,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 +9345,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 +9385,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 +9525,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()) @@ -9630,15 +9661,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"); diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1d8687e4bf1c1..a541f1ff692bd 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; @@ -599,6 +598,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 +606,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 +625,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; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 10aedb68fcd9d..2e5e1b60f16de 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -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()); @@ -9583,12 +9598,6 @@ void ASTReader::AssignedLambdaNumbering(CXXRecordDecl *Lambda) { CXXRecordDecl *Previous = cast(Iter->second)->getMostRecentDecl(); Lambda->setPreviousDecl(Previous); - // FIXME: It will be best to use the Previous type when we creating the - // lambda directly. But that requires us to get the lambda context decl and - // lambda index before creating the lambda, which needs a drastic change in - // the parser. - const_cast(Lambda->TypeForDecl->CanonicalType) = - Previous->TypeForDecl->CanonicalType; return; } @@ -10534,12 +10543,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..ef7190da062ea 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) { 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..353e8a2daa925 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()); } @@ -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/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/LLVMConventionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 1cb3848cfed2a..29ed4ad171aec 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; 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..844316c4a8f7d 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 @@ -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..d53aad46d7699 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,8 +244,10 @@ 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; } @@ -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) { diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp index 98c587d62978b..3be2b19574e40 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(); diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index 34fcb9b64d555..e99816fa782d8 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -843,7 +843,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 +854,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/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..8372371aff368 100644 --- a/clang/lib/Tooling/Refactoring/Lookup.cpp +++ b/clang/lib/Tooling/Refactoring/Lookup.cpp @@ -217,7 +217,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..7d153ec958bef 100644 --- a/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp +++ b/clang/lib/Tooling/Refactoring/Rename/USRLocFinder.cpp @@ -203,8 +203,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 +217,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 +235,7 @@ class RenameLocFinder : public RecursiveASTVisitor { RenameInfos.push_back({StartLoc, EndLoc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, + /*Specifier=*/std::nullopt, /*IgnorePrefixQualifiers=*/true}); } } @@ -257,7 +257,7 @@ class RenameLocFinder : public RecursiveASTVisitor { RenameInfos.push_back({Loc, Loc, /*FromDecl=*/nullptr, /*Context=*/nullptr, - /*Specifier=*/nullptr, + /*Specifier=*/std::nullopt, /*IgnorePrefixQualifiers=*/true}); } } @@ -288,7 +288,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 +332,7 @@ class RenameLocFinder : public RecursiveASTVisitor { Decl, getClosestAncestorDecl(*Expr), Expr->getQualifier(), - /*IgnorePrefixQualifers=*/false}; + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } @@ -411,7 +411,7 @@ class RenameLocFinder : public RecursiveASTVisitor { TargetDecl, getClosestAncestorDecl(Loc), GetNestedNameForType(Loc), - /*IgnorePrefixQualifers=*/false}; + /*IgnorePrefixQualifiers=*/false}; RenameInfos.push_back(Info); } return true; @@ -421,33 +421,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 +453,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 +528,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..2e43714b16c1c 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -1328,7 +1328,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 +1391,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..27ab412e1e685 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1677,10 +1677,16 @@ 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)); @@ -1763,7 +1769,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 +1835,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 +1845,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. @@ -1883,13 +1892,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()); } @@ -5360,9 +5362,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/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index a6301daa672c3..a51efe28c0b01 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -1332,12 +1332,6 @@ 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()) diff --git a/clang/tools/libclang/CXIndexDataConsumer.cpp b/clang/tools/libclang/CXIndexDataConsumer.cpp index f0d92e8c40124..ebab5135605b6 100644 --- a/clang/tools/libclang/CXIndexDataConsumer.cpp +++ b/clang/tools/libclang/CXIndexDataConsumer.cpp @@ -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..3feb56334d79c 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); @@ -566,11 +567,7 @@ CXCursor clang_getTypeDeclaration(CXType CT) { D = cast(TP)->getDecl(); 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)); @@ -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.isCanonical()) + return MakeCXType(T, GetTU(CT)); return MakeCXType(QualType(), GetTU(CT)); }