From e0a22d06888c13989b3f72db319f1d498bf69153 Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 18 Oct 2011 21:02:43 +0000 Subject: [PATCH] Macro metaprogramming for builtin types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142420 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/BuiltinTypes.def | 203 +++++++++++++++++++++++++++++ include/clang/AST/Type.h | 83 +----------- lib/AST/ASTImporter.cpp | 63 ++------- lib/AST/Expr.cpp | 2 +- lib/AST/ExprClassification.cpp | 6 +- lib/AST/ItaniumMangle.cpp | 8 +- lib/AST/MicrosoftMangle.cpp | 14 +- lib/CodeGen/CGDebugInfo.cpp | 14 +- lib/Sema/SemaExpr.cpp | 35 +---- tools/libclang/CIndex.cpp | 2 +- 10 files changed, 244 insertions(+), 186 deletions(-) create mode 100644 include/clang/AST/BuiltinTypes.def diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def new file mode 100644 index 0000000000..067862c1c1 --- /dev/null +++ b/include/clang/AST/BuiltinTypes.def @@ -0,0 +1,203 @@ +//===-- BuiltinTypeNodes.def - Metadata about BuiltinTypes ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the database about various builtin singleton types. +// +// BuiltinType::Id is the enumerator defining the type. +// +// Context.SingletonId is the global singleton of this type. Some global +// singletons are shared by multiple types. +// +// BUILTIN_TYPE(Id, SingletonId) - A builtin type that has not been +// covered by any other #define. Defining this macro covers all +// the builtins. +// +// SIGNED_TYPE(Id, SingletonId) - A signed integral type. +// +// UNSIGNED_TYPE(Id, SingletonId) - An unsigned integral type. +// +// FLOATING_TYPE(Id, SingletonId) - A floating-point type. +// +// PLACEHOLDER_TYPE(Id, SingletonId) - A placeholder type. Placeholder +// types are used to perform context-sensitive checking of specific +// forms of expression. +// +// SHARED_SINGLETON_TYPE(Expansion) - The given expansion corresponds +// to a builtin which uses a shared singleton type. +// +//===----------------------------------------------------------------------===// + +#ifndef SIGNED_TYPE +#define SIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef UNSIGNED_TYPE +#define UNSIGNED_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef FLOATING_TYPE +#define FLOATING_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef PLACEHOLDER_TYPE +#define PLACEHOLDER_TYPE(Id, SingletonId) BUILTIN_TYPE(Id, SingletonId) +#endif + +#ifndef SHARED_SINGLETON_TYPE +#define SHARED_SINGLETON_TYPE(Expansion) Expansion +#endif + +//===- Builtin Types ------------------------------------------------------===// + +// void +BUILTIN_TYPE(Void, VoidTy) + +//===- Unsigned Types -----------------------------------------------------===// + +// 'bool' in C++, '_Bool' in C99 +UNSIGNED_TYPE(Bool, BoolTy) + +// 'char' for targets where it's unsigned +SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(Char_U, CharTy)) + +// 'unsigned char', explicitly qualified +UNSIGNED_TYPE(UChar, UnsignedCharTy) + +// 'wchar_t' for targets where it's unsigned +SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) + +// 'char16_t' in C++ +UNSIGNED_TYPE(Char16, Char16Ty) + +// 'char32_t' in C++ +UNSIGNED_TYPE(Char32, Char32Ty) + +// 'unsigned short' +UNSIGNED_TYPE(UShort, UnsignedShortTy) + +// 'unsigned int' +UNSIGNED_TYPE(UInt, UnsignedIntTy) + +// 'unsigned long' +UNSIGNED_TYPE(ULong, UnsignedLongTy) + +// 'unsigned long long' +UNSIGNED_TYPE(ULongLong, UnsignedLongLongTy) + +// '__uint128_t' +UNSIGNED_TYPE(UInt128, UnsignedInt128Ty) + +//===- Signed Types -------------------------------------------------------===// + +// 'char' for targets where it's signed +SHARED_SINGLETON_TYPE(SIGNED_TYPE(Char_S, CharTy)) + +// 'signed char', explicitly qualified +SIGNED_TYPE(SChar, SignedCharTy) + +// 'wchar_t' for targets where it's signed +SHARED_SINGLETON_TYPE(SIGNED_TYPE(WChar_S, WCharTy)) + +// 'short' or 'signed short' +SIGNED_TYPE(Short, ShortTy) + +// 'int' or 'signed int' +SIGNED_TYPE(Int, IntTy) + +// 'long' or 'signed long' +SIGNED_TYPE(Long, LongTy) + +// 'long long' or 'signed long long' +SIGNED_TYPE(LongLong, LongLongTy) + +// '__int128_t' +SIGNED_TYPE(Int128, Int128Ty) + +//===- Floating point types -----------------------------------------------===// + +// 'half' in OpenCL, '__fp16' in ARM NEON. +FLOATING_TYPE(Half, HalfTy) + +// 'float' +FLOATING_TYPE(Float, FloatTy) + +// 'double' +FLOATING_TYPE(Double, DoubleTy) + +// 'long double' +FLOATING_TYPE(LongDouble, LongDoubleTy) + +//===- Language-specific types --------------------------------------------===// + +// This is the type of C++0x 'nullptr'. +BUILTIN_TYPE(NullPtr, NullPtrTy) + +// The primitive Objective C 'id' type. The user-visible 'id' +// type is a typedef of an ObjCObjectPointerType to an +// ObjCObjectType with this as its base. In fact, this only ever +// shows up in an AST as the base type of an ObjCObjectType. +BUILTIN_TYPE(ObjCId, ObjCBuiltinIdTy) + +// The primitive Objective C 'Class' type. The user-visible +// 'Class' type is a typedef of an ObjCObjectPointerType to an +// ObjCObjectType with this as its base. In fact, this only ever +// shows up in an AST as the base type of an ObjCObjectType. +BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy) + +// The primitive Objective C 'SEL' type. The user-visible 'SEL' +// type is a typedef of a PointerType to this. +BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy) + +// This represents the type of an expression whose type is +// totally unknown, e.g. 'T::foo'. It is permitted for this to +// appear in situations where the structure of the type is +// theoretically deducible. +BUILTIN_TYPE(Dependent, DependentTy) + +// The type of an unresolved overload set. A placeholder type. +// Expressions with this type have one of the following basic +// forms, with parentheses generally permitted: +// foo # possibly qualified, not if an implicit access +// foo # possibly qualified, not if an implicit access +// &foo # possibly qualified, not if an implicit access +// x->foo # only if might be a static member function +// &x->foo # only if might be a static member function +// &Class::foo # when a pointer-to-member; sub-expr also has this type +// OverloadExpr::find can be used to analyze the expression. +PLACEHOLDER_TYPE(Overload, OverloadTy) + +// The type of a bound C++ non-static member function. +// A placeholder type. Expressions with this type have one of the +// following basic forms: +// foo # if an implicit access +// x->foo # if only contains non-static members +PLACEHOLDER_TYPE(BoundMember, BoundMemberTy) + +// __builtin_any_type. A placeholder type. Useful for clients +// like debuggers that don't know what type to give something. +// Only a small number of operations are valid on expressions of +// unknown type, most notably explicit casts. +PLACEHOLDER_TYPE(UnknownAny, UnknownAnyTy) + +// The type of a cast which, in ARC, would normally require a +// __bridge, but which might be okay depending on the immediate +// context. +PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy) + +#ifdef LAST_BUILTIN_TYPE +LAST_BUILTIN_TYPE(ARCUnbridgedCast) +#undef LAST_BUILTIN_TYPE +#endif + +#undef SHARED_SINGLETON_TYPE +#undef PLACEHOLDER_TYPE +#undef FLOATING_TYPE +#undef SIGNED_TYPE +#undef UNSIGNED_TYPE +#undef BUILTIN_TYPE diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index f0f78e279a..725ccc8eea 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1677,86 +1677,9 @@ template <> inline const Class##Type *Type::castAs() const { \ class BuiltinType : public Type { public: enum Kind { - Void, - - Bool, // This is bool and/or _Bool. - Char_U, // This is 'char' for targets where char is unsigned. - UChar, // This is explicitly qualified unsigned char. - WChar_U, // This is 'wchar_t' for C++, when unsigned. - Char16, // This is 'char16_t' for C++. - Char32, // This is 'char32_t' for C++. - UShort, - UInt, - ULong, - ULongLong, - UInt128, // __uint128_t - - Char_S, // This is 'char' for targets where char is signed. - SChar, // This is explicitly qualified signed char. - WChar_S, // This is 'wchar_t' for C++, when signed. - Short, - Int, - Long, - LongLong, - Int128, // __int128_t - - Half, // This is the 'half' type in OpenCL, - // __fp16 in case of ARM NEON. - Float, Double, LongDouble, - - NullPtr, // This is the type of C++0x 'nullptr'. - - /// The primitive Objective C 'id' type. The user-visible 'id' - /// type is a typedef of an ObjCObjectPointerType to an - /// ObjCObjectType with this as its base. In fact, this only ever - /// shows up in an AST as the base type of an ObjCObjectType. - ObjCId, - - /// The primitive Objective C 'Class' type. The user-visible - /// 'Class' type is a typedef of an ObjCObjectPointerType to an - /// ObjCObjectType with this as its base. In fact, this only ever - /// shows up in an AST as the base type of an ObjCObjectType. - ObjCClass, - - /// The primitive Objective C 'SEL' type. The user-visible 'SEL' - /// type is a typedef of a PointerType to this. - ObjCSel, - - /// This represents the type of an expression whose type is - /// totally unknown, e.g. 'T::foo'. It is permitted for this to - /// appear in situations where the structure of the type is - /// theoretically deducible. - Dependent, - - /// The type of an unresolved overload set. A placeholder type. - /// Expressions with this type have one of the following basic - /// forms, with parentheses generally permitted: - /// foo # possibly qualified, not if an implicit access - /// foo # possibly qualified, not if an implicit access - /// &foo # possibly qualified, not if an implicit access - /// x->foo # only if might be a static member function - /// &x->foo # only if might be a static member function - /// &Class::foo # when a pointer-to-member; sub-expr also has this type - /// OverloadExpr::find can be used to analyze the expression. - Overload, - - /// The type of a bound C++ non-static member function. - /// A placeholder type. Expressions with this type have one of the - /// following basic forms: - /// foo # if an implicit access - /// x->foo # if only contains non-static members - BoundMember, - - /// __builtin_any_type. A placeholder type. Useful for clients - /// like debuggers that don't know what type to give something. - /// Only a small number of operations are valid on expressions of - /// unknown type, most notably explicit casts. - UnknownAny, - - /// The type of a cast which, in ARC, would normally require a - /// __bridge, but which might be okay depending on the immediate - /// context. - ARCUnbridgedCast +#define BUILTIN_TYPE(Id, SingletonId) Id, +#define LAST_BUILTIN_TYPE(Id) LastKind = Id +#include "clang/AST/BuiltinTypes.def" }; public: diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 7e252d1d16..068425e250 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -1324,9 +1324,17 @@ QualType ASTNodeImporter::VisitType(const Type *T) { QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { switch (T->getKind()) { - case BuiltinType::Void: return Importer.getToContext().VoidTy; - case BuiltinType::Bool: return Importer.getToContext().BoolTy; - +#define SHARED_SINGLETON_TYPE(Expansion) +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: return Importer.getToContext().SingletonId; +#include "clang/AST/BuiltinTypes.def" + + // FIXME: for Char16, Char32, and NullPtr, make sure that the "to" + // context supports C++. + + // FIXME: for ObjCId, ObjCClass, and ObjCSel, make sure that the "to" + // context supports ObjC. + case BuiltinType::Char_U: // The context we're importing from has an unsigned 'char'. If we're // importing into a context with a signed 'char', translate to @@ -1336,23 +1344,6 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { return Importer.getToContext().CharTy; - case BuiltinType::UChar: return Importer.getToContext().UnsignedCharTy; - - case BuiltinType::Char16: - // FIXME: Make sure that the "to" context supports C++! - return Importer.getToContext().Char16Ty; - - case BuiltinType::Char32: - // FIXME: Make sure that the "to" context supports C++! - return Importer.getToContext().Char32Ty; - - case BuiltinType::UShort: return Importer.getToContext().UnsignedShortTy; - case BuiltinType::UInt: return Importer.getToContext().UnsignedIntTy; - case BuiltinType::ULong: return Importer.getToContext().UnsignedLongTy; - case BuiltinType::ULongLong: - return Importer.getToContext().UnsignedLongLongTy; - case BuiltinType::UInt128: return Importer.getToContext().UnsignedInt128Ty; - case BuiltinType::Char_S: // The context we're importing from has an unsigned 'char'. If we're // importing into a context with a signed 'char', translate to @@ -1362,43 +1353,11 @@ QualType ASTNodeImporter::VisitBuiltinType(const BuiltinType *T) { return Importer.getToContext().CharTy; - case BuiltinType::SChar: return Importer.getToContext().SignedCharTy; case BuiltinType::WChar_S: case BuiltinType::WChar_U: // FIXME: If not in C++, shall we translate to the C equivalent of // wchar_t? return Importer.getToContext().WCharTy; - - case BuiltinType::Short : return Importer.getToContext().ShortTy; - case BuiltinType::Int : return Importer.getToContext().IntTy; - case BuiltinType::Long : return Importer.getToContext().LongTy; - case BuiltinType::LongLong : return Importer.getToContext().LongLongTy; - case BuiltinType::Int128 : return Importer.getToContext().Int128Ty; - case BuiltinType::Half: return Importer.getToContext().HalfTy; - case BuiltinType::Float: return Importer.getToContext().FloatTy; - case BuiltinType::Double: return Importer.getToContext().DoubleTy; - case BuiltinType::LongDouble: return Importer.getToContext().LongDoubleTy; - - case BuiltinType::NullPtr: - // FIXME: Make sure that the "to" context supports C++0x! - return Importer.getToContext().NullPtrTy; - - case BuiltinType::Overload: return Importer.getToContext().OverloadTy; - case BuiltinType::Dependent: return Importer.getToContext().DependentTy; - case BuiltinType::UnknownAny: return Importer.getToContext().UnknownAnyTy; - case BuiltinType::BoundMember: return Importer.getToContext().BoundMemberTy; - case BuiltinType::ARCUnbridgedCast: - return Importer.getToContext().ARCUnbridgedCastTy; - - case BuiltinType::ObjCId: - // FIXME: Make sure that the "to" context supports Objective-C! - return Importer.getToContext().ObjCBuiltinIdTy; - - case BuiltinType::ObjCClass: - return Importer.getToContext().ObjCBuiltinClassTy; - - case BuiltinType::ObjCSel: - return Importer.getToContext().ObjCBuiltinSelTy; } return QualType(); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index b0bcfe09f6..427c331ed0 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1766,7 +1766,7 @@ bool Expr::isBoundMemberFunction(ASTContext &Ctx) const { } QualType Expr::findBoundMemberType(const Expr *expr) { - assert(expr->getType()->isSpecificPlaceholderType(BuiltinType::BoundMember)); + assert(expr->hasPlaceholderType(BuiltinType::BoundMember)); // Bound member expressions are always one of these possibilities: // x->m x.m x->*y x.*y diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 49c68213aa..594ae69ec4 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -480,14 +480,16 @@ static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { // is a pointer to a data member is of the same value category as its first // operand. if (E->getOpcode() == BO_PtrMemD) - return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + return (E->getType()->isFunctionType() || + E->hasPlaceholderType(BuiltinType::BoundMember)) ? Cl::CL_MemberFunction : ClassifyInternal(Ctx, E->getLHS()); // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its // second operand is a pointer to data member and a prvalue otherwise. if (E->getOpcode() == BO_PtrMemI) - return (E->getType()->isFunctionType() || E->getType() == Ctx.BoundMemberTy) + return (E->getType()->isFunctionType() || + E->hasPlaceholderType(BuiltinType::BoundMember)) ? Cl::CL_MemberFunction : Cl::CL_LValue; diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index f7af57ef66..889cf513bb 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1735,11 +1735,11 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::LongDouble: Out << 'e'; break; case BuiltinType::NullPtr: Out << "Dn"; break; - case BuiltinType::Overload: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::BoundMember: - case BuiltinType::UnknownAny: - case BuiltinType::ARCUnbridgedCast: llvm_unreachable("mangling a placeholder type"); break; case BuiltinType::ObjCId: Out << "11objc_object"; break; diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 98fc2d52cb..1a18ef1dc0 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -701,13 +701,13 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::WChar_S: case BuiltinType::WChar_U: Out << "_W"; break; - case BuiltinType::Overload: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - case BuiltinType::UnknownAny: - case BuiltinType::BoundMember: - case BuiltinType::ARCUnbridgedCast: - llvm_unreachable( - "Overloaded and dependent types shouldn't get to name mangling"); + llvm_unreachable("placeholder types shouldn't get to name mangling"); + case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; @@ -716,7 +716,7 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::Char32: case BuiltinType::Half: case BuiltinType::NullPtr: - llvm_unreachable("Don't know how to mangle this type"); + assert(0 && "Don't know how to mangle this type yet"); } } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index b894326bd8..d4b566bb20 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -321,16 +321,12 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { unsigned Encoding = 0; const char *BTName = NULL; switch (BT->getKind()) { +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - llvm_unreachable("Unexpected builtin type Dependent"); - case BuiltinType::Overload: - llvm_unreachable("Unexpected builtin type Overload"); - case BuiltinType::BoundMember: - llvm_unreachable("Unexpected builtin type BoundMember"); - case BuiltinType::UnknownAny: - llvm_unreachable("Unexpected builtin type UnknownAny"); - case BuiltinType::ARCUnbridgedCast: - llvm_unreachable("Unexpected builtin type ARCUnbridgedCast"); + llvm_unreachable("Unexpected builtin type"); case BuiltinType::NullPtr: return DBuilder. createNullPtrType(BT->getName(CGM.getContext().getLangOptions())); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d3a8ff95d2..5fd7e4e22b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10092,36 +10092,11 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { case BuiltinType::UnknownAny: return diagnoseUnknownAnyExpr(*this, E); - // Everything else should be impossible. TODO: metaprogram this. - case BuiltinType::Void: - case BuiltinType::Bool: - case BuiltinType::Char_U: - case BuiltinType::UChar: - case BuiltinType::WChar_U: - case BuiltinType::Char16: - case BuiltinType::Char32: - case BuiltinType::UShort: - case BuiltinType::UInt: - case BuiltinType::ULong: - case BuiltinType::ULongLong: - case BuiltinType::UInt128: - case BuiltinType::Char_S: - case BuiltinType::SChar: - case BuiltinType::WChar_S: - case BuiltinType::Short: - case BuiltinType::Int: - case BuiltinType::Long: - case BuiltinType::LongLong: - case BuiltinType::Int128: - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::Double: - case BuiltinType::LongDouble: - case BuiltinType::NullPtr: - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - case BuiltinType::Dependent: + // Everything else should be impossible. +#define BUILTIN_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#define PLACEHOLDER_TYPE(Id, SingletonId) +#include "clang/AST/BuiltinTypes.def" break; } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 46f8965902..e085a27c09 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1343,7 +1343,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { // Some builtin types (such as Objective-C's "id", "sel", and // "Class") have associated declarations. Create cursors for those. QualType VisitType; - switch (TL.getType()->getAs()->getKind()) { + switch (TL.getTypePtr()->getKind()) { case BuiltinType::Void: case BuiltinType::Bool: case BuiltinType::Char_U: -- 2.40.0