Macro metaprogramming for builtin types.

llvm-svn: 142420
This commit is contained in:
John McCall
2011-10-18 21:02:43 +00:00
parent 0bf8a492fd
commit e314e27c58
10 changed files with 244 additions and 186 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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");
}
}

View File

@@ -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()));

View File

@@ -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;
}

View File

@@ -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<BuiltinType>()->getKind()) {
switch (TL.getTypePtr()->getKind()) {
case BuiltinType::Void:
case BuiltinType::Bool:
case BuiltinType::Char_U: