From d6903daf0da6979822b8981ea3641455ff6d06f8 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Tue, 16 Jul 2024 14:48:10 +0200 Subject: [PATCH 1/7] [Clang] Add __common_type builtin --- clang/include/clang/AST/ASTContext.h | 11 ++ clang/include/clang/AST/DeclID.h | 5 +- clang/include/clang/Basic/Builtins.h | 5 +- clang/include/clang/Sema/Sema.h | 4 + clang/lib/AST/ASTContext.cpp | 7 + clang/lib/AST/ASTImporter.cpp | 3 + clang/lib/AST/DeclTemplate.cpp | 53 ++++++ clang/lib/Lex/PPMacroExpansion.cpp | 1 + clang/lib/Sema/SemaChecking.cpp | 8 + clang/lib/Sema/SemaLookup.cpp | 4 + clang/lib/Sema/SemaTemplate.cpp | 160 +++++++++++++++++- clang/lib/Serialization/ASTReader.cpp | 3 + clang/lib/Serialization/ASTWriter.cpp | 2 + clang/test/SemaCXX/type-trait-common-type.cpp | 126 ++++++++++++++ libcxx/include/__type_traits/common_type.h | 16 +- libcxx/include/module.modulemap | 2 + 16 files changed, 404 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaCXX/type-trait-common-type.cpp diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 608bd90fcc3ff..d02e742297898 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -399,6 +399,9 @@ class ASTContext : public RefCountedBase { /// The identifier '__type_pack_element'. mutable IdentifierInfo *TypePackElementName = nullptr; + /// The identifier '__common_type'. + mutable IdentifierInfo *CommonTypeName = nullptr; + QualType ObjCConstantStringType; mutable RecordDecl *CFConstantStringTagDecl = nullptr; mutable TypedefDecl *CFConstantStringTypeDecl = nullptr; @@ -606,6 +609,7 @@ class ASTContext : public RefCountedBase { mutable ExternCContextDecl *ExternCContext = nullptr; mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr; mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr; + mutable BuiltinTemplateDecl *CommonTypeDecl = nullptr; /// The associated SourceManager object. SourceManager &SourceMgr; @@ -1107,6 +1111,7 @@ class ASTContext : public RefCountedBase { ExternCContextDecl *getExternCContextDecl() const; BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; BuiltinTemplateDecl *getTypePackElementDecl() const; + BuiltinTemplateDecl *getCommonTypeDecl() const; // Builtin Types. CanQualType VoidTy; @@ -1984,6 +1989,12 @@ class ASTContext : public RefCountedBase { return TypePackElementName; } + IdentifierInfo *getCommonTypeName() const { + if (!CommonTypeName) + CommonTypeName = &Idents.get("__common_type"); + return CommonTypeName; + } + /// Retrieve the Objective-C "instancetype" type, if already known; /// otherwise, returns a NULL type; QualType getObjCInstanceType() { diff --git a/clang/include/clang/AST/DeclID.h b/clang/include/clang/AST/DeclID.h index e5e27389fac60..875e9a72b3951 100644 --- a/clang/include/clang/AST/DeclID.h +++ b/clang/include/clang/AST/DeclID.h @@ -84,13 +84,16 @@ enum PredefinedDeclIDs { /// The internal '__type_pack_element' template. PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17, + + /// The internal '__common_type' template. + PREDEF_DECL_COMMON_TYPE_ID = 18, }; /// The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. -const unsigned int NUM_PREDEF_DECL_IDS = 18; +const unsigned int NUM_PREDEF_DECL_IDS = 19; /// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means /// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index e85ec5b2dca14..4353b72f71383 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -309,7 +309,10 @@ enum BuiltinTemplateKind : int { BTK__make_integer_seq, /// This names the __type_pack_element BuiltinTemplateDecl. - BTK__type_pack_element + BTK__type_pack_element, + + /// This names the __common_type BuiltinTemplateDecl. + BTK__common_type, }; } // end namespace clang diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 3cb1aa935fe46..5c7945c4c5c58 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2282,6 +2282,10 @@ class Sema final : public SemaBase { /// Check to see if a given expression could have '.c_str()' called on it. bool hasCStrMethod(const Expr *E); + // Check whether a type member 'Type::Name' exists, and if yes, return the + // type. If there is no type, the QualType is null + QualType getTypeMember(StringRef Name, QualType Type); + /// Diagnose pointers that are always non-null. /// \param E the expression containing the pointer /// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index a8e599f7ebe04..b8b4f426ff96c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1170,6 +1170,13 @@ ASTContext::getTypePackElementDecl() const { return TypePackElementDecl; } +BuiltinTemplateDecl *ASTContext::getCommonTypeDecl() const { + if (!CommonTypeDecl) + CommonTypeDecl = + buildBuiltinTemplateDecl(BTK__common_type, getCommonTypeName()); + return CommonTypeDecl; +} + RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK) const { SourceLocation Loc; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 0c27f6f5df2da..e4515e19a49a3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5408,6 +5408,9 @@ ExpectedDecl ASTNodeImporter::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { case BuiltinTemplateKind::BTK__type_pack_element: ToD = Importer.getToContext().getTypePackElementDecl(); break; + case BuiltinTemplateKind::BTK__common_type: + ToD = Importer.getToContext().getCommonTypeDecl(); + break; } assert(ToD && "BuiltinTemplateDecl of unsupported kind!"); Importer.MapImported(D, ToD); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 722c7fcf0b0df..d290c91fb8290 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1599,6 +1599,57 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { nullptr); } +static TemplateParameterList *createCommonTypeList(const ASTContext &C, + DeclContext *DC) { + // class... Args + auto *Args = TemplateTypeParmDecl::Create( + C, DC, {}, {}, /*Depth=*/1, /*Position=*/0, /*Id=*/nullptr, + /*Typename=*/false, /*ParameterPack=*/true); + Args->setImplicit(); + + // + auto *BaseTemplateList = + TemplateParameterList::Create(C, {}, {}, Args, {}, nullptr); + + // template class BaseTemplate + auto *BaseTemplate = TemplateTemplateParmDecl::Create( + C, DC, {}, /*Depth=*/0, /*Position=*/0, /*ParameterPack=*/false, {}, + /*Typename=*/false, BaseTemplateList); + + // class TypeMember + auto *TypeMember = TemplateTypeParmDecl::Create( + C, DC, {}, {}, /*Depth=*/1, /*Position=*/0, /*Id=*/nullptr, + /*Typename=*/false, /*ParameterPack=*/false); + + // + auto *HasTypeMemberList = + TemplateParameterList::Create(C, {}, {}, TypeMember, {}, nullptr); + + // template class HasTypeMember + auto *HasTypeMember = + TemplateTemplateParmDecl::Create(C, DC, {}, /*Depth=*/0, /*Position=*/1, + /*ParameterPack=*/false, {}, + /*Typename=*/false, HasTypeMemberList); + + // class HasNoTypeMember + auto *HasNoTypeMember = TemplateTypeParmDecl::Create( + C, DC, {}, {}, /*Depth=*/0, /*Position=*/2, /*Id=*/nullptr, + /*Typename=*/false, /*ParameterPack=*/false); + + // class... Ts + auto *Ts = TemplateTypeParmDecl::Create( + C, DC, {}, {}, /*Depth=*/0, /*Position=*/3, + /*Id=*/nullptr, /*Typename=*/false, /*ParameterPack=*/true); + Ts->setImplicit(); + + // template