[cfe-commits] r170431 [1/3] - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ lib/Serialization/ test/CodeGenOpenCL/ test/PCH/ test/Parser/ tools/libclang/
Guy Benyei
guy.benyei at intel.com
Tue Dec 18 06:30:41 PST 2012
Author: gbenyei
Date: Tue Dec 18 08:30:41 2012
New Revision: 170431
URL: http://llvm.org/viewvc/llvm-project?rev=170431&view=rev
Log:
Revert changes from r170428, as I accidentally changed the line endings of these files to Windows style.
Removed:
cfe/trunk/test/CodeGenOpenCL/opencl_types.cl
cfe/trunk/test/PCH/ocl_types.cl
cfe/trunk/test/PCH/ocl_types.h
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/BuiltinTypes.def
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/Specifiers.h
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/ItaniumMangle.cpp
cfe/trunk/lib/AST/MicrosoftMangle.cpp
cfe/trunk/lib/AST/NSAPI.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/AST/TypeLoc.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
cfe/trunk/lib/CodeGen/CGOpenCLRuntime.cpp
cfe/trunk/lib/CodeGen/CGOpenCLRuntime.h
cfe/trunk/lib/CodeGen/CGRTTI.cpp
cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseTentative.cpp
cfe/trunk/lib/Sema/DeclSpec.cpp
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Serialization/ASTCommon.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/test/Parser/opencl-image-access.cl
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/CIndexUSRs.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Dec 18 08:30:41 2012
@@ -716,9 +716,6 @@
CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
CanQualType ObjCBuiltinBoolTy;
- CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy;
- CanQualType OCLImage2dTy, OCLImage2dArrayTy;
- CanQualType OCLImage3dTy;
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
mutable QualType AutoDeductTy; // Deduction against 'auto'.
Modified: cfe/trunk/include/clang/AST/BuiltinTypes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/BuiltinTypes.def?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/BuiltinTypes.def (original)
+++ cfe/trunk/include/clang/AST/BuiltinTypes.def Tue Dec 18 08:30:41 2012
@@ -1,234 +1,226 @@
-//===-- 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)
-
-// OpenCL image types.
-BUILTIN_TYPE(OCLImage1d, OCLImage1dTy)
-BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy)
-BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy)
-BUILTIN_TYPE(OCLImage2d, OCLImage2dTy)
-BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy)
-BUILTIN_TYPE(OCLImage3d, OCLImage3dTy)
-
-// 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.
-//
-// Overload should be the first placeholder type, or else change
-// BuiltinType::isNonOverloadPlaceholderType()
-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)
-
-// The type of an expression which refers to a pseudo-object,
-// such as those introduced by Objective C's @property or
-// VS.NET's __property declarations. A placeholder type. The
-// pseudo-object is actually accessed by emitting a call to
-// some sort of function or method; typically there is a pair
-// of a setter and a getter, with the setter used if the
-// pseudo-object reference is used syntactically as the
-// left-hand-side of an assignment operator.
-//
-// A pseudo-object reference naming an Objective-C @property is
-// always a dot access with a base of object-pointer type,
-// e.g. 'x.foo'.
-//
-// In VS.NET, a __property declaration creates an implicit
-// member with an associated name, which can then be named
-// in any of the normal ways an ordinary member could be.
-PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
-
-// __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)
-
-PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
-
-// 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
+//===-- 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.
+//
+// Overload should be the first placeholder type, or else change
+// BuiltinType::isNonOverloadPlaceholderType()
+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)
+
+// The type of an expression which refers to a pseudo-object,
+// such as those introduced by Objective C's @property or
+// VS.NET's __property declarations. A placeholder type. The
+// pseudo-object is actually accessed by emitting a call to
+// some sort of function or method; typically there is a pair
+// of a setter and a getter, with the setter used if the
+// pseudo-object reference is used syntactically as the
+// left-hand-side of an assignment operator.
+//
+// A pseudo-object reference naming an Objective-C @property is
+// always a dot access with a base of object-pointer type,
+// e.g. 'x.foo'.
+//
+// In VS.NET, a __property declaration creates an implicit
+// member with an associated name, which can then be named
+// in any of the normal ways an ordinary member could be.
+PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
+
+// __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)
+
+PLACEHOLDER_TYPE(BuiltinFn, BuiltinFnTy)
+
+// 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
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Tue Dec 18 08:30:41 2012
@@ -1580,17 +1580,6 @@
bool isNullPtrType() const; // C++0x nullptr_t
bool isAtomicType() const; // C11 _Atomic()
- bool isImage1dT() const; // OpenCL image1d_t
- bool isImage1dArrayT() const; // OpenCL image1d_array_t
- bool isImage1dBufferT() const; // OpenCL image1d_buffer_t
- bool isImage2dT() const; // OpenCL image2d_t
- bool isImage2dArrayT() const; // OpenCL image2d_array_t
- bool isImage3dT() const; // OpenCL image3d_t
-
- bool isImageType() const; // Any OpenCL image type
-
- bool isOpenCLSpecificType() const; // Any OpenCL specific type
-
/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
/// than implicitly __strong.
@@ -4894,40 +4883,6 @@
inline bool Type::isObjCBuiltinType() const {
return isObjCIdType() || isObjCClassType() || isObjCSelType();
}
-
-inline bool Type::isImage1dT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage1d);
-}
-
-inline bool Type::isImage1dArrayT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage1dArray);
-}
-
-inline bool Type::isImage1dBufferT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage1dBuffer);
-}
-
-inline bool Type::isImage2dT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage2d);
-}
-
-inline bool Type::isImage2dArrayT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage2dArray);
-}
-
-inline bool Type::isImage3dT() const {
- return isSpecificBuiltinType(BuiltinType::OCLImage3d);
-}
-inline bool Type::isImageType() const {
- return isImage3dT() ||
- isImage2dT() || isImage2dArrayT() ||
- isImage1dT() || isImage1dArrayT() || isImage1dBufferT();
-}
-
-inline bool Type::isOpenCLSpecificType() const {
- return isImageType();
-}
-
inline bool Type::isTemplateTypeParmType() const {
return isa<TemplateTypeParmType>(CanonicalType);
}
Modified: cfe/trunk/include/clang/Basic/Specifiers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Specifiers.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Specifiers.h (original)
+++ cfe/trunk/include/clang/Basic/Specifiers.h Tue Dec 18 08:30:41 2012
@@ -1,200 +1,194 @@
-//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Defines various enumerations that describe declaration and
-/// type specifiers.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
-#define LLVM_CLANG_BASIC_SPECIFIERS_H
-
-namespace clang {
- /// \brief Specifies the width of a type, e.g., short, long, or long long.
- enum TypeSpecifierWidth {
- TSW_unspecified,
- TSW_short,
- TSW_long,
- TSW_longlong
- };
-
- /// \brief Specifies the signedness of a type, e.g., signed or unsigned.
- enum TypeSpecifierSign {
- TSS_unspecified,
- TSS_signed,
- TSS_unsigned
- };
-
- /// \brief Specifies the kind of type.
- enum TypeSpecifierType {
- TST_unspecified,
- TST_void,
- TST_char,
- TST_wchar, // C++ wchar_t
- TST_char16, // C++0x char16_t
- TST_char32, // C++0x char32_t
- TST_int,
- TST_int128,
- TST_half, // OpenCL half, ARM NEON __fp16
- TST_float,
- TST_double,
- TST_bool, // _Bool
- TST_decimal32, // _Decimal32
- TST_decimal64, // _Decimal64
- TST_decimal128, // _Decimal128
- TST_enum,
- TST_union,
- TST_struct,
- TST_class, // C++ class type
- TST_interface, // C++ (Microsoft-specific) __interface type
- TST_typename, // Typedef, C++ class-name or enum name, etc.
- TST_typeofType,
- TST_typeofExpr,
- TST_decltype, // C++0x decltype
- TST_underlyingType, // __underlying_type for C++0x
- TST_auto, // C++0x auto
- TST_unknown_anytype, // __unknown_anytype extension
- TST_atomic, // C11 _Atomic
- TST_image1d_t, // OpenCL image1d_t
- TST_image1d_array_t, // OpenCL image1d_array_t
- TST_image1d_buffer_t, // OpenCL image1d_buffer_t
- TST_image2d_t, // OpenCL image2d_t
- TST_image2d_array_t, // OpenCL image2d_array_t
- TST_image3d_t, // OpenCL image3d_t
- TST_error // erroneous type
- };
-
- /// \brief Structure that packs information about the type specifiers that
- /// were written in a particular type specifier sequence.
- struct WrittenBuiltinSpecs {
- /*DeclSpec::TST*/ unsigned Type : 6;
- /*DeclSpec::TSS*/ unsigned Sign : 2;
- /*DeclSpec::TSW*/ unsigned Width : 2;
- bool ModeAttr : 1;
- };
-
- /// \brief A C++ access specifier (public, private, protected), plus the
- /// special value "none" which means different things in different contexts.
- enum AccessSpecifier {
- AS_public,
- AS_protected,
- AS_private,
- AS_none
- };
-
- /// \brief The categorization of expression values, currently following the
- /// C++11 scheme.
- enum ExprValueKind {
- /// \brief An r-value expression (a pr-value in the C++11 taxonomy)
- /// produces a temporary value.
- VK_RValue,
-
- /// \brief An l-value expression is a reference to an object with
- /// independent storage.
- VK_LValue,
-
- /// \brief An x-value expression is a reference to an object with
- /// independent storage but which can be "moved", i.e.
- /// efficiently cannibalized for its resources.
- VK_XValue
- };
-
- /// \brief A further classification of the kind of object referenced by an
- /// l-value or x-value.
- enum ExprObjectKind {
- /// An ordinary object is located at an address in memory.
- OK_Ordinary,
-
- /// A bitfield object is a bitfield on a C or C++ record.
- OK_BitField,
-
- /// A vector component is an element or range of elements on a vector.
- OK_VectorComponent,
-
- /// An Objective-C property is a logical field of an Objective-C
- /// object which is read and written via Objective-C method calls.
- OK_ObjCProperty,
-
- /// An Objective-C array/dictionary subscripting which reads an
- /// object or writes at the subscripted array/dictionary element via
- /// Objective-C method calls.
- OK_ObjCSubscript
- };
-
- // \brief Describes the kind of template specialization that a
- // particular template specialization declaration represents.
- enum TemplateSpecializationKind {
- /// This template specialization was formed from a template-id but
- /// has not yet been declared, defined, or instantiated.
- TSK_Undeclared = 0,
- /// This template specialization was implicitly instantiated from a
- /// template. (C++ [temp.inst]).
- TSK_ImplicitInstantiation,
- /// This template specialization was declared or defined by an
- /// explicit specialization (C++ [temp.expl.spec]) or partial
- /// specialization (C++ [temp.class.spec]).
- TSK_ExplicitSpecialization,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation declaration request
- /// (C++0x [temp.explicit]).
- TSK_ExplicitInstantiationDeclaration,
- /// This template specialization was instantiated from a template
- /// due to an explicit instantiation definition request
- /// (C++ [temp.explicit]).
- TSK_ExplicitInstantiationDefinition
- };
-
- /// \brief Storage classes.
- enum StorageClass {
- // These are legal on both functions and variables.
- SC_None,
- SC_Extern,
- SC_Static,
- SC_PrivateExtern,
-
- // These are only legal on variables.
- SC_OpenCLWorkGroupLocal,
- SC_Auto,
- SC_Register
- };
-
- /// \brief Checks whether the given storage class is legal for functions.
- inline bool isLegalForFunction(StorageClass SC) {
- return SC <= SC_PrivateExtern;
- }
-
- /// \brief Checks whether the given storage class is legal for variables.
- inline bool isLegalForVariable(StorageClass SC) {
- return true;
- }
-
- /// \brief In-class initialization styles for non-static data members.
- enum InClassInitStyle {
- ICIS_NoInit, ///< No in-class initializer.
- ICIS_CopyInit, ///< Copy initialization.
- ICIS_ListInit ///< Direct list-initialization.
- };
-
- /// \brief CallingConv - Specifies the calling convention that a function uses.
- enum CallingConv {
- CC_Default,
- CC_C, // __attribute__((cdecl))
- CC_X86StdCall, // __attribute__((stdcall))
- CC_X86FastCall, // __attribute__((fastcall))
- CC_X86ThisCall, // __attribute__((thiscall))
- CC_X86Pascal, // __attribute__((pascal))
- CC_AAPCS, // __attribute__((pcs("aapcs")))
- CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
- CC_PnaclCall // __attribute__((pnaclcall))
- };
-
-} // end namespace clang
-
-#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
+//===--- Specifiers.h - Declaration and Type Specifiers ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines various enumerations that describe declaration and
+/// type specifiers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_SPECIFIERS_H
+#define LLVM_CLANG_BASIC_SPECIFIERS_H
+
+namespace clang {
+ /// \brief Specifies the width of a type, e.g., short, long, or long long.
+ enum TypeSpecifierWidth {
+ TSW_unspecified,
+ TSW_short,
+ TSW_long,
+ TSW_longlong
+ };
+
+ /// \brief Specifies the signedness of a type, e.g., signed or unsigned.
+ enum TypeSpecifierSign {
+ TSS_unspecified,
+ TSS_signed,
+ TSS_unsigned
+ };
+
+ /// \brief Specifies the kind of type.
+ enum TypeSpecifierType {
+ TST_unspecified,
+ TST_void,
+ TST_char,
+ TST_wchar, // C++ wchar_t
+ TST_char16, // C++0x char16_t
+ TST_char32, // C++0x char32_t
+ TST_int,
+ TST_int128,
+ TST_half, // OpenCL half, ARM NEON __fp16
+ TST_float,
+ TST_double,
+ TST_bool, // _Bool
+ TST_decimal32, // _Decimal32
+ TST_decimal64, // _Decimal64
+ TST_decimal128, // _Decimal128
+ TST_enum,
+ TST_union,
+ TST_struct,
+ TST_class, // C++ class type
+ TST_interface, // C++ (Microsoft-specific) __interface type
+ TST_typename, // Typedef, C++ class-name or enum name, etc.
+ TST_typeofType,
+ TST_typeofExpr,
+ TST_decltype, // C++0x decltype
+ TST_underlyingType, // __underlying_type for C++0x
+ TST_auto, // C++0x auto
+ TST_unknown_anytype, // __unknown_anytype extension
+ TST_atomic, // C11 _Atomic
+ TST_error // erroneous type
+ };
+
+ /// \brief Structure that packs information about the type specifiers that
+ /// were written in a particular type specifier sequence.
+ struct WrittenBuiltinSpecs {
+ /*DeclSpec::TST*/ unsigned Type : 5;
+ /*DeclSpec::TSS*/ unsigned Sign : 2;
+ /*DeclSpec::TSW*/ unsigned Width : 2;
+ bool ModeAttr : 1;
+ };
+
+ /// \brief A C++ access specifier (public, private, protected), plus the
+ /// special value "none" which means different things in different contexts.
+ enum AccessSpecifier {
+ AS_public,
+ AS_protected,
+ AS_private,
+ AS_none
+ };
+
+ /// \brief The categorization of expression values, currently following the
+ /// C++11 scheme.
+ enum ExprValueKind {
+ /// \brief An r-value expression (a pr-value in the C++11 taxonomy)
+ /// produces a temporary value.
+ VK_RValue,
+
+ /// \brief An l-value expression is a reference to an object with
+ /// independent storage.
+ VK_LValue,
+
+ /// \brief An x-value expression is a reference to an object with
+ /// independent storage but which can be "moved", i.e.
+ /// efficiently cannibalized for its resources.
+ VK_XValue
+ };
+
+ /// \brief A further classification of the kind of object referenced by an
+ /// l-value or x-value.
+ enum ExprObjectKind {
+ /// An ordinary object is located at an address in memory.
+ OK_Ordinary,
+
+ /// A bitfield object is a bitfield on a C or C++ record.
+ OK_BitField,
+
+ /// A vector component is an element or range of elements on a vector.
+ OK_VectorComponent,
+
+ /// An Objective-C property is a logical field of an Objective-C
+ /// object which is read and written via Objective-C method calls.
+ OK_ObjCProperty,
+
+ /// An Objective-C array/dictionary subscripting which reads an
+ /// object or writes at the subscripted array/dictionary element via
+ /// Objective-C method calls.
+ OK_ObjCSubscript
+ };
+
+ // \brief Describes the kind of template specialization that a
+ // particular template specialization declaration represents.
+ enum TemplateSpecializationKind {
+ /// This template specialization was formed from a template-id but
+ /// has not yet been declared, defined, or instantiated.
+ TSK_Undeclared = 0,
+ /// This template specialization was implicitly instantiated from a
+ /// template. (C++ [temp.inst]).
+ TSK_ImplicitInstantiation,
+ /// This template specialization was declared or defined by an
+ /// explicit specialization (C++ [temp.expl.spec]) or partial
+ /// specialization (C++ [temp.class.spec]).
+ TSK_ExplicitSpecialization,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation declaration request
+ /// (C++0x [temp.explicit]).
+ TSK_ExplicitInstantiationDeclaration,
+ /// This template specialization was instantiated from a template
+ /// due to an explicit instantiation definition request
+ /// (C++ [temp.explicit]).
+ TSK_ExplicitInstantiationDefinition
+ };
+
+ /// \brief Storage classes.
+ enum StorageClass {
+ // These are legal on both functions and variables.
+ SC_None,
+ SC_Extern,
+ SC_Static,
+ SC_PrivateExtern,
+
+ // These are only legal on variables.
+ SC_OpenCLWorkGroupLocal,
+ SC_Auto,
+ SC_Register
+ };
+
+ /// \brief Checks whether the given storage class is legal for functions.
+ inline bool isLegalForFunction(StorageClass SC) {
+ return SC <= SC_PrivateExtern;
+ }
+
+ /// \brief Checks whether the given storage class is legal for variables.
+ inline bool isLegalForVariable(StorageClass SC) {
+ return true;
+ }
+
+ /// \brief In-class initialization styles for non-static data members.
+ enum InClassInitStyle {
+ ICIS_NoInit, ///< No in-class initializer.
+ ICIS_CopyInit, ///< Copy initialization.
+ ICIS_ListInit ///< Direct list-initialization.
+ };
+
+ /// \brief CallingConv - Specifies the calling convention that a function uses.
+ enum CallingConv {
+ CC_Default,
+ CC_C, // __attribute__((cdecl))
+ CC_X86StdCall, // __attribute__((stdcall))
+ CC_X86FastCall, // __attribute__((fastcall))
+ CC_X86ThisCall, // __attribute__((thiscall))
+ CC_X86Pascal, // __attribute__((pascal))
+ CC_AAPCS, // __attribute__((pcs("aapcs")))
+ CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp")))
+ CC_PnaclCall // __attribute__((pnaclcall))
+ };
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_BASIC_SPECIFIERS_H
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Tue Dec 18 08:30:41 2012
@@ -448,12 +448,6 @@
ALIAS("write_only", __write_only , KEYOPENCL)
ALIAS("read_write", __read_write , KEYOPENCL)
KEYWORD(__builtin_astype , KEYOPENCL)
-KEYWORD(image1d_t , KEYOPENCL)
-KEYWORD(image1d_array_t , KEYOPENCL)
-KEYWORD(image1d_buffer_t , KEYOPENCL)
-KEYWORD(image2d_t , KEYOPENCL)
-KEYWORD(image2d_array_t , KEYOPENCL)
-KEYWORD(image3d_t , KEYOPENCL)
// Borland Extensions.
KEYWORD(__pascal , KEYALL)
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Tue Dec 18 08:30:41 2012
@@ -276,12 +276,6 @@
static const TST TST_auto = clang::TST_auto;
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
static const TST TST_atomic = clang::TST_atomic;
- static const TST TST_image1d_t = clang::TST_image1d_t;
- static const TST TST_image1d_array_t = clang::TST_image1d_array_t;
- static const TST TST_image1d_buffer_t = clang::TST_image1d_buffer_t;
- static const TST TST_image2d_t = clang::TST_image2d_t;
- static const TST TST_image2d_array_t = clang::TST_image2d_array_t;
- static const TST TST_image3d_t = clang::TST_image3d_t;
static const TST TST_error = clang::TST_error;
// type-qualifiers
@@ -312,7 +306,7 @@
/*TSW*/unsigned TypeSpecWidth : 2;
/*TSC*/unsigned TypeSpecComplex : 2;
/*TSS*/unsigned TypeSpecSign : 2;
- /*TST*/unsigned TypeSpecType : 6;
+ /*TST*/unsigned TypeSpecType : 5;
unsigned TypeAltiVecVector : 1;
unsigned TypeAltiVecPixel : 1;
unsigned TypeAltiVecBool : 1;
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Dec 18 08:30:41 2012
@@ -1,1367 +1,1355 @@
-//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header defines Bitcode enum values for Clang serialized AST files.
-//
-// The enum values defined in this file should be considered permanent. If
-// new features are added, they should have values added at the end of the
-// respective lists.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
-#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
-
-#include "clang/AST/Type.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Bitcode/BitCodes.h"
-#include "llvm/Support/DataTypes.h"
-
-namespace clang {
- namespace serialization {
- /// \brief AST file major version number supported by this version of
- /// Clang.
- ///
- /// Whenever the AST file format changes in a way that makes it
- /// incompatible with previous versions (such that a reader
- /// designed for the previous version could not support reading
- /// the new version), this number should be increased.
- ///
- /// Version 4 of AST files also requires that the version control branch and
- /// revision match exactly, since there is no backward compatibility of
- /// AST files at this time.
- const unsigned VERSION_MAJOR = 5;
-
- /// \brief AST file minor version number supported by this version of
- /// Clang.
- ///
- /// Whenever the AST format changes in a way that is still
- /// compatible with previous versions (such that a reader designed
- /// for the previous version could still support reading the new
- /// version by ignoring new kinds of subblocks), this number
- /// should be increased.
- const unsigned VERSION_MINOR = 0;
-
- /// \brief An ID number that refers to an identifier in an AST file.
- ///
- /// The ID numbers of identifiers are consecutive (in order of discovery)
- /// and start at 1. 0 is reserved for NULL.
- typedef uint32_t IdentifierID;
-
- /// \brief An ID number that refers to a declaration in an AST file.
- ///
- /// The ID numbers of declarations are consecutive (in order of
- /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
- /// At the start of a chain of precompiled headers, declaration ID 1 is
- /// used for the translation unit declaration.
- typedef uint32_t DeclID;
-
- /// \brief a Decl::Kind/DeclID pair.
- typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
-
- // FIXME: Turn these into classes so we can have some type safety when
- // we go from local ID to global and vice-versa.
- typedef DeclID LocalDeclID;
- typedef DeclID GlobalDeclID;
-
- /// \brief An ID number that refers to a type in an AST file.
- ///
- /// The ID of a type is partitioned into two parts: the lower
- /// three bits are used to store the const/volatile/restrict
- /// qualifiers (as with QualType) and the upper bits provide a
- /// type index. The type index values are partitioned into two
- /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
- /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
- /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
- /// other types that have serialized representations.
- typedef uint32_t TypeID;
-
- /// \brief A type index; the type ID with the qualifier bits removed.
- class TypeIdx {
- uint32_t Idx;
- public:
- TypeIdx() : Idx(0) { }
- explicit TypeIdx(uint32_t index) : Idx(index) { }
-
- uint32_t getIndex() const { return Idx; }
- TypeID asTypeID(unsigned FastQuals) const {
- if (Idx == uint32_t(-1))
- return TypeID(-1);
-
- return (Idx << Qualifiers::FastWidth) | FastQuals;
- }
- static TypeIdx fromTypeID(TypeID ID) {
- if (ID == TypeID(-1))
- return TypeIdx(-1);
-
- return TypeIdx(ID >> Qualifiers::FastWidth);
- }
- };
-
- /// A structure for putting "fast"-unqualified QualTypes into a
- /// DenseMap. This uses the standard pointer hash function.
- struct UnsafeQualTypeDenseMapInfo {
- static inline bool isEqual(QualType A, QualType B) { return A == B; }
- static inline QualType getEmptyKey() {
- return QualType::getFromOpaquePtr((void*) 1);
- }
- static inline QualType getTombstoneKey() {
- return QualType::getFromOpaquePtr((void*) 2);
- }
- static inline unsigned getHashValue(QualType T) {
- assert(!T.getLocalFastQualifiers() &&
- "hash invalid for types with fast quals");
- uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
- }
- };
-
- /// \brief An ID number that refers to an identifier in an AST file.
- typedef uint32_t IdentID;
-
- /// \brief The number of predefined identifier IDs.
- const unsigned int NUM_PREDEF_IDENT_IDS = 1;
-
- /// \brief An ID number that refers to a macro in an AST file.
- typedef uint32_t MacroID;
-
- /// \brief The number of predefined macro IDs.
- const unsigned int NUM_PREDEF_MACRO_IDS = 1;
-
- /// \brief An ID number that refers to an ObjC selector in an AST file.
- typedef uint32_t SelectorID;
-
- /// \brief The number of predefined selector IDs.
- const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
-
- /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
- /// AST file.
- typedef uint32_t CXXBaseSpecifiersID;
-
- /// \brief An ID number that refers to an entity in the detailed
- /// preprocessing record.
- typedef uint32_t PreprocessedEntityID;
-
- /// \brief An ID number that refers to a submodule in a module file.
- typedef uint32_t SubmoduleID;
-
- /// \brief The number of predefined submodule IDs.
- const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
-
- /// \brief Source range/offset of a preprocessed entity.
- struct PPEntityOffset {
- /// \brief Raw source location of beginning of range.
- unsigned Begin;
- /// \brief Raw source location of end of range.
- unsigned End;
- /// \brief Offset in the AST file.
- uint32_t BitOffset;
-
- PPEntityOffset(SourceRange R, uint32_t BitOffset)
- : Begin(R.getBegin().getRawEncoding()),
- End(R.getEnd().getRawEncoding()),
- BitOffset(BitOffset) { }
- };
-
- /// \brief Source range/offset of a preprocessed entity.
- struct DeclOffset {
- /// \brief Raw source location.
- unsigned Loc;
- /// \brief Offset in the AST file.
- uint32_t BitOffset;
-
- DeclOffset() : Loc(0), BitOffset(0) { }
- DeclOffset(SourceLocation Loc, uint32_t BitOffset)
- : Loc(Loc.getRawEncoding()),
- BitOffset(BitOffset) { }
- void setLocation(SourceLocation L) {
- Loc = L.getRawEncoding();
- }
- };
-
- /// \brief The number of predefined preprocessed entity IDs.
- const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
-
- /// \brief Describes the various kinds of blocks that occur within
- /// an AST file.
- enum BlockIDs {
- /// \brief The AST block, which acts as a container around the
- /// full AST block.
- AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
-
- /// \brief The block containing information about the source
- /// manager.
- SOURCE_MANAGER_BLOCK_ID,
-
- /// \brief The block containing information about the
- /// preprocessor.
- PREPROCESSOR_BLOCK_ID,
-
- /// \brief The block containing the definitions of all of the
- /// types and decls used within the AST file.
- DECLTYPES_BLOCK_ID,
-
- /// \brief The block containing DECL_UPDATES records.
- DECL_UPDATES_BLOCK_ID,
-
- /// \brief The block containing the detailed preprocessing record.
- PREPROCESSOR_DETAIL_BLOCK_ID,
-
- /// \brief The block containing the submodule structure.
- SUBMODULE_BLOCK_ID,
-
- /// \brief The block containing comments.
- COMMENTS_BLOCK_ID,
-
- /// \brief The control block, which contains all of the
- /// information that needs to be validated prior to committing
- /// to loading the AST file.
- CONTROL_BLOCK_ID,
-
- /// \brief The block of input files, which were used as inputs
- /// to create this AST file.
- ///
- /// This block is part of the control block.
- INPUT_FILES_BLOCK_ID
- };
-
- /// \brief Record types that occur within the control block.
- enum ControlRecordTypes {
- /// \brief AST file metadata, including the AST file version number
- /// and information about the compiler used to build this AST file.
- METADATA = 1,
-
- /// \brief Record code for the list of other AST files imported by
- /// this AST file.
- IMPORTS = 2,
-
- /// \brief Record code for the language options table.
- ///
- /// The record with this code contains the contents of the
- /// LangOptions structure. We serialize the entire contents of
- /// the structure, and let the reader decide which options are
- /// actually important to check.
- LANGUAGE_OPTIONS = 3,
-
- /// \brief Record code for the target options table.
- TARGET_OPTIONS = 4,
-
- /// \brief Record code for the original file that was used to
- /// generate the AST file, including both its file ID and its
- /// name.
- ORIGINAL_FILE = 5,
-
- /// \brief The directory that the PCH was originally created in.
- ORIGINAL_PCH_DIR = 6,
-
- /// \brief Record code for file ID of the file or buffer that was used to
- /// generate the AST file.
- ORIGINAL_FILE_ID = 7,
-
- /// \brief Offsets into the input-files block where input files
- /// reside.
- INPUT_FILE_OFFSETS = 8,
-
- /// \brief Record code for the diagnostic options table.
- DIAGNOSTIC_OPTIONS = 9,
-
- /// \brief Record code for the filesystem options table.
- FILE_SYSTEM_OPTIONS = 10,
-
- /// \brief Record code for the headers search options table.
- HEADER_SEARCH_OPTIONS = 11,
-
- /// \brief Record code for the preprocessor options table.
- PREPROCESSOR_OPTIONS = 12
- };
-
- /// \brief Record types that occur within the input-files block
- /// inside the control block.
- enum InputFileRecordTypes {
- /// \brief An input file.
- INPUT_FILE = 1
- };
-
- /// \brief Record types that occur within the AST block itself.
- enum ASTRecordTypes {
- /// \brief Record code for the offsets of each type.
- ///
- /// The TYPE_OFFSET constant describes the record that occurs
- /// within the AST block. The record itself is an array of offsets that
- /// point into the declarations and types block (identified by
- /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
- /// of a type. For a given type ID @c T, the lower three bits of
- /// @c T are its qualifiers (const, volatile, restrict), as in
- /// the QualType class. The upper bits, after being shifted and
- /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
- /// TYPE_OFFSET block to determine the offset of that type's
- /// corresponding record within the DECLTYPES_BLOCK_ID block.
- TYPE_OFFSET = 1,
-
- /// \brief Record code for the offsets of each decl.
- ///
- /// The DECL_OFFSET constant describes the record that occurs
- /// within the block identified by DECL_OFFSETS_BLOCK_ID within
- /// the AST block. The record itself is an array of offsets that
- /// point into the declarations and types block (identified by
- /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
- /// record, after subtracting one to account for the use of
- /// declaration ID 0 for a NULL declaration pointer. Index 0 is
- /// reserved for the translation unit declaration.
- DECL_OFFSET = 2,
-
- /// \brief Record code for the table of offsets of each
- /// identifier ID.
- ///
- /// The offset table contains offsets into the blob stored in
- /// the IDENTIFIER_TABLE record. Each offset points to the
- /// NULL-terminated string that corresponds to that identifier.
- IDENTIFIER_OFFSET = 3,
-
- /// \brief This is so that older clang versions, before the introduction
- /// of the control block, can read and reject the newer PCH format.
- /// *DON"T CHANGE THIS NUMBER*.
- METADATA_OLD_FORMAT = 4,
-
- /// \brief Record code for the identifier table.
- ///
- /// The identifier table is a simple blob that contains
- /// NULL-terminated strings for all of the identifiers
- /// referenced by the AST file. The IDENTIFIER_OFFSET table
- /// contains the mapping from identifier IDs to the characters
- /// in this blob. Note that the starting offsets of all of the
- /// identifiers are odd, so that, when the identifier offset
- /// table is loaded in, we can use the low bit to distinguish
- /// between offsets (for unresolved identifier IDs) and
- /// IdentifierInfo pointers (for already-resolved identifier
- /// IDs).
- IDENTIFIER_TABLE = 5,
-
- /// \brief Record code for the array of external definitions.
- ///
- /// The AST file contains a list of all of the unnamed external
- /// definitions present within the parsed headers, stored as an
- /// array of declaration IDs. These external definitions will be
- /// reported to the AST consumer after the AST file has been
- /// read, since their presence can affect the semantics of the
- /// program (e.g., for code generation).
- EXTERNAL_DEFINITIONS = 6,
-
- /// \brief Record code for the set of non-builtin, special
- /// types.
- ///
- /// This record contains the type IDs for the various type nodes
- /// that are constructed during semantic analysis (e.g.,
- /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
- /// offsets into this record.
- SPECIAL_TYPES = 7,
-
- /// \brief Record code for the extra statistics we gather while
- /// generating an AST file.
- STATISTICS = 8,
-
- /// \brief Record code for the array of tentative definitions.
- TENTATIVE_DEFINITIONS = 9,
-
- /// \brief Record code for the array of locally-scoped external
- /// declarations.
- LOCALLY_SCOPED_EXTERNAL_DECLS = 10,
-
- /// \brief Record code for the table of offsets into the
- /// Objective-C method pool.
- SELECTOR_OFFSETS = 11,
-
- /// \brief Record code for the Objective-C method pool,
- METHOD_POOL = 12,
-
- /// \brief The value of the next __COUNTER__ to dispense.
- /// [PP_COUNTER_VALUE, Val]
- PP_COUNTER_VALUE = 13,
-
- /// \brief Record code for the table of offsets into the block
- /// of source-location information.
- SOURCE_LOCATION_OFFSETS = 14,
-
- /// \brief Record code for the set of source location entries
- /// that need to be preloaded by the AST reader.
- ///
- /// This set contains the source location entry for the
- /// predefines buffer and for any file entries that need to be
- /// preloaded.
- SOURCE_LOCATION_PRELOADS = 15,
-
- /// \brief Record code for the set of ext_vector type names.
- EXT_VECTOR_DECLS = 16,
-
- /// \brief Record code for the array of unused file scoped decls.
- UNUSED_FILESCOPED_DECLS = 17,
-
- /// \brief Record code for the table of offsets to entries in the
- /// preprocessing record.
- PPD_ENTITIES_OFFSETS = 18,
-
- /// \brief Record code for the array of VTable uses.
- VTABLE_USES = 19,
-
- /// \brief Record code for the array of dynamic classes.
- DYNAMIC_CLASSES = 20,
-
- /// \brief Record code for referenced selector pool.
- REFERENCED_SELECTOR_POOL = 21,
-
- /// \brief Record code for an update to the TU's lexically contained
- /// declarations.
- TU_UPDATE_LEXICAL = 22,
-
- /// \brief Record code for the array describing the locations (in the
- /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
- /// the first known ID.
- LOCAL_REDECLARATIONS_MAP = 23,
-
- /// \brief Record code for declarations that Sema keeps references of.
- SEMA_DECL_REFS = 24,
-
- /// \brief Record code for weak undeclared identifiers.
- WEAK_UNDECLARED_IDENTIFIERS = 25,
-
- /// \brief Record code for pending implicit instantiations.
- PENDING_IMPLICIT_INSTANTIATIONS = 26,
-
- /// \brief Record code for a decl replacement block.
- ///
- /// If a declaration is modified after having been deserialized, and then
- /// written to a dependent AST file, its ID and offset must be added to
- /// the replacement block.
- DECL_REPLACEMENTS = 27,
-
- /// \brief Record code for an update to a decl context's lookup table.
- ///
- /// In practice, this should only be used for the TU and namespaces.
- UPDATE_VISIBLE = 28,
-
- /// \brief Record for offsets of DECL_UPDATES records for declarations
- /// that were modified after being deserialized and need updates.
- DECL_UPDATE_OFFSETS = 29,
-
- /// \brief Record of updates for a declaration that was modified after
- /// being deserialized.
- DECL_UPDATES = 30,
-
- /// \brief Record code for the table of offsets to CXXBaseSpecifier
- /// sets.
- CXX_BASE_SPECIFIER_OFFSETS = 31,
-
- /// \brief Record code for \#pragma diagnostic mappings.
- DIAG_PRAGMA_MAPPINGS = 32,
-
- /// \brief Record code for special CUDA declarations.
- CUDA_SPECIAL_DECL_REFS = 33,
-
- /// \brief Record code for header search information.
- HEADER_SEARCH_TABLE = 34,
-
- /// \brief Record code for floating point \#pragma options.
- FP_PRAGMA_OPTIONS = 35,
-
- /// \brief Record code for enabled OpenCL extensions.
- OPENCL_EXTENSIONS = 36,
-
- /// \brief The list of delegating constructor declarations.
- DELEGATING_CTORS = 37,
-
- /// \brief Record code for the set of known namespaces, which are used
- /// for typo correction.
- KNOWN_NAMESPACES = 38,
-
- /// \brief Record code for the remapping information used to relate
- /// loaded modules to the various offsets and IDs(e.g., source location
- /// offests, declaration and type IDs) that are used in that module to
- /// refer to other modules.
- MODULE_OFFSET_MAP = 39,
-
- /// \brief Record code for the source manager line table information,
- /// which stores information about \#line directives.
- SOURCE_MANAGER_LINE_TABLE = 40,
-
- /// \brief Record code for map of Objective-C class definition IDs to the
- /// ObjC categories in a module that are attached to that class.
- OBJC_CATEGORIES_MAP = 41,
-
- /// \brief Record code for a file sorted array of DeclIDs in a module.
- FILE_SORTED_DECLS = 42,
-
- /// \brief Record code for an array of all of the (sub)modules that were
- /// imported by the AST file.
- IMPORTED_MODULES = 43,
-
- /// \brief Record code for the set of merged declarations in an AST file.
- MERGED_DECLARATIONS = 44,
-
- /// \brief Record code for the array of redeclaration chains.
- ///
- /// This array can only be interpreted properly using the local
- /// redeclarations map.
- LOCAL_REDECLARATIONS = 45,
-
- /// \brief Record code for the array of Objective-C categories (including
- /// extensions).
- ///
- /// This array can only be interpreted properly using the Objective-C
- /// categories map.
- OBJC_CATEGORIES = 46,
-
- /// \brief Record code for the table of offsets of each macro ID.
- ///
- /// The offset table contains offsets into the blob stored in
- /// the preprocessor block. Each offset points to the corresponding
- /// macro definition.
- MACRO_OFFSET = 47,
-
- /// \brief Record of updates for a macro that was modified after
- /// being deserialized.
- MACRO_UPDATES = 48
- };
-
- /// \brief Record types used within a source manager block.
- enum SourceManagerRecordTypes {
- /// \brief Describes a source location entry (SLocEntry) for a
- /// file.
- SM_SLOC_FILE_ENTRY = 1,
- /// \brief Describes a source location entry (SLocEntry) for a
- /// buffer.
- SM_SLOC_BUFFER_ENTRY = 2,
- /// \brief Describes a blob that contains the data for a buffer
- /// entry. This kind of record always directly follows a
- /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
- /// overridden buffer.
- SM_SLOC_BUFFER_BLOB = 3,
- /// \brief Describes a source location entry (SLocEntry) for a
- /// macro expansion.
- SM_SLOC_EXPANSION_ENTRY = 4
- };
-
- /// \brief Record types used within a preprocessor block.
- enum PreprocessorRecordTypes {
- // The macros in the PP section are a PP_MACRO_* instance followed by a
- // list of PP_TOKEN instances for each token in the definition.
-
- /// \brief An object-like macro definition.
- /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
- PP_MACRO_OBJECT_LIKE = 1,
-
- /// \brief A function-like macro definition.
- /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
- /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
- PP_MACRO_FUNCTION_LIKE = 2,
-
- /// \brief Describes one token.
- /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
- PP_TOKEN = 3
- };
-
- /// \brief Record types used within a preprocessor detail block.
- enum PreprocessorDetailRecordTypes {
- /// \brief Describes a macro expansion within the preprocessing record.
- PPD_MACRO_EXPANSION = 0,
-
- /// \brief Describes a macro definition within the preprocessing record.
- PPD_MACRO_DEFINITION = 1,
-
- /// \brief Describes an inclusion directive within the preprocessing
- /// record.
- PPD_INCLUSION_DIRECTIVE = 2
- };
-
- /// \brief Record types used within a submodule description block.
- enum SubmoduleRecordTypes {
- /// \brief Metadata for submodules as a whole.
- SUBMODULE_METADATA = 0,
- /// \brief Defines the major attributes of a submodule, including its
- /// name and parent.
- SUBMODULE_DEFINITION = 1,
- /// \brief Specifies the umbrella header used to create this module,
- /// if any.
- SUBMODULE_UMBRELLA_HEADER = 2,
- /// \brief Specifies a header that falls into this (sub)module.
- SUBMODULE_HEADER = 3,
- /// \brief Specifies a top-level header that falls into this (sub)module.
- SUBMODULE_TOPHEADER = 4,
- /// \brief Specifies an umbrella directory.
- SUBMODULE_UMBRELLA_DIR = 5,
- /// \brief Specifies the submodules that are imported by this
- /// submodule.
- SUBMODULE_IMPORTS = 6,
- /// \brief Specifies the submodules that are re-exported from this
- /// submodule.
- SUBMODULE_EXPORTS = 7,
- /// \brief Specifies a required feature.
- SUBMODULE_REQUIRES = 8,
- /// \brief Specifies a header that has been explicitly excluded
- /// from this submodule.
- SUBMODULE_EXCLUDED_HEADER = 9
- };
-
- /// \brief Record types used within a comments block.
- enum CommentRecordTypes {
- COMMENTS_RAW_COMMENT = 0
- };
-
- /// \defgroup ASTAST AST file AST constants
- ///
- /// The constants in this group describe various components of the
- /// abstract syntax tree within an AST file.
- ///
- /// @{
-
- /// \brief Predefined type IDs.
- ///
- /// These type IDs correspond to predefined types in the AST
- /// context, such as built-in types (int) and special place-holder
- /// types (the \<overload> and \<dependent> type markers). Such
- /// types are never actually serialized, since they will be built
- /// by the AST context when it is created.
- enum PredefinedTypeIDs {
- /// \brief The NULL type.
- PREDEF_TYPE_NULL_ID = 0,
- /// \brief The void type.
- PREDEF_TYPE_VOID_ID = 1,
- /// \brief The 'bool' or '_Bool' type.
- PREDEF_TYPE_BOOL_ID = 2,
- /// \brief The 'char' type, when it is unsigned.
- PREDEF_TYPE_CHAR_U_ID = 3,
- /// \brief The 'unsigned char' type.
- PREDEF_TYPE_UCHAR_ID = 4,
- /// \brief The 'unsigned short' type.
- PREDEF_TYPE_USHORT_ID = 5,
- /// \brief The 'unsigned int' type.
- PREDEF_TYPE_UINT_ID = 6,
- /// \brief The 'unsigned long' type.
- PREDEF_TYPE_ULONG_ID = 7,
- /// \brief The 'unsigned long long' type.
- PREDEF_TYPE_ULONGLONG_ID = 8,
- /// \brief The 'char' type, when it is signed.
- PREDEF_TYPE_CHAR_S_ID = 9,
- /// \brief The 'signed char' type.
- PREDEF_TYPE_SCHAR_ID = 10,
- /// \brief The C++ 'wchar_t' type.
- PREDEF_TYPE_WCHAR_ID = 11,
- /// \brief The (signed) 'short' type.
- PREDEF_TYPE_SHORT_ID = 12,
- /// \brief The (signed) 'int' type.
- PREDEF_TYPE_INT_ID = 13,
- /// \brief The (signed) 'long' type.
- PREDEF_TYPE_LONG_ID = 14,
- /// \brief The (signed) 'long long' type.
- PREDEF_TYPE_LONGLONG_ID = 15,
- /// \brief The 'float' type.
- PREDEF_TYPE_FLOAT_ID = 16,
- /// \brief The 'double' type.
- PREDEF_TYPE_DOUBLE_ID = 17,
- /// \brief The 'long double' type.
- PREDEF_TYPE_LONGDOUBLE_ID = 18,
- /// \brief The placeholder type for overloaded function sets.
- PREDEF_TYPE_OVERLOAD_ID = 19,
- /// \brief The placeholder type for dependent types.
- PREDEF_TYPE_DEPENDENT_ID = 20,
- /// \brief The '__uint128_t' type.
- PREDEF_TYPE_UINT128_ID = 21,
- /// \brief The '__int128_t' type.
- PREDEF_TYPE_INT128_ID = 22,
- /// \brief The type of 'nullptr'.
- PREDEF_TYPE_NULLPTR_ID = 23,
- /// \brief The C++ 'char16_t' type.
- PREDEF_TYPE_CHAR16_ID = 24,
- /// \brief The C++ 'char32_t' type.
- PREDEF_TYPE_CHAR32_ID = 25,
- /// \brief The ObjC 'id' type.
- PREDEF_TYPE_OBJC_ID = 26,
- /// \brief The ObjC 'Class' type.
- PREDEF_TYPE_OBJC_CLASS = 27,
- /// \brief The ObjC 'SEL' type.
- PREDEF_TYPE_OBJC_SEL = 28,
- /// \brief The 'unknown any' placeholder type.
- PREDEF_TYPE_UNKNOWN_ANY = 29,
- /// \brief The placeholder type for bound member functions.
- PREDEF_TYPE_BOUND_MEMBER = 30,
- /// \brief The "auto" deduction type.
- PREDEF_TYPE_AUTO_DEDUCT = 31,
- /// \brief The "auto &&" deduction type.
- PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
- /// \brief The OpenCL 'half' / ARM NEON __fp16 type.
- PREDEF_TYPE_HALF_ID = 33,
- /// \brief ARC's unbridged-cast placeholder type.
- PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
- /// \brief The pseudo-object placeholder type.
- PREDEF_TYPE_PSEUDO_OBJECT = 35,
- /// \brief The __va_list_tag placeholder type.
- PREDEF_TYPE_VA_LIST_TAG = 36,
- /// \brief The placeholder type for builtin functions.
- PREDEF_TYPE_BUILTIN_FN = 37,
- /// \brief OpenCL 1d image type.
- PREDEF_TYPE_IMAGE1D_ID = 38,
- /// \brief OpenCL 1d image array type.
- PREDEF_TYPE_IMAGE1D_ARR_ID = 39,
- /// \brief OpenCL 1d image buffer type.
- PREDEF_TYPE_IMAGE1D_BUFF_ID = 40,
- /// \brief OpenCL 2d image type.
- PREDEF_TYPE_IMAGE2D_ID = 41,
- /// \brief OpenCL 2d image array type.
- PREDEF_TYPE_IMAGE2D_ARR_ID = 42,
- /// \brief OpenCL 3d image type.
- PREDEF_TYPE_IMAGE3D_ID = 43
- };
-
- /// \brief The number of predefined type IDs that are reserved for
- /// the PREDEF_TYPE_* constants.
- ///
- /// Type IDs for non-predefined types will start at
- /// NUM_PREDEF_TYPE_IDs.
- const unsigned NUM_PREDEF_TYPE_IDS = 100;
-
- /// \brief The number of allowed abbreviations in bits
- const unsigned NUM_ALLOWED_ABBREVS_SIZE = 4;
-
- /// \brief Record codes for each kind of type.
- ///
- /// These constants describe the type records that can occur within a
- /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
- /// constant describes a record for a specific type class in the
- /// AST.
- enum TypeCode {
- /// \brief An ExtQualType record.
- TYPE_EXT_QUAL = 1,
- /// \brief A ComplexType record.
- TYPE_COMPLEX = 3,
- /// \brief A PointerType record.
- TYPE_POINTER = 4,
- /// \brief A BlockPointerType record.
- TYPE_BLOCK_POINTER = 5,
- /// \brief An LValueReferenceType record.
- TYPE_LVALUE_REFERENCE = 6,
- /// \brief An RValueReferenceType record.
- TYPE_RVALUE_REFERENCE = 7,
- /// \brief A MemberPointerType record.
- TYPE_MEMBER_POINTER = 8,
- /// \brief A ConstantArrayType record.
- TYPE_CONSTANT_ARRAY = 9,
- /// \brief An IncompleteArrayType record.
- TYPE_INCOMPLETE_ARRAY = 10,
- /// \brief A VariableArrayType record.
- TYPE_VARIABLE_ARRAY = 11,
- /// \brief A VectorType record.
- TYPE_VECTOR = 12,
- /// \brief An ExtVectorType record.
- TYPE_EXT_VECTOR = 13,
- /// \brief A FunctionNoProtoType record.
- TYPE_FUNCTION_NO_PROTO = 14,
- /// \brief A FunctionProtoType record.
- TYPE_FUNCTION_PROTO = 15,
- /// \brief A TypedefType record.
- TYPE_TYPEDEF = 16,
- /// \brief A TypeOfExprType record.
- TYPE_TYPEOF_EXPR = 17,
- /// \brief A TypeOfType record.
- TYPE_TYPEOF = 18,
- /// \brief A RecordType record.
- TYPE_RECORD = 19,
- /// \brief An EnumType record.
- TYPE_ENUM = 20,
- /// \brief An ObjCInterfaceType record.
- TYPE_OBJC_INTERFACE = 21,
- /// \brief An ObjCObjectPointerType record.
- TYPE_OBJC_OBJECT_POINTER = 22,
- /// \brief a DecltypeType record.
- TYPE_DECLTYPE = 23,
- /// \brief An ElaboratedType record.
- TYPE_ELABORATED = 24,
- /// \brief A SubstTemplateTypeParmType record.
- TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
- /// \brief An UnresolvedUsingType record.
- TYPE_UNRESOLVED_USING = 26,
- /// \brief An InjectedClassNameType record.
- TYPE_INJECTED_CLASS_NAME = 27,
- /// \brief An ObjCObjectType record.
- TYPE_OBJC_OBJECT = 28,
- /// \brief An TemplateTypeParmType record.
- TYPE_TEMPLATE_TYPE_PARM = 29,
- /// \brief An TemplateSpecializationType record.
- TYPE_TEMPLATE_SPECIALIZATION = 30,
- /// \brief A DependentNameType record.
- TYPE_DEPENDENT_NAME = 31,
- /// \brief A DependentTemplateSpecializationType record.
- TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
- /// \brief A DependentSizedArrayType record.
- TYPE_DEPENDENT_SIZED_ARRAY = 33,
- /// \brief A ParenType record.
- TYPE_PAREN = 34,
- /// \brief A PackExpansionType record.
- TYPE_PACK_EXPANSION = 35,
- /// \brief An AttributedType record.
- TYPE_ATTRIBUTED = 36,
- /// \brief A SubstTemplateTypeParmPackType record.
- TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
- /// \brief A AutoType record.
- TYPE_AUTO = 38,
- /// \brief A UnaryTransformType record.
- TYPE_UNARY_TRANSFORM = 39,
- /// \brief An AtomicType record.
- TYPE_ATOMIC = 40
- };
-
- /// \brief The type IDs for special types constructed by semantic
- /// analysis.
- ///
- /// The constants in this enumeration are indices into the
- /// SPECIAL_TYPES record.
- enum SpecialTypeIDs {
- /// \brief CFConstantString type
- SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
- /// \brief C FILE typedef type
- SPECIAL_TYPE_FILE = 1,
- /// \brief C jmp_buf typedef type
- SPECIAL_TYPE_JMP_BUF = 2,
- /// \brief C sigjmp_buf typedef type
- SPECIAL_TYPE_SIGJMP_BUF = 3,
- /// \brief Objective-C "id" redefinition type
- SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
- /// \brief Objective-C "Class" redefinition type
- SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
- /// \brief Objective-C "SEL" redefinition type
- SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
- /// \brief C ucontext_t typedef type
- SPECIAL_TYPE_UCONTEXT_T = 7
- };
-
- /// \brief The number of special type IDs.
- const unsigned NumSpecialTypeIDs = 8;
-
- /// \brief Predefined declaration IDs.
- ///
- /// These declaration IDs correspond to predefined declarations in the AST
- /// context, such as the NULL declaration ID. Such declarations are never
- /// actually serialized, since they will be built by the AST context when
- /// it is created.
- enum PredefinedDeclIDs {
- /// \brief The NULL declaration.
- PREDEF_DECL_NULL_ID = 0,
-
- /// \brief The translation unit.
- PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
-
- /// \brief The Objective-C 'id' type.
- PREDEF_DECL_OBJC_ID_ID = 2,
-
- /// \brief The Objective-C 'SEL' type.
- PREDEF_DECL_OBJC_SEL_ID = 3,
-
- /// \brief The Objective-C 'Class' type.
- PREDEF_DECL_OBJC_CLASS_ID = 4,
-
- /// \brief The Objective-C 'Protocol' type.
- PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
-
- /// \brief The signed 128-bit integer type.
- PREDEF_DECL_INT_128_ID = 6,
-
- /// \brief The unsigned 128-bit integer type.
- PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
-
- /// \brief The internal 'instancetype' typedef.
- PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
-
- /// \brief The internal '__builtin_va_list' typedef.
- PREDEF_DECL_BUILTIN_VA_LIST_ID = 9
- };
-
- /// \brief 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 = 10;
-
- /// \brief Record codes for each kind of declaration.
- ///
- /// These constants describe the declaration records that can occur within
- /// a declarations block (identified by DECLS_BLOCK_ID). Each
- /// constant describes a record for a specific declaration class
- /// in the AST.
- enum DeclCode {
- /// \brief A TypedefDecl record.
- DECL_TYPEDEF = 51,
- /// \brief A TypeAliasDecl record.
- DECL_TYPEALIAS,
- /// \brief An EnumDecl record.
- DECL_ENUM,
- /// \brief A RecordDecl record.
- DECL_RECORD,
- /// \brief An EnumConstantDecl record.
- DECL_ENUM_CONSTANT,
- /// \brief A FunctionDecl record.
- DECL_FUNCTION,
- /// \brief A ObjCMethodDecl record.
- DECL_OBJC_METHOD,
- /// \brief A ObjCInterfaceDecl record.
- DECL_OBJC_INTERFACE,
- /// \brief A ObjCProtocolDecl record.
- DECL_OBJC_PROTOCOL,
- /// \brief A ObjCIvarDecl record.
- DECL_OBJC_IVAR,
- /// \brief A ObjCAtDefsFieldDecl record.
- DECL_OBJC_AT_DEFS_FIELD,
- /// \brief A ObjCCategoryDecl record.
- DECL_OBJC_CATEGORY,
- /// \brief A ObjCCategoryImplDecl record.
- DECL_OBJC_CATEGORY_IMPL,
- /// \brief A ObjCImplementationDecl record.
- DECL_OBJC_IMPLEMENTATION,
- /// \brief A ObjCCompatibleAliasDecl record.
- DECL_OBJC_COMPATIBLE_ALIAS,
- /// \brief A ObjCPropertyDecl record.
- DECL_OBJC_PROPERTY,
- /// \brief A ObjCPropertyImplDecl record.
- DECL_OBJC_PROPERTY_IMPL,
- /// \brief A FieldDecl record.
- DECL_FIELD,
- /// \brief A VarDecl record.
- DECL_VAR,
- /// \brief An ImplicitParamDecl record.
- DECL_IMPLICIT_PARAM,
- /// \brief A ParmVarDecl record.
- DECL_PARM_VAR,
- /// \brief A FileScopeAsmDecl record.
- DECL_FILE_SCOPE_ASM,
- /// \brief A BlockDecl record.
- DECL_BLOCK,
- /// \brief A record that stores the set of declarations that are
- /// lexically stored within a given DeclContext.
- ///
- /// The record itself is a blob that is an array of declaration IDs,
- /// in the order in which those declarations were added to the
- /// declaration context. This data is used when iterating over
- /// the contents of a DeclContext, e.g., via
- /// DeclContext::decls_begin() and DeclContext::decls_end().
- DECL_CONTEXT_LEXICAL,
- /// \brief A record that stores the set of declarations that are
- /// visible from a given DeclContext.
- ///
- /// The record itself stores a set of mappings, each of which
- /// associates a declaration name with one or more declaration
- /// IDs. This data is used when performing qualified name lookup
- /// into a DeclContext via DeclContext::lookup.
- DECL_CONTEXT_VISIBLE,
- /// \brief A LabelDecl record.
- DECL_LABEL,
- /// \brief A NamespaceDecl record.
- DECL_NAMESPACE,
- /// \brief A NamespaceAliasDecl record.
- DECL_NAMESPACE_ALIAS,
- /// \brief A UsingDecl record.
- DECL_USING,
- /// \brief A UsingShadowDecl record.
- DECL_USING_SHADOW,
- /// \brief A UsingDirecitveDecl record.
- DECL_USING_DIRECTIVE,
- /// \brief An UnresolvedUsingValueDecl record.
- DECL_UNRESOLVED_USING_VALUE,
- /// \brief An UnresolvedUsingTypenameDecl record.
- DECL_UNRESOLVED_USING_TYPENAME,
- /// \brief A LinkageSpecDecl record.
- DECL_LINKAGE_SPEC,
- /// \brief A CXXRecordDecl record.
- DECL_CXX_RECORD,
- /// \brief A CXXMethodDecl record.
- DECL_CXX_METHOD,
- /// \brief A CXXConstructorDecl record.
- DECL_CXX_CONSTRUCTOR,
- /// \brief A CXXDestructorDecl record.
- DECL_CXX_DESTRUCTOR,
- /// \brief A CXXConversionDecl record.
- DECL_CXX_CONVERSION,
- /// \brief An AccessSpecDecl record.
- DECL_ACCESS_SPEC,
-
- /// \brief A FriendDecl record.
- DECL_FRIEND,
- /// \brief A FriendTemplateDecl record.
- DECL_FRIEND_TEMPLATE,
- /// \brief A ClassTemplateDecl record.
- DECL_CLASS_TEMPLATE,
- /// \brief A ClassTemplateSpecializationDecl record.
- DECL_CLASS_TEMPLATE_SPECIALIZATION,
- /// \brief A ClassTemplatePartialSpecializationDecl record.
- DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
- /// \brief A FunctionTemplateDecl record.
- DECL_FUNCTION_TEMPLATE,
- /// \brief A TemplateTypeParmDecl record.
- DECL_TEMPLATE_TYPE_PARM,
- /// \brief A NonTypeTemplateParmDecl record.
- DECL_NON_TYPE_TEMPLATE_PARM,
- /// \brief A TemplateTemplateParmDecl record.
- DECL_TEMPLATE_TEMPLATE_PARM,
- /// \brief A TypeAliasTemplateDecl record.
- DECL_TYPE_ALIAS_TEMPLATE,
- /// \brief A StaticAssertDecl record.
- DECL_STATIC_ASSERT,
- /// \brief A record containing CXXBaseSpecifiers.
- DECL_CXX_BASE_SPECIFIERS,
- /// \brief A IndirectFieldDecl record.
- DECL_INDIRECTFIELD,
- /// \brief A NonTypeTemplateParmDecl record that stores an expanded
- /// non-type template parameter pack.
- DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
- /// \brief A TemplateTemplateParmDecl record that stores an expanded
- /// template template parameter pack.
- DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
- /// \brief A ClassScopeFunctionSpecializationDecl record a class scope
- /// function specialization. (Microsoft extension).
- DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
- /// \brief An ImportDecl recording a module import.
- DECL_IMPORT
- };
-
- /// \brief Record codes for each kind of statement or expression.
- ///
- /// These constants describe the records that describe statements
- /// or expressions. These records occur within type and declarations
- /// block, so they begin with record values of 100. Each constant
- /// describes a record for a specific statement or expression class in the
- /// AST.
- enum StmtCode {
- /// \brief A marker record that indicates that we are at the end
- /// of an expression.
- STMT_STOP = 100,
- /// \brief A NULL expression.
- STMT_NULL_PTR,
- /// \brief A reference to a previously [de]serialized Stmt record.
- STMT_REF_PTR,
- /// \brief A NullStmt record.
- STMT_NULL,
- /// \brief A CompoundStmt record.
- STMT_COMPOUND,
- /// \brief A CaseStmt record.
- STMT_CASE,
- /// \brief A DefaultStmt record.
- STMT_DEFAULT,
- /// \brief A LabelStmt record.
- STMT_LABEL,
- /// \brief An AttributedStmt record.
- STMT_ATTRIBUTED,
- /// \brief An IfStmt record.
- STMT_IF,
- /// \brief A SwitchStmt record.
- STMT_SWITCH,
- /// \brief A WhileStmt record.
- STMT_WHILE,
- /// \brief A DoStmt record.
- STMT_DO,
- /// \brief A ForStmt record.
- STMT_FOR,
- /// \brief A GotoStmt record.
- STMT_GOTO,
- /// \brief An IndirectGotoStmt record.
- STMT_INDIRECT_GOTO,
- /// \brief A ContinueStmt record.
- STMT_CONTINUE,
- /// \brief A BreakStmt record.
- STMT_BREAK,
- /// \brief A ReturnStmt record.
- STMT_RETURN,
- /// \brief A DeclStmt record.
- STMT_DECL,
- /// \brief A GCC-style AsmStmt record.
- STMT_GCCASM,
- /// \brief A MS-style AsmStmt record.
- STMT_MSASM,
- /// \brief A PredefinedExpr record.
- EXPR_PREDEFINED,
- /// \brief A DeclRefExpr record.
- EXPR_DECL_REF,
- /// \brief An IntegerLiteral record.
- EXPR_INTEGER_LITERAL,
- /// \brief A FloatingLiteral record.
- EXPR_FLOATING_LITERAL,
- /// \brief An ImaginaryLiteral record.
- EXPR_IMAGINARY_LITERAL,
- /// \brief A StringLiteral record.
- EXPR_STRING_LITERAL,
- /// \brief A CharacterLiteral record.
- EXPR_CHARACTER_LITERAL,
- /// \brief A ParenExpr record.
- EXPR_PAREN,
- /// \brief A ParenListExpr record.
- EXPR_PAREN_LIST,
- /// \brief A UnaryOperator record.
- EXPR_UNARY_OPERATOR,
- /// \brief An OffsetOfExpr record.
- EXPR_OFFSETOF,
- /// \brief A SizefAlignOfExpr record.
- EXPR_SIZEOF_ALIGN_OF,
- /// \brief An ArraySubscriptExpr record.
- EXPR_ARRAY_SUBSCRIPT,
- /// \brief A CallExpr record.
- EXPR_CALL,
- /// \brief A MemberExpr record.
- EXPR_MEMBER,
- /// \brief A BinaryOperator record.
- EXPR_BINARY_OPERATOR,
- /// \brief A CompoundAssignOperator record.
- EXPR_COMPOUND_ASSIGN_OPERATOR,
- /// \brief A ConditionOperator record.
- EXPR_CONDITIONAL_OPERATOR,
- /// \brief An ImplicitCastExpr record.
- EXPR_IMPLICIT_CAST,
- /// \brief A CStyleCastExpr record.
- EXPR_CSTYLE_CAST,
- /// \brief A CompoundLiteralExpr record.
- EXPR_COMPOUND_LITERAL,
- /// \brief An ExtVectorElementExpr record.
- EXPR_EXT_VECTOR_ELEMENT,
- /// \brief An InitListExpr record.
- EXPR_INIT_LIST,
- /// \brief A DesignatedInitExpr record.
- EXPR_DESIGNATED_INIT,
- /// \brief An ImplicitValueInitExpr record.
- EXPR_IMPLICIT_VALUE_INIT,
- /// \brief A VAArgExpr record.
- EXPR_VA_ARG,
- /// \brief An AddrLabelExpr record.
- EXPR_ADDR_LABEL,
- /// \brief A StmtExpr record.
- EXPR_STMT,
- /// \brief A ChooseExpr record.
- EXPR_CHOOSE,
- /// \brief A GNUNullExpr record.
- EXPR_GNU_NULL,
- /// \brief A ShuffleVectorExpr record.
- EXPR_SHUFFLE_VECTOR,
- /// \brief BlockExpr
- EXPR_BLOCK,
- /// \brief A GenericSelectionExpr record.
- EXPR_GENERIC_SELECTION,
- /// \brief A PseudoObjectExpr record.
- EXPR_PSEUDO_OBJECT,
- /// \brief An AtomicExpr record.
- EXPR_ATOMIC,
-
- // Objective-C
-
- /// \brief An ObjCStringLiteral record.
- EXPR_OBJC_STRING_LITERAL,
-
- EXPR_OBJC_BOXED_EXPRESSION,
- EXPR_OBJC_ARRAY_LITERAL,
- EXPR_OBJC_DICTIONARY_LITERAL,
-
-
- /// \brief An ObjCEncodeExpr record.
- EXPR_OBJC_ENCODE,
- /// \brief An ObjCSelectorExpr record.
- EXPR_OBJC_SELECTOR_EXPR,
- /// \brief An ObjCProtocolExpr record.
- EXPR_OBJC_PROTOCOL_EXPR,
- /// \brief An ObjCIvarRefExpr record.
- EXPR_OBJC_IVAR_REF_EXPR,
- /// \brief An ObjCPropertyRefExpr record.
- EXPR_OBJC_PROPERTY_REF_EXPR,
- /// \brief An ObjCSubscriptRefExpr record.
- EXPR_OBJC_SUBSCRIPT_REF_EXPR,
- /// \brief UNUSED
- EXPR_OBJC_KVC_REF_EXPR,
- /// \brief An ObjCMessageExpr record.
- EXPR_OBJC_MESSAGE_EXPR,
- /// \brief An ObjCIsa Expr record.
- EXPR_OBJC_ISA,
- /// \brief An ObjCIndirectCopyRestoreExpr record.
- EXPR_OBJC_INDIRECT_COPY_RESTORE,
-
- /// \brief An ObjCForCollectionStmt record.
- STMT_OBJC_FOR_COLLECTION,
- /// \brief An ObjCAtCatchStmt record.
- STMT_OBJC_CATCH,
- /// \brief An ObjCAtFinallyStmt record.
- STMT_OBJC_FINALLY,
- /// \brief An ObjCAtTryStmt record.
- STMT_OBJC_AT_TRY,
- /// \brief An ObjCAtSynchronizedStmt record.
- STMT_OBJC_AT_SYNCHRONIZED,
- /// \brief An ObjCAtThrowStmt record.
- STMT_OBJC_AT_THROW,
- /// \brief An ObjCAutoreleasePoolStmt record.
- STMT_OBJC_AUTORELEASE_POOL,
- /// \brief A ObjCBoolLiteralExpr record.
- EXPR_OBJC_BOOL_LITERAL,
-
- // C++
-
- /// \brief A CXXCatchStmt record.
- STMT_CXX_CATCH,
- /// \brief A CXXTryStmt record.
- STMT_CXX_TRY,
- /// \brief A CXXForRangeStmt record.
- STMT_CXX_FOR_RANGE,
-
- /// \brief A CXXOperatorCallExpr record.
- EXPR_CXX_OPERATOR_CALL,
- /// \brief A CXXMemberCallExpr record.
- EXPR_CXX_MEMBER_CALL,
- /// \brief A CXXConstructExpr record.
- EXPR_CXX_CONSTRUCT,
- /// \brief A CXXTemporaryObjectExpr record.
- EXPR_CXX_TEMPORARY_OBJECT,
- /// \brief A CXXStaticCastExpr record.
- EXPR_CXX_STATIC_CAST,
- /// \brief A CXXDynamicCastExpr record.
- EXPR_CXX_DYNAMIC_CAST,
- /// \brief A CXXReinterpretCastExpr record.
- EXPR_CXX_REINTERPRET_CAST,
- /// \brief A CXXConstCastExpr record.
- EXPR_CXX_CONST_CAST,
- /// \brief A CXXFunctionalCastExpr record.
- EXPR_CXX_FUNCTIONAL_CAST,
- /// \brief A UserDefinedLiteral record.
- EXPR_USER_DEFINED_LITERAL,
- /// \brief A CXXBoolLiteralExpr record.
- EXPR_CXX_BOOL_LITERAL,
- EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
- EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
- EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
- EXPR_CXX_THIS, // CXXThisExpr
- EXPR_CXX_THROW, // CXXThrowExpr
- EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
- EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
-
- EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
- EXPR_CXX_NEW, // CXXNewExpr
- EXPR_CXX_DELETE, // CXXDeleteExpr
- EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
-
- EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
-
- EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
- EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
- EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
- EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
- EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
-
- EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
- EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
- EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
-
- EXPR_OPAQUE_VALUE, // OpaqueValueExpr
- EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
- EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
- EXPR_TYPE_TRAIT, // TypeTraitExpr
- EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
-
- EXPR_PACK_EXPANSION, // PackExpansionExpr
- EXPR_SIZEOF_PACK, // SizeOfPackExpr
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
- EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
- EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
- EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
-
- // CUDA
- EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
-
- // OpenCL
- EXPR_ASTYPE, // AsTypeExpr
-
- // Microsoft
- EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
- EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
- STMT_SEH_EXCEPT, // SEHExceptStmt
- STMT_SEH_FINALLY, // SEHFinallyStmt
- STMT_SEH_TRY, // SEHTryStmt
-
- // ARC
- EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
-
- STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
- EXPR_LAMBDA // LambdaExpr
- };
-
- /// \brief The kinds of designators that can occur in a
- /// DesignatedInitExpr.
- enum DesignatorTypes {
- /// \brief Field designator where only the field name is known.
- DESIG_FIELD_NAME = 0,
- /// \brief Field designator where the field has been resolved to
- /// a declaration.
- DESIG_FIELD_DECL = 1,
- /// \brief Array designator.
- DESIG_ARRAY = 2,
- /// \brief GNU array range designator.
- DESIG_ARRAY_RANGE = 3
- };
-
- /// \brief The different kinds of data that can occur in a
- /// CtorInitializer.
- enum CtorInitializerType {
- CTOR_INITIALIZER_BASE,
- CTOR_INITIALIZER_DELEGATING,
- CTOR_INITIALIZER_MEMBER,
- CTOR_INITIALIZER_INDIRECT_MEMBER
- };
-
- /// \brief Describes the redeclarations of a declaration.
- struct LocalRedeclarationsInfo {
- DeclID FirstID; // The ID of the first declaration
- unsigned Offset; // Offset into the array of redeclaration chains.
-
- friend bool operator<(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID < Y.FirstID;
- }
-
- friend bool operator>(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID > Y.FirstID;
- }
-
- friend bool operator<=(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID <= Y.FirstID;
- }
-
- friend bool operator>=(const LocalRedeclarationsInfo &X,
- const LocalRedeclarationsInfo &Y) {
- return X.FirstID >= Y.FirstID;
- }
- };
-
- /// \brief Describes the categories of an Objective-C class.
- struct ObjCCategoriesInfo {
- DeclID DefinitionID; // The ID of the definition
- unsigned Offset; // Offset into the array of category lists.
-
- friend bool operator<(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID < Y.DefinitionID;
- }
-
- friend bool operator>(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID > Y.DefinitionID;
- }
-
- friend bool operator<=(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID <= Y.DefinitionID;
- }
-
- friend bool operator>=(const ObjCCategoriesInfo &X,
- const ObjCCategoriesInfo &Y) {
- return X.DefinitionID >= Y.DefinitionID;
- }
- };
-
- /// @}
- }
-} // end namespace clang
-
-#endif
+//===- ASTBitCodes.h - Enum values for the PCH bitcode format ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines Bitcode enum values for Clang serialized AST files.
+//
+// The enum values defined in this file should be considered permanent. If
+// new features are added, they should have values added at the end of the
+// respective lists.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H
+#define LLVM_CLANG_FRONTEND_PCHBITCODES_H
+
+#include "clang/AST/Type.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace clang {
+ namespace serialization {
+ /// \brief AST file major version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the AST file format changes in a way that makes it
+ /// incompatible with previous versions (such that a reader
+ /// designed for the previous version could not support reading
+ /// the new version), this number should be increased.
+ ///
+ /// Version 4 of AST files also requires that the version control branch and
+ /// revision match exactly, since there is no backward compatibility of
+ /// AST files at this time.
+ const unsigned VERSION_MAJOR = 5;
+
+ /// \brief AST file minor version number supported by this version of
+ /// Clang.
+ ///
+ /// Whenever the AST format changes in a way that is still
+ /// compatible with previous versions (such that a reader designed
+ /// for the previous version could still support reading the new
+ /// version by ignoring new kinds of subblocks), this number
+ /// should be increased.
+ const unsigned VERSION_MINOR = 0;
+
+ /// \brief An ID number that refers to an identifier in an AST file.
+ ///
+ /// The ID numbers of identifiers are consecutive (in order of discovery)
+ /// and start at 1. 0 is reserved for NULL.
+ typedef uint32_t IdentifierID;
+
+ /// \brief An ID number that refers to a declaration in an AST file.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
+ /// At the start of a chain of precompiled headers, declaration ID 1 is
+ /// used for the translation unit declaration.
+ typedef uint32_t DeclID;
+
+ /// \brief a Decl::Kind/DeclID pair.
+ typedef std::pair<uint32_t, DeclID> KindDeclIDPair;
+
+ // FIXME: Turn these into classes so we can have some type safety when
+ // we go from local ID to global and vice-versa.
+ typedef DeclID LocalDeclID;
+ typedef DeclID GlobalDeclID;
+
+ /// \brief An ID number that refers to a type in an AST file.
+ ///
+ /// The ID of a type is partitioned into two parts: the lower
+ /// three bits are used to store the const/volatile/restrict
+ /// qualifiers (as with QualType) and the upper bits provide a
+ /// type index. The type index values are partitioned into two
+ /// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
+ /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
+ /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
+ /// other types that have serialized representations.
+ typedef uint32_t TypeID;
+
+ /// \brief A type index; the type ID with the qualifier bits removed.
+ class TypeIdx {
+ uint32_t Idx;
+ public:
+ TypeIdx() : Idx(0) { }
+ explicit TypeIdx(uint32_t index) : Idx(index) { }
+
+ uint32_t getIndex() const { return Idx; }
+ TypeID asTypeID(unsigned FastQuals) const {
+ if (Idx == uint32_t(-1))
+ return TypeID(-1);
+
+ return (Idx << Qualifiers::FastWidth) | FastQuals;
+ }
+ static TypeIdx fromTypeID(TypeID ID) {
+ if (ID == TypeID(-1))
+ return TypeIdx(-1);
+
+ return TypeIdx(ID >> Qualifiers::FastWidth);
+ }
+ };
+
+ /// A structure for putting "fast"-unqualified QualTypes into a
+ /// DenseMap. This uses the standard pointer hash function.
+ struct UnsafeQualTypeDenseMapInfo {
+ static inline bool isEqual(QualType A, QualType B) { return A == B; }
+ static inline QualType getEmptyKey() {
+ return QualType::getFromOpaquePtr((void*) 1);
+ }
+ static inline QualType getTombstoneKey() {
+ return QualType::getFromOpaquePtr((void*) 2);
+ }
+ static inline unsigned getHashValue(QualType T) {
+ assert(!T.getLocalFastQualifiers() &&
+ "hash invalid for types with fast quals");
+ uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ return (unsigned(v) >> 4) ^ (unsigned(v) >> 9);
+ }
+ };
+
+ /// \brief An ID number that refers to an identifier in an AST file.
+ typedef uint32_t IdentID;
+
+ /// \brief The number of predefined identifier IDs.
+ const unsigned int NUM_PREDEF_IDENT_IDS = 1;
+
+ /// \brief An ID number that refers to a macro in an AST file.
+ typedef uint32_t MacroID;
+
+ /// \brief The number of predefined macro IDs.
+ const unsigned int NUM_PREDEF_MACRO_IDS = 1;
+
+ /// \brief An ID number that refers to an ObjC selector in an AST file.
+ typedef uint32_t SelectorID;
+
+ /// \brief The number of predefined selector IDs.
+ const unsigned int NUM_PREDEF_SELECTOR_IDS = 1;
+
+ /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an
+ /// AST file.
+ typedef uint32_t CXXBaseSpecifiersID;
+
+ /// \brief An ID number that refers to an entity in the detailed
+ /// preprocessing record.
+ typedef uint32_t PreprocessedEntityID;
+
+ /// \brief An ID number that refers to a submodule in a module file.
+ typedef uint32_t SubmoduleID;
+
+ /// \brief The number of predefined submodule IDs.
+ const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
+
+ /// \brief Source range/offset of a preprocessed entity.
+ struct PPEntityOffset {
+ /// \brief Raw source location of beginning of range.
+ unsigned Begin;
+ /// \brief Raw source location of end of range.
+ unsigned End;
+ /// \brief Offset in the AST file.
+ uint32_t BitOffset;
+
+ PPEntityOffset(SourceRange R, uint32_t BitOffset)
+ : Begin(R.getBegin().getRawEncoding()),
+ End(R.getEnd().getRawEncoding()),
+ BitOffset(BitOffset) { }
+ };
+
+ /// \brief Source range/offset of a preprocessed entity.
+ struct DeclOffset {
+ /// \brief Raw source location.
+ unsigned Loc;
+ /// \brief Offset in the AST file.
+ uint32_t BitOffset;
+
+ DeclOffset() : Loc(0), BitOffset(0) { }
+ DeclOffset(SourceLocation Loc, uint32_t BitOffset)
+ : Loc(Loc.getRawEncoding()),
+ BitOffset(BitOffset) { }
+ void setLocation(SourceLocation L) {
+ Loc = L.getRawEncoding();
+ }
+ };
+
+ /// \brief The number of predefined preprocessed entity IDs.
+ const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;
+
+ /// \brief Describes the various kinds of blocks that occur within
+ /// an AST file.
+ enum BlockIDs {
+ /// \brief The AST block, which acts as a container around the
+ /// full AST block.
+ AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID,
+
+ /// \brief The block containing information about the source
+ /// manager.
+ SOURCE_MANAGER_BLOCK_ID,
+
+ /// \brief The block containing information about the
+ /// preprocessor.
+ PREPROCESSOR_BLOCK_ID,
+
+ /// \brief The block containing the definitions of all of the
+ /// types and decls used within the AST file.
+ DECLTYPES_BLOCK_ID,
+
+ /// \brief The block containing DECL_UPDATES records.
+ DECL_UPDATES_BLOCK_ID,
+
+ /// \brief The block containing the detailed preprocessing record.
+ PREPROCESSOR_DETAIL_BLOCK_ID,
+
+ /// \brief The block containing the submodule structure.
+ SUBMODULE_BLOCK_ID,
+
+ /// \brief The block containing comments.
+ COMMENTS_BLOCK_ID,
+
+ /// \brief The control block, which contains all of the
+ /// information that needs to be validated prior to committing
+ /// to loading the AST file.
+ CONTROL_BLOCK_ID,
+
+ /// \brief The block of input files, which were used as inputs
+ /// to create this AST file.
+ ///
+ /// This block is part of the control block.
+ INPUT_FILES_BLOCK_ID
+ };
+
+ /// \brief Record types that occur within the control block.
+ enum ControlRecordTypes {
+ /// \brief AST file metadata, including the AST file version number
+ /// and information about the compiler used to build this AST file.
+ METADATA = 1,
+
+ /// \brief Record code for the list of other AST files imported by
+ /// this AST file.
+ IMPORTS = 2,
+
+ /// \brief Record code for the language options table.
+ ///
+ /// The record with this code contains the contents of the
+ /// LangOptions structure. We serialize the entire contents of
+ /// the structure, and let the reader decide which options are
+ /// actually important to check.
+ LANGUAGE_OPTIONS = 3,
+
+ /// \brief Record code for the target options table.
+ TARGET_OPTIONS = 4,
+
+ /// \brief Record code for the original file that was used to
+ /// generate the AST file, including both its file ID and its
+ /// name.
+ ORIGINAL_FILE = 5,
+
+ /// \brief The directory that the PCH was originally created in.
+ ORIGINAL_PCH_DIR = 6,
+
+ /// \brief Record code for file ID of the file or buffer that was used to
+ /// generate the AST file.
+ ORIGINAL_FILE_ID = 7,
+
+ /// \brief Offsets into the input-files block where input files
+ /// reside.
+ INPUT_FILE_OFFSETS = 8,
+
+ /// \brief Record code for the diagnostic options table.
+ DIAGNOSTIC_OPTIONS = 9,
+
+ /// \brief Record code for the filesystem options table.
+ FILE_SYSTEM_OPTIONS = 10,
+
+ /// \brief Record code for the headers search options table.
+ HEADER_SEARCH_OPTIONS = 11,
+
+ /// \brief Record code for the preprocessor options table.
+ PREPROCESSOR_OPTIONS = 12
+ };
+
+ /// \brief Record types that occur within the input-files block
+ /// inside the control block.
+ enum InputFileRecordTypes {
+ /// \brief An input file.
+ INPUT_FILE = 1
+ };
+
+ /// \brief Record types that occur within the AST block itself.
+ enum ASTRecordTypes {
+ /// \brief Record code for the offsets of each type.
+ ///
+ /// The TYPE_OFFSET constant describes the record that occurs
+ /// within the AST block. The record itself is an array of offsets that
+ /// point into the declarations and types block (identified by
+ /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
+ /// of a type. For a given type ID @c T, the lower three bits of
+ /// @c T are its qualifiers (const, volatile, restrict), as in
+ /// the QualType class. The upper bits, after being shifted and
+ /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
+ /// TYPE_OFFSET block to determine the offset of that type's
+ /// corresponding record within the DECLTYPES_BLOCK_ID block.
+ TYPE_OFFSET = 1,
+
+ /// \brief Record code for the offsets of each decl.
+ ///
+ /// The DECL_OFFSET constant describes the record that occurs
+ /// within the block identified by DECL_OFFSETS_BLOCK_ID within
+ /// the AST block. The record itself is an array of offsets that
+ /// point into the declarations and types block (identified by
+ /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
+ /// record, after subtracting one to account for the use of
+ /// declaration ID 0 for a NULL declaration pointer. Index 0 is
+ /// reserved for the translation unit declaration.
+ DECL_OFFSET = 2,
+
+ /// \brief Record code for the table of offsets of each
+ /// identifier ID.
+ ///
+ /// The offset table contains offsets into the blob stored in
+ /// the IDENTIFIER_TABLE record. Each offset points to the
+ /// NULL-terminated string that corresponds to that identifier.
+ IDENTIFIER_OFFSET = 3,
+
+ /// \brief This is so that older clang versions, before the introduction
+ /// of the control block, can read and reject the newer PCH format.
+ /// *DON"T CHANGE THIS NUMBER*.
+ METADATA_OLD_FORMAT = 4,
+
+ /// \brief Record code for the identifier table.
+ ///
+ /// The identifier table is a simple blob that contains
+ /// NULL-terminated strings for all of the identifiers
+ /// referenced by the AST file. The IDENTIFIER_OFFSET table
+ /// contains the mapping from identifier IDs to the characters
+ /// in this blob. Note that the starting offsets of all of the
+ /// identifiers are odd, so that, when the identifier offset
+ /// table is loaded in, we can use the low bit to distinguish
+ /// between offsets (for unresolved identifier IDs) and
+ /// IdentifierInfo pointers (for already-resolved identifier
+ /// IDs).
+ IDENTIFIER_TABLE = 5,
+
+ /// \brief Record code for the array of external definitions.
+ ///
+ /// The AST file contains a list of all of the unnamed external
+ /// definitions present within the parsed headers, stored as an
+ /// array of declaration IDs. These external definitions will be
+ /// reported to the AST consumer after the AST file has been
+ /// read, since their presence can affect the semantics of the
+ /// program (e.g., for code generation).
+ EXTERNAL_DEFINITIONS = 6,
+
+ /// \brief Record code for the set of non-builtin, special
+ /// types.
+ ///
+ /// This record contains the type IDs for the various type nodes
+ /// that are constructed during semantic analysis (e.g.,
+ /// __builtin_va_list). The SPECIAL_TYPE_* constants provide
+ /// offsets into this record.
+ SPECIAL_TYPES = 7,
+
+ /// \brief Record code for the extra statistics we gather while
+ /// generating an AST file.
+ STATISTICS = 8,
+
+ /// \brief Record code for the array of tentative definitions.
+ TENTATIVE_DEFINITIONS = 9,
+
+ /// \brief Record code for the array of locally-scoped external
+ /// declarations.
+ LOCALLY_SCOPED_EXTERNAL_DECLS = 10,
+
+ /// \brief Record code for the table of offsets into the
+ /// Objective-C method pool.
+ SELECTOR_OFFSETS = 11,
+
+ /// \brief Record code for the Objective-C method pool,
+ METHOD_POOL = 12,
+
+ /// \brief The value of the next __COUNTER__ to dispense.
+ /// [PP_COUNTER_VALUE, Val]
+ PP_COUNTER_VALUE = 13,
+
+ /// \brief Record code for the table of offsets into the block
+ /// of source-location information.
+ SOURCE_LOCATION_OFFSETS = 14,
+
+ /// \brief Record code for the set of source location entries
+ /// that need to be preloaded by the AST reader.
+ ///
+ /// This set contains the source location entry for the
+ /// predefines buffer and for any file entries that need to be
+ /// preloaded.
+ SOURCE_LOCATION_PRELOADS = 15,
+
+ /// \brief Record code for the set of ext_vector type names.
+ EXT_VECTOR_DECLS = 16,
+
+ /// \brief Record code for the array of unused file scoped decls.
+ UNUSED_FILESCOPED_DECLS = 17,
+
+ /// \brief Record code for the table of offsets to entries in the
+ /// preprocessing record.
+ PPD_ENTITIES_OFFSETS = 18,
+
+ /// \brief Record code for the array of VTable uses.
+ VTABLE_USES = 19,
+
+ /// \brief Record code for the array of dynamic classes.
+ DYNAMIC_CLASSES = 20,
+
+ /// \brief Record code for referenced selector pool.
+ REFERENCED_SELECTOR_POOL = 21,
+
+ /// \brief Record code for an update to the TU's lexically contained
+ /// declarations.
+ TU_UPDATE_LEXICAL = 22,
+
+ /// \brief Record code for the array describing the locations (in the
+ /// LOCAL_REDECLARATIONS record) of the redeclaration chains, indexed by
+ /// the first known ID.
+ LOCAL_REDECLARATIONS_MAP = 23,
+
+ /// \brief Record code for declarations that Sema keeps references of.
+ SEMA_DECL_REFS = 24,
+
+ /// \brief Record code for weak undeclared identifiers.
+ WEAK_UNDECLARED_IDENTIFIERS = 25,
+
+ /// \brief Record code for pending implicit instantiations.
+ PENDING_IMPLICIT_INSTANTIATIONS = 26,
+
+ /// \brief Record code for a decl replacement block.
+ ///
+ /// If a declaration is modified after having been deserialized, and then
+ /// written to a dependent AST file, its ID and offset must be added to
+ /// the replacement block.
+ DECL_REPLACEMENTS = 27,
+
+ /// \brief Record code for an update to a decl context's lookup table.
+ ///
+ /// In practice, this should only be used for the TU and namespaces.
+ UPDATE_VISIBLE = 28,
+
+ /// \brief Record for offsets of DECL_UPDATES records for declarations
+ /// that were modified after being deserialized and need updates.
+ DECL_UPDATE_OFFSETS = 29,
+
+ /// \brief Record of updates for a declaration that was modified after
+ /// being deserialized.
+ DECL_UPDATES = 30,
+
+ /// \brief Record code for the table of offsets to CXXBaseSpecifier
+ /// sets.
+ CXX_BASE_SPECIFIER_OFFSETS = 31,
+
+ /// \brief Record code for \#pragma diagnostic mappings.
+ DIAG_PRAGMA_MAPPINGS = 32,
+
+ /// \brief Record code for special CUDA declarations.
+ CUDA_SPECIAL_DECL_REFS = 33,
+
+ /// \brief Record code for header search information.
+ HEADER_SEARCH_TABLE = 34,
+
+ /// \brief Record code for floating point \#pragma options.
+ FP_PRAGMA_OPTIONS = 35,
+
+ /// \brief Record code for enabled OpenCL extensions.
+ OPENCL_EXTENSIONS = 36,
+
+ /// \brief The list of delegating constructor declarations.
+ DELEGATING_CTORS = 37,
+
+ /// \brief Record code for the set of known namespaces, which are used
+ /// for typo correction.
+ KNOWN_NAMESPACES = 38,
+
+ /// \brief Record code for the remapping information used to relate
+ /// loaded modules to the various offsets and IDs(e.g., source location
+ /// offests, declaration and type IDs) that are used in that module to
+ /// refer to other modules.
+ MODULE_OFFSET_MAP = 39,
+
+ /// \brief Record code for the source manager line table information,
+ /// which stores information about \#line directives.
+ SOURCE_MANAGER_LINE_TABLE = 40,
+
+ /// \brief Record code for map of Objective-C class definition IDs to the
+ /// ObjC categories in a module that are attached to that class.
+ OBJC_CATEGORIES_MAP = 41,
+
+ /// \brief Record code for a file sorted array of DeclIDs in a module.
+ FILE_SORTED_DECLS = 42,
+
+ /// \brief Record code for an array of all of the (sub)modules that were
+ /// imported by the AST file.
+ IMPORTED_MODULES = 43,
+
+ /// \brief Record code for the set of merged declarations in an AST file.
+ MERGED_DECLARATIONS = 44,
+
+ /// \brief Record code for the array of redeclaration chains.
+ ///
+ /// This array can only be interpreted properly using the local
+ /// redeclarations map.
+ LOCAL_REDECLARATIONS = 45,
+
+ /// \brief Record code for the array of Objective-C categories (including
+ /// extensions).
+ ///
+ /// This array can only be interpreted properly using the Objective-C
+ /// categories map.
+ OBJC_CATEGORIES = 46,
+
+ /// \brief Record code for the table of offsets of each macro ID.
+ ///
+ /// The offset table contains offsets into the blob stored in
+ /// the preprocessor block. Each offset points to the corresponding
+ /// macro definition.
+ MACRO_OFFSET = 47,
+
+ /// \brief Record of updates for a macro that was modified after
+ /// being deserialized.
+ MACRO_UPDATES = 48
+ };
+
+ /// \brief Record types used within a source manager block.
+ enum SourceManagerRecordTypes {
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// file.
+ SM_SLOC_FILE_ENTRY = 1,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// buffer.
+ SM_SLOC_BUFFER_ENTRY = 2,
+ /// \brief Describes a blob that contains the data for a buffer
+ /// entry. This kind of record always directly follows a
+ /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an
+ /// overridden buffer.
+ SM_SLOC_BUFFER_BLOB = 3,
+ /// \brief Describes a source location entry (SLocEntry) for a
+ /// macro expansion.
+ SM_SLOC_EXPANSION_ENTRY = 4
+ };
+
+ /// \brief Record types used within a preprocessor block.
+ enum PreprocessorRecordTypes {
+ // The macros in the PP section are a PP_MACRO_* instance followed by a
+ // list of PP_TOKEN instances for each token in the definition.
+
+ /// \brief An object-like macro definition.
+ /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed]
+ PP_MACRO_OBJECT_LIKE = 1,
+
+ /// \brief A function-like macro definition.
+ /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs,
+ /// IsGNUVarars, NumArgs, ArgIdentInfoID* ]
+ PP_MACRO_FUNCTION_LIKE = 2,
+
+ /// \brief Describes one token.
+ /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags]
+ PP_TOKEN = 3
+ };
+
+ /// \brief Record types used within a preprocessor detail block.
+ enum PreprocessorDetailRecordTypes {
+ /// \brief Describes a macro expansion within the preprocessing record.
+ PPD_MACRO_EXPANSION = 0,
+
+ /// \brief Describes a macro definition within the preprocessing record.
+ PPD_MACRO_DEFINITION = 1,
+
+ /// \brief Describes an inclusion directive within the preprocessing
+ /// record.
+ PPD_INCLUSION_DIRECTIVE = 2
+ };
+
+ /// \brief Record types used within a submodule description block.
+ enum SubmoduleRecordTypes {
+ /// \brief Metadata for submodules as a whole.
+ SUBMODULE_METADATA = 0,
+ /// \brief Defines the major attributes of a submodule, including its
+ /// name and parent.
+ SUBMODULE_DEFINITION = 1,
+ /// \brief Specifies the umbrella header used to create this module,
+ /// if any.
+ SUBMODULE_UMBRELLA_HEADER = 2,
+ /// \brief Specifies a header that falls into this (sub)module.
+ SUBMODULE_HEADER = 3,
+ /// \brief Specifies a top-level header that falls into this (sub)module.
+ SUBMODULE_TOPHEADER = 4,
+ /// \brief Specifies an umbrella directory.
+ SUBMODULE_UMBRELLA_DIR = 5,
+ /// \brief Specifies the submodules that are imported by this
+ /// submodule.
+ SUBMODULE_IMPORTS = 6,
+ /// \brief Specifies the submodules that are re-exported from this
+ /// submodule.
+ SUBMODULE_EXPORTS = 7,
+ /// \brief Specifies a required feature.
+ SUBMODULE_REQUIRES = 8,
+ /// \brief Specifies a header that has been explicitly excluded
+ /// from this submodule.
+ SUBMODULE_EXCLUDED_HEADER = 9
+ };
+
+ /// \brief Record types used within a comments block.
+ enum CommentRecordTypes {
+ COMMENTS_RAW_COMMENT = 0
+ };
+
+ /// \defgroup ASTAST AST file AST constants
+ ///
+ /// The constants in this group describe various components of the
+ /// abstract syntax tree within an AST file.
+ ///
+ /// @{
+
+ /// \brief Predefined type IDs.
+ ///
+ /// These type IDs correspond to predefined types in the AST
+ /// context, such as built-in types (int) and special place-holder
+ /// types (the \<overload> and \<dependent> type markers). Such
+ /// types are never actually serialized, since they will be built
+ /// by the AST context when it is created.
+ enum PredefinedTypeIDs {
+ /// \brief The NULL type.
+ PREDEF_TYPE_NULL_ID = 0,
+ /// \brief The void type.
+ PREDEF_TYPE_VOID_ID = 1,
+ /// \brief The 'bool' or '_Bool' type.
+ PREDEF_TYPE_BOOL_ID = 2,
+ /// \brief The 'char' type, when it is unsigned.
+ PREDEF_TYPE_CHAR_U_ID = 3,
+ /// \brief The 'unsigned char' type.
+ PREDEF_TYPE_UCHAR_ID = 4,
+ /// \brief The 'unsigned short' type.
+ PREDEF_TYPE_USHORT_ID = 5,
+ /// \brief The 'unsigned int' type.
+ PREDEF_TYPE_UINT_ID = 6,
+ /// \brief The 'unsigned long' type.
+ PREDEF_TYPE_ULONG_ID = 7,
+ /// \brief The 'unsigned long long' type.
+ PREDEF_TYPE_ULONGLONG_ID = 8,
+ /// \brief The 'char' type, when it is signed.
+ PREDEF_TYPE_CHAR_S_ID = 9,
+ /// \brief The 'signed char' type.
+ PREDEF_TYPE_SCHAR_ID = 10,
+ /// \brief The C++ 'wchar_t' type.
+ PREDEF_TYPE_WCHAR_ID = 11,
+ /// \brief The (signed) 'short' type.
+ PREDEF_TYPE_SHORT_ID = 12,
+ /// \brief The (signed) 'int' type.
+ PREDEF_TYPE_INT_ID = 13,
+ /// \brief The (signed) 'long' type.
+ PREDEF_TYPE_LONG_ID = 14,
+ /// \brief The (signed) 'long long' type.
+ PREDEF_TYPE_LONGLONG_ID = 15,
+ /// \brief The 'float' type.
+ PREDEF_TYPE_FLOAT_ID = 16,
+ /// \brief The 'double' type.
+ PREDEF_TYPE_DOUBLE_ID = 17,
+ /// \brief The 'long double' type.
+ PREDEF_TYPE_LONGDOUBLE_ID = 18,
+ /// \brief The placeholder type for overloaded function sets.
+ PREDEF_TYPE_OVERLOAD_ID = 19,
+ /// \brief The placeholder type for dependent types.
+ PREDEF_TYPE_DEPENDENT_ID = 20,
+ /// \brief The '__uint128_t' type.
+ PREDEF_TYPE_UINT128_ID = 21,
+ /// \brief The '__int128_t' type.
+ PREDEF_TYPE_INT128_ID = 22,
+ /// \brief The type of 'nullptr'.
+ PREDEF_TYPE_NULLPTR_ID = 23,
+ /// \brief The C++ 'char16_t' type.
+ PREDEF_TYPE_CHAR16_ID = 24,
+ /// \brief The C++ 'char32_t' type.
+ PREDEF_TYPE_CHAR32_ID = 25,
+ /// \brief The ObjC 'id' type.
+ PREDEF_TYPE_OBJC_ID = 26,
+ /// \brief The ObjC 'Class' type.
+ PREDEF_TYPE_OBJC_CLASS = 27,
+ /// \brief The ObjC 'SEL' type.
+ PREDEF_TYPE_OBJC_SEL = 28,
+ /// \brief The 'unknown any' placeholder type.
+ PREDEF_TYPE_UNKNOWN_ANY = 29,
+ /// \brief The placeholder type for bound member functions.
+ PREDEF_TYPE_BOUND_MEMBER = 30,
+ /// \brief The "auto" deduction type.
+ PREDEF_TYPE_AUTO_DEDUCT = 31,
+ /// \brief The "auto &&" deduction type.
+ PREDEF_TYPE_AUTO_RREF_DEDUCT = 32,
+ /// \brief The OpenCL 'half' / ARM NEON __fp16 type.
+ PREDEF_TYPE_HALF_ID = 33,
+ /// \brief ARC's unbridged-cast placeholder type.
+ PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
+ /// \brief The pseudo-object placeholder type.
+ PREDEF_TYPE_PSEUDO_OBJECT = 35,
+ /// \brief The __va_list_tag placeholder type.
+ PREDEF_TYPE_VA_LIST_TAG = 36,
+ /// \brief The placeholder type for builtin functions.
+ PREDEF_TYPE_BUILTIN_FN = 37
+ };
+
+ /// \brief The number of predefined type IDs that are reserved for
+ /// the PREDEF_TYPE_* constants.
+ ///
+ /// Type IDs for non-predefined types will start at
+ /// NUM_PREDEF_TYPE_IDs.
+ const unsigned NUM_PREDEF_TYPE_IDS = 100;
+
+ /// \brief The number of allowed abbreviations in bits
+ const unsigned NUM_ALLOWED_ABBREVS_SIZE = 4;
+
+ /// \brief Record codes for each kind of type.
+ ///
+ /// These constants describe the type records that can occur within a
+ /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each
+ /// constant describes a record for a specific type class in the
+ /// AST.
+ enum TypeCode {
+ /// \brief An ExtQualType record.
+ TYPE_EXT_QUAL = 1,
+ /// \brief A ComplexType record.
+ TYPE_COMPLEX = 3,
+ /// \brief A PointerType record.
+ TYPE_POINTER = 4,
+ /// \brief A BlockPointerType record.
+ TYPE_BLOCK_POINTER = 5,
+ /// \brief An LValueReferenceType record.
+ TYPE_LVALUE_REFERENCE = 6,
+ /// \brief An RValueReferenceType record.
+ TYPE_RVALUE_REFERENCE = 7,
+ /// \brief A MemberPointerType record.
+ TYPE_MEMBER_POINTER = 8,
+ /// \brief A ConstantArrayType record.
+ TYPE_CONSTANT_ARRAY = 9,
+ /// \brief An IncompleteArrayType record.
+ TYPE_INCOMPLETE_ARRAY = 10,
+ /// \brief A VariableArrayType record.
+ TYPE_VARIABLE_ARRAY = 11,
+ /// \brief A VectorType record.
+ TYPE_VECTOR = 12,
+ /// \brief An ExtVectorType record.
+ TYPE_EXT_VECTOR = 13,
+ /// \brief A FunctionNoProtoType record.
+ TYPE_FUNCTION_NO_PROTO = 14,
+ /// \brief A FunctionProtoType record.
+ TYPE_FUNCTION_PROTO = 15,
+ /// \brief A TypedefType record.
+ TYPE_TYPEDEF = 16,
+ /// \brief A TypeOfExprType record.
+ TYPE_TYPEOF_EXPR = 17,
+ /// \brief A TypeOfType record.
+ TYPE_TYPEOF = 18,
+ /// \brief A RecordType record.
+ TYPE_RECORD = 19,
+ /// \brief An EnumType record.
+ TYPE_ENUM = 20,
+ /// \brief An ObjCInterfaceType record.
+ TYPE_OBJC_INTERFACE = 21,
+ /// \brief An ObjCObjectPointerType record.
+ TYPE_OBJC_OBJECT_POINTER = 22,
+ /// \brief a DecltypeType record.
+ TYPE_DECLTYPE = 23,
+ /// \brief An ElaboratedType record.
+ TYPE_ELABORATED = 24,
+ /// \brief A SubstTemplateTypeParmType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM = 25,
+ /// \brief An UnresolvedUsingType record.
+ TYPE_UNRESOLVED_USING = 26,
+ /// \brief An InjectedClassNameType record.
+ TYPE_INJECTED_CLASS_NAME = 27,
+ /// \brief An ObjCObjectType record.
+ TYPE_OBJC_OBJECT = 28,
+ /// \brief An TemplateTypeParmType record.
+ TYPE_TEMPLATE_TYPE_PARM = 29,
+ /// \brief An TemplateSpecializationType record.
+ TYPE_TEMPLATE_SPECIALIZATION = 30,
+ /// \brief A DependentNameType record.
+ TYPE_DEPENDENT_NAME = 31,
+ /// \brief A DependentTemplateSpecializationType record.
+ TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32,
+ /// \brief A DependentSizedArrayType record.
+ TYPE_DEPENDENT_SIZED_ARRAY = 33,
+ /// \brief A ParenType record.
+ TYPE_PAREN = 34,
+ /// \brief A PackExpansionType record.
+ TYPE_PACK_EXPANSION = 35,
+ /// \brief An AttributedType record.
+ TYPE_ATTRIBUTED = 36,
+ /// \brief A SubstTemplateTypeParmPackType record.
+ TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
+ /// \brief A AutoType record.
+ TYPE_AUTO = 38,
+ /// \brief A UnaryTransformType record.
+ TYPE_UNARY_TRANSFORM = 39,
+ /// \brief An AtomicType record.
+ TYPE_ATOMIC = 40
+ };
+
+ /// \brief The type IDs for special types constructed by semantic
+ /// analysis.
+ ///
+ /// The constants in this enumeration are indices into the
+ /// SPECIAL_TYPES record.
+ enum SpecialTypeIDs {
+ /// \brief CFConstantString type
+ SPECIAL_TYPE_CF_CONSTANT_STRING = 0,
+ /// \brief C FILE typedef type
+ SPECIAL_TYPE_FILE = 1,
+ /// \brief C jmp_buf typedef type
+ SPECIAL_TYPE_JMP_BUF = 2,
+ /// \brief C sigjmp_buf typedef type
+ SPECIAL_TYPE_SIGJMP_BUF = 3,
+ /// \brief Objective-C "id" redefinition type
+ SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4,
+ /// \brief Objective-C "Class" redefinition type
+ SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5,
+ /// \brief Objective-C "SEL" redefinition type
+ SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6,
+ /// \brief C ucontext_t typedef type
+ SPECIAL_TYPE_UCONTEXT_T = 7
+ };
+
+ /// \brief The number of special type IDs.
+ const unsigned NumSpecialTypeIDs = 8;
+
+ /// \brief Predefined declaration IDs.
+ ///
+ /// These declaration IDs correspond to predefined declarations in the AST
+ /// context, such as the NULL declaration ID. Such declarations are never
+ /// actually serialized, since they will be built by the AST context when
+ /// it is created.
+ enum PredefinedDeclIDs {
+ /// \brief The NULL declaration.
+ PREDEF_DECL_NULL_ID = 0,
+
+ /// \brief The translation unit.
+ PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
+
+ /// \brief The Objective-C 'id' type.
+ PREDEF_DECL_OBJC_ID_ID = 2,
+
+ /// \brief The Objective-C 'SEL' type.
+ PREDEF_DECL_OBJC_SEL_ID = 3,
+
+ /// \brief The Objective-C 'Class' type.
+ PREDEF_DECL_OBJC_CLASS_ID = 4,
+
+ /// \brief The Objective-C 'Protocol' type.
+ PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
+
+ /// \brief The signed 128-bit integer type.
+ PREDEF_DECL_INT_128_ID = 6,
+
+ /// \brief The unsigned 128-bit integer type.
+ PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
+
+ /// \brief The internal 'instancetype' typedef.
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
+
+ /// \brief The internal '__builtin_va_list' typedef.
+ PREDEF_DECL_BUILTIN_VA_LIST_ID = 9
+ };
+
+ /// \brief 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 = 10;
+
+ /// \brief Record codes for each kind of declaration.
+ ///
+ /// These constants describe the declaration records that can occur within
+ /// a declarations block (identified by DECLS_BLOCK_ID). Each
+ /// constant describes a record for a specific declaration class
+ /// in the AST.
+ enum DeclCode {
+ /// \brief A TypedefDecl record.
+ DECL_TYPEDEF = 51,
+ /// \brief A TypeAliasDecl record.
+ DECL_TYPEALIAS,
+ /// \brief An EnumDecl record.
+ DECL_ENUM,
+ /// \brief A RecordDecl record.
+ DECL_RECORD,
+ /// \brief An EnumConstantDecl record.
+ DECL_ENUM_CONSTANT,
+ /// \brief A FunctionDecl record.
+ DECL_FUNCTION,
+ /// \brief A ObjCMethodDecl record.
+ DECL_OBJC_METHOD,
+ /// \brief A ObjCInterfaceDecl record.
+ DECL_OBJC_INTERFACE,
+ /// \brief A ObjCProtocolDecl record.
+ DECL_OBJC_PROTOCOL,
+ /// \brief A ObjCIvarDecl record.
+ DECL_OBJC_IVAR,
+ /// \brief A ObjCAtDefsFieldDecl record.
+ DECL_OBJC_AT_DEFS_FIELD,
+ /// \brief A ObjCCategoryDecl record.
+ DECL_OBJC_CATEGORY,
+ /// \brief A ObjCCategoryImplDecl record.
+ DECL_OBJC_CATEGORY_IMPL,
+ /// \brief A ObjCImplementationDecl record.
+ DECL_OBJC_IMPLEMENTATION,
+ /// \brief A ObjCCompatibleAliasDecl record.
+ DECL_OBJC_COMPATIBLE_ALIAS,
+ /// \brief A ObjCPropertyDecl record.
+ DECL_OBJC_PROPERTY,
+ /// \brief A ObjCPropertyImplDecl record.
+ DECL_OBJC_PROPERTY_IMPL,
+ /// \brief A FieldDecl record.
+ DECL_FIELD,
+ /// \brief A VarDecl record.
+ DECL_VAR,
+ /// \brief An ImplicitParamDecl record.
+ DECL_IMPLICIT_PARAM,
+ /// \brief A ParmVarDecl record.
+ DECL_PARM_VAR,
+ /// \brief A FileScopeAsmDecl record.
+ DECL_FILE_SCOPE_ASM,
+ /// \brief A BlockDecl record.
+ DECL_BLOCK,
+ /// \brief A record that stores the set of declarations that are
+ /// lexically stored within a given DeclContext.
+ ///
+ /// The record itself is a blob that is an array of declaration IDs,
+ /// in the order in which those declarations were added to the
+ /// declaration context. This data is used when iterating over
+ /// the contents of a DeclContext, e.g., via
+ /// DeclContext::decls_begin() and DeclContext::decls_end().
+ DECL_CONTEXT_LEXICAL,
+ /// \brief A record that stores the set of declarations that are
+ /// visible from a given DeclContext.
+ ///
+ /// The record itself stores a set of mappings, each of which
+ /// associates a declaration name with one or more declaration
+ /// IDs. This data is used when performing qualified name lookup
+ /// into a DeclContext via DeclContext::lookup.
+ DECL_CONTEXT_VISIBLE,
+ /// \brief A LabelDecl record.
+ DECL_LABEL,
+ /// \brief A NamespaceDecl record.
+ DECL_NAMESPACE,
+ /// \brief A NamespaceAliasDecl record.
+ DECL_NAMESPACE_ALIAS,
+ /// \brief A UsingDecl record.
+ DECL_USING,
+ /// \brief A UsingShadowDecl record.
+ DECL_USING_SHADOW,
+ /// \brief A UsingDirecitveDecl record.
+ DECL_USING_DIRECTIVE,
+ /// \brief An UnresolvedUsingValueDecl record.
+ DECL_UNRESOLVED_USING_VALUE,
+ /// \brief An UnresolvedUsingTypenameDecl record.
+ DECL_UNRESOLVED_USING_TYPENAME,
+ /// \brief A LinkageSpecDecl record.
+ DECL_LINKAGE_SPEC,
+ /// \brief A CXXRecordDecl record.
+ DECL_CXX_RECORD,
+ /// \brief A CXXMethodDecl record.
+ DECL_CXX_METHOD,
+ /// \brief A CXXConstructorDecl record.
+ DECL_CXX_CONSTRUCTOR,
+ /// \brief A CXXDestructorDecl record.
+ DECL_CXX_DESTRUCTOR,
+ /// \brief A CXXConversionDecl record.
+ DECL_CXX_CONVERSION,
+ /// \brief An AccessSpecDecl record.
+ DECL_ACCESS_SPEC,
+
+ /// \brief A FriendDecl record.
+ DECL_FRIEND,
+ /// \brief A FriendTemplateDecl record.
+ DECL_FRIEND_TEMPLATE,
+ /// \brief A ClassTemplateDecl record.
+ DECL_CLASS_TEMPLATE,
+ /// \brief A ClassTemplateSpecializationDecl record.
+ DECL_CLASS_TEMPLATE_SPECIALIZATION,
+ /// \brief A ClassTemplatePartialSpecializationDecl record.
+ DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION,
+ /// \brief A FunctionTemplateDecl record.
+ DECL_FUNCTION_TEMPLATE,
+ /// \brief A TemplateTypeParmDecl record.
+ DECL_TEMPLATE_TYPE_PARM,
+ /// \brief A NonTypeTemplateParmDecl record.
+ DECL_NON_TYPE_TEMPLATE_PARM,
+ /// \brief A TemplateTemplateParmDecl record.
+ DECL_TEMPLATE_TEMPLATE_PARM,
+ /// \brief A TypeAliasTemplateDecl record.
+ DECL_TYPE_ALIAS_TEMPLATE,
+ /// \brief A StaticAssertDecl record.
+ DECL_STATIC_ASSERT,
+ /// \brief A record containing CXXBaseSpecifiers.
+ DECL_CXX_BASE_SPECIFIERS,
+ /// \brief A IndirectFieldDecl record.
+ DECL_INDIRECTFIELD,
+ /// \brief A NonTypeTemplateParmDecl record that stores an expanded
+ /// non-type template parameter pack.
+ DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
+ /// \brief A TemplateTemplateParmDecl record that stores an expanded
+ /// template template parameter pack.
+ DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
+ /// \brief A ClassScopeFunctionSpecializationDecl record a class scope
+ /// function specialization. (Microsoft extension).
+ DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
+ /// \brief An ImportDecl recording a module import.
+ DECL_IMPORT
+ };
+
+ /// \brief Record codes for each kind of statement or expression.
+ ///
+ /// These constants describe the records that describe statements
+ /// or expressions. These records occur within type and declarations
+ /// block, so they begin with record values of 100. Each constant
+ /// describes a record for a specific statement or expression class in the
+ /// AST.
+ enum StmtCode {
+ /// \brief A marker record that indicates that we are at the end
+ /// of an expression.
+ STMT_STOP = 100,
+ /// \brief A NULL expression.
+ STMT_NULL_PTR,
+ /// \brief A reference to a previously [de]serialized Stmt record.
+ STMT_REF_PTR,
+ /// \brief A NullStmt record.
+ STMT_NULL,
+ /// \brief A CompoundStmt record.
+ STMT_COMPOUND,
+ /// \brief A CaseStmt record.
+ STMT_CASE,
+ /// \brief A DefaultStmt record.
+ STMT_DEFAULT,
+ /// \brief A LabelStmt record.
+ STMT_LABEL,
+ /// \brief An AttributedStmt record.
+ STMT_ATTRIBUTED,
+ /// \brief An IfStmt record.
+ STMT_IF,
+ /// \brief A SwitchStmt record.
+ STMT_SWITCH,
+ /// \brief A WhileStmt record.
+ STMT_WHILE,
+ /// \brief A DoStmt record.
+ STMT_DO,
+ /// \brief A ForStmt record.
+ STMT_FOR,
+ /// \brief A GotoStmt record.
+ STMT_GOTO,
+ /// \brief An IndirectGotoStmt record.
+ STMT_INDIRECT_GOTO,
+ /// \brief A ContinueStmt record.
+ STMT_CONTINUE,
+ /// \brief A BreakStmt record.
+ STMT_BREAK,
+ /// \brief A ReturnStmt record.
+ STMT_RETURN,
+ /// \brief A DeclStmt record.
+ STMT_DECL,
+ /// \brief A GCC-style AsmStmt record.
+ STMT_GCCASM,
+ /// \brief A MS-style AsmStmt record.
+ STMT_MSASM,
+ /// \brief A PredefinedExpr record.
+ EXPR_PREDEFINED,
+ /// \brief A DeclRefExpr record.
+ EXPR_DECL_REF,
+ /// \brief An IntegerLiteral record.
+ EXPR_INTEGER_LITERAL,
+ /// \brief A FloatingLiteral record.
+ EXPR_FLOATING_LITERAL,
+ /// \brief An ImaginaryLiteral record.
+ EXPR_IMAGINARY_LITERAL,
+ /// \brief A StringLiteral record.
+ EXPR_STRING_LITERAL,
+ /// \brief A CharacterLiteral record.
+ EXPR_CHARACTER_LITERAL,
+ /// \brief A ParenExpr record.
+ EXPR_PAREN,
+ /// \brief A ParenListExpr record.
+ EXPR_PAREN_LIST,
+ /// \brief A UnaryOperator record.
+ EXPR_UNARY_OPERATOR,
+ /// \brief An OffsetOfExpr record.
+ EXPR_OFFSETOF,
+ /// \brief A SizefAlignOfExpr record.
+ EXPR_SIZEOF_ALIGN_OF,
+ /// \brief An ArraySubscriptExpr record.
+ EXPR_ARRAY_SUBSCRIPT,
+ /// \brief A CallExpr record.
+ EXPR_CALL,
+ /// \brief A MemberExpr record.
+ EXPR_MEMBER,
+ /// \brief A BinaryOperator record.
+ EXPR_BINARY_OPERATOR,
+ /// \brief A CompoundAssignOperator record.
+ EXPR_COMPOUND_ASSIGN_OPERATOR,
+ /// \brief A ConditionOperator record.
+ EXPR_CONDITIONAL_OPERATOR,
+ /// \brief An ImplicitCastExpr record.
+ EXPR_IMPLICIT_CAST,
+ /// \brief A CStyleCastExpr record.
+ EXPR_CSTYLE_CAST,
+ /// \brief A CompoundLiteralExpr record.
+ EXPR_COMPOUND_LITERAL,
+ /// \brief An ExtVectorElementExpr record.
+ EXPR_EXT_VECTOR_ELEMENT,
+ /// \brief An InitListExpr record.
+ EXPR_INIT_LIST,
+ /// \brief A DesignatedInitExpr record.
+ EXPR_DESIGNATED_INIT,
+ /// \brief An ImplicitValueInitExpr record.
+ EXPR_IMPLICIT_VALUE_INIT,
+ /// \brief A VAArgExpr record.
+ EXPR_VA_ARG,
+ /// \brief An AddrLabelExpr record.
+ EXPR_ADDR_LABEL,
+ /// \brief A StmtExpr record.
+ EXPR_STMT,
+ /// \brief A ChooseExpr record.
+ EXPR_CHOOSE,
+ /// \brief A GNUNullExpr record.
+ EXPR_GNU_NULL,
+ /// \brief A ShuffleVectorExpr record.
+ EXPR_SHUFFLE_VECTOR,
+ /// \brief BlockExpr
+ EXPR_BLOCK,
+ /// \brief A GenericSelectionExpr record.
+ EXPR_GENERIC_SELECTION,
+ /// \brief A PseudoObjectExpr record.
+ EXPR_PSEUDO_OBJECT,
+ /// \brief An AtomicExpr record.
+ EXPR_ATOMIC,
+
+ // Objective-C
+
+ /// \brief An ObjCStringLiteral record.
+ EXPR_OBJC_STRING_LITERAL,
+
+ EXPR_OBJC_BOXED_EXPRESSION,
+ EXPR_OBJC_ARRAY_LITERAL,
+ EXPR_OBJC_DICTIONARY_LITERAL,
+
+
+ /// \brief An ObjCEncodeExpr record.
+ EXPR_OBJC_ENCODE,
+ /// \brief An ObjCSelectorExpr record.
+ EXPR_OBJC_SELECTOR_EXPR,
+ /// \brief An ObjCProtocolExpr record.
+ EXPR_OBJC_PROTOCOL_EXPR,
+ /// \brief An ObjCIvarRefExpr record.
+ EXPR_OBJC_IVAR_REF_EXPR,
+ /// \brief An ObjCPropertyRefExpr record.
+ EXPR_OBJC_PROPERTY_REF_EXPR,
+ /// \brief An ObjCSubscriptRefExpr record.
+ EXPR_OBJC_SUBSCRIPT_REF_EXPR,
+ /// \brief UNUSED
+ EXPR_OBJC_KVC_REF_EXPR,
+ /// \brief An ObjCMessageExpr record.
+ EXPR_OBJC_MESSAGE_EXPR,
+ /// \brief An ObjCIsa Expr record.
+ EXPR_OBJC_ISA,
+ /// \brief An ObjCIndirectCopyRestoreExpr record.
+ EXPR_OBJC_INDIRECT_COPY_RESTORE,
+
+ /// \brief An ObjCForCollectionStmt record.
+ STMT_OBJC_FOR_COLLECTION,
+ /// \brief An ObjCAtCatchStmt record.
+ STMT_OBJC_CATCH,
+ /// \brief An ObjCAtFinallyStmt record.
+ STMT_OBJC_FINALLY,
+ /// \brief An ObjCAtTryStmt record.
+ STMT_OBJC_AT_TRY,
+ /// \brief An ObjCAtSynchronizedStmt record.
+ STMT_OBJC_AT_SYNCHRONIZED,
+ /// \brief An ObjCAtThrowStmt record.
+ STMT_OBJC_AT_THROW,
+ /// \brief An ObjCAutoreleasePoolStmt record.
+ STMT_OBJC_AUTORELEASE_POOL,
+ /// \brief A ObjCBoolLiteralExpr record.
+ EXPR_OBJC_BOOL_LITERAL,
+
+ // C++
+
+ /// \brief A CXXCatchStmt record.
+ STMT_CXX_CATCH,
+ /// \brief A CXXTryStmt record.
+ STMT_CXX_TRY,
+ /// \brief A CXXForRangeStmt record.
+ STMT_CXX_FOR_RANGE,
+
+ /// \brief A CXXOperatorCallExpr record.
+ EXPR_CXX_OPERATOR_CALL,
+ /// \brief A CXXMemberCallExpr record.
+ EXPR_CXX_MEMBER_CALL,
+ /// \brief A CXXConstructExpr record.
+ EXPR_CXX_CONSTRUCT,
+ /// \brief A CXXTemporaryObjectExpr record.
+ EXPR_CXX_TEMPORARY_OBJECT,
+ /// \brief A CXXStaticCastExpr record.
+ EXPR_CXX_STATIC_CAST,
+ /// \brief A CXXDynamicCastExpr record.
+ EXPR_CXX_DYNAMIC_CAST,
+ /// \brief A CXXReinterpretCastExpr record.
+ EXPR_CXX_REINTERPRET_CAST,
+ /// \brief A CXXConstCastExpr record.
+ EXPR_CXX_CONST_CAST,
+ /// \brief A CXXFunctionalCastExpr record.
+ EXPR_CXX_FUNCTIONAL_CAST,
+ /// \brief A UserDefinedLiteral record.
+ EXPR_USER_DEFINED_LITERAL,
+ /// \brief A CXXBoolLiteralExpr record.
+ EXPR_CXX_BOOL_LITERAL,
+ EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr
+ EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr).
+ EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type).
+ EXPR_CXX_THIS, // CXXThisExpr
+ EXPR_CXX_THROW, // CXXThrowExpr
+ EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr
+ EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr
+
+ EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr
+ EXPR_CXX_NEW, // CXXNewExpr
+ EXPR_CXX_DELETE, // CXXDeleteExpr
+ EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr
+
+ EXPR_EXPR_WITH_CLEANUPS, // ExprWithCleanups
+
+ EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr
+ EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr
+ EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr
+ EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr
+ EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
+
+ EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
+ EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr
+ EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr
+
+ EXPR_OPAQUE_VALUE, // OpaqueValueExpr
+ EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
+ EXPR_TYPE_TRAIT, // TypeTraitExpr
+ EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
+
+ EXPR_PACK_EXPANSION, // PackExpansionExpr
+ EXPR_SIZEOF_PACK, // SizeOfPackExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, // SubstNonTypeTemplateParmExpr
+ EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
+ EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
+ EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
+
+ // CUDA
+ EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
+
+ // OpenCL
+ EXPR_ASTYPE, // AsTypeExpr
+
+ // Microsoft
+ EXPR_CXX_UUIDOF_EXPR, // CXXUuidofExpr (of expr).
+ EXPR_CXX_UUIDOF_TYPE, // CXXUuidofExpr (of type).
+ STMT_SEH_EXCEPT, // SEHExceptStmt
+ STMT_SEH_FINALLY, // SEHFinallyStmt
+ STMT_SEH_TRY, // SEHTryStmt
+
+ // ARC
+ EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
+
+ STMT_MS_DEPENDENT_EXISTS, // MSDependentExistsStmt
+ EXPR_LAMBDA // LambdaExpr
+ };
+
+ /// \brief The kinds of designators that can occur in a
+ /// DesignatedInitExpr.
+ enum DesignatorTypes {
+ /// \brief Field designator where only the field name is known.
+ DESIG_FIELD_NAME = 0,
+ /// \brief Field designator where the field has been resolved to
+ /// a declaration.
+ DESIG_FIELD_DECL = 1,
+ /// \brief Array designator.
+ DESIG_ARRAY = 2,
+ /// \brief GNU array range designator.
+ DESIG_ARRAY_RANGE = 3
+ };
+
+ /// \brief The different kinds of data that can occur in a
+ /// CtorInitializer.
+ enum CtorInitializerType {
+ CTOR_INITIALIZER_BASE,
+ CTOR_INITIALIZER_DELEGATING,
+ CTOR_INITIALIZER_MEMBER,
+ CTOR_INITIALIZER_INDIRECT_MEMBER
+ };
+
+ /// \brief Describes the redeclarations of a declaration.
+ struct LocalRedeclarationsInfo {
+ DeclID FirstID; // The ID of the first declaration
+ unsigned Offset; // Offset into the array of redeclaration chains.
+
+ friend bool operator<(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID < Y.FirstID;
+ }
+
+ friend bool operator>(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID > Y.FirstID;
+ }
+
+ friend bool operator<=(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID <= Y.FirstID;
+ }
+
+ friend bool operator>=(const LocalRedeclarationsInfo &X,
+ const LocalRedeclarationsInfo &Y) {
+ return X.FirstID >= Y.FirstID;
+ }
+ };
+
+ /// \brief Describes the categories of an Objective-C class.
+ struct ObjCCategoriesInfo {
+ DeclID DefinitionID; // The ID of the definition
+ unsigned Offset; // Offset into the array of category lists.
+
+ friend bool operator<(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID < Y.DefinitionID;
+ }
+
+ friend bool operator>(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID > Y.DefinitionID;
+ }
+
+ friend bool operator<=(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID <= Y.DefinitionID;
+ }
+
+ friend bool operator>=(const ObjCCategoriesInfo &X,
+ const ObjCCategoriesInfo &Y) {
+ return X.DefinitionID >= Y.DefinitionID;
+ }
+ };
+
+ /// @}
+ }
+} // end namespace clang
+
+#endif
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Dec 18 08:30:41 2012
@@ -874,15 +874,6 @@
InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel);
-
- if (LangOpts.OpenCL) {
- InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d);
- InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray);
- InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer);
- InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d);
- InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray);
- InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d);
- }
// Builtin type for __objc_yes and __objc_no
ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ?
@@ -1421,16 +1412,6 @@
Width = Target->getPointerWidth(0);
Align = Target->getPointerAlign(0);
break;
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- // Currently these types are pointers to opaque types.
- Width = Target->getPointerWidth(0);
- Align = Target->getPointerAlign(0);
- break;
}
break;
case Type::ObjCObjectPointer:
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Dec 18 08:30:41 2012
@@ -1,3580 +1,3574 @@
-//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implements C++ name mangling according to the Itanium C++ ABI,
-// which is used in GCC 3.2 and newer (and many compilers that are
-// ABI-compatible with GCC):
-//
-// http://www.codesourcery.com/public/cxx-abi/abi.html
-//
-//===----------------------------------------------------------------------===//
-#include "clang/AST/Mangle.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/AST/TypeLoc.h"
-#include "clang/Basic/ABI.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-
-#define MANGLE_CHECKER 0
-
-#if MANGLE_CHECKER
-#include <cxxabi.h>
-#endif
-
-using namespace clang;
-
-namespace {
-
-/// \brief Retrieve the declaration context that should be used when mangling
-/// the given declaration.
-static const DeclContext *getEffectiveDeclContext(const Decl *D) {
- // The ABI assumes that lambda closure types that occur within
- // default arguments live in the context of the function. However, due to
- // the way in which Clang parses and creates function declarations, this is
- // not the case: the lambda closure type ends up living in the context
- // where the function itself resides, because the function declaration itself
- // had not yet been created. Fix the context here.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (RD->isLambda())
- if (ParmVarDecl *ContextParam
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
- return ContextParam->getDeclContext();
- }
-
- return D->getDeclContext();
-}
-
-static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
- return getEffectiveDeclContext(cast<Decl>(DC));
-}
-
-static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
- const DeclContext *DC = dyn_cast<DeclContext>(ND);
- if (!DC)
- DC = getEffectiveDeclContext(ND);
- while (!DC->isNamespace() && !DC->isTranslationUnit()) {
- const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC));
- if (isa<FunctionDecl>(Parent))
- return dyn_cast<CXXRecordDecl>(DC);
- DC = Parent;
- }
- return 0;
-}
-
-static const FunctionDecl *getStructor(const FunctionDecl *fn) {
- if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
- return ftd->getTemplatedDecl();
-
- return fn;
-}
-
-static const NamedDecl *getStructor(const NamedDecl *decl) {
- const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);
- return (fn ? getStructor(fn) : decl);
-}
-
-static const unsigned UnknownArity = ~0U;
-
-class ItaniumMangleContext : public MangleContext {
- llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
- unsigned Discriminator;
- llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
-
-public:
- explicit ItaniumMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags)
- : MangleContext(Context, Diags) { }
-
- uint64_t getAnonymousStructId(const TagDecl *TD) {
- std::pair<llvm::DenseMap<const TagDecl *,
- uint64_t>::iterator, bool> Result =
- AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
- return Result.first->second;
- }
-
- void startNewFunction() {
- MangleContext::startNewFunction();
- mangleInitDiscriminator();
- }
-
- /// @name Mangler Entry Points
- /// @{
-
- bool shouldMangleDeclName(const NamedDecl *D);
- void mangleName(const NamedDecl *D, raw_ostream &);
- void mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &);
- void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
- const ThisAdjustment &ThisAdjustment,
- raw_ostream &);
- void mangleReferenceTemporary(const VarDecl *D,
- raw_ostream &);
- void mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &);
- void mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &);
- void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &);
- void mangleCXXRTTI(QualType T, raw_ostream &);
- void mangleCXXRTTIName(QualType T, raw_ostream &);
- void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- raw_ostream &);
- void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- raw_ostream &);
-
- void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &);
-
- void mangleInitDiscriminator() {
- Discriminator = 0;
- }
-
- bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
- // Lambda closure types with external linkage (indicated by a
- // non-zero lambda mangling number) have their own numbering scheme, so
- // they do not need a discriminator.
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND))
- if (RD->isLambda() && RD->getLambdaManglingNumber() > 0)
- return false;
-
- unsigned &discriminator = Uniquifier[ND];
- if (!discriminator)
- discriminator = ++Discriminator;
- if (discriminator == 1)
- return false;
- disc = discriminator-2;
- return true;
- }
- /// @}
-};
-
-/// CXXNameMangler - Manage the mangling of a single name.
-class CXXNameMangler {
- ItaniumMangleContext &Context;
- raw_ostream &Out;
-
- /// The "structor" is the top-level declaration being mangled, if
- /// that's not a template specialization; otherwise it's the pattern
- /// for that specialization.
- const NamedDecl *Structor;
- unsigned StructorType;
-
- /// SeqID - The next subsitution sequence number.
- unsigned SeqID;
-
- class FunctionTypeDepthState {
- unsigned Bits;
-
- enum { InResultTypeMask = 1 };
-
- public:
- FunctionTypeDepthState() : Bits(0) {}
-
- /// The number of function types we're inside.
- unsigned getDepth() const {
- return Bits >> 1;
- }
-
- /// True if we're in the return type of the innermost function type.
- bool isInResultType() const {
- return Bits & InResultTypeMask;
- }
-
- FunctionTypeDepthState push() {
- FunctionTypeDepthState tmp = *this;
- Bits = (Bits & ~InResultTypeMask) + 2;
- return tmp;
- }
-
- void enterResultType() {
- Bits |= InResultTypeMask;
- }
-
- void leaveResultType() {
- Bits &= ~InResultTypeMask;
- }
-
- void pop(FunctionTypeDepthState saved) {
- assert(getDepth() == saved.getDepth() + 1);
- Bits = saved.Bits;
- }
-
- } FunctionTypeDepth;
-
- llvm::DenseMap<uintptr_t, unsigned> Substitutions;
-
- ASTContext &getASTContext() const { return Context.getASTContext(); }
-
-public:
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
- const NamedDecl *D = 0)
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
- SeqID(0) {
- // These can't be mangled without a ctor type or dtor type.
- assert(!D || (!isa<CXXDestructorDecl>(D) &&
- !isa<CXXConstructorDecl>(D)));
- }
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
- const CXXConstructorDecl *D, CXXCtorType Type)
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
- SeqID(0) { }
- CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
- const CXXDestructorDecl *D, CXXDtorType Type)
- : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
- SeqID(0) { }
-
-#if MANGLE_CHECKER
- ~CXXNameMangler() {
- if (Out.str()[0] == '\01')
- return;
-
- int status = 0;
- char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status);
- assert(status == 0 && "Could not demangle mangled name!");
- free(result);
- }
-#endif
- raw_ostream &getStream() { return Out; }
-
- void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
- void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
- void mangleNumber(const llvm::APSInt &I);
- void mangleNumber(int64_t Number);
- void mangleFloat(const llvm::APFloat &F);
- void mangleFunctionEncoding(const FunctionDecl *FD);
- void mangleName(const NamedDecl *ND);
- void mangleType(QualType T);
- void mangleNameOrStandardSubstitution(const NamedDecl *ND);
-
-private:
- bool mangleSubstitution(const NamedDecl *ND);
- bool mangleSubstitution(QualType T);
- bool mangleSubstitution(TemplateName Template);
- bool mangleSubstitution(uintptr_t Ptr);
-
- void mangleExistingSubstitution(QualType type);
- void mangleExistingSubstitution(TemplateName name);
-
- bool mangleStandardSubstitution(const NamedDecl *ND);
-
- void addSubstitution(const NamedDecl *ND) {
- ND = cast<NamedDecl>(ND->getCanonicalDecl());
-
- addSubstitution(reinterpret_cast<uintptr_t>(ND));
- }
- void addSubstitution(QualType T);
- void addSubstitution(TemplateName Template);
- void addSubstitution(uintptr_t Ptr);
-
- void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- bool recursive = false);
- void mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName name,
- unsigned KnownArity = UnknownArity);
-
- void mangleName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void mangleUnqualifiedName(const NamedDecl *ND) {
- mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
- }
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
- unsigned KnownArity);
- void mangleUnscopedName(const NamedDecl *ND);
- void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleUnscopedTemplateName(TemplateName);
- void mangleSourceName(const IdentifierInfo *II);
- void mangleLocalName(const NamedDecl *ND);
- void mangleLambda(const CXXRecordDecl *Lambda);
- void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
- bool NoFunction=false);
- void mangleNestedName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void manglePrefix(NestedNameSpecifier *qualifier);
- void manglePrefix(const DeclContext *DC, bool NoFunction=false);
- void manglePrefix(QualType type);
- void mangleTemplatePrefix(const TemplateDecl *ND);
- void mangleTemplatePrefix(TemplateName Template);
- void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
- void mangleQualifiers(Qualifiers Quals);
- void mangleRefQualifier(RefQualifierKind RefQualifier);
-
- void mangleObjCMethodName(const ObjCMethodDecl *MD);
-
- // Declare manglers for every type class.
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
-#include "clang/AST/TypeNodes.def"
-
- void mangleType(const TagType*);
- void mangleType(TemplateName);
- void mangleBareFunctionType(const FunctionType *T,
- bool MangleReturnType);
- void mangleNeonVectorType(const VectorType *T);
-
- void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
- void mangleMemberExpr(const Expr *base, bool isArrow,
- NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName name,
- unsigned knownArity);
- void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
- void mangleCXXCtorType(CXXCtorType T);
- void mangleCXXDtorType(CXXDtorType T);
-
- void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
- void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs);
- void mangleTemplateArgs(const TemplateArgumentList &AL);
- void mangleTemplateArg(TemplateArgument A);
-
- void mangleTemplateParameter(unsigned Index);
-
- void mangleFunctionParam(const ParmVarDecl *parm);
-};
-
-}
-
-static bool isInCLinkageSpecification(const Decl *D) {
- D = D->getCanonicalDecl();
- for (const DeclContext *DC = getEffectiveDeclContext(D);
- !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
- }
-
- return false;
-}
-
-bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) {
- // In C, functions with no attributes never need to be mangled. Fastpath them.
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
- return false;
-
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (D->hasAttr<AsmLabelAttr>())
- return true;
-
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling
- // (always) as does passing a C++ member function and a function
- // whose name is not a simple identifier.
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
- !FD->getDeclName().isIdentifier()))
- return true;
-
- // Otherwise, no mangling is done outside C++ mode.
- if (!getASTContext().getLangOpts().CPlusPlus)
- return false;
-
- // Variables at global scope with non-internal linkage are not mangled
- if (!FD) {
- const DeclContext *DC = getEffectiveDeclContext(D);
- // Check for extern variable declared locally.
- if (DC->isFunctionOrMethod() && D->hasLinkage())
- while (!DC->isNamespace() && !DC->isTranslationUnit())
- DC = getEffectiveParentContext(DC);
- if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
- return false;
- }
-
- // Class members are always mangled.
- if (getEffectiveDeclContext(D)->isRecord())
- return true;
-
- // C functions and "main" are not mangled.
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
- return false;
-
- return true;
-}
-
-void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
- // If we have an asm name, then we use it as the mangling.
-
- // Adding the prefix can cause problems when one file has a "foo" and
- // another has a "\01foo". That is known to happen on ELF with the
- // tricks normally used for producing aliases (PR9177). Fortunately the
- // llvm mangler on ELF is a nop, so we can just avoid adding the \01
- // marker. We also avoid adding the marker if this is an alias for an
- // LLVM intrinsic.
- StringRef UserLabelPrefix =
- getASTContext().getTargetInfo().getUserLabelPrefix();
- if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))
- Out << '\01'; // LLVM IR Marker for __asm("foo")
-
- Out << ALA->getLabel();
- return;
- }
-
- // <mangled-name> ::= _Z <encoding>
- // ::= <data name>
- // ::= <special-name>
- Out << Prefix;
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- mangleName(VD);
- else
- mangleName(cast<FieldDecl>(D));
-}
-
-void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
- // <encoding> ::= <function name> <bare-function-type>
- mangleName(FD);
-
- // Don't mangle in the type if this isn't a decl we should typically mangle.
- if (!Context.shouldMangleDeclName(FD))
- return;
-
- // Whether the mangling of a function type includes the return type depends on
- // the context and the nature of the function. The rules for deciding whether
- // the return type is included are:
- //
- // 1. Template functions (names or types) have return types encoded, with
- // the exceptions listed below.
- // 2. Function types not appearing as part of a function name mangling,
- // e.g. parameters, pointer types, etc., have return type encoded, with the
- // exceptions listed below.
- // 3. Non-template function names do not have return types encoded.
- //
- // The exceptions mentioned in (1) and (2) above, for which the return type is
- // never included, are
- // 1. Constructors.
- // 2. Destructors.
- // 3. Conversion operator functions, e.g. operator int.
- bool MangleReturnType = false;
- if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) {
- if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
- isa<CXXConversionDecl>(FD)))
- MangleReturnType = true;
-
- // Mangle the type of the primary template.
- FD = PrimaryTemplate->getTemplatedDecl();
- }
-
- mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
- MangleReturnType);
-}
-
-static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
- while (isa<LinkageSpecDecl>(DC)) {
- DC = getEffectiveParentContext(DC);
- }
-
- return DC;
-}
-
-/// isStd - Return whether a given namespace is the 'std' namespace.
-static bool isStd(const NamespaceDecl *NS) {
- if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
- ->isTranslationUnit())
- return false;
-
- const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
- return II && II->isStr("std");
-}
-
-// isStdNamespace - Return whether a given decl context is a toplevel 'std'
-// namespace.
-static bool isStdNamespace(const DeclContext *DC) {
- if (!DC->isNamespace())
- return false;
-
- return isStd(cast<NamespaceDecl>(DC));
-}
-
-static const TemplateDecl *
-isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
- // Check if we have a function template.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
- if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
- TemplateArgs = FD->getTemplateSpecializationArgs();
- return TD;
- }
- }
-
- // Check if we have a class template.
- if (const ClassTemplateSpecializationDecl *Spec =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
- TemplateArgs = &Spec->getTemplateArgs();
- return Spec->getSpecializedTemplate();
- }
-
- return 0;
-}
-
-static bool isLambda(const NamedDecl *ND) {
- const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
- if (!Record)
- return false;
-
- return Record->isLambda();
-}
-
-void CXXNameMangler::mangleName(const NamedDecl *ND) {
- // <name> ::= <nested-name>
- // ::= <unscoped-name>
- // ::= <unscoped-template-name> <template-args>
- // ::= <local-name>
- //
- const DeclContext *DC = getEffectiveDeclContext(ND);
-
- // If this is an extern variable declared locally, the relevant DeclContext
- // is that of the containing namespace, or the translation unit.
- // FIXME: This is a hack; extern variables declared locally should have
- // a proper semantic declaration context!
- if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))
- while (!DC->isNamespace() && !DC->isTranslationUnit())
- DC = getEffectiveParentContext(DC);
- else if (GetLocalClassDecl(ND)) {
- mangleLocalName(ND);
- return;
- }
-
- DC = IgnoreLinkageSpecDecls(DC);
-
- if (DC->isTranslationUnit() || isStdNamespace(DC)) {
- // Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- mangleUnscopedTemplateName(TD);
- mangleTemplateArgs(*TemplateArgs);
- return;
- }
-
- mangleUnscopedName(ND);
- return;
- }
-
- if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {
- mangleLocalName(ND);
- return;
- }
-
- mangleNestedName(ND, DC);
-}
-void CXXNameMangler::mangleName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
-
- if (DC->isTranslationUnit() || isStdNamespace(DC)) {
- mangleUnscopedTemplateName(TD);
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
- } else {
- mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
- }
-}
-
-void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {
- // <unscoped-name> ::= <unqualified-name>
- // ::= St <unqualified-name> # ::std::
-
- if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
- Out << "St";
-
- mangleUnqualifiedName(ND);
-}
-
-void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
- // <unscoped-template-name> ::= <unscoped-name>
- // ::= <substitution>
- if (mangleSubstitution(ND))
- return;
-
- // <template-template-param> ::= <template-param>
- if (const TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
- mangleTemplateParameter(TTP->getIndex());
- return;
- }
-
- mangleUnscopedName(ND->getTemplatedDecl());
- addSubstitution(ND);
-}
-
-void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
- // <unscoped-template-name> ::= <unscoped-name>
- // ::= <substitution>
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return mangleUnscopedTemplateName(TD);
-
- if (mangleSubstitution(Template))
- return;
-
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
- assert(Dependent && "Not a dependent template name?");
- if (const IdentifierInfo *Id = Dependent->getIdentifier())
- mangleSourceName(Id);
- else
- mangleOperatorName(Dependent->getOperator(), UnknownArity);
-
- addSubstitution(Template);
-}
-
-void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
- // ABI:
- // Floating-point literals are encoded using a fixed-length
- // lowercase hexadecimal string corresponding to the internal
- // representation (IEEE on Itanium), high-order bytes first,
- // without leading zeroes. For example: "Lf bf800000 E" is -1.0f
- // on Itanium.
- // The 'without leading zeroes' thing seems to be an editorial
- // mistake; see the discussion on cxx-abi-dev beginning on
- // 2012-01-16.
-
- // Our requirements here are just barely weird enough to justify
- // using a custom algorithm instead of post-processing APInt::toString().
-
- llvm::APInt valueBits = f.bitcastToAPInt();
- unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4;
- assert(numCharacters != 0);
-
- // Allocate a buffer of the right number of characters.
- llvm::SmallVector<char, 20> buffer;
- buffer.set_size(numCharacters);
-
- // Fill the buffer left-to-right.
- for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) {
- // The bit-index of the next hex digit.
- unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1);
-
- // Project out 4 bits starting at 'digitIndex'.
- llvm::integerPart hexDigit
- = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth];
- hexDigit >>= (digitBitIndex % llvm::integerPartWidth);
- hexDigit &= 0xF;
-
- // Map that over to a lowercase hex digit.
- static const char charForHex[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
- buffer[stringIndex] = charForHex[hexDigit];
- }
-
- Out.write(buffer.data(), numCharacters);
-}
-
-void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
- if (Value.isSigned() && Value.isNegative()) {
- Out << 'n';
- Value.abs().print(Out, /*signed*/ false);
- } else {
- Value.print(Out, /*signed*/ false);
- }
-}
-
-void CXXNameMangler::mangleNumber(int64_t Number) {
- // <number> ::= [n] <non-negative decimal integer>
- if (Number < 0) {
- Out << 'n';
- Number = -Number;
- }
-
- Out << Number;
-}
-
-void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
- // <call-offset> ::= h <nv-offset> _
- // ::= v <v-offset> _
- // <nv-offset> ::= <offset number> # non-virtual base override
- // <v-offset> ::= <offset number> _ <virtual offset number>
- // # virtual base override, with vcall offset
- if (!Virtual) {
- Out << 'h';
- mangleNumber(NonVirtual);
- Out << '_';
- return;
- }
-
- Out << 'v';
- mangleNumber(NonVirtual);
- Out << '_';
- mangleNumber(Virtual);
- Out << '_';
-}
-
-void CXXNameMangler::manglePrefix(QualType type) {
- if (const TemplateSpecializationType *TST =
- type->getAs<TemplateSpecializationType>()) {
- if (!mangleSubstitution(QualType(TST, 0))) {
- mangleTemplatePrefix(TST->getTemplateName());
-
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
- addSubstitution(QualType(TST, 0));
- }
- } else if (const DependentTemplateSpecializationType *DTST
- = type->getAs<DependentTemplateSpecializationType>()) {
- TemplateName Template
- = getASTContext().getDependentTemplateName(DTST->getQualifier(),
- DTST->getIdentifier());
- mangleTemplatePrefix(Template);
-
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
- } else {
- // We use the QualType mangle type variant here because it handles
- // substitutions.
- mangleType(type);
- }
-}
-
-/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
-///
-/// \param firstQualifierLookup - the entity found by unqualified lookup
-/// for the first name in the qualifier, if this is for a member expression
-/// \param recursive - true if this is being called recursively,
-/// i.e. if there is more prefix "to the right".
-void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- bool recursive) {
-
- // x, ::x
- // <unresolved-name> ::= [gs] <base-unresolved-name>
-
- // T::x / decltype(p)::x
- // <unresolved-name> ::= sr <unresolved-type> <base-unresolved-name>
-
- // T::N::x /decltype(p)::N::x
- // <unresolved-name> ::= srN <unresolved-type> <unresolved-qualifier-level>+ E
- // <base-unresolved-name>
-
- // A::x, N::y, A<T>::z; "gs" means leading "::"
- // <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
- // <base-unresolved-name>
-
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- Out << "gs";
-
- // We want an 'sr' unless this is the entire NNS.
- if (recursive)
- Out << "sr";
-
- // We never want an 'E' here.
- return;
-
- case NestedNameSpecifier::Namespace:
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
- /*recursive*/ true);
- else
- Out << "sr";
- mangleSourceName(qualifier->getAsNamespace()->getIdentifier());
- break;
- case NestedNameSpecifier::NamespaceAlias:
- if (qualifier->getPrefix())
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
- /*recursive*/ true);
- else
- Out << "sr";
- mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier());
- break;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate: {
- const Type *type = qualifier->getAsType();
-
- // We only want to use an unresolved-type encoding if this is one of:
- // - a decltype
- // - a template type parameter
- // - a template template parameter with arguments
- // In all of these cases, we should have no prefix.
- if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
- /*recursive*/ true);
- } else {
- // Otherwise, all the cases want this.
- Out << "sr";
- }
-
- // Only certain other types are valid as prefixes; enumerate them.
- switch (type->getTypeClass()) {
- case Type::Builtin:
- case Type::Complex:
- case Type::Pointer:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- case Type::Enum:
- case Type::Paren:
- case Type::Elaborated:
- case Type::Attributed:
- case Type::Auto:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- llvm_unreachable("type is illegal as a nested name specifier");
-
- case Type::SubstTemplateTypeParmPack:
- // FIXME: not clear how to mangle this!
- // template <class T...> class A {
- // template <class U...> void foo(decltype(T::foo(U())) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
-
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <template-template-param> <template-args>
- // (this last is not official yet)
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::TemplateTypeParm:
- case Type::UnaryTransform:
- case Type::SubstTemplateTypeParm:
- unresolvedType:
- assert(!qualifier->getPrefix());
-
- // We only get here recursively if we're followed by identifiers.
- if (recursive) Out << 'N';
-
- // This seems to do everything we want. It's not really
- // sanctioned for a substituted template parameter, though.
- mangleType(QualType(type, 0));
-
- // We never want to print 'E' directly after an unresolved-type,
- // so we return directly.
- return;
-
- case Type::Typedef:
- mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::UnresolvedUsing:
- mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::Record:
- mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
- break;
-
- case Type::TemplateSpecialization: {
- const TemplateSpecializationType *tst
- = cast<TemplateSpecializationType>(type);
- TemplateName name = tst->getTemplateName();
- switch (name.getKind()) {
- case TemplateName::Template:
- case TemplateName::QualifiedTemplate: {
- TemplateDecl *temp = name.getAsTemplateDecl();
-
- // If the base is a template template parameter, this is an
- // unresolved type.
- assert(temp && "no template for template specialization type");
- if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
-
- mangleSourceName(temp->getIdentifier());
- break;
- }
-
- case TemplateName::OverloadedTemplate:
- case TemplateName::DependentTemplate:
- llvm_unreachable("invalid base for a template specialization type");
-
- case TemplateName::SubstTemplateTemplateParm: {
- SubstTemplateTemplateParmStorage *subst
- = name.getAsSubstTemplateTemplateParm();
- mangleExistingSubstitution(subst->getReplacement());
- break;
- }
-
- case TemplateName::SubstTemplateTemplateParmPack: {
- // FIXME: not clear how to mangle this!
- // template <template <class U> class T...> class A {
- // template <class U...> void foo(decltype(T<U>::foo) x...);
- // };
- Out << "_SUBSTPACK_";
- break;
- }
- }
-
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
-
- case Type::InjectedClassName:
- mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
- ->getIdentifier());
- break;
-
- case Type::DependentName:
- mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
- break;
-
- case Type::DependentTemplateSpecialization: {
- const DependentTemplateSpecializationType *tst
- = cast<DependentTemplateSpecializationType>(type);
- mangleSourceName(tst->getIdentifier());
- mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
- break;
- }
- }
- break;
- }
-
- case NestedNameSpecifier::Identifier:
- // Member expressions can have these without prefixes.
- if (qualifier->getPrefix()) {
- mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
- /*recursive*/ true);
- } else if (firstQualifierLookup) {
-
- // Try to make a proper qualifier out of the lookup result, and
- // then just recurse on that.
- NestedNameSpecifier *newQualifier;
- if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
- QualType type = getASTContext().getTypeDeclType(typeDecl);
-
- // Pretend we had a different nested name specifier.
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
- /*template*/ false,
- type.getTypePtr());
- } else if (NamespaceDecl *nspace =
- dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
- nspace);
- } else if (NamespaceAliasDecl *alias =
- dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
- newQualifier = NestedNameSpecifier::Create(getASTContext(),
- /*prefix*/ 0,
- alias);
- } else {
- // No sensible mangling to do here.
- newQualifier = 0;
- }
-
- if (newQualifier)
- return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive);
-
- } else {
- Out << "sr";
- }
-
- mangleSourceName(qualifier->getAsIdentifier());
- break;
- }
-
- // If this was the innermost part of the NNS, and we fell out to
- // here, append an 'E'.
- if (!recursive)
- Out << 'E';
-}
-
-/// Mangle an unresolved-name, which is generally used for names which
-/// weren't resolved to specific entities.
-void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName name,
- unsigned knownArity) {
- if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
- mangleUnqualifiedName(0, name, knownArity);
-}
-
-static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
- assert(RD->isAnonymousStructOrUnion() &&
- "Expected anonymous struct or union!");
-
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
- if (I->getIdentifier())
- return *I;
-
- if (const RecordType *RT = I->getType()->getAs<RecordType>())
- if (const FieldDecl *NamedDataMember =
- FindFirstNamedDataMember(RT->getDecl()))
- return NamedDataMember;
- }
-
- // We didn't find a named data member.
- return 0;
-}
-
-void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
- DeclarationName Name,
- unsigned KnownArity) {
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- switch (Name.getNameKind()) {
- case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
- // We must avoid conflicts between internally- and externally-
- // linked variable and function declaration names in the same TU:
- // void test() { extern void foo(); }
- // static void foo();
- // This naming convention is the same as that followed by GCC,
- // though it shouldn't actually matter.
- if (ND && ND->getLinkage() == InternalLinkage &&
- getEffectiveDeclContext(ND)->isFileContext())
- Out << 'L';
-
- mangleSourceName(II);
- break;
- }
-
- // Otherwise, an anonymous entity. We must have a declaration.
- assert(ND && "mangling empty name without declaration");
-
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
- if (NS->isAnonymousNamespace()) {
- // This is how gcc mangles these names.
- Out << "12_GLOBAL__N_1";
- break;
- }
- }
-
- if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
- // We must have an anonymous union or struct declaration.
- const RecordDecl *RD =
- cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
-
- // Itanium C++ ABI 5.1.2:
- //
- // For the purposes of mangling, the name of an anonymous union is
- // considered to be the name of the first named data member found by a
- // pre-order, depth-first, declaration-order walk of the data members of
- // the anonymous union. If there is no such data member (i.e., if all of
- // the data members in the union are unnamed), then there is no way for
- // a program to refer to the anonymous union, and there is therefore no
- // need to mangle its name.
- const FieldDecl *FD = FindFirstNamedDataMember(RD);
-
- // It's actually possible for various reasons for us to get here
- // with an empty anonymous struct / union. Fortunately, it
- // doesn't really matter what name we generate.
- if (!FD) break;
- assert(FD->getIdentifier() && "Data member name isn't an identifier!");
-
- mangleSourceName(FD->getIdentifier());
- break;
- }
-
- // We must have an anonymous struct.
- const TagDecl *TD = cast<TagDecl>(ND);
- if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
- assert(TD->getDeclContext() == D->getDeclContext() &&
- "Typedef should not be in another decl context!");
- assert(D->getDeclName().getAsIdentifierInfo() &&
- "Typedef was not named!");
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());
- break;
- }
-
- // <unnamed-type-name> ::= <closure-type-name>
- //
- // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
- // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'.
- if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
- if (Record->isLambda() && Record->getLambdaManglingNumber()) {
- mangleLambda(Record);
- break;
- }
- }
-
- int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD);
- if (UnnamedMangle != -1) {
- Out << "Ut";
- if (UnnamedMangle != 0)
- Out << llvm::utostr(UnnamedMangle - 1);
- Out << '_';
- break;
- }
-
- // Get a unique id for the anonymous struct.
- uint64_t AnonStructId = Context.getAnonymousStructId(TD);
-
- // Mangle it as a source name in the form
- // [n] $_<id>
- // where n is the length of the string.
- SmallString<8> Str;
- Str += "$_";
- Str += llvm::utostr(AnonStructId);
-
- Out << Str.size();
- Out << Str.str();
- break;
- }
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- llvm_unreachable("Can't mangle Objective-C selector names here!");
-
- case DeclarationName::CXXConstructorName:
- if (ND == Structor)
- // If the named decl is the C++ constructor we're mangling, use the type
- // we were given.
- mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
- else
- // Otherwise, use the complete constructor name. This is relevant if a
- // class with a constructor is declared within a constructor.
- mangleCXXCtorType(Ctor_Complete);
- break;
-
- case DeclarationName::CXXDestructorName:
- if (ND == Structor)
- // If the named decl is the C++ destructor we're mangling, use the type we
- // were given.
- mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
- else
- // Otherwise, use the complete destructor name. This is relevant if a
- // class with a destructor is declared within a destructor.
- mangleCXXDtorType(Dtor_Complete);
- break;
-
- case DeclarationName::CXXConversionFunctionName:
- // <operator-name> ::= cv <type> # (cast)
- Out << "cv";
- mangleType(Name.getCXXNameType());
- break;
-
- case DeclarationName::CXXOperatorName: {
- unsigned Arity;
- if (ND) {
- Arity = cast<FunctionDecl>(ND)->getNumParams();
-
- // If we have a C++ member function, we need to include the 'this' pointer.
- // FIXME: This does not make sense for operators that are static, but their
- // names stay the same regardless of the arity (operator new for instance).
- if (isa<CXXMethodDecl>(ND))
- Arity++;
- } else
- Arity = KnownArity;
-
- mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
- break;
- }
-
- case DeclarationName::CXXLiteralOperatorName:
- // FIXME: This mangling is not yet official.
- Out << "li";
- mangleSourceName(Name.getCXXLiteralIdentifier());
- break;
-
- case DeclarationName::CXXUsingDirective:
- llvm_unreachable("Can't mangle a using directive name!");
- }
-}
-
-void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
- // <source-name> ::= <positive length number> <identifier>
- // <number> ::= [n] <non-negative decimal integer>
- // <identifier> ::= <unqualified source code identifier>
- Out << II->getLength() << II->getName();
-}
-
-void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
- const DeclContext *DC,
- bool NoFunction) {
- // <nested-name>
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
- // <template-args> E
-
- Out << 'N';
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
- mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
- mangleRefQualifier(Method->getRefQualifier());
- }
-
- // Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- mangleTemplatePrefix(TD);
- mangleTemplateArgs(*TemplateArgs);
- }
- else {
- manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(ND);
- }
-
- Out << 'E';
-}
-void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
-
- Out << 'N';
-
- mangleTemplatePrefix(TD);
- mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
-
- Out << 'E';
-}
-
-void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
- // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
- // := Z <function encoding> E s [<discriminator>]
- // <local-name> := Z <function encoding> E d [ <parameter number> ]
- // _ <entity name>
- // <discriminator> := _ <non-negative number>
- const DeclContext *DC = getEffectiveDeclContext(ND);
- if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) {
- // Don't add objc method name mangling to locally declared function
- mangleUnqualifiedName(ND);
- return;
- }
-
- Out << 'Z';
-
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
- mangleObjCMethodName(MD);
- } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
- mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD)));
- Out << 'E';
-
- // The parameter number is omitted for the last parameter, 0 for the
- // second-to-last parameter, 1 for the third-to-last parameter, etc. The
- // <entity name> will of course contain a <closure-type-name>: Its
- // numbering will be local to the particular argument in which it appears
- // -- other default arguments do not affect its encoding.
- bool SkipDiscriminator = false;
- if (RD->isLambda()) {
- if (const ParmVarDecl *Parm
- = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) {
- if (const FunctionDecl *Func
- = dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
- Out << 'd';
- unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();
- if (Num > 1)
- mangleNumber(Num - 2);
- Out << '_';
- SkipDiscriminator = true;
- }
- }
- }
-
- // Mangle the name relative to the closest enclosing function.
- if (ND == RD) // equality ok because RD derived from ND above
- mangleUnqualifiedName(ND);
- else
- mangleNestedName(ND, DC, true /*NoFunction*/);
-
- if (!SkipDiscriminator) {
- unsigned disc;
- if (Context.getNextDiscriminator(RD, disc)) {
- if (disc < 10)
- Out << '_' << disc;
- else
- Out << "__" << disc << '_';
- }
- }
-
- return;
- }
- else
- mangleFunctionEncoding(cast<FunctionDecl>(DC));
-
- Out << 'E';
- mangleUnqualifiedName(ND);
-}
-
-void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
- // If the context of a closure type is an initializer for a class member
- // (static or nonstatic), it is encoded in a qualified name with a final
- // <prefix> of the form:
- //
- // <data-member-prefix> := <member source-name> M
- //
- // Technically, the data-member-prefix is part of the <prefix>. However,
- // since a closure type will always be mangled with a prefix, it's easier
- // to emit that last part of the prefix here.
- if (Decl *Context = Lambda->getLambdaContextDecl()) {
- if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
- Context->getDeclContext()->isRecord()) {
- if (const IdentifierInfo *Name
- = cast<NamedDecl>(Context)->getIdentifier()) {
- mangleSourceName(Name);
- Out << 'M';
- }
- }
- }
-
- Out << "Ul";
- const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
- getAs<FunctionProtoType>();
- mangleBareFunctionType(Proto, /*MangleReturnType=*/false);
- Out << "E";
-
- // The number is omitted for the first closure type with a given
- // <lambda-sig> in a given context; it is n-2 for the nth closure type
- // (in lexical order) with that same <lambda-sig> and context.
- //
- // The AST keeps track of the number for us.
- unsigned Number = Lambda->getLambdaManglingNumber();
- assert(Number > 0 && "Lambda should be mangled as an unnamed class");
- if (Number > 1)
- mangleNumber(Number - 2);
- Out << '_';
-}
-
-void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
- switch (qualifier->getKind()) {
- case NestedNameSpecifier::Global:
- // nothing
- return;
-
- case NestedNameSpecifier::Namespace:
- mangleName(qualifier->getAsNamespace());
- return;
-
- case NestedNameSpecifier::NamespaceAlias:
- mangleName(qualifier->getAsNamespaceAlias()->getNamespace());
- return;
-
- case NestedNameSpecifier::TypeSpec:
- case NestedNameSpecifier::TypeSpecWithTemplate:
- manglePrefix(QualType(qualifier->getAsType(), 0));
- return;
-
- case NestedNameSpecifier::Identifier:
- // Member expressions can have these without prefixes, but that
- // should end up in mangleUnresolvedPrefix instead.
- assert(qualifier->getPrefix());
- manglePrefix(qualifier->getPrefix());
-
- mangleSourceName(qualifier->getAsIdentifier());
- return;
- }
-
- llvm_unreachable("unexpected nested name specifier");
-}
-
-void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
- // <prefix> ::= <prefix> <unqualified-name>
- // ::= <template-prefix> <template-args>
- // ::= <template-param>
- // ::= # empty
- // ::= <substitution>
-
- DC = IgnoreLinkageSpecDecls(DC);
-
- if (DC->isTranslationUnit())
- return;
-
- if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
- manglePrefix(getEffectiveParentContext(DC), NoFunction);
- SmallString<64> Name;
- llvm::raw_svector_ostream NameStream(Name);
- Context.mangleBlock(Block, NameStream);
- NameStream.flush();
- Out << Name.size() << Name;
- return;
- }
-
- const NamedDecl *ND = cast<NamedDecl>(DC);
- if (mangleSubstitution(ND))
- return;
-
- // Check if we have a template.
- const TemplateArgumentList *TemplateArgs = 0;
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- mangleTemplatePrefix(TD);
- mangleTemplateArgs(*TemplateArgs);
- }
- else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
- return;
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
- mangleObjCMethodName(Method);
- else {
- manglePrefix(getEffectiveDeclContext(ND), NoFunction);
- mangleUnqualifiedName(ND);
- }
-
- addSubstitution(ND);
-}
-
-void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
- // <template-prefix> ::= <prefix> <template unqualified-name>
- // ::= <template-param>
- // ::= <substitution>
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return mangleTemplatePrefix(TD);
-
- if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
- manglePrefix(Qualified->getQualifier());
-
- if (OverloadedTemplateStorage *Overloaded
- = Template.getAsOverloadedTemplate()) {
- mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(),
- UnknownArity);
- return;
- }
-
- DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
- assert(Dependent && "Unknown template name kind?");
- manglePrefix(Dependent->getQualifier());
- mangleUnscopedTemplateName(Template);
-}
-
-void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
- // <template-prefix> ::= <prefix> <template unqualified-name>
- // ::= <template-param>
- // ::= <substitution>
- // <template-template-param> ::= <template-param>
- // <substitution>
-
- if (mangleSubstitution(ND))
- return;
-
- // <template-template-param> ::= <template-param>
- if (const TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
- mangleTemplateParameter(TTP->getIndex());
- return;
- }
-
- manglePrefix(getEffectiveDeclContext(ND));
- mangleUnqualifiedName(ND->getTemplatedDecl());
- addSubstitution(ND);
-}
-
-/// Mangles a template name under the production <type>. Required for
-/// template template arguments.
-/// <type> ::= <class-enum-type>
-/// ::= <template-param>
-/// ::= <substitution>
-void CXXNameMangler::mangleType(TemplateName TN) {
- if (mangleSubstitution(TN))
- return;
-
- TemplateDecl *TD = 0;
-
- switch (TN.getKind()) {
- case TemplateName::QualifiedTemplate:
- TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();
- goto HaveDecl;
-
- case TemplateName::Template:
- TD = TN.getAsTemplateDecl();
- goto HaveDecl;
-
- HaveDecl:
- if (isa<TemplateTemplateParmDecl>(TD))
- mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());
- else
- mangleName(TD);
- break;
-
- case TemplateName::OverloadedTemplate:
- llvm_unreachable("can't mangle an overloaded template name as a <type>");
-
- case TemplateName::DependentTemplate: {
- const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
- assert(Dependent->isIdentifier());
-
- // <class-enum-type> ::= <name>
- // <name> ::= <nested-name>
- mangleUnresolvedPrefix(Dependent->getQualifier(), 0);
- mangleSourceName(Dependent->getIdentifier());
- break;
- }
-
- case TemplateName::SubstTemplateTemplateParm: {
- // Substituted template parameters are mangled as the substituted
- // template. This will check for the substitution twice, which is
- // fine, but we have to return early so that we don't try to *add*
- // the substitution twice.
- SubstTemplateTemplateParmStorage *subst
- = TN.getAsSubstTemplateTemplateParm();
- mangleType(subst->getReplacement());
- return;
- }
-
- case TemplateName::SubstTemplateTemplateParmPack: {
- // FIXME: not clear how to mangle this!
- // template <template <class> class T...> class A {
- // template <template <class> class U...> void foo(B<T,U> x...);
- // };
- Out << "_SUBSTPACK_";
- break;
- }
- }
-
- addSubstitution(TN);
-}
-
-void
-CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
- switch (OO) {
- // <operator-name> ::= nw # new
- case OO_New: Out << "nw"; break;
- // ::= na # new[]
- case OO_Array_New: Out << "na"; break;
- // ::= dl # delete
- case OO_Delete: Out << "dl"; break;
- // ::= da # delete[]
- case OO_Array_Delete: Out << "da"; break;
- // ::= ps # + (unary)
- // ::= pl # + (binary or unknown)
- case OO_Plus:
- Out << (Arity == 1? "ps" : "pl"); break;
- // ::= ng # - (unary)
- // ::= mi # - (binary or unknown)
- case OO_Minus:
- Out << (Arity == 1? "ng" : "mi"); break;
- // ::= ad # & (unary)
- // ::= an # & (binary or unknown)
- case OO_Amp:
- Out << (Arity == 1? "ad" : "an"); break;
- // ::= de # * (unary)
- // ::= ml # * (binary or unknown)
- case OO_Star:
- // Use binary when unknown.
- Out << (Arity == 1? "de" : "ml"); break;
- // ::= co # ~
- case OO_Tilde: Out << "co"; break;
- // ::= dv # /
- case OO_Slash: Out << "dv"; break;
- // ::= rm # %
- case OO_Percent: Out << "rm"; break;
- // ::= or # |
- case OO_Pipe: Out << "or"; break;
- // ::= eo # ^
- case OO_Caret: Out << "eo"; break;
- // ::= aS # =
- case OO_Equal: Out << "aS"; break;
- // ::= pL # +=
- case OO_PlusEqual: Out << "pL"; break;
- // ::= mI # -=
- case OO_MinusEqual: Out << "mI"; break;
- // ::= mL # *=
- case OO_StarEqual: Out << "mL"; break;
- // ::= dV # /=
- case OO_SlashEqual: Out << "dV"; break;
- // ::= rM # %=
- case OO_PercentEqual: Out << "rM"; break;
- // ::= aN # &=
- case OO_AmpEqual: Out << "aN"; break;
- // ::= oR # |=
- case OO_PipeEqual: Out << "oR"; break;
- // ::= eO # ^=
- case OO_CaretEqual: Out << "eO"; break;
- // ::= ls # <<
- case OO_LessLess: Out << "ls"; break;
- // ::= rs # >>
- case OO_GreaterGreater: Out << "rs"; break;
- // ::= lS # <<=
- case OO_LessLessEqual: Out << "lS"; break;
- // ::= rS # >>=
- case OO_GreaterGreaterEqual: Out << "rS"; break;
- // ::= eq # ==
- case OO_EqualEqual: Out << "eq"; break;
- // ::= ne # !=
- case OO_ExclaimEqual: Out << "ne"; break;
- // ::= lt # <
- case OO_Less: Out << "lt"; break;
- // ::= gt # >
- case OO_Greater: Out << "gt"; break;
- // ::= le # <=
- case OO_LessEqual: Out << "le"; break;
- // ::= ge # >=
- case OO_GreaterEqual: Out << "ge"; break;
- // ::= nt # !
- case OO_Exclaim: Out << "nt"; break;
- // ::= aa # &&
- case OO_AmpAmp: Out << "aa"; break;
- // ::= oo # ||
- case OO_PipePipe: Out << "oo"; break;
- // ::= pp # ++
- case OO_PlusPlus: Out << "pp"; break;
- // ::= mm # --
- case OO_MinusMinus: Out << "mm"; break;
- // ::= cm # ,
- case OO_Comma: Out << "cm"; break;
- // ::= pm # ->*
- case OO_ArrowStar: Out << "pm"; break;
- // ::= pt # ->
- case OO_Arrow: Out << "pt"; break;
- // ::= cl # ()
- case OO_Call: Out << "cl"; break;
- // ::= ix # []
- case OO_Subscript: Out << "ix"; break;
-
- // ::= qu # ?
- // The conditional operator can't be overloaded, but we still handle it when
- // mangling expressions.
- case OO_Conditional: Out << "qu"; break;
-
- case OO_None:
- case NUM_OVERLOADED_OPERATORS:
- llvm_unreachable("Not an overloaded operator");
- }
-}
-
-void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
- // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
- if (Quals.hasRestrict())
- Out << 'r';
- if (Quals.hasVolatile())
- Out << 'V';
- if (Quals.hasConst())
- Out << 'K';
-
- if (Quals.hasAddressSpace()) {
- // Extension:
- //
- // <type> ::= U <address-space-number>
- //
- // where <address-space-number> is a source name consisting of 'AS'
- // followed by the address space <number>.
- SmallString<64> ASString;
- ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace());
- Out << 'U' << ASString.size() << ASString;
- }
-
- StringRef LifetimeName;
- switch (Quals.getObjCLifetime()) {
- // Objective-C ARC Extension:
- //
- // <type> ::= U "__strong"
- // <type> ::= U "__weak"
- // <type> ::= U "__autoreleasing"
- case Qualifiers::OCL_None:
- break;
-
- case Qualifiers::OCL_Weak:
- LifetimeName = "__weak";
- break;
-
- case Qualifiers::OCL_Strong:
- LifetimeName = "__strong";
- break;
-
- case Qualifiers::OCL_Autoreleasing:
- LifetimeName = "__autoreleasing";
- break;
-
- case Qualifiers::OCL_ExplicitNone:
- // The __unsafe_unretained qualifier is *not* mangled, so that
- // __unsafe_unretained types in ARC produce the same manglings as the
- // equivalent (but, naturally, unqualified) types in non-ARC, providing
- // better ABI compatibility.
- //
- // It's safe to do this because unqualified 'id' won't show up
- // in any type signatures that need to be mangled.
- break;
- }
- if (!LifetimeName.empty())
- Out << 'U' << LifetimeName.size() << LifetimeName;
-}
-
-void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
- // <ref-qualifier> ::= R # lvalue reference
- // ::= O # rvalue-reference
- // Proposal to Itanium C++ ABI list on 1/26/11
- switch (RefQualifier) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- Out << 'R';
- break;
-
- case RQ_RValue:
- Out << 'O';
- break;
- }
-}
-
-void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
- Context.mangleObjCMethodName(MD, Out);
-}
-
-void CXXNameMangler::mangleType(QualType T) {
- // If our type is instantiation-dependent but not dependent, we mangle
- // it as it was written in the source, removing any top-level sugar.
- // Otherwise, use the canonical type.
- //
- // FIXME: This is an approximation of the instantiation-dependent name
- // mangling rules, since we should really be using the type as written and
- // augmented via semantic analysis (i.e., with implicit conversions and
- // default template arguments) for any instantiation-dependent type.
- // Unfortunately, that requires several changes to our AST:
- // - Instantiation-dependent TemplateSpecializationTypes will need to be
- // uniqued, so that we can handle substitutions properly
- // - Default template arguments will need to be represented in the
- // TemplateSpecializationType, since they need to be mangled even though
- // they aren't written.
- // - Conversions on non-type template arguments need to be expressed, since
- // they can affect the mangling of sizeof/alignof.
- if (!T->isInstantiationDependentType() || T->isDependentType())
- T = T.getCanonicalType();
- else {
- // Desugar any types that are purely sugar.
- do {
- // Don't desugar through template specialization types that aren't
- // type aliases. We need to mangle the template arguments as written.
- if (const TemplateSpecializationType *TST
- = dyn_cast<TemplateSpecializationType>(T))
- if (!TST->isTypeAlias())
- break;
-
- QualType Desugared
- = T.getSingleStepDesugaredType(Context.getASTContext());
- if (Desugared == T)
- break;
-
- T = Desugared;
- } while (true);
- }
- SplitQualType split = T.split();
- Qualifiers quals = split.Quals;
- const Type *ty = split.Ty;
-
- bool isSubstitutable = quals || !isa<BuiltinType>(T);
- if (isSubstitutable && mangleSubstitution(T))
- return;
-
- // If we're mangling a qualified array type, push the qualifiers to
- // the element type.
- if (quals && isa<ArrayType>(T)) {
- ty = Context.getASTContext().getAsArrayType(T);
- quals = Qualifiers();
-
- // Note that we don't update T: we want to add the
- // substitution at the original type.
- }
-
- if (quals) {
- mangleQualifiers(quals);
- // Recurse: even if the qualified type isn't yet substitutable,
- // the unqualified type might be.
- mangleType(QualType(ty, 0));
- } else {
- switch (ty->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
- return;
-#define TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- mangleType(static_cast<const CLASS##Type*>(ty)); \
- break;
-#include "clang/AST/TypeNodes.def"
- }
- }
-
- // Add the substitution.
- if (isSubstitutable)
- addSubstitution(T);
-}
-
-void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
- if (!mangleStandardSubstitution(ND))
- mangleName(ND);
-}
-
-void CXXNameMangler::mangleType(const BuiltinType *T) {
- // <type> ::= <builtin-type>
- // <builtin-type> ::= v # void
- // ::= w # wchar_t
- // ::= b # bool
- // ::= c # char
- // ::= a # signed char
- // ::= h # unsigned char
- // ::= s # short
- // ::= t # unsigned short
- // ::= i # int
- // ::= j # unsigned int
- // ::= l # long
- // ::= m # unsigned long
- // ::= x # long long, __int64
- // ::= y # unsigned long long, __int64
- // ::= n # __int128
- // UNSUPPORTED: ::= o # unsigned __int128
- // ::= f # float
- // ::= d # double
- // ::= e # long double, __float80
- // UNSUPPORTED: ::= g # __float128
- // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
- // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
- // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
- // ::= Dh # IEEE 754r half-precision floating point (16 bits)
- // ::= Di # char32_t
- // ::= Ds # char16_t
- // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
- // ::= u <source-name> # vendor extended type
- switch (T->getKind()) {
- case BuiltinType::Void: Out << 'v'; break;
- case BuiltinType::Bool: Out << 'b'; break;
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
- case BuiltinType::UChar: Out << 'h'; break;
- case BuiltinType::UShort: Out << 't'; break;
- case BuiltinType::UInt: Out << 'j'; break;
- case BuiltinType::ULong: Out << 'm'; break;
- case BuiltinType::ULongLong: Out << 'y'; break;
- case BuiltinType::UInt128: Out << 'o'; break;
- case BuiltinType::SChar: Out << 'a'; break;
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: Out << 'w'; break;
- case BuiltinType::Char16: Out << "Ds"; break;
- case BuiltinType::Char32: Out << "Di"; break;
- case BuiltinType::Short: Out << 's'; break;
- case BuiltinType::Int: Out << 'i'; break;
- case BuiltinType::Long: Out << 'l'; break;
- case BuiltinType::LongLong: Out << 'x'; break;
- case BuiltinType::Int128: Out << 'n'; break;
- case BuiltinType::Half: Out << "Dh"; break;
- case BuiltinType::Float: Out << 'f'; break;
- case BuiltinType::Double: Out << 'd'; break;
- case BuiltinType::LongDouble: Out << 'e'; break;
- case BuiltinType::NullPtr: Out << "Dn"; break;
-
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- case BuiltinType::Dependent:
- llvm_unreachable("mangling a placeholder type");
- case BuiltinType::ObjCId: Out << "11objc_object"; break;
- case BuiltinType::ObjCClass: Out << "10objc_class"; break;
- case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
- case BuiltinType::OCLImage1d: Out << "11ocl_image1d"; break;
- case BuiltinType::OCLImage1dArray: Out << "16ocl_image1darray"; break;
- case BuiltinType::OCLImage1dBuffer: Out << "17ocl_image1dbuffer"; break;
- case BuiltinType::OCLImage2d: Out << "11ocl_image2d"; break;
- case BuiltinType::OCLImage2dArray: Out << "16ocl_image2darray"; break;
- case BuiltinType::OCLImage3d: Out << "11ocl_image3d"; break;
- }
-}
-
-// <type> ::= <function-type>
-// <function-type> ::= [<CV-qualifiers>] F [Y]
-// <bare-function-type> [<ref-qualifier>] E
-// (Proposal to cxx-abi-dev, 2012-05-11)
-void CXXNameMangler::mangleType(const FunctionProtoType *T) {
- // Mangle CV-qualifiers, if present. These are 'this' qualifiers,
- // e.g. "const" in "int (A::*)() const".
- mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
-
- Out << 'F';
-
- // FIXME: We don't have enough information in the AST to produce the 'Y'
- // encoding for extern "C" function types.
- mangleBareFunctionType(T, /*MangleReturnType=*/true);
-
- // Mangle the ref-qualifier, if present.
- mangleRefQualifier(T->getRefQualifier());
-
- Out << 'E';
-}
-void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
- llvm_unreachable("Can't mangle K&R function prototypes");
-}
-void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
- bool MangleReturnType) {
- // We should never be mangling something without a prototype.
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
-
- // Record that we're in a function type. See mangleFunctionParam
- // for details on what we're trying to achieve here.
- FunctionTypeDepthState saved = FunctionTypeDepth.push();
-
- // <bare-function-type> ::= <signature type>+
- if (MangleReturnType) {
- FunctionTypeDepth.enterResultType();
- mangleType(Proto->getResultType());
- FunctionTypeDepth.leaveResultType();
- }
-
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
- // <builtin-type> ::= v # void
- Out << 'v';
-
- FunctionTypeDepth.pop(saved);
- return;
- }
-
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- mangleType(Context.getASTContext().getSignatureParameterType(*Arg));
-
- FunctionTypeDepth.pop(saved);
-
- // <builtin-type> ::= z # ellipsis
- if (Proto->isVariadic())
- Out << 'z';
-}
-
-// <type> ::= <class-enum-type>
-// <class-enum-type> ::= <name>
-void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
- mangleName(T->getDecl());
-}
-
-// <type> ::= <class-enum-type>
-// <class-enum-type> ::= <name>
-void CXXNameMangler::mangleType(const EnumType *T) {
- mangleType(static_cast<const TagType*>(T));
-}
-void CXXNameMangler::mangleType(const RecordType *T) {
- mangleType(static_cast<const TagType*>(T));
-}
-void CXXNameMangler::mangleType(const TagType *T) {
- mangleName(T->getDecl());
-}
-
-// <type> ::= <array-type>
-// <array-type> ::= A <positive dimension number> _ <element type>
-// ::= A [<dimension expression>] _ <element type>
-void CXXNameMangler::mangleType(const ConstantArrayType *T) {
- Out << 'A' << T->getSize() << '_';
- mangleType(T->getElementType());
-}
-void CXXNameMangler::mangleType(const VariableArrayType *T) {
- Out << 'A';
- // decayed vla types (size 0) will just be skipped.
- if (T->getSizeExpr())
- mangleExpression(T->getSizeExpr());
- Out << '_';
- mangleType(T->getElementType());
-}
-void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
- Out << 'A';
- mangleExpression(T->getSizeExpr());
- Out << '_';
- mangleType(T->getElementType());
-}
-void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
- Out << "A_";
- mangleType(T->getElementType());
-}
-
-// <type> ::= <pointer-to-member-type>
-// <pointer-to-member-type> ::= M <class type> <member type>
-void CXXNameMangler::mangleType(const MemberPointerType *T) {
- Out << 'M';
- mangleType(QualType(T->getClass(), 0));
- QualType PointeeType = T->getPointeeType();
- if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
- mangleType(FPT);
-
- // Itanium C++ ABI 5.1.8:
- //
- // The type of a non-static member function is considered to be different,
- // for the purposes of substitution, from the type of a namespace-scope or
- // static member function whose type appears similar. The types of two
- // non-static member functions are considered to be different, for the
- // purposes of substitution, if the functions are members of different
- // classes. In other words, for the purposes of substitution, the class of
- // which the function is a member is considered part of the type of
- // function.
-
- // Given that we already substitute member function pointers as a
- // whole, the net effect of this rule is just to unconditionally
- // suppress substitution on the function type in a member pointer.
- // We increment the SeqID here to emulate adding an entry to the
- // substitution table.
- ++SeqID;
- } else
- mangleType(PointeeType);
-}
-
-// <type> ::= <template-param>
-void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
- mangleTemplateParameter(T->getIndex());
-}
-
-// <type> ::= <template-param>
-void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
- // FIXME: not clear how to mangle this!
- // template <class T...> class A {
- // template <class U...> void foo(T(*)(U) x...);
- // };
- Out << "_SUBSTPACK_";
-}
-
-// <type> ::= P <type> # pointer-to
-void CXXNameMangler::mangleType(const PointerType *T) {
- Out << 'P';
- mangleType(T->getPointeeType());
-}
-void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
- Out << 'P';
- mangleType(T->getPointeeType());
-}
-
-// <type> ::= R <type> # reference-to
-void CXXNameMangler::mangleType(const LValueReferenceType *T) {
- Out << 'R';
- mangleType(T->getPointeeType());
-}
-
-// <type> ::= O <type> # rvalue reference-to (C++0x)
-void CXXNameMangler::mangleType(const RValueReferenceType *T) {
- Out << 'O';
- mangleType(T->getPointeeType());
-}
-
-// <type> ::= C <type> # complex pair (C 2000)
-void CXXNameMangler::mangleType(const ComplexType *T) {
- Out << 'C';
- mangleType(T->getElementType());
-}
-
-// ARM's ABI for Neon vector types specifies that they should be mangled as
-// if they are structs (to match ARM's initial implementation). The
-// vector type must be one of the special types predefined by ARM.
-void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
- QualType EltType = T->getElementType();
- assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
- const char *EltName = 0;
- if (T->getVectorKind() == VectorType::NeonPolyVector) {
- switch (cast<BuiltinType>(EltType)->getKind()) {
- case BuiltinType::SChar: EltName = "poly8_t"; break;
- case BuiltinType::Short: EltName = "poly16_t"; break;
- default: llvm_unreachable("unexpected Neon polynomial vector element type");
- }
- } else {
- switch (cast<BuiltinType>(EltType)->getKind()) {
- case BuiltinType::SChar: EltName = "int8_t"; break;
- case BuiltinType::UChar: EltName = "uint8_t"; break;
- case BuiltinType::Short: EltName = "int16_t"; break;
- case BuiltinType::UShort: EltName = "uint16_t"; break;
- case BuiltinType::Int: EltName = "int32_t"; break;
- case BuiltinType::UInt: EltName = "uint32_t"; break;
- case BuiltinType::LongLong: EltName = "int64_t"; break;
- case BuiltinType::ULongLong: EltName = "uint64_t"; break;
- case BuiltinType::Float: EltName = "float32_t"; break;
- default: llvm_unreachable("unexpected Neon vector element type");
- }
- }
- const char *BaseName = 0;
- unsigned BitSize = (T->getNumElements() *
- getASTContext().getTypeSize(EltType));
- if (BitSize == 64)
- BaseName = "__simd64_";
- else {
- assert(BitSize == 128 && "Neon vector type not 64 or 128 bits");
- BaseName = "__simd128_";
- }
- Out << strlen(BaseName) + strlen(EltName);
- Out << BaseName << EltName;
-}
-
-// GNU extension: vector types
-// <type> ::= <vector-type>
-// <vector-type> ::= Dv <positive dimension number> _
-// <extended element type>
-// ::= Dv [<dimension expression>] _ <element type>
-// <extended element type> ::= <element type>
-// ::= p # AltiVec vector pixel
-// ::= b # Altivec vector bool
-void CXXNameMangler::mangleType(const VectorType *T) {
- if ((T->getVectorKind() == VectorType::NeonVector ||
- T->getVectorKind() == VectorType::NeonPolyVector)) {
- mangleNeonVectorType(T);
- return;
- }
- Out << "Dv" << T->getNumElements() << '_';
- if (T->getVectorKind() == VectorType::AltiVecPixel)
- Out << 'p';
- else if (T->getVectorKind() == VectorType::AltiVecBool)
- Out << 'b';
- else
- mangleType(T->getElementType());
-}
-void CXXNameMangler::mangleType(const ExtVectorType *T) {
- mangleType(static_cast<const VectorType*>(T));
-}
-void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
- Out << "Dv";
- mangleExpression(T->getSizeExpr());
- Out << '_';
- mangleType(T->getElementType());
-}
-
-void CXXNameMangler::mangleType(const PackExpansionType *T) {
- // <type> ::= Dp <type> # pack expansion (C++0x)
- Out << "Dp";
- mangleType(T->getPattern());
-}
-
-void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
- mangleSourceName(T->getDecl()->getIdentifier());
-}
-
-void CXXNameMangler::mangleType(const ObjCObjectType *T) {
- // We don't allow overloading by different protocol qualification,
- // so mangling them isn't necessary.
- mangleType(T->getBaseType());
-}
-
-void CXXNameMangler::mangleType(const BlockPointerType *T) {
- Out << "U13block_pointer";
- mangleType(T->getPointeeType());
-}
-
-void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
- // Mangle injected class name types as if the user had written the
- // specialization out fully. It may not actually be possible to see
- // this mangling, though.
- mangleType(T->getInjectedSpecializationType());
-}
-
-void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
- if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
- mangleName(TD, T->getArgs(), T->getNumArgs());
- } else {
- if (mangleSubstitution(QualType(T, 0)))
- return;
-
- mangleTemplatePrefix(T->getTemplateName());
-
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());
- addSubstitution(QualType(T, 0));
- }
-}
-
-void CXXNameMangler::mangleType(const DependentNameType *T) {
- // Typename types are always nested
- Out << 'N';
- manglePrefix(T->getQualifier());
- mangleSourceName(T->getIdentifier());
- Out << 'E';
-}
-
-void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
- // Dependently-scoped template types are nested if they have a prefix.
- Out << 'N';
-
- // TODO: avoid making this TemplateName.
- TemplateName Prefix =
- getASTContext().getDependentTemplateName(T->getQualifier(),
- T->getIdentifier());
- mangleTemplatePrefix(Prefix);
-
- // FIXME: GCC does not appear to mangle the template arguments when
- // the template in question is a dependent template name. Should we
- // emulate that badness?
- mangleTemplateArgs(T->getArgs(), T->getNumArgs());
- Out << 'E';
-}
-
-void CXXNameMangler::mangleType(const TypeOfType *T) {
- // FIXME: this is pretty unsatisfactory, but there isn't an obvious
- // "extension with parameters" mangling.
- Out << "u6typeof";
-}
-
-void CXXNameMangler::mangleType(const TypeOfExprType *T) {
- // FIXME: this is pretty unsatisfactory, but there isn't an obvious
- // "extension with parameters" mangling.
- Out << "u6typeof";
-}
-
-void CXXNameMangler::mangleType(const DecltypeType *T) {
- Expr *E = T->getUnderlyingExpr();
-
- // type ::= Dt <expression> E # decltype of an id-expression
- // # or class member access
- // ::= DT <expression> E # decltype of an expression
-
- // This purports to be an exhaustive list of id-expressions and
- // class member accesses. Note that we do not ignore parentheses;
- // parentheses change the semantics of decltype for these
- // expressions (and cause the mangler to use the other form).
- if (isa<DeclRefExpr>(E) ||
- isa<MemberExpr>(E) ||
- isa<UnresolvedLookupExpr>(E) ||
- isa<DependentScopeDeclRefExpr>(E) ||
- isa<CXXDependentScopeMemberExpr>(E) ||
- isa<UnresolvedMemberExpr>(E))
- Out << "Dt";
- else
- Out << "DT";
- mangleExpression(E);
- Out << 'E';
-}
-
-void CXXNameMangler::mangleType(const UnaryTransformType *T) {
- // If this is dependent, we need to record that. If not, we simply
- // mangle it as the underlying type since they are equivalent.
- if (T->isDependentType()) {
- Out << 'U';
-
- switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- Out << "3eut";
- break;
- }
- }
-
- mangleType(T->getUnderlyingType());
-}
-
-void CXXNameMangler::mangleType(const AutoType *T) {
- QualType D = T->getDeducedType();
- // <builtin-type> ::= Da # dependent auto
- if (D.isNull())
- Out << "Da";
- else
- mangleType(D);
-}
-
-void CXXNameMangler::mangleType(const AtomicType *T) {
- // <type> ::= U <source-name> <type> # vendor extended type qualifier
- // (Until there's a standardized mangling...)
- Out << "U7_Atomic";
- mangleType(T->getValueType());
-}
-
-void CXXNameMangler::mangleIntegerLiteral(QualType T,
- const llvm::APSInt &Value) {
- // <expr-primary> ::= L <type> <value number> E # integer literal
- Out << 'L';
-
- mangleType(T);
- if (T->isBooleanType()) {
- // Boolean values are encoded as 0/1.
- Out << (Value.getBoolValue() ? '1' : '0');
- } else {
- mangleNumber(Value);
- }
- Out << 'E';
-
-}
-
-/// Mangles a member expression.
-void CXXNameMangler::mangleMemberExpr(const Expr *base,
- bool isArrow,
- NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
- DeclarationName member,
- unsigned arity) {
- // <expression> ::= dt <expression> <unresolved-name>
- // ::= pt <expression> <unresolved-name>
- if (base) {
- if (base->isImplicitCXXThis()) {
- // Note: GCC mangles member expressions to the implicit 'this' as
- // *this., whereas we represent them as this->. The Itanium C++ ABI
- // does not specify anything here, so we follow GCC.
- Out << "dtdefpT";
- } else {
- Out << (isArrow ? "pt" : "dt");
- mangleExpression(base);
- }
- }
- mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
-}
-
-/// Look at the callee of the given call expression and determine if
-/// it's a parenthesized id-expression which would have triggered ADL
-/// otherwise.
-static bool isParenthesizedADLCallee(const CallExpr *call) {
- const Expr *callee = call->getCallee();
- const Expr *fn = callee->IgnoreParens();
-
- // Must be parenthesized. IgnoreParens() skips __extension__ nodes,
- // too, but for those to appear in the callee, it would have to be
- // parenthesized.
- if (callee == fn) return false;
-
- // Must be an unresolved lookup.
- const UnresolvedLookupExpr *lookup = dyn_cast<UnresolvedLookupExpr>(fn);
- if (!lookup) return false;
-
- assert(!lookup->requiresADL());
-
- // Must be an unqualified lookup.
- if (lookup->getQualifier()) return false;
-
- // Must not have found a class member. Note that if one is a class
- // member, they're all class members.
- if (lookup->getNumDecls() > 0 &&
- (*lookup->decls_begin())->isCXXClassMember())
- return false;
-
- // Otherwise, ADL would have been triggered.
- return true;
-}
-
-void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
- // <expression> ::= <unary operator-name> <expression>
- // ::= <binary operator-name> <expression> <expression>
- // ::= <trinary operator-name> <expression> <expression> <expression>
- // ::= cv <type> expression # conversion with one argument
- // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
- // ::= st <type> # sizeof (a type)
- // ::= at <type> # alignof (a type)
- // ::= <template-param>
- // ::= <function-param>
- // ::= sr <type> <unqualified-name> # dependent name
- // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
- // ::= ds <expression> <expression> # expr.*expr
- // ::= sZ <template-param> # size of a parameter pack
- // ::= sZ <function-param> # size of a function parameter pack
- // ::= <expr-primary>
- // <expr-primary> ::= L <type> <value number> E # integer literal
- // ::= L <type <value float> E # floating literal
- // ::= L <mangled-name> E # external name
- // ::= fpT # 'this' expression
- QualType ImplicitlyConvertedToType;
-
-recurse:
- switch (E->getStmtClass()) {
- case Expr::NoStmtClass:
-#define ABSTRACT_STMT(Type)
-#define EXPR(Type, Base)
-#define STMT(Type, Base) \
- case Expr::Type##Class:
-#include "clang/AST/StmtNodes.inc"
- // fallthrough
-
- // These all can only appear in local or variable-initialization
- // contexts and so should never appear in a mangling.
- case Expr::AddrLabelExprClass:
- case Expr::DesignatedInitExprClass:
- case Expr::ImplicitValueInitExprClass:
- case Expr::ParenListExprClass:
- case Expr::LambdaExprClass:
- llvm_unreachable("unexpected statement kind");
-
- // FIXME: invent manglings for all these.
- case Expr::BlockExprClass:
- case Expr::CXXPseudoDestructorExprClass:
- case Expr::ChooseExprClass:
- case Expr::CompoundLiteralExprClass:
- case Expr::ExtVectorElementExprClass:
- case Expr::GenericSelectionExprClass:
- case Expr::ObjCEncodeExprClass:
- case Expr::ObjCIsaExprClass:
- case Expr::ObjCIvarRefExprClass:
- case Expr::ObjCMessageExprClass:
- case Expr::ObjCPropertyRefExprClass:
- case Expr::ObjCProtocolExprClass:
- case Expr::ObjCSelectorExprClass:
- case Expr::ObjCStringLiteralClass:
- case Expr::ObjCBoxedExprClass:
- case Expr::ObjCArrayLiteralClass:
- case Expr::ObjCDictionaryLiteralClass:
- case Expr::ObjCSubscriptRefExprClass:
- case Expr::ObjCIndirectCopyRestoreExprClass:
- case Expr::OffsetOfExprClass:
- case Expr::PredefinedExprClass:
- case Expr::ShuffleVectorExprClass:
- case Expr::StmtExprClass:
- case Expr::UnaryTypeTraitExprClass:
- case Expr::BinaryTypeTraitExprClass:
- case Expr::TypeTraitExprClass:
- case Expr::ArrayTypeTraitExprClass:
- case Expr::ExpressionTraitExprClass:
- case Expr::VAArgExprClass:
- case Expr::CXXUuidofExprClass:
- case Expr::CUDAKernelCallExprClass:
- case Expr::AsTypeExprClass:
- case Expr::PseudoObjectExprClass:
- case Expr::AtomicExprClass:
- {
- // As bad as this diagnostic is, it's better than crashing.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot yet mangle expression type %0");
- Diags.Report(E->getExprLoc(), DiagID)
- << E->getStmtClassName() << E->getSourceRange();
- break;
- }
-
- // Even gcc-4.5 doesn't mangle this.
- case Expr::BinaryConditionalOperatorClass: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID =
- Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "?: operator with omitted middle operand cannot be mangled");
- Diags.Report(E->getExprLoc(), DiagID)
- << E->getStmtClassName() << E->getSourceRange();
- break;
- }
-
- // These are used for internal purposes and cannot be meaningfully mangled.
- case Expr::OpaqueValueExprClass:
- llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");
-
- case Expr::InitListExprClass: {
- // Proposal by Jason Merrill, 2012-01-03
- Out << "il";
- const InitListExpr *InitList = cast<InitListExpr>(E);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
- Out << "E";
- break;
- }
-
- case Expr::CXXDefaultArgExprClass:
- mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
- break;
-
- case Expr::SubstNonTypeTemplateParmExprClass:
- mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
- Arity);
- break;
-
- case Expr::UserDefinedLiteralClass:
- // We follow g++'s approach of mangling a UDL as a call to the literal
- // operator.
- case Expr::CXXMemberCallExprClass: // fallthrough
- case Expr::CallExprClass: {
- const CallExpr *CE = cast<CallExpr>(E);
-
- // <expression> ::= cp <simple-id> <expression>* E
- // We use this mangling only when the call would use ADL except
- // for being parenthesized. Per discussion with David
- // Vandervoorde, 2011.04.25.
- if (isParenthesizedADLCallee(CE)) {
- Out << "cp";
- // The callee here is a parenthesized UnresolvedLookupExpr with
- // no qualifier and should always get mangled as a <simple-id>
- // anyway.
-
- // <expression> ::= cl <expression>* E
- } else {
- Out << "cl";
- }
-
- mangleExpression(CE->getCallee(), CE->getNumArgs());
- for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
- mangleExpression(CE->getArg(I));
- Out << 'E';
- break;
- }
-
- case Expr::CXXNewExprClass: {
- const CXXNewExpr *New = cast<CXXNewExpr>(E);
- if (New->isGlobalNew()) Out << "gs";
- Out << (New->isArray() ? "na" : "nw");
- for (CXXNewExpr::const_arg_iterator I = New->placement_arg_begin(),
- E = New->placement_arg_end(); I != E; ++I)
- mangleExpression(*I);
- Out << '_';
- mangleType(New->getAllocatedType());
- if (New->hasInitializer()) {
- // Proposal by Jason Merrill, 2012-01-03
- if (New->getInitializationStyle() == CXXNewExpr::ListInit)
- Out << "il";
- else
- Out << "pi";
- const Expr *Init = New->getInitializer();
- if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
- // Directly inline the initializers.
- for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
- E = CCE->arg_end();
- I != E; ++I)
- mangleExpression(*I);
- } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
- for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
- mangleExpression(PLE->getExpr(i));
- } else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&
- isa<InitListExpr>(Init)) {
- // Only take InitListExprs apart for list-initialization.
- const InitListExpr *InitList = cast<InitListExpr>(Init);
- for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
- mangleExpression(InitList->getInit(i));
- } else
- mangleExpression(Init);
- }
- Out << 'E';
- break;
- }
-
- case Expr::MemberExprClass: {
- const MemberExpr *ME = cast<MemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(),
- Arity);
- break;
- }
-
- case Expr::UnresolvedMemberExprClass: {
- const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), 0, ME->getMemberName(),
- Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getExplicitTemplateArgs());
- break;
- }
-
- case Expr::CXXDependentScopeMemberExprClass: {
- const CXXDependentScopeMemberExpr *ME
- = cast<CXXDependentScopeMemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), ME->getFirstQualifierFoundInScope(),
- ME->getMember(), Arity);
- if (ME->hasExplicitTemplateArgs())
- mangleTemplateArgs(ME->getExplicitTemplateArgs());
- break;
- }
-
- case Expr::UnresolvedLookupExprClass: {
- const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
- mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (ULE->hasExplicitTemplateArgs())
- mangleTemplateArgs(ULE->getExplicitTemplateArgs());
- break;
- }
-
- case Expr::CXXUnresolvedConstructExprClass: {
- const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
- unsigned N = CE->arg_size();
-
- Out << "cv";
- mangleType(CE->getType());
- if (N != 1) Out << '_';
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
- if (N != 1) Out << 'E';
- break;
- }
-
- case Expr::CXXTemporaryObjectExprClass:
- case Expr::CXXConstructExprClass: {
- const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
- unsigned N = CE->getNumArgs();
-
- // Proposal by Jason Merrill, 2012-01-03
- if (CE->isListInitialization())
- Out << "tl";
- else
- Out << "cv";
- mangleType(CE->getType());
- if (N != 1) Out << '_';
- for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
- if (N != 1) Out << 'E';
- break;
- }
-
- case Expr::CXXScalarValueInitExprClass:
- Out <<"cv";
- mangleType(E->getType());
- Out <<"_E";
- break;
-
- case Expr::CXXNoexceptExprClass:
- Out << "nx";
- mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
- break;
-
- case Expr::UnaryExprOrTypeTraitExprClass: {
- const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
-
- if (!SAE->isInstantiationDependent()) {
- // Itanium C++ ABI:
- // If the operand of a sizeof or alignof operator is not
- // instantiation-dependent it is encoded as an integer literal
- // reflecting the result of the operator.
- //
- // If the result of the operator is implicitly converted to a known
- // integer type, that type is used for the literal; otherwise, the type
- // of std::size_t or std::ptrdiff_t is used.
- QualType T = (ImplicitlyConvertedToType.isNull() ||
- !ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
- : ImplicitlyConvertedToType;
- llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
- mangleIntegerLiteral(T, V);
- break;
- }
-
- switch(SAE->getKind()) {
- case UETT_SizeOf:
- Out << 's';
- break;
- case UETT_AlignOf:
- Out << 'a';
- break;
- case UETT_VecStep:
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot yet mangle vec_step expression");
- Diags.Report(DiagID);
- return;
- }
- if (SAE->isArgumentType()) {
- Out << 't';
- mangleType(SAE->getArgumentType());
- } else {
- Out << 'z';
- mangleExpression(SAE->getArgumentExpr());
- }
- break;
- }
-
- case Expr::CXXThrowExprClass: {
- const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
-
- // Proposal from David Vandervoorde, 2010.06.30
- if (TE->getSubExpr()) {
- Out << "tw";
- mangleExpression(TE->getSubExpr());
- } else {
- Out << "tr";
- }
- break;
- }
-
- case Expr::CXXTypeidExprClass: {
- const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
-
- // Proposal from David Vandervoorde, 2010.06.30
- if (TIE->isTypeOperand()) {
- Out << "ti";
- mangleType(TIE->getTypeOperand());
- } else {
- Out << "te";
- mangleExpression(TIE->getExprOperand());
- }
- break;
- }
-
- case Expr::CXXDeleteExprClass: {
- const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
-
- // Proposal from David Vandervoorde, 2010.06.30
- if (DE->isGlobalDelete()) Out << "gs";
- Out << (DE->isArrayForm() ? "da" : "dl");
- mangleExpression(DE->getArgument());
- break;
- }
-
- case Expr::UnaryOperatorClass: {
- const UnaryOperator *UO = cast<UnaryOperator>(E);
- mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
- /*Arity=*/1);
- mangleExpression(UO->getSubExpr());
- break;
- }
-
- case Expr::ArraySubscriptExprClass: {
- const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);
-
- // Array subscript is treated as a syntactically weird form of
- // binary operator.
- Out << "ix";
- mangleExpression(AE->getLHS());
- mangleExpression(AE->getRHS());
- break;
- }
-
- case Expr::CompoundAssignOperatorClass: // fallthrough
- case Expr::BinaryOperatorClass: {
- const BinaryOperator *BO = cast<BinaryOperator>(E);
- if (BO->getOpcode() == BO_PtrMemD)
- Out << "ds";
- else
- mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
- /*Arity=*/2);
- mangleExpression(BO->getLHS());
- mangleExpression(BO->getRHS());
- break;
- }
-
- case Expr::ConditionalOperatorClass: {
- const ConditionalOperator *CO = cast<ConditionalOperator>(E);
- mangleOperatorName(OO_Conditional, /*Arity=*/3);
- mangleExpression(CO->getCond());
- mangleExpression(CO->getLHS(), Arity);
- mangleExpression(CO->getRHS(), Arity);
- break;
- }
-
- case Expr::ImplicitCastExprClass: {
- ImplicitlyConvertedToType = E->getType();
- E = cast<ImplicitCastExpr>(E)->getSubExpr();
- goto recurse;
- }
-
- case Expr::ObjCBridgedCastExprClass: {
- // Mangle ownership casts as a vendor extended operator __bridge,
- // __bridge_transfer, or __bridge_retain.
- StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
- Out << "v1U" << Kind.size() << Kind;
- }
- // Fall through to mangle the cast itself.
-
- case Expr::CStyleCastExprClass:
- case Expr::CXXStaticCastExprClass:
- case Expr::CXXDynamicCastExprClass:
- case Expr::CXXReinterpretCastExprClass:
- case Expr::CXXConstCastExprClass:
- case Expr::CXXFunctionalCastExprClass: {
- const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
- Out << "cv";
- mangleType(ECE->getType());
- mangleExpression(ECE->getSubExpr());
- break;
- }
-
- case Expr::CXXOperatorCallExprClass: {
- const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
- unsigned NumArgs = CE->getNumArgs();
- mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
- // Mangle the arguments.
- for (unsigned i = 0; i != NumArgs; ++i)
- mangleExpression(CE->getArg(i));
- break;
- }
-
- case Expr::ParenExprClass:
- mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
- break;
-
- case Expr::DeclRefExprClass: {
- const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
-
- switch (D->getKind()) {
- default:
- // <expr-primary> ::= L <mangled-name> E # external name
- Out << 'L';
- mangle(D, "_Z");
- Out << 'E';
- break;
-
- case Decl::ParmVar:
- mangleFunctionParam(cast<ParmVarDecl>(D));
- break;
-
- case Decl::EnumConstant: {
- const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
- mangleIntegerLiteral(ED->getType(), ED->getInitVal());
- break;
- }
-
- case Decl::NonTypeTemplateParm: {
- const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
- mangleTemplateParameter(PD->getIndex());
- break;
- }
-
- }
-
- break;
- }
-
- case Expr::SubstNonTypeTemplateParmPackExprClass:
- // FIXME: not clear how to mangle this!
- // template <unsigned N...> class A {
- // template <class U...> void foo(U (&x)[N]...);
- // };
- Out << "_SUBSTPACK_";
- break;
-
- case Expr::FunctionParmPackExprClass: {
- // FIXME: not clear how to mangle this!
- const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
- Out << "v110_SUBSTPACK";
- mangleFunctionParam(FPPE->getParameterPack());
- break;
- }
-
- case Expr::DependentScopeDeclRefExprClass: {
- const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
- mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
-
- // All the <unresolved-name> productions end in a
- // base-unresolved-name, where <template-args> are just tacked
- // onto the end.
- if (DRE->hasExplicitTemplateArgs())
- mangleTemplateArgs(DRE->getExplicitTemplateArgs());
- break;
- }
-
- case Expr::CXXBindTemporaryExprClass:
- mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
- break;
-
- case Expr::ExprWithCleanupsClass:
- mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);
- break;
-
- case Expr::FloatingLiteralClass: {
- const FloatingLiteral *FL = cast<FloatingLiteral>(E);
- Out << 'L';
- mangleType(FL->getType());
- mangleFloat(FL->getValue());
- Out << 'E';
- break;
- }
-
- case Expr::CharacterLiteralClass:
- Out << 'L';
- mangleType(E->getType());
- Out << cast<CharacterLiteral>(E)->getValue();
- Out << 'E';
- break;
-
- // FIXME. __objc_yes/__objc_no are mangled same as true/false
- case Expr::ObjCBoolLiteralExprClass:
- Out << "Lb";
- Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
- Out << 'E';
- break;
-
- case Expr::CXXBoolLiteralExprClass:
- Out << "Lb";
- Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
- Out << 'E';
- break;
-
- case Expr::IntegerLiteralClass: {
- llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
- if (E->getType()->isSignedIntegerType())
- Value.setIsSigned(true);
- mangleIntegerLiteral(E->getType(), Value);
- break;
- }
-
- case Expr::ImaginaryLiteralClass: {
- const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);
- // Mangle as if a complex literal.
- // Proposal from David Vandevoorde, 2010.06.30.
- Out << 'L';
- mangleType(E->getType());
- if (const FloatingLiteral *Imag =
- dyn_cast<FloatingLiteral>(IE->getSubExpr())) {
- // Mangle a floating-point zero of the appropriate type.
- mangleFloat(llvm::APFloat(Imag->getValue().getSemantics()));
- Out << '_';
- mangleFloat(Imag->getValue());
- } else {
- Out << "0_";
- llvm::APSInt Value(cast<IntegerLiteral>(IE->getSubExpr())->getValue());
- if (IE->getSubExpr()->getType()->isSignedIntegerType())
- Value.setIsSigned(true);
- mangleNumber(Value);
- }
- Out << 'E';
- break;
- }
-
- case Expr::StringLiteralClass: {
- // Revised proposal from David Vandervoorde, 2010.07.15.
- Out << 'L';
- assert(isa<ConstantArrayType>(E->getType()));
- mangleType(E->getType());
- Out << 'E';
- break;
- }
-
- case Expr::GNUNullExprClass:
- // FIXME: should this really be mangled the same as nullptr?
- // fallthrough
-
- case Expr::CXXNullPtrLiteralExprClass: {
- // Proposal from David Vandervoorde, 2010.06.30, as
- // modified by ABI list discussion.
- Out << "LDnE";
- break;
- }
-
- case Expr::PackExpansionExprClass:
- Out << "sp";
- mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
- break;
-
- case Expr::SizeOfPackExprClass: {
- Out << "sZ";
- const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();
- if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
- mangleTemplateParameter(TTP->getIndex());
- else if (const NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(Pack))
- mangleTemplateParameter(NTTP->getIndex());
- else if (const TemplateTemplateParmDecl *TempTP
- = dyn_cast<TemplateTemplateParmDecl>(Pack))
- mangleTemplateParameter(TempTP->getIndex());
- else
- mangleFunctionParam(cast<ParmVarDecl>(Pack));
- break;
- }
-
- case Expr::MaterializeTemporaryExprClass: {
- mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
- break;
- }
-
- case Expr::CXXThisExprClass:
- Out << "fpT";
- break;
- }
-}
-
-/// Mangle an expression which refers to a parameter variable.
-///
-/// <expression> ::= <function-param>
-/// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, I == 0
-/// <function-param> ::= fp <top-level CV-qualifiers>
-/// <parameter-2 non-negative number> _ # L == 0, I > 0
-/// <function-param> ::= fL <L-1 non-negative number>
-/// p <top-level CV-qualifiers> _ # L > 0, I == 0
-/// <function-param> ::= fL <L-1 non-negative number>
-/// p <top-level CV-qualifiers>
-/// <I-1 non-negative number> _ # L > 0, I > 0
-///
-/// L is the nesting depth of the parameter, defined as 1 if the
-/// parameter comes from the innermost function prototype scope
-/// enclosing the current context, 2 if from the next enclosing
-/// function prototype scope, and so on, with one special case: if
-/// we've processed the full parameter clause for the innermost
-/// function type, then L is one less. This definition conveniently
-/// makes it irrelevant whether a function's result type was written
-/// trailing or leading, but is otherwise overly complicated; the
-/// numbering was first designed without considering references to
-/// parameter in locations other than return types, and then the
-/// mangling had to be generalized without changing the existing
-/// manglings.
-///
-/// I is the zero-based index of the parameter within its parameter
-/// declaration clause. Note that the original ABI document describes
-/// this using 1-based ordinals.
-void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
- unsigned parmDepth = parm->getFunctionScopeDepth();
- unsigned parmIndex = parm->getFunctionScopeIndex();
-
- // Compute 'L'.
- // parmDepth does not include the declaring function prototype.
- // FunctionTypeDepth does account for that.
- assert(parmDepth < FunctionTypeDepth.getDepth());
- unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth;
- if (FunctionTypeDepth.isInResultType())
- nestingDepth--;
-
- if (nestingDepth == 0) {
- Out << "fp";
- } else {
- Out << "fL" << (nestingDepth - 1) << 'p';
- }
-
- // Top-level qualifiers. We don't have to worry about arrays here,
- // because parameters declared as arrays should already have been
- // transformed to have pointer type. FIXME: apparently these don't
- // get mangled if used as an rvalue of a known non-class type?
- assert(!parm->getType()->isArrayType()
- && "parameter's type is still an array type?");
- mangleQualifiers(parm->getType().getQualifiers());
-
- // Parameter index.
- if (parmIndex != 0) {
- Out << (parmIndex - 1);
- }
- Out << '_';
-}
-
-void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
- // <ctor-dtor-name> ::= C1 # complete object constructor
- // ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
- //
- switch (T) {
- case Ctor_Complete:
- Out << "C1";
- break;
- case Ctor_Base:
- Out << "C2";
- break;
- case Ctor_CompleteAllocating:
- Out << "C3";
- break;
- }
-}
-
-void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
- // <ctor-dtor-name> ::= D0 # deleting destructor
- // ::= D1 # complete object destructor
- // ::= D2 # base object destructor
- //
- switch (T) {
- case Dtor_Deleting:
- Out << "D0";
- break;
- case Dtor_Complete:
- Out << "D1";
- break;
- case Dtor_Base:
- Out << "D2";
- break;
- }
-}
-
-void CXXNameMangler::mangleTemplateArgs(
- const ASTTemplateArgumentListInfo &TemplateArgs) {
- // <template-args> ::= I <template-arg>+ E
- Out << 'I';
- for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
- mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
- Out << 'E';
-}
-
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
- // <template-args> ::= I <template-arg>+ E
- Out << 'I';
- for (unsigned i = 0, e = AL.size(); i != e; ++i)
- mangleTemplateArg(AL[i]);
- Out << 'E';
-}
-
-void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs) {
- // <template-args> ::= I <template-arg>+ E
- Out << 'I';
- for (unsigned i = 0; i != NumTemplateArgs; ++i)
- mangleTemplateArg(TemplateArgs[i]);
- Out << 'E';
-}
-
-void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
- // <template-arg> ::= <type> # type or template
- // ::= X <expression> E # expression
- // ::= <expr-primary> # simple expressions
- // ::= J <template-arg>* E # argument pack
- // ::= sp <expression> # pack expansion of (C++0x)
- if (!A.isInstantiationDependent() || A.isDependent())
- A = Context.getASTContext().getCanonicalTemplateArgument(A);
-
- switch (A.getKind()) {
- case TemplateArgument::Null:
- llvm_unreachable("Cannot mangle NULL template argument");
-
- case TemplateArgument::Type:
- mangleType(A.getAsType());
- break;
- case TemplateArgument::Template:
- // This is mangled as <type>.
- mangleType(A.getAsTemplate());
- break;
- case TemplateArgument::TemplateExpansion:
- // <type> ::= Dp <type> # pack expansion (C++0x)
- Out << "Dp";
- mangleType(A.getAsTemplateOrTemplatePattern());
- break;
- case TemplateArgument::Expression: {
- // It's possible to end up with a DeclRefExpr here in certain
- // dependent cases, in which case we should mangle as a
- // declaration.
- const Expr *E = A.getAsExpr()->IgnoreParens();
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
- const ValueDecl *D = DRE->getDecl();
- if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
- Out << "L";
- mangle(D, "_Z");
- Out << 'E';
- break;
- }
- }
-
- Out << 'X';
- mangleExpression(E);
- Out << 'E';
- break;
- }
- case TemplateArgument::Integral:
- mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
- break;
- case TemplateArgument::Declaration: {
- // <expr-primary> ::= L <mangled-name> E # external name
- // Clang produces AST's where pointer-to-member-function expressions
- // and pointer-to-function expressions are represented as a declaration not
- // an expression. We compensate for it here to produce the correct mangling.
- ValueDecl *D = A.getAsDecl();
- bool compensateMangling = !A.isDeclForReferenceParam();
- if (compensateMangling) {
- Out << 'X';
- mangleOperatorName(OO_Amp, 1);
- }
-
- Out << 'L';
- // References to external entities use the mangled name; if the name would
- // not normally be manged then mangle it as unqualified.
- //
- // FIXME: The ABI specifies that external names here should have _Z, but
- // gcc leaves this off.
- if (compensateMangling)
- mangle(D, "_Z");
- else
- mangle(D, "Z");
- Out << 'E';
-
- if (compensateMangling)
- Out << 'E';
-
- break;
- }
- case TemplateArgument::NullPtr: {
- // <expr-primary> ::= L <type> 0 E
- Out << 'L';
- mangleType(A.getNullPtrType());
- Out << "0E";
- break;
- }
- case TemplateArgument::Pack: {
- // Note: proposal by Mike Herrick on 12/20/10
- Out << 'J';
- for (TemplateArgument::pack_iterator PA = A.pack_begin(),
- PAEnd = A.pack_end();
- PA != PAEnd; ++PA)
- mangleTemplateArg(*PA);
- Out << 'E';
- }
- }
-}
-
-void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
- // <template-param> ::= T_ # first template parameter
- // ::= T <parameter-2 non-negative number> _
- if (Index == 0)
- Out << "T_";
- else
- Out << 'T' << (Index - 1) << '_';
-}
-
-void CXXNameMangler::mangleExistingSubstitution(QualType type) {
- bool result = mangleSubstitution(type);
- assert(result && "no existing substitution for type");
- (void) result;
-}
-
-void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {
- bool result = mangleSubstitution(tname);
- assert(result && "no existing substitution for template name");
- (void) result;
-}
-
-// <substitution> ::= S <seq-id> _
-// ::= S_
-bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
- // Try one of the standard substitutions first.
- if (mangleStandardSubstitution(ND))
- return true;
-
- ND = cast<NamedDecl>(ND->getCanonicalDecl());
- return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
-}
-
-/// \brief Determine whether the given type has any qualifiers that are
-/// relevant for substitutions.
-static bool hasMangledSubstitutionQualifiers(QualType T) {
- Qualifiers Qs = T.getQualifiers();
- return Qs.getCVRQualifiers() || Qs.hasAddressSpace();
-}
-
-bool CXXNameMangler::mangleSubstitution(QualType T) {
- if (!hasMangledSubstitutionQualifiers(T)) {
- if (const RecordType *RT = T->getAs<RecordType>())
- return mangleSubstitution(RT->getDecl());
- }
-
- uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
-
- return mangleSubstitution(TypePtr);
-}
-
-bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return mangleSubstitution(TD);
-
- Template = Context.getASTContext().getCanonicalTemplateName(Template);
- return mangleSubstitution(
- reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
-}
-
-bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
- llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);
- if (I == Substitutions.end())
- return false;
-
- unsigned SeqID = I->second;
- if (SeqID == 0)
- Out << "S_";
- else {
- SeqID--;
-
- // <seq-id> is encoded in base-36, using digits and upper case letters.
- char Buffer[10];
- char *BufferPtr = llvm::array_endof(Buffer);
-
- if (SeqID == 0) *--BufferPtr = '0';
-
- while (SeqID) {
- assert(BufferPtr > Buffer && "Buffer overflow!");
-
- char c = static_cast<char>(SeqID % 36);
-
- *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
- SeqID /= 36;
- }
-
- Out << 'S'
- << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
- << '_';
- }
-
- return true;
-}
-
-static bool isCharType(QualType T) {
- if (T.isNull())
- return false;
-
- return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
- T->isSpecificBuiltinType(BuiltinType::Char_U);
-}
-
-/// isCharSpecialization - Returns whether a given type is a template
-/// specialization of a given name with a single argument of type char.
-static bool isCharSpecialization(QualType T, const char *Name) {
- if (T.isNull())
- return false;
-
- const RecordType *RT = T->getAs<RecordType>();
- if (!RT)
- return false;
-
- const ClassTemplateSpecializationDecl *SD =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
- if (!SD)
- return false;
-
- if (!isStdNamespace(getEffectiveDeclContext(SD)))
- return false;
-
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
- if (TemplateArgs.size() != 1)
- return false;
-
- if (!isCharType(TemplateArgs[0].getAsType()))
- return false;
-
- return SD->getIdentifier()->getName() == Name;
-}
-
-template <std::size_t StrLen>
-static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
- const char (&Str)[StrLen]) {
- if (!SD->getIdentifier()->isStr(Str))
- return false;
-
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
- if (TemplateArgs.size() != 2)
- return false;
-
- if (!isCharType(TemplateArgs[0].getAsType()))
- return false;
-
- if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
- return false;
-
- return true;
-}
-
-bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
- // <substitution> ::= St # ::std::
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
- if (isStd(NS)) {
- Out << "St";
- return true;
- }
- }
-
- if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
- if (!isStdNamespace(getEffectiveDeclContext(TD)))
- return false;
-
- // <substitution> ::= Sa # ::std::allocator
- if (TD->getIdentifier()->isStr("allocator")) {
- Out << "Sa";
- return true;
- }
-
- // <<substitution> ::= Sb # ::std::basic_string
- if (TD->getIdentifier()->isStr("basic_string")) {
- Out << "Sb";
- return true;
- }
- }
-
- if (const ClassTemplateSpecializationDecl *SD =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
- if (!isStdNamespace(getEffectiveDeclContext(SD)))
- return false;
-
- // <substitution> ::= Ss # ::std::basic_string<char,
- // ::std::char_traits<char>,
- // ::std::allocator<char> >
- if (SD->getIdentifier()->isStr("basic_string")) {
- const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
-
- if (TemplateArgs.size() != 3)
- return false;
-
- if (!isCharType(TemplateArgs[0].getAsType()))
- return false;
-
- if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
- return false;
-
- if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
- return false;
-
- Out << "Ss";
- return true;
- }
-
- // <substitution> ::= Si # ::std::basic_istream<char,
- // ::std::char_traits<char> >
- if (isStreamCharSpecialization(SD, "basic_istream")) {
- Out << "Si";
- return true;
- }
-
- // <substitution> ::= So # ::std::basic_ostream<char,
- // ::std::char_traits<char> >
- if (isStreamCharSpecialization(SD, "basic_ostream")) {
- Out << "So";
- return true;
- }
-
- // <substitution> ::= Sd # ::std::basic_iostream<char,
- // ::std::char_traits<char> >
- if (isStreamCharSpecialization(SD, "basic_iostream")) {
- Out << "Sd";
- return true;
- }
- }
- return false;
-}
-
-void CXXNameMangler::addSubstitution(QualType T) {
- if (!hasMangledSubstitutionQualifiers(T)) {
- if (const RecordType *RT = T->getAs<RecordType>()) {
- addSubstitution(RT->getDecl());
- return;
- }
- }
-
- uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- addSubstitution(TypePtr);
-}
-
-void CXXNameMangler::addSubstitution(TemplateName Template) {
- if (TemplateDecl *TD = Template.getAsTemplateDecl())
- return addSubstitution(TD);
-
- Template = Context.getASTContext().getCanonicalTemplateName(Template);
- addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
-}
-
-void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
- assert(!Substitutions.count(Ptr) && "Substitution already exists!");
- Substitutions[Ptr] = SeqID++;
-}
-
-//
-
-/// \brief Mangles the name of the declaration D and emits that name to the
-/// given output stream.
-///
-/// If the declaration D requires a mangled name, this routine will emit that
-/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
-/// and this routine will return false. In this case, the caller should just
-/// emit the identifier of the declaration (\c D->getIdentifier()) as its
-/// name.
-void ItaniumMangleContext::mangleName(const NamedDecl *D,
- raw_ostream &Out) {
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
- "Invalid mangleName() call, argument is not a variable or function!");
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
- "Invalid mangleName() call on 'structor decl!");
-
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
- getASTContext().getSourceManager(),
- "Mangling declaration");
-
- CXXNameMangler Mangler(*this, Out, D);
- return Mangler.mangle(D);
-}
-
-void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out, D, Type);
- Mangler.mangle(D);
-}
-
-void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream &Out) {
- CXXNameMangler Mangler(*this, Out, D, Type);
- Mangler.mangle(D);
-}
-
-void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &Out) {
- // <special-name> ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // # first call-offset is 'this' adjustment
- // # second call-offset is result adjustment
-
- assert(!isa<CXXDestructorDecl>(MD) &&
- "Use mangleCXXDtor for destructor decls!");
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZT";
- if (!Thunk.Return.isEmpty())
- Mangler.getStream() << 'c';
-
- // Mangle the 'this' pointer adjustment.
- Mangler.mangleCallOffset(Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset);
-
- // Mangle the return pointer adjustment if there is one.
- if (!Thunk.Return.isEmpty())
- Mangler.mangleCallOffset(Thunk.Return.NonVirtual,
- Thunk.Return.VBaseOffsetOffset);
-
- Mangler.mangleFunctionEncoding(MD);
-}
-
-void
-ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
- CXXDtorType Type,
- const ThisAdjustment &ThisAdjustment,
- raw_ostream &Out) {
- // <special-name> ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- CXXNameMangler Mangler(*this, Out, DD, Type);
- Mangler.getStream() << "_ZT";
-
- // Mangle the 'this' pointer adjustment.
- Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
- ThisAdjustment.VCallOffsetOffset);
-
- Mangler.mangleFunctionEncoding(DD);
-}
-
-/// mangleGuardVariable - Returns the mangled name for a guard variable
-/// for the passed in VarDecl.
-void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
- raw_ostream &Out) {
- // <special-name> ::= GV <object name> # Guard variable for one-time
- // # initialization
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZGV";
- Mangler.mangleName(D);
-}
-
-void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,
- raw_ostream &Out) {
- // We match the GCC mangling here.
- // <special-name> ::= GR <object name>
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZGR";
- Mangler.mangleName(D);
-}
-
-void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- // <special-name> ::= TV <type> # virtual table
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZTV";
- Mangler.mangleNameOrStandardSubstitution(RD);
-}
-
-void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- // <special-name> ::= TT <type> # VTT structure
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZTT";
- Mangler.mangleNameOrStandardSubstitution(RD);
-}
-
-void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
- int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &Out) {
- // <special-name> ::= TC <type> <offset number> _ <base type>
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZTC";
- Mangler.mangleNameOrStandardSubstitution(RD);
- Mangler.getStream() << Offset;
- Mangler.getStream() << '_';
- Mangler.mangleNameOrStandardSubstitution(Type);
-}
-
-void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,
- raw_ostream &Out) {
- // <special-name> ::= TI <type> # typeinfo structure
- assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZTI";
- Mangler.mangleType(Ty);
-}
-
-void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,
- raw_ostream &Out) {
- // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
- CXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "_ZTS";
- Mangler.mangleType(Ty);
-}
-
-MangleContext *clang::createItaniumMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) {
- return new ItaniumMangleContext(Context, Diags);
-}
+//===--- ItaniumMangle.cpp - Itanium C++ Name Mangling ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements C++ name mangling according to the Itanium C++ ABI,
+// which is used in GCC 3.2 and newer (and many compilers that are
+// ABI-compatible with GCC):
+//
+// http://www.codesourcery.com/public/cxx-abi/abi.html
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/Mangle.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/Basic/ABI.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define MANGLE_CHECKER 0
+
+#if MANGLE_CHECKER
+#include <cxxabi.h>
+#endif
+
+using namespace clang;
+
+namespace {
+
+/// \brief Retrieve the declaration context that should be used when mangling
+/// the given declaration.
+static const DeclContext *getEffectiveDeclContext(const Decl *D) {
+ // The ABI assumes that lambda closure types that occur within
+ // default arguments live in the context of the function. However, due to
+ // the way in which Clang parses and creates function declarations, this is
+ // not the case: the lambda closure type ends up living in the context
+ // where the function itself resides, because the function declaration itself
+ // had not yet been created. Fix the context here.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+ if (RD->isLambda())
+ if (ParmVarDecl *ContextParam
+ = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+ return ContextParam->getDeclContext();
+ }
+
+ return D->getDeclContext();
+}
+
+static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
+ return getEffectiveDeclContext(cast<Decl>(DC));
+}
+
+static const CXXRecordDecl *GetLocalClassDecl(const NamedDecl *ND) {
+ const DeclContext *DC = dyn_cast<DeclContext>(ND);
+ if (!DC)
+ DC = getEffectiveDeclContext(ND);
+ while (!DC->isNamespace() && !DC->isTranslationUnit()) {
+ const DeclContext *Parent = getEffectiveDeclContext(cast<Decl>(DC));
+ if (isa<FunctionDecl>(Parent))
+ return dyn_cast<CXXRecordDecl>(DC);
+ DC = Parent;
+ }
+ return 0;
+}
+
+static const FunctionDecl *getStructor(const FunctionDecl *fn) {
+ if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
+ return ftd->getTemplatedDecl();
+
+ return fn;
+}
+
+static const NamedDecl *getStructor(const NamedDecl *decl) {
+ const FunctionDecl *fn = dyn_cast_or_null<FunctionDecl>(decl);
+ return (fn ? getStructor(fn) : decl);
+}
+
+static const unsigned UnknownArity = ~0U;
+
+class ItaniumMangleContext : public MangleContext {
+ llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
+ unsigned Discriminator;
+ llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+
+public:
+ explicit ItaniumMangleContext(ASTContext &Context,
+ DiagnosticsEngine &Diags)
+ : MangleContext(Context, Diags) { }
+
+ uint64_t getAnonymousStructId(const TagDecl *TD) {
+ std::pair<llvm::DenseMap<const TagDecl *,
+ uint64_t>::iterator, bool> Result =
+ AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size()));
+ return Result.first->second;
+ }
+
+ void startNewFunction() {
+ MangleContext::startNewFunction();
+ mangleInitDiscriminator();
+ }
+
+ /// @name Mangler Entry Points
+ /// @{
+
+ bool shouldMangleDeclName(const NamedDecl *D);
+ void mangleName(const NamedDecl *D, raw_ostream &);
+ void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ raw_ostream &);
+ void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ raw_ostream &);
+ void mangleReferenceTemporary(const VarDecl *D,
+ raw_ostream &);
+ void mangleCXXVTable(const CXXRecordDecl *RD,
+ raw_ostream &);
+ void mangleCXXVTT(const CXXRecordDecl *RD,
+ raw_ostream &);
+ void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &);
+ void mangleCXXRTTI(QualType T, raw_ostream &);
+ void mangleCXXRTTIName(QualType T, raw_ostream &);
+ void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ raw_ostream &);
+ void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ raw_ostream &);
+
+ void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &);
+
+ void mangleInitDiscriminator() {
+ Discriminator = 0;
+ }
+
+ bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
+ // Lambda closure types with external linkage (indicated by a
+ // non-zero lambda mangling number) have their own numbering scheme, so
+ // they do not need a discriminator.
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(ND))
+ if (RD->isLambda() && RD->getLambdaManglingNumber() > 0)
+ return false;
+
+ unsigned &discriminator = Uniquifier[ND];
+ if (!discriminator)
+ discriminator = ++Discriminator;
+ if (discriminator == 1)
+ return false;
+ disc = discriminator-2;
+ return true;
+ }
+ /// @}
+};
+
+/// CXXNameMangler - Manage the mangling of a single name.
+class CXXNameMangler {
+ ItaniumMangleContext &Context;
+ raw_ostream &Out;
+
+ /// The "structor" is the top-level declaration being mangled, if
+ /// that's not a template specialization; otherwise it's the pattern
+ /// for that specialization.
+ const NamedDecl *Structor;
+ unsigned StructorType;
+
+ /// SeqID - The next subsitution sequence number.
+ unsigned SeqID;
+
+ class FunctionTypeDepthState {
+ unsigned Bits;
+
+ enum { InResultTypeMask = 1 };
+
+ public:
+ FunctionTypeDepthState() : Bits(0) {}
+
+ /// The number of function types we're inside.
+ unsigned getDepth() const {
+ return Bits >> 1;
+ }
+
+ /// True if we're in the return type of the innermost function type.
+ bool isInResultType() const {
+ return Bits & InResultTypeMask;
+ }
+
+ FunctionTypeDepthState push() {
+ FunctionTypeDepthState tmp = *this;
+ Bits = (Bits & ~InResultTypeMask) + 2;
+ return tmp;
+ }
+
+ void enterResultType() {
+ Bits |= InResultTypeMask;
+ }
+
+ void leaveResultType() {
+ Bits &= ~InResultTypeMask;
+ }
+
+ void pop(FunctionTypeDepthState saved) {
+ assert(getDepth() == saved.getDepth() + 1);
+ Bits = saved.Bits;
+ }
+
+ } FunctionTypeDepth;
+
+ llvm::DenseMap<uintptr_t, unsigned> Substitutions;
+
+ ASTContext &getASTContext() const { return Context.getASTContext(); }
+
+public:
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
+ const NamedDecl *D = 0)
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(0),
+ SeqID(0) {
+ // These can't be mangled without a ctor type or dtor type.
+ assert(!D || (!isa<CXXDestructorDecl>(D) &&
+ !isa<CXXConstructorDecl>(D)));
+ }
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
+ const CXXConstructorDecl *D, CXXCtorType Type)
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ SeqID(0) { }
+ CXXNameMangler(ItaniumMangleContext &C, raw_ostream &Out_,
+ const CXXDestructorDecl *D, CXXDtorType Type)
+ : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
+ SeqID(0) { }
+
+#if MANGLE_CHECKER
+ ~CXXNameMangler() {
+ if (Out.str()[0] == '\01')
+ return;
+
+ int status = 0;
+ char *result = abi::__cxa_demangle(Out.str().str().c_str(), 0, 0, &status);
+ assert(status == 0 && "Could not demangle mangled name!");
+ free(result);
+ }
+#endif
+ raw_ostream &getStream() { return Out; }
+
+ void mangle(const NamedDecl *D, StringRef Prefix = "_Z");
+ void mangleCallOffset(int64_t NonVirtual, int64_t Virtual);
+ void mangleNumber(const llvm::APSInt &I);
+ void mangleNumber(int64_t Number);
+ void mangleFloat(const llvm::APFloat &F);
+ void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleName(const NamedDecl *ND);
+ void mangleType(QualType T);
+ void mangleNameOrStandardSubstitution(const NamedDecl *ND);
+
+private:
+ bool mangleSubstitution(const NamedDecl *ND);
+ bool mangleSubstitution(QualType T);
+ bool mangleSubstitution(TemplateName Template);
+ bool mangleSubstitution(uintptr_t Ptr);
+
+ void mangleExistingSubstitution(QualType type);
+ void mangleExistingSubstitution(TemplateName name);
+
+ bool mangleStandardSubstitution(const NamedDecl *ND);
+
+ void addSubstitution(const NamedDecl *ND) {
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
+
+ addSubstitution(reinterpret_cast<uintptr_t>(ND));
+ }
+ void addSubstitution(QualType T);
+ void addSubstitution(TemplateName Template);
+ void addSubstitution(uintptr_t Ptr);
+
+ void mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ bool recursive = false);
+ void mangleUnresolvedName(NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ DeclarationName name,
+ unsigned KnownArity = UnknownArity);
+
+ void mangleName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void mangleUnqualifiedName(const NamedDecl *ND) {
+ mangleUnqualifiedName(ND, ND->getDeclName(), UnknownArity);
+ }
+ void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name,
+ unsigned KnownArity);
+ void mangleUnscopedName(const NamedDecl *ND);
+ void mangleUnscopedTemplateName(const TemplateDecl *ND);
+ void mangleUnscopedTemplateName(TemplateName);
+ void mangleSourceName(const IdentifierInfo *II);
+ void mangleLocalName(const NamedDecl *ND);
+ void mangleLambda(const CXXRecordDecl *Lambda);
+ void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
+ bool NoFunction=false);
+ void mangleNestedName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void manglePrefix(NestedNameSpecifier *qualifier);
+ void manglePrefix(const DeclContext *DC, bool NoFunction=false);
+ void manglePrefix(QualType type);
+ void mangleTemplatePrefix(const TemplateDecl *ND);
+ void mangleTemplatePrefix(TemplateName Template);
+ void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
+ void mangleQualifiers(Qualifiers Quals);
+ void mangleRefQualifier(RefQualifierKind RefQualifier);
+
+ void mangleObjCMethodName(const ObjCMethodDecl *MD);
+
+ // Declare manglers for every type class.
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T);
+#include "clang/AST/TypeNodes.def"
+
+ void mangleType(const TagType*);
+ void mangleType(TemplateName);
+ void mangleBareFunctionType(const FunctionType *T,
+ bool MangleReturnType);
+ void mangleNeonVectorType(const VectorType *T);
+
+ void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
+ void mangleMemberExpr(const Expr *base, bool isArrow,
+ NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ DeclarationName name,
+ unsigned knownArity);
+ void mangleExpression(const Expr *E, unsigned Arity = UnknownArity);
+ void mangleCXXCtorType(CXXCtorType T);
+ void mangleCXXDtorType(CXXDtorType T);
+
+ void mangleTemplateArgs(const ASTTemplateArgumentListInfo &TemplateArgs);
+ void mangleTemplateArgs(const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs);
+ void mangleTemplateArgs(const TemplateArgumentList &AL);
+ void mangleTemplateArg(TemplateArgument A);
+
+ void mangleTemplateParameter(unsigned Index);
+
+ void mangleFunctionParam(const ParmVarDecl *parm);
+};
+
+}
+
+static bool isInCLinkageSpecification(const Decl *D) {
+ D = D->getCanonicalDecl();
+ for (const DeclContext *DC = getEffectiveDeclContext(D);
+ !DC->isTranslationUnit(); DC = getEffectiveParentContext(DC)) {
+ if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
+ return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
+ }
+
+ return false;
+}
+
+bool ItaniumMangleContext::shouldMangleDeclName(const NamedDecl *D) {
+ // In C, functions with no attributes never need to be mangled. Fastpath them.
+ if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
+ return false;
+
+ // Any decl can be declared with __asm("foo") on it, and this takes precedence
+ // over all other naming in the .o file.
+ if (D->hasAttr<AsmLabelAttr>())
+ return true;
+
+ // Clang's "overloadable" attribute extension to C/C++ implies name mangling
+ // (always) as does passing a C++ member function and a function
+ // whose name is not a simple identifier.
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
+ !FD->getDeclName().isIdentifier()))
+ return true;
+
+ // Otherwise, no mangling is done outside C++ mode.
+ if (!getASTContext().getLangOpts().CPlusPlus)
+ return false;
+
+ // Variables at global scope with non-internal linkage are not mangled
+ if (!FD) {
+ const DeclContext *DC = getEffectiveDeclContext(D);
+ // Check for extern variable declared locally.
+ if (DC->isFunctionOrMethod() && D->hasLinkage())
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = getEffectiveParentContext(DC);
+ if (DC->isTranslationUnit() && D->getLinkage() != InternalLinkage)
+ return false;
+ }
+
+ // Class members are always mangled.
+ if (getEffectiveDeclContext(D)->isRecord())
+ return true;
+
+ // C functions and "main" are not mangled.
+ if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
+ return false;
+
+ return true;
+}
+
+void CXXNameMangler::mangle(const NamedDecl *D, StringRef Prefix) {
+ // Any decl can be declared with __asm("foo") on it, and this takes precedence
+ // over all other naming in the .o file.
+ if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
+ // If we have an asm name, then we use it as the mangling.
+
+ // Adding the prefix can cause problems when one file has a "foo" and
+ // another has a "\01foo". That is known to happen on ELF with the
+ // tricks normally used for producing aliases (PR9177). Fortunately the
+ // llvm mangler on ELF is a nop, so we can just avoid adding the \01
+ // marker. We also avoid adding the marker if this is an alias for an
+ // LLVM intrinsic.
+ StringRef UserLabelPrefix =
+ getASTContext().getTargetInfo().getUserLabelPrefix();
+ if (!UserLabelPrefix.empty() && !ALA->getLabel().startswith("llvm."))
+ Out << '\01'; // LLVM IR Marker for __asm("foo")
+
+ Out << ALA->getLabel();
+ return;
+ }
+
+ // <mangled-name> ::= _Z <encoding>
+ // ::= <data name>
+ // ::= <special-name>
+ Out << Prefix;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ mangleFunctionEncoding(FD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ mangleName(VD);
+ else
+ mangleName(cast<FieldDecl>(D));
+}
+
+void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <encoding> ::= <function name> <bare-function-type>
+ mangleName(FD);
+
+ // Don't mangle in the type if this isn't a decl we should typically mangle.
+ if (!Context.shouldMangleDeclName(FD))
+ return;
+
+ // Whether the mangling of a function type includes the return type depends on
+ // the context and the nature of the function. The rules for deciding whether
+ // the return type is included are:
+ //
+ // 1. Template functions (names or types) have return types encoded, with
+ // the exceptions listed below.
+ // 2. Function types not appearing as part of a function name mangling,
+ // e.g. parameters, pointer types, etc., have return type encoded, with the
+ // exceptions listed below.
+ // 3. Non-template function names do not have return types encoded.
+ //
+ // The exceptions mentioned in (1) and (2) above, for which the return type is
+ // never included, are
+ // 1. Constructors.
+ // 2. Destructors.
+ // 3. Conversion operator functions, e.g. operator int.
+ bool MangleReturnType = false;
+ if (FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate()) {
+ if (!(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) ||
+ isa<CXXConversionDecl>(FD)))
+ MangleReturnType = true;
+
+ // Mangle the type of the primary template.
+ FD = PrimaryTemplate->getTemplatedDecl();
+ }
+
+ mangleBareFunctionType(FD->getType()->getAs<FunctionType>(),
+ MangleReturnType);
+}
+
+static const DeclContext *IgnoreLinkageSpecDecls(const DeclContext *DC) {
+ while (isa<LinkageSpecDecl>(DC)) {
+ DC = getEffectiveParentContext(DC);
+ }
+
+ return DC;
+}
+
+/// isStd - Return whether a given namespace is the 'std' namespace.
+static bool isStd(const NamespaceDecl *NS) {
+ if (!IgnoreLinkageSpecDecls(getEffectiveParentContext(NS))
+ ->isTranslationUnit())
+ return false;
+
+ const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
+ return II && II->isStr("std");
+}
+
+// isStdNamespace - Return whether a given decl context is a toplevel 'std'
+// namespace.
+static bool isStdNamespace(const DeclContext *DC) {
+ if (!DC->isNamespace())
+ return false;
+
+ return isStd(cast<NamespaceDecl>(DC));
+}
+
+static const TemplateDecl *
+isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) {
+ // Check if we have a function template.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
+ if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
+ TemplateArgs = FD->getTemplateSpecializationArgs();
+ return TD;
+ }
+ }
+
+ // Check if we have a class template.
+ if (const ClassTemplateSpecializationDecl *Spec =
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ TemplateArgs = &Spec->getTemplateArgs();
+ return Spec->getSpecializedTemplate();
+ }
+
+ return 0;
+}
+
+static bool isLambda(const NamedDecl *ND) {
+ const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
+ if (!Record)
+ return false;
+
+ return Record->isLambda();
+}
+
+void CXXNameMangler::mangleName(const NamedDecl *ND) {
+ // <name> ::= <nested-name>
+ // ::= <unscoped-name>
+ // ::= <unscoped-template-name> <template-args>
+ // ::= <local-name>
+ //
+ const DeclContext *DC = getEffectiveDeclContext(ND);
+
+ // If this is an extern variable declared locally, the relevant DeclContext
+ // is that of the containing namespace, or the translation unit.
+ // FIXME: This is a hack; extern variables declared locally should have
+ // a proper semantic declaration context!
+ if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND))
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = getEffectiveParentContext(DC);
+ else if (GetLocalClassDecl(ND)) {
+ mangleLocalName(ND);
+ return;
+ }
+
+ DC = IgnoreLinkageSpecDecls(DC);
+
+ if (DC->isTranslationUnit() || isStdNamespace(DC)) {
+ // Check if we have a template.
+ const TemplateArgumentList *TemplateArgs = 0;
+ if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ mangleUnscopedTemplateName(TD);
+ mangleTemplateArgs(*TemplateArgs);
+ return;
+ }
+
+ mangleUnscopedName(ND);
+ return;
+ }
+
+ if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {
+ mangleLocalName(ND);
+ return;
+ }
+
+ mangleNestedName(ND, DC);
+}
+void CXXNameMangler::mangleName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ const DeclContext *DC = IgnoreLinkageSpecDecls(getEffectiveDeclContext(TD));
+
+ if (DC->isTranslationUnit() || isStdNamespace(DC)) {
+ mangleUnscopedTemplateName(TD);
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
+ } else {
+ mangleNestedName(TD, TemplateArgs, NumTemplateArgs);
+ }
+}
+
+void CXXNameMangler::mangleUnscopedName(const NamedDecl *ND) {
+ // <unscoped-name> ::= <unqualified-name>
+ // ::= St <unqualified-name> # ::std::
+
+ if (isStdNamespace(IgnoreLinkageSpecDecls(getEffectiveDeclContext(ND))))
+ Out << "St";
+
+ mangleUnqualifiedName(ND);
+}
+
+void CXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *ND) {
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+ if (mangleSubstitution(ND))
+ return;
+
+ // <template-template-param> ::= <template-param>
+ if (const TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ mangleTemplateParameter(TTP->getIndex());
+ return;
+ }
+
+ mangleUnscopedName(ND->getTemplatedDecl());
+ addSubstitution(ND);
+}
+
+void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
+ // <unscoped-template-name> ::= <unscoped-name>
+ // ::= <substitution>
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleUnscopedTemplateName(TD);
+
+ if (mangleSubstitution(Template))
+ return;
+
+ DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+ assert(Dependent && "Not a dependent template name?");
+ if (const IdentifierInfo *Id = Dependent->getIdentifier())
+ mangleSourceName(Id);
+ else
+ mangleOperatorName(Dependent->getOperator(), UnknownArity);
+
+ addSubstitution(Template);
+}
+
+void CXXNameMangler::mangleFloat(const llvm::APFloat &f) {
+ // ABI:
+ // Floating-point literals are encoded using a fixed-length
+ // lowercase hexadecimal string corresponding to the internal
+ // representation (IEEE on Itanium), high-order bytes first,
+ // without leading zeroes. For example: "Lf bf800000 E" is -1.0f
+ // on Itanium.
+ // The 'without leading zeroes' thing seems to be an editorial
+ // mistake; see the discussion on cxx-abi-dev beginning on
+ // 2012-01-16.
+
+ // Our requirements here are just barely weird enough to justify
+ // using a custom algorithm instead of post-processing APInt::toString().
+
+ llvm::APInt valueBits = f.bitcastToAPInt();
+ unsigned numCharacters = (valueBits.getBitWidth() + 3) / 4;
+ assert(numCharacters != 0);
+
+ // Allocate a buffer of the right number of characters.
+ llvm::SmallVector<char, 20> buffer;
+ buffer.set_size(numCharacters);
+
+ // Fill the buffer left-to-right.
+ for (unsigned stringIndex = 0; stringIndex != numCharacters; ++stringIndex) {
+ // The bit-index of the next hex digit.
+ unsigned digitBitIndex = 4 * (numCharacters - stringIndex - 1);
+
+ // Project out 4 bits starting at 'digitIndex'.
+ llvm::integerPart hexDigit
+ = valueBits.getRawData()[digitBitIndex / llvm::integerPartWidth];
+ hexDigit >>= (digitBitIndex % llvm::integerPartWidth);
+ hexDigit &= 0xF;
+
+ // Map that over to a lowercase hex digit.
+ static const char charForHex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+ };
+ buffer[stringIndex] = charForHex[hexDigit];
+ }
+
+ Out.write(buffer.data(), numCharacters);
+}
+
+void CXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
+ if (Value.isSigned() && Value.isNegative()) {
+ Out << 'n';
+ Value.abs().print(Out, /*signed*/ false);
+ } else {
+ Value.print(Out, /*signed*/ false);
+ }
+}
+
+void CXXNameMangler::mangleNumber(int64_t Number) {
+ // <number> ::= [n] <non-negative decimal integer>
+ if (Number < 0) {
+ Out << 'n';
+ Number = -Number;
+ }
+
+ Out << Number;
+}
+
+void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) {
+ // <call-offset> ::= h <nv-offset> _
+ // ::= v <v-offset> _
+ // <nv-offset> ::= <offset number> # non-virtual base override
+ // <v-offset> ::= <offset number> _ <virtual offset number>
+ // # virtual base override, with vcall offset
+ if (!Virtual) {
+ Out << 'h';
+ mangleNumber(NonVirtual);
+ Out << '_';
+ return;
+ }
+
+ Out << 'v';
+ mangleNumber(NonVirtual);
+ Out << '_';
+ mangleNumber(Virtual);
+ Out << '_';
+}
+
+void CXXNameMangler::manglePrefix(QualType type) {
+ if (const TemplateSpecializationType *TST =
+ type->getAs<TemplateSpecializationType>()) {
+ if (!mangleSubstitution(QualType(TST, 0))) {
+ mangleTemplatePrefix(TST->getTemplateName());
+
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(TST->getArgs(), TST->getNumArgs());
+ addSubstitution(QualType(TST, 0));
+ }
+ } else if (const DependentTemplateSpecializationType *DTST
+ = type->getAs<DependentTemplateSpecializationType>()) {
+ TemplateName Template
+ = getASTContext().getDependentTemplateName(DTST->getQualifier(),
+ DTST->getIdentifier());
+ mangleTemplatePrefix(Template);
+
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(DTST->getArgs(), DTST->getNumArgs());
+ } else {
+ // We use the QualType mangle type variant here because it handles
+ // substitutions.
+ mangleType(type);
+ }
+}
+
+/// Mangle everything prior to the base-unresolved-name in an unresolved-name.
+///
+/// \param firstQualifierLookup - the entity found by unqualified lookup
+/// for the first name in the qualifier, if this is for a member expression
+/// \param recursive - true if this is being called recursively,
+/// i.e. if there is more prefix "to the right".
+void CXXNameMangler::mangleUnresolvedPrefix(NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ bool recursive) {
+
+ // x, ::x
+ // <unresolved-name> ::= [gs] <base-unresolved-name>
+
+ // T::x / decltype(p)::x
+ // <unresolved-name> ::= sr <unresolved-type> <base-unresolved-name>
+
+ // T::N::x /decltype(p)::N::x
+ // <unresolved-name> ::= srN <unresolved-type> <unresolved-qualifier-level>+ E
+ // <base-unresolved-name>
+
+ // A::x, N::y, A<T>::z; "gs" means leading "::"
+ // <unresolved-name> ::= [gs] sr <unresolved-qualifier-level>+ E
+ // <base-unresolved-name>
+
+ switch (qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ Out << "gs";
+
+ // We want an 'sr' unless this is the entire NNS.
+ if (recursive)
+ Out << "sr";
+
+ // We never want an 'E' here.
+ return;
+
+ case NestedNameSpecifier::Namespace:
+ if (qualifier->getPrefix())
+ mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ /*recursive*/ true);
+ else
+ Out << "sr";
+ mangleSourceName(qualifier->getAsNamespace()->getIdentifier());
+ break;
+ case NestedNameSpecifier::NamespaceAlias:
+ if (qualifier->getPrefix())
+ mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ /*recursive*/ true);
+ else
+ Out << "sr";
+ mangleSourceName(qualifier->getAsNamespaceAlias()->getIdentifier());
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate: {
+ const Type *type = qualifier->getAsType();
+
+ // We only want to use an unresolved-type encoding if this is one of:
+ // - a decltype
+ // - a template type parameter
+ // - a template template parameter with arguments
+ // In all of these cases, we should have no prefix.
+ if (qualifier->getPrefix()) {
+ mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ /*recursive*/ true);
+ } else {
+ // Otherwise, all the cases want this.
+ Out << "sr";
+ }
+
+ // Only certain other types are valid as prefixes; enumerate them.
+ switch (type->getTypeClass()) {
+ case Type::Builtin:
+ case Type::Complex:
+ case Type::Pointer:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ case Type::Enum:
+ case Type::Paren:
+ case Type::Elaborated:
+ case Type::Attributed:
+ case Type::Auto:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ case Type::Atomic:
+ llvm_unreachable("type is illegal as a nested name specifier");
+
+ case Type::SubstTemplateTypeParmPack:
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(decltype(T::foo(U())) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+
+ // <unresolved-type> ::= <template-param>
+ // ::= <decltype>
+ // ::= <template-template-param> <template-args>
+ // (this last is not official yet)
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::TemplateTypeParm:
+ case Type::UnaryTransform:
+ case Type::SubstTemplateTypeParm:
+ unresolvedType:
+ assert(!qualifier->getPrefix());
+
+ // We only get here recursively if we're followed by identifiers.
+ if (recursive) Out << 'N';
+
+ // This seems to do everything we want. It's not really
+ // sanctioned for a substituted template parameter, though.
+ mangleType(QualType(type, 0));
+
+ // We never want to print 'E' directly after an unresolved-type,
+ // so we return directly.
+ return;
+
+ case Type::Typedef:
+ mangleSourceName(cast<TypedefType>(type)->getDecl()->getIdentifier());
+ break;
+
+ case Type::UnresolvedUsing:
+ mangleSourceName(cast<UnresolvedUsingType>(type)->getDecl()
+ ->getIdentifier());
+ break;
+
+ case Type::Record:
+ mangleSourceName(cast<RecordType>(type)->getDecl()->getIdentifier());
+ break;
+
+ case Type::TemplateSpecialization: {
+ const TemplateSpecializationType *tst
+ = cast<TemplateSpecializationType>(type);
+ TemplateName name = tst->getTemplateName();
+ switch (name.getKind()) {
+ case TemplateName::Template:
+ case TemplateName::QualifiedTemplate: {
+ TemplateDecl *temp = name.getAsTemplateDecl();
+
+ // If the base is a template template parameter, this is an
+ // unresolved type.
+ assert(temp && "no template for template specialization type");
+ if (isa<TemplateTemplateParmDecl>(temp)) goto unresolvedType;
+
+ mangleSourceName(temp->getIdentifier());
+ break;
+ }
+
+ case TemplateName::OverloadedTemplate:
+ case TemplateName::DependentTemplate:
+ llvm_unreachable("invalid base for a template specialization type");
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ SubstTemplateTemplateParmStorage *subst
+ = name.getAsSubstTemplateTemplateParm();
+ mangleExistingSubstitution(subst->getReplacement());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ // FIXME: not clear how to mangle this!
+ // template <template <class U> class T...> class A {
+ // template <class U...> void foo(decltype(T<U>::foo) x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+ }
+ }
+
+ mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
+ break;
+ }
+
+ case Type::InjectedClassName:
+ mangleSourceName(cast<InjectedClassNameType>(type)->getDecl()
+ ->getIdentifier());
+ break;
+
+ case Type::DependentName:
+ mangleSourceName(cast<DependentNameType>(type)->getIdentifier());
+ break;
+
+ case Type::DependentTemplateSpecialization: {
+ const DependentTemplateSpecializationType *tst
+ = cast<DependentTemplateSpecializationType>(type);
+ mangleSourceName(tst->getIdentifier());
+ mangleTemplateArgs(tst->getArgs(), tst->getNumArgs());
+ break;
+ }
+ }
+ break;
+ }
+
+ case NestedNameSpecifier::Identifier:
+ // Member expressions can have these without prefixes.
+ if (qualifier->getPrefix()) {
+ mangleUnresolvedPrefix(qualifier->getPrefix(), firstQualifierLookup,
+ /*recursive*/ true);
+ } else if (firstQualifierLookup) {
+
+ // Try to make a proper qualifier out of the lookup result, and
+ // then just recurse on that.
+ NestedNameSpecifier *newQualifier;
+ if (TypeDecl *typeDecl = dyn_cast<TypeDecl>(firstQualifierLookup)) {
+ QualType type = getASTContext().getTypeDeclType(typeDecl);
+
+ // Pretend we had a different nested name specifier.
+ newQualifier = NestedNameSpecifier::Create(getASTContext(),
+ /*prefix*/ 0,
+ /*template*/ false,
+ type.getTypePtr());
+ } else if (NamespaceDecl *nspace =
+ dyn_cast<NamespaceDecl>(firstQualifierLookup)) {
+ newQualifier = NestedNameSpecifier::Create(getASTContext(),
+ /*prefix*/ 0,
+ nspace);
+ } else if (NamespaceAliasDecl *alias =
+ dyn_cast<NamespaceAliasDecl>(firstQualifierLookup)) {
+ newQualifier = NestedNameSpecifier::Create(getASTContext(),
+ /*prefix*/ 0,
+ alias);
+ } else {
+ // No sensible mangling to do here.
+ newQualifier = 0;
+ }
+
+ if (newQualifier)
+ return mangleUnresolvedPrefix(newQualifier, /*lookup*/ 0, recursive);
+
+ } else {
+ Out << "sr";
+ }
+
+ mangleSourceName(qualifier->getAsIdentifier());
+ break;
+ }
+
+ // If this was the innermost part of the NNS, and we fell out to
+ // here, append an 'E'.
+ if (!recursive)
+ Out << 'E';
+}
+
+/// Mangle an unresolved-name, which is generally used for names which
+/// weren't resolved to specific entities.
+void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ DeclarationName name,
+ unsigned knownArity) {
+ if (qualifier) mangleUnresolvedPrefix(qualifier, firstQualifierLookup);
+ mangleUnqualifiedName(0, name, knownArity);
+}
+
+static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
+ assert(RD->isAnonymousStructOrUnion() &&
+ "Expected anonymous struct or union!");
+
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I) {
+ if (I->getIdentifier())
+ return *I;
+
+ if (const RecordType *RT = I->getType()->getAs<RecordType>())
+ if (const FieldDecl *NamedDataMember =
+ FindFirstNamedDataMember(RT->getDecl()))
+ return NamedDataMember;
+ }
+
+ // We didn't find a named data member.
+ return 0;
+}
+
+void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+ DeclarationName Name,
+ unsigned KnownArity) {
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier: {
+ if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ // We must avoid conflicts between internally- and externally-
+ // linked variable and function declaration names in the same TU:
+ // void test() { extern void foo(); }
+ // static void foo();
+ // This naming convention is the same as that followed by GCC,
+ // though it shouldn't actually matter.
+ if (ND && ND->getLinkage() == InternalLinkage &&
+ getEffectiveDeclContext(ND)->isFileContext())
+ Out << 'L';
+
+ mangleSourceName(II);
+ break;
+ }
+
+ // Otherwise, an anonymous entity. We must have a declaration.
+ assert(ND && "mangling empty name without declaration");
+
+ if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
+ if (NS->isAnonymousNamespace()) {
+ // This is how gcc mangles these names.
+ Out << "12_GLOBAL__N_1";
+ break;
+ }
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ // We must have an anonymous union or struct declaration.
+ const RecordDecl *RD =
+ cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
+
+ // Itanium C++ ABI 5.1.2:
+ //
+ // For the purposes of mangling, the name of an anonymous union is
+ // considered to be the name of the first named data member found by a
+ // pre-order, depth-first, declaration-order walk of the data members of
+ // the anonymous union. If there is no such data member (i.e., if all of
+ // the data members in the union are unnamed), then there is no way for
+ // a program to refer to the anonymous union, and there is therefore no
+ // need to mangle its name.
+ const FieldDecl *FD = FindFirstNamedDataMember(RD);
+
+ // It's actually possible for various reasons for us to get here
+ // with an empty anonymous struct / union. Fortunately, it
+ // doesn't really matter what name we generate.
+ if (!FD) break;
+ assert(FD->getIdentifier() && "Data member name isn't an identifier!");
+
+ mangleSourceName(FD->getIdentifier());
+ break;
+ }
+
+ // We must have an anonymous struct.
+ const TagDecl *TD = cast<TagDecl>(ND);
+ if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
+ assert(TD->getDeclContext() == D->getDeclContext() &&
+ "Typedef should not be in another decl context!");
+ assert(D->getDeclName().getAsIdentifierInfo() &&
+ "Typedef was not named!");
+ mangleSourceName(D->getDeclName().getAsIdentifierInfo());
+ break;
+ }
+
+ // <unnamed-type-name> ::= <closure-type-name>
+ //
+ // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
+ // <lambda-sig> ::= <parameter-type>+ # Parameter types or 'v' for 'void'.
+ if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
+ if (Record->isLambda() && Record->getLambdaManglingNumber()) {
+ mangleLambda(Record);
+ break;
+ }
+ }
+
+ int UnnamedMangle = Context.getASTContext().getUnnamedTagManglingNumber(TD);
+ if (UnnamedMangle != -1) {
+ Out << "Ut";
+ if (UnnamedMangle != 0)
+ Out << llvm::utostr(UnnamedMangle - 1);
+ Out << '_';
+ break;
+ }
+
+ // Get a unique id for the anonymous struct.
+ uint64_t AnonStructId = Context.getAnonymousStructId(TD);
+
+ // Mangle it as a source name in the form
+ // [n] $_<id>
+ // where n is the length of the string.
+ SmallString<8> Str;
+ Str += "$_";
+ Str += llvm::utostr(AnonStructId);
+
+ Out << Str.size();
+ Out << Str.str();
+ break;
+ }
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
+
+ case DeclarationName::CXXConstructorName:
+ if (ND == Structor)
+ // If the named decl is the C++ constructor we're mangling, use the type
+ // we were given.
+ mangleCXXCtorType(static_cast<CXXCtorType>(StructorType));
+ else
+ // Otherwise, use the complete constructor name. This is relevant if a
+ // class with a constructor is declared within a constructor.
+ mangleCXXCtorType(Ctor_Complete);
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ if (ND == Structor)
+ // If the named decl is the C++ destructor we're mangling, use the type we
+ // were given.
+ mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
+ else
+ // Otherwise, use the complete destructor name. This is relevant if a
+ // class with a destructor is declared within a destructor.
+ mangleCXXDtorType(Dtor_Complete);
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= cv <type> # (cast)
+ Out << "cv";
+ mangleType(Name.getCXXNameType());
+ break;
+
+ case DeclarationName::CXXOperatorName: {
+ unsigned Arity;
+ if (ND) {
+ Arity = cast<FunctionDecl>(ND)->getNumParams();
+
+ // If we have a C++ member function, we need to include the 'this' pointer.
+ // FIXME: This does not make sense for operators that are static, but their
+ // names stay the same regardless of the arity (operator new for instance).
+ if (isa<CXXMethodDecl>(ND))
+ Arity++;
+ } else
+ Arity = KnownArity;
+
+ mangleOperatorName(Name.getCXXOverloadedOperator(), Arity);
+ break;
+ }
+
+ case DeclarationName::CXXLiteralOperatorName:
+ // FIXME: This mangling is not yet official.
+ Out << "li";
+ mangleSourceName(Name.getCXXLiteralIdentifier());
+ break;
+
+ case DeclarationName::CXXUsingDirective:
+ llvm_unreachable("Can't mangle a using directive name!");
+ }
+}
+
+void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+ // <source-name> ::= <positive length number> <identifier>
+ // <number> ::= [n] <non-negative decimal integer>
+ // <identifier> ::= <unqualified source code identifier>
+ Out << II->getLength() << II->getName();
+}
+
+void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
+ const DeclContext *DC,
+ bool NoFunction) {
+ // <nested-name>
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+ // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
+ // <template-args> E
+
+ Out << 'N';
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
+ mangleQualifiers(Qualifiers::fromCVRMask(Method->getTypeQualifiers()));
+ mangleRefQualifier(Method->getRefQualifier());
+ }
+
+ // Check if we have a template.
+ const TemplateArgumentList *TemplateArgs = 0;
+ if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ mangleTemplatePrefix(TD);
+ mangleTemplateArgs(*TemplateArgs);
+ }
+ else {
+ manglePrefix(DC, NoFunction);
+ mangleUnqualifiedName(ND);
+ }
+
+ Out << 'E';
+}
+void CXXNameMangler::mangleNestedName(const TemplateDecl *TD,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ // <nested-name> ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+
+ Out << 'N';
+
+ mangleTemplatePrefix(TD);
+ mangleTemplateArgs(TemplateArgs, NumTemplateArgs);
+
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
+ // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
+ // := Z <function encoding> E s [<discriminator>]
+ // <local-name> := Z <function encoding> E d [ <parameter number> ]
+ // _ <entity name>
+ // <discriminator> := _ <non-negative number>
+ const DeclContext *DC = getEffectiveDeclContext(ND);
+ if (isa<ObjCMethodDecl>(DC) && isa<FunctionDecl>(ND)) {
+ // Don't add objc method name mangling to locally declared function
+ mangleUnqualifiedName(ND);
+ return;
+ }
+
+ Out << 'Z';
+
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC)) {
+ mangleObjCMethodName(MD);
+ } else if (const CXXRecordDecl *RD = GetLocalClassDecl(ND)) {
+ mangleFunctionEncoding(cast<FunctionDecl>(getEffectiveDeclContext(RD)));
+ Out << 'E';
+
+ // The parameter number is omitted for the last parameter, 0 for the
+ // second-to-last parameter, 1 for the third-to-last parameter, etc. The
+ // <entity name> will of course contain a <closure-type-name>: Its
+ // numbering will be local to the particular argument in which it appears
+ // -- other default arguments do not affect its encoding.
+ bool SkipDiscriminator = false;
+ if (RD->isLambda()) {
+ if (const ParmVarDecl *Parm
+ = dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl())) {
+ if (const FunctionDecl *Func
+ = dyn_cast<FunctionDecl>(Parm->getDeclContext())) {
+ Out << 'd';
+ unsigned Num = Func->getNumParams() - Parm->getFunctionScopeIndex();
+ if (Num > 1)
+ mangleNumber(Num - 2);
+ Out << '_';
+ SkipDiscriminator = true;
+ }
+ }
+ }
+
+ // Mangle the name relative to the closest enclosing function.
+ if (ND == RD) // equality ok because RD derived from ND above
+ mangleUnqualifiedName(ND);
+ else
+ mangleNestedName(ND, DC, true /*NoFunction*/);
+
+ if (!SkipDiscriminator) {
+ unsigned disc;
+ if (Context.getNextDiscriminator(RD, disc)) {
+ if (disc < 10)
+ Out << '_' << disc;
+ else
+ Out << "__" << disc << '_';
+ }
+ }
+
+ return;
+ }
+ else
+ mangleFunctionEncoding(cast<FunctionDecl>(DC));
+
+ Out << 'E';
+ mangleUnqualifiedName(ND);
+}
+
+void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
+ // If the context of a closure type is an initializer for a class member
+ // (static or nonstatic), it is encoded in a qualified name with a final
+ // <prefix> of the form:
+ //
+ // <data-member-prefix> := <member source-name> M
+ //
+ // Technically, the data-member-prefix is part of the <prefix>. However,
+ // since a closure type will always be mangled with a prefix, it's easier
+ // to emit that last part of the prefix here.
+ if (Decl *Context = Lambda->getLambdaContextDecl()) {
+ if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
+ Context->getDeclContext()->isRecord()) {
+ if (const IdentifierInfo *Name
+ = cast<NamedDecl>(Context)->getIdentifier()) {
+ mangleSourceName(Name);
+ Out << 'M';
+ }
+ }
+ }
+
+ Out << "Ul";
+ const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
+ getAs<FunctionProtoType>();
+ mangleBareFunctionType(Proto, /*MangleReturnType=*/false);
+ Out << "E";
+
+ // The number is omitted for the first closure type with a given
+ // <lambda-sig> in a given context; it is n-2 for the nth closure type
+ // (in lexical order) with that same <lambda-sig> and context.
+ //
+ // The AST keeps track of the number for us.
+ unsigned Number = Lambda->getLambdaManglingNumber();
+ assert(Number > 0 && "Lambda should be mangled as an unnamed class");
+ if (Number > 1)
+ mangleNumber(Number - 2);
+ Out << '_';
+}
+
+void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
+ switch (qualifier->getKind()) {
+ case NestedNameSpecifier::Global:
+ // nothing
+ return;
+
+ case NestedNameSpecifier::Namespace:
+ mangleName(qualifier->getAsNamespace());
+ return;
+
+ case NestedNameSpecifier::NamespaceAlias:
+ mangleName(qualifier->getAsNamespaceAlias()->getNamespace());
+ return;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ manglePrefix(QualType(qualifier->getAsType(), 0));
+ return;
+
+ case NestedNameSpecifier::Identifier:
+ // Member expressions can have these without prefixes, but that
+ // should end up in mangleUnresolvedPrefix instead.
+ assert(qualifier->getPrefix());
+ manglePrefix(qualifier->getPrefix());
+
+ mangleSourceName(qualifier->getAsIdentifier());
+ return;
+ }
+
+ llvm_unreachable("unexpected nested name specifier");
+}
+
+void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
+ // <prefix> ::= <prefix> <unqualified-name>
+ // ::= <template-prefix> <template-args>
+ // ::= <template-param>
+ // ::= # empty
+ // ::= <substitution>
+
+ DC = IgnoreLinkageSpecDecls(DC);
+
+ if (DC->isTranslationUnit())
+ return;
+
+ if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
+ manglePrefix(getEffectiveParentContext(DC), NoFunction);
+ SmallString<64> Name;
+ llvm::raw_svector_ostream NameStream(Name);
+ Context.mangleBlock(Block, NameStream);
+ NameStream.flush();
+ Out << Name.size() << Name;
+ return;
+ }
+
+ const NamedDecl *ND = cast<NamedDecl>(DC);
+ if (mangleSubstitution(ND))
+ return;
+
+ // Check if we have a template.
+ const TemplateArgumentList *TemplateArgs = 0;
+ if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ mangleTemplatePrefix(TD);
+ mangleTemplateArgs(*TemplateArgs);
+ }
+ else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
+ return;
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
+ mangleObjCMethodName(Method);
+ else {
+ manglePrefix(getEffectiveDeclContext(ND), NoFunction);
+ mangleUnqualifiedName(ND);
+ }
+
+ addSubstitution(ND);
+}
+
+void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) {
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleTemplatePrefix(TD);
+
+ if (QualifiedTemplateName *Qualified = Template.getAsQualifiedTemplateName())
+ manglePrefix(Qualified->getQualifier());
+
+ if (OverloadedTemplateStorage *Overloaded
+ = Template.getAsOverloadedTemplate()) {
+ mangleUnqualifiedName(0, (*Overloaded->begin())->getDeclName(),
+ UnknownArity);
+ return;
+ }
+
+ DependentTemplateName *Dependent = Template.getAsDependentTemplateName();
+ assert(Dependent && "Unknown template name kind?");
+ manglePrefix(Dependent->getQualifier());
+ mangleUnscopedTemplateName(Template);
+}
+
+void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND) {
+ // <template-prefix> ::= <prefix> <template unqualified-name>
+ // ::= <template-param>
+ // ::= <substitution>
+ // <template-template-param> ::= <template-param>
+ // <substitution>
+
+ if (mangleSubstitution(ND))
+ return;
+
+ // <template-template-param> ::= <template-param>
+ if (const TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(ND)) {
+ mangleTemplateParameter(TTP->getIndex());
+ return;
+ }
+
+ manglePrefix(getEffectiveDeclContext(ND));
+ mangleUnqualifiedName(ND->getTemplatedDecl());
+ addSubstitution(ND);
+}
+
+/// Mangles a template name under the production <type>. Required for
+/// template template arguments.
+/// <type> ::= <class-enum-type>
+/// ::= <template-param>
+/// ::= <substitution>
+void CXXNameMangler::mangleType(TemplateName TN) {
+ if (mangleSubstitution(TN))
+ return;
+
+ TemplateDecl *TD = 0;
+
+ switch (TN.getKind()) {
+ case TemplateName::QualifiedTemplate:
+ TD = TN.getAsQualifiedTemplateName()->getTemplateDecl();
+ goto HaveDecl;
+
+ case TemplateName::Template:
+ TD = TN.getAsTemplateDecl();
+ goto HaveDecl;
+
+ HaveDecl:
+ if (isa<TemplateTemplateParmDecl>(TD))
+ mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());
+ else
+ mangleName(TD);
+ break;
+
+ case TemplateName::OverloadedTemplate:
+ llvm_unreachable("can't mangle an overloaded template name as a <type>");
+
+ case TemplateName::DependentTemplate: {
+ const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
+ assert(Dependent->isIdentifier());
+
+ // <class-enum-type> ::= <name>
+ // <name> ::= <nested-name>
+ mangleUnresolvedPrefix(Dependent->getQualifier(), 0);
+ mangleSourceName(Dependent->getIdentifier());
+ break;
+ }
+
+ case TemplateName::SubstTemplateTemplateParm: {
+ // Substituted template parameters are mangled as the substituted
+ // template. This will check for the substitution twice, which is
+ // fine, but we have to return early so that we don't try to *add*
+ // the substitution twice.
+ SubstTemplateTemplateParmStorage *subst
+ = TN.getAsSubstTemplateTemplateParm();
+ mangleType(subst->getReplacement());
+ return;
+ }
+
+ case TemplateName::SubstTemplateTemplateParmPack: {
+ // FIXME: not clear how to mangle this!
+ // template <template <class> class T...> class A {
+ // template <template <class> class U...> void foo(B<T,U> x...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+ }
+ }
+
+ addSubstitution(TN);
+}
+
+void
+CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
+ switch (OO) {
+ // <operator-name> ::= nw # new
+ case OO_New: Out << "nw"; break;
+ // ::= na # new[]
+ case OO_Array_New: Out << "na"; break;
+ // ::= dl # delete
+ case OO_Delete: Out << "dl"; break;
+ // ::= da # delete[]
+ case OO_Array_Delete: Out << "da"; break;
+ // ::= ps # + (unary)
+ // ::= pl # + (binary or unknown)
+ case OO_Plus:
+ Out << (Arity == 1? "ps" : "pl"); break;
+ // ::= ng # - (unary)
+ // ::= mi # - (binary or unknown)
+ case OO_Minus:
+ Out << (Arity == 1? "ng" : "mi"); break;
+ // ::= ad # & (unary)
+ // ::= an # & (binary or unknown)
+ case OO_Amp:
+ Out << (Arity == 1? "ad" : "an"); break;
+ // ::= de # * (unary)
+ // ::= ml # * (binary or unknown)
+ case OO_Star:
+ // Use binary when unknown.
+ Out << (Arity == 1? "de" : "ml"); break;
+ // ::= co # ~
+ case OO_Tilde: Out << "co"; break;
+ // ::= dv # /
+ case OO_Slash: Out << "dv"; break;
+ // ::= rm # %
+ case OO_Percent: Out << "rm"; break;
+ // ::= or # |
+ case OO_Pipe: Out << "or"; break;
+ // ::= eo # ^
+ case OO_Caret: Out << "eo"; break;
+ // ::= aS # =
+ case OO_Equal: Out << "aS"; break;
+ // ::= pL # +=
+ case OO_PlusEqual: Out << "pL"; break;
+ // ::= mI # -=
+ case OO_MinusEqual: Out << "mI"; break;
+ // ::= mL # *=
+ case OO_StarEqual: Out << "mL"; break;
+ // ::= dV # /=
+ case OO_SlashEqual: Out << "dV"; break;
+ // ::= rM # %=
+ case OO_PercentEqual: Out << "rM"; break;
+ // ::= aN # &=
+ case OO_AmpEqual: Out << "aN"; break;
+ // ::= oR # |=
+ case OO_PipeEqual: Out << "oR"; break;
+ // ::= eO # ^=
+ case OO_CaretEqual: Out << "eO"; break;
+ // ::= ls # <<
+ case OO_LessLess: Out << "ls"; break;
+ // ::= rs # >>
+ case OO_GreaterGreater: Out << "rs"; break;
+ // ::= lS # <<=
+ case OO_LessLessEqual: Out << "lS"; break;
+ // ::= rS # >>=
+ case OO_GreaterGreaterEqual: Out << "rS"; break;
+ // ::= eq # ==
+ case OO_EqualEqual: Out << "eq"; break;
+ // ::= ne # !=
+ case OO_ExclaimEqual: Out << "ne"; break;
+ // ::= lt # <
+ case OO_Less: Out << "lt"; break;
+ // ::= gt # >
+ case OO_Greater: Out << "gt"; break;
+ // ::= le # <=
+ case OO_LessEqual: Out << "le"; break;
+ // ::= ge # >=
+ case OO_GreaterEqual: Out << "ge"; break;
+ // ::= nt # !
+ case OO_Exclaim: Out << "nt"; break;
+ // ::= aa # &&
+ case OO_AmpAmp: Out << "aa"; break;
+ // ::= oo # ||
+ case OO_PipePipe: Out << "oo"; break;
+ // ::= pp # ++
+ case OO_PlusPlus: Out << "pp"; break;
+ // ::= mm # --
+ case OO_MinusMinus: Out << "mm"; break;
+ // ::= cm # ,
+ case OO_Comma: Out << "cm"; break;
+ // ::= pm # ->*
+ case OO_ArrowStar: Out << "pm"; break;
+ // ::= pt # ->
+ case OO_Arrow: Out << "pt"; break;
+ // ::= cl # ()
+ case OO_Call: Out << "cl"; break;
+ // ::= ix # []
+ case OO_Subscript: Out << "ix"; break;
+
+ // ::= qu # ?
+ // The conditional operator can't be overloaded, but we still handle it when
+ // mangling expressions.
+ case OO_Conditional: Out << "qu"; break;
+
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("Not an overloaded operator");
+ }
+}
+
+void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
+ // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
+ if (Quals.hasRestrict())
+ Out << 'r';
+ if (Quals.hasVolatile())
+ Out << 'V';
+ if (Quals.hasConst())
+ Out << 'K';
+
+ if (Quals.hasAddressSpace()) {
+ // Extension:
+ //
+ // <type> ::= U <address-space-number>
+ //
+ // where <address-space-number> is a source name consisting of 'AS'
+ // followed by the address space <number>.
+ SmallString<64> ASString;
+ ASString = "AS" + llvm::utostr_32(Quals.getAddressSpace());
+ Out << 'U' << ASString.size() << ASString;
+ }
+
+ StringRef LifetimeName;
+ switch (Quals.getObjCLifetime()) {
+ // Objective-C ARC Extension:
+ //
+ // <type> ::= U "__strong"
+ // <type> ::= U "__weak"
+ // <type> ::= U "__autoreleasing"
+ case Qualifiers::OCL_None:
+ break;
+
+ case Qualifiers::OCL_Weak:
+ LifetimeName = "__weak";
+ break;
+
+ case Qualifiers::OCL_Strong:
+ LifetimeName = "__strong";
+ break;
+
+ case Qualifiers::OCL_Autoreleasing:
+ LifetimeName = "__autoreleasing";
+ break;
+
+ case Qualifiers::OCL_ExplicitNone:
+ // The __unsafe_unretained qualifier is *not* mangled, so that
+ // __unsafe_unretained types in ARC produce the same manglings as the
+ // equivalent (but, naturally, unqualified) types in non-ARC, providing
+ // better ABI compatibility.
+ //
+ // It's safe to do this because unqualified 'id' won't show up
+ // in any type signatures that need to be mangled.
+ break;
+ }
+ if (!LifetimeName.empty())
+ Out << 'U' << LifetimeName.size() << LifetimeName;
+}
+
+void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
+ // <ref-qualifier> ::= R # lvalue reference
+ // ::= O # rvalue-reference
+ // Proposal to Itanium C++ ABI list on 1/26/11
+ switch (RefQualifier) {
+ case RQ_None:
+ break;
+
+ case RQ_LValue:
+ Out << 'R';
+ break;
+
+ case RQ_RValue:
+ Out << 'O';
+ break;
+ }
+}
+
+void CXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
+ Context.mangleObjCMethodName(MD, Out);
+}
+
+void CXXNameMangler::mangleType(QualType T) {
+ // If our type is instantiation-dependent but not dependent, we mangle
+ // it as it was written in the source, removing any top-level sugar.
+ // Otherwise, use the canonical type.
+ //
+ // FIXME: This is an approximation of the instantiation-dependent name
+ // mangling rules, since we should really be using the type as written and
+ // augmented via semantic analysis (i.e., with implicit conversions and
+ // default template arguments) for any instantiation-dependent type.
+ // Unfortunately, that requires several changes to our AST:
+ // - Instantiation-dependent TemplateSpecializationTypes will need to be
+ // uniqued, so that we can handle substitutions properly
+ // - Default template arguments will need to be represented in the
+ // TemplateSpecializationType, since they need to be mangled even though
+ // they aren't written.
+ // - Conversions on non-type template arguments need to be expressed, since
+ // they can affect the mangling of sizeof/alignof.
+ if (!T->isInstantiationDependentType() || T->isDependentType())
+ T = T.getCanonicalType();
+ else {
+ // Desugar any types that are purely sugar.
+ do {
+ // Don't desugar through template specialization types that aren't
+ // type aliases. We need to mangle the template arguments as written.
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ if (!TST->isTypeAlias())
+ break;
+
+ QualType Desugared
+ = T.getSingleStepDesugaredType(Context.getASTContext());
+ if (Desugared == T)
+ break;
+
+ T = Desugared;
+ } while (true);
+ }
+ SplitQualType split = T.split();
+ Qualifiers quals = split.Quals;
+ const Type *ty = split.Ty;
+
+ bool isSubstitutable = quals || !isa<BuiltinType>(T);
+ if (isSubstitutable && mangleSubstitution(T))
+ return;
+
+ // If we're mangling a qualified array type, push the qualifiers to
+ // the element type.
+ if (quals && isa<ArrayType>(T)) {
+ ty = Context.getASTContext().getAsArrayType(T);
+ quals = Qualifiers();
+
+ // Note that we don't update T: we want to add the
+ // substitution at the original type.
+ }
+
+ if (quals) {
+ mangleQualifiers(quals);
+ // Recurse: even if the qualified type isn't yet substitutable,
+ // the unqualified type might be.
+ mangleType(QualType(ty, 0));
+ } else {
+ switch (ty->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
+ return;
+#define TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ mangleType(static_cast<const CLASS##Type*>(ty)); \
+ break;
+#include "clang/AST/TypeNodes.def"
+ }
+ }
+
+ // Add the substitution.
+ if (isSubstitutable)
+ addSubstitution(T);
+}
+
+void CXXNameMangler::mangleNameOrStandardSubstitution(const NamedDecl *ND) {
+ if (!mangleStandardSubstitution(ND))
+ mangleName(ND);
+}
+
+void CXXNameMangler::mangleType(const BuiltinType *T) {
+ // <type> ::= <builtin-type>
+ // <builtin-type> ::= v # void
+ // ::= w # wchar_t
+ // ::= b # bool
+ // ::= c # char
+ // ::= a # signed char
+ // ::= h # unsigned char
+ // ::= s # short
+ // ::= t # unsigned short
+ // ::= i # int
+ // ::= j # unsigned int
+ // ::= l # long
+ // ::= m # unsigned long
+ // ::= x # long long, __int64
+ // ::= y # unsigned long long, __int64
+ // ::= n # __int128
+ // UNSUPPORTED: ::= o # unsigned __int128
+ // ::= f # float
+ // ::= d # double
+ // ::= e # long double, __float80
+ // UNSUPPORTED: ::= g # __float128
+ // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
+ // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
+ // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
+ // ::= Dh # IEEE 754r half-precision floating point (16 bits)
+ // ::= Di # char32_t
+ // ::= Ds # char16_t
+ // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
+ // ::= u <source-name> # vendor extended type
+ switch (T->getKind()) {
+ case BuiltinType::Void: Out << 'v'; break;
+ case BuiltinType::Bool: Out << 'b'; break;
+ case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
+ case BuiltinType::UChar: Out << 'h'; break;
+ case BuiltinType::UShort: Out << 't'; break;
+ case BuiltinType::UInt: Out << 'j'; break;
+ case BuiltinType::ULong: Out << 'm'; break;
+ case BuiltinType::ULongLong: Out << 'y'; break;
+ case BuiltinType::UInt128: Out << 'o'; break;
+ case BuiltinType::SChar: Out << 'a'; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: Out << 'w'; break;
+ case BuiltinType::Char16: Out << "Ds"; break;
+ case BuiltinType::Char32: Out << "Di"; break;
+ case BuiltinType::Short: Out << 's'; break;
+ case BuiltinType::Int: Out << 'i'; break;
+ case BuiltinType::Long: Out << 'l'; break;
+ case BuiltinType::LongLong: Out << 'x'; break;
+ case BuiltinType::Int128: Out << 'n'; break;
+ case BuiltinType::Half: Out << "Dh"; break;
+ case BuiltinType::Float: Out << 'f'; break;
+ case BuiltinType::Double: Out << 'd'; break;
+ case BuiltinType::LongDouble: Out << 'e'; break;
+ case BuiltinType::NullPtr: Out << "Dn"; break;
+
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) \
+ case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ case BuiltinType::Dependent:
+ llvm_unreachable("mangling a placeholder type");
+ case BuiltinType::ObjCId: Out << "11objc_object"; break;
+ case BuiltinType::ObjCClass: Out << "10objc_class"; break;
+ case BuiltinType::ObjCSel: Out << "13objc_selector"; break;
+ }
+}
+
+// <type> ::= <function-type>
+// <function-type> ::= [<CV-qualifiers>] F [Y]
+// <bare-function-type> [<ref-qualifier>] E
+// (Proposal to cxx-abi-dev, 2012-05-11)
+void CXXNameMangler::mangleType(const FunctionProtoType *T) {
+ // Mangle CV-qualifiers, if present. These are 'this' qualifiers,
+ // e.g. "const" in "int (A::*)() const".
+ mangleQualifiers(Qualifiers::fromCVRMask(T->getTypeQuals()));
+
+ Out << 'F';
+
+ // FIXME: We don't have enough information in the AST to produce the 'Y'
+ // encoding for extern "C" function types.
+ mangleBareFunctionType(T, /*MangleReturnType=*/true);
+
+ // Mangle the ref-qualifier, if present.
+ mangleRefQualifier(T->getRefQualifier());
+
+ Out << 'E';
+}
+void CXXNameMangler::mangleType(const FunctionNoProtoType *T) {
+ llvm_unreachable("Can't mangle K&R function prototypes");
+}
+void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
+ bool MangleReturnType) {
+ // We should never be mangling something without a prototype.
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
+ // Record that we're in a function type. See mangleFunctionParam
+ // for details on what we're trying to achieve here.
+ FunctionTypeDepthState saved = FunctionTypeDepth.push();
+
+ // <bare-function-type> ::= <signature type>+
+ if (MangleReturnType) {
+ FunctionTypeDepth.enterResultType();
+ mangleType(Proto->getResultType());
+ FunctionTypeDepth.leaveResultType();
+ }
+
+ if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ // <builtin-type> ::= v # void
+ Out << 'v';
+
+ FunctionTypeDepth.pop(saved);
+ return;
+ }
+
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleType(Context.getASTContext().getSignatureParameterType(*Arg));
+
+ FunctionTypeDepth.pop(saved);
+
+ // <builtin-type> ::= z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'z';
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <class-enum-type>
+// <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const EnumType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void CXXNameMangler::mangleType(const RecordType *T) {
+ mangleType(static_cast<const TagType*>(T));
+}
+void CXXNameMangler::mangleType(const TagType *T) {
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <array-type>
+// <array-type> ::= A <positive dimension number> _ <element type>
+// ::= A [<dimension expression>] _ <element type>
+void CXXNameMangler::mangleType(const ConstantArrayType *T) {
+ Out << 'A' << T->getSize() << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const VariableArrayType *T) {
+ Out << 'A';
+ // decayed vla types (size 0) will just be skipped.
+ if (T->getSizeExpr())
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const DependentSizedArrayType *T) {
+ Out << 'A';
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const IncompleteArrayType *T) {
+ Out << "A_";
+ mangleType(T->getElementType());
+}
+
+// <type> ::= <pointer-to-member-type>
+// <pointer-to-member-type> ::= M <class type> <member type>
+void CXXNameMangler::mangleType(const MemberPointerType *T) {
+ Out << 'M';
+ mangleType(QualType(T->getClass(), 0));
+ QualType PointeeType = T->getPointeeType();
+ if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(PointeeType)) {
+ mangleType(FPT);
+
+ // Itanium C++ ABI 5.1.8:
+ //
+ // The type of a non-static member function is considered to be different,
+ // for the purposes of substitution, from the type of a namespace-scope or
+ // static member function whose type appears similar. The types of two
+ // non-static member functions are considered to be different, for the
+ // purposes of substitution, if the functions are members of different
+ // classes. In other words, for the purposes of substitution, the class of
+ // which the function is a member is considered part of the type of
+ // function.
+
+ // Given that we already substitute member function pointers as a
+ // whole, the net effect of this rule is just to unconditionally
+ // suppress substitution on the function type in a member pointer.
+ // We increment the SeqID here to emulate adding an entry to the
+ // substitution table.
+ ++SeqID;
+ } else
+ mangleType(PointeeType);
+}
+
+// <type> ::= <template-param>
+void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
+ mangleTemplateParameter(T->getIndex());
+}
+
+// <type> ::= <template-param>
+void CXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T) {
+ // FIXME: not clear how to mangle this!
+ // template <class T...> class A {
+ // template <class U...> void foo(T(*)(U) x...);
+ // };
+ Out << "_SUBSTPACK_";
+}
+
+// <type> ::= P <type> # pointer-to
+void CXXNameMangler::mangleType(const PointerType *T) {
+ Out << 'P';
+ mangleType(T->getPointeeType());
+}
+void CXXNameMangler::mangleType(const ObjCObjectPointerType *T) {
+ Out << 'P';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= R <type> # reference-to
+void CXXNameMangler::mangleType(const LValueReferenceType *T) {
+ Out << 'R';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= O <type> # rvalue reference-to (C++0x)
+void CXXNameMangler::mangleType(const RValueReferenceType *T) {
+ Out << 'O';
+ mangleType(T->getPointeeType());
+}
+
+// <type> ::= C <type> # complex pair (C 2000)
+void CXXNameMangler::mangleType(const ComplexType *T) {
+ Out << 'C';
+ mangleType(T->getElementType());
+}
+
+// ARM's ABI for Neon vector types specifies that they should be mangled as
+// if they are structs (to match ARM's initial implementation). The
+// vector type must be one of the special types predefined by ARM.
+void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
+ QualType EltType = T->getElementType();
+ assert(EltType->isBuiltinType() && "Neon vector element not a BuiltinType");
+ const char *EltName = 0;
+ if (T->getVectorKind() == VectorType::NeonPolyVector) {
+ switch (cast<BuiltinType>(EltType)->getKind()) {
+ case BuiltinType::SChar: EltName = "poly8_t"; break;
+ case BuiltinType::Short: EltName = "poly16_t"; break;
+ default: llvm_unreachable("unexpected Neon polynomial vector element type");
+ }
+ } else {
+ switch (cast<BuiltinType>(EltType)->getKind()) {
+ case BuiltinType::SChar: EltName = "int8_t"; break;
+ case BuiltinType::UChar: EltName = "uint8_t"; break;
+ case BuiltinType::Short: EltName = "int16_t"; break;
+ case BuiltinType::UShort: EltName = "uint16_t"; break;
+ case BuiltinType::Int: EltName = "int32_t"; break;
+ case BuiltinType::UInt: EltName = "uint32_t"; break;
+ case BuiltinType::LongLong: EltName = "int64_t"; break;
+ case BuiltinType::ULongLong: EltName = "uint64_t"; break;
+ case BuiltinType::Float: EltName = "float32_t"; break;
+ default: llvm_unreachable("unexpected Neon vector element type");
+ }
+ }
+ const char *BaseName = 0;
+ unsigned BitSize = (T->getNumElements() *
+ getASTContext().getTypeSize(EltType));
+ if (BitSize == 64)
+ BaseName = "__simd64_";
+ else {
+ assert(BitSize == 128 && "Neon vector type not 64 or 128 bits");
+ BaseName = "__simd128_";
+ }
+ Out << strlen(BaseName) + strlen(EltName);
+ Out << BaseName << EltName;
+}
+
+// GNU extension: vector types
+// <type> ::= <vector-type>
+// <vector-type> ::= Dv <positive dimension number> _
+// <extended element type>
+// ::= Dv [<dimension expression>] _ <element type>
+// <extended element type> ::= <element type>
+// ::= p # AltiVec vector pixel
+// ::= b # Altivec vector bool
+void CXXNameMangler::mangleType(const VectorType *T) {
+ if ((T->getVectorKind() == VectorType::NeonVector ||
+ T->getVectorKind() == VectorType::NeonPolyVector)) {
+ mangleNeonVectorType(T);
+ return;
+ }
+ Out << "Dv" << T->getNumElements() << '_';
+ if (T->getVectorKind() == VectorType::AltiVecPixel)
+ Out << 'p';
+ else if (T->getVectorKind() == VectorType::AltiVecBool)
+ Out << 'b';
+ else
+ mangleType(T->getElementType());
+}
+void CXXNameMangler::mangleType(const ExtVectorType *T) {
+ mangleType(static_cast<const VectorType*>(T));
+}
+void CXXNameMangler::mangleType(const DependentSizedExtVectorType *T) {
+ Out << "Dv";
+ mangleExpression(T->getSizeExpr());
+ Out << '_';
+ mangleType(T->getElementType());
+}
+
+void CXXNameMangler::mangleType(const PackExpansionType *T) {
+ // <type> ::= Dp <type> # pack expansion (C++0x)
+ Out << "Dp";
+ mangleType(T->getPattern());
+}
+
+void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
+ mangleSourceName(T->getDecl()->getIdentifier());
+}
+
+void CXXNameMangler::mangleType(const ObjCObjectType *T) {
+ // We don't allow overloading by different protocol qualification,
+ // so mangling them isn't necessary.
+ mangleType(T->getBaseType());
+}
+
+void CXXNameMangler::mangleType(const BlockPointerType *T) {
+ Out << "U13block_pointer";
+ mangleType(T->getPointeeType());
+}
+
+void CXXNameMangler::mangleType(const InjectedClassNameType *T) {
+ // Mangle injected class name types as if the user had written the
+ // specialization out fully. It may not actually be possible to see
+ // this mangling, though.
+ mangleType(T->getInjectedSpecializationType());
+}
+
+void CXXNameMangler::mangleType(const TemplateSpecializationType *T) {
+ if (TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl()) {
+ mangleName(TD, T->getArgs(), T->getNumArgs());
+ } else {
+ if (mangleSubstitution(QualType(T, 0)))
+ return;
+
+ mangleTemplatePrefix(T->getTemplateName());
+
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(T->getArgs(), T->getNumArgs());
+ addSubstitution(QualType(T, 0));
+ }
+}
+
+void CXXNameMangler::mangleType(const DependentNameType *T) {
+ // Typename types are always nested
+ Out << 'N';
+ manglePrefix(T->getQualifier());
+ mangleSourceName(T->getIdentifier());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const DependentTemplateSpecializationType *T) {
+ // Dependently-scoped template types are nested if they have a prefix.
+ Out << 'N';
+
+ // TODO: avoid making this TemplateName.
+ TemplateName Prefix =
+ getASTContext().getDependentTemplateName(T->getQualifier(),
+ T->getIdentifier());
+ mangleTemplatePrefix(Prefix);
+
+ // FIXME: GCC does not appear to mangle the template arguments when
+ // the template in question is a dependent template name. Should we
+ // emulate that badness?
+ mangleTemplateArgs(T->getArgs(), T->getNumArgs());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const TypeOfType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const TypeOfExprType *T) {
+ // FIXME: this is pretty unsatisfactory, but there isn't an obvious
+ // "extension with parameters" mangling.
+ Out << "u6typeof";
+}
+
+void CXXNameMangler::mangleType(const DecltypeType *T) {
+ Expr *E = T->getUnderlyingExpr();
+
+ // type ::= Dt <expression> E # decltype of an id-expression
+ // # or class member access
+ // ::= DT <expression> E # decltype of an expression
+
+ // This purports to be an exhaustive list of id-expressions and
+ // class member accesses. Note that we do not ignore parentheses;
+ // parentheses change the semantics of decltype for these
+ // expressions (and cause the mangler to use the other form).
+ if (isa<DeclRefExpr>(E) ||
+ isa<MemberExpr>(E) ||
+ isa<UnresolvedLookupExpr>(E) ||
+ isa<DependentScopeDeclRefExpr>(E) ||
+ isa<CXXDependentScopeMemberExpr>(E) ||
+ isa<UnresolvedMemberExpr>(E))
+ Out << "Dt";
+ else
+ Out << "DT";
+ mangleExpression(E);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleType(const UnaryTransformType *T) {
+ // If this is dependent, we need to record that. If not, we simply
+ // mangle it as the underlying type since they are equivalent.
+ if (T->isDependentType()) {
+ Out << 'U';
+
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ Out << "3eut";
+ break;
+ }
+ }
+
+ mangleType(T->getUnderlyingType());
+}
+
+void CXXNameMangler::mangleType(const AutoType *T) {
+ QualType D = T->getDeducedType();
+ // <builtin-type> ::= Da # dependent auto
+ if (D.isNull())
+ Out << "Da";
+ else
+ mangleType(D);
+}
+
+void CXXNameMangler::mangleType(const AtomicType *T) {
+ // <type> ::= U <source-name> <type> # vendor extended type qualifier
+ // (Until there's a standardized mangling...)
+ Out << "U7_Atomic";
+ mangleType(T->getValueType());
+}
+
+void CXXNameMangler::mangleIntegerLiteral(QualType T,
+ const llvm::APSInt &Value) {
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+ Out << 'L';
+
+ mangleType(T);
+ if (T->isBooleanType()) {
+ // Boolean values are encoded as 0/1.
+ Out << (Value.getBoolValue() ? '1' : '0');
+ } else {
+ mangleNumber(Value);
+ }
+ Out << 'E';
+
+}
+
+/// Mangles a member expression.
+void CXXNameMangler::mangleMemberExpr(const Expr *base,
+ bool isArrow,
+ NestedNameSpecifier *qualifier,
+ NamedDecl *firstQualifierLookup,
+ DeclarationName member,
+ unsigned arity) {
+ // <expression> ::= dt <expression> <unresolved-name>
+ // ::= pt <expression> <unresolved-name>
+ if (base) {
+ if (base->isImplicitCXXThis()) {
+ // Note: GCC mangles member expressions to the implicit 'this' as
+ // *this., whereas we represent them as this->. The Itanium C++ ABI
+ // does not specify anything here, so we follow GCC.
+ Out << "dtdefpT";
+ } else {
+ Out << (isArrow ? "pt" : "dt");
+ mangleExpression(base);
+ }
+ }
+ mangleUnresolvedName(qualifier, firstQualifierLookup, member, arity);
+}
+
+/// Look at the callee of the given call expression and determine if
+/// it's a parenthesized id-expression which would have triggered ADL
+/// otherwise.
+static bool isParenthesizedADLCallee(const CallExpr *call) {
+ const Expr *callee = call->getCallee();
+ const Expr *fn = callee->IgnoreParens();
+
+ // Must be parenthesized. IgnoreParens() skips __extension__ nodes,
+ // too, but for those to appear in the callee, it would have to be
+ // parenthesized.
+ if (callee == fn) return false;
+
+ // Must be an unresolved lookup.
+ const UnresolvedLookupExpr *lookup = dyn_cast<UnresolvedLookupExpr>(fn);
+ if (!lookup) return false;
+
+ assert(!lookup->requiresADL());
+
+ // Must be an unqualified lookup.
+ if (lookup->getQualifier()) return false;
+
+ // Must not have found a class member. Note that if one is a class
+ // member, they're all class members.
+ if (lookup->getNumDecls() > 0 &&
+ (*lookup->decls_begin())->isCXXClassMember())
+ return false;
+
+ // Otherwise, ADL would have been triggered.
+ return true;
+}
+
+void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
+ // <expression> ::= <unary operator-name> <expression>
+ // ::= <binary operator-name> <expression> <expression>
+ // ::= <trinary operator-name> <expression> <expression> <expression>
+ // ::= cv <type> expression # conversion with one argument
+ // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
+ // ::= st <type> # sizeof (a type)
+ // ::= at <type> # alignof (a type)
+ // ::= <template-param>
+ // ::= <function-param>
+ // ::= sr <type> <unqualified-name> # dependent name
+ // ::= sr <type> <unqualified-name> <template-args> # dependent template-id
+ // ::= ds <expression> <expression> # expr.*expr
+ // ::= sZ <template-param> # size of a parameter pack
+ // ::= sZ <function-param> # size of a function parameter pack
+ // ::= <expr-primary>
+ // <expr-primary> ::= L <type> <value number> E # integer literal
+ // ::= L <type <value float> E # floating literal
+ // ::= L <mangled-name> E # external name
+ // ::= fpT # 'this' expression
+ QualType ImplicitlyConvertedToType;
+
+recurse:
+ switch (E->getStmtClass()) {
+ case Expr::NoStmtClass:
+#define ABSTRACT_STMT(Type)
+#define EXPR(Type, Base)
+#define STMT(Type, Base) \
+ case Expr::Type##Class:
+#include "clang/AST/StmtNodes.inc"
+ // fallthrough
+
+ // These all can only appear in local or variable-initialization
+ // contexts and so should never appear in a mangling.
+ case Expr::AddrLabelExprClass:
+ case Expr::DesignatedInitExprClass:
+ case Expr::ImplicitValueInitExprClass:
+ case Expr::ParenListExprClass:
+ case Expr::LambdaExprClass:
+ llvm_unreachable("unexpected statement kind");
+
+ // FIXME: invent manglings for all these.
+ case Expr::BlockExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::ChooseExprClass:
+ case Expr::CompoundLiteralExprClass:
+ case Expr::ExtVectorElementExprClass:
+ case Expr::GenericSelectionExprClass:
+ case Expr::ObjCEncodeExprClass:
+ case Expr::ObjCIsaExprClass:
+ case Expr::ObjCIvarRefExprClass:
+ case Expr::ObjCMessageExprClass:
+ case Expr::ObjCPropertyRefExprClass:
+ case Expr::ObjCProtocolExprClass:
+ case Expr::ObjCSelectorExprClass:
+ case Expr::ObjCStringLiteralClass:
+ case Expr::ObjCBoxedExprClass:
+ case Expr::ObjCArrayLiteralClass:
+ case Expr::ObjCDictionaryLiteralClass:
+ case Expr::ObjCSubscriptRefExprClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::OffsetOfExprClass:
+ case Expr::PredefinedExprClass:
+ case Expr::ShuffleVectorExprClass:
+ case Expr::StmtExprClass:
+ case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
+ case Expr::TypeTraitExprClass:
+ case Expr::ArrayTypeTraitExprClass:
+ case Expr::ExpressionTraitExprClass:
+ case Expr::VAArgExprClass:
+ case Expr::CXXUuidofExprClass:
+ case Expr::CUDAKernelCallExprClass:
+ case Expr::AsTypeExprClass:
+ case Expr::PseudoObjectExprClass:
+ case Expr::AtomicExprClass:
+ {
+ // As bad as this diagnostic is, it's better than crashing.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet mangle expression type %0");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+ break;
+ }
+
+ // Even gcc-4.5 doesn't mangle this.
+ case Expr::BinaryConditionalOperatorClass: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID =
+ Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "?: operator with omitted middle operand cannot be mangled");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+ break;
+ }
+
+ // These are used for internal purposes and cannot be meaningfully mangled.
+ case Expr::OpaqueValueExprClass:
+ llvm_unreachable("cannot mangle opaque value; mangling wrong thing?");
+
+ case Expr::InitListExprClass: {
+ // Proposal by Jason Merrill, 2012-01-03
+ Out << "il";
+ const InitListExpr *InitList = cast<InitListExpr>(E);
+ for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
+ mangleExpression(InitList->getInit(i));
+ Out << "E";
+ break;
+ }
+
+ case Expr::CXXDefaultArgExprClass:
+ mangleExpression(cast<CXXDefaultArgExpr>(E)->getExpr(), Arity);
+ break;
+
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ mangleExpression(cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement(),
+ Arity);
+ break;
+
+ case Expr::UserDefinedLiteralClass:
+ // We follow g++'s approach of mangling a UDL as a call to the literal
+ // operator.
+ case Expr::CXXMemberCallExprClass: // fallthrough
+ case Expr::CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+
+ // <expression> ::= cp <simple-id> <expression>* E
+ // We use this mangling only when the call would use ADL except
+ // for being parenthesized. Per discussion with David
+ // Vandervoorde, 2011.04.25.
+ if (isParenthesizedADLCallee(CE)) {
+ Out << "cp";
+ // The callee here is a parenthesized UnresolvedLookupExpr with
+ // no qualifier and should always get mangled as a <simple-id>
+ // anyway.
+
+ // <expression> ::= cl <expression>* E
+ } else {
+ Out << "cl";
+ }
+
+ mangleExpression(CE->getCallee(), CE->getNumArgs());
+ for (unsigned I = 0, N = CE->getNumArgs(); I != N; ++I)
+ mangleExpression(CE->getArg(I));
+ Out << 'E';
+ break;
+ }
+
+ case Expr::CXXNewExprClass: {
+ const CXXNewExpr *New = cast<CXXNewExpr>(E);
+ if (New->isGlobalNew()) Out << "gs";
+ Out << (New->isArray() ? "na" : "nw");
+ for (CXXNewExpr::const_arg_iterator I = New->placement_arg_begin(),
+ E = New->placement_arg_end(); I != E; ++I)
+ mangleExpression(*I);
+ Out << '_';
+ mangleType(New->getAllocatedType());
+ if (New->hasInitializer()) {
+ // Proposal by Jason Merrill, 2012-01-03
+ if (New->getInitializationStyle() == CXXNewExpr::ListInit)
+ Out << "il";
+ else
+ Out << "pi";
+ const Expr *Init = New->getInitializer();
+ if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
+ // Directly inline the initializers.
+ for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
+ E = CCE->arg_end();
+ I != E; ++I)
+ mangleExpression(*I);
+ } else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
+ for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
+ mangleExpression(PLE->getExpr(i));
+ } else if (New->getInitializationStyle() == CXXNewExpr::ListInit &&
+ isa<InitListExpr>(Init)) {
+ // Only take InitListExprs apart for list-initialization.
+ const InitListExpr *InitList = cast<InitListExpr>(Init);
+ for (unsigned i = 0, e = InitList->getNumInits(); i != e; ++i)
+ mangleExpression(InitList->getInit(i));
+ } else
+ mangleExpression(Init);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case Expr::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), 0, ME->getMemberDecl()->getDeclName(),
+ Arity);
+ break;
+ }
+
+ case Expr::UnresolvedMemberExprClass: {
+ const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), 0, ME->getMemberName(),
+ Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::CXXDependentScopeMemberExprClass: {
+ const CXXDependentScopeMemberExpr *ME
+ = cast<CXXDependentScopeMemberExpr>(E);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(),
+ ME->getQualifier(), ME->getFirstQualifierFoundInScope(),
+ ME->getMember(), Arity);
+ if (ME->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ME->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::UnresolvedLookupExprClass: {
+ const UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(E);
+ mangleUnresolvedName(ULE->getQualifier(), 0, ULE->getName(), Arity);
+
+ // All the <unresolved-name> productions end in a
+ // base-unresolved-name, where <template-args> are just tacked
+ // onto the end.
+ if (ULE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(ULE->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::CXXUnresolvedConstructExprClass: {
+ const CXXUnresolvedConstructExpr *CE = cast<CXXUnresolvedConstructExpr>(E);
+ unsigned N = CE->arg_size();
+
+ Out << "cv";
+ mangleType(CE->getType());
+ if (N != 1) Out << '_';
+ for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+ if (N != 1) Out << 'E';
+ break;
+ }
+
+ case Expr::CXXTemporaryObjectExprClass:
+ case Expr::CXXConstructExprClass: {
+ const CXXConstructExpr *CE = cast<CXXConstructExpr>(E);
+ unsigned N = CE->getNumArgs();
+
+ // Proposal by Jason Merrill, 2012-01-03
+ if (CE->isListInitialization())
+ Out << "tl";
+ else
+ Out << "cv";
+ mangleType(CE->getType());
+ if (N != 1) Out << '_';
+ for (unsigned I = 0; I != N; ++I) mangleExpression(CE->getArg(I));
+ if (N != 1) Out << 'E';
+ break;
+ }
+
+ case Expr::CXXScalarValueInitExprClass:
+ Out <<"cv";
+ mangleType(E->getType());
+ Out <<"_E";
+ break;
+
+ case Expr::CXXNoexceptExprClass:
+ Out << "nx";
+ mangleExpression(cast<CXXNoexceptExpr>(E)->getOperand());
+ break;
+
+ case Expr::UnaryExprOrTypeTraitExprClass: {
+ const UnaryExprOrTypeTraitExpr *SAE = cast<UnaryExprOrTypeTraitExpr>(E);
+
+ if (!SAE->isInstantiationDependent()) {
+ // Itanium C++ ABI:
+ // If the operand of a sizeof or alignof operator is not
+ // instantiation-dependent it is encoded as an integer literal
+ // reflecting the result of the operator.
+ //
+ // If the result of the operator is implicitly converted to a known
+ // integer type, that type is used for the literal; otherwise, the type
+ // of std::size_t or std::ptrdiff_t is used.
+ QualType T = (ImplicitlyConvertedToType.isNull() ||
+ !ImplicitlyConvertedToType->isIntegerType())? SAE->getType()
+ : ImplicitlyConvertedToType;
+ llvm::APSInt V = SAE->EvaluateKnownConstInt(Context.getASTContext());
+ mangleIntegerLiteral(T, V);
+ break;
+ }
+
+ switch(SAE->getKind()) {
+ case UETT_SizeOf:
+ Out << 's';
+ break;
+ case UETT_AlignOf:
+ Out << 'a';
+ break;
+ case UETT_VecStep:
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet mangle vec_step expression");
+ Diags.Report(DiagID);
+ return;
+ }
+ if (SAE->isArgumentType()) {
+ Out << 't';
+ mangleType(SAE->getArgumentType());
+ } else {
+ Out << 'z';
+ mangleExpression(SAE->getArgumentExpr());
+ }
+ break;
+ }
+
+ case Expr::CXXThrowExprClass: {
+ const CXXThrowExpr *TE = cast<CXXThrowExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (TE->getSubExpr()) {
+ Out << "tw";
+ mangleExpression(TE->getSubExpr());
+ } else {
+ Out << "tr";
+ }
+ break;
+ }
+
+ case Expr::CXXTypeidExprClass: {
+ const CXXTypeidExpr *TIE = cast<CXXTypeidExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (TIE->isTypeOperand()) {
+ Out << "ti";
+ mangleType(TIE->getTypeOperand());
+ } else {
+ Out << "te";
+ mangleExpression(TIE->getExprOperand());
+ }
+ break;
+ }
+
+ case Expr::CXXDeleteExprClass: {
+ const CXXDeleteExpr *DE = cast<CXXDeleteExpr>(E);
+
+ // Proposal from David Vandervoorde, 2010.06.30
+ if (DE->isGlobalDelete()) Out << "gs";
+ Out << (DE->isArrayForm() ? "da" : "dl");
+ mangleExpression(DE->getArgument());
+ break;
+ }
+
+ case Expr::UnaryOperatorClass: {
+ const UnaryOperator *UO = cast<UnaryOperator>(E);
+ mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()),
+ /*Arity=*/1);
+ mangleExpression(UO->getSubExpr());
+ break;
+ }
+
+ case Expr::ArraySubscriptExprClass: {
+ const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(E);
+
+ // Array subscript is treated as a syntactically weird form of
+ // binary operator.
+ Out << "ix";
+ mangleExpression(AE->getLHS());
+ mangleExpression(AE->getRHS());
+ break;
+ }
+
+ case Expr::CompoundAssignOperatorClass: // fallthrough
+ case Expr::BinaryOperatorClass: {
+ const BinaryOperator *BO = cast<BinaryOperator>(E);
+ if (BO->getOpcode() == BO_PtrMemD)
+ Out << "ds";
+ else
+ mangleOperatorName(BinaryOperator::getOverloadedOperator(BO->getOpcode()),
+ /*Arity=*/2);
+ mangleExpression(BO->getLHS());
+ mangleExpression(BO->getRHS());
+ break;
+ }
+
+ case Expr::ConditionalOperatorClass: {
+ const ConditionalOperator *CO = cast<ConditionalOperator>(E);
+ mangleOperatorName(OO_Conditional, /*Arity=*/3);
+ mangleExpression(CO->getCond());
+ mangleExpression(CO->getLHS(), Arity);
+ mangleExpression(CO->getRHS(), Arity);
+ break;
+ }
+
+ case Expr::ImplicitCastExprClass: {
+ ImplicitlyConvertedToType = E->getType();
+ E = cast<ImplicitCastExpr>(E)->getSubExpr();
+ goto recurse;
+ }
+
+ case Expr::ObjCBridgedCastExprClass: {
+ // Mangle ownership casts as a vendor extended operator __bridge,
+ // __bridge_transfer, or __bridge_retain.
+ StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
+ Out << "v1U" << Kind.size() << Kind;
+ }
+ // Fall through to mangle the cast itself.
+
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXDynamicCastExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::CXXConstCastExprClass:
+ case Expr::CXXFunctionalCastExprClass: {
+ const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
+ Out << "cv";
+ mangleType(ECE->getType());
+ mangleExpression(ECE->getSubExpr());
+ break;
+ }
+
+ case Expr::CXXOperatorCallExprClass: {
+ const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
+ unsigned NumArgs = CE->getNumArgs();
+ mangleOperatorName(CE->getOperator(), /*Arity=*/NumArgs);
+ // Mangle the arguments.
+ for (unsigned i = 0; i != NumArgs; ++i)
+ mangleExpression(CE->getArg(i));
+ break;
+ }
+
+ case Expr::ParenExprClass:
+ mangleExpression(cast<ParenExpr>(E)->getSubExpr(), Arity);
+ break;
+
+ case Expr::DeclRefExprClass: {
+ const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
+
+ switch (D->getKind()) {
+ default:
+ // <expr-primary> ::= L <mangled-name> E # external name
+ Out << 'L';
+ mangle(D, "_Z");
+ Out << 'E';
+ break;
+
+ case Decl::ParmVar:
+ mangleFunctionParam(cast<ParmVarDecl>(D));
+ break;
+
+ case Decl::EnumConstant: {
+ const EnumConstantDecl *ED = cast<EnumConstantDecl>(D);
+ mangleIntegerLiteral(ED->getType(), ED->getInitVal());
+ break;
+ }
+
+ case Decl::NonTypeTemplateParm: {
+ const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
+ mangleTemplateParameter(PD->getIndex());
+ break;
+ }
+
+ }
+
+ break;
+ }
+
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
+ // FIXME: not clear how to mangle this!
+ // template <unsigned N...> class A {
+ // template <class U...> void foo(U (&x)[N]...);
+ // };
+ Out << "_SUBSTPACK_";
+ break;
+
+ case Expr::FunctionParmPackExprClass: {
+ // FIXME: not clear how to mangle this!
+ const FunctionParmPackExpr *FPPE = cast<FunctionParmPackExpr>(E);
+ Out << "v110_SUBSTPACK";
+ mangleFunctionParam(FPPE->getParameterPack());
+ break;
+ }
+
+ case Expr::DependentScopeDeclRefExprClass: {
+ const DependentScopeDeclRefExpr *DRE = cast<DependentScopeDeclRefExpr>(E);
+ mangleUnresolvedName(DRE->getQualifier(), 0, DRE->getDeclName(), Arity);
+
+ // All the <unresolved-name> productions end in a
+ // base-unresolved-name, where <template-args> are just tacked
+ // onto the end.
+ if (DRE->hasExplicitTemplateArgs())
+ mangleTemplateArgs(DRE->getExplicitTemplateArgs());
+ break;
+ }
+
+ case Expr::CXXBindTemporaryExprClass:
+ mangleExpression(cast<CXXBindTemporaryExpr>(E)->getSubExpr());
+ break;
+
+ case Expr::ExprWithCleanupsClass:
+ mangleExpression(cast<ExprWithCleanups>(E)->getSubExpr(), Arity);
+ break;
+
+ case Expr::FloatingLiteralClass: {
+ const FloatingLiteral *FL = cast<FloatingLiteral>(E);
+ Out << 'L';
+ mangleType(FL->getType());
+ mangleFloat(FL->getValue());
+ Out << 'E';
+ break;
+ }
+
+ case Expr::CharacterLiteralClass:
+ Out << 'L';
+ mangleType(E->getType());
+ Out << cast<CharacterLiteral>(E)->getValue();
+ Out << 'E';
+ break;
+
+ // FIXME. __objc_yes/__objc_no are mangled same as true/false
+ case Expr::ObjCBoolLiteralExprClass:
+ Out << "Lb";
+ Out << (cast<ObjCBoolLiteralExpr>(E)->getValue() ? '1' : '0');
+ Out << 'E';
+ break;
+
+ case Expr::CXXBoolLiteralExprClass:
+ Out << "Lb";
+ Out << (cast<CXXBoolLiteralExpr>(E)->getValue() ? '1' : '0');
+ Out << 'E';
+ break;
+
+ case Expr::IntegerLiteralClass: {
+ llvm::APSInt Value(cast<IntegerLiteral>(E)->getValue());
+ if (E->getType()->isSignedIntegerType())
+ Value.setIsSigned(true);
+ mangleIntegerLiteral(E->getType(), Value);
+ break;
+ }
+
+ case Expr::ImaginaryLiteralClass: {
+ const ImaginaryLiteral *IE = cast<ImaginaryLiteral>(E);
+ // Mangle as if a complex literal.
+ // Proposal from David Vandevoorde, 2010.06.30.
+ Out << 'L';
+ mangleType(E->getType());
+ if (const FloatingLiteral *Imag =
+ dyn_cast<FloatingLiteral>(IE->getSubExpr())) {
+ // Mangle a floating-point zero of the appropriate type.
+ mangleFloat(llvm::APFloat(Imag->getValue().getSemantics()));
+ Out << '_';
+ mangleFloat(Imag->getValue());
+ } else {
+ Out << "0_";
+ llvm::APSInt Value(cast<IntegerLiteral>(IE->getSubExpr())->getValue());
+ if (IE->getSubExpr()->getType()->isSignedIntegerType())
+ Value.setIsSigned(true);
+ mangleNumber(Value);
+ }
+ Out << 'E';
+ break;
+ }
+
+ case Expr::StringLiteralClass: {
+ // Revised proposal from David Vandervoorde, 2010.07.15.
+ Out << 'L';
+ assert(isa<ConstantArrayType>(E->getType()));
+ mangleType(E->getType());
+ Out << 'E';
+ break;
+ }
+
+ case Expr::GNUNullExprClass:
+ // FIXME: should this really be mangled the same as nullptr?
+ // fallthrough
+
+ case Expr::CXXNullPtrLiteralExprClass: {
+ // Proposal from David Vandervoorde, 2010.06.30, as
+ // modified by ABI list discussion.
+ Out << "LDnE";
+ break;
+ }
+
+ case Expr::PackExpansionExprClass:
+ Out << "sp";
+ mangleExpression(cast<PackExpansionExpr>(E)->getPattern());
+ break;
+
+ case Expr::SizeOfPackExprClass: {
+ Out << "sZ";
+ const NamedDecl *Pack = cast<SizeOfPackExpr>(E)->getPack();
+ if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
+ mangleTemplateParameter(TTP->getIndex());
+ else if (const NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Pack))
+ mangleTemplateParameter(NTTP->getIndex());
+ else if (const TemplateTemplateParmDecl *TempTP
+ = dyn_cast<TemplateTemplateParmDecl>(Pack))
+ mangleTemplateParameter(TempTP->getIndex());
+ else
+ mangleFunctionParam(cast<ParmVarDecl>(Pack));
+ break;
+ }
+
+ case Expr::MaterializeTemporaryExprClass: {
+ mangleExpression(cast<MaterializeTemporaryExpr>(E)->GetTemporaryExpr());
+ break;
+ }
+
+ case Expr::CXXThisExprClass:
+ Out << "fpT";
+ break;
+ }
+}
+
+/// Mangle an expression which refers to a parameter variable.
+///
+/// <expression> ::= <function-param>
+/// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, I == 0
+/// <function-param> ::= fp <top-level CV-qualifiers>
+/// <parameter-2 non-negative number> _ # L == 0, I > 0
+/// <function-param> ::= fL <L-1 non-negative number>
+/// p <top-level CV-qualifiers> _ # L > 0, I == 0
+/// <function-param> ::= fL <L-1 non-negative number>
+/// p <top-level CV-qualifiers>
+/// <I-1 non-negative number> _ # L > 0, I > 0
+///
+/// L is the nesting depth of the parameter, defined as 1 if the
+/// parameter comes from the innermost function prototype scope
+/// enclosing the current context, 2 if from the next enclosing
+/// function prototype scope, and so on, with one special case: if
+/// we've processed the full parameter clause for the innermost
+/// function type, then L is one less. This definition conveniently
+/// makes it irrelevant whether a function's result type was written
+/// trailing or leading, but is otherwise overly complicated; the
+/// numbering was first designed without considering references to
+/// parameter in locations other than return types, and then the
+/// mangling had to be generalized without changing the existing
+/// manglings.
+///
+/// I is the zero-based index of the parameter within its parameter
+/// declaration clause. Note that the original ABI document describes
+/// this using 1-based ordinals.
+void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
+ unsigned parmDepth = parm->getFunctionScopeDepth();
+ unsigned parmIndex = parm->getFunctionScopeIndex();
+
+ // Compute 'L'.
+ // parmDepth does not include the declaring function prototype.
+ // FunctionTypeDepth does account for that.
+ assert(parmDepth < FunctionTypeDepth.getDepth());
+ unsigned nestingDepth = FunctionTypeDepth.getDepth() - parmDepth;
+ if (FunctionTypeDepth.isInResultType())
+ nestingDepth--;
+
+ if (nestingDepth == 0) {
+ Out << "fp";
+ } else {
+ Out << "fL" << (nestingDepth - 1) << 'p';
+ }
+
+ // Top-level qualifiers. We don't have to worry about arrays here,
+ // because parameters declared as arrays should already have been
+ // transformed to have pointer type. FIXME: apparently these don't
+ // get mangled if used as an rvalue of a known non-class type?
+ assert(!parm->getType()->isArrayType()
+ && "parameter's type is still an array type?");
+ mangleQualifiers(parm->getType().getQualifiers());
+
+ // Parameter index.
+ if (parmIndex != 0) {
+ Out << (parmIndex - 1);
+ }
+ Out << '_';
+}
+
+void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
+ // <ctor-dtor-name> ::= C1 # complete object constructor
+ // ::= C2 # base object constructor
+ // ::= C3 # complete object allocating constructor
+ //
+ switch (T) {
+ case Ctor_Complete:
+ Out << "C1";
+ break;
+ case Ctor_Base:
+ Out << "C2";
+ break;
+ case Ctor_CompleteAllocating:
+ Out << "C3";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
+ // <ctor-dtor-name> ::= D0 # deleting destructor
+ // ::= D1 # complete object destructor
+ // ::= D2 # base object destructor
+ //
+ switch (T) {
+ case Dtor_Deleting:
+ Out << "D0";
+ break;
+ case Dtor_Complete:
+ Out << "D1";
+ break;
+ case Dtor_Base:
+ Out << "D2";
+ break;
+ }
+}
+
+void CXXNameMangler::mangleTemplateArgs(
+ const ASTTemplateArgumentListInfo &TemplateArgs) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0, e = TemplateArgs.NumTemplateArgs; i != e; ++i)
+ mangleTemplateArg(TemplateArgs.getTemplateArgs()[i].getArgument());
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgumentList &AL) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0, e = AL.size(); i != e; ++i)
+ mangleTemplateArg(AL[i]);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArgs(const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ // <template-args> ::= I <template-arg>+ E
+ Out << 'I';
+ for (unsigned i = 0; i != NumTemplateArgs; ++i)
+ mangleTemplateArg(TemplateArgs[i]);
+ Out << 'E';
+}
+
+void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
+ // <template-arg> ::= <type> # type or template
+ // ::= X <expression> E # expression
+ // ::= <expr-primary> # simple expressions
+ // ::= J <template-arg>* E # argument pack
+ // ::= sp <expression> # pack expansion of (C++0x)
+ if (!A.isInstantiationDependent() || A.isDependent())
+ A = Context.getASTContext().getCanonicalTemplateArgument(A);
+
+ switch (A.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Cannot mangle NULL template argument");
+
+ case TemplateArgument::Type:
+ mangleType(A.getAsType());
+ break;
+ case TemplateArgument::Template:
+ // This is mangled as <type>.
+ mangleType(A.getAsTemplate());
+ break;
+ case TemplateArgument::TemplateExpansion:
+ // <type> ::= Dp <type> # pack expansion (C++0x)
+ Out << "Dp";
+ mangleType(A.getAsTemplateOrTemplatePattern());
+ break;
+ case TemplateArgument::Expression: {
+ // It's possible to end up with a DeclRefExpr here in certain
+ // dependent cases, in which case we should mangle as a
+ // declaration.
+ const Expr *E = A.getAsExpr()->IgnoreParens();
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+ const ValueDecl *D = DRE->getDecl();
+ if (isa<VarDecl>(D) || isa<FunctionDecl>(D)) {
+ Out << "L";
+ mangle(D, "_Z");
+ Out << 'E';
+ break;
+ }
+ }
+
+ Out << 'X';
+ mangleExpression(E);
+ Out << 'E';
+ break;
+ }
+ case TemplateArgument::Integral:
+ mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral());
+ break;
+ case TemplateArgument::Declaration: {
+ // <expr-primary> ::= L <mangled-name> E # external name
+ // Clang produces AST's where pointer-to-member-function expressions
+ // and pointer-to-function expressions are represented as a declaration not
+ // an expression. We compensate for it here to produce the correct mangling.
+ ValueDecl *D = A.getAsDecl();
+ bool compensateMangling = !A.isDeclForReferenceParam();
+ if (compensateMangling) {
+ Out << 'X';
+ mangleOperatorName(OO_Amp, 1);
+ }
+
+ Out << 'L';
+ // References to external entities use the mangled name; if the name would
+ // not normally be manged then mangle it as unqualified.
+ //
+ // FIXME: The ABI specifies that external names here should have _Z, but
+ // gcc leaves this off.
+ if (compensateMangling)
+ mangle(D, "_Z");
+ else
+ mangle(D, "Z");
+ Out << 'E';
+
+ if (compensateMangling)
+ Out << 'E';
+
+ break;
+ }
+ case TemplateArgument::NullPtr: {
+ // <expr-primary> ::= L <type> 0 E
+ Out << 'L';
+ mangleType(A.getNullPtrType());
+ Out << "0E";
+ break;
+ }
+ case TemplateArgument::Pack: {
+ // Note: proposal by Mike Herrick on 12/20/10
+ Out << 'J';
+ for (TemplateArgument::pack_iterator PA = A.pack_begin(),
+ PAEnd = A.pack_end();
+ PA != PAEnd; ++PA)
+ mangleTemplateArg(*PA);
+ Out << 'E';
+ }
+ }
+}
+
+void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
+ // <template-param> ::= T_ # first template parameter
+ // ::= T <parameter-2 non-negative number> _
+ if (Index == 0)
+ Out << "T_";
+ else
+ Out << 'T' << (Index - 1) << '_';
+}
+
+void CXXNameMangler::mangleExistingSubstitution(QualType type) {
+ bool result = mangleSubstitution(type);
+ assert(result && "no existing substitution for type");
+ (void) result;
+}
+
+void CXXNameMangler::mangleExistingSubstitution(TemplateName tname) {
+ bool result = mangleSubstitution(tname);
+ assert(result && "no existing substitution for template name");
+ (void) result;
+}
+
+// <substitution> ::= S <seq-id> _
+// ::= S_
+bool CXXNameMangler::mangleSubstitution(const NamedDecl *ND) {
+ // Try one of the standard substitutions first.
+ if (mangleStandardSubstitution(ND))
+ return true;
+
+ ND = cast<NamedDecl>(ND->getCanonicalDecl());
+ return mangleSubstitution(reinterpret_cast<uintptr_t>(ND));
+}
+
+/// \brief Determine whether the given type has any qualifiers that are
+/// relevant for substitutions.
+static bool hasMangledSubstitutionQualifiers(QualType T) {
+ Qualifiers Qs = T.getQualifiers();
+ return Qs.getCVRQualifiers() || Qs.hasAddressSpace();
+}
+
+bool CXXNameMangler::mangleSubstitution(QualType T) {
+ if (!hasMangledSubstitutionQualifiers(T)) {
+ if (const RecordType *RT = T->getAs<RecordType>())
+ return mangleSubstitution(RT->getDecl());
+ }
+
+ uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+
+ return mangleSubstitution(TypePtr);
+}
+
+bool CXXNameMangler::mangleSubstitution(TemplateName Template) {
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return mangleSubstitution(TD);
+
+ Template = Context.getASTContext().getCanonicalTemplateName(Template);
+ return mangleSubstitution(
+ reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
+bool CXXNameMangler::mangleSubstitution(uintptr_t Ptr) {
+ llvm::DenseMap<uintptr_t, unsigned>::iterator I = Substitutions.find(Ptr);
+ if (I == Substitutions.end())
+ return false;
+
+ unsigned SeqID = I->second;
+ if (SeqID == 0)
+ Out << "S_";
+ else {
+ SeqID--;
+
+ // <seq-id> is encoded in base-36, using digits and upper case letters.
+ char Buffer[10];
+ char *BufferPtr = llvm::array_endof(Buffer);
+
+ if (SeqID == 0) *--BufferPtr = '0';
+
+ while (SeqID) {
+ assert(BufferPtr > Buffer && "Buffer overflow!");
+
+ char c = static_cast<char>(SeqID % 36);
+
+ *--BufferPtr = (c < 10 ? '0' + c : 'A' + c - 10);
+ SeqID /= 36;
+ }
+
+ Out << 'S'
+ << StringRef(BufferPtr, llvm::array_endof(Buffer)-BufferPtr)
+ << '_';
+ }
+
+ return true;
+}
+
+static bool isCharType(QualType T) {
+ if (T.isNull())
+ return false;
+
+ return T->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ T->isSpecificBuiltinType(BuiltinType::Char_U);
+}
+
+/// isCharSpecialization - Returns whether a given type is a template
+/// specialization of a given name with a single argument of type char.
+static bool isCharSpecialization(QualType T, const char *Name) {
+ if (T.isNull())
+ return false;
+
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ const ClassTemplateSpecializationDecl *SD =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ if (!SD)
+ return false;
+
+ if (!isStdNamespace(getEffectiveDeclContext(SD)))
+ return false;
+
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+ if (TemplateArgs.size() != 1)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ return SD->getIdentifier()->getName() == Name;
+}
+
+template <std::size_t StrLen>
+static bool isStreamCharSpecialization(const ClassTemplateSpecializationDecl*SD,
+ const char (&Str)[StrLen]) {
+ if (!SD->getIdentifier()->isStr(Str))
+ return false;
+
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+ if (TemplateArgs.size() != 2)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
+ return false;
+
+ return true;
+}
+
+bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) {
+ // <substitution> ::= St # ::std::
+ if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
+ if (isStd(NS)) {
+ Out << "St";
+ return true;
+ }
+ }
+
+ if (const ClassTemplateDecl *TD = dyn_cast<ClassTemplateDecl>(ND)) {
+ if (!isStdNamespace(getEffectiveDeclContext(TD)))
+ return false;
+
+ // <substitution> ::= Sa # ::std::allocator
+ if (TD->getIdentifier()->isStr("allocator")) {
+ Out << "Sa";
+ return true;
+ }
+
+ // <<substitution> ::= Sb # ::std::basic_string
+ if (TD->getIdentifier()->isStr("basic_string")) {
+ Out << "Sb";
+ return true;
+ }
+ }
+
+ if (const ClassTemplateSpecializationDecl *SD =
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ if (!isStdNamespace(getEffectiveDeclContext(SD)))
+ return false;
+
+ // <substitution> ::= Ss # ::std::basic_string<char,
+ // ::std::char_traits<char>,
+ // ::std::allocator<char> >
+ if (SD->getIdentifier()->isStr("basic_string")) {
+ const TemplateArgumentList &TemplateArgs = SD->getTemplateArgs();
+
+ if (TemplateArgs.size() != 3)
+ return false;
+
+ if (!isCharType(TemplateArgs[0].getAsType()))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[1].getAsType(), "char_traits"))
+ return false;
+
+ if (!isCharSpecialization(TemplateArgs[2].getAsType(), "allocator"))
+ return false;
+
+ Out << "Ss";
+ return true;
+ }
+
+ // <substitution> ::= Si # ::std::basic_istream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_istream")) {
+ Out << "Si";
+ return true;
+ }
+
+ // <substitution> ::= So # ::std::basic_ostream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_ostream")) {
+ Out << "So";
+ return true;
+ }
+
+ // <substitution> ::= Sd # ::std::basic_iostream<char,
+ // ::std::char_traits<char> >
+ if (isStreamCharSpecialization(SD, "basic_iostream")) {
+ Out << "Sd";
+ return true;
+ }
+ }
+ return false;
+}
+
+void CXXNameMangler::addSubstitution(QualType T) {
+ if (!hasMangledSubstitutionQualifiers(T)) {
+ if (const RecordType *RT = T->getAs<RecordType>()) {
+ addSubstitution(RT->getDecl());
+ return;
+ }
+ }
+
+ uintptr_t TypePtr = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ addSubstitution(TypePtr);
+}
+
+void CXXNameMangler::addSubstitution(TemplateName Template) {
+ if (TemplateDecl *TD = Template.getAsTemplateDecl())
+ return addSubstitution(TD);
+
+ Template = Context.getASTContext().getCanonicalTemplateName(Template);
+ addSubstitution(reinterpret_cast<uintptr_t>(Template.getAsVoidPointer()));
+}
+
+void CXXNameMangler::addSubstitution(uintptr_t Ptr) {
+ assert(!Substitutions.count(Ptr) && "Substitution already exists!");
+ Substitutions[Ptr] = SeqID++;
+}
+
+//
+
+/// \brief Mangles the name of the declaration D and emits that name to the
+/// given output stream.
+///
+/// If the declaration D requires a mangled name, this routine will emit that
+/// mangled name to \p os and return true. Otherwise, \p os will be unchanged
+/// and this routine will return false. In this case, the caller should just
+/// emit the identifier of the declaration (\c D->getIdentifier()) as its
+/// name.
+void ItaniumMangleContext::mangleName(const NamedDecl *D,
+ raw_ostream &Out) {
+ assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
+ "Invalid mangleName() call, argument is not a variable or function!");
+ assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
+ "Invalid mangleName() call on 'structor decl!");
+
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ getASTContext().getSourceManager(),
+ "Mangling declaration");
+
+ CXXNameMangler Mangler(*this, Out, D);
+ return Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Type);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Type);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContext::mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ raw_ostream &Out) {
+ // <special-name> ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ // # first call-offset is 'this' adjustment
+ // # second call-offset is result adjustment
+
+ assert(!isa<CXXDestructorDecl>(MD) &&
+ "Use mangleCXXDtor for destructor decls!");
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZT";
+ if (!Thunk.Return.isEmpty())
+ Mangler.getStream() << 'c';
+
+ // Mangle the 'this' pointer adjustment.
+ Mangler.mangleCallOffset(Thunk.This.NonVirtual, Thunk.This.VCallOffsetOffset);
+
+ // Mangle the return pointer adjustment if there is one.
+ if (!Thunk.Return.isEmpty())
+ Mangler.mangleCallOffset(Thunk.Return.NonVirtual,
+ Thunk.Return.VBaseOffsetOffset);
+
+ Mangler.mangleFunctionEncoding(MD);
+}
+
+void
+ItaniumMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ raw_ostream &Out) {
+ // <special-name> ::= T <call-offset> <base encoding>
+ // # base is the nominal target function of thunk
+ CXXNameMangler Mangler(*this, Out, DD, Type);
+ Mangler.getStream() << "_ZT";
+
+ // Mangle the 'this' pointer adjustment.
+ Mangler.mangleCallOffset(ThisAdjustment.NonVirtual,
+ ThisAdjustment.VCallOffsetOffset);
+
+ Mangler.mangleFunctionEncoding(DD);
+}
+
+/// mangleGuardVariable - Returns the mangled name for a guard variable
+/// for the passed in VarDecl.
+void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D,
+ raw_ostream &Out) {
+ // <special-name> ::= GV <object name> # Guard variable for one-time
+ // # initialization
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZGV";
+ Mangler.mangleName(D);
+}
+
+void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D,
+ raw_ostream &Out) {
+ // We match the GCC mangling here.
+ // <special-name> ::= GR <object name>
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZGR";
+ Mangler.mangleName(D);
+}
+
+void ItaniumMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ // <special-name> ::= TV <type> # virtual table
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTV";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+}
+
+void ItaniumMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ // <special-name> ::= TT <type> # VTT structure
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTT";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+}
+
+void ItaniumMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
+ int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &Out) {
+ // <special-name> ::= TC <type> <offset number> _ <base type>
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTC";
+ Mangler.mangleNameOrStandardSubstitution(RD);
+ Mangler.getStream() << Offset;
+ Mangler.getStream() << '_';
+ Mangler.mangleNameOrStandardSubstitution(Type);
+}
+
+void ItaniumMangleContext::mangleCXXRTTI(QualType Ty,
+ raw_ostream &Out) {
+ // <special-name> ::= TI <type> # typeinfo structure
+ assert(!Ty.hasQualifiers() && "RTTI info cannot have top-level qualifiers");
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTI";
+ Mangler.mangleType(Ty);
+}
+
+void ItaniumMangleContext::mangleCXXRTTIName(QualType Ty,
+ raw_ostream &Out) {
+ // <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
+ CXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "_ZTS";
+ Mangler.mangleType(Ty);
+}
+
+MangleContext *clang::createItaniumMangleContext(ASTContext &Context,
+ DiagnosticsEngine &Diags) {
+ return new ItaniumMangleContext(Context, Diags);
+}
Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Dec 18 08:30:41 2012
@@ -1,1725 +1,1718 @@
-//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides C++ name mangling targeting the Microsoft Visual C++ ABI.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/Mangle.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/Basic/ABI.h"
-#include "clang/Basic/DiagnosticOptions.h"
-#include <map>
-
-using namespace clang;
-
-namespace {
-
-/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftCXXNameMangler {
- MangleContext &Context;
- raw_ostream &Out;
-
- // FIXME: audit the performance of BackRefMap as it might do way too many
- // copying of strings.
- typedef std::map<std::string, unsigned> BackRefMap;
- BackRefMap NameBackReferences;
- bool UseNameBackReferences;
-
- typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;
- ArgBackRefMap TypeBackReferences;
-
- ASTContext &getASTContext() const { return Context.getASTContext(); }
-
-public:
- MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
- : Context(C), Out(Out_), UseNameBackReferences(true) { }
-
- raw_ostream &getStream() const { return Out; }
-
- void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
- void mangleName(const NamedDecl *ND);
- void mangleFunctionEncoding(const FunctionDecl *FD);
- void mangleVariableEncoding(const VarDecl *VD);
- void mangleNumber(int64_t Number);
- void mangleNumber(const llvm::APSInt &Value);
- void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
-
-private:
- void disableBackReferences() { UseNameBackReferences = false; }
- void mangleUnqualifiedName(const NamedDecl *ND) {
- mangleUnqualifiedName(ND, ND->getDeclName());
- }
- void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
- void mangleSourceName(const IdentifierInfo *II);
- void manglePostfix(const DeclContext *DC, bool NoFunction=false);
- void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
- void mangleQualifiers(Qualifiers Quals, bool IsMember);
- void manglePointerQualifiers(Qualifiers Quals);
-
- void mangleUnscopedTemplateName(const TemplateDecl *ND);
- void mangleTemplateInstantiationName(const TemplateDecl *TD,
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
- void mangleObjCMethodName(const ObjCMethodDecl *MD);
- void mangleLocalName(const FunctionDecl *FD);
-
- void mangleArgumentType(QualType T, SourceRange Range);
-
- // Declare manglers for every type class.
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT)
-#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
- SourceRange Range);
-#include "clang/AST/TypeNodes.def"
-#undef ABSTRACT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef TYPE
-
- void mangleType(const TagType*);
- void mangleType(const FunctionType *T, const FunctionDecl *D,
- bool IsStructor, bool IsInstMethod);
- void mangleType(const ArrayType *T, bool IsGlobal);
- void mangleExtraDimensions(QualType T);
- void mangleFunctionClass(const FunctionDecl *FD);
- void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
- void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
- void mangleExpression(const Expr *E);
- void mangleThrowSpecification(const FunctionProtoType *T);
-
- void mangleTemplateArgs(
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
-
-};
-
-/// MicrosoftMangleContext - Overrides the default MangleContext for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftMangleContext : public MangleContext {
-public:
- MicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
- virtual bool shouldMangleDeclName(const NamedDecl *D);
- virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
- virtual void mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &);
- virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
- const ThisAdjustment &ThisAdjustment,
- raw_ostream &);
- virtual void mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &);
- virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &);
- virtual void mangleCXXRTTI(QualType T, raw_ostream &);
- virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
- virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
- raw_ostream &);
- virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
- raw_ostream &);
- virtual void mangleReferenceTemporary(const clang::VarDecl *,
- raw_ostream &);
-};
-
-}
-
-static bool isInCLinkageSpecification(const Decl *D) {
- D = D->getCanonicalDecl();
- for (const DeclContext *DC = D->getDeclContext();
- !DC->isTranslationUnit(); DC = DC->getParent()) {
- if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
- return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
- }
-
- return false;
-}
-
-bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
- // In C, functions with no attributes never need to be mangled. Fastpath them.
- if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
- return false;
-
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (D->hasAttr<AsmLabelAttr>())
- return true;
-
- // Clang's "overloadable" attribute extension to C/C++ implies name mangling
- // (always) as does passing a C++ member function and a function
- // whose name is not a simple identifier.
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
- !FD->getDeclName().isIdentifier()))
- return true;
-
- // Otherwise, no mangling is done outside C++ mode.
- if (!getASTContext().getLangOpts().CPlusPlus)
- return false;
-
- // Variables at global scope with internal linkage are not mangled.
- if (!FD) {
- const DeclContext *DC = D->getDeclContext();
- if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
- return false;
- }
-
- // C functions and "main" are not mangled.
- if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
- return false;
-
- return true;
-}
-
-void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
- StringRef Prefix) {
- // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
- // Therefore it's really important that we don't decorate the
- // name with leading underscores or leading/trailing at signs. So, by
- // default, we emit an asm marker at the start so we get the name right.
- // Callers can override this with a custom prefix.
-
- // Any decl can be declared with __asm("foo") on it, and this takes precedence
- // over all other naming in the .o file.
- if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
- // If we have an asm name, then we use it as the mangling.
- Out << '\01' << ALA->getLabel();
- return;
- }
-
- // <mangled-name> ::= ? <name> <type-encoding>
- Out << Prefix;
- mangleName(D);
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- mangleFunctionEncoding(FD);
- else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
- mangleVariableEncoding(VD);
- else {
- // TODO: Fields? Can MSVC even mangle them?
- // Issue a diagnostic for now.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this declaration yet");
- Diags.Report(D->getLocation(), DiagID)
- << D->getSourceRange();
- }
-}
-
-void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
- // <type-encoding> ::= <function-class> <function-type>
-
- // Don't mangle in the type if this isn't a decl we should typically mangle.
- if (!Context.shouldMangleDeclName(FD))
- return;
-
- // We should never ever see a FunctionNoProtoType at this point.
- // We don't even know how to mangle their types anyway :).
- const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
-
- bool InStructor = false, InInstMethod = false;
- const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- if (MD) {
- if (MD->isInstance())
- InInstMethod = true;
- if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
- InStructor = true;
- }
-
- // First, the function class.
- mangleFunctionClass(FD);
-
- mangleType(FT, FD, InStructor, InInstMethod);
-}
-
-void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
- // <type-encoding> ::= <storage-class> <variable-type>
- // <storage-class> ::= 0 # private static member
- // ::= 1 # protected static member
- // ::= 2 # public static member
- // ::= 3 # global
- // ::= 4 # static local
-
- // The first character in the encoding (after the name) is the storage class.
- if (VD->isStaticDataMember()) {
- // If it's a static member, it also encodes the access level.
- switch (VD->getAccess()) {
- default:
- case AS_private: Out << '0'; break;
- case AS_protected: Out << '1'; break;
- case AS_public: Out << '2'; break;
- }
- }
- else if (!VD->isStaticLocal())
- Out << '3';
- else
- Out << '4';
- // Now mangle the type.
- // <variable-type> ::= <type> <cvr-qualifiers>
- // ::= <type> <pointee-cvr-qualifiers> # pointers, references
- // Pointers and references are odd. The type of 'int * const foo;' gets
- // mangled as 'QAHA' instead of 'PAHB', for example.
- TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
- QualType Ty = TL.getType();
- if (Ty->isPointerType() || Ty->isReferenceType()) {
- mangleType(Ty, TL.getSourceRange());
- mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
- } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
- // Global arrays are funny, too.
- mangleType(AT, true);
- mangleQualifiers(Ty.getQualifiers(), false);
- } else {
- mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
- mangleQualifiers(Ty.getLocalQualifiers(), false);
- }
-}
-
-void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
- // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
- const DeclContext *DC = ND->getDeclContext();
-
- // Always start with the unqualified name.
- mangleUnqualifiedName(ND);
-
- // If this is an extern variable declared locally, the relevant DeclContext
- // is that of the containing namespace, or the translation unit.
- if (isa<FunctionDecl>(DC) && ND->hasLinkage())
- while (!DC->isNamespace() && !DC->isTranslationUnit())
- DC = DC->getParent();
-
- manglePostfix(DC);
-
- // Terminate the whole name with an '@'.
- Out << '@';
-}
-
-void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
- llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);
- APSNumber = Number;
- mangleNumber(APSNumber);
-}
-
-void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
- // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
- // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
- // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
- if (Value.isSigned() && Value.isNegative()) {
- Out << '?';
- mangleNumber(llvm::APSInt(Value.abs()));
- return;
- }
- llvm::APSInt Temp(Value);
- // There's a special shorter mangling for 0, but Microsoft
- // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
- if (Value.uge(1) && Value.ule(10)) {
- --Temp;
- Temp.print(Out, false);
- } else {
- // We have to build up the encoding in reverse order, so it will come
- // out right when we write it out.
- char Encoding[64];
- char *EndPtr = Encoding+sizeof(Encoding);
- char *CurPtr = EndPtr;
- llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());
- NibbleMask = 0xf;
- do {
- *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);
- Temp = Temp.lshr(4);
- } while (Temp != 0);
- Out.write(CurPtr, EndPtr-CurPtr);
- Out << '@';
- }
-}
-
-static const TemplateDecl *
-isTemplate(const NamedDecl *ND,
- SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // Check if we have a function template.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
- if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
- if (FD->getTemplateSpecializationArgsAsWritten()) {
- const ASTTemplateArgumentListInfo *ArgList =
- FD->getTemplateSpecializationArgsAsWritten();
- TemplateArgs.append(ArgList->getTemplateArgs(),
- ArgList->getTemplateArgs() +
- ArgList->NumTemplateArgs);
- } else {
- const TemplateArgumentList *ArgList =
- FD->getTemplateSpecializationArgs();
- TemplateArgumentListInfo LI;
- for (unsigned i = 0, e = ArgList->size(); i != e; ++i)
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i),
- FD->getTypeSourceInfo()));
- }
- return TD;
- }
- }
-
- // Check if we have a class template.
- if (const ClassTemplateSpecializationDecl *Spec =
- dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
- TypeSourceInfo *TSI = Spec->getTypeAsWritten();
- if (TSI) {
- TemplateSpecializationTypeLoc TSTL =
- cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
- TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc());
- for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i)
- TemplateArgs.push_back(TSTL.getArgLoc(i));
- } else {
- TemplateArgumentListInfo LI;
- const TemplateArgumentList &ArgList =
- Spec->getTemplateArgs();
- for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
- TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i],
- TemplateArgumentLocInfo()));
- }
- return Spec->getSpecializedTemplate();
- }
-
- return 0;
-}
-
-void
-MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
- DeclarationName Name) {
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <template-name>
- SmallVector<TemplateArgumentLoc, 2> TemplateArgs;
- // Check if we have a template.
- if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
- // We have a template.
- // Here comes the tricky thing: if we need to mangle something like
- // void foo(A::X<Y>, B::X<Y>),
- // the X<Y> part is aliased. However, if you need to mangle
- // void foo(A::X<A::Y>, A::X<B::Y>),
- // the A::X<> part is not aliased.
- // That said, from the mangler's perspective we have a structure like this:
- // namespace[s] -> type[ -> template-parameters]
- // but from the Clang perspective we have
- // type [ -> template-parameters]
- // \-> namespace[s]
- // What we do is we create a new mangler, mangle the same type (without
- // a namespace suffix) using the extra mangler with back references
- // disabled (to avoid infinite recursion) and then use the mangled type
- // name as a key to check the mangling of different types for aliasing.
-
- std::string BackReferenceKey;
- BackRefMap::iterator Found;
- if (UseNameBackReferences) {
- llvm::raw_string_ostream Stream(BackReferenceKey);
- MicrosoftCXXNameMangler Extra(Context, Stream);
- Extra.disableBackReferences();
- Extra.mangleUnqualifiedName(ND, Name);
- Stream.flush();
-
- Found = NameBackReferences.find(BackReferenceKey);
- }
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {
- mangleTemplateInstantiationName(TD, TemplateArgs);
- if (UseNameBackReferences && NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- NameBackReferences[BackReferenceKey] = Size;
- }
- } else {
- Out << Found->second;
- }
- return;
- }
-
- switch (Name.getNameKind()) {
- case DeclarationName::Identifier: {
- if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
- mangleSourceName(II);
- break;
- }
-
- // Otherwise, an anonymous entity. We must have a declaration.
- assert(ND && "mangling empty name without declaration");
-
- if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
- if (NS->isAnonymousNamespace()) {
- Out << "?A@";
- break;
- }
- }
-
- // We must have an anonymous struct.
- const TagDecl *TD = cast<TagDecl>(ND);
- if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
- assert(TD->getDeclContext() == D->getDeclContext() &&
- "Typedef should not be in another decl context!");
- assert(D->getDeclName().getAsIdentifierInfo() &&
- "Typedef was not named!");
- mangleSourceName(D->getDeclName().getAsIdentifierInfo());
- break;
- }
-
- // When VC encounters an anonymous type with no tag and no typedef,
- // it literally emits '<unnamed-tag>'.
- Out << "<unnamed-tag>";
- break;
- }
-
- case DeclarationName::ObjCZeroArgSelector:
- case DeclarationName::ObjCOneArgSelector:
- case DeclarationName::ObjCMultiArgSelector:
- llvm_unreachable("Can't mangle Objective-C selector names here!");
-
- case DeclarationName::CXXConstructorName:
- Out << "?0";
- break;
-
- case DeclarationName::CXXDestructorName:
- Out << "?1";
- break;
-
- case DeclarationName::CXXConversionFunctionName:
- // <operator-name> ::= ?B # (cast)
- // The target type is encoded as the return type.
- Out << "?B";
- break;
-
- case DeclarationName::CXXOperatorName:
- mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation());
- break;
-
- case DeclarationName::CXXLiteralOperatorName: {
- // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
- DiagnosticsEngine Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this literal operator yet");
- Diags.Report(ND->getLocation(), DiagID);
- break;
- }
-
- case DeclarationName::CXXUsingDirective:
- llvm_unreachable("Can't mangle a using directive name!");
- }
-}
-
-void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
- bool NoFunction) {
- // <postfix> ::= <unqualified-name> [<postfix>]
- // ::= <substitution> [<postfix>]
-
- if (!DC) return;
-
- while (isa<LinkageSpecDecl>(DC))
- DC = DC->getParent();
-
- if (DC->isTranslationUnit())
- return;
-
- if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
- Context.mangleBlock(BD, Out);
- Out << '@';
- return manglePostfix(DC->getParent(), NoFunction);
- }
-
- if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
- return;
- else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
- mangleObjCMethodName(Method);
- else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC))
- mangleLocalName(Func);
- else {
- mangleUnqualifiedName(cast<NamedDecl>(DC));
- manglePostfix(DC->getParent(), NoFunction);
- }
-}
-
-void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
- SourceLocation Loc) {
- switch (OO) {
- // ?0 # constructor
- // ?1 # destructor
- // <operator-name> ::= ?2 # new
- case OO_New: Out << "?2"; break;
- // <operator-name> ::= ?3 # delete
- case OO_Delete: Out << "?3"; break;
- // <operator-name> ::= ?4 # =
- case OO_Equal: Out << "?4"; break;
- // <operator-name> ::= ?5 # >>
- case OO_GreaterGreater: Out << "?5"; break;
- // <operator-name> ::= ?6 # <<
- case OO_LessLess: Out << "?6"; break;
- // <operator-name> ::= ?7 # !
- case OO_Exclaim: Out << "?7"; break;
- // <operator-name> ::= ?8 # ==
- case OO_EqualEqual: Out << "?8"; break;
- // <operator-name> ::= ?9 # !=
- case OO_ExclaimEqual: Out << "?9"; break;
- // <operator-name> ::= ?A # []
- case OO_Subscript: Out << "?A"; break;
- // ?B # conversion
- // <operator-name> ::= ?C # ->
- case OO_Arrow: Out << "?C"; break;
- // <operator-name> ::= ?D # *
- case OO_Star: Out << "?D"; break;
- // <operator-name> ::= ?E # ++
- case OO_PlusPlus: Out << "?E"; break;
- // <operator-name> ::= ?F # --
- case OO_MinusMinus: Out << "?F"; break;
- // <operator-name> ::= ?G # -
- case OO_Minus: Out << "?G"; break;
- // <operator-name> ::= ?H # +
- case OO_Plus: Out << "?H"; break;
- // <operator-name> ::= ?I # &
- case OO_Amp: Out << "?I"; break;
- // <operator-name> ::= ?J # ->*
- case OO_ArrowStar: Out << "?J"; break;
- // <operator-name> ::= ?K # /
- case OO_Slash: Out << "?K"; break;
- // <operator-name> ::= ?L # %
- case OO_Percent: Out << "?L"; break;
- // <operator-name> ::= ?M # <
- case OO_Less: Out << "?M"; break;
- // <operator-name> ::= ?N # <=
- case OO_LessEqual: Out << "?N"; break;
- // <operator-name> ::= ?O # >
- case OO_Greater: Out << "?O"; break;
- // <operator-name> ::= ?P # >=
- case OO_GreaterEqual: Out << "?P"; break;
- // <operator-name> ::= ?Q # ,
- case OO_Comma: Out << "?Q"; break;
- // <operator-name> ::= ?R # ()
- case OO_Call: Out << "?R"; break;
- // <operator-name> ::= ?S # ~
- case OO_Tilde: Out << "?S"; break;
- // <operator-name> ::= ?T # ^
- case OO_Caret: Out << "?T"; break;
- // <operator-name> ::= ?U # |
- case OO_Pipe: Out << "?U"; break;
- // <operator-name> ::= ?V # &&
- case OO_AmpAmp: Out << "?V"; break;
- // <operator-name> ::= ?W # ||
- case OO_PipePipe: Out << "?W"; break;
- // <operator-name> ::= ?X # *=
- case OO_StarEqual: Out << "?X"; break;
- // <operator-name> ::= ?Y # +=
- case OO_PlusEqual: Out << "?Y"; break;
- // <operator-name> ::= ?Z # -=
- case OO_MinusEqual: Out << "?Z"; break;
- // <operator-name> ::= ?_0 # /=
- case OO_SlashEqual: Out << "?_0"; break;
- // <operator-name> ::= ?_1 # %=
- case OO_PercentEqual: Out << "?_1"; break;
- // <operator-name> ::= ?_2 # >>=
- case OO_GreaterGreaterEqual: Out << "?_2"; break;
- // <operator-name> ::= ?_3 # <<=
- case OO_LessLessEqual: Out << "?_3"; break;
- // <operator-name> ::= ?_4 # &=
- case OO_AmpEqual: Out << "?_4"; break;
- // <operator-name> ::= ?_5 # |=
- case OO_PipeEqual: Out << "?_5"; break;
- // <operator-name> ::= ?_6 # ^=
- case OO_CaretEqual: Out << "?_6"; break;
- // ?_7 # vftable
- // ?_8 # vbtable
- // ?_9 # vcall
- // ?_A # typeof
- // ?_B # local static guard
- // ?_C # string
- // ?_D # vbase destructor
- // ?_E # vector deleting destructor
- // ?_F # default constructor closure
- // ?_G # scalar deleting destructor
- // ?_H # vector constructor iterator
- // ?_I # vector destructor iterator
- // ?_J # vector vbase constructor iterator
- // ?_K # virtual displacement map
- // ?_L # eh vector constructor iterator
- // ?_M # eh vector destructor iterator
- // ?_N # eh vector vbase constructor iterator
- // ?_O # copy constructor closure
- // ?_P<name> # udt returning <name>
- // ?_Q # <unknown>
- // ?_R0 # RTTI Type Descriptor
- // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)
- // ?_R2 # RTTI Base Class Array
- // ?_R3 # RTTI Class Hierarchy Descriptor
- // ?_R4 # RTTI Complete Object Locator
- // ?_S # local vftable
- // ?_T # local vftable constructor closure
- // <operator-name> ::= ?_U # new[]
- case OO_Array_New: Out << "?_U"; break;
- // <operator-name> ::= ?_V # delete[]
- case OO_Array_Delete: Out << "?_V"; break;
-
- case OO_Conditional: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this conditional operator yet");
- Diags.Report(Loc, DiagID);
- break;
- }
-
- case OO_None:
- case NUM_OVERLOADED_OPERATORS:
- llvm_unreachable("Not an overloaded operator");
- }
-}
-
-void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
- // <source name> ::= <identifier> @
- std::string key = II->getNameStart();
- BackRefMap::iterator Found;
- if (UseNameBackReferences)
- Found = NameBackReferences.find(key);
- if (!UseNameBackReferences || Found == NameBackReferences.end()) {
- Out << II->getName() << '@';
- if (UseNameBackReferences && NameBackReferences.size() < 10) {
- size_t Size = NameBackReferences.size();
- NameBackReferences[key] = Size;
- }
- } else {
- Out << Found->second;
- }
-}
-
-void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
- Context.mangleObjCMethodName(MD, Out);
-}
-
-// Find out how many function decls live above this one and return an integer
-// suitable for use as the number in a numbered anonymous scope.
-// TODO: Memoize.
-static unsigned getLocalNestingLevel(const FunctionDecl *FD) {
- const DeclContext *DC = FD->getParent();
- int level = 1;
-
- while (DC && !DC->isTranslationUnit()) {
- if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++;
- DC = DC->getParent();
- }
-
- return 2*level;
-}
-
-void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) {
- // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name>
- // <numbered-anonymous-scope> ::= ? <number>
- // Even though the name is rendered in reverse order (e.g.
- // A::B::C is rendered as C at B@A), VC numbers the scopes from outermost to
- // innermost. So a method bar in class C local to function foo gets mangled
- // as something like:
- // ?bar at C@?1??foo@@YAXXZ at QAEXXZ
- // This is more apparent when you have a type nested inside a method of a
- // type nested inside a function. A method baz in class D local to method
- // bar of class C local to function foo gets mangled as:
- // ?baz at D@?3??bar at C@?1??foo@@YAXXZ at QAEXXZ@QAEXXZ
- // This scheme is general enough to support GCC-style nested
- // functions. You could have a method baz of class C inside a function bar
- // inside a function foo, like so:
- // ?baz at C@?3??bar@?1??foo@@YAXXZ at YAXXZ@QAEXXZ
- int NestLevel = getLocalNestingLevel(FD);
- Out << '?';
- mangleNumber(NestLevel);
- Out << '?';
- mangle(FD, "?");
-}
-
-void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
- const TemplateDecl *TD,
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // <template-name> ::= <unscoped-template-name> <template-args>
- // ::= <substitution>
- // Always start with the unqualified name.
-
- // Templates have their own context for back references.
- ArgBackRefMap OuterArgsContext;
- BackRefMap OuterTemplateContext;
- NameBackReferences.swap(OuterTemplateContext);
- TypeBackReferences.swap(OuterArgsContext);
-
- mangleUnscopedTemplateName(TD);
- mangleTemplateArgs(TemplateArgs);
-
- // Restore the previous back reference contexts.
- NameBackReferences.swap(OuterTemplateContext);
- TypeBackReferences.swap(OuterArgsContext);
-}
-
-void
-MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
- // <unscoped-template-name> ::= ?$ <unqualified-name>
- Out << "?$";
- mangleUnqualifiedName(TD);
-}
-
-void
-MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
- bool IsBoolean) {
- // <integer-literal> ::= $0 <number>
- Out << "$0";
- // Make sure booleans are encoded as 0/1.
- if (IsBoolean && Value.getBoolValue())
- mangleNumber(1);
- else
- mangleNumber(Value);
-}
-
-void
-MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
- // See if this is a constant expression.
- llvm::APSInt Value;
- if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
- mangleIntegerLiteral(Value, E->getType()->isBooleanType());
- return;
- }
-
- // As bad as this diagnostic is, it's better than crashing.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot yet mangle expression type %0");
- Diags.Report(E->getExprLoc(), DiagID)
- << E->getStmtClassName() << E->getSourceRange();
-}
-
-void
-MicrosoftCXXNameMangler::mangleTemplateArgs(
- const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
- // <template-args> ::= {<type> | <integer-literal>}+ @
- unsigned NumTemplateArgs = TemplateArgs.size();
- for (unsigned i = 0; i < NumTemplateArgs; ++i) {
- const TemplateArgumentLoc &TAL = TemplateArgs[i];
- const TemplateArgument &TA = TAL.getArgument();
- switch (TA.getKind()) {
- case TemplateArgument::Null:
- llvm_unreachable("Can't mangle null template arguments!");
- case TemplateArgument::Type:
- mangleType(TA.getAsType(), TAL.getSourceRange());
- break;
- case TemplateArgument::Integral:
- mangleIntegerLiteral(TA.getAsIntegral(),
- TA.getIntegralType()->isBooleanType());
- break;
- case TemplateArgument::Expression:
- mangleExpression(TA.getAsExpr());
- break;
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- case TemplateArgument::Declaration:
- case TemplateArgument::NullPtr:
- case TemplateArgument::Pack: {
- // Issue a diagnostic.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|"
- "integral|template|template pack expansion|ERROR|parameter pack}0 "
- "template argument yet");
- Diags.Report(TAL.getLocation(), DiagID)
- << TA.getKind()
- << TAL.getSourceRange();
- }
- }
- }
- Out << '@';
-}
-
-void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
- bool IsMember) {
- // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
- // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only);
- // 'I' means __restrict (32/64-bit).
- // Note that the MSVC __restrict keyword isn't the same as the C99 restrict
- // keyword!
- // <base-cvr-qualifiers> ::= A # near
- // ::= B # near const
- // ::= C # near volatile
- // ::= D # near const volatile
- // ::= E # far (16-bit)
- // ::= F # far const (16-bit)
- // ::= G # far volatile (16-bit)
- // ::= H # far const volatile (16-bit)
- // ::= I # huge (16-bit)
- // ::= J # huge const (16-bit)
- // ::= K # huge volatile (16-bit)
- // ::= L # huge const volatile (16-bit)
- // ::= M <basis> # based
- // ::= N <basis> # based const
- // ::= O <basis> # based volatile
- // ::= P <basis> # based const volatile
- // ::= Q # near member
- // ::= R # near const member
- // ::= S # near volatile member
- // ::= T # near const volatile member
- // ::= U # far member (16-bit)
- // ::= V # far const member (16-bit)
- // ::= W # far volatile member (16-bit)
- // ::= X # far const volatile member (16-bit)
- // ::= Y # huge member (16-bit)
- // ::= Z # huge const member (16-bit)
- // ::= 0 # huge volatile member (16-bit)
- // ::= 1 # huge const volatile member (16-bit)
- // ::= 2 <basis> # based member
- // ::= 3 <basis> # based const member
- // ::= 4 <basis> # based volatile member
- // ::= 5 <basis> # based const volatile member
- // ::= 6 # near function (pointers only)
- // ::= 7 # far function (pointers only)
- // ::= 8 # near method (pointers only)
- // ::= 9 # far method (pointers only)
- // ::= _A <basis> # based function (pointers only)
- // ::= _B <basis> # based function (far?) (pointers only)
- // ::= _C <basis> # based method (pointers only)
- // ::= _D <basis> # based method (far?) (pointers only)
- // ::= _E # block (Clang)
- // <basis> ::= 0 # __based(void)
- // ::= 1 # __based(segment)?
- // ::= 2 <name> # __based(name)
- // ::= 3 # ?
- // ::= 4 # ?
- // ::= 5 # not really based
- bool HasConst = Quals.hasConst(),
- HasVolatile = Quals.hasVolatile();
- if (!IsMember) {
- if (HasConst && HasVolatile) {
- Out << 'D';
- } else if (HasVolatile) {
- Out << 'C';
- } else if (HasConst) {
- Out << 'B';
- } else {
- Out << 'A';
- }
- } else {
- if (HasConst && HasVolatile) {
- Out << 'T';
- } else if (HasVolatile) {
- Out << 'S';
- } else if (HasConst) {
- Out << 'R';
- } else {
- Out << 'Q';
- }
- }
-
- // FIXME: For now, just drop all extension qualifiers on the floor.
-}
-
-void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
- // <pointer-cvr-qualifiers> ::= P # no qualifiers
- // ::= Q # const
- // ::= R # volatile
- // ::= S # const volatile
- bool HasConst = Quals.hasConst(),
- HasVolatile = Quals.hasVolatile();
- if (HasConst && HasVolatile) {
- Out << 'S';
- } else if (HasVolatile) {
- Out << 'R';
- } else if (HasConst) {
- Out << 'Q';
- } else {
- Out << 'P';
- }
-}
-
-void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
- SourceRange Range) {
- void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
- ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
-
- if (Found == TypeBackReferences.end()) {
- size_t OutSizeBefore = Out.GetNumBytesInBuffer();
-
- mangleType(T, Range, false);
-
- // See if it's worth creating a back reference.
- // Only types longer than 1 character are considered
- // and only 10 back references slots are available:
- bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);
- if (LongerThanOneChar && TypeBackReferences.size() < 10) {
- size_t Size = TypeBackReferences.size();
- TypeBackReferences[TypePtr] = Size;
- }
- } else {
- Out << Found->second;
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
- bool MangleQualifiers) {
- // Only operate on the canonical type!
- T = getASTContext().getCanonicalType(T);
-
- Qualifiers Quals = T.getLocalQualifiers();
- // We have to mangle these now, while we still have enough information.
- if (T->isAnyPointerType() || T->isMemberPointerType() ||
- T->isBlockPointerType()) {
- manglePointerQualifiers(Quals);
- } else if (Quals && MangleQualifiers) {
- mangleQualifiers(Quals, false);
- }
-
- SplitQualType split = T.split();
- const Type *ty = split.Ty;
-
- // If we're mangling a qualified array type, push the qualifiers to
- // the element type.
- if (split.Quals && isa<ArrayType>(T)) {
- ty = Context.getASTContext().getAsArrayType(T);
- }
-
- switch (ty->getTypeClass()) {
-#define ABSTRACT_TYPE(CLASS, PARENT)
-#define NON_CANONICAL_TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
- return;
-#define TYPE(CLASS, PARENT) \
- case Type::CLASS: \
- mangleType(cast<CLASS##Type>(ty), Range); \
- break;
-#include "clang/AST/TypeNodes.def"
-#undef ABSTRACT_TYPE
-#undef NON_CANONICAL_TYPE
-#undef TYPE
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
- SourceRange Range) {
- // <type> ::= <builtin-type>
- // <builtin-type> ::= X # void
- // ::= C # signed char
- // ::= D # char
- // ::= E # unsigned char
- // ::= F # short
- // ::= G # unsigned short (or wchar_t if it's not a builtin)
- // ::= H # int
- // ::= I # unsigned int
- // ::= J # long
- // ::= K # unsigned long
- // L # <none>
- // ::= M # float
- // ::= N # double
- // ::= O # long double (__float80 is mangled differently)
- // ::= _J # long long, __int64
- // ::= _K # unsigned long long, __int64
- // ::= _L # __int128
- // ::= _M # unsigned __int128
- // ::= _N # bool
- // _O # <array in parameter>
- // ::= _T # __float80 (Intel)
- // ::= _W # wchar_t
- // ::= _Z # __float80 (Digital Mars)
- switch (T->getKind()) {
- case BuiltinType::Void: Out << 'X'; break;
- case BuiltinType::SChar: Out << 'C'; break;
- case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;
- case BuiltinType::UChar: Out << 'E'; break;
- case BuiltinType::Short: Out << 'F'; break;
- case BuiltinType::UShort: Out << 'G'; break;
- case BuiltinType::Int: Out << 'H'; break;
- case BuiltinType::UInt: Out << 'I'; break;
- case BuiltinType::Long: Out << 'J'; break;
- case BuiltinType::ULong: Out << 'K'; break;
- case BuiltinType::Float: Out << 'M'; break;
- case BuiltinType::Double: Out << 'N'; break;
- // TODO: Determine size and mangle accordingly
- case BuiltinType::LongDouble: Out << 'O'; break;
- case BuiltinType::LongLong: Out << "_J"; break;
- case BuiltinType::ULongLong: Out << "_K"; break;
- case BuiltinType::Int128: Out << "_L"; break;
- case BuiltinType::UInt128: Out << "_M"; break;
- case BuiltinType::Bool: Out << "_N"; break;
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U: Out << "_W"; break;
-
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- case BuiltinType::Dependent:
- 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;
-
- case BuiltinType::OCLImage1d: Out << "PAUocl_image1d@@"; break;
- case BuiltinType::OCLImage1dArray: Out << "PAUocl_image1darray@@"; break;
- case BuiltinType::OCLImage1dBuffer: Out << "PAUocl_image1dbuffer@@"; break;
- case BuiltinType::OCLImage2d: Out << "PAUocl_image2d@@"; break;
- case BuiltinType::OCLImage2dArray: Out << "PAUocl_image2darray@@"; break;
- case BuiltinType::OCLImage3d: Out << "PAUocl_image3d@@"; break;
-
- case BuiltinType::NullPtr: Out << "$$T"; break;
-
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Half: {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this built-in %0 type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << T->getName(Context.getASTContext().getPrintingPolicy())
- << Range;
- break;
- }
- }
-}
-
-// <type> ::= <function-type>
-void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
- SourceRange) {
- // Structors only appear in decls, so at this point we know it's not a
- // structor type.
- // FIXME: This may not be lambda-friendly.
- Out << "$$A6";
- mangleType(T, NULL, false, false);
-}
-void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
- SourceRange) {
- llvm_unreachable("Can't mangle K&R function prototypes");
-}
-
-void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
- const FunctionDecl *D,
- bool IsStructor,
- bool IsInstMethod) {
- // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
- // <return-type> <argument-list> <throw-spec>
- const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
-
- // If this is a C++ instance method, mangle the CVR qualifiers for the
- // this pointer.
- if (IsInstMethod)
- mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
-
- mangleCallingConvention(T, IsInstMethod);
-
- // <return-type> ::= <type>
- // ::= @ # structors (they have no declared return type)
- if (IsStructor)
- Out << '@';
- else {
- QualType Result = Proto->getResultType();
- const Type* RT = Result.getTypePtr();
- if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
- if (Result.hasQualifiers() || !RT->isBuiltinType())
- Out << '?';
- if (!RT->isBuiltinType() && !Result.hasQualifiers()) {
- // Lack of qualifiers for user types is mangled as 'A'.
- Out << 'A';
- }
- }
-
- // FIXME: Get the source range for the result type. Or, better yet,
- // implement the unimplemented stuff so we don't need accurate source
- // location info anymore :).
- mangleType(Result, SourceRange());
- }
-
- // <argument-list> ::= X # void
- // ::= <type>+ @
- // ::= <type>* Z # varargs
- if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
- Out << 'X';
- } else {
- if (D) {
- // If we got a decl, use the type-as-written to make sure arrays
- // get mangled right. Note that we can't rely on the TSI
- // existing if (for example) the parameter was synthesized.
- for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
- ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
- TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
- QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
- mangleArgumentType(Type, (*Parm)->getSourceRange());
- }
- } else {
- // Happens for function pointer type arguments for example.
- for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
- ArgEnd = Proto->arg_type_end();
- Arg != ArgEnd; ++Arg)
- mangleArgumentType(*Arg, SourceRange());
- }
- // <builtin-type> ::= Z # ellipsis
- if (Proto->isVariadic())
- Out << 'Z';
- else
- Out << '@';
- }
-
- mangleThrowSpecification(Proto);
-}
-
-void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
- // <function-class> ::= A # private: near
- // ::= B # private: far
- // ::= C # private: static near
- // ::= D # private: static far
- // ::= E # private: virtual near
- // ::= F # private: virtual far
- // ::= G # private: thunk near
- // ::= H # private: thunk far
- // ::= I # protected: near
- // ::= J # protected: far
- // ::= K # protected: static near
- // ::= L # protected: static far
- // ::= M # protected: virtual near
- // ::= N # protected: virtual far
- // ::= O # protected: thunk near
- // ::= P # protected: thunk far
- // ::= Q # public: near
- // ::= R # public: far
- // ::= S # public: static near
- // ::= T # public: static far
- // ::= U # public: virtual near
- // ::= V # public: virtual far
- // ::= W # public: thunk near
- // ::= X # public: thunk far
- // ::= Y # global near
- // ::= Z # global far
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
- switch (MD->getAccess()) {
- default:
- case AS_private:
- if (MD->isStatic())
- Out << 'C';
- else if (MD->isVirtual())
- Out << 'E';
- else
- Out << 'A';
- break;
- case AS_protected:
- if (MD->isStatic())
- Out << 'K';
- else if (MD->isVirtual())
- Out << 'M';
- else
- Out << 'I';
- break;
- case AS_public:
- if (MD->isStatic())
- Out << 'S';
- else if (MD->isVirtual())
- Out << 'U';
- else
- Out << 'Q';
- }
- } else
- Out << 'Y';
-}
-void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
- bool IsInstMethod) {
- // <calling-convention> ::= A # __cdecl
- // ::= B # __export __cdecl
- // ::= C # __pascal
- // ::= D # __export __pascal
- // ::= E # __thiscall
- // ::= F # __export __thiscall
- // ::= G # __stdcall
- // ::= H # __export __stdcall
- // ::= I # __fastcall
- // ::= J # __export __fastcall
- // The 'export' calling conventions are from a bygone era
- // (*cough*Win16*cough*) when functions were declared for export with
- // that keyword. (It didn't actually export them, it just made them so
- // that they could be in a DLL and somebody from another module could call
- // them.)
- CallingConv CC = T->getCallConv();
- if (CC == CC_Default) {
- if (IsInstMethod) {
- const FunctionProtoType *FPT =
- T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();
- bool isVariadic = FPT->isVariadic();
- CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
- } else {
- CC = CC_C;
- }
- }
- switch (CC) {
- default:
- llvm_unreachable("Unsupported CC for mangling");
- case CC_Default:
- case CC_C: Out << 'A'; break;
- case CC_X86Pascal: Out << 'C'; break;
- case CC_X86ThisCall: Out << 'E'; break;
- case CC_X86StdCall: Out << 'G'; break;
- case CC_X86FastCall: Out << 'I'; break;
- }
-}
-void MicrosoftCXXNameMangler::mangleThrowSpecification(
- const FunctionProtoType *FT) {
- // <throw-spec> ::= Z # throw(...) (default)
- // ::= @ # throw() or __declspec/__attribute__((nothrow))
- // ::= <type>+
- // NOTE: Since the Microsoft compiler ignores throw specifications, they are
- // all actually mangled as 'Z'. (They're ignored because their associated
- // functionality isn't implemented, and probably never will be.)
- Out << 'Z';
-}
-
-void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
- SourceRange Range) {
- // Probably should be mangled as a template instantiation; need to see what
- // VC does first.
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this unresolved dependent type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>
-// <union-type> ::= T <name>
-// <struct-type> ::= U <name>
-// <class-type> ::= V <name>
-// <enum-type> ::= W <size> <name>
-void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
- mangleType(cast<TagType>(T));
-}
-void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
- mangleType(cast<TagType>(T));
-}
-void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
- switch (T->getDecl()->getTagKind()) {
- case TTK_Union:
- Out << 'T';
- break;
- case TTK_Struct:
- case TTK_Interface:
- Out << 'U';
- break;
- case TTK_Class:
- Out << 'V';
- break;
- case TTK_Enum:
- Out << 'W';
- Out << getASTContext().getTypeSizeInChars(
- cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();
- break;
- }
- mangleName(T->getDecl());
-}
-
-// <type> ::= <array-type>
-// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
-// [Y <dimension-count> <dimension>+]
-// <element-type> # as global
-// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
-// <element-type> # as param
-// It's supposed to be the other way around, but for some strange reason, it
-// isn't. Today this behavior is retained for the sole purpose of backwards
-// compatibility.
-void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
- // This isn't a recursive mangling, so now we have to do it all in this
- // one call.
- if (IsGlobal) {
- manglePointerQualifiers(T->getElementType().getQualifiers());
- } else {
- Out << 'Q';
- }
- mangleExtraDimensions(T->getElementType());
-}
-void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
- SourceRange) {
- mangleType(cast<ArrayType>(T), false);
-}
-void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
- SmallVector<llvm::APInt, 3> Dimensions;
- for (;;) {
- if (const ConstantArrayType *CAT =
- getASTContext().getAsConstantArrayType(ElementTy)) {
- Dimensions.push_back(CAT->getSize());
- ElementTy = CAT->getElementType();
- } else if (ElementTy->isVariableArrayType()) {
- const VariableArrayType *VAT =
- getASTContext().getAsVariableArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this variable-length array yet");
- Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)
- << VAT->getBracketsRange();
- return;
- } else if (ElementTy->isDependentSizedArrayType()) {
- // The dependent expression has to be folded into a constant (TODO).
- const DependentSizedArrayType *DSAT =
- getASTContext().getAsDependentSizedArrayType(ElementTy);
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent-length array yet");
- Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
- << DSAT->getBracketsRange();
- return;
- } else if (ElementTy->isIncompleteArrayType()) continue;
- else break;
- }
- mangleQualifiers(ElementTy.getQualifiers(), false);
- // If there are any additional dimensions, mangle them now.
- if (Dimensions.size() > 0) {
- Out << 'Y';
- // <dimension-count> ::= <number> # number of extra dimensions
- mangleNumber(Dimensions.size());
- for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {
- mangleNumber(Dimensions[Dim].getLimitedValue());
- }
- }
- mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange());
-}
-
-// <type> ::= <pointer-to-member-type>
-// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
-// <class name> <type>
-void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
- SourceRange Range) {
- QualType PointeeType = T->getPointeeType();
- if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
- Out << '8';
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleType(FPT, NULL, false, true);
- } else {
- mangleQualifiers(PointeeType.getQualifiers(), true);
- mangleName(T->getClass()->castAs<RecordType>()->getDecl());
- mangleType(PointeeType.getLocalUnqualifiedType(), Range);
- }
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this template type parameter type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(
- const SubstTemplateTypeParmPackType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this substituted parameter pack yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-// <type> ::= <pointer-type>
-// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
- SourceRange Range) {
- QualType PointeeTy = T->getPointeeType();
- if (PointeeTy->isArrayType()) {
- // Pointers to arrays are mangled like arrays.
- mangleExtraDimensions(PointeeTy);
- } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
- // Function pointers are special.
- Out << '6';
- mangleType(FT, NULL, false, false);
- } else {
- mangleQualifiers(PointeeTy.getQualifiers(), false);
- mangleType(PointeeTy, Range, false);
- }
-}
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
- SourceRange Range) {
- // Object pointers never have qualifiers.
- Out << 'A';
- mangleType(T->getPointeeType(), Range);
-}
-
-// <type> ::= <reference-type>
-// <reference-type> ::= A <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
- SourceRange Range) {
- Out << 'A';
- QualType PointeeTy = T->getPointeeType();
- if (!PointeeTy.hasQualifiers())
- // Lack of qualifiers is mangled as 'A'.
- Out << 'A';
- mangleType(PointeeTy, Range);
-}
-
-// <type> ::= <r-value-reference-type>
-// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
-void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
- SourceRange Range) {
- Out << "$$Q";
- QualType PointeeTy = T->getPointeeType();
- if (!PointeeTy.hasQualifiers())
- // Lack of qualifiers is mangled as 'A'.
- Out << 'A';
- mangleType(PointeeTy, Range);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this complex number type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this extended vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent-sized extended vector type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,
- SourceRange) {
- // ObjC interfaces have structs underlying them.
- Out << 'U';
- mangleName(T->getDecl());
-}
-
-void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
- SourceRange Range) {
- // We don't allow overloading by different protocol qualification,
- // so mangling them isn't necessary.
- mangleType(T->getBaseType(), Range);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
- SourceRange Range) {
- Out << "_E";
-
- QualType pointee = T->getPointeeType();
- mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
-}
-
-void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this injected class name type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this template specialization type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent name type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(
- const DependentTemplateSpecializationType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this dependent template specialization type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this pack expansion yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this typeof(type) yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this typeof(expression) yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this decltype() yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this unary transform type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this 'auto' type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
- SourceRange Range) {
- DiagnosticsEngine &Diags = Context.getDiags();
- unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this C11 atomic type yet");
- Diags.Report(Range.getBegin(), DiagID)
- << Range;
-}
-
-void MicrosoftMangleContext::mangleName(const NamedDecl *D,
- raw_ostream &Out) {
- assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
- "Invalid mangleName() call, argument is not a variable or function!");
- assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
- "Invalid mangleName() call on 'structor decl!");
-
- PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
- getASTContext().getSourceManager(),
- "Mangling declaration");
-
- MicrosoftCXXNameMangler Mangler(*this, Out);
- return Mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
- const ThunkInfo &Thunk,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this method yet");
- getDiags().Report(MD->getLocation(), DiagID);
-}
-void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
- CXXDtorType Type,
- const ThisAdjustment &,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle thunk for this destructor yet");
- getDiags().Report(DD->getLocation(), DiagID);
-}
-void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
- raw_ostream &Out) {
- // <mangled-name> ::= ? <operator-name> <class-name> <storage-class>
- // <cvr-qualifiers> [<name>] @
- // <operator-name> ::= _7 # vftable
- // ::= _8 # vbtable
- // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
- // is always '6' for vftables and '7' for vbtables. (The difference is
- // beyond me.)
- // TODO: vbtables.
- MicrosoftCXXNameMangler Mangler(*this, Out);
- Mangler.getStream() << "\01??_7";
- Mangler.mangleName(RD);
- Mangler.getStream() << "6B";
- // TODO: If the class has more than one vtable, mangle in the class it came
- // from.
- Mangler.getStream() << '@';
-}
-void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
-}
-void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
- int64_t Offset,
- const CXXRecordDecl *Type,
- raw_ostream &) {
- llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
-}
-void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
- raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle RTTI descriptors for type %0 yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
-}
-void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
- raw_ostream &) {
- // FIXME: Give a location...
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle the name of type %0 into RTTI descriptors yet");
- getDiags().Report(DiagID)
- << T.getBaseTypeIdentifier();
-}
-void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
- CXXCtorType Type,
- raw_ostream & Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
- mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
- CXXDtorType Type,
- raw_ostream & Out) {
- MicrosoftCXXNameMangler mangler(*this, Out);
- mangler.mangle(D);
-}
-void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
- raw_ostream &) {
- unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "cannot mangle this reference temporary yet");
- getDiags().Report(VD->getLocation(), DiagID);
-}
-
-MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
- DiagnosticsEngine &Diags) {
- return new MicrosoftMangleContext(Context, Diags);
-}
+//===--- MicrosoftMangle.cpp - Microsoft Visual C++ Name Mangling ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides C++ name mangling targeting the Microsoft Visual C++ ABI.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/Mangle.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Basic/ABI.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include <map>
+
+using namespace clang;
+
+namespace {
+
+/// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftCXXNameMangler {
+ MangleContext &Context;
+ raw_ostream &Out;
+
+ // FIXME: audit the performance of BackRefMap as it might do way too many
+ // copying of strings.
+ typedef std::map<std::string, unsigned> BackRefMap;
+ BackRefMap NameBackReferences;
+ bool UseNameBackReferences;
+
+ typedef llvm::DenseMap<void*, unsigned> ArgBackRefMap;
+ ArgBackRefMap TypeBackReferences;
+
+ ASTContext &getASTContext() const { return Context.getASTContext(); }
+
+public:
+ MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
+ : Context(C), Out(Out_), UseNameBackReferences(true) { }
+
+ raw_ostream &getStream() const { return Out; }
+
+ void mangle(const NamedDecl *D, StringRef Prefix = "\01?");
+ void mangleName(const NamedDecl *ND);
+ void mangleFunctionEncoding(const FunctionDecl *FD);
+ void mangleVariableEncoding(const VarDecl *VD);
+ void mangleNumber(int64_t Number);
+ void mangleNumber(const llvm::APSInt &Value);
+ void mangleType(QualType T, SourceRange Range, bool MangleQualifiers = true);
+
+private:
+ void disableBackReferences() { UseNameBackReferences = false; }
+ void mangleUnqualifiedName(const NamedDecl *ND) {
+ mangleUnqualifiedName(ND, ND->getDeclName());
+ }
+ void mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name);
+ void mangleSourceName(const IdentifierInfo *II);
+ void manglePostfix(const DeclContext *DC, bool NoFunction=false);
+ void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc);
+ void mangleQualifiers(Qualifiers Quals, bool IsMember);
+ void manglePointerQualifiers(Qualifiers Quals);
+
+ void mangleUnscopedTemplateName(const TemplateDecl *ND);
+ void mangleTemplateInstantiationName(const TemplateDecl *TD,
+ const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
+ void mangleObjCMethodName(const ObjCMethodDecl *MD);
+ void mangleLocalName(const FunctionDecl *FD);
+
+ void mangleArgumentType(QualType T, SourceRange Range);
+
+ // Declare manglers for every type class.
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT)
+#define TYPE(CLASS, PARENT) void mangleType(const CLASS##Type *T, \
+ SourceRange Range);
+#include "clang/AST/TypeNodes.def"
+#undef ABSTRACT_TYPE
+#undef NON_CANONICAL_TYPE
+#undef TYPE
+
+ void mangleType(const TagType*);
+ void mangleType(const FunctionType *T, const FunctionDecl *D,
+ bool IsStructor, bool IsInstMethod);
+ void mangleType(const ArrayType *T, bool IsGlobal);
+ void mangleExtraDimensions(QualType T);
+ void mangleFunctionClass(const FunctionDecl *FD);
+ void mangleCallingConvention(const FunctionType *T, bool IsInstMethod = false);
+ void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
+ void mangleExpression(const Expr *E);
+ void mangleThrowSpecification(const FunctionProtoType *T);
+
+ void mangleTemplateArgs(
+ const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs);
+
+};
+
+/// MicrosoftMangleContext - Overrides the default MangleContext for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftMangleContext : public MangleContext {
+public:
+ MicrosoftMangleContext(ASTContext &Context,
+ DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
+ virtual bool shouldMangleDeclName(const NamedDecl *D);
+ virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
+ virtual void mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ raw_ostream &);
+ virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+ const ThisAdjustment &ThisAdjustment,
+ raw_ostream &);
+ virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+ raw_ostream &);
+ virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+ raw_ostream &);
+ virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &);
+ virtual void mangleCXXRTTI(QualType T, raw_ostream &);
+ virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
+ virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+ raw_ostream &);
+ virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+ raw_ostream &);
+ virtual void mangleReferenceTemporary(const clang::VarDecl *,
+ raw_ostream &);
+};
+
+}
+
+static bool isInCLinkageSpecification(const Decl *D) {
+ D = D->getCanonicalDecl();
+ for (const DeclContext *DC = D->getDeclContext();
+ !DC->isTranslationUnit(); DC = DC->getParent()) {
+ if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
+ return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
+ }
+
+ return false;
+}
+
+bool MicrosoftMangleContext::shouldMangleDeclName(const NamedDecl *D) {
+ // In C, functions with no attributes never need to be mangled. Fastpath them.
+ if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs())
+ return false;
+
+ // Any decl can be declared with __asm("foo") on it, and this takes precedence
+ // over all other naming in the .o file.
+ if (D->hasAttr<AsmLabelAttr>())
+ return true;
+
+ // Clang's "overloadable" attribute extension to C/C++ implies name mangling
+ // (always) as does passing a C++ member function and a function
+ // whose name is not a simple identifier.
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (FD && (FD->hasAttr<OverloadableAttr>() || isa<CXXMethodDecl>(FD) ||
+ !FD->getDeclName().isIdentifier()))
+ return true;
+
+ // Otherwise, no mangling is done outside C++ mode.
+ if (!getASTContext().getLangOpts().CPlusPlus)
+ return false;
+
+ // Variables at global scope with internal linkage are not mangled.
+ if (!FD) {
+ const DeclContext *DC = D->getDeclContext();
+ if (DC->isTranslationUnit() && D->getLinkage() == InternalLinkage)
+ return false;
+ }
+
+ // C functions and "main" are not mangled.
+ if ((FD && FD->isMain()) || isInCLinkageSpecification(D))
+ return false;
+
+ return true;
+}
+
+void MicrosoftCXXNameMangler::mangle(const NamedDecl *D,
+ StringRef Prefix) {
+ // MSVC doesn't mangle C++ names the same way it mangles extern "C" names.
+ // Therefore it's really important that we don't decorate the
+ // name with leading underscores or leading/trailing at signs. So, by
+ // default, we emit an asm marker at the start so we get the name right.
+ // Callers can override this with a custom prefix.
+
+ // Any decl can be declared with __asm("foo") on it, and this takes precedence
+ // over all other naming in the .o file.
+ if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
+ // If we have an asm name, then we use it as the mangling.
+ Out << '\01' << ALA->getLabel();
+ return;
+ }
+
+ // <mangled-name> ::= ? <name> <type-encoding>
+ Out << Prefix;
+ mangleName(D);
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ mangleFunctionEncoding(FD);
+ else if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ mangleVariableEncoding(VD);
+ else {
+ // TODO: Fields? Can MSVC even mangle them?
+ // Issue a diagnostic for now.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this declaration yet");
+ Diags.Report(D->getLocation(), DiagID)
+ << D->getSourceRange();
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
+ // <type-encoding> ::= <function-class> <function-type>
+
+ // Don't mangle in the type if this isn't a decl we should typically mangle.
+ if (!Context.shouldMangleDeclName(FD))
+ return;
+
+ // We should never ever see a FunctionNoProtoType at this point.
+ // We don't even know how to mangle their types anyway :).
+ const FunctionProtoType *FT = FD->getType()->castAs<FunctionProtoType>();
+
+ bool InStructor = false, InInstMethod = false;
+ const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (MD) {
+ if (MD->isInstance())
+ InInstMethod = true;
+ if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
+ InStructor = true;
+ }
+
+ // First, the function class.
+ mangleFunctionClass(FD);
+
+ mangleType(FT, FD, InStructor, InInstMethod);
+}
+
+void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
+ // <type-encoding> ::= <storage-class> <variable-type>
+ // <storage-class> ::= 0 # private static member
+ // ::= 1 # protected static member
+ // ::= 2 # public static member
+ // ::= 3 # global
+ // ::= 4 # static local
+
+ // The first character in the encoding (after the name) is the storage class.
+ if (VD->isStaticDataMember()) {
+ // If it's a static member, it also encodes the access level.
+ switch (VD->getAccess()) {
+ default:
+ case AS_private: Out << '0'; break;
+ case AS_protected: Out << '1'; break;
+ case AS_public: Out << '2'; break;
+ }
+ }
+ else if (!VD->isStaticLocal())
+ Out << '3';
+ else
+ Out << '4';
+ // Now mangle the type.
+ // <variable-type> ::= <type> <cvr-qualifiers>
+ // ::= <type> <pointee-cvr-qualifiers> # pointers, references
+ // Pointers and references are odd. The type of 'int * const foo;' gets
+ // mangled as 'QAHA' instead of 'PAHB', for example.
+ TypeLoc TL = VD->getTypeSourceInfo()->getTypeLoc();
+ QualType Ty = TL.getType();
+ if (Ty->isPointerType() || Ty->isReferenceType()) {
+ mangleType(Ty, TL.getSourceRange());
+ mangleQualifiers(Ty->getPointeeType().getQualifiers(), false);
+ } else if (const ArrayType *AT = getASTContext().getAsArrayType(Ty)) {
+ // Global arrays are funny, too.
+ mangleType(AT, true);
+ mangleQualifiers(Ty.getQualifiers(), false);
+ } else {
+ mangleType(Ty.getLocalUnqualifiedType(), TL.getSourceRange());
+ mangleQualifiers(Ty.getLocalQualifiers(), false);
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleName(const NamedDecl *ND) {
+ // <name> ::= <unscoped-name> {[<named-scope>]+ | [<nested-name>]}? @
+ const DeclContext *DC = ND->getDeclContext();
+
+ // Always start with the unqualified name.
+ mangleUnqualifiedName(ND);
+
+ // If this is an extern variable declared locally, the relevant DeclContext
+ // is that of the containing namespace, or the translation unit.
+ if (isa<FunctionDecl>(DC) && ND->hasLinkage())
+ while (!DC->isNamespace() && !DC->isTranslationUnit())
+ DC = DC->getParent();
+
+ manglePostfix(DC);
+
+ // Terminate the whole name with an '@'.
+ Out << '@';
+}
+
+void MicrosoftCXXNameMangler::mangleNumber(int64_t Number) {
+ llvm::APSInt APSNumber(/*BitWidth=*/64, /*isUnsigned=*/false);
+ APSNumber = Number;
+ mangleNumber(APSNumber);
+}
+
+void MicrosoftCXXNameMangler::mangleNumber(const llvm::APSInt &Value) {
+ // <number> ::= [?] <decimal digit> # 1 <= Number <= 10
+ // ::= [?] <hex digit>+ @ # 0 or > 9; A = 0, B = 1, etc...
+ // ::= [?] @ # 0 (alternate mangling, not emitted by VC)
+ if (Value.isSigned() && Value.isNegative()) {
+ Out << '?';
+ mangleNumber(llvm::APSInt(Value.abs()));
+ return;
+ }
+ llvm::APSInt Temp(Value);
+ // There's a special shorter mangling for 0, but Microsoft
+ // chose not to use it. Instead, 0 gets mangled as "A@". Oh well...
+ if (Value.uge(1) && Value.ule(10)) {
+ --Temp;
+ Temp.print(Out, false);
+ } else {
+ // We have to build up the encoding in reverse order, so it will come
+ // out right when we write it out.
+ char Encoding[64];
+ char *EndPtr = Encoding+sizeof(Encoding);
+ char *CurPtr = EndPtr;
+ llvm::APSInt NibbleMask(Value.getBitWidth(), Value.isUnsigned());
+ NibbleMask = 0xf;
+ do {
+ *--CurPtr = 'A' + Temp.And(NibbleMask).getLimitedValue(0xf);
+ Temp = Temp.lshr(4);
+ } while (Temp != 0);
+ Out.write(CurPtr, EndPtr-CurPtr);
+ Out << '@';
+ }
+}
+
+static const TemplateDecl *
+isTemplate(const NamedDecl *ND,
+ SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ // Check if we have a function template.
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)){
+ if (const TemplateDecl *TD = FD->getPrimaryTemplate()) {
+ if (FD->getTemplateSpecializationArgsAsWritten()) {
+ const ASTTemplateArgumentListInfo *ArgList =
+ FD->getTemplateSpecializationArgsAsWritten();
+ TemplateArgs.append(ArgList->getTemplateArgs(),
+ ArgList->getTemplateArgs() +
+ ArgList->NumTemplateArgs);
+ } else {
+ const TemplateArgumentList *ArgList =
+ FD->getTemplateSpecializationArgs();
+ TemplateArgumentListInfo LI;
+ for (unsigned i = 0, e = ArgList->size(); i != e; ++i)
+ TemplateArgs.push_back(TemplateArgumentLoc(ArgList->get(i),
+ FD->getTypeSourceInfo()));
+ }
+ return TD;
+ }
+ }
+
+ // Check if we have a class template.
+ if (const ClassTemplateSpecializationDecl *Spec =
+ dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
+ TypeSourceInfo *TSI = Spec->getTypeAsWritten();
+ if (TSI) {
+ TemplateSpecializationTypeLoc TSTL =
+ cast<TemplateSpecializationTypeLoc>(TSI->getTypeLoc());
+ TemplateArgumentListInfo LI(TSTL.getLAngleLoc(), TSTL.getRAngleLoc());
+ for (unsigned i = 0, e = TSTL.getNumArgs(); i != e; ++i)
+ TemplateArgs.push_back(TSTL.getArgLoc(i));
+ } else {
+ TemplateArgumentListInfo LI;
+ const TemplateArgumentList &ArgList =
+ Spec->getTemplateArgs();
+ for (unsigned i = 0, e = ArgList.size(); i != e; ++i)
+ TemplateArgs.push_back(TemplateArgumentLoc(ArgList[i],
+ TemplateArgumentLocInfo()));
+ }
+ return Spec->getSpecializedTemplate();
+ }
+
+ return 0;
+}
+
+void
+MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
+ DeclarationName Name) {
+ // <unqualified-name> ::= <operator-name>
+ // ::= <ctor-dtor-name>
+ // ::= <source-name>
+ // ::= <template-name>
+ SmallVector<TemplateArgumentLoc, 2> TemplateArgs;
+ // Check if we have a template.
+ if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
+ // We have a template.
+ // Here comes the tricky thing: if we need to mangle something like
+ // void foo(A::X<Y>, B::X<Y>),
+ // the X<Y> part is aliased. However, if you need to mangle
+ // void foo(A::X<A::Y>, A::X<B::Y>),
+ // the A::X<> part is not aliased.
+ // That said, from the mangler's perspective we have a structure like this:
+ // namespace[s] -> type[ -> template-parameters]
+ // but from the Clang perspective we have
+ // type [ -> template-parameters]
+ // \-> namespace[s]
+ // What we do is we create a new mangler, mangle the same type (without
+ // a namespace suffix) using the extra mangler with back references
+ // disabled (to avoid infinite recursion) and then use the mangled type
+ // name as a key to check the mangling of different types for aliasing.
+
+ std::string BackReferenceKey;
+ BackRefMap::iterator Found;
+ if (UseNameBackReferences) {
+ llvm::raw_string_ostream Stream(BackReferenceKey);
+ MicrosoftCXXNameMangler Extra(Context, Stream);
+ Extra.disableBackReferences();
+ Extra.mangleUnqualifiedName(ND, Name);
+ Stream.flush();
+
+ Found = NameBackReferences.find(BackReferenceKey);
+ }
+ if (!UseNameBackReferences || Found == NameBackReferences.end()) {
+ mangleTemplateInstantiationName(TD, TemplateArgs);
+ if (UseNameBackReferences && NameBackReferences.size() < 10) {
+ size_t Size = NameBackReferences.size();
+ NameBackReferences[BackReferenceKey] = Size;
+ }
+ } else {
+ Out << Found->second;
+ }
+ return;
+ }
+
+ switch (Name.getNameKind()) {
+ case DeclarationName::Identifier: {
+ if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) {
+ mangleSourceName(II);
+ break;
+ }
+
+ // Otherwise, an anonymous entity. We must have a declaration.
+ assert(ND && "mangling empty name without declaration");
+
+ if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) {
+ if (NS->isAnonymousNamespace()) {
+ Out << "?A@";
+ break;
+ }
+ }
+
+ // We must have an anonymous struct.
+ const TagDecl *TD = cast<TagDecl>(ND);
+ if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) {
+ assert(TD->getDeclContext() == D->getDeclContext() &&
+ "Typedef should not be in another decl context!");
+ assert(D->getDeclName().getAsIdentifierInfo() &&
+ "Typedef was not named!");
+ mangleSourceName(D->getDeclName().getAsIdentifierInfo());
+ break;
+ }
+
+ // When VC encounters an anonymous type with no tag and no typedef,
+ // it literally emits '<unnamed-tag>'.
+ Out << "<unnamed-tag>";
+ break;
+ }
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ llvm_unreachable("Can't mangle Objective-C selector names here!");
+
+ case DeclarationName::CXXConstructorName:
+ Out << "?0";
+ break;
+
+ case DeclarationName::CXXDestructorName:
+ Out << "?1";
+ break;
+
+ case DeclarationName::CXXConversionFunctionName:
+ // <operator-name> ::= ?B # (cast)
+ // The target type is encoded as the return type.
+ Out << "?B";
+ break;
+
+ case DeclarationName::CXXOperatorName:
+ mangleOperatorName(Name.getCXXOverloadedOperator(), ND->getLocation());
+ break;
+
+ case DeclarationName::CXXLiteralOperatorName: {
+ // FIXME: Was this added in VS2010? Does MS even know how to mangle this?
+ DiagnosticsEngine Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this literal operator yet");
+ Diags.Report(ND->getLocation(), DiagID);
+ break;
+ }
+
+ case DeclarationName::CXXUsingDirective:
+ llvm_unreachable("Can't mangle a using directive name!");
+ }
+}
+
+void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC,
+ bool NoFunction) {
+ // <postfix> ::= <unqualified-name> [<postfix>]
+ // ::= <substitution> [<postfix>]
+
+ if (!DC) return;
+
+ while (isa<LinkageSpecDecl>(DC))
+ DC = DC->getParent();
+
+ if (DC->isTranslationUnit())
+ return;
+
+ if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC)) {
+ Context.mangleBlock(BD, Out);
+ Out << '@';
+ return manglePostfix(DC->getParent(), NoFunction);
+ }
+
+ if (NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
+ return;
+ else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+ mangleObjCMethodName(Method);
+ else if (const FunctionDecl *Func = dyn_cast<FunctionDecl>(DC))
+ mangleLocalName(Func);
+ else {
+ mangleUnqualifiedName(cast<NamedDecl>(DC));
+ manglePostfix(DC->getParent(), NoFunction);
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO,
+ SourceLocation Loc) {
+ switch (OO) {
+ // ?0 # constructor
+ // ?1 # destructor
+ // <operator-name> ::= ?2 # new
+ case OO_New: Out << "?2"; break;
+ // <operator-name> ::= ?3 # delete
+ case OO_Delete: Out << "?3"; break;
+ // <operator-name> ::= ?4 # =
+ case OO_Equal: Out << "?4"; break;
+ // <operator-name> ::= ?5 # >>
+ case OO_GreaterGreater: Out << "?5"; break;
+ // <operator-name> ::= ?6 # <<
+ case OO_LessLess: Out << "?6"; break;
+ // <operator-name> ::= ?7 # !
+ case OO_Exclaim: Out << "?7"; break;
+ // <operator-name> ::= ?8 # ==
+ case OO_EqualEqual: Out << "?8"; break;
+ // <operator-name> ::= ?9 # !=
+ case OO_ExclaimEqual: Out << "?9"; break;
+ // <operator-name> ::= ?A # []
+ case OO_Subscript: Out << "?A"; break;
+ // ?B # conversion
+ // <operator-name> ::= ?C # ->
+ case OO_Arrow: Out << "?C"; break;
+ // <operator-name> ::= ?D # *
+ case OO_Star: Out << "?D"; break;
+ // <operator-name> ::= ?E # ++
+ case OO_PlusPlus: Out << "?E"; break;
+ // <operator-name> ::= ?F # --
+ case OO_MinusMinus: Out << "?F"; break;
+ // <operator-name> ::= ?G # -
+ case OO_Minus: Out << "?G"; break;
+ // <operator-name> ::= ?H # +
+ case OO_Plus: Out << "?H"; break;
+ // <operator-name> ::= ?I # &
+ case OO_Amp: Out << "?I"; break;
+ // <operator-name> ::= ?J # ->*
+ case OO_ArrowStar: Out << "?J"; break;
+ // <operator-name> ::= ?K # /
+ case OO_Slash: Out << "?K"; break;
+ // <operator-name> ::= ?L # %
+ case OO_Percent: Out << "?L"; break;
+ // <operator-name> ::= ?M # <
+ case OO_Less: Out << "?M"; break;
+ // <operator-name> ::= ?N # <=
+ case OO_LessEqual: Out << "?N"; break;
+ // <operator-name> ::= ?O # >
+ case OO_Greater: Out << "?O"; break;
+ // <operator-name> ::= ?P # >=
+ case OO_GreaterEqual: Out << "?P"; break;
+ // <operator-name> ::= ?Q # ,
+ case OO_Comma: Out << "?Q"; break;
+ // <operator-name> ::= ?R # ()
+ case OO_Call: Out << "?R"; break;
+ // <operator-name> ::= ?S # ~
+ case OO_Tilde: Out << "?S"; break;
+ // <operator-name> ::= ?T # ^
+ case OO_Caret: Out << "?T"; break;
+ // <operator-name> ::= ?U # |
+ case OO_Pipe: Out << "?U"; break;
+ // <operator-name> ::= ?V # &&
+ case OO_AmpAmp: Out << "?V"; break;
+ // <operator-name> ::= ?W # ||
+ case OO_PipePipe: Out << "?W"; break;
+ // <operator-name> ::= ?X # *=
+ case OO_StarEqual: Out << "?X"; break;
+ // <operator-name> ::= ?Y # +=
+ case OO_PlusEqual: Out << "?Y"; break;
+ // <operator-name> ::= ?Z # -=
+ case OO_MinusEqual: Out << "?Z"; break;
+ // <operator-name> ::= ?_0 # /=
+ case OO_SlashEqual: Out << "?_0"; break;
+ // <operator-name> ::= ?_1 # %=
+ case OO_PercentEqual: Out << "?_1"; break;
+ // <operator-name> ::= ?_2 # >>=
+ case OO_GreaterGreaterEqual: Out << "?_2"; break;
+ // <operator-name> ::= ?_3 # <<=
+ case OO_LessLessEqual: Out << "?_3"; break;
+ // <operator-name> ::= ?_4 # &=
+ case OO_AmpEqual: Out << "?_4"; break;
+ // <operator-name> ::= ?_5 # |=
+ case OO_PipeEqual: Out << "?_5"; break;
+ // <operator-name> ::= ?_6 # ^=
+ case OO_CaretEqual: Out << "?_6"; break;
+ // ?_7 # vftable
+ // ?_8 # vbtable
+ // ?_9 # vcall
+ // ?_A # typeof
+ // ?_B # local static guard
+ // ?_C # string
+ // ?_D # vbase destructor
+ // ?_E # vector deleting destructor
+ // ?_F # default constructor closure
+ // ?_G # scalar deleting destructor
+ // ?_H # vector constructor iterator
+ // ?_I # vector destructor iterator
+ // ?_J # vector vbase constructor iterator
+ // ?_K # virtual displacement map
+ // ?_L # eh vector constructor iterator
+ // ?_M # eh vector destructor iterator
+ // ?_N # eh vector vbase constructor iterator
+ // ?_O # copy constructor closure
+ // ?_P<name> # udt returning <name>
+ // ?_Q # <unknown>
+ // ?_R0 # RTTI Type Descriptor
+ // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)
+ // ?_R2 # RTTI Base Class Array
+ // ?_R3 # RTTI Class Hierarchy Descriptor
+ // ?_R4 # RTTI Complete Object Locator
+ // ?_S # local vftable
+ // ?_T # local vftable constructor closure
+ // <operator-name> ::= ?_U # new[]
+ case OO_Array_New: Out << "?_U"; break;
+ // <operator-name> ::= ?_V # delete[]
+ case OO_Array_Delete: Out << "?_V"; break;
+
+ case OO_Conditional: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this conditional operator yet");
+ Diags.Report(Loc, DiagID);
+ break;
+ }
+
+ case OO_None:
+ case NUM_OVERLOADED_OPERATORS:
+ llvm_unreachable("Not an overloaded operator");
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
+ // <source name> ::= <identifier> @
+ std::string key = II->getNameStart();
+ BackRefMap::iterator Found;
+ if (UseNameBackReferences)
+ Found = NameBackReferences.find(key);
+ if (!UseNameBackReferences || Found == NameBackReferences.end()) {
+ Out << II->getName() << '@';
+ if (UseNameBackReferences && NameBackReferences.size() < 10) {
+ size_t Size = NameBackReferences.size();
+ NameBackReferences[key] = Size;
+ }
+ } else {
+ Out << Found->second;
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) {
+ Context.mangleObjCMethodName(MD, Out);
+}
+
+// Find out how many function decls live above this one and return an integer
+// suitable for use as the number in a numbered anonymous scope.
+// TODO: Memoize.
+static unsigned getLocalNestingLevel(const FunctionDecl *FD) {
+ const DeclContext *DC = FD->getParent();
+ int level = 1;
+
+ while (DC && !DC->isTranslationUnit()) {
+ if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) level++;
+ DC = DC->getParent();
+ }
+
+ return 2*level;
+}
+
+void MicrosoftCXXNameMangler::mangleLocalName(const FunctionDecl *FD) {
+ // <nested-name> ::= <numbered-anonymous-scope> ? <mangled-name>
+ // <numbered-anonymous-scope> ::= ? <number>
+ // Even though the name is rendered in reverse order (e.g.
+ // A::B::C is rendered as C at B@A), VC numbers the scopes from outermost to
+ // innermost. So a method bar in class C local to function foo gets mangled
+ // as something like:
+ // ?bar at C@?1??foo@@YAXXZ at QAEXXZ
+ // This is more apparent when you have a type nested inside a method of a
+ // type nested inside a function. A method baz in class D local to method
+ // bar of class C local to function foo gets mangled as:
+ // ?baz at D@?3??bar at C@?1??foo@@YAXXZ at QAEXXZ@QAEXXZ
+ // This scheme is general enough to support GCC-style nested
+ // functions. You could have a method baz of class C inside a function bar
+ // inside a function foo, like so:
+ // ?baz at C@?3??bar@?1??foo@@YAXXZ at YAXXZ@QAEXXZ
+ int NestLevel = getLocalNestingLevel(FD);
+ Out << '?';
+ mangleNumber(NestLevel);
+ Out << '?';
+ mangle(FD, "?");
+}
+
+void MicrosoftCXXNameMangler::mangleTemplateInstantiationName(
+ const TemplateDecl *TD,
+ const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ // <template-name> ::= <unscoped-template-name> <template-args>
+ // ::= <substitution>
+ // Always start with the unqualified name.
+
+ // Templates have their own context for back references.
+ ArgBackRefMap OuterArgsContext;
+ BackRefMap OuterTemplateContext;
+ NameBackReferences.swap(OuterTemplateContext);
+ TypeBackReferences.swap(OuterArgsContext);
+
+ mangleUnscopedTemplateName(TD);
+ mangleTemplateArgs(TemplateArgs);
+
+ // Restore the previous back reference contexts.
+ NameBackReferences.swap(OuterTemplateContext);
+ TypeBackReferences.swap(OuterArgsContext);
+}
+
+void
+MicrosoftCXXNameMangler::mangleUnscopedTemplateName(const TemplateDecl *TD) {
+ // <unscoped-template-name> ::= ?$ <unqualified-name>
+ Out << "?$";
+ mangleUnqualifiedName(TD);
+}
+
+void
+MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value,
+ bool IsBoolean) {
+ // <integer-literal> ::= $0 <number>
+ Out << "$0";
+ // Make sure booleans are encoded as 0/1.
+ if (IsBoolean && Value.getBoolValue())
+ mangleNumber(1);
+ else
+ mangleNumber(Value);
+}
+
+void
+MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
+ // See if this is a constant expression.
+ llvm::APSInt Value;
+ if (E->isIntegerConstantExpr(Value, Context.getASTContext())) {
+ mangleIntegerLiteral(Value, E->getType()->isBooleanType());
+ return;
+ }
+
+ // As bad as this diagnostic is, it's better than crashing.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot yet mangle expression type %0");
+ Diags.Report(E->getExprLoc(), DiagID)
+ << E->getStmtClassName() << E->getSourceRange();
+}
+
+void
+MicrosoftCXXNameMangler::mangleTemplateArgs(
+ const SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ // <template-args> ::= {<type> | <integer-literal>}+ @
+ unsigned NumTemplateArgs = TemplateArgs.size();
+ for (unsigned i = 0; i < NumTemplateArgs; ++i) {
+ const TemplateArgumentLoc &TAL = TemplateArgs[i];
+ const TemplateArgument &TA = TAL.getArgument();
+ switch (TA.getKind()) {
+ case TemplateArgument::Null:
+ llvm_unreachable("Can't mangle null template arguments!");
+ case TemplateArgument::Type:
+ mangleType(TA.getAsType(), TAL.getSourceRange());
+ break;
+ case TemplateArgument::Integral:
+ mangleIntegerLiteral(TA.getAsIntegral(),
+ TA.getIntegralType()->isBooleanType());
+ break;
+ case TemplateArgument::Expression:
+ mangleExpression(TA.getAsExpr());
+ break;
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::NullPtr:
+ case TemplateArgument::Pack: {
+ // Issue a diagnostic.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this %select{ERROR|ERROR|pointer/reference|nullptr|"
+ "integral|template|template pack expansion|ERROR|parameter pack}0 "
+ "template argument yet");
+ Diags.Report(TAL.getLocation(), DiagID)
+ << TA.getKind()
+ << TAL.getSourceRange();
+ }
+ }
+ }
+ Out << '@';
+}
+
+void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
+ bool IsMember) {
+ // <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
+ // 'E' means __ptr64 (32-bit only); 'F' means __unaligned (32/64-bit only);
+ // 'I' means __restrict (32/64-bit).
+ // Note that the MSVC __restrict keyword isn't the same as the C99 restrict
+ // keyword!
+ // <base-cvr-qualifiers> ::= A # near
+ // ::= B # near const
+ // ::= C # near volatile
+ // ::= D # near const volatile
+ // ::= E # far (16-bit)
+ // ::= F # far const (16-bit)
+ // ::= G # far volatile (16-bit)
+ // ::= H # far const volatile (16-bit)
+ // ::= I # huge (16-bit)
+ // ::= J # huge const (16-bit)
+ // ::= K # huge volatile (16-bit)
+ // ::= L # huge const volatile (16-bit)
+ // ::= M <basis> # based
+ // ::= N <basis> # based const
+ // ::= O <basis> # based volatile
+ // ::= P <basis> # based const volatile
+ // ::= Q # near member
+ // ::= R # near const member
+ // ::= S # near volatile member
+ // ::= T # near const volatile member
+ // ::= U # far member (16-bit)
+ // ::= V # far const member (16-bit)
+ // ::= W # far volatile member (16-bit)
+ // ::= X # far const volatile member (16-bit)
+ // ::= Y # huge member (16-bit)
+ // ::= Z # huge const member (16-bit)
+ // ::= 0 # huge volatile member (16-bit)
+ // ::= 1 # huge const volatile member (16-bit)
+ // ::= 2 <basis> # based member
+ // ::= 3 <basis> # based const member
+ // ::= 4 <basis> # based volatile member
+ // ::= 5 <basis> # based const volatile member
+ // ::= 6 # near function (pointers only)
+ // ::= 7 # far function (pointers only)
+ // ::= 8 # near method (pointers only)
+ // ::= 9 # far method (pointers only)
+ // ::= _A <basis> # based function (pointers only)
+ // ::= _B <basis> # based function (far?) (pointers only)
+ // ::= _C <basis> # based method (pointers only)
+ // ::= _D <basis> # based method (far?) (pointers only)
+ // ::= _E # block (Clang)
+ // <basis> ::= 0 # __based(void)
+ // ::= 1 # __based(segment)?
+ // ::= 2 <name> # __based(name)
+ // ::= 3 # ?
+ // ::= 4 # ?
+ // ::= 5 # not really based
+ bool HasConst = Quals.hasConst(),
+ HasVolatile = Quals.hasVolatile();
+ if (!IsMember) {
+ if (HasConst && HasVolatile) {
+ Out << 'D';
+ } else if (HasVolatile) {
+ Out << 'C';
+ } else if (HasConst) {
+ Out << 'B';
+ } else {
+ Out << 'A';
+ }
+ } else {
+ if (HasConst && HasVolatile) {
+ Out << 'T';
+ } else if (HasVolatile) {
+ Out << 'S';
+ } else if (HasConst) {
+ Out << 'R';
+ } else {
+ Out << 'Q';
+ }
+ }
+
+ // FIXME: For now, just drop all extension qualifiers on the floor.
+}
+
+void MicrosoftCXXNameMangler::manglePointerQualifiers(Qualifiers Quals) {
+ // <pointer-cvr-qualifiers> ::= P # no qualifiers
+ // ::= Q # const
+ // ::= R # volatile
+ // ::= S # const volatile
+ bool HasConst = Quals.hasConst(),
+ HasVolatile = Quals.hasVolatile();
+ if (HasConst && HasVolatile) {
+ Out << 'S';
+ } else if (HasVolatile) {
+ Out << 'R';
+ } else if (HasConst) {
+ Out << 'Q';
+ } else {
+ Out << 'P';
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleArgumentType(QualType T,
+ SourceRange Range) {
+ void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr();
+ ArgBackRefMap::iterator Found = TypeBackReferences.find(TypePtr);
+
+ if (Found == TypeBackReferences.end()) {
+ size_t OutSizeBefore = Out.GetNumBytesInBuffer();
+
+ mangleType(T, Range, false);
+
+ // See if it's worth creating a back reference.
+ // Only types longer than 1 character are considered
+ // and only 10 back references slots are available:
+ bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1);
+ if (LongerThanOneChar && TypeBackReferences.size() < 10) {
+ size_t Size = TypeBackReferences.size();
+ TypeBackReferences[TypePtr] = Size;
+ }
+ } else {
+ Out << Found->second;
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
+ bool MangleQualifiers) {
+ // Only operate on the canonical type!
+ T = getASTContext().getCanonicalType(T);
+
+ Qualifiers Quals = T.getLocalQualifiers();
+ // We have to mangle these now, while we still have enough information.
+ if (T->isAnyPointerType() || T->isMemberPointerType() ||
+ T->isBlockPointerType()) {
+ manglePointerQualifiers(Quals);
+ } else if (Quals && MangleQualifiers) {
+ mangleQualifiers(Quals, false);
+ }
+
+ SplitQualType split = T.split();
+ const Type *ty = split.Ty;
+
+ // If we're mangling a qualified array type, push the qualifiers to
+ // the element type.
+ if (split.Quals && isa<ArrayType>(T)) {
+ ty = Context.getASTContext().getAsArrayType(T);
+ }
+
+ switch (ty->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, PARENT)
+#define NON_CANONICAL_TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
+ return;
+#define TYPE(CLASS, PARENT) \
+ case Type::CLASS: \
+ mangleType(cast<CLASS##Type>(ty), Range); \
+ break;
+#include "clang/AST/TypeNodes.def"
+#undef ABSTRACT_TYPE
+#undef NON_CANONICAL_TYPE
+#undef TYPE
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T,
+ SourceRange Range) {
+ // <type> ::= <builtin-type>
+ // <builtin-type> ::= X # void
+ // ::= C # signed char
+ // ::= D # char
+ // ::= E # unsigned char
+ // ::= F # short
+ // ::= G # unsigned short (or wchar_t if it's not a builtin)
+ // ::= H # int
+ // ::= I # unsigned int
+ // ::= J # long
+ // ::= K # unsigned long
+ // L # <none>
+ // ::= M # float
+ // ::= N # double
+ // ::= O # long double (__float80 is mangled differently)
+ // ::= _J # long long, __int64
+ // ::= _K # unsigned long long, __int64
+ // ::= _L # __int128
+ // ::= _M # unsigned __int128
+ // ::= _N # bool
+ // _O # <array in parameter>
+ // ::= _T # __float80 (Intel)
+ // ::= _W # wchar_t
+ // ::= _Z # __float80 (Digital Mars)
+ switch (T->getKind()) {
+ case BuiltinType::Void: Out << 'X'; break;
+ case BuiltinType::SChar: Out << 'C'; break;
+ case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'D'; break;
+ case BuiltinType::UChar: Out << 'E'; break;
+ case BuiltinType::Short: Out << 'F'; break;
+ case BuiltinType::UShort: Out << 'G'; break;
+ case BuiltinType::Int: Out << 'H'; break;
+ case BuiltinType::UInt: Out << 'I'; break;
+ case BuiltinType::Long: Out << 'J'; break;
+ case BuiltinType::ULong: Out << 'K'; break;
+ case BuiltinType::Float: Out << 'M'; break;
+ case BuiltinType::Double: Out << 'N'; break;
+ // TODO: Determine size and mangle accordingly
+ case BuiltinType::LongDouble: Out << 'O'; break;
+ case BuiltinType::LongLong: Out << "_J"; break;
+ case BuiltinType::ULongLong: Out << "_K"; break;
+ case BuiltinType::Int128: Out << "_L"; break;
+ case BuiltinType::UInt128: Out << "_M"; break;
+ case BuiltinType::Bool: Out << "_N"; break;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U: Out << "_W"; break;
+
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) \
+ case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ case BuiltinType::Dependent:
+ 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;
+
+ case BuiltinType::NullPtr: Out << "$$T"; break;
+
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Half: {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this built-in %0 type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << T->getName(Context.getASTContext().getPrintingPolicy())
+ << Range;
+ break;
+ }
+ }
+}
+
+// <type> ::= <function-type>
+void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T,
+ SourceRange) {
+ // Structors only appear in decls, so at this point we know it's not a
+ // structor type.
+ // FIXME: This may not be lambda-friendly.
+ Out << "$$A6";
+ mangleType(T, NULL, false, false);
+}
+void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T,
+ SourceRange) {
+ llvm_unreachable("Can't mangle K&R function prototypes");
+}
+
+void MicrosoftCXXNameMangler::mangleType(const FunctionType *T,
+ const FunctionDecl *D,
+ bool IsStructor,
+ bool IsInstMethod) {
+ // <function-type> ::= <this-cvr-qualifiers> <calling-convention>
+ // <return-type> <argument-list> <throw-spec>
+ const FunctionProtoType *Proto = cast<FunctionProtoType>(T);
+
+ // If this is a C++ instance method, mangle the CVR qualifiers for the
+ // this pointer.
+ if (IsInstMethod)
+ mangleQualifiers(Qualifiers::fromCVRMask(Proto->getTypeQuals()), false);
+
+ mangleCallingConvention(T, IsInstMethod);
+
+ // <return-type> ::= <type>
+ // ::= @ # structors (they have no declared return type)
+ if (IsStructor)
+ Out << '@';
+ else {
+ QualType Result = Proto->getResultType();
+ const Type* RT = Result.getTypePtr();
+ if (!RT->isAnyPointerType() && !RT->isReferenceType()) {
+ if (Result.hasQualifiers() || !RT->isBuiltinType())
+ Out << '?';
+ if (!RT->isBuiltinType() && !Result.hasQualifiers()) {
+ // Lack of qualifiers for user types is mangled as 'A'.
+ Out << 'A';
+ }
+ }
+
+ // FIXME: Get the source range for the result type. Or, better yet,
+ // implement the unimplemented stuff so we don't need accurate source
+ // location info anymore :).
+ mangleType(Result, SourceRange());
+ }
+
+ // <argument-list> ::= X # void
+ // ::= <type>+ @
+ // ::= <type>* Z # varargs
+ if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) {
+ Out << 'X';
+ } else {
+ if (D) {
+ // If we got a decl, use the type-as-written to make sure arrays
+ // get mangled right. Note that we can't rely on the TSI
+ // existing if (for example) the parameter was synthesized.
+ for (FunctionDecl::param_const_iterator Parm = D->param_begin(),
+ ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) {
+ TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo();
+ QualType Type = TSI ? TSI->getType() : (*Parm)->getType();
+ mangleArgumentType(Type, (*Parm)->getSourceRange());
+ }
+ } else {
+ // Happens for function pointer type arguments for example.
+ for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
+ ArgEnd = Proto->arg_type_end();
+ Arg != ArgEnd; ++Arg)
+ mangleArgumentType(*Arg, SourceRange());
+ }
+ // <builtin-type> ::= Z # ellipsis
+ if (Proto->isVariadic())
+ Out << 'Z';
+ else
+ Out << '@';
+ }
+
+ mangleThrowSpecification(Proto);
+}
+
+void MicrosoftCXXNameMangler::mangleFunctionClass(const FunctionDecl *FD) {
+ // <function-class> ::= A # private: near
+ // ::= B # private: far
+ // ::= C # private: static near
+ // ::= D # private: static far
+ // ::= E # private: virtual near
+ // ::= F # private: virtual far
+ // ::= G # private: thunk near
+ // ::= H # private: thunk far
+ // ::= I # protected: near
+ // ::= J # protected: far
+ // ::= K # protected: static near
+ // ::= L # protected: static far
+ // ::= M # protected: virtual near
+ // ::= N # protected: virtual far
+ // ::= O # protected: thunk near
+ // ::= P # protected: thunk far
+ // ::= Q # public: near
+ // ::= R # public: far
+ // ::= S # public: static near
+ // ::= T # public: static far
+ // ::= U # public: virtual near
+ // ::= V # public: virtual far
+ // ::= W # public: thunk near
+ // ::= X # public: thunk far
+ // ::= Y # global near
+ // ::= Z # global far
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ switch (MD->getAccess()) {
+ default:
+ case AS_private:
+ if (MD->isStatic())
+ Out << 'C';
+ else if (MD->isVirtual())
+ Out << 'E';
+ else
+ Out << 'A';
+ break;
+ case AS_protected:
+ if (MD->isStatic())
+ Out << 'K';
+ else if (MD->isVirtual())
+ Out << 'M';
+ else
+ Out << 'I';
+ break;
+ case AS_public:
+ if (MD->isStatic())
+ Out << 'S';
+ else if (MD->isVirtual())
+ Out << 'U';
+ else
+ Out << 'Q';
+ }
+ } else
+ Out << 'Y';
+}
+void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T,
+ bool IsInstMethod) {
+ // <calling-convention> ::= A # __cdecl
+ // ::= B # __export __cdecl
+ // ::= C # __pascal
+ // ::= D # __export __pascal
+ // ::= E # __thiscall
+ // ::= F # __export __thiscall
+ // ::= G # __stdcall
+ // ::= H # __export __stdcall
+ // ::= I # __fastcall
+ // ::= J # __export __fastcall
+ // The 'export' calling conventions are from a bygone era
+ // (*cough*Win16*cough*) when functions were declared for export with
+ // that keyword. (It didn't actually export them, it just made them so
+ // that they could be in a DLL and somebody from another module could call
+ // them.)
+ CallingConv CC = T->getCallConv();
+ if (CC == CC_Default) {
+ if (IsInstMethod) {
+ const FunctionProtoType *FPT =
+ T->getCanonicalTypeUnqualified().castAs<FunctionProtoType>();
+ bool isVariadic = FPT->isVariadic();
+ CC = getASTContext().getDefaultCXXMethodCallConv(isVariadic);
+ } else {
+ CC = CC_C;
+ }
+ }
+ switch (CC) {
+ default:
+ llvm_unreachable("Unsupported CC for mangling");
+ case CC_Default:
+ case CC_C: Out << 'A'; break;
+ case CC_X86Pascal: Out << 'C'; break;
+ case CC_X86ThisCall: Out << 'E'; break;
+ case CC_X86StdCall: Out << 'G'; break;
+ case CC_X86FastCall: Out << 'I'; break;
+ }
+}
+void MicrosoftCXXNameMangler::mangleThrowSpecification(
+ const FunctionProtoType *FT) {
+ // <throw-spec> ::= Z # throw(...) (default)
+ // ::= @ # throw() or __declspec/__attribute__((nothrow))
+ // ::= <type>+
+ // NOTE: Since the Microsoft compiler ignores throw specifications, they are
+ // all actually mangled as 'Z'. (They're ignored because their associated
+ // functionality isn't implemented, and probably never will be.)
+ Out << 'Z';
+}
+
+void MicrosoftCXXNameMangler::mangleType(const UnresolvedUsingType *T,
+ SourceRange Range) {
+ // Probably should be mangled as a template instantiation; need to see what
+ // VC does first.
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this unresolved dependent type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+// <type> ::= <union-type> | <struct-type> | <class-type> | <enum-type>
+// <union-type> ::= T <name>
+// <struct-type> ::= U <name>
+// <class-type> ::= V <name>
+// <enum-type> ::= W <size> <name>
+void MicrosoftCXXNameMangler::mangleType(const EnumType *T, SourceRange) {
+ mangleType(cast<TagType>(T));
+}
+void MicrosoftCXXNameMangler::mangleType(const RecordType *T, SourceRange) {
+ mangleType(cast<TagType>(T));
+}
+void MicrosoftCXXNameMangler::mangleType(const TagType *T) {
+ switch (T->getDecl()->getTagKind()) {
+ case TTK_Union:
+ Out << 'T';
+ break;
+ case TTK_Struct:
+ case TTK_Interface:
+ Out << 'U';
+ break;
+ case TTK_Class:
+ Out << 'V';
+ break;
+ case TTK_Enum:
+ Out << 'W';
+ Out << getASTContext().getTypeSizeInChars(
+ cast<EnumDecl>(T->getDecl())->getIntegerType()).getQuantity();
+ break;
+ }
+ mangleName(T->getDecl());
+}
+
+// <type> ::= <array-type>
+// <array-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
+// [Y <dimension-count> <dimension>+]
+// <element-type> # as global
+// ::= Q <cvr-qualifiers> [Y <dimension-count> <dimension>+]
+// <element-type> # as param
+// It's supposed to be the other way around, but for some strange reason, it
+// isn't. Today this behavior is retained for the sole purpose of backwards
+// compatibility.
+void MicrosoftCXXNameMangler::mangleType(const ArrayType *T, bool IsGlobal) {
+ // This isn't a recursive mangling, so now we have to do it all in this
+ // one call.
+ if (IsGlobal) {
+ manglePointerQualifiers(T->getElementType().getQualifiers());
+ } else {
+ Out << 'Q';
+ }
+ mangleExtraDimensions(T->getElementType());
+}
+void MicrosoftCXXNameMangler::mangleType(const ConstantArrayType *T,
+ SourceRange) {
+ mangleType(cast<ArrayType>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const VariableArrayType *T,
+ SourceRange) {
+ mangleType(cast<ArrayType>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedArrayType *T,
+ SourceRange) {
+ mangleType(cast<ArrayType>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleType(const IncompleteArrayType *T,
+ SourceRange) {
+ mangleType(cast<ArrayType>(T), false);
+}
+void MicrosoftCXXNameMangler::mangleExtraDimensions(QualType ElementTy) {
+ SmallVector<llvm::APInt, 3> Dimensions;
+ for (;;) {
+ if (const ConstantArrayType *CAT =
+ getASTContext().getAsConstantArrayType(ElementTy)) {
+ Dimensions.push_back(CAT->getSize());
+ ElementTy = CAT->getElementType();
+ } else if (ElementTy->isVariableArrayType()) {
+ const VariableArrayType *VAT =
+ getASTContext().getAsVariableArrayType(ElementTy);
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this variable-length array yet");
+ Diags.Report(VAT->getSizeExpr()->getExprLoc(), DiagID)
+ << VAT->getBracketsRange();
+ return;
+ } else if (ElementTy->isDependentSizedArrayType()) {
+ // The dependent expression has to be folded into a constant (TODO).
+ const DependentSizedArrayType *DSAT =
+ getASTContext().getAsDependentSizedArrayType(ElementTy);
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this dependent-length array yet");
+ Diags.Report(DSAT->getSizeExpr()->getExprLoc(), DiagID)
+ << DSAT->getBracketsRange();
+ return;
+ } else if (ElementTy->isIncompleteArrayType()) continue;
+ else break;
+ }
+ mangleQualifiers(ElementTy.getQualifiers(), false);
+ // If there are any additional dimensions, mangle them now.
+ if (Dimensions.size() > 0) {
+ Out << 'Y';
+ // <dimension-count> ::= <number> # number of extra dimensions
+ mangleNumber(Dimensions.size());
+ for (unsigned Dim = 0; Dim < Dimensions.size(); ++Dim) {
+ mangleNumber(Dimensions[Dim].getLimitedValue());
+ }
+ }
+ mangleType(ElementTy.getLocalUnqualifiedType(), SourceRange());
+}
+
+// <type> ::= <pointer-to-member-type>
+// <pointer-to-member-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers>
+// <class name> <type>
+void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
+ SourceRange Range) {
+ QualType PointeeType = T->getPointeeType();
+ if (const FunctionProtoType *FPT = PointeeType->getAs<FunctionProtoType>()) {
+ Out << '8';
+ mangleName(T->getClass()->castAs<RecordType>()->getDecl());
+ mangleType(FPT, NULL, false, true);
+ } else {
+ mangleQualifiers(PointeeType.getQualifiers(), true);
+ mangleName(T->getClass()->castAs<RecordType>()->getDecl());
+ mangleType(PointeeType.getLocalUnqualifiedType(), Range);
+ }
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this template type parameter type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(
+ const SubstTemplateTypeParmPackType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this substituted parameter pack yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+// <type> ::= <pointer-type>
+// <pointer-type> ::= <pointer-cvr-qualifiers> <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const PointerType *T,
+ SourceRange Range) {
+ QualType PointeeTy = T->getPointeeType();
+ if (PointeeTy->isArrayType()) {
+ // Pointers to arrays are mangled like arrays.
+ mangleExtraDimensions(PointeeTy);
+ } else if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
+ // Function pointers are special.
+ Out << '6';
+ mangleType(FT, NULL, false, false);
+ } else {
+ mangleQualifiers(PointeeTy.getQualifiers(), false);
+ mangleType(PointeeTy, Range, false);
+ }
+}
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
+ SourceRange Range) {
+ // Object pointers never have qualifiers.
+ Out << 'A';
+ mangleType(T->getPointeeType(), Range);
+}
+
+// <type> ::= <reference-type>
+// <reference-type> ::= A <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T,
+ SourceRange Range) {
+ Out << 'A';
+ QualType PointeeTy = T->getPointeeType();
+ if (!PointeeTy.hasQualifiers())
+ // Lack of qualifiers is mangled as 'A'.
+ Out << 'A';
+ mangleType(PointeeTy, Range);
+}
+
+// <type> ::= <r-value-reference-type>
+// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type>
+void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T,
+ SourceRange Range) {
+ Out << "$$Q";
+ QualType PointeeTy = T->getPointeeType();
+ if (!PointeeTy.hasQualifiers())
+ // Lack of qualifiers is mangled as 'A'.
+ Out << 'A';
+ mangleType(PointeeTy, Range);
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ComplexType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this complex number type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const VectorType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this vector type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this extended vector type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this dependent-sized extended vector type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T,
+ SourceRange) {
+ // ObjC interfaces have structs underlying them.
+ Out << 'U';
+ mangleName(T->getDecl());
+}
+
+void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T,
+ SourceRange Range) {
+ // We don't allow overloading by different protocol qualification,
+ // so mangling them isn't necessary.
+ mangleType(T->getBaseType(), Range);
+}
+
+void MicrosoftCXXNameMangler::mangleType(const BlockPointerType *T,
+ SourceRange Range) {
+ Out << "_E";
+
+ QualType pointee = T->getPointeeType();
+ mangleType(pointee->castAs<FunctionProtoType>(), NULL, false, false);
+}
+
+void MicrosoftCXXNameMangler::mangleType(const InjectedClassNameType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this injected class name type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TemplateSpecializationType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this template specialization type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DependentNameType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this dependent name type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(
+ const DependentTemplateSpecializationType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this dependent template specialization type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const PackExpansionType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this pack expansion yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TypeOfType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this typeof(type) yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const TypeOfExprType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this typeof(expression) yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const DecltypeType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this decltype() yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const UnaryTransformType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this unary transform type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const AutoType *T, SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this 'auto' type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftCXXNameMangler::mangleType(const AtomicType *T,
+ SourceRange Range) {
+ DiagnosticsEngine &Diags = Context.getDiags();
+ unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this C11 atomic type yet");
+ Diags.Report(Range.getBegin(), DiagID)
+ << Range;
+}
+
+void MicrosoftMangleContext::mangleName(const NamedDecl *D,
+ raw_ostream &Out) {
+ assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
+ "Invalid mangleName() call, argument is not a variable or function!");
+ assert(!isa<CXXConstructorDecl>(D) && !isa<CXXDestructorDecl>(D) &&
+ "Invalid mangleName() call on 'structor decl!");
+
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ getASTContext().getSourceManager(),
+ "Mangling declaration");
+
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ return Mangler.mangle(D);
+}
+void MicrosoftMangleContext::mangleThunk(const CXXMethodDecl *MD,
+ const ThunkInfo &Thunk,
+ raw_ostream &) {
+ unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle thunk for this method yet");
+ getDiags().Report(MD->getLocation(), DiagID);
+}
+void MicrosoftMangleContext::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
+ CXXDtorType Type,
+ const ThisAdjustment &,
+ raw_ostream &) {
+ unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle thunk for this destructor yet");
+ getDiags().Report(DD->getLocation(), DiagID);
+}
+void MicrosoftMangleContext::mangleCXXVTable(const CXXRecordDecl *RD,
+ raw_ostream &Out) {
+ // <mangled-name> ::= ? <operator-name> <class-name> <storage-class>
+ // <cvr-qualifiers> [<name>] @
+ // <operator-name> ::= _7 # vftable
+ // ::= _8 # vbtable
+ // NOTE: <cvr-qualifiers> here is always 'B' (const). <storage-class>
+ // is always '6' for vftables and '7' for vbtables. (The difference is
+ // beyond me.)
+ // TODO: vbtables.
+ MicrosoftCXXNameMangler Mangler(*this, Out);
+ Mangler.getStream() << "\01??_7";
+ Mangler.mangleName(RD);
+ Mangler.getStream() << "6B";
+ // TODO: If the class has more than one vtable, mangle in the class it came
+ // from.
+ Mangler.getStream() << '@';
+}
+void MicrosoftMangleContext::mangleCXXVTT(const CXXRecordDecl *RD,
+ raw_ostream &) {
+ llvm_unreachable("The MS C++ ABI does not have virtual table tables!");
+}
+void MicrosoftMangleContext::mangleCXXCtorVTable(const CXXRecordDecl *RD,
+ int64_t Offset,
+ const CXXRecordDecl *Type,
+ raw_ostream &) {
+ llvm_unreachable("The MS C++ ABI does not have constructor vtables!");
+}
+void MicrosoftMangleContext::mangleCXXRTTI(QualType T,
+ raw_ostream &) {
+ // FIXME: Give a location...
+ unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle RTTI descriptors for type %0 yet");
+ getDiags().Report(DiagID)
+ << T.getBaseTypeIdentifier();
+}
+void MicrosoftMangleContext::mangleCXXRTTIName(QualType T,
+ raw_ostream &) {
+ // FIXME: Give a location...
+ unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle the name of type %0 into RTTI descriptors yet");
+ getDiags().Report(DiagID)
+ << T.getBaseTypeIdentifier();
+}
+void MicrosoftMangleContext::mangleCXXCtor(const CXXConstructorDecl *D,
+ CXXCtorType Type,
+ raw_ostream & Out) {
+ MicrosoftCXXNameMangler mangler(*this, Out);
+ mangler.mangle(D);
+}
+void MicrosoftMangleContext::mangleCXXDtor(const CXXDestructorDecl *D,
+ CXXDtorType Type,
+ raw_ostream & Out) {
+ MicrosoftCXXNameMangler mangler(*this, Out);
+ mangler.mangle(D);
+}
+void MicrosoftMangleContext::mangleReferenceTemporary(const clang::VarDecl *VD,
+ raw_ostream &) {
+ unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "cannot mangle this reference temporary yet");
+ getDiags().Report(VD->getLocation(), DiagID);
+}
+
+MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
+ DiagnosticsEngine &Diags) {
+ return new MicrosoftMangleContext(Context, Diags);
+}
Modified: cfe/trunk/lib/AST/NSAPI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/NSAPI.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/NSAPI.cpp (original)
+++ cfe/trunk/lib/AST/NSAPI.cpp Tue Dec 18 08:30:41 2012
@@ -1,420 +1,414 @@
-//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/NSAPI.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-
-using namespace clang;
-
-NSAPI::NSAPI(ASTContext &ctx)
- : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
- NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
-}
-
-IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
- static const char *ClassName[NumClassIds] = {
- "NSObject",
- "NSString",
- "NSArray",
- "NSMutableArray",
- "NSDictionary",
- "NSMutableDictionary",
- "NSNumber"
- };
-
- if (!ClassIds[K])
- return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
-
- return ClassIds[K];
-}
-
-Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
- if (NSStringSelectors[MK].isNull()) {
- Selector Sel;
- switch (MK) {
- case NSStr_stringWithString:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
- break;
- case NSStr_stringWithUTF8String:
- Sel = Ctx.Selectors.getUnarySelector(
- &Ctx.Idents.get("stringWithUTF8String"));
- break;
- case NSStr_stringWithCStringEncoding: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("stringWithCString"),
- &Ctx.Idents.get("encoding")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- case NSStr_stringWithCString:
- Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
- break;
- case NSStr_initWithString:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
- break;
- }
- return (NSStringSelectors[MK] = Sel);
- }
-
- return NSStringSelectors[MK];
-}
-
-llvm::Optional<NSAPI::NSStringMethodKind>
-NSAPI::getNSStringMethodKind(Selector Sel) const {
- for (unsigned i = 0; i != NumNSStringMethods; ++i) {
- NSStringMethodKind MK = NSStringMethodKind(i);
- if (Sel == getNSStringSelector(MK))
- return MK;
- }
-
- return llvm::Optional<NSStringMethodKind>();
-}
-
-Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
- if (NSArraySelectors[MK].isNull()) {
- Selector Sel;
- switch (MK) {
- case NSArr_array:
- Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
- break;
- case NSArr_arrayWithArray:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
- break;
- case NSArr_arrayWithObject:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
- break;
- case NSArr_arrayWithObjects:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
- break;
- case NSArr_arrayWithObjectsCount: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("arrayWithObjects"),
- &Ctx.Idents.get("count")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- case NSArr_initWithArray:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
- break;
- case NSArr_initWithObjects:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
- break;
- case NSArr_objectAtIndex:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
- break;
- case NSMutableArr_replaceObjectAtIndex: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("replaceObjectAtIndex"),
- &Ctx.Idents.get("withObject")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- }
- return (NSArraySelectors[MK] = Sel);
- }
-
- return NSArraySelectors[MK];
-}
-
-llvm::Optional<NSAPI::NSArrayMethodKind>
-NSAPI::getNSArrayMethodKind(Selector Sel) {
- for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
- NSArrayMethodKind MK = NSArrayMethodKind(i);
- if (Sel == getNSArraySelector(MK))
- return MK;
- }
-
- return llvm::Optional<NSArrayMethodKind>();
-}
-
-Selector NSAPI::getNSDictionarySelector(
- NSDictionaryMethodKind MK) const {
- if (NSDictionarySelectors[MK].isNull()) {
- Selector Sel;
- switch (MK) {
- case NSDict_dictionary:
- Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
- break;
- case NSDict_dictionaryWithDictionary:
- Sel = Ctx.Selectors.getUnarySelector(
- &Ctx.Idents.get("dictionaryWithDictionary"));
- break;
- case NSDict_dictionaryWithObjectForKey: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("dictionaryWithObject"),
- &Ctx.Idents.get("forKey")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- case NSDict_dictionaryWithObjectsForKeys: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("dictionaryWithObjects"),
- &Ctx.Idents.get("forKeys")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- case NSDict_dictionaryWithObjectsForKeysCount: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("dictionaryWithObjects"),
- &Ctx.Idents.get("forKeys"),
- &Ctx.Idents.get("count")
- };
- Sel = Ctx.Selectors.getSelector(3, KeyIdents);
- break;
- }
- case NSDict_dictionaryWithObjectsAndKeys:
- Sel = Ctx.Selectors.getUnarySelector(
- &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
- break;
- case NSDict_initWithDictionary:
- Sel = Ctx.Selectors.getUnarySelector(
- &Ctx.Idents.get("initWithDictionary"));
- break;
- case NSDict_initWithObjectsAndKeys:
- Sel = Ctx.Selectors.getUnarySelector(
- &Ctx.Idents.get("initWithObjectsAndKeys"));
- break;
- case NSDict_objectForKey:
- Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
- break;
- case NSMutableDict_setObjectForKey: {
- IdentifierInfo *KeyIdents[] = {
- &Ctx.Idents.get("setObject"),
- &Ctx.Idents.get("forKey")
- };
- Sel = Ctx.Selectors.getSelector(2, KeyIdents);
- break;
- }
- }
- return (NSDictionarySelectors[MK] = Sel);
- }
-
- return NSDictionarySelectors[MK];
-}
-
-llvm::Optional<NSAPI::NSDictionaryMethodKind>
-NSAPI::getNSDictionaryMethodKind(Selector Sel) {
- for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
- NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
- if (Sel == getNSDictionarySelector(MK))
- return MK;
- }
-
- return llvm::Optional<NSDictionaryMethodKind>();
-}
-
-Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
- bool Instance) const {
- static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
- "numberWithChar",
- "numberWithUnsignedChar",
- "numberWithShort",
- "numberWithUnsignedShort",
- "numberWithInt",
- "numberWithUnsignedInt",
- "numberWithLong",
- "numberWithUnsignedLong",
- "numberWithLongLong",
- "numberWithUnsignedLongLong",
- "numberWithFloat",
- "numberWithDouble",
- "numberWithBool",
- "numberWithInteger",
- "numberWithUnsignedInteger"
- };
- static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
- "initWithChar",
- "initWithUnsignedChar",
- "initWithShort",
- "initWithUnsignedShort",
- "initWithInt",
- "initWithUnsignedInt",
- "initWithLong",
- "initWithUnsignedLong",
- "initWithLongLong",
- "initWithUnsignedLongLong",
- "initWithFloat",
- "initWithDouble",
- "initWithBool",
- "initWithInteger",
- "initWithUnsignedInteger"
- };
-
- Selector *Sels;
- const char **Names;
- if (Instance) {
- Sels = NSNumberInstanceSelectors;
- Names = InstanceSelectorName;
- } else {
- Sels = NSNumberClassSelectors;
- Names = ClassSelectorName;
- }
-
- if (Sels[MK].isNull())
- Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
- return Sels[MK];
-}
-
-llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
-NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
- for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
- NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
- if (isNSNumberLiteralSelector(MK, Sel))
- return MK;
- }
-
- return llvm::Optional<NSNumberLiteralMethodKind>();
-}
-
-llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
-NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
- const BuiltinType *BT = T->getAs<BuiltinType>();
- if (!BT)
- return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
-
- const TypedefType *TDT = T->getAs<TypedefType>();
- if (TDT) {
- QualType TDTTy = QualType(TDT, 0);
- if (isObjCBOOLType(TDTTy))
- return NSAPI::NSNumberWithBool;
- if (isObjCNSIntegerType(TDTTy))
- return NSAPI::NSNumberWithInteger;
- if (isObjCNSUIntegerType(TDTTy))
- return NSAPI::NSNumberWithUnsignedInteger;
- }
-
- switch (BT->getKind()) {
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- return NSAPI::NSNumberWithChar;
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- return NSAPI::NSNumberWithUnsignedChar;
- case BuiltinType::Short:
- return NSAPI::NSNumberWithShort;
- case BuiltinType::UShort:
- return NSAPI::NSNumberWithUnsignedShort;
- case BuiltinType::Int:
- return NSAPI::NSNumberWithInt;
- case BuiltinType::UInt:
- return NSAPI::NSNumberWithUnsignedInt;
- case BuiltinType::Long:
- return NSAPI::NSNumberWithLong;
- case BuiltinType::ULong:
- return NSAPI::NSNumberWithUnsignedLong;
- case BuiltinType::LongLong:
- return NSAPI::NSNumberWithLongLong;
- case BuiltinType::ULongLong:
- return NSAPI::NSNumberWithUnsignedLongLong;
- case BuiltinType::Float:
- return NSAPI::NSNumberWithFloat;
- case BuiltinType::Double:
- return NSAPI::NSNumberWithDouble;
- case BuiltinType::Bool:
- return NSAPI::NSNumberWithBool;
-
- case BuiltinType::Void:
- case BuiltinType::WChar_U:
- case BuiltinType::WChar_S:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Int128:
- case BuiltinType::LongDouble:
- case BuiltinType::UInt128:
- case BuiltinType::NullPtr:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCSel:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- case BuiltinType::BoundMember:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::UnknownAny:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::Half:
- case BuiltinType::PseudoObject:
- case BuiltinType::BuiltinFn:
- break;
- }
-
- return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
-}
-
-/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
-bool NSAPI::isObjCBOOLType(QualType T) const {
- return isObjCTypedef(T, "BOOL", BOOLId);
-}
-/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
-bool NSAPI::isObjCNSIntegerType(QualType T) const {
- return isObjCTypedef(T, "NSInteger", NSIntegerId);
-}
-/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
-bool NSAPI::isObjCNSUIntegerType(QualType T) const {
- return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
-}
-
-bool NSAPI::isObjCTypedef(QualType T,
- StringRef name, IdentifierInfo *&II) const {
- if (!Ctx.getLangOpts().ObjC1)
- return false;
- if (T.isNull())
- return false;
-
- if (!II)
- II = &Ctx.Idents.get(name);
-
- while (const TypedefType *TDT = T->getAs<TypedefType>()) {
- if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
- return true;
- T = TDT->desugar();
- }
-
- return false;
-}
-
-bool NSAPI::isObjCEnumerator(const Expr *E,
- StringRef name, IdentifierInfo *&II) const {
- if (!Ctx.getLangOpts().ObjC1)
- return false;
- if (!E)
- return false;
-
- if (!II)
- II = &Ctx.Idents.get(name);
-
- if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
- if (const EnumConstantDecl *
- EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
- return EnumD->getIdentifier() == II;
-
- return false;
-}
-
-Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
- Selector &Sel) const {
- if (Sel.isNull()) {
- SmallVector<IdentifierInfo *, 4> Idents;
- for (ArrayRef<StringRef>::const_iterator
- I = Ids.begin(), E = Ids.end(); I != E; ++I)
- Idents.push_back(&Ctx.Idents.get(*I));
- Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
- }
- return Sel;
-}
+//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/NSAPI.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+
+using namespace clang;
+
+NSAPI::NSAPI(ASTContext &ctx)
+ : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
+ NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
+}
+
+IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
+ static const char *ClassName[NumClassIds] = {
+ "NSObject",
+ "NSString",
+ "NSArray",
+ "NSMutableArray",
+ "NSDictionary",
+ "NSMutableDictionary",
+ "NSNumber"
+ };
+
+ if (!ClassIds[K])
+ return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
+
+ return ClassIds[K];
+}
+
+Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
+ if (NSStringSelectors[MK].isNull()) {
+ Selector Sel;
+ switch (MK) {
+ case NSStr_stringWithString:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
+ break;
+ case NSStr_stringWithUTF8String:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("stringWithUTF8String"));
+ break;
+ case NSStr_stringWithCStringEncoding: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("stringWithCString"),
+ &Ctx.Idents.get("encoding")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSStr_stringWithCString:
+ Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
+ break;
+ case NSStr_initWithString:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
+ break;
+ }
+ return (NSStringSelectors[MK] = Sel);
+ }
+
+ return NSStringSelectors[MK];
+}
+
+llvm::Optional<NSAPI::NSStringMethodKind>
+NSAPI::getNSStringMethodKind(Selector Sel) const {
+ for (unsigned i = 0; i != NumNSStringMethods; ++i) {
+ NSStringMethodKind MK = NSStringMethodKind(i);
+ if (Sel == getNSStringSelector(MK))
+ return MK;
+ }
+
+ return llvm::Optional<NSStringMethodKind>();
+}
+
+Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
+ if (NSArraySelectors[MK].isNull()) {
+ Selector Sel;
+ switch (MK) {
+ case NSArr_array:
+ Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
+ break;
+ case NSArr_arrayWithArray:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
+ break;
+ case NSArr_arrayWithObject:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
+ break;
+ case NSArr_arrayWithObjects:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
+ break;
+ case NSArr_arrayWithObjectsCount: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("arrayWithObjects"),
+ &Ctx.Idents.get("count")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSArr_initWithArray:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
+ break;
+ case NSArr_initWithObjects:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
+ break;
+ case NSArr_objectAtIndex:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
+ break;
+ case NSMutableArr_replaceObjectAtIndex: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("replaceObjectAtIndex"),
+ &Ctx.Idents.get("withObject")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ }
+ return (NSArraySelectors[MK] = Sel);
+ }
+
+ return NSArraySelectors[MK];
+}
+
+llvm::Optional<NSAPI::NSArrayMethodKind>
+NSAPI::getNSArrayMethodKind(Selector Sel) {
+ for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
+ NSArrayMethodKind MK = NSArrayMethodKind(i);
+ if (Sel == getNSArraySelector(MK))
+ return MK;
+ }
+
+ return llvm::Optional<NSArrayMethodKind>();
+}
+
+Selector NSAPI::getNSDictionarySelector(
+ NSDictionaryMethodKind MK) const {
+ if (NSDictionarySelectors[MK].isNull()) {
+ Selector Sel;
+ switch (MK) {
+ case NSDict_dictionary:
+ Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
+ break;
+ case NSDict_dictionaryWithDictionary:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("dictionaryWithDictionary"));
+ break;
+ case NSDict_dictionaryWithObjectForKey: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("dictionaryWithObject"),
+ &Ctx.Idents.get("forKey")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSDict_dictionaryWithObjectsForKeys: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("dictionaryWithObjects"),
+ &Ctx.Idents.get("forKeys")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ case NSDict_dictionaryWithObjectsForKeysCount: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("dictionaryWithObjects"),
+ &Ctx.Idents.get("forKeys"),
+ &Ctx.Idents.get("count")
+ };
+ Sel = Ctx.Selectors.getSelector(3, KeyIdents);
+ break;
+ }
+ case NSDict_dictionaryWithObjectsAndKeys:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
+ break;
+ case NSDict_initWithDictionary:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("initWithDictionary"));
+ break;
+ case NSDict_initWithObjectsAndKeys:
+ Sel = Ctx.Selectors.getUnarySelector(
+ &Ctx.Idents.get("initWithObjectsAndKeys"));
+ break;
+ case NSDict_objectForKey:
+ Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
+ break;
+ case NSMutableDict_setObjectForKey: {
+ IdentifierInfo *KeyIdents[] = {
+ &Ctx.Idents.get("setObject"),
+ &Ctx.Idents.get("forKey")
+ };
+ Sel = Ctx.Selectors.getSelector(2, KeyIdents);
+ break;
+ }
+ }
+ return (NSDictionarySelectors[MK] = Sel);
+ }
+
+ return NSDictionarySelectors[MK];
+}
+
+llvm::Optional<NSAPI::NSDictionaryMethodKind>
+NSAPI::getNSDictionaryMethodKind(Selector Sel) {
+ for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
+ NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
+ if (Sel == getNSDictionarySelector(MK))
+ return MK;
+ }
+
+ return llvm::Optional<NSDictionaryMethodKind>();
+}
+
+Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
+ bool Instance) const {
+ static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
+ "numberWithChar",
+ "numberWithUnsignedChar",
+ "numberWithShort",
+ "numberWithUnsignedShort",
+ "numberWithInt",
+ "numberWithUnsignedInt",
+ "numberWithLong",
+ "numberWithUnsignedLong",
+ "numberWithLongLong",
+ "numberWithUnsignedLongLong",
+ "numberWithFloat",
+ "numberWithDouble",
+ "numberWithBool",
+ "numberWithInteger",
+ "numberWithUnsignedInteger"
+ };
+ static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
+ "initWithChar",
+ "initWithUnsignedChar",
+ "initWithShort",
+ "initWithUnsignedShort",
+ "initWithInt",
+ "initWithUnsignedInt",
+ "initWithLong",
+ "initWithUnsignedLong",
+ "initWithLongLong",
+ "initWithUnsignedLongLong",
+ "initWithFloat",
+ "initWithDouble",
+ "initWithBool",
+ "initWithInteger",
+ "initWithUnsignedInteger"
+ };
+
+ Selector *Sels;
+ const char **Names;
+ if (Instance) {
+ Sels = NSNumberInstanceSelectors;
+ Names = InstanceSelectorName;
+ } else {
+ Sels = NSNumberClassSelectors;
+ Names = ClassSelectorName;
+ }
+
+ if (Sels[MK].isNull())
+ Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
+ return Sels[MK];
+}
+
+llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
+NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
+ for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
+ NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
+ if (isNSNumberLiteralSelector(MK, Sel))
+ return MK;
+ }
+
+ return llvm::Optional<NSNumberLiteralMethodKind>();
+}
+
+llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
+NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
+ const BuiltinType *BT = T->getAs<BuiltinType>();
+ if (!BT)
+ return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
+
+ const TypedefType *TDT = T->getAs<TypedefType>();
+ if (TDT) {
+ QualType TDTTy = QualType(TDT, 0);
+ if (isObjCBOOLType(TDTTy))
+ return NSAPI::NSNumberWithBool;
+ if (isObjCNSIntegerType(TDTTy))
+ return NSAPI::NSNumberWithInteger;
+ if (isObjCNSUIntegerType(TDTTy))
+ return NSAPI::NSNumberWithUnsignedInteger;
+ }
+
+ switch (BT->getKind()) {
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return NSAPI::NSNumberWithChar;
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ return NSAPI::NSNumberWithUnsignedChar;
+ case BuiltinType::Short:
+ return NSAPI::NSNumberWithShort;
+ case BuiltinType::UShort:
+ return NSAPI::NSNumberWithUnsignedShort;
+ case BuiltinType::Int:
+ return NSAPI::NSNumberWithInt;
+ case BuiltinType::UInt:
+ return NSAPI::NSNumberWithUnsignedInt;
+ case BuiltinType::Long:
+ return NSAPI::NSNumberWithLong;
+ case BuiltinType::ULong:
+ return NSAPI::NSNumberWithUnsignedLong;
+ case BuiltinType::LongLong:
+ return NSAPI::NSNumberWithLongLong;
+ case BuiltinType::ULongLong:
+ return NSAPI::NSNumberWithUnsignedLongLong;
+ case BuiltinType::Float:
+ return NSAPI::NSNumberWithFloat;
+ case BuiltinType::Double:
+ return NSAPI::NSNumberWithDouble;
+ case BuiltinType::Bool:
+ return NSAPI::NSNumberWithBool;
+
+ case BuiltinType::Void:
+ case BuiltinType::WChar_U:
+ case BuiltinType::WChar_S:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Int128:
+ case BuiltinType::LongDouble:
+ case BuiltinType::UInt128:
+ case BuiltinType::NullPtr:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCSel:
+ case BuiltinType::BoundMember:
+ case BuiltinType::Dependent:
+ case BuiltinType::Overload:
+ case BuiltinType::UnknownAny:
+ case BuiltinType::ARCUnbridgedCast:
+ case BuiltinType::Half:
+ case BuiltinType::PseudoObject:
+ case BuiltinType::BuiltinFn:
+ break;
+ }
+
+ return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
+}
+
+/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
+bool NSAPI::isObjCBOOLType(QualType T) const {
+ return isObjCTypedef(T, "BOOL", BOOLId);
+}
+/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
+bool NSAPI::isObjCNSIntegerType(QualType T) const {
+ return isObjCTypedef(T, "NSInteger", NSIntegerId);
+}
+/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
+bool NSAPI::isObjCNSUIntegerType(QualType T) const {
+ return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
+}
+
+bool NSAPI::isObjCTypedef(QualType T,
+ StringRef name, IdentifierInfo *&II) const {
+ if (!Ctx.getLangOpts().ObjC1)
+ return false;
+ if (T.isNull())
+ return false;
+
+ if (!II)
+ II = &Ctx.Idents.get(name);
+
+ while (const TypedefType *TDT = T->getAs<TypedefType>()) {
+ if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
+ return true;
+ T = TDT->desugar();
+ }
+
+ return false;
+}
+
+bool NSAPI::isObjCEnumerator(const Expr *E,
+ StringRef name, IdentifierInfo *&II) const {
+ if (!Ctx.getLangOpts().ObjC1)
+ return false;
+ if (!E)
+ return false;
+
+ if (!II)
+ II = &Ctx.Idents.get(name);
+
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
+ if (const EnumConstantDecl *
+ EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
+ return EnumD->getIdentifier() == II;
+
+ return false;
+}
+
+Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
+ Selector &Sel) const {
+ if (Sel.isNull()) {
+ SmallVector<IdentifierInfo *, 4> Idents;
+ for (ArrayRef<StringRef>::const_iterator
+ I = Ids.begin(), E = Ids.end(); I != E; ++I)
+ Idents.push_back(&Ctx.Idents.get(*I));
+ Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
+ }
+ return Sel;
+}
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Dec 18 08:30:41 2012
@@ -1512,12 +1512,6 @@
case ObjCId: return "id";
case ObjCClass: return "Class";
case ObjCSel: return "SEL";
- case OCLImage1d: return "image1d_t";
- case OCLImage1dArray: return "image1d_array_t";
- case OCLImage1dBuffer: return "image1d_buffer_t";
- case OCLImage2d: return "image2d_t";
- case OCLImage2dArray: return "image2d_array_t";
- case OCLImage3d: return "image3d_t";
}
llvm_unreachable("Invalid builtin type.");
Modified: cfe/trunk/lib/AST/TypeLoc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)
+++ cfe/trunk/lib/AST/TypeLoc.cpp Tue Dec 18 08:30:41 2012
@@ -1,367 +1,361 @@
-//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- 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 TypeLoc subclasses implementations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/TypeLoc.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/TypeLocVisitor.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace clang;
-
-//===----------------------------------------------------------------------===//
-// TypeLoc Implementation
-//===----------------------------------------------------------------------===//
-
-namespace {
- class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
- public:
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getLocalSourceRange(); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
-SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
- if (TL.isNull()) return SourceRange();
- return TypeLocRanger().Visit(TL);
-}
-
-namespace {
- class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
- public:
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getFullDataSize(); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
-/// \brief Returns the size of the type source info data block.
-unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
- if (Ty.isNull()) return 0;
- return TypeSizer().Visit(TypeLoc(Ty, 0));
-}
-
-namespace {
- class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
- public:
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return TyLoc.getNextTypeLoc(); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
-/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
-/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
-TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
- return NextLoc().Visit(TL);
-}
-
-/// \brief Initializes a type location, and all of its children
-/// recursively, as if the entire tree had been written in the
-/// given location.
-void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
- SourceLocation Loc) {
- while (true) {
- switch (TL.getTypeLocClass()) {
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- case CLASS: { \
- CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
- TLCasted.initializeLocal(Context, Loc); \
- TL = TLCasted.getNextTypeLoc(); \
- if (!TL) return; \
- continue; \
- }
-#include "clang/AST/TypeLocNodes.def"
- }
- }
-}
-
-SourceLocation TypeLoc::getBeginLoc() const {
- TypeLoc Cur = *this;
- TypeLoc LeftMost = Cur;
- while (true) {
- switch (Cur.getTypeLocClass()) {
- case Elaborated:
- LeftMost = Cur;
- break;
- case FunctionProto:
- if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
- LeftMost = Cur;
- break;
- }
- /* Fall through */
- case FunctionNoProto:
- case ConstantArray:
- case DependentSizedArray:
- case IncompleteArray:
- case VariableArray:
- // FIXME: Currently QualifiedTypeLoc does not have a source range
- case Qualified:
- Cur = Cur.getNextTypeLoc();
- continue;
- default:
- if (!Cur.getLocalSourceRange().getBegin().isInvalid())
- LeftMost = Cur;
- Cur = Cur.getNextTypeLoc();
- if (Cur.isNull())
- break;
- continue;
- } // switch
- break;
- } // while
- return LeftMost.getLocalSourceRange().getBegin();
-}
-
-SourceLocation TypeLoc::getEndLoc() const {
- TypeLoc Cur = *this;
- TypeLoc Last;
- while (true) {
- switch (Cur.getTypeLocClass()) {
- default:
- if (!Last)
- Last = Cur;
- return Last.getLocalSourceRange().getEnd();
- case Paren:
- case ConstantArray:
- case DependentSizedArray:
- case IncompleteArray:
- case VariableArray:
- case FunctionNoProto:
- Last = Cur;
- break;
- case FunctionProto:
- if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
- Last = TypeLoc();
- else
- Last = Cur;
- break;
- case Pointer:
- case BlockPointer:
- case MemberPointer:
- case LValueReference:
- case RValueReference:
- case PackExpansion:
- if (!Last)
- Last = Cur;
- break;
- case Qualified:
- case Elaborated:
- break;
- }
- Cur = Cur.getNextTypeLoc();
- }
-}
-
-
-namespace {
- struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
- // Overload resolution does the real work for us.
- static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
- static bool isTypeSpec(TypeLoc _) { return false; }
-
-#define ABSTRACT_TYPELOC(CLASS, PARENT)
-#define TYPELOC(CLASS, PARENT) \
- bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
- return isTypeSpec(TyLoc); \
- }
-#include "clang/AST/TypeLocNodes.def"
- };
-}
-
-
-/// \brief Determines if the given type loc corresponds to a
-/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
-/// the type hierarchy, this is made somewhat complicated.
-///
-/// There are a lot of types that currently use TypeSpecTypeLoc
-/// because it's a convenient base class. Ideally we would not accept
-/// those here, but ideally we would have better implementations for
-/// them.
-bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
- if (TL->getType().hasLocalQualifiers()) return false;
- return TSTChecker().Visit(*TL);
-}
-
-// Reimplemented to account for GNU/C++ extension
-// typeof unary-expression
-// where there are no parentheses.
-SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
- if (getRParenLoc().isValid())
- return SourceRange(getTypeofLoc(), getRParenLoc());
- else
- return SourceRange(getTypeofLoc(),
- getUnderlyingExpr()->getSourceRange().getEnd());
-}
-
-
-TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
- if (needsExtraLocalData())
- return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
- switch (getTypePtr()->getKind()) {
- case BuiltinType::Void:
- return TST_void;
- case BuiltinType::Bool:
- return TST_bool;
- case BuiltinType::Char_U:
- case BuiltinType::Char_S:
- return TST_char;
- case BuiltinType::Char16:
- return TST_char16;
- case BuiltinType::Char32:
- return TST_char32;
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- return TST_wchar;
- case BuiltinType::UChar:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128:
- case BuiltinType::SChar:
- 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:
- llvm_unreachable("Builtin type needs extra local data!");
- // Fall through, if the impossible happens.
-
- case BuiltinType::NullPtr:
- case BuiltinType::Overload:
- case BuiltinType::Dependent:
- case BuiltinType::BoundMember:
- case BuiltinType::UnknownAny:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::PseudoObject:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- case BuiltinType::BuiltinFn:
- return TST_unspecified;
- }
-
- llvm_unreachable("Invalid BuiltinType Kind!");
-}
-
-TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
- while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
- TL = PTL->getInnerLoc();
- return TL;
-}
-
-void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
- SourceLocation Loc) {
- setElaboratedKeywordLoc(Loc);
- NestedNameSpecifierLocBuilder Builder;
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
- setQualifierLoc(Builder.getWithLocInContext(Context));
-}
-
-void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
- SourceLocation Loc) {
- setElaboratedKeywordLoc(Loc);
- NestedNameSpecifierLocBuilder Builder;
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
- setQualifierLoc(Builder.getWithLocInContext(Context));
- setNameLoc(Loc);
-}
-
-void
-DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
- SourceLocation Loc) {
- setElaboratedKeywordLoc(Loc);
- if (getTypePtr()->getQualifier()) {
- NestedNameSpecifierLocBuilder Builder;
- Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
- setQualifierLoc(Builder.getWithLocInContext(Context));
- } else {
- setQualifierLoc(NestedNameSpecifierLoc());
- }
- setTemplateKeywordLoc(Loc);
- setTemplateNameLoc(Loc);
- setLAngleLoc(Loc);
- setRAngleLoc(Loc);
- TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
- getTypePtr()->getArgs(),
- getArgInfos(), Loc);
-}
-
-void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
- unsigned NumArgs,
- const TemplateArgument *Args,
- TemplateArgumentLocInfo *ArgInfos,
- SourceLocation Loc) {
- for (unsigned i = 0, e = NumArgs; i != e; ++i) {
- switch (Args[i].getKind()) {
- case TemplateArgument::Null:
- case TemplateArgument::Declaration:
- case TemplateArgument::Integral:
- case TemplateArgument::NullPtr:
- llvm_unreachable("Impossible TemplateArgument");
-
- case TemplateArgument::Expression:
- ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
- break;
-
- case TemplateArgument::Type:
- ArgInfos[i] = TemplateArgumentLocInfo(
- Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
- Loc));
- break;
-
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion: {
- NestedNameSpecifierLocBuilder Builder;
- TemplateName Template = Args[i].getAsTemplate();
- if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
- Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
- else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
-
- ArgInfos[i] = TemplateArgumentLocInfo(
- Builder.getWithLocInContext(Context),
- Loc,
- Args[i].getKind() == TemplateArgument::Template
- ? SourceLocation()
- : Loc);
- break;
- }
-
- case TemplateArgument::Pack:
- ArgInfos[i] = TemplateArgumentLocInfo();
- break;
- }
- }
-}
+//===--- TypeLoc.cpp - Type Source Info Wrapper -----------------*- 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 TypeLoc subclasses implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// TypeLoc Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+ class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getLocalSourceRange(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
+ if (TL.isNull()) return SourceRange();
+ return TypeLocRanger().Visit(TL);
+}
+
+namespace {
+ class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getFullDataSize(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Returns the size of the type source info data block.
+unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
+ if (Ty.isNull()) return 0;
+ return TypeSizer().Visit(TypeLoc(Ty, 0));
+}
+
+namespace {
+ class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> {
+ public:
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return TyLoc.getNextTypeLoc(); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+/// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the
+/// TypeLoc is a PointerLoc and next TypeLoc is for "int".
+TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) {
+ return NextLoc().Visit(TL);
+}
+
+/// \brief Initializes a type location, and all of its children
+/// recursively, as if the entire tree had been written in the
+/// given location.
+void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL,
+ SourceLocation Loc) {
+ while (true) {
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ case CLASS: { \
+ CLASS##TypeLoc TLCasted = cast<CLASS##TypeLoc>(TL); \
+ TLCasted.initializeLocal(Context, Loc); \
+ TL = TLCasted.getNextTypeLoc(); \
+ if (!TL) return; \
+ continue; \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ }
+ }
+}
+
+SourceLocation TypeLoc::getBeginLoc() const {
+ TypeLoc Cur = *this;
+ TypeLoc LeftMost = Cur;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ case Elaborated:
+ LeftMost = Cur;
+ break;
+ case FunctionProto:
+ if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) {
+ LeftMost = Cur;
+ break;
+ }
+ /* Fall through */
+ case FunctionNoProto:
+ case ConstantArray:
+ case DependentSizedArray:
+ case IncompleteArray:
+ case VariableArray:
+ // FIXME: Currently QualifiedTypeLoc does not have a source range
+ case Qualified:
+ Cur = Cur.getNextTypeLoc();
+ continue;
+ default:
+ if (!Cur.getLocalSourceRange().getBegin().isInvalid())
+ LeftMost = Cur;
+ Cur = Cur.getNextTypeLoc();
+ if (Cur.isNull())
+ break;
+ continue;
+ } // switch
+ break;
+ } // while
+ return LeftMost.getLocalSourceRange().getBegin();
+}
+
+SourceLocation TypeLoc::getEndLoc() const {
+ TypeLoc Cur = *this;
+ TypeLoc Last;
+ while (true) {
+ switch (Cur.getTypeLocClass()) {
+ default:
+ if (!Last)
+ Last = Cur;
+ return Last.getLocalSourceRange().getEnd();
+ case Paren:
+ case ConstantArray:
+ case DependentSizedArray:
+ case IncompleteArray:
+ case VariableArray:
+ case FunctionNoProto:
+ Last = Cur;
+ break;
+ case FunctionProto:
+ if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn())
+ Last = TypeLoc();
+ else
+ Last = Cur;
+ break;
+ case Pointer:
+ case BlockPointer:
+ case MemberPointer:
+ case LValueReference:
+ case RValueReference:
+ case PackExpansion:
+ if (!Last)
+ Last = Cur;
+ break;
+ case Qualified:
+ case Elaborated:
+ break;
+ }
+ Cur = Cur.getNextTypeLoc();
+ }
+}
+
+
+namespace {
+ struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+ // Overload resolution does the real work for us.
+ static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+ static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+ return isTypeSpec(TyLoc); \
+ }
+#include "clang/AST/TypeLocNodes.def"
+ };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class. Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+ if (TL->getType().hasLocalQualifiers()) return false;
+ return TSTChecker().Visit(*TL);
+}
+
+// Reimplemented to account for GNU/C++ extension
+// typeof unary-expression
+// where there are no parentheses.
+SourceRange TypeOfExprTypeLoc::getLocalSourceRange() const {
+ if (getRParenLoc().isValid())
+ return SourceRange(getTypeofLoc(), getRParenLoc());
+ else
+ return SourceRange(getTypeofLoc(),
+ getUnderlyingExpr()->getSourceRange().getEnd());
+}
+
+
+TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
+ if (needsExtraLocalData())
+ return static_cast<TypeSpecifierType>(getWrittenBuiltinSpecs().Type);
+ switch (getTypePtr()->getKind()) {
+ case BuiltinType::Void:
+ return TST_void;
+ case BuiltinType::Bool:
+ return TST_bool;
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ return TST_char;
+ case BuiltinType::Char16:
+ return TST_char16;
+ case BuiltinType::Char32:
+ return TST_char32;
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ return TST_wchar;
+ case BuiltinType::UChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::SChar:
+ 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:
+ llvm_unreachable("Builtin type needs extra local data!");
+ // Fall through, if the impossible happens.
+
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ case BuiltinType::BoundMember:
+ case BuiltinType::UnknownAny:
+ case BuiltinType::ARCUnbridgedCast:
+ case BuiltinType::PseudoObject:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ case BuiltinType::BuiltinFn:
+ return TST_unspecified;
+ }
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
+
+TypeLoc TypeLoc::IgnoreParensImpl(TypeLoc TL) {
+ while (ParenTypeLoc* PTL = dyn_cast<ParenTypeLoc>(&TL))
+ TL = PTL->getInnerLoc();
+ return TL;
+}
+
+void ElaboratedTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+}
+
+void DependentNameTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ setNameLoc(Loc);
+}
+
+void
+DependentTemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
+ SourceLocation Loc) {
+ setElaboratedKeywordLoc(Loc);
+ if (getTypePtr()->getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, getTypePtr()->getQualifier(), Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ } else {
+ setQualifierLoc(NestedNameSpecifierLoc());
+ }
+ setTemplateKeywordLoc(Loc);
+ setTemplateNameLoc(Loc);
+ setLAngleLoc(Loc);
+ setRAngleLoc(Loc);
+ TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
+ getTypePtr()->getArgs(),
+ getArgInfos(), Loc);
+}
+
+void TemplateSpecializationTypeLoc::initializeArgLocs(ASTContext &Context,
+ unsigned NumArgs,
+ const TemplateArgument *Args,
+ TemplateArgumentLocInfo *ArgInfos,
+ SourceLocation Loc) {
+ for (unsigned i = 0, e = NumArgs; i != e; ++i) {
+ switch (Args[i].getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ case TemplateArgument::NullPtr:
+ llvm_unreachable("Impossible TemplateArgument");
+
+ case TemplateArgument::Expression:
+ ArgInfos[i] = TemplateArgumentLocInfo(Args[i].getAsExpr());
+ break;
+
+ case TemplateArgument::Type:
+ ArgInfos[i] = TemplateArgumentLocInfo(
+ Context.getTrivialTypeSourceInfo(Args[i].getAsType(),
+ Loc));
+ break;
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
+ NestedNameSpecifierLocBuilder Builder;
+ TemplateName Template = Args[i].getAsTemplate();
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ Builder.MakeTrivial(Context, DTN->getQualifier(), Loc);
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ Builder.MakeTrivial(Context, QTN->getQualifier(), Loc);
+
+ ArgInfos[i] = TemplateArgumentLocInfo(
+ Builder.getWithLocInContext(Context),
+ Loc,
+ Args[i].getKind() == TemplateArgument::Template
+ ? SourceLocation()
+ : Loc);
+ break;
+ }
+
+ case TemplateArgument::Pack:
+ ArgInfos[i] = TemplateArgumentLocInfo();
+ break;
+ }
+ }
+}
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Tue Dec 18 08:30:41 2012
@@ -1,2834 +1,2802 @@
-//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This coordinates the debug information generation while generating code.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CGDebugInfo.h"
-#include "CGBlocks.h"
-#include "CGObjCRuntime.h"
-#include "CodeGenFunction.h"
-#include "CodeGenModule.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DeclFriend.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/Version.h"
-#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Constants.h"
-#include "llvm/DataLayout.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
-#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/FileSystem.h"
-using namespace clang;
-using namespace clang::CodeGen;
-
-CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
- : CGM(CGM), DBuilder(CGM.getModule()),
- BlockLiteralGenericSet(false) {
- CreateCompileUnit();
-}
-
-CGDebugInfo::~CGDebugInfo() {
- assert(LexicalBlockStack.empty() &&
- "Region stack mismatch, stack not empty!");
-}
-
-void CGDebugInfo::setLocation(SourceLocation Loc) {
- // If the new location isn't valid return.
- if (!Loc.isValid()) return;
-
- CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
-
- // If we've changed files in the middle of a lexical scope go ahead
- // and create a new lexical scope with file node if it's different
- // from the one in the scope.
- if (LexicalBlockStack.empty()) return;
-
- SourceManager &SM = CGM.getContext().getSourceManager();
- PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
- PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
-
- if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
- !strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
- return;
-
- llvm::MDNode *LB = LexicalBlockStack.back();
- llvm::DIScope Scope = llvm::DIScope(LB);
- if (Scope.isLexicalBlockFile()) {
- llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB);
- llvm::DIDescriptor D
- = DBuilder.createLexicalBlockFile(LBF.getScope(),
- getOrCreateFile(CurLoc));
- llvm::MDNode *N = D;
- LexicalBlockStack.pop_back();
- LexicalBlockStack.push_back(N);
- } else if (Scope.isLexicalBlock()) {
- llvm::DIDescriptor D
- = DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
- llvm::MDNode *N = D;
- LexicalBlockStack.pop_back();
- LexicalBlockStack.push_back(N);
- }
-}
-
-/// getContextDescriptor - Get context info for the decl.
-llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) {
- if (!Context)
- return TheCU;
-
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- I = RegionMap.find(Context);
- if (I != RegionMap.end()) {
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
- }
-
- // Check namespace.
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
-
- if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {
- if (!RDecl->isDependentType()) {
- llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
- getOrCreateMainFile());
- return llvm::DIDescriptor(Ty);
- }
- }
- return TheCU;
-}
-
-/// getFunctionName - Get function name for the given FunctionDecl. If the
-/// name is constructred on demand (e.g. C++ destructor) then the name
-/// is stored on the side.
-StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
- assert (FD && "Invalid FunctionDecl!");
- IdentifierInfo *FII = FD->getIdentifier();
- FunctionTemplateSpecializationInfo *Info
- = FD->getTemplateSpecializationInfo();
- if (!Info && FII)
- return FII->getName();
-
- // Otherwise construct human readable name for debug info.
- std::string NS = FD->getNameAsString();
-
- // Add any template specialization args.
- if (Info) {
- const TemplateArgumentList *TArgs = Info->TemplateArguments;
- const TemplateArgument *Args = TArgs->data();
- unsigned NumArgs = TArgs->size();
- PrintingPolicy Policy(CGM.getLangOpts());
- NS += TemplateSpecializationType::PrintTemplateArgumentList(Args,
- NumArgs,
- Policy);
- }
-
- // Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
- memcpy(StrPtr, NS.data(), NS.length());
- return StringRef(StrPtr, NS.length());
-}
-
-StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
- SmallString<256> MethodName;
- llvm::raw_svector_ostream OS(MethodName);
- OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
- const DeclContext *DC = OMD->getDeclContext();
- if (const ObjCImplementationDecl *OID =
- dyn_cast<const ObjCImplementationDecl>(DC)) {
- OS << OID->getName();
- } else if (const ObjCInterfaceDecl *OID =
- dyn_cast<const ObjCInterfaceDecl>(DC)) {
- OS << OID->getName();
- } else if (const ObjCCategoryImplDecl *OCD =
- dyn_cast<const ObjCCategoryImplDecl>(DC)){
- OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
- OCD->getIdentifier()->getNameStart() << ')';
- }
- OS << ' ' << OMD->getSelector().getAsString() << ']';
-
- char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
- memcpy(StrPtr, MethodName.begin(), OS.tell());
- return StringRef(StrPtr, OS.tell());
-}
-
-/// getSelectorName - Return selector name. This is used for debugging
-/// info.
-StringRef CGDebugInfo::getSelectorName(Selector S) {
- const std::string &SName = S.getAsString();
- char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());
- memcpy(StrPtr, SName.data(), SName.size());
- return StringRef(StrPtr, SName.size());
-}
-
-/// getClassName - Get class name including template argument list.
-StringRef
-CGDebugInfo::getClassName(const RecordDecl *RD) {
- const ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(RD);
- if (!Spec)
- return RD->getName();
-
- const TemplateArgument *Args;
- unsigned NumArgs;
- if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
- const TemplateSpecializationType *TST =
- cast<TemplateSpecializationType>(TAW->getType());
- Args = TST->getArgs();
- NumArgs = TST->getNumArgs();
- } else {
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- Args = TemplateArgs.data();
- NumArgs = TemplateArgs.size();
- }
- StringRef Name = RD->getIdentifier()->getName();
- PrintingPolicy Policy(CGM.getLangOpts());
- std::string TemplateArgList =
- TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);
-
- // Copy this name on the side and use its reference.
- size_t Length = Name.size() + TemplateArgList.size();
- char *StrPtr = DebugInfoNames.Allocate<char>(Length);
- memcpy(StrPtr, Name.data(), Name.size());
- memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
- return StringRef(StrPtr, Length);
-}
-
-/// getOrCreateFile - Get the file debug info descriptor for the input location.
-llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
- if (!Loc.isValid())
- // If Location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
-
- SourceManager &SM = CGM.getContext().getSourceManager();
- PresumedLoc PLoc = SM.getPresumedLoc(Loc);
-
- if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
- // If the location is not valid then use main input file.
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
-
- // Cache the results.
- const char *fname = PLoc.getFilename();
- llvm::DenseMap<const char *, llvm::WeakVH>::iterator it =
- DIFileCache.find(fname);
-
- if (it != DIFileCache.end()) {
- // Verify that the information still exists.
- if (llvm::Value *V = it->second)
- return llvm::DIFile(cast<llvm::MDNode>(V));
- }
-
- llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
-
- DIFileCache[fname] = F;
- return F;
-}
-
-/// getOrCreateMainFile - Get the file info for main compile unit.
-llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
- return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
-}
-
-/// getLineNumber - Get line number for the location. If location is invalid
-/// then use current location.
-unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
- if (Loc.isInvalid() && CurLoc.isInvalid())
- return 0;
- SourceManager &SM = CGM.getContext().getSourceManager();
- PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
- return PLoc.isValid()? PLoc.getLine() : 0;
-}
-
-/// getColumnNumber - Get column number for the location.
-unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
- // We may not want column information at all.
- if (!CGM.getCodeGenOpts().DebugColumnInfo)
- return 0;
-
- // If the location is invalid then use the current column.
- if (Loc.isInvalid() && CurLoc.isInvalid())
- return 0;
- SourceManager &SM = CGM.getContext().getSourceManager();
- PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
- return PLoc.isValid()? PLoc.getColumn() : 0;
-}
-
-StringRef CGDebugInfo::getCurrentDirname() {
- if (!CGM.getCodeGenOpts().DebugCompilationDir.empty())
- return CGM.getCodeGenOpts().DebugCompilationDir;
-
- if (!CWDName.empty())
- return CWDName;
- SmallString<256> CWD;
- llvm::sys::fs::current_path(CWD);
- char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
- memcpy(CompDirnamePtr, CWD.data(), CWD.size());
- return CWDName = StringRef(CompDirnamePtr, CWD.size());
-}
-
-/// CreateCompileUnit - Create new compile unit.
-void CGDebugInfo::CreateCompileUnit() {
-
- // Get absolute path name.
- SourceManager &SM = CGM.getContext().getSourceManager();
- std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
- if (MainFileName.empty())
- MainFileName = "<unknown>";
-
- // The main file name provided via the "-main-file-name" option contains just
- // the file name itself with no path information. This file name may have had
- // a relative path, so we look into the actual file entry for the main
- // file to determine the real absolute path for the file.
- std::string MainFileDir;
- if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
- MainFileDir = MainFile->getDir()->getName();
- if (MainFileDir != ".")
- MainFileName = MainFileDir + "/" + MainFileName;
- }
-
- // Save filename string.
- char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
- memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
- StringRef Filename(FilenamePtr, MainFileName.length());
-
- unsigned LangTag;
- const LangOptions &LO = CGM.getLangOpts();
- if (LO.CPlusPlus) {
- if (LO.ObjC1)
- LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
- else
- LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
- } else if (LO.ObjC1) {
- LangTag = llvm::dwarf::DW_LANG_ObjC;
- } else if (LO.C99) {
- LangTag = llvm::dwarf::DW_LANG_C99;
- } else {
- LangTag = llvm::dwarf::DW_LANG_C89;
- }
-
- std::string Producer = getClangFullVersion();
-
- // Figure out which version of the ObjC runtime we have.
- unsigned RuntimeVers = 0;
- if (LO.ObjC1)
- RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;
-
- // Create new compile unit.
- DBuilder.createCompileUnit(
- LangTag, Filename, getCurrentDirname(),
- Producer,
- LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
- // FIXME - Eliminate TheCU.
- TheCU = llvm::DICompileUnit(DBuilder.getCU());
-}
-
-/// CreateType - Get the Basic type from the cache or create a new
-/// one if necessary.
-llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
- unsigned Encoding = 0;
- StringRef BTName;
- 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");
- case BuiltinType::NullPtr:
- return DBuilder.
- createNullPtrType(BT->getName(CGM.getLangOpts()));
- case BuiltinType::Void:
- return llvm::DIType();
- case BuiltinType::ObjCClass:
- if (ClassTy.Verify())
- return ClassTy;
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_class", TheCU,
- getOrCreateMainFile(), 0);
- return ClassTy;
- case BuiltinType::ObjCId: {
- // typedef struct objc_class *Class;
- // typedef struct objc_object {
- // Class isa;
- // } *id;
-
- if (ObjTy.Verify())
- return ObjTy;
-
- if (!ClassTy.Verify())
- ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_class", TheCU,
- getOrCreateMainFile(), 0);
-
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
-
- llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
-
- llvm::DIType FwdTy = DBuilder.createStructType(TheCU, "objc_object",
- getOrCreateMainFile(),
- 0, 0, 0, 0,
- llvm::DIArray());
-
- llvm::TrackingVH<llvm::MDNode> ObjNode(FwdTy);
- SmallVector<llvm::Value *, 1> EltTys;
- llvm::DIType FieldTy =
- DBuilder.createMemberType(llvm::DIDescriptor(ObjNode), "isa",
- getOrCreateMainFile(), 0, Size,
- 0, 0, 0, ISATy);
- EltTys.push_back(FieldTy);
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
-
- ObjNode->replaceOperandWith(10, Elements);
- ObjTy = llvm::DIType(ObjNode);
- return ObjTy;
- }
- case BuiltinType::ObjCSel: {
- if (SelTy.Verify())
- return SelTy;
- SelTy =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- "objc_selector", TheCU, getOrCreateMainFile(),
- 0);
- return SelTy;
- }
-
- case BuiltinType::OCLImage1d:
- return getOrCreateStructPtrType("opencl_image1d_t",
- OCLImage1dDITy);
- case BuiltinType::OCLImage1dArray:
- return getOrCreateStructPtrType("opencl_image1d_array_t",
- OCLImage1dArrayDITy);
- case BuiltinType::OCLImage1dBuffer:
- return getOrCreateStructPtrType("opencl_image1d_buffer_t",
- OCLImage1dBufferDITy);
- case BuiltinType::OCLImage2d:
- return getOrCreateStructPtrType("opencl_image2d_t",
- OCLImage2dDITy);
- case BuiltinType::OCLImage2dArray:
- return getOrCreateStructPtrType("opencl_image2d_array_t",
- OCLImage2dArrayDITy);
- case BuiltinType::OCLImage3d:
- return getOrCreateStructPtrType("opencl_image3d_t",
- OCLImage3dDITy);
-
- case BuiltinType::UChar:
- case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
- case BuiltinType::Char_S:
- case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;
- case BuiltinType::Char16:
- case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break;
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::UInt128:
- case BuiltinType::ULong:
- case BuiltinType::WChar_U:
- case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Int128:
- case BuiltinType::Long:
- case BuiltinType::WChar_S:
- case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
- case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::LongDouble:
- case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
- }
-
- switch (BT->getKind()) {
- case BuiltinType::Long: BTName = "long int"; break;
- case BuiltinType::LongLong: BTName = "long long int"; break;
- case BuiltinType::ULong: BTName = "long unsigned int"; break;
- case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
- default:
- BTName = BT->getName(CGM.getLangOpts());
- break;
- }
- // Bit size, align and offset of the type.
- uint64_t Size = CGM.getContext().getTypeSize(BT);
- uint64_t Align = CGM.getContext().getTypeAlign(BT);
- llvm::DIType DbgTy =
- DBuilder.createBasicType(BTName, Size, Align, Encoding);
- return DbgTy;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
- // Bit size, align and offset of the type.
- unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
- if (Ty->isComplexIntegerType())
- Encoding = llvm::dwarf::DW_ATE_lo_user;
-
- uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- llvm::DIType DbgTy =
- DBuilder.createBasicType("complex", Size, Align, Encoding);
-
- return DbgTy;
-}
-
-/// CreateCVRType - Get the qualified type from the cache or create
-/// a new one if necessary.
-llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
- QualifierCollector Qc;
- const Type *T = Qc.strip(Ty);
-
- // Ignore these qualifiers for now.
- Qc.removeObjCGCAttr();
- Qc.removeAddressSpace();
- Qc.removeObjCLifetime();
-
- // We will create one Derived type for one qualifier and recurse to handle any
- // additional ones.
- unsigned Tag;
- if (Qc.hasConst()) {
- Tag = llvm::dwarf::DW_TAG_const_type;
- Qc.removeConst();
- } else if (Qc.hasVolatile()) {
- Tag = llvm::dwarf::DW_TAG_volatile_type;
- Qc.removeVolatile();
- } else if (Qc.hasRestrict()) {
- Tag = llvm::dwarf::DW_TAG_restrict_type;
- Qc.removeRestrict();
- } else {
- assert(Qc.empty() && "Unknown type qualifier for debug info");
- return getOrCreateType(QualType(T, 0), Unit);
- }
-
- llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
-
- // No need to fill in the Name, Line, Size, Alignment, Offset in case of
- // CVR derived types.
- llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
-
- return DbgTy;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
- llvm::DIFile Unit) {
- llvm::DIType DbgTy =
- CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
- Ty->getPointeeType(), Unit);
- return DbgTy;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
- llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
- Ty->getPointeeType(), Unit);
-}
-
-// Creates a forward declaration for a RecordDecl in the given context.
-llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
- llvm::DIDescriptor Ctx) {
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
- unsigned Line = getLineNumber(RD->getLocation());
- StringRef RDName = getClassName(RD);
-
- unsigned Tag = 0;
- if (RD->isStruct() || RD->isInterface())
- Tag = llvm::dwarf::DW_TAG_structure_type;
- else if (RD->isUnion())
- Tag = llvm::dwarf::DW_TAG_union_type;
- else {
- assert(RD->isClass());
- Tag = llvm::dwarf::DW_TAG_class_type;
- }
-
- // Create the type.
- return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line);
-}
-
-// Walk up the context chain and create forward decls for record decls,
-// and normal descriptors for namespaces.
-llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
- if (!Context)
- return TheCU;
-
- // See if we already have the parent.
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- I = RegionMap.find(Context);
- if (I != RegionMap.end()) {
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
- }
-
- // Check namespace.
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
-
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
- if (!RD->isDependentType()) {
- llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
- getOrCreateMainFile());
- return llvm::DIDescriptor(Ty);
- }
- }
- return TheCU;
-}
-
-/// CreatePointeeType - Create Pointee type. If Pointee is a record
-/// then emit record's fwd if debug info size reduction is enabled.
-llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
- llvm::DIFile Unit) {
- if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo)
- return getOrCreateType(PointeeTy, Unit);
-
- // Limit debug info for the pointee type.
-
- // If we have an existing type, use that, it's still smaller than creating
- // a new type.
- llvm::DIType Ty = getTypeOrNull(PointeeTy);
- if (Ty.Verify()) return Ty;
-
- // Handle qualifiers.
- if (PointeeTy.hasLocalQualifiers())
- return CreateQualifiedType(PointeeTy, Unit);
-
- if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
- RecordDecl *RD = RTy->getDecl();
- llvm::DIDescriptor FDContext =
- getContextDescriptor(cast<Decl>(RD->getDeclContext()));
- llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
- TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;
- return RetTy;
- }
- return getOrCreateType(PointeeTy, Unit);
-
-}
-
-llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
- const Type *Ty,
- QualType PointeeTy,
- llvm::DIFile Unit) {
- if (Tag == llvm::dwarf::DW_TAG_reference_type ||
- Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
- return DBuilder.createReferenceType(Tag,
- CreatePointeeType(PointeeTy, Unit));
-
- // Bit size, align and offset of the type.
- // Size is always the size of a pointer. We can't use getTypeSize here
- // because that does not return the correct value for references.
- unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
- uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
-
- return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit),
- Size, Align);
-}
-
-llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache) {
- if (Cache.Verify())
- return Cache;
- Cache =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Name, TheCU, getOrCreateMainFile(),
- 0);
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- Cache = DBuilder.createPointerType(Cache, Size);
- return Cache;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
- llvm::DIFile Unit) {
- if (BlockLiteralGenericSet)
- return BlockLiteralGeneric;
-
- SmallVector<llvm::Value *, 8> EltTys;
- llvm::DIType FieldTy;
- QualType FType;
- uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
- llvm::DIArray Elements;
- llvm::DIType EltTy, DescTy;
-
- FieldOffset = 0;
- FType = CGM.getContext().UnsignedLongTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
-
- Elements = DBuilder.getOrCreateArray(EltTys);
- EltTys.clear();
-
- unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
- unsigned LineNo = getLineNumber(CurLoc);
-
- EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
- Unit, LineNo, FieldOffset, 0,
- Flags, Elements);
-
- // Bit size, align and offset of the type.
- uint64_t Size = CGM.getContext().getTypeSize(Ty);
-
- DescTy = DBuilder.createPointerType(EltTy, Size);
-
- FieldOffset = 0;
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
- FType = CGM.getContext().IntTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
-
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- FieldTy = DescTy;
- FieldSize = CGM.getContext().getTypeSize(Ty);
- FieldAlign = CGM.getContext().getTypeAlign(Ty);
- FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit,
- LineNo, FieldSize, FieldAlign,
- FieldOffset, 0, FieldTy);
- EltTys.push_back(FieldTy);
-
- FieldOffset += FieldSize;
- Elements = DBuilder.getOrCreateArray(EltTys);
-
- EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
- Unit, LineNo, FieldOffset, 0,
- Flags, Elements);
-
- BlockLiteralGenericSet = true;
- BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
- return BlockLiteralGeneric;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
- // Typedefs are derived from some other type. If we have a typedef of a
- // typedef, make sure to emit the whole chain.
- llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
- if (!Src.Verify())
- return llvm::DIType();
- // We don't set size information, but do specify where the typedef was
- // declared.
- unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
- const TypedefNameDecl *TyDecl = Ty->getDecl();
-
- llvm::DIDescriptor TypedefContext =
- getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
-
- return
- DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
- llvm::DIFile Unit) {
- SmallVector<llvm::Value *, 16> EltTys;
-
- // Add the result type at least.
- EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
-
- // Set up remainder of arguments if there is a prototype.
- // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
- if (isa<FunctionNoProtoType>(Ty))
- EltTys.push_back(DBuilder.createUnspecifiedParameter());
- else if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Ty)) {
- for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i)
- EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit));
- }
-
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys);
- return DBuilder.createSubroutineType(Unit, EltTypeArray);
-}
-
-
-void CGDebugInfo::
-CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) {
-
- for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
- I != E; ++I)
- if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
- if (V->getInit()) {
- const APValue *Value = V->evaluateValue();
- if (Value && Value->isInt()) {
- llvm::ConstantInt *CI
- = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
-
- // Create the descriptor for static variable.
- llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
- StringRef VName = V->getName();
- llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
- // Do not use DIGlobalVariable for enums.
- if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
- DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
- getLineNumber(V->getLocation()),
- VTy, true, CI);
- }
- }
- }
- }
-}
-
-llvm::DIType CGDebugInfo::createFieldType(StringRef name,
- QualType type,
- uint64_t sizeInBitsOverride,
- SourceLocation loc,
- AccessSpecifier AS,
- uint64_t offsetInBits,
- llvm::DIFile tunit,
- llvm::DIDescriptor scope) {
- llvm::DIType debugType = getOrCreateType(type, tunit);
-
- // Get the location for the field.
- llvm::DIFile file = getOrCreateFile(loc);
- unsigned line = getLineNumber(loc);
-
- uint64_t sizeInBits = 0;
- unsigned alignInBits = 0;
- if (!type->isIncompleteArrayType()) {
- llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
-
- if (sizeInBitsOverride)
- sizeInBits = sizeInBitsOverride;
- }
-
- unsigned flags = 0;
- if (AS == clang::AS_private)
- flags |= llvm::DIDescriptor::FlagPrivate;
- else if (AS == clang::AS_protected)
- flags |= llvm::DIDescriptor::FlagProtected;
-
- return DBuilder.createMemberType(scope, name, file, line, sizeInBits,
- alignInBits, offsetInBits, flags, debugType);
-}
-
-/// CollectRecordFields - A helper function to collect debug info for
-/// record fields. This is used while creating debug info entry for a Record.
-void CGDebugInfo::
-CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
- SmallVectorImpl<llvm::Value *> &elements,
- llvm::DIType RecordTy) {
- unsigned fieldNo = 0;
- const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
-
- // For C++11 Lambdas a Field will be the same as a Capture, but the Capture
- // has the name and the location of the variable so we should iterate over
- // both concurrently.
- if (CXXDecl && CXXDecl->isLambda()) {
- RecordDecl::field_iterator Field = CXXDecl->field_begin();
- unsigned fieldno = 0;
- for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
- E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {
- const LambdaExpr::Capture C = *I;
- if (C.capturesVariable()) {
- VarDecl *V = C.getCapturedVar();
- llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
- StringRef VName = V->getName();
- uint64_t SizeInBitsOverride = 0;
- if (Field->isBitField()) {
- SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());
- assert(SizeInBitsOverride && "found named 0-width bitfield");
- }
- llvm::DIType fieldType
- = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(),
- Field->getAccess(), layout.getFieldOffset(fieldno),
- VUnit, RecordTy);
- elements.push_back(fieldType);
- } else {
- // TODO: Need to handle 'this' in some way by probably renaming the
- // this of the lambda class and having a field member of 'this' or
- // by using AT_object_pointer for the function and having that be
- // used as 'this' for semantic references.
- assert(C.capturesThis() && "Field that isn't captured and isn't this?");
- FieldDecl *f = *Field;
- llvm::DIFile VUnit = getOrCreateFile(f->getLocation());
- QualType type = f->getType();
- llvm::DIType fieldType
- = createFieldType("this", type, 0, f->getLocation(), f->getAccess(),
- layout.getFieldOffset(fieldNo), VUnit, RecordTy);
-
- elements.push_back(fieldType);
- }
- }
- } else {
- bool IsMsStruct = record->isMsStruct(CGM.getContext());
- const FieldDecl *LastFD = 0;
- for (RecordDecl::field_iterator I = record->field_begin(),
- E = record->field_end();
- I != E; ++I, ++fieldNo) {
- FieldDecl *field = *I;
-
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are ignored
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) {
- --fieldNo;
- continue;
- }
- LastFD = field;
- }
-
- StringRef name = field->getName();
- QualType type = field->getType();
-
- // Ignore unnamed fields unless they're anonymous structs/unions.
- if (name.empty() && !type->isRecordType()) {
- LastFD = field;
- continue;
- }
-
- uint64_t SizeInBitsOverride = 0;
- if (field->isBitField()) {
- SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());
- assert(SizeInBitsOverride && "found named 0-width bitfield");
- }
-
- llvm::DIType fieldType
- = createFieldType(name, type, SizeInBitsOverride,
- field->getLocation(), field->getAccess(),
- layout.getFieldOffset(fieldNo), tunit, RecordTy);
-
- elements.push_back(fieldType);
- }
- }
-}
-
-/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
-/// function type is not updated to include implicit "this" pointer. Use this
-/// routine to get a method type which includes "this" pointer.
-llvm::DIType
-CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile Unit) {
- llvm::DIType FnTy
- = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),
- 0),
- Unit);
-
- // Add "this" pointer.
- llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();
- assert (Args.getNumElements() && "Invalid number of arguments!");
-
- SmallVector<llvm::Value *, 16> Elts;
-
- // First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(Args.getElement(0));
-
- if (!Method->isStatic()) {
- // "this" pointer is always first argument.
- QualType ThisPtr = Method->getThisType(CGM.getContext());
-
- const CXXRecordDecl *RD = Method->getParent();
- if (isa<ClassTemplateSpecializationDecl>(RD)) {
- // Create pointer type directly in this case.
- const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);
- QualType PointeeTy = ThisPtrTy->getPointeeType();
- unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
- uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
- llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
- llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align);
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
- // TODO: This and the artificial type below are misleading, the
- // types aren't artificial the argument is, but the current
- // metadata doesn't represent that.
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- } else {
- llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- }
- }
-
- // Copy rest of the arguments.
- for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
- Elts.push_back(Args.getElement(i));
-
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
-
- return DBuilder.createSubroutineType(Unit, EltTypeArray);
-}
-
-/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
-/// inside a function.
-static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
- if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
- return isFunctionLocalClass(NRD);
- if (isa<FunctionDecl>(RD->getDeclContext()))
- return true;
- return false;
-}
-
-/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
-/// a single member function GlobalDecl.
-llvm::DISubprogram
-CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
- llvm::DIFile Unit,
- llvm::DIType RecordTy) {
- bool IsCtorOrDtor =
- isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
-
- StringRef MethodName = getFunctionName(Method);
- llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
-
- // Since a single ctor/dtor corresponds to multiple functions, it doesn't
- // make sense to give a single ctor/dtor a linkage name.
- StringRef MethodLinkageName;
- if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))
- MethodLinkageName = CGM.getMangledName(Method);
-
- // Get the location for the method.
- llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
- unsigned MethodLine = getLineNumber(Method->getLocation());
-
- // Collect virtual method info.
- llvm::DIType ContainingType;
- unsigned Virtuality = 0;
- unsigned VIndex = 0;
-
- if (Method->isVirtual()) {
- if (Method->isPure())
- Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
- else
- Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
-
- // It doesn't make sense to give a virtual destructor a vtable index,
- // since a single destructor has two entries in the vtable.
- if (!isa<CXXDestructorDecl>(Method))
- VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);
- ContainingType = RecordTy;
- }
-
- unsigned Flags = 0;
- if (Method->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
- AccessSpecifier Access = Method->getAccess();
- if (Access == clang::AS_private)
- Flags |= llvm::DIDescriptor::FlagPrivate;
- else if (Access == clang::AS_protected)
- Flags |= llvm::DIDescriptor::FlagProtected;
- if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
- if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
- } else if (const CXXConversionDecl *CXXC =
- dyn_cast<CXXConversionDecl>(Method)) {
- if (CXXC->isExplicit())
- Flags |= llvm::DIDescriptor::FlagExplicit;
- }
- if (Method->hasPrototype())
- Flags |= llvm::DIDescriptor::FlagPrototyped;
-
- llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
- llvm::DISubprogram SP =
- DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
- MethodDefUnit, MethodLine,
- MethodTy, /*isLocalToUnit=*/false,
- /* isDefinition=*/ false,
- Virtuality, VIndex, ContainingType,
- Flags, CGM.getLangOpts().Optimize, NULL,
- TParamsArray);
-
- SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);
-
- return SP;
-}
-
-/// CollectCXXMemberFunctions - A helper function to collect debug info for
-/// C++ member functions. This is used while creating debug info entry for
-/// a Record.
-void CGDebugInfo::
-CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy) {
-
- // Since we want more than just the individual member decls if we
- // have templated functions iterate over every declaration to gather
- // the functions.
- for(DeclContext::decl_iterator I = RD->decls_begin(),
- E = RD->decls_end(); I != E; ++I) {
- Decl *D = *I;
- if (D->isImplicit() && !D->isUsed())
- continue;
-
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
- else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
- for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(),
- SE = FTD->spec_end(); SI != SE; ++SI)
- EltTys.push_back(CreateCXXMemberFunction(cast<CXXMethodDecl>(*SI), Unit,
- RecordTy));
- }
-}
-
-/// CollectCXXFriends - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
-/// a Record.
-void CGDebugInfo::
-CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy) {
- for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
- BE = RD->friend_end(); BI != BE; ++BI) {
- if ((*BI)->isUnsupportedFriend())
- continue;
- if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.createFriend(RecordTy,
- getOrCreateType(TInfo->getType(),
- Unit)));
- }
-}
-
-/// CollectCXXBases - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
-/// a Record.
-void CGDebugInfo::
-CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy) {
-
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
- BE = RD->bases_end(); BI != BE; ++BI) {
- unsigned BFlags = 0;
- uint64_t BaseOffset;
-
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
-
- if (BI->isVirtual()) {
- // virtual base offset offset is -ve. The code generator emits dwarf
- // expression where it expects +ve number.
- BaseOffset =
- 0 - CGM.getVTableContext()
- .getVirtualBaseOffsetOffset(RD, Base).getQuantity();
- BFlags = llvm::DIDescriptor::FlagVirtual;
- } else
- BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
- // FIXME: Inconsistent units for BaseOffset. It is in bytes when
- // BI->isVirtual() and bits when not.
-
- AccessSpecifier Access = BI->getAccessSpecifier();
- if (Access == clang::AS_private)
- BFlags |= llvm::DIDescriptor::FlagPrivate;
- else if (Access == clang::AS_protected)
- BFlags |= llvm::DIDescriptor::FlagProtected;
-
- llvm::DIType DTy =
- DBuilder.createInheritance(RecordTy,
- getOrCreateType(BI->getType(), Unit),
- BaseOffset, BFlags);
- EltTys.push_back(DTy);
- }
-}
-
-/// CollectTemplateParams - A helper function to collect template parameters.
-llvm::DIArray CGDebugInfo::
-CollectTemplateParams(const TemplateParameterList *TPList,
- const TemplateArgumentList &TAList,
- llvm::DIFile Unit) {
- SmallVector<llvm::Value *, 16> TemplateParams;
- for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
- const TemplateArgument &TA = TAList[i];
- const NamedDecl *ND = TPList->getParam(i);
- if (TA.getKind() == TemplateArgument::Type) {
- llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
- llvm::DITemplateTypeParameter TTP =
- DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);
- TemplateParams.push_back(TTP);
- } else if (TA.getKind() == TemplateArgument::Integral) {
- llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
- llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
- TA.getAsIntegral().getZExtValue());
- TemplateParams.push_back(TVP);
- }
- }
- return DBuilder.getOrCreateArray(TemplateParams);
-}
-
-/// CollectFunctionTemplateParams - A helper function to collect debug
-/// info for function template parameters.
-llvm::DIArray CGDebugInfo::
-CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {
- if (FD->getTemplatedKind() ==
- FunctionDecl::TK_FunctionTemplateSpecialization) {
- const TemplateParameterList *TList =
- FD->getTemplateSpecializationInfo()->getTemplate()
- ->getTemplateParameters();
- return
- CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);
- }
- return llvm::DIArray();
-}
-
-/// CollectCXXTemplateParams - A helper function to collect debug info for
-/// template parameters.
-llvm::DIArray CGDebugInfo::
-CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
- llvm::DIFile Unit) {
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- PU = TSpecial->getSpecializedTemplateOrPartial();
-
- TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
- PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
- PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
- const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
- return CollectTemplateParams(TPList, TAList, Unit);
-}
-
-/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
-llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
- if (VTablePtrType.isValid())
- return VTablePtrType;
-
- ASTContext &Context = CGM.getContext();
-
- /* Function type */
- llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
- llvm::DIArray SElements = DBuilder.getOrCreateArray(STy);
- llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
- unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
- llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
- "__vtbl_ptr_type");
- VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
- return VTablePtrType;
-}
-
-/// getVTableName - Get vtable name for the given Class.
-StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
- // Construct gdb compatible name name.
- std::string Name = "_vptr$" + RD->getNameAsString();
-
- // Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
- memcpy(StrPtr, Name.data(), Name.length());
- return StringRef(StrPtr, Name.length());
-}
-
-
-/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
-/// debug info entry in EltTys vector.
-void CGDebugInfo::
-CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys) {
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
-
- // If there is a primary base then it will hold vtable info.
- if (RL.getPrimaryBase())
- return;
-
- // If this class is not dynamic then there is not any vtable info to collect.
- if (!RD->isDynamicClass())
- return;
-
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- llvm::DIType VPTR
- = DBuilder.createMemberType(Unit, getVTableName(RD), Unit,
- 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,
- getOrCreateVTablePtrType(Unit));
- EltTys.push_back(VPTR);
-}
-
-/// getOrCreateRecordType - Emit record type's standalone debug info.
-llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
- SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
- return T;
-}
-
-/// getOrCreateInterfaceType - Emit an objective c interface type standalone
-/// debug info.
-llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
- SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
- DBuilder.retainType(T);
- return T;
-}
-
-/// CreateType - get structure or union type.
-llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
- RecordDecl *RD = Ty->getDecl();
-
- // Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
-
- // Records and classes and unions can all be recursive. To handle them, we
- // first generate a debug descriptor for the struct as a forward declaration.
- // Then (if it is a definition) we go through and get debug info for all of
- // its members. Finally, we create a descriptor for the complete type (which
- // may refer to the forward decl if the struct is recursive) and replace all
- // uses of the forward declaration with the final definition.
-
- llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit);
-
- if (FwdDecl.isForwardDecl())
- return FwdDecl;
-
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(FwdDecl);
-
- // Push the struct on region stack.
- LexicalBlockStack.push_back(FwdDeclNode);
- RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
-
- // Add this to the completed types cache since we're completing it.
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
-
- // Convert all the elements.
- SmallVector<llvm::Value *, 16> EltTys;
-
- // Note: The split of CXXDecl information here is intentional, the
- // gdb tests will depend on a certain ordering at printout. The debug
- // information offsets are still correct if we merge them all together
- // though.
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
- if (CXXDecl) {
- CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectVTableInfo(CXXDecl, DefUnit, EltTys);
- }
-
- // Collect static variables with initializers and other fields.
- CollectRecordStaticVars(RD, FwdDecl);
- CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
- llvm::DIArray TParamsArray;
- if (CXXDecl) {
- CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);
- if (const ClassTemplateSpecializationDecl *TSpecial
- = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);
- }
-
- LexicalBlockStack.pop_back();
- RegionMap.erase(Ty->getDecl());
-
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- // FIXME: Magic numbers ahoy! These should be changed when we
- // get some enums in llvm/Analysis/DebugInfo.h to refer to
- // them.
- if (RD->isUnion())
- FwdDeclNode->replaceOperandWith(10, Elements);
- else if (CXXDecl) {
- FwdDeclNode->replaceOperandWith(10, Elements);
- FwdDeclNode->replaceOperandWith(13, TParamsArray);
- } else
- FwdDeclNode->replaceOperandWith(10, Elements);
-
- RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode);
- return llvm::DIType(FwdDeclNode);
-}
-
-/// CreateType - get objective-c object type.
-llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
- llvm::DIFile Unit) {
- // Ignore protocols.
- return getOrCreateType(Ty->getBaseType(), Unit);
-}
-
-/// CreateType - get objective-c interface type.
-llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
- llvm::DIFile Unit) {
- ObjCInterfaceDecl *ID = Ty->getDecl();
- if (!ID)
- return llvm::DIType();
-
- // Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
- unsigned Line = getLineNumber(ID->getLocation());
- unsigned RuntimeLang = TheCU.getLanguage();
-
- // If this is just a forward declaration return a special forward-declaration
- // debug type since we won't be able to lay out the entire type.
- ObjCInterfaceDecl *Def = ID->getDefinition();
- if (!Def) {
- llvm::DIType FwdDecl =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- ID->getName(), TheCU, DefUnit, Line,
- RuntimeLang);
- return FwdDecl;
- }
-
- ID = Def;
-
- // Bit size, align and offset of the type.
- uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
-
- unsigned Flags = 0;
- if (ID->getImplementation())
- Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
-
- llvm::DIType RealDecl =
- DBuilder.createStructType(Unit, ID->getName(), DefUnit,
- Line, Size, Align, Flags,
- llvm::DIArray(), RuntimeLang);
-
- // Otherwise, insert it into the CompletedTypeCache so that recursive uses
- // will find it and we're emitting the complete type.
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
- // Push the struct on region stack.
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl);
-
- LexicalBlockStack.push_back(FwdDeclNode);
- RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
-
- // Convert all the elements.
- SmallVector<llvm::Value *, 16> EltTys;
-
- ObjCInterfaceDecl *SClass = ID->getSuperClass();
- if (SClass) {
- llvm::DIType SClassTy =
- getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
- if (!SClassTy.isValid())
- return llvm::DIType();
-
- llvm::DIType InhTag =
- DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
- EltTys.push_back(InhTag);
- }
-
- for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(),
- E = ID->prop_end(); I != E; ++I) {
- const ObjCPropertyDecl *PD = *I;
- SourceLocation Loc = PD->getLocation();
- llvm::DIFile PUnit = getOrCreateFile(Loc);
- unsigned PLine = getLineNumber(Loc);
- ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
- ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
- llvm::MDNode *PropertyNode =
- DBuilder.createObjCProperty(PD->getName(),
- PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
- getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
- getSelectorName(PD->getSetterName()),
- PD->getPropertyAttributes(),
- getOrCreateType(PD->getType(), PUnit));
- EltTys.push_back(PropertyNode);
- }
-
- const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
- unsigned FieldNo = 0;
- for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
- Field = Field->getNextIvar(), ++FieldNo) {
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- if (!FieldTy.isValid())
- return llvm::DIType();
-
- StringRef FieldName = Field->getName();
-
- // Ignore unnamed fields.
- if (FieldName.empty())
- continue;
-
- // Get the location for the field.
- llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
- unsigned FieldLine = getLineNumber(Field->getLocation());
- QualType FType = Field->getType();
- uint64_t FieldSize = 0;
- unsigned FieldAlign = 0;
-
- if (!FType->isIncompleteArrayType()) {
-
- // Bit size, align and offset of the type.
- FieldSize = Field->isBitField()
- ? Field->getBitWidthValue(CGM.getContext())
- : CGM.getContext().getTypeSize(FType);
- FieldAlign = CGM.getContext().getTypeAlign(FType);
- }
-
- uint64_t FieldOffset;
- if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
- // We don't know the runtime offset of an ivar if we're using the
- // non-fragile ABI. For bitfields, use the bit offset into the first
- // byte of storage of the bitfield. For other fields, use zero.
- if (Field->isBitField()) {
- FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset(
- CGM, ID, Field);
- FieldOffset %= CGM.getContext().getCharWidth();
- } else {
- FieldOffset = 0;
- }
- } else {
- FieldOffset = RL.getFieldOffset(FieldNo);
- }
-
- unsigned Flags = 0;
- if (Field->getAccessControl() == ObjCIvarDecl::Protected)
- Flags = llvm::DIDescriptor::FlagProtected;
- else if (Field->getAccessControl() == ObjCIvarDecl::Private)
- Flags = llvm::DIDescriptor::FlagPrivate;
-
- llvm::MDNode *PropertyNode = NULL;
- if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
- if (ObjCPropertyImplDecl *PImpD =
- ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
- if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
- SourceLocation Loc = PD->getLocation();
- llvm::DIFile PUnit = getOrCreateFile(Loc);
- unsigned PLine = getLineNumber(Loc);
- ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
- ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
- PropertyNode =
- DBuilder.createObjCProperty(PD->getName(),
- PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
- getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
- getSelectorName(PD->getSetterName()),
- PD->getPropertyAttributes(),
- getOrCreateType(PD->getType(), PUnit));
- }
- }
- }
- FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit,
- FieldLine, FieldSize, FieldAlign,
- FieldOffset, Flags, FieldTy,
- PropertyNode);
- EltTys.push_back(FieldTy);
- }
-
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- FwdDeclNode->replaceOperandWith(10, Elements);
-
- LexicalBlockStack.pop_back();
- return llvm::DIType(FwdDeclNode);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
- llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
- int64_t Count = Ty->getNumElements();
- if (Count == 0)
- // If number of elements are not known then this is an unbounded array.
- // Use Count == -1 to express such arrays.
- Count = -1;
-
- llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, Count);
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
-
- uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
-
- return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
- llvm::DIFile Unit) {
- uint64_t Size;
- uint64_t Align;
-
- // FIXME: make getTypeAlign() aware of VLAs and incomplete array types
- if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
- Size = 0;
- Align =
- CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
- } else if (Ty->isIncompleteArrayType()) {
- Size = 0;
- if (Ty->getElementType()->isIncompleteType())
- Align = 0;
- else
- Align = CGM.getContext().getTypeAlign(Ty->getElementType());
- } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {
- Size = 0;
- Align = 0;
- } else {
- // Size and align of the whole array, not the element type.
- Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
- }
-
- // Add the dimensions of the array. FIXME: This loses CV qualifiers from
- // interior arrays, do we care? Why aren't nested arrays represented the
- // obvious/recursive way?
- SmallVector<llvm::Value *, 8> Subscripts;
- QualType EltTy(Ty, 0);
- while ((Ty = dyn_cast<ArrayType>(EltTy))) {
- // If the number of elements is known, then count is that number. Otherwise,
- // it's -1. This allows us to represent a subrange with an array of 0
- // elements, like this:
- //
- // struct foo {
- // int x[0];
- // };
- int64_t Count = -1; // Count == -1 is an unbounded array.
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
- Count = CAT->getSize().getZExtValue();
-
- // FIXME: Verify this is right for VLAs.
- Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
- EltTy = Ty->getElementType();
- }
-
- llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
-
- llvm::DIType DbgTy =
- DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
- SubscriptArray);
- return DbgTy;
-}
-
-llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
- llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
- Ty, Ty->getPointeeType(), Unit);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
- llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
- Ty, Ty->getPointeeType(), Unit);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
- llvm::DIFile U) {
- QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
- llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
-
- if (!Ty->getPointeeType()->isFunctionType()) {
- // We have a data member pointer type.
- return PointerDiffDITy;
- }
-
- // We have a member function pointer type. Treat it as a struct with two
- // ptrdiff_t members.
- std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
-
- uint64_t FieldOffset = 0;
- llvm::Value *ElementTypes[2];
-
- // FIXME: This should be a DW_TAG_pointer_to_member type.
- ElementTypes[0] =
- DBuilder.createMemberType(U, "ptr", U, 0,
- Info.first, Info.second, FieldOffset, 0,
- PointerDiffDITy);
- FieldOffset += Info.first;
-
- ElementTypes[1] =
- DBuilder.createMemberType(U, "ptr", U, 0,
- Info.first, Info.second, FieldOffset, 0,
- PointerDiffDITy);
-
- llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes);
-
- return DBuilder.createStructType(U, StringRef("test"),
- U, 0, FieldOffset,
- 0, 0, Elements);
-}
-
-llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
- llvm::DIFile U) {
- // Ignore the atomic wrapping
- // FIXME: What is the correct representation?
- return getOrCreateType(Ty->getValueType(), U);
-}
-
-/// CreateEnumType - get enumeration type.
-llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
- uint64_t Size = 0;
- uint64_t Align = 0;
- if (!ED->getTypeForDecl()->isIncompleteType()) {
- Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
- }
-
- // If this is just a forward declaration, construct an appropriately
- // marked node and just return it.
- if (!ED->getDefinition()) {
- llvm::DIDescriptor EDContext;
- EDContext = getContextDescriptor(cast<Decl>(ED->getDeclContext()));
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
- unsigned Line = getLineNumber(ED->getLocation());
- StringRef EDName = ED->getName();
- return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,
- EDName, EDContext, DefUnit, Line, 0,
- Size, Align);
- }
-
- // Create DIEnumerator elements for each enumerator.
- SmallVector<llvm::Value *, 16> Enumerators;
- ED = ED->getDefinition();
- for (EnumDecl::enumerator_iterator
- Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
- Enum != EnumEnd; ++Enum) {
- Enumerators.push_back(
- DBuilder.createEnumerator(Enum->getName(),
- Enum->getInitVal().getZExtValue()));
- }
-
- // Return a CompositeType for the enum itself.
- llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators);
-
- llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
- unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIDescriptor EnumContext =
- getContextDescriptor(cast<Decl>(ED->getDeclContext()));
- llvm::DIType ClassTy = ED->isScopedUsingClassTag() ?
- getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType();
- llvm::DIType DbgTy =
- DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
- Size, Align, EltArray,
- ClassTy);
- return DbgTy;
-}
-
-static QualType UnwrapTypeForDebugInfo(QualType T) {
- do {
- QualType LastT = T;
- switch (T->getTypeClass()) {
- default:
- return T;
- case Type::TemplateSpecialization:
- T = cast<TemplateSpecializationType>(T)->desugar();
- break;
- case Type::TypeOfExpr:
- T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
- break;
- case Type::TypeOf:
- T = cast<TypeOfType>(T)->getUnderlyingType();
- break;
- case Type::Decltype:
- T = cast<DecltypeType>(T)->getUnderlyingType();
- break;
- case Type::UnaryTransform:
- T = cast<UnaryTransformType>(T)->getUnderlyingType();
- break;
- case Type::Attributed:
- T = cast<AttributedType>(T)->getEquivalentType();
- break;
- case Type::Elaborated:
- T = cast<ElaboratedType>(T)->getNamedType();
- break;
- case Type::Paren:
- T = cast<ParenType>(T)->getInnerType();
- break;
- case Type::SubstTemplateTypeParm: {
- // We need to keep the qualifiers handy since getReplacementType()
- // will strip them away.
- unsigned Quals = T.getLocalFastQualifiers();
- T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
- T.addFastQualifiers(Quals);
- }
- break;
- case Type::Auto:
- T = cast<AutoType>(T)->getDeducedType();
- break;
- }
-
- assert(T != LastT && "Type unwrapping failed to unwrap!");
- if (T == LastT)
- return T;
- } while (true);
-}
-
-/// getType - Get the type from the cache or return null type if it doesn't exist.
-llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
-
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
-
- // Check for existing entry.
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
- TypeCache.find(Ty.getAsOpaquePtr());
- if (it != TypeCache.end()) {
- // Verify that the debug info still exists.
- if (llvm::Value *V = it->second)
- return llvm::DIType(cast<llvm::MDNode>(V));
- }
-
- return llvm::DIType();
-}
-
-/// getCompletedTypeOrNull - Get the type from the cache or return null if it
-/// doesn't exist.
-llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
-
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
-
- // Check for existing entry.
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
- CompletedTypeCache.find(Ty.getAsOpaquePtr());
- if (it != CompletedTypeCache.end()) {
- // Verify that the debug info still exists.
- if (llvm::Value *V = it->second)
- return llvm::DIType(cast<llvm::MDNode>(V));
- }
-
- return llvm::DIType();
-}
-
-
-/// getOrCreateType - Get the type from the cache or create a new
-/// one if necessary.
-llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
- if (Ty.isNull())
- return llvm::DIType();
-
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
-
- llvm::DIType T = getCompletedTypeOrNull(Ty);
-
- if (T.Verify())
- return T;
-
- // Otherwise create the type.
- llvm::DIType Res = CreateTypeNode(Ty, Unit);
-
- llvm::DIType TC = getTypeOrNull(Ty);
- if (TC.Verify() && TC.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
- static_cast<llvm::Value*>(TC)));
-
- // And update the type cache.
- TypeCache[Ty.getAsOpaquePtr()] = Res;
-
- if (!Res.isForwardDecl())
- CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;
-
- return Res;
-}
-
-/// CreateTypeNode - Create a new debug type node.
-llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
- // Handle qualifiers, which recursively handles what they refer to.
- if (Ty.hasLocalQualifiers())
- return CreateQualifiedType(Ty, Unit);
-
- const char *Diag = 0;
-
- // Work out details of type.
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_TYPE(Class, Base)
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
- llvm_unreachable("Dependent types cannot show up in debug information");
-
- case Type::ExtVector:
- case Type::Vector:
- return CreateType(cast<VectorType>(Ty), Unit);
- case Type::ObjCObjectPointer:
- return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
- case Type::ObjCObject:
- return CreateType(cast<ObjCObjectType>(Ty), Unit);
- case Type::ObjCInterface:
- return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
- case Type::Builtin:
- return CreateType(cast<BuiltinType>(Ty));
- case Type::Complex:
- return CreateType(cast<ComplexType>(Ty));
- case Type::Pointer:
- return CreateType(cast<PointerType>(Ty), Unit);
- case Type::BlockPointer:
- return CreateType(cast<BlockPointerType>(Ty), Unit);
- case Type::Typedef:
- return CreateType(cast<TypedefType>(Ty), Unit);
- case Type::Record:
- return CreateType(cast<RecordType>(Ty));
- case Type::Enum:
- return CreateEnumType(cast<EnumType>(Ty)->getDecl());
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- return CreateType(cast<FunctionType>(Ty), Unit);
- case Type::ConstantArray:
- case Type::VariableArray:
- case Type::IncompleteArray:
- return CreateType(cast<ArrayType>(Ty), Unit);
-
- case Type::LValueReference:
- return CreateType(cast<LValueReferenceType>(Ty), Unit);
- case Type::RValueReference:
- return CreateType(cast<RValueReferenceType>(Ty), Unit);
-
- case Type::MemberPointer:
- return CreateType(cast<MemberPointerType>(Ty), Unit);
-
- case Type::Atomic:
- return CreateType(cast<AtomicType>(Ty), Unit);
-
- case Type::Attributed:
- case Type::TemplateSpecialization:
- case Type::Elaborated:
- case Type::Paren:
- case Type::SubstTemplateTypeParm:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::Auto:
- llvm_unreachable("type should have been unwrapped!");
- }
-
- assert(Diag && "Fall through without a diagnostic?");
- unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,
- "debug information for %0 is not yet supported");
- CGM.getDiags().Report(DiagID)
- << Diag;
- return llvm::DIType();
-}
-
-/// getOrCreateLimitedType - Get the type from the cache or create a new
-/// limited type if necessary.
-llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,
- llvm::DIFile Unit) {
- if (Ty.isNull())
- return llvm::DIType();
-
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
-
- llvm::DIType T = getTypeOrNull(Ty);
-
- // We may have cached a forward decl when we could have created
- // a non-forward decl. Go ahead and create a non-forward decl
- // now.
- if (T.Verify() && !T.isForwardDecl()) return T;
-
- // Otherwise create the type.
- llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);
-
- if (T.Verify() && T.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
- static_cast<llvm::Value*>(T)));
-
- // And update the type cache.
- TypeCache[Ty.getAsOpaquePtr()] = Res;
- return Res;
-}
-
-// TODO: Currently used for context chains when limiting debug info.
-llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
- RecordDecl *RD = Ty->getDecl();
-
- // Get overall information about the record type for the debug info.
- llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
- unsigned Line = getLineNumber(RD->getLocation());
- StringRef RDName = getClassName(RD);
-
- llvm::DIDescriptor RDContext;
- if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo)
- RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
- else
- RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
-
- // If this is just a forward declaration, construct an appropriately
- // marked node and just return it.
- if (!RD->getDefinition())
- return createRecordFwdDecl(RD, RDContext);
-
- uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
- llvm::TrackingVH<llvm::MDNode> RealDecl;
-
- if (RD->isUnion())
- RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
- else if (RD->isClass()) {
- // FIXME: This could be a struct type giving a default visibility different
- // than C++ class type, but needs llvm metadata changes first.
- RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, 0, llvm::DIType(),
- llvm::DIArray(), llvm::DIType(),
- llvm::DIArray());
- } else
- RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
-
- RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = llvm::DIType(RealDecl);
-
- if (CXXDecl) {
- // A class's primary base or the class itself contains the vtable.
- llvm::MDNode *ContainingType = NULL;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
- // Seek non virtual primary base root.
- while (1) {
- const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
- const CXXRecordDecl *PBT = BRL.getPrimaryBase();
- if (PBT && !BRL.isPrimaryBaseVirtual())
- PBase = PBT;
- else
- break;
- }
- ContainingType =
- getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
- }
- else if (CXXDecl->isDynamicClass())
- ContainingType = RealDecl;
-
- RealDecl->replaceOperandWith(12, ContainingType);
- }
- return llvm::DIType(RealDecl);
-}
-
-/// CreateLimitedTypeNode - Create a new debug type node, but only forward
-/// declare composite types that haven't been processed yet.
-llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
-
- // Work out details of type.
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_TYPE(Class, Base)
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
- #include "clang/AST/TypeNodes.def"
- llvm_unreachable("Dependent types cannot show up in debug information");
-
- case Type::Record:
- return CreateLimitedType(cast<RecordType>(Ty));
- default:
- return CreateTypeNode(Ty, Unit);
- }
-}
-
-/// CreateMemberType - Create new member and increase Offset by FType's size.
-llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
- StringRef Name,
- uint64_t *Offset) {
- llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
- uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
- unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
- llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0,
- FieldSize, FieldAlign,
- *Offset, 0, FieldTy);
- *Offset += FieldSize;
- return Ty;
-}
-
-/// getFunctionDeclaration - Return debug info descriptor to describe method
-/// declaration for the given method definition.
-llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
- const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) return llvm::DISubprogram();
-
- // Setup context.
- getContextDescriptor(cast<Decl>(D->getDeclContext()));
-
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
- MI = SPCache.find(FD->getCanonicalDecl());
- if (MI != SPCache.end()) {
- llvm::Value *V = MI->second;
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
- return SP;
- }
-
- for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),
- E = FD->redecls_end(); I != E; ++I) {
- const FunctionDecl *NextFD = *I;
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
- MI = SPCache.find(NextFD->getCanonicalDecl());
- if (MI != SPCache.end()) {
- llvm::Value *V = MI->second;
- llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
- return SP;
- }
- }
- return llvm::DISubprogram();
-}
-
-// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
-// implicit parameter "this".
-llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
- QualType FnType,
- llvm::DIFile F) {
-
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- return getOrCreateMethodType(Method, F);
- if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) {
- // Add "self" and "_cmd"
- SmallVector<llvm::Value *, 16> Elts;
-
- // First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
- // "self" pointer is always first argument.
- llvm::DIType SelfTy = getOrCreateType(OMethod->getSelfDecl()->getType(), F);
- Elts.push_back(DBuilder.createObjectPointerType(SelfTy));
- // "_cmd" pointer is always second argument.
- llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
- Elts.push_back(DBuilder.createArtificialType(CmdTy));
- // Get rest of the arguments.
- for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
- PE = OMethod->param_end(); PI != PE; ++PI)
- Elts.push_back(getOrCreateType((*PI)->getType(), F));
-
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
- return DBuilder.createSubroutineType(F, EltTypeArray);
- }
- return getOrCreateType(FnType, F);
-}
-
-/// EmitFunctionStart - Constructs the debug code for entering a function.
-void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
- llvm::Function *Fn,
- CGBuilderTy &Builder) {
-
- StringRef Name;
- StringRef LinkageName;
-
- FnBeginRegionCount.push_back(LexicalBlockStack.size());
-
- const Decl *D = GD.getDecl();
- // Function may lack declaration in source code if it is created by Clang
- // CodeGen (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
- bool HasDecl = (D != 0);
- // Use the location of the declaration.
- SourceLocation Loc;
- if (HasDecl)
- Loc = D->getLocation();
-
- unsigned Flags = 0;
- llvm::DIFile Unit = getOrCreateFile(Loc);
- llvm::DIDescriptor FDContext(Unit);
- llvm::DIArray TParamsArray;
- if (!HasDecl) {
- // Use llvm function name.
- Name = Fn->getName();
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // If there is a DISubprogram for this function available then use it.
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
- FI = SPCache.find(FD->getCanonicalDecl());
- if (FI != SPCache.end()) {
- llvm::Value *V = FI->second;
- llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
- llvm::MDNode *SPN = SP;
- LexicalBlockStack.push_back(SPN);
- RegionMap[D] = llvm::WeakVH(SP);
- return;
- }
- }
- Name = getFunctionName(FD);
- // Use mangled name as linkage name for c/c++ functions.
- if (FD->hasPrototype()) {
- LinkageName = CGM.getMangledName(GD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
- }
- if (LinkageName == Name ||
- CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly)
- LinkageName = StringRef();
-
- if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
- if (const NamespaceDecl *NSDecl =
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
- FDContext = getOrCreateNameSpace(NSDecl);
- else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
-
- // Collect template parameters.
- TParamsArray = CollectFunctionTemplateParams(FD, Unit);
- }
- } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
- Name = getObjCMethodName(OMD);
- Flags |= llvm::DIDescriptor::FlagPrototyped;
- } else {
- // Use llvm function name.
- Name = Fn->getName();
- Flags |= llvm::DIDescriptor::FlagPrototyped;
- }
- if (!Name.empty() && Name[0] == '\01')
- Name = Name.substr(1);
-
- unsigned LineNo = getLineNumber(Loc);
- if (!HasDecl || D->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
-
- llvm::DIType DIFnType;
- llvm::DISubprogram SPDecl;
- if (HasDecl &&
- CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
- DIFnType = getOrCreateFunctionType(D, FnType, Unit);
- SPDecl = getFunctionDeclaration(D);
- } else {
- // Create fake but valid subroutine type. Otherwise
- // llvm::DISubprogram::Verify() would return false, and
- // subprogram DIE will miss DW_AT_decl_file and
- // DW_AT_decl_line fields.
- SmallVector<llvm::Value*, 16> Elts;
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
- DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);
- }
- llvm::DISubprogram SP;
- SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
- LineNo, DIFnType,
- Fn->hasInternalLinkage(), true/*definition*/,
- getLineNumber(CurLoc), Flags,
- CGM.getLangOpts().Optimize,
- Fn, TParamsArray, SPDecl);
-
- // Push function on region stack.
- llvm::MDNode *SPN = SP;
- LexicalBlockStack.push_back(SPN);
- if (HasDecl)
- RegionMap[D] = llvm::WeakVH(SP);
-}
-
-/// EmitLocation - Emit metadata to indicate a change in line/column
-/// information in the source file.
-void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
-
- // Update our current location
- setLocation(Loc);
-
- if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
-
- // Don't bother if things are the same as last time.
- SourceManager &SM = CGM.getContext().getSourceManager();
- if (CurLoc == PrevLoc ||
- SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))
- // New Builder may not be in sync with CGDebugInfo.
- if (!Builder.getCurrentDebugLocation().isUnknown())
- return;
-
- // Update last state.
- PrevLoc = CurLoc;
-
- llvm::MDNode *Scope = LexicalBlockStack.back();
- Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
- getColumnNumber(CurLoc),
- Scope));
-}
-
-/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
-/// the stack.
-void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
- llvm::DIDescriptor D =
- DBuilder.createLexicalBlock(LexicalBlockStack.empty() ?
- llvm::DIDescriptor() :
- llvm::DIDescriptor(LexicalBlockStack.back()),
- getOrCreateFile(CurLoc),
- getLineNumber(CurLoc),
- getColumnNumber(CurLoc));
- llvm::MDNode *DN = D;
- LexicalBlockStack.push_back(DN);
-}
-
-/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
-/// region - beginning of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {
- // Set our current location.
- setLocation(Loc);
-
- // Create a new lexical block and push it on the stack.
- CreateLexicalBlock(Loc);
-
- // Emit a line table change for the current location inside the new scope.
- Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc),
- getColumnNumber(Loc),
- LexicalBlockStack.back()));
-}
-
-/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
-/// region - end of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
-
- // Provide an entry in the line table for the end of the block.
- EmitLocation(Builder, Loc);
-
- LexicalBlockStack.pop_back();
-}
-
-/// EmitFunctionEnd - Constructs the debug code for exiting a function.
-void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
- unsigned RCount = FnBeginRegionCount.back();
- assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");
-
- // Pop all regions for this function.
- while (LexicalBlockStack.size() != RCount)
- EmitLexicalBlockEnd(Builder, CurLoc);
- FnBeginRegionCount.pop_back();
-}
-
-// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
-// See BuildByRefType.
-llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
- uint64_t *XOffset) {
-
- SmallVector<llvm::Value *, 5> EltTys;
- QualType FType;
- uint64_t FieldSize, FieldOffset;
- unsigned FieldAlign;
-
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- QualType Type = VD->getType();
-
- FieldOffset = 0;
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));
- FType = CGM.getContext().IntTy;
- EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
-
- bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);
- if (HasCopyAndDispose) {
- FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
- EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
- &FieldOffset));
- EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
- &FieldOffset));
- }
- bool HasByrefExtendedLayout;
- Qualifiers::ObjCLifetime Lifetime;
- if (CGM.getContext().getByrefLifetime(Type,
- Lifetime, HasByrefExtendedLayout)
- && HasByrefExtendedLayout)
- EltTys.push_back(CreateMemberType(Unit, FType,
- "__byref_variable_layout",
- &FieldOffset));
-
- CharUnits Align = CGM.getContext().getDeclAlign(VD);
- if (Align > CGM.getContext().toCharUnitsFromBits(
- CGM.getContext().getTargetInfo().getPointerAlign(0))) {
- CharUnits FieldOffsetInBytes
- = CGM.getContext().toCharUnitsFromBits(FieldOffset);
- CharUnits AlignedOffsetInBytes
- = FieldOffsetInBytes.RoundUpToAlignment(Align);
- CharUnits NumPaddingBytes
- = AlignedOffsetInBytes - FieldOffsetInBytes;
-
- if (NumPaddingBytes.isPositive()) {
- llvm::APInt pad(32, NumPaddingBytes.getQuantity());
- FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
- pad, ArrayType::Normal, 0);
- EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
- }
- }
-
- FType = Type;
- llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
- FieldSize = CGM.getContext().getTypeSize(FType);
- FieldAlign = CGM.getContext().toBits(Align);
-
- *XOffset = FieldOffset;
- FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,
- 0, FieldSize, FieldAlign,
- FieldOffset, 0, FieldTy);
- EltTys.push_back(FieldTy);
- FieldOffset += FieldSize;
-
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
-
- unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
-
- return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
- Elements);
-}
-
-/// EmitDeclare - Emit local variable declaration debug info.
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
- llvm::Value *Storage,
- unsigned ArgNo, CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
-
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- llvm::DIType Ty;
- uint64_t XOffset = 0;
- if (VD->hasAttr<BlocksAttr>())
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
- Ty = getOrCreateType(VD->getType(), Unit);
-
- // If there is no debug info for this type then do not emit debug info
- // for this variable.
- if (!Ty)
- return;
-
- if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
- // If Storage is an aggregate returned as 'sret' then let debugger know
- // about this.
- if (Arg->hasStructRetAttr())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
- else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
- // If an aggregate variable has non trivial destructor or non trivial copy
- // constructor than it is pass indirectly. Let debug info know about this
- // by using reference of the aggregate type as a argument type.
- if (Record->hasNonTrivialCopyConstructor() ||
- !Record->hasTrivialDestructor())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
- }
- }
-
- // Get location information.
- unsigned Line = getLineNumber(VD->getLocation());
- unsigned Column = getColumnNumber(VD->getLocation());
- unsigned Flags = 0;
- if (VD->isImplicit())
- Flags |= llvm::DIDescriptor::FlagArtificial;
- // If this is the first argument and it is implicit then
- // give it an object pointer flag.
- // FIXME: There has to be a better way to do this, but for static
- // functions there won't be an implicit param at arg1 and
- // otherwise it is 'self' or 'this'.
- if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
- Flags |= llvm::DIDescriptor::FlagObjectPointer;
-
- llvm::MDNode *Scope = LexicalBlockStack.back();
-
- StringRef Name = VD->getName();
- if (!Name.empty()) {
- if (VD->hasAttr<BlocksAttr>()) {
- CharUnits offset = CharUnits::fromQuantity(32);
- SmallVector<llvm::Value *, 9> addr;
- llvm::Type *Int64Ty = CGM.Int64Ty;
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
- // offset of __forwarding field
- offset = CGM.getContext().toCharUnitsFromBits(
- CGM.getContext().getTargetInfo().getPointerWidth(0));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
- // offset of x field
- offset = CGM.getContext().toCharUnitsFromBits(XOffset);
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
-
- // Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createComplexVariable(Tag,
- llvm::DIDescriptor(Scope),
- VD->getName(), Unit, Line, Ty,
- addr, ArgNo);
-
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- return;
- } else if (isa<VariableArrayType>(VD->getType())) {
- // These are "complex" variables in that they need an op_deref.
- // Create the descriptor for the variable.
- llvm::Value *Addr = llvm::ConstantInt::get(CGM.Int64Ty,
- llvm::DIBuilder::OpDeref);
- llvm::DIVariable D =
- DBuilder.createComplexVariable(Tag,
- llvm::DIDescriptor(Scope),
- Name, Unit, Line, Ty,
- Addr, ArgNo);
-
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- return;
- }
-
- // Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
- Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, ArgNo);
-
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- return;
- }
-
- // If VD is an anonymous union then Storage represents value for
- // all union fields.
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
- const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
- if (RD->isUnion()) {
- for (RecordDecl::field_iterator I = RD->field_begin(),
- E = RD->field_end();
- I != E; ++I) {
- FieldDecl *Field = *I;
- llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
- StringRef FieldName = Field->getName();
-
- // Ignore unnamed fields. Do not ignore unnamed records.
- if (FieldName.empty() && !isa<RecordType>(Field->getType()))
- continue;
-
- // Use VarDecl's Tag, Scope and Line number.
- llvm::DIVariable D =
- DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
- FieldName, Unit, Line, FieldTy,
- CGM.getLangOpts().Optimize, Flags,
- ArgNo);
-
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- }
- }
- }
-}
-
-void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
- llvm::Value *Storage,
- CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
-}
-
-void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
- llvm::Value *Storage,
- CGBuilderTy &Builder,
- const CGBlockInfo &blockInfo) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
-
- if (Builder.GetInsertBlock() == 0)
- return;
-
- bool isByRef = VD->hasAttr<BlocksAttr>();
-
- uint64_t XOffset = 0;
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- llvm::DIType Ty;
- if (isByRef)
- Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
- Ty = getOrCreateType(VD->getType(), Unit);
-
- // Self is passed along as an implicit non-arg variable in a
- // block. Mark it as the object pointer.
- if (isa<ImplicitParamDecl>(VD) && VD->getName() == "self")
- Ty = DBuilder.createObjectPointerType(Ty);
-
- // Get location information.
- unsigned Line = getLineNumber(VD->getLocation());
- unsigned Column = getColumnNumber(VD->getLocation());
-
- const llvm::DataLayout &target = CGM.getDataLayout();
-
- CharUnits offset = CharUnits::fromQuantity(
- target.getStructLayout(blockInfo.StructureType)
- ->getElementOffset(blockInfo.getCapture(VD).getIndex()));
-
- SmallVector<llvm::Value *, 9> addr;
- llvm::Type *Int64Ty = CGM.Int64Ty;
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
- if (isByRef) {
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
- // offset of __forwarding field
- offset = CGM.getContext()
- .toCharUnitsFromBits(target.getPointerSizeInBits(0));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
- addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
- // offset of x field
- offset = CGM.getContext().toCharUnitsFromBits(XOffset);
- addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
- }
-
- // Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
- llvm::DIDescriptor(LexicalBlockStack.back()),
- VD->getName(), Unit, Line, Ty, addr);
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column,
- LexicalBlockStack.back()));
-}
-
-/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
-/// variable declaration.
-void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
- unsigned ArgNo,
- CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
-}
-
-namespace {
- struct BlockLayoutChunk {
- uint64_t OffsetInBits;
- const BlockDecl::Capture *Capture;
- };
- bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
- return l.OffsetInBits < r.OffsetInBits;
- }
-}
-
-void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
- llvm::Value *addr,
- CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- ASTContext &C = CGM.getContext();
- const BlockDecl *blockDecl = block.getBlockDecl();
-
- // Collect some general information about the block's location.
- SourceLocation loc = blockDecl->getCaretLocation();
- llvm::DIFile tunit = getOrCreateFile(loc);
- unsigned line = getLineNumber(loc);
- unsigned column = getColumnNumber(loc);
-
- // Build the debug-info type for the block literal.
- getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
-
- const llvm::StructLayout *blockLayout =
- CGM.getDataLayout().getStructLayout(block.StructureType);
-
- SmallVector<llvm::Value*, 16> fields;
- fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
- blockLayout->getElementOffsetInBits(0),
- tunit, tunit));
- fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
- blockLayout->getElementOffsetInBits(1),
- tunit, tunit));
- fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
- blockLayout->getElementOffsetInBits(2),
- tunit, tunit));
- fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
- blockLayout->getElementOffsetInBits(3),
- tunit, tunit));
- fields.push_back(createFieldType("__descriptor",
- C.getPointerType(block.NeedsCopyDispose ?
- C.getBlockDescriptorExtendedType() :
- C.getBlockDescriptorType()),
- 0, loc, AS_public,
- blockLayout->getElementOffsetInBits(4),
- tunit, tunit));
-
- // We want to sort the captures by offset, not because DWARF
- // requires this, but because we're paranoid about debuggers.
- SmallVector<BlockLayoutChunk, 8> chunks;
-
- // 'this' capture.
- if (blockDecl->capturesCXXThis()) {
- BlockLayoutChunk chunk;
- chunk.OffsetInBits =
- blockLayout->getElementOffsetInBits(block.CXXThisIndex);
- chunk.Capture = 0;
- chunks.push_back(chunk);
- }
-
- // Variable captures.
- for (BlockDecl::capture_const_iterator
- i = blockDecl->capture_begin(), e = blockDecl->capture_end();
- i != e; ++i) {
- const BlockDecl::Capture &capture = *i;
- const VarDecl *variable = capture.getVariable();
- const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
-
- // Ignore constant captures.
- if (captureInfo.isConstant())
- continue;
-
- BlockLayoutChunk chunk;
- chunk.OffsetInBits =
- blockLayout->getElementOffsetInBits(captureInfo.getIndex());
- chunk.Capture = &capture;
- chunks.push_back(chunk);
- }
-
- // Sort by offset.
- llvm::array_pod_sort(chunks.begin(), chunks.end());
-
- for (SmallVectorImpl<BlockLayoutChunk>::iterator
- i = chunks.begin(), e = chunks.end(); i != e; ++i) {
- uint64_t offsetInBits = i->OffsetInBits;
- const BlockDecl::Capture *capture = i->Capture;
-
- // If we have a null capture, this must be the C++ 'this' capture.
- if (!capture) {
- const CXXMethodDecl *method =
- cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
- QualType type = method->getThisType(C);
-
- fields.push_back(createFieldType("this", type, 0, loc, AS_public,
- offsetInBits, tunit, tunit));
- continue;
- }
-
- const VarDecl *variable = capture->getVariable();
- StringRef name = variable->getName();
-
- llvm::DIType fieldType;
- if (capture->isByRef()) {
- std::pair<uint64_t,unsigned> ptrInfo = C.getTypeInfo(C.VoidPtrTy);
-
- // FIXME: this creates a second copy of this type!
- uint64_t xoffset;
- fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
- fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first);
- fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
- ptrInfo.first, ptrInfo.second,
- offsetInBits, 0, fieldType);
- } else {
- fieldType = createFieldType(name, variable->getType(), 0,
- loc, AS_public, offsetInBits, tunit, tunit);
- }
- fields.push_back(fieldType);
- }
-
- SmallString<36> typeName;
- llvm::raw_svector_ostream(typeName)
- << "__block_literal_" << CGM.getUniqueBlockCount();
-
- llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields);
-
- llvm::DIType type =
- DBuilder.createStructType(tunit, typeName.str(), tunit, line,
- CGM.getContext().toBits(block.BlockSize),
- CGM.getContext().toBits(block.BlockAlign),
- 0, fieldsArray);
- type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
-
- // Get overall information about the block.
- unsigned flags = llvm::DIDescriptor::FlagArtificial;
- llvm::MDNode *scope = LexicalBlockStack.back();
- StringRef name = ".block_descriptor";
-
- // Create the descriptor for the parameter.
- llvm::DIVariable debugVar =
- DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
- llvm::DIDescriptor(scope),
- name, tunit, line, type,
- CGM.getLangOpts().Optimize, flags,
- cast<llvm::Argument>(addr)->getArgNo() + 1);
-
- // Insert an llvm.dbg.value into the current block.
- llvm::Instruction *declare =
- DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
- Builder.GetInsertBlock());
- declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
-}
-
-/// EmitGlobalVariable - Emit information about a global variable.
-void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
- const VarDecl *D) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- // Create global variable debug descriptor.
- llvm::DIFile Unit = getOrCreateFile(D->getLocation());
- unsigned LineNo = getLineNumber(D->getLocation());
-
- setLocation(D->getLocation());
-
- QualType T = D->getType();
- if (T->isIncompleteArrayType()) {
-
- // CodeGen turns int[] into int[1] so we'll do the same here.
- llvm::APInt ConstVal(32, 1);
- QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
-
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,
- ArrayType::Normal, 0);
- }
- StringRef DeclName = D->getName();
- StringRef LinkageName;
- if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())
- && !isa<ObjCMethodDecl>(D->getDeclContext()))
- LinkageName = Var->getName();
- if (LinkageName == DeclName)
- LinkageName = StringRef();
- llvm::DIDescriptor DContext =
- getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
- Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var);
-}
-
-/// EmitGlobalVariable - Emit information about an objective-c interface.
-void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
- ObjCInterfaceDecl *ID) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- // Create global variable debug descriptor.
- llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
- unsigned LineNo = getLineNumber(ID->getLocation());
-
- StringRef Name = ID->getName();
-
- QualType T = CGM.getContext().getObjCInterfaceType(ID);
- if (T->isIncompleteArrayType()) {
-
- // CodeGen turns int[] into int[1] so we'll do the same here.
- llvm::APInt ConstVal(32, 1);
- QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
-
- T = CGM.getContext().getConstantArrayType(ET, ConstVal,
- ArrayType::Normal, 0);
- }
-
- DBuilder.createGlobalVariable(Name, Unit, LineNo,
- getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var);
-}
-
-/// EmitGlobalVariable - Emit global variable's debug info.
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
- llvm::Constant *Init) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
- // Create the descriptor for the variable.
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- StringRef Name = VD->getName();
- llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
- if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
- const EnumDecl *ED = cast<EnumDecl>(ECD->getDeclContext());
- assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");
- Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
- }
- // Do not use DIGlobalVariable for enums.
- if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
- return;
- DBuilder.createStaticVariable(Unit, Name, Name, Unit,
- getLineNumber(VD->getLocation()),
- Ty, true, Init);
-}
-
-/// getOrCreateNamesSpace - Return namespace descriptor for the given
-/// namespace decl.
-llvm::DINameSpace
-CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
- NameSpaceCache.find(NSDecl);
- if (I != NameSpaceCache.end())
- return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
-
- unsigned LineNo = getLineNumber(NSDecl->getLocation());
- llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIDescriptor Context =
- getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
- llvm::DINameSpace NS =
- DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
- NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
- return NS;
-}
-
-void CGDebugInfo::finalize() {
- for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI
- = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) {
- llvm::DIType Ty, RepTy;
- // Verify that the debug info still exists.
- if (llvm::Value *V = VI->second)
- Ty = llvm::DIType(cast<llvm::MDNode>(V));
-
- llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
- TypeCache.find(VI->first);
- if (it != TypeCache.end()) {
- // Verify that the debug info still exists.
- if (llvm::Value *V = it->second)
- RepTy = llvm::DIType(cast<llvm::MDNode>(V));
- }
-
- if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {
- Ty.replaceAllUsesWith(RepTy);
- }
- }
- DBuilder.finalize();
-}
+//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This coordinates the debug information generation while generating code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGDebugInfo.h"
+#include "CGBlocks.h"
+#include "CGObjCRuntime.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Frontend/CodeGenOptions.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Constants.h"
+#include "llvm/DataLayout.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/Intrinsics.h"
+#include "llvm/Module.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/FileSystem.h"
+using namespace clang;
+using namespace clang::CodeGen;
+
+CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
+ : CGM(CGM), DBuilder(CGM.getModule()),
+ BlockLiteralGenericSet(false) {
+ CreateCompileUnit();
+}
+
+CGDebugInfo::~CGDebugInfo() {
+ assert(LexicalBlockStack.empty() &&
+ "Region stack mismatch, stack not empty!");
+}
+
+void CGDebugInfo::setLocation(SourceLocation Loc) {
+ // If the new location isn't valid return.
+ if (!Loc.isValid()) return;
+
+ CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
+
+ // If we've changed files in the middle of a lexical scope go ahead
+ // and create a new lexical scope with file node if it's different
+ // from the one in the scope.
+ if (LexicalBlockStack.empty()) return;
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc);
+ PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc);
+
+ if (PCLoc.isInvalid() || PPLoc.isInvalid() ||
+ !strcmp(PPLoc.getFilename(), PCLoc.getFilename()))
+ return;
+
+ llvm::MDNode *LB = LexicalBlockStack.back();
+ llvm::DIScope Scope = llvm::DIScope(LB);
+ if (Scope.isLexicalBlockFile()) {
+ llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB);
+ llvm::DIDescriptor D
+ = DBuilder.createLexicalBlockFile(LBF.getScope(),
+ getOrCreateFile(CurLoc));
+ llvm::MDNode *N = D;
+ LexicalBlockStack.pop_back();
+ LexicalBlockStack.push_back(N);
+ } else if (Scope.isLexicalBlock()) {
+ llvm::DIDescriptor D
+ = DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
+ llvm::MDNode *N = D;
+ LexicalBlockStack.pop_back();
+ LexicalBlockStack.push_back(N);
+ }
+}
+
+/// getContextDescriptor - Get context info for the decl.
+llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) {
+ if (!Context)
+ return TheCU;
+
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
+ I = RegionMap.find(Context);
+ if (I != RegionMap.end()) {
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+ }
+
+ // Check namespace.
+ if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
+ return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
+
+ if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) {
+ if (!RDecl->isDependentType()) {
+ llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl),
+ getOrCreateMainFile());
+ return llvm::DIDescriptor(Ty);
+ }
+ }
+ return TheCU;
+}
+
+/// getFunctionName - Get function name for the given FunctionDecl. If the
+/// name is constructred on demand (e.g. C++ destructor) then the name
+/// is stored on the side.
+StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
+ assert (FD && "Invalid FunctionDecl!");
+ IdentifierInfo *FII = FD->getIdentifier();
+ FunctionTemplateSpecializationInfo *Info
+ = FD->getTemplateSpecializationInfo();
+ if (!Info && FII)
+ return FII->getName();
+
+ // Otherwise construct human readable name for debug info.
+ std::string NS = FD->getNameAsString();
+
+ // Add any template specialization args.
+ if (Info) {
+ const TemplateArgumentList *TArgs = Info->TemplateArguments;
+ const TemplateArgument *Args = TArgs->data();
+ unsigned NumArgs = TArgs->size();
+ PrintingPolicy Policy(CGM.getLangOpts());
+ NS += TemplateSpecializationType::PrintTemplateArgumentList(Args,
+ NumArgs,
+ Policy);
+ }
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
+ memcpy(StrPtr, NS.data(), NS.length());
+ return StringRef(StrPtr, NS.length());
+}
+
+StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
+ SmallString<256> MethodName;
+ llvm::raw_svector_ostream OS(MethodName);
+ OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
+ const DeclContext *DC = OMD->getDeclContext();
+ if (const ObjCImplementationDecl *OID =
+ dyn_cast<const ObjCImplementationDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const ObjCInterfaceDecl *OID =
+ dyn_cast<const ObjCInterfaceDecl>(DC)) {
+ OS << OID->getName();
+ } else if (const ObjCCategoryImplDecl *OCD =
+ dyn_cast<const ObjCCategoryImplDecl>(DC)){
+ OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
+ OCD->getIdentifier()->getNameStart() << ')';
+ }
+ OS << ' ' << OMD->getSelector().getAsString() << ']';
+
+ char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
+ memcpy(StrPtr, MethodName.begin(), OS.tell());
+ return StringRef(StrPtr, OS.tell());
+}
+
+/// getSelectorName - Return selector name. This is used for debugging
+/// info.
+StringRef CGDebugInfo::getSelectorName(Selector S) {
+ const std::string &SName = S.getAsString();
+ char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());
+ memcpy(StrPtr, SName.data(), SName.size());
+ return StringRef(StrPtr, SName.size());
+}
+
+/// getClassName - Get class name including template argument list.
+StringRef
+CGDebugInfo::getClassName(const RecordDecl *RD) {
+ const ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD);
+ if (!Spec)
+ return RD->getName();
+
+ const TemplateArgument *Args;
+ unsigned NumArgs;
+ if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
+ const TemplateSpecializationType *TST =
+ cast<TemplateSpecializationType>(TAW->getType());
+ Args = TST->getArgs();
+ NumArgs = TST->getNumArgs();
+ } else {
+ const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+ Args = TemplateArgs.data();
+ NumArgs = TemplateArgs.size();
+ }
+ StringRef Name = RD->getIdentifier()->getName();
+ PrintingPolicy Policy(CGM.getLangOpts());
+ std::string TemplateArgList =
+ TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);
+
+ // Copy this name on the side and use its reference.
+ size_t Length = Name.size() + TemplateArgList.size();
+ char *StrPtr = DebugInfoNames.Allocate<char>(Length);
+ memcpy(StrPtr, Name.data(), Name.size());
+ memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
+ return StringRef(StrPtr, Length);
+}
+
+/// getOrCreateFile - Get the file debug info descriptor for the input location.
+llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) {
+ if (!Loc.isValid())
+ // If Location is not valid then use main input file.
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc);
+
+ if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty())
+ // If the location is not valid then use main input file.
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+
+ // Cache the results.
+ const char *fname = PLoc.getFilename();
+ llvm::DenseMap<const char *, llvm::WeakVH>::iterator it =
+ DIFileCache.find(fname);
+
+ if (it != DIFileCache.end()) {
+ // Verify that the information still exists.
+ if (llvm::Value *V = it->second)
+ return llvm::DIFile(cast<llvm::MDNode>(V));
+ }
+
+ llvm::DIFile F = DBuilder.createFile(PLoc.getFilename(), getCurrentDirname());
+
+ DIFileCache[fname] = F;
+ return F;
+}
+
+/// getOrCreateMainFile - Get the file info for main compile unit.
+llvm::DIFile CGDebugInfo::getOrCreateMainFile() {
+ return DBuilder.createFile(TheCU.getFilename(), TheCU.getDirectory());
+}
+
+/// getLineNumber - Get line number for the location. If location is invalid
+/// then use current location.
+unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
+ if (Loc.isInvalid() && CurLoc.isInvalid())
+ return 0;
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
+ return PLoc.isValid()? PLoc.getLine() : 0;
+}
+
+/// getColumnNumber - Get column number for the location.
+unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
+ // We may not want column information at all.
+ if (!CGM.getCodeGenOpts().DebugColumnInfo)
+ return 0;
+
+ // If the location is invalid then use the current column.
+ if (Loc.isInvalid() && CurLoc.isInvalid())
+ return 0;
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc);
+ return PLoc.isValid()? PLoc.getColumn() : 0;
+}
+
+StringRef CGDebugInfo::getCurrentDirname() {
+ if (!CGM.getCodeGenOpts().DebugCompilationDir.empty())
+ return CGM.getCodeGenOpts().DebugCompilationDir;
+
+ if (!CWDName.empty())
+ return CWDName;
+ SmallString<256> CWD;
+ llvm::sys::fs::current_path(CWD);
+ char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
+ memcpy(CompDirnamePtr, CWD.data(), CWD.size());
+ return CWDName = StringRef(CompDirnamePtr, CWD.size());
+}
+
+/// CreateCompileUnit - Create new compile unit.
+void CGDebugInfo::CreateCompileUnit() {
+
+ // Get absolute path name.
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ std::string MainFileName = CGM.getCodeGenOpts().MainFileName;
+ if (MainFileName.empty())
+ MainFileName = "<unknown>";
+
+ // The main file name provided via the "-main-file-name" option contains just
+ // the file name itself with no path information. This file name may have had
+ // a relative path, so we look into the actual file entry for the main
+ // file to determine the real absolute path for the file.
+ std::string MainFileDir;
+ if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
+ MainFileDir = MainFile->getDir()->getName();
+ if (MainFileDir != ".")
+ MainFileName = MainFileDir + "/" + MainFileName;
+ }
+
+ // Save filename string.
+ char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
+ memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
+ StringRef Filename(FilenamePtr, MainFileName.length());
+
+ unsigned LangTag;
+ const LangOptions &LO = CGM.getLangOpts();
+ if (LO.CPlusPlus) {
+ if (LO.ObjC1)
+ LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus;
+ else
+ LangTag = llvm::dwarf::DW_LANG_C_plus_plus;
+ } else if (LO.ObjC1) {
+ LangTag = llvm::dwarf::DW_LANG_ObjC;
+ } else if (LO.C99) {
+ LangTag = llvm::dwarf::DW_LANG_C99;
+ } else {
+ LangTag = llvm::dwarf::DW_LANG_C89;
+ }
+
+ std::string Producer = getClangFullVersion();
+
+ // Figure out which version of the ObjC runtime we have.
+ unsigned RuntimeVers = 0;
+ if (LO.ObjC1)
+ RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;
+
+ // Create new compile unit.
+ DBuilder.createCompileUnit(
+ LangTag, Filename, getCurrentDirname(),
+ Producer,
+ LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers);
+ // FIXME - Eliminate TheCU.
+ TheCU = llvm::DICompileUnit(DBuilder.getCU());
+}
+
+/// CreateType - Get the Basic type from the cache or create a new
+/// one if necessary.
+llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
+ unsigned Encoding = 0;
+ StringRef BTName;
+ 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");
+ case BuiltinType::NullPtr:
+ return DBuilder.
+ createNullPtrType(BT->getName(CGM.getLangOpts()));
+ case BuiltinType::Void:
+ return llvm::DIType();
+ case BuiltinType::ObjCClass:
+ if (ClassTy.Verify())
+ return ClassTy;
+ ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_class", TheCU,
+ getOrCreateMainFile(), 0);
+ return ClassTy;
+ case BuiltinType::ObjCId: {
+ // typedef struct objc_class *Class;
+ // typedef struct objc_object {
+ // Class isa;
+ // } *id;
+
+ if (ObjTy.Verify())
+ return ObjTy;
+
+ if (!ClassTy.Verify())
+ ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_class", TheCU,
+ getOrCreateMainFile(), 0);
+
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+
+ llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
+
+ llvm::DIType FwdTy = DBuilder.createStructType(TheCU, "objc_object",
+ getOrCreateMainFile(),
+ 0, 0, 0, 0,
+ llvm::DIArray());
+
+ llvm::TrackingVH<llvm::MDNode> ObjNode(FwdTy);
+ SmallVector<llvm::Value *, 1> EltTys;
+ llvm::DIType FieldTy =
+ DBuilder.createMemberType(llvm::DIDescriptor(ObjNode), "isa",
+ getOrCreateMainFile(), 0, Size,
+ 0, 0, 0, ISATy);
+ EltTys.push_back(FieldTy);
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+
+ ObjNode->replaceOperandWith(10, Elements);
+ ObjTy = llvm::DIType(ObjNode);
+ return ObjTy;
+ }
+ case BuiltinType::ObjCSel: {
+ if (SelTy.Verify())
+ return SelTy;
+ SelTy =
+ DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ "objc_selector", TheCU, getOrCreateMainFile(),
+ 0);
+ return SelTy;
+ }
+ case BuiltinType::UChar:
+ case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar: Encoding = llvm::dwarf::DW_ATE_signed_char; break;
+ case BuiltinType::Char16:
+ case BuiltinType::Char32: Encoding = llvm::dwarf::DW_ATE_UTF; break;
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::UInt128:
+ case BuiltinType::ULong:
+ case BuiltinType::WChar_U:
+ case BuiltinType::ULongLong: Encoding = llvm::dwarf::DW_ATE_unsigned; break;
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Int128:
+ case BuiltinType::Long:
+ case BuiltinType::WChar_S:
+ case BuiltinType::LongLong: Encoding = llvm::dwarf::DW_ATE_signed; break;
+ case BuiltinType::Bool: Encoding = llvm::dwarf::DW_ATE_boolean; break;
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Double: Encoding = llvm::dwarf::DW_ATE_float; break;
+ }
+
+ switch (BT->getKind()) {
+ case BuiltinType::Long: BTName = "long int"; break;
+ case BuiltinType::LongLong: BTName = "long long int"; break;
+ case BuiltinType::ULong: BTName = "long unsigned int"; break;
+ case BuiltinType::ULongLong: BTName = "long long unsigned int"; break;
+ default:
+ BTName = BT->getName(CGM.getLangOpts());
+ break;
+ }
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(BT);
+ uint64_t Align = CGM.getContext().getTypeAlign(BT);
+ llvm::DIType DbgTy =
+ DBuilder.createBasicType(BTName, Size, Align, Encoding);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
+ // Bit size, align and offset of the type.
+ unsigned Encoding = llvm::dwarf::DW_ATE_complex_float;
+ if (Ty->isComplexIntegerType())
+ Encoding = llvm::dwarf::DW_ATE_lo_user;
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ llvm::DIType DbgTy =
+ DBuilder.createBasicType("complex", Size, Align, Encoding);
+
+ return DbgTy;
+}
+
+/// CreateCVRType - Get the qualified type from the cache or create
+/// a new one if necessary.
+llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
+ QualifierCollector Qc;
+ const Type *T = Qc.strip(Ty);
+
+ // Ignore these qualifiers for now.
+ Qc.removeObjCGCAttr();
+ Qc.removeAddressSpace();
+ Qc.removeObjCLifetime();
+
+ // We will create one Derived type for one qualifier and recurse to handle any
+ // additional ones.
+ unsigned Tag;
+ if (Qc.hasConst()) {
+ Tag = llvm::dwarf::DW_TAG_const_type;
+ Qc.removeConst();
+ } else if (Qc.hasVolatile()) {
+ Tag = llvm::dwarf::DW_TAG_volatile_type;
+ Qc.removeVolatile();
+ } else if (Qc.hasRestrict()) {
+ Tag = llvm::dwarf::DW_TAG_restrict_type;
+ Qc.removeRestrict();
+ } else {
+ assert(Qc.empty() && "Unknown type qualifier for debug info");
+ return getOrCreateType(QualType(T, 0), Unit);
+ }
+
+ llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
+
+ // No need to fill in the Name, Line, Size, Alignment, Offset in case of
+ // CVR derived types.
+ llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
+
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
+ llvm::DIFile Unit) {
+ llvm::DIType DbgTy =
+ CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ Ty->getPointeeType(), Unit);
+}
+
+// Creates a forward declaration for a RecordDecl in the given context.
+llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
+ llvm::DIDescriptor Ctx) {
+ llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ unsigned Line = getLineNumber(RD->getLocation());
+ StringRef RDName = getClassName(RD);
+
+ unsigned Tag = 0;
+ if (RD->isStruct() || RD->isInterface())
+ Tag = llvm::dwarf::DW_TAG_structure_type;
+ else if (RD->isUnion())
+ Tag = llvm::dwarf::DW_TAG_union_type;
+ else {
+ assert(RD->isClass());
+ Tag = llvm::dwarf::DW_TAG_class_type;
+ }
+
+ // Create the type.
+ return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line);
+}
+
+// Walk up the context chain and create forward decls for record decls,
+// and normal descriptors for namespaces.
+llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
+ if (!Context)
+ return TheCU;
+
+ // See if we already have the parent.
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
+ I = RegionMap.find(Context);
+ if (I != RegionMap.end()) {
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+ }
+
+ // Check namespace.
+ if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
+ return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
+
+ if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
+ if (!RD->isDependentType()) {
+ llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
+ getOrCreateMainFile());
+ return llvm::DIDescriptor(Ty);
+ }
+ }
+ return TheCU;
+}
+
+/// CreatePointeeType - Create Pointee type. If Pointee is a record
+/// then emit record's fwd if debug info size reduction is enabled.
+llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
+ llvm::DIFile Unit) {
+ if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo)
+ return getOrCreateType(PointeeTy, Unit);
+
+ // Limit debug info for the pointee type.
+
+ // If we have an existing type, use that, it's still smaller than creating
+ // a new type.
+ llvm::DIType Ty = getTypeOrNull(PointeeTy);
+ if (Ty.Verify()) return Ty;
+
+ // Handle qualifiers.
+ if (PointeeTy.hasLocalQualifiers())
+ return CreateQualifiedType(PointeeTy, Unit);
+
+ if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
+ RecordDecl *RD = RTy->getDecl();
+ llvm::DIDescriptor FDContext =
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
+ TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;
+ return RetTy;
+ }
+ return getOrCreateType(PointeeTy, Unit);
+
+}
+
+llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
+ const Type *Ty,
+ QualType PointeeTy,
+ llvm::DIFile Unit) {
+ if (Tag == llvm::dwarf::DW_TAG_reference_type ||
+ Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
+ return DBuilder.createReferenceType(Tag,
+ CreatePointeeType(PointeeTy, Unit));
+
+ // Bit size, align and offset of the type.
+ // Size is always the size of a pointer. We can't use getTypeSize here
+ // because that does not return the correct value for references.
+ unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
+ uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit),
+ Size, Align);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
+ llvm::DIFile Unit) {
+ if (BlockLiteralGenericSet)
+ return BlockLiteralGeneric;
+
+ SmallVector<llvm::Value *, 8> EltTys;
+ llvm::DIType FieldTy;
+ QualType FType;
+ uint64_t FieldSize, FieldOffset;
+ unsigned FieldAlign;
+ llvm::DIArray Elements;
+ llvm::DIType EltTy, DescTy;
+
+ FieldOffset = 0;
+ FType = CGM.getContext().UnsignedLongTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset));
+
+ Elements = DBuilder.getOrCreateArray(EltTys);
+ EltTys.clear();
+
+ unsigned Flags = llvm::DIDescriptor::FlagAppleBlock;
+ unsigned LineNo = getLineNumber(CurLoc);
+
+ EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
+ Unit, LineNo, FieldOffset, 0,
+ Flags, Elements);
+
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+
+ DescTy = DBuilder.createPointerType(EltTy, Size);
+
+ FieldOffset = 0;
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__reserved", &FieldOffset));
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__FuncPtr", &FieldOffset));
+
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ FieldTy = DescTy;
+ FieldSize = CGM.getContext().getTypeSize(Ty);
+ FieldAlign = CGM.getContext().getTypeAlign(Ty);
+ FieldTy = DBuilder.createMemberType(Unit, "__descriptor", Unit,
+ LineNo, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+
+ FieldOffset += FieldSize;
+ Elements = DBuilder.getOrCreateArray(EltTys);
+
+ EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
+ Unit, LineNo, FieldOffset, 0,
+ Flags, Elements);
+
+ BlockLiteralGenericSet = true;
+ BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
+ return BlockLiteralGeneric;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) {
+ // Typedefs are derived from some other type. If we have a typedef of a
+ // typedef, make sure to emit the whole chain.
+ llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+ if (!Src.Verify())
+ return llvm::DIType();
+ // We don't set size information, but do specify where the typedef was
+ // declared.
+ unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
+ const TypedefNameDecl *TyDecl = Ty->getDecl();
+
+ llvm::DIDescriptor TypedefContext =
+ getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
+
+ return
+ DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
+ llvm::DIFile Unit) {
+ SmallVector<llvm::Value *, 16> EltTys;
+
+ // Add the result type at least.
+ EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
+
+ // Set up remainder of arguments if there is a prototype.
+ // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
+ if (isa<FunctionNoProtoType>(Ty))
+ EltTys.push_back(DBuilder.createUnspecifiedParameter());
+ else if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Ty)) {
+ for (unsigned i = 0, e = FPT->getNumArgs(); i != e; ++i)
+ EltTys.push_back(getOrCreateType(FPT->getArgType(i), Unit));
+ }
+
+ llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(EltTys);
+ return DBuilder.createSubroutineType(Unit, EltTypeArray);
+}
+
+
+void CGDebugInfo::
+CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) {
+
+ for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
+ I != E; ++I)
+ if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
+ if (V->getInit()) {
+ const APValue *Value = V->evaluateValue();
+ if (Value && Value->isInt()) {
+ llvm::ConstantInt *CI
+ = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
+
+ // Create the descriptor for static variable.
+ llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
+ StringRef VName = V->getName();
+ llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
+ // Do not use DIGlobalVariable for enums.
+ if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
+ DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
+ getLineNumber(V->getLocation()),
+ VTy, true, CI);
+ }
+ }
+ }
+ }
+}
+
+llvm::DIType CGDebugInfo::createFieldType(StringRef name,
+ QualType type,
+ uint64_t sizeInBitsOverride,
+ SourceLocation loc,
+ AccessSpecifier AS,
+ uint64_t offsetInBits,
+ llvm::DIFile tunit,
+ llvm::DIDescriptor scope) {
+ llvm::DIType debugType = getOrCreateType(type, tunit);
+
+ // Get the location for the field.
+ llvm::DIFile file = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+
+ uint64_t sizeInBits = 0;
+ unsigned alignInBits = 0;
+ if (!type->isIncompleteArrayType()) {
+ llvm::tie(sizeInBits, alignInBits) = CGM.getContext().getTypeInfo(type);
+
+ if (sizeInBitsOverride)
+ sizeInBits = sizeInBitsOverride;
+ }
+
+ unsigned flags = 0;
+ if (AS == clang::AS_private)
+ flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (AS == clang::AS_protected)
+ flags |= llvm::DIDescriptor::FlagProtected;
+
+ return DBuilder.createMemberType(scope, name, file, line, sizeInBits,
+ alignInBits, offsetInBits, flags, debugType);
+}
+
+/// CollectRecordFields - A helper function to collect debug info for
+/// record fields. This is used while creating debug info entry for a Record.
+void CGDebugInfo::
+CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
+ SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DIType RecordTy) {
+ unsigned fieldNo = 0;
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
+
+ // For C++11 Lambdas a Field will be the same as a Capture, but the Capture
+ // has the name and the location of the variable so we should iterate over
+ // both concurrently.
+ if (CXXDecl && CXXDecl->isLambda()) {
+ RecordDecl::field_iterator Field = CXXDecl->field_begin();
+ unsigned fieldno = 0;
+ for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
+ E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {
+ const LambdaExpr::Capture C = *I;
+ if (C.capturesVariable()) {
+ VarDecl *V = C.getCapturedVar();
+ llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
+ StringRef VName = V->getName();
+ uint64_t SizeInBitsOverride = 0;
+ if (Field->isBitField()) {
+ SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());
+ assert(SizeInBitsOverride && "found named 0-width bitfield");
+ }
+ llvm::DIType fieldType
+ = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(),
+ Field->getAccess(), layout.getFieldOffset(fieldno),
+ VUnit, RecordTy);
+ elements.push_back(fieldType);
+ } else {
+ // TODO: Need to handle 'this' in some way by probably renaming the
+ // this of the lambda class and having a field member of 'this' or
+ // by using AT_object_pointer for the function and having that be
+ // used as 'this' for semantic references.
+ assert(C.capturesThis() && "Field that isn't captured and isn't this?");
+ FieldDecl *f = *Field;
+ llvm::DIFile VUnit = getOrCreateFile(f->getLocation());
+ QualType type = f->getType();
+ llvm::DIType fieldType
+ = createFieldType("this", type, 0, f->getLocation(), f->getAccess(),
+ layout.getFieldOffset(fieldNo), VUnit, RecordTy);
+
+ elements.push_back(fieldType);
+ }
+ }
+ } else {
+ bool IsMsStruct = record->isMsStruct(CGM.getContext());
+ const FieldDecl *LastFD = 0;
+ for (RecordDecl::field_iterator I = record->field_begin(),
+ E = record->field_end();
+ I != E; ++I, ++fieldNo) {
+ FieldDecl *field = *I;
+
+ if (IsMsStruct) {
+ // Zero-length bitfields following non-bitfield members are ignored
+ if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) {
+ --fieldNo;
+ continue;
+ }
+ LastFD = field;
+ }
+
+ StringRef name = field->getName();
+ QualType type = field->getType();
+
+ // Ignore unnamed fields unless they're anonymous structs/unions.
+ if (name.empty() && !type->isRecordType()) {
+ LastFD = field;
+ continue;
+ }
+
+ uint64_t SizeInBitsOverride = 0;
+ if (field->isBitField()) {
+ SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());
+ assert(SizeInBitsOverride && "found named 0-width bitfield");
+ }
+
+ llvm::DIType fieldType
+ = createFieldType(name, type, SizeInBitsOverride,
+ field->getLocation(), field->getAccess(),
+ layout.getFieldOffset(fieldNo), tunit, RecordTy);
+
+ elements.push_back(fieldType);
+ }
+ }
+}
+
+/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
+/// function type is not updated to include implicit "this" pointer. Use this
+/// routine to get a method type which includes "this" pointer.
+llvm::DIType
+CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
+ llvm::DIFile Unit) {
+ llvm::DIType FnTy
+ = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),
+ 0),
+ Unit);
+
+ // Add "this" pointer.
+ llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();
+ assert (Args.getNumElements() && "Invalid number of arguments!");
+
+ SmallVector<llvm::Value *, 16> Elts;
+
+ // First element is always return type. For 'void' functions it is NULL.
+ Elts.push_back(Args.getElement(0));
+
+ if (!Method->isStatic()) {
+ // "this" pointer is always first argument.
+ QualType ThisPtr = Method->getThisType(CGM.getContext());
+
+ const CXXRecordDecl *RD = Method->getParent();
+ if (isa<ClassTemplateSpecializationDecl>(RD)) {
+ // Create pointer type directly in this case.
+ const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);
+ QualType PointeeTy = ThisPtrTy->getPointeeType();
+ unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
+ uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
+ uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
+ llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
+ llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align);
+ TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
+ // TODO: This and the artificial type below are misleading, the
+ // types aren't artificial the argument is, but the current
+ // metadata doesn't represent that.
+ ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
+ Elts.push_back(ThisPtrType);
+ } else {
+ llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);
+ TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
+ ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
+ Elts.push_back(ThisPtrType);
+ }
+ }
+
+ // Copy rest of the arguments.
+ for (unsigned i = 1, e = Args.getNumElements(); i != e; ++i)
+ Elts.push_back(Args.getElement(i));
+
+ llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
+
+ return DBuilder.createSubroutineType(Unit, EltTypeArray);
+}
+
+/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
+/// inside a function.
+static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
+ if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
+ return isFunctionLocalClass(NRD);
+ if (isa<FunctionDecl>(RD->getDeclContext()))
+ return true;
+ return false;
+}
+
+/// CreateCXXMemberFunction - A helper function to create a DISubprogram for
+/// a single member function GlobalDecl.
+llvm::DISubprogram
+CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
+ llvm::DIFile Unit,
+ llvm::DIType RecordTy) {
+ bool IsCtorOrDtor =
+ isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
+
+ StringRef MethodName = getFunctionName(Method);
+ llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
+
+ // Since a single ctor/dtor corresponds to multiple functions, it doesn't
+ // make sense to give a single ctor/dtor a linkage name.
+ StringRef MethodLinkageName;
+ if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent()))
+ MethodLinkageName = CGM.getMangledName(Method);
+
+ // Get the location for the method.
+ llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
+ unsigned MethodLine = getLineNumber(Method->getLocation());
+
+ // Collect virtual method info.
+ llvm::DIType ContainingType;
+ unsigned Virtuality = 0;
+ unsigned VIndex = 0;
+
+ if (Method->isVirtual()) {
+ if (Method->isPure())
+ Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
+ else
+ Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
+
+ // It doesn't make sense to give a virtual destructor a vtable index,
+ // since a single destructor has two entries in the vtable.
+ if (!isa<CXXDestructorDecl>(Method))
+ VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);
+ ContainingType = RecordTy;
+ }
+
+ unsigned Flags = 0;
+ if (Method->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+ AccessSpecifier Access = Method->getAccess();
+ if (Access == clang::AS_private)
+ Flags |= llvm::DIDescriptor::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ Flags |= llvm::DIDescriptor::FlagProtected;
+ if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
+ if (CXXC->isExplicit())
+ Flags |= llvm::DIDescriptor::FlagExplicit;
+ } else if (const CXXConversionDecl *CXXC =
+ dyn_cast<CXXConversionDecl>(Method)) {
+ if (CXXC->isExplicit())
+ Flags |= llvm::DIDescriptor::FlagExplicit;
+ }
+ if (Method->hasPrototype())
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+
+ llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
+ llvm::DISubprogram SP =
+ DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
+ MethodDefUnit, MethodLine,
+ MethodTy, /*isLocalToUnit=*/false,
+ /* isDefinition=*/ false,
+ Virtuality, VIndex, ContainingType,
+ Flags, CGM.getLangOpts().Optimize, NULL,
+ TParamsArray);
+
+ SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);
+
+ return SP;
+}
+
+/// CollectCXXMemberFunctions - A helper function to collect debug info for
+/// C++ member functions. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+
+ // Since we want more than just the individual member decls if we
+ // have templated functions iterate over every declaration to gather
+ // the functions.
+ for(DeclContext::decl_iterator I = RD->decls_begin(),
+ E = RD->decls_end(); I != E; ++I) {
+ Decl *D = *I;
+ if (D->isImplicit() && !D->isUsed())
+ continue;
+
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(),
+ SE = FTD->spec_end(); SI != SE; ++SI)
+ EltTys.push_back(CreateCXXMemberFunction(cast<CXXMethodDecl>(*SI), Unit,
+ RecordTy));
+ }
+}
+
+/// CollectCXXFriends - A helper function to collect debug info for
+/// C++ base classes. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+ for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
+ BE = RD->friend_end(); BI != BE; ++BI) {
+ if ((*BI)->isUnsupportedFriend())
+ continue;
+ if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
+ EltTys.push_back(DBuilder.createFriend(RecordTy,
+ getOrCreateType(TInfo->getType(),
+ Unit)));
+ }
+}
+
+/// CollectCXXBases - A helper function to collect debug info for
+/// C++ base classes. This is used while creating debug info entry for
+/// a Record.
+void CGDebugInfo::
+CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy) {
+
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ for (CXXRecordDecl::base_class_const_iterator BI = RD->bases_begin(),
+ BE = RD->bases_end(); BI != BE; ++BI) {
+ unsigned BFlags = 0;
+ uint64_t BaseOffset;
+
+ const CXXRecordDecl *Base =
+ cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
+
+ if (BI->isVirtual()) {
+ // virtual base offset offset is -ve. The code generator emits dwarf
+ // expression where it expects +ve number.
+ BaseOffset =
+ 0 - CGM.getVTableContext()
+ .getVirtualBaseOffsetOffset(RD, Base).getQuantity();
+ BFlags = llvm::DIDescriptor::FlagVirtual;
+ } else
+ BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
+ // FIXME: Inconsistent units for BaseOffset. It is in bytes when
+ // BI->isVirtual() and bits when not.
+
+ AccessSpecifier Access = BI->getAccessSpecifier();
+ if (Access == clang::AS_private)
+ BFlags |= llvm::DIDescriptor::FlagPrivate;
+ else if (Access == clang::AS_protected)
+ BFlags |= llvm::DIDescriptor::FlagProtected;
+
+ llvm::DIType DTy =
+ DBuilder.createInheritance(RecordTy,
+ getOrCreateType(BI->getType(), Unit),
+ BaseOffset, BFlags);
+ EltTys.push_back(DTy);
+ }
+}
+
+/// CollectTemplateParams - A helper function to collect template parameters.
+llvm::DIArray CGDebugInfo::
+CollectTemplateParams(const TemplateParameterList *TPList,
+ const TemplateArgumentList &TAList,
+ llvm::DIFile Unit) {
+ SmallVector<llvm::Value *, 16> TemplateParams;
+ for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
+ const TemplateArgument &TA = TAList[i];
+ const NamedDecl *ND = TPList->getParam(i);
+ if (TA.getKind() == TemplateArgument::Type) {
+ llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
+ llvm::DITemplateTypeParameter TTP =
+ DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);
+ TemplateParams.push_back(TTP);
+ } else if (TA.getKind() == TemplateArgument::Integral) {
+ llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
+ TA.getAsIntegral().getZExtValue());
+ TemplateParams.push_back(TVP);
+ }
+ }
+ return DBuilder.getOrCreateArray(TemplateParams);
+}
+
+/// CollectFunctionTemplateParams - A helper function to collect debug
+/// info for function template parameters.
+llvm::DIArray CGDebugInfo::
+CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {
+ if (FD->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization) {
+ const TemplateParameterList *TList =
+ FD->getTemplateSpecializationInfo()->getTemplate()
+ ->getTemplateParameters();
+ return
+ CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);
+ }
+ return llvm::DIArray();
+}
+
+/// CollectCXXTemplateParams - A helper function to collect debug info for
+/// template parameters.
+llvm::DIArray CGDebugInfo::
+CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
+ llvm::DIFile Unit) {
+ llvm::PointerUnion<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>
+ PU = TSpecial->getSpecializedTemplateOrPartial();
+
+ TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
+ PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
+ PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
+ const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
+ return CollectTemplateParams(TPList, TAList, Unit);
+}
+
+/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
+llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
+ if (VTablePtrType.isValid())
+ return VTablePtrType;
+
+ ASTContext &Context = CGM.getContext();
+
+ /* Function type */
+ llvm::Value *STy = getOrCreateType(Context.IntTy, Unit);
+ llvm::DIArray SElements = DBuilder.getOrCreateArray(STy);
+ llvm::DIType SubTy = DBuilder.createSubroutineType(Unit, SElements);
+ unsigned Size = Context.getTypeSize(Context.VoidPtrTy);
+ llvm::DIType vtbl_ptr_type = DBuilder.createPointerType(SubTy, Size, 0,
+ "__vtbl_ptr_type");
+ VTablePtrType = DBuilder.createPointerType(vtbl_ptr_type, Size);
+ return VTablePtrType;
+}
+
+/// getVTableName - Get vtable name for the given Class.
+StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
+ // Construct gdb compatible name name.
+ std::string Name = "_vptr$" + RD->getNameAsString();
+
+ // Copy this name on the side and use its reference.
+ char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
+ memcpy(StrPtr, Name.data(), Name.length());
+ return StringRef(StrPtr, Name.length());
+}
+
+
+/// CollectVTableInfo - If the C++ class has vtable info then insert appropriate
+/// debug info entry in EltTys vector.
+void CGDebugInfo::
+CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
+ SmallVectorImpl<llvm::Value *> &EltTys) {
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+
+ // If there is a primary base then it will hold vtable info.
+ if (RL.getPrimaryBase())
+ return;
+
+ // If this class is not dynamic then there is not any vtable info to collect.
+ if (!RD->isDynamicClass())
+ return;
+
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ llvm::DIType VPTR
+ = DBuilder.createMemberType(Unit, getVTableName(RD), Unit,
+ 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,
+ getOrCreateVTablePtrType(Unit));
+ EltTys.push_back(VPTR);
+}
+
+/// getOrCreateRecordType - Emit record type's standalone debug info.
+llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
+ SourceLocation Loc) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
+ return T;
+}
+
+/// getOrCreateInterfaceType - Emit an objective c interface type standalone
+/// debug info.
+llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
+ SourceLocation Loc) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
+ DBuilder.retainType(T);
+ return T;
+}
+
+/// CreateType - get structure or union type.
+llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
+ RecordDecl *RD = Ty->getDecl();
+
+ // Get overall information about the record type for the debug info.
+ llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+
+ // Records and classes and unions can all be recursive. To handle them, we
+ // first generate a debug descriptor for the struct as a forward declaration.
+ // Then (if it is a definition) we go through and get debug info for all of
+ // its members. Finally, we create a descriptor for the complete type (which
+ // may refer to the forward decl if the struct is recursive) and replace all
+ // uses of the forward declaration with the final definition.
+
+ llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit);
+
+ if (FwdDecl.isForwardDecl())
+ return FwdDecl;
+
+ llvm::TrackingVH<llvm::MDNode> FwdDeclNode(FwdDecl);
+
+ // Push the struct on region stack.
+ LexicalBlockStack.push_back(FwdDeclNode);
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
+
+ // Add this to the completed types cache since we're completing it.
+ CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
+
+ // Convert all the elements.
+ SmallVector<llvm::Value *, 16> EltTys;
+
+ // Note: The split of CXXDecl information here is intentional, the
+ // gdb tests will depend on a certain ordering at printout. The debug
+ // information offsets are still correct if we merge them all together
+ // though.
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+ if (CXXDecl) {
+ CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl);
+ CollectVTableInfo(CXXDecl, DefUnit, EltTys);
+ }
+
+ // Collect static variables with initializers and other fields.
+ CollectRecordStaticVars(RD, FwdDecl);
+ CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
+ llvm::DIArray TParamsArray;
+ if (CXXDecl) {
+ CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
+ CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);
+ if (const ClassTemplateSpecializationDecl *TSpecial
+ = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);
+ }
+
+ LexicalBlockStack.pop_back();
+ RegionMap.erase(Ty->getDecl());
+
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ // FIXME: Magic numbers ahoy! These should be changed when we
+ // get some enums in llvm/Analysis/DebugInfo.h to refer to
+ // them.
+ if (RD->isUnion())
+ FwdDeclNode->replaceOperandWith(10, Elements);
+ else if (CXXDecl) {
+ FwdDeclNode->replaceOperandWith(10, Elements);
+ FwdDeclNode->replaceOperandWith(13, TParamsArray);
+ } else
+ FwdDeclNode->replaceOperandWith(10, Elements);
+
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode);
+ return llvm::DIType(FwdDeclNode);
+}
+
+/// CreateType - get objective-c object type.
+llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
+ llvm::DIFile Unit) {
+ // Ignore protocols.
+ return getOrCreateType(Ty->getBaseType(), Unit);
+}
+
+/// CreateType - get objective-c interface type.
+llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
+ llvm::DIFile Unit) {
+ ObjCInterfaceDecl *ID = Ty->getDecl();
+ if (!ID)
+ return llvm::DIType();
+
+ // Get overall information about the record type for the debug info.
+ llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation());
+ unsigned Line = getLineNumber(ID->getLocation());
+ unsigned RuntimeLang = TheCU.getLanguage();
+
+ // If this is just a forward declaration return a special forward-declaration
+ // debug type since we won't be able to lay out the entire type.
+ ObjCInterfaceDecl *Def = ID->getDefinition();
+ if (!Def) {
+ llvm::DIType FwdDecl =
+ DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ ID->getName(), TheCU, DefUnit, Line,
+ RuntimeLang);
+ return FwdDecl;
+ }
+
+ ID = Def;
+
+ // Bit size, align and offset of the type.
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ unsigned Flags = 0;
+ if (ID->getImplementation())
+ Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
+
+ llvm::DIType RealDecl =
+ DBuilder.createStructType(Unit, ID->getName(), DefUnit,
+ Line, Size, Align, Flags,
+ llvm::DIArray(), RuntimeLang);
+
+ // Otherwise, insert it into the CompletedTypeCache so that recursive uses
+ // will find it and we're emitting the complete type.
+ CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
+ // Push the struct on region stack.
+ llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl);
+
+ LexicalBlockStack.push_back(FwdDeclNode);
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
+
+ // Convert all the elements.
+ SmallVector<llvm::Value *, 16> EltTys;
+
+ ObjCInterfaceDecl *SClass = ID->getSuperClass();
+ if (SClass) {
+ llvm::DIType SClassTy =
+ getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
+ if (!SClassTy.isValid())
+ return llvm::DIType();
+
+ llvm::DIType InhTag =
+ DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
+ EltTys.push_back(InhTag);
+ }
+
+ for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(),
+ E = ID->prop_end(); I != E; ++I) {
+ const ObjCPropertyDecl *PD = *I;
+ SourceLocation Loc = PD->getLocation();
+ llvm::DIFile PUnit = getOrCreateFile(Loc);
+ unsigned PLine = getLineNumber(Loc);
+ ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
+ ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
+ llvm::MDNode *PropertyNode =
+ DBuilder.createObjCProperty(PD->getName(),
+ PUnit, PLine,
+ (Getter && Getter->isImplicit()) ? "" :
+ getSelectorName(PD->getGetterName()),
+ (Setter && Setter->isImplicit()) ? "" :
+ getSelectorName(PD->getSetterName()),
+ PD->getPropertyAttributes(),
+ getOrCreateType(PD->getType(), PUnit));
+ EltTys.push_back(PropertyNode);
+ }
+
+ const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
+ unsigned FieldNo = 0;
+ for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field;
+ Field = Field->getNextIvar(), ++FieldNo) {
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ if (!FieldTy.isValid())
+ return llvm::DIType();
+
+ StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields.
+ if (FieldName.empty())
+ continue;
+
+ // Get the location for the field.
+ llvm::DIFile FieldDefUnit = getOrCreateFile(Field->getLocation());
+ unsigned FieldLine = getLineNumber(Field->getLocation());
+ QualType FType = Field->getType();
+ uint64_t FieldSize = 0;
+ unsigned FieldAlign = 0;
+
+ if (!FType->isIncompleteArrayType()) {
+
+ // Bit size, align and offset of the type.
+ FieldSize = Field->isBitField()
+ ? Field->getBitWidthValue(CGM.getContext())
+ : CGM.getContext().getTypeSize(FType);
+ FieldAlign = CGM.getContext().getTypeAlign(FType);
+ }
+
+ uint64_t FieldOffset;
+ if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
+ // We don't know the runtime offset of an ivar if we're using the
+ // non-fragile ABI. For bitfields, use the bit offset into the first
+ // byte of storage of the bitfield. For other fields, use zero.
+ if (Field->isBitField()) {
+ FieldOffset = CGM.getObjCRuntime().ComputeBitfieldBitOffset(
+ CGM, ID, Field);
+ FieldOffset %= CGM.getContext().getCharWidth();
+ } else {
+ FieldOffset = 0;
+ }
+ } else {
+ FieldOffset = RL.getFieldOffset(FieldNo);
+ }
+
+ unsigned Flags = 0;
+ if (Field->getAccessControl() == ObjCIvarDecl::Protected)
+ Flags = llvm::DIDescriptor::FlagProtected;
+ else if (Field->getAccessControl() == ObjCIvarDecl::Private)
+ Flags = llvm::DIDescriptor::FlagPrivate;
+
+ llvm::MDNode *PropertyNode = NULL;
+ if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
+ if (ObjCPropertyImplDecl *PImpD =
+ ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
+ if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
+ SourceLocation Loc = PD->getLocation();
+ llvm::DIFile PUnit = getOrCreateFile(Loc);
+ unsigned PLine = getLineNumber(Loc);
+ ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
+ ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
+ PropertyNode =
+ DBuilder.createObjCProperty(PD->getName(),
+ PUnit, PLine,
+ (Getter && Getter->isImplicit()) ? "" :
+ getSelectorName(PD->getGetterName()),
+ (Setter && Setter->isImplicit()) ? "" :
+ getSelectorName(PD->getSetterName()),
+ PD->getPropertyAttributes(),
+ getOrCreateType(PD->getType(), PUnit));
+ }
+ }
+ }
+ FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit,
+ FieldLine, FieldSize, FieldAlign,
+ FieldOffset, Flags, FieldTy,
+ PropertyNode);
+ EltTys.push_back(FieldTy);
+ }
+
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ FwdDeclNode->replaceOperandWith(10, Elements);
+
+ LexicalBlockStack.pop_back();
+ return llvm::DIType(FwdDeclNode);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
+ llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
+ int64_t Count = Ty->getNumElements();
+ if (Count == 0)
+ // If number of elements are not known then this is an unbounded array.
+ // Use Count == -1 to express such arrays.
+ Count = -1;
+
+ llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, Count);
+ llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+
+ return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
+ llvm::DIFile Unit) {
+ uint64_t Size;
+ uint64_t Align;
+
+ // FIXME: make getTypeAlign() aware of VLAs and incomplete array types
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(Ty)) {
+ Size = 0;
+ Align =
+ CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
+ } else if (Ty->isIncompleteArrayType()) {
+ Size = 0;
+ if (Ty->getElementType()->isIncompleteType())
+ Align = 0;
+ else
+ Align = CGM.getContext().getTypeAlign(Ty->getElementType());
+ } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {
+ Size = 0;
+ Align = 0;
+ } else {
+ // Size and align of the whole array, not the element type.
+ Size = CGM.getContext().getTypeSize(Ty);
+ Align = CGM.getContext().getTypeAlign(Ty);
+ }
+
+ // Add the dimensions of the array. FIXME: This loses CV qualifiers from
+ // interior arrays, do we care? Why aren't nested arrays represented the
+ // obvious/recursive way?
+ SmallVector<llvm::Value *, 8> Subscripts;
+ QualType EltTy(Ty, 0);
+ while ((Ty = dyn_cast<ArrayType>(EltTy))) {
+ // If the number of elements is known, then count is that number. Otherwise,
+ // it's -1. This allows us to represent a subrange with an array of 0
+ // elements, like this:
+ //
+ // struct foo {
+ // int x[0];
+ // };
+ int64_t Count = -1; // Count == -1 is an unbounded array.
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
+ Count = CAT->getSize().getZExtValue();
+
+ // FIXME: Verify this is right for VLAs.
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
+ EltTy = Ty->getElementType();
+ }
+
+ llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
+
+ llvm::DIType DbgTy =
+ DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
+ SubscriptArray);
+ return DbgTy;
+}
+
+llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
+ Ty, Ty->getPointeeType(), Unit);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
+ llvm::DIFile Unit) {
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
+ Ty, Ty->getPointeeType(), Unit);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
+ llvm::DIFile U) {
+ QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
+ llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
+
+ if (!Ty->getPointeeType()->isFunctionType()) {
+ // We have a data member pointer type.
+ return PointerDiffDITy;
+ }
+
+ // We have a member function pointer type. Treat it as a struct with two
+ // ptrdiff_t members.
+ std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
+
+ uint64_t FieldOffset = 0;
+ llvm::Value *ElementTypes[2];
+
+ // FIXME: This should be a DW_TAG_pointer_to_member type.
+ ElementTypes[0] =
+ DBuilder.createMemberType(U, "ptr", U, 0,
+ Info.first, Info.second, FieldOffset, 0,
+ PointerDiffDITy);
+ FieldOffset += Info.first;
+
+ ElementTypes[1] =
+ DBuilder.createMemberType(U, "ptr", U, 0,
+ Info.first, Info.second, FieldOffset, 0,
+ PointerDiffDITy);
+
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes);
+
+ return DBuilder.createStructType(U, StringRef("test"),
+ U, 0, FieldOffset,
+ 0, 0, Elements);
+}
+
+llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
+ llvm::DIFile U) {
+ // Ignore the atomic wrapping
+ // FIXME: What is the correct representation?
+ return getOrCreateType(Ty->getValueType(), U);
+}
+
+/// CreateEnumType - get enumeration type.
+llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
+ uint64_t Size = 0;
+ uint64_t Align = 0;
+ if (!ED->getTypeForDecl()->isIncompleteType()) {
+ Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
+ Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ }
+
+ // If this is just a forward declaration, construct an appropriately
+ // marked node and just return it.
+ if (!ED->getDefinition()) {
+ llvm::DIDescriptor EDContext;
+ EDContext = getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ unsigned Line = getLineNumber(ED->getLocation());
+ StringRef EDName = ED->getName();
+ return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,
+ EDName, EDContext, DefUnit, Line, 0,
+ Size, Align);
+ }
+
+ // Create DIEnumerator elements for each enumerator.
+ SmallVector<llvm::Value *, 16> Enumerators;
+ ED = ED->getDefinition();
+ for (EnumDecl::enumerator_iterator
+ Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end();
+ Enum != EnumEnd; ++Enum) {
+ Enumerators.push_back(
+ DBuilder.createEnumerator(Enum->getName(),
+ Enum->getInitVal().getZExtValue()));
+ }
+
+ // Return a CompositeType for the enum itself.
+ llvm::DIArray EltArray = DBuilder.getOrCreateArray(Enumerators);
+
+ llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
+ unsigned Line = getLineNumber(ED->getLocation());
+ llvm::DIDescriptor EnumContext =
+ getContextDescriptor(cast<Decl>(ED->getDeclContext()));
+ llvm::DIType ClassTy = ED->isScopedUsingClassTag() ?
+ getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType();
+ llvm::DIType DbgTy =
+ DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
+ Size, Align, EltArray,
+ ClassTy);
+ return DbgTy;
+}
+
+static QualType UnwrapTypeForDebugInfo(QualType T) {
+ do {
+ QualType LastT = T;
+ switch (T->getTypeClass()) {
+ default:
+ return T;
+ case Type::TemplateSpecialization:
+ T = cast<TemplateSpecializationType>(T)->desugar();
+ break;
+ case Type::TypeOfExpr:
+ T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType();
+ break;
+ case Type::TypeOf:
+ T = cast<TypeOfType>(T)->getUnderlyingType();
+ break;
+ case Type::Decltype:
+ T = cast<DecltypeType>(T)->getUnderlyingType();
+ break;
+ case Type::UnaryTransform:
+ T = cast<UnaryTransformType>(T)->getUnderlyingType();
+ break;
+ case Type::Attributed:
+ T = cast<AttributedType>(T)->getEquivalentType();
+ break;
+ case Type::Elaborated:
+ T = cast<ElaboratedType>(T)->getNamedType();
+ break;
+ case Type::Paren:
+ T = cast<ParenType>(T)->getInnerType();
+ break;
+ case Type::SubstTemplateTypeParm: {
+ // We need to keep the qualifiers handy since getReplacementType()
+ // will strip them away.
+ unsigned Quals = T.getLocalFastQualifiers();
+ T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
+ T.addFastQualifiers(Quals);
+ }
+ break;
+ case Type::Auto:
+ T = cast<AutoType>(T)->getDeducedType();
+ break;
+ }
+
+ assert(T != LastT && "Type unwrapping failed to unwrap!");
+ if (T == LastT)
+ return T;
+ } while (true);
+}
+
+/// getType - Get the type from the cache or return null type if it doesn't exist.
+llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
+
+ // Unwrap the type as needed for debug information.
+ Ty = UnwrapTypeForDebugInfo(Ty);
+
+ // Check for existing entry.
+ llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
+ TypeCache.find(Ty.getAsOpaquePtr());
+ if (it != TypeCache.end()) {
+ // Verify that the debug info still exists.
+ if (llvm::Value *V = it->second)
+ return llvm::DIType(cast<llvm::MDNode>(V));
+ }
+
+ return llvm::DIType();
+}
+
+/// getCompletedTypeOrNull - Get the type from the cache or return null if it
+/// doesn't exist.
+llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
+
+ // Unwrap the type as needed for debug information.
+ Ty = UnwrapTypeForDebugInfo(Ty);
+
+ // Check for existing entry.
+ llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
+ CompletedTypeCache.find(Ty.getAsOpaquePtr());
+ if (it != CompletedTypeCache.end()) {
+ // Verify that the debug info still exists.
+ if (llvm::Value *V = it->second)
+ return llvm::DIType(cast<llvm::MDNode>(V));
+ }
+
+ return llvm::DIType();
+}
+
+
+/// getOrCreateType - Get the type from the cache or create a new
+/// one if necessary.
+llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
+ if (Ty.isNull())
+ return llvm::DIType();
+
+ // Unwrap the type as needed for debug information.
+ Ty = UnwrapTypeForDebugInfo(Ty);
+
+ llvm::DIType T = getCompletedTypeOrNull(Ty);
+
+ if (T.Verify())
+ return T;
+
+ // Otherwise create the type.
+ llvm::DIType Res = CreateTypeNode(Ty, Unit);
+
+ llvm::DIType TC = getTypeOrNull(Ty);
+ if (TC.Verify() && TC.isForwardDecl())
+ ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
+ static_cast<llvm::Value*>(TC)));
+
+ // And update the type cache.
+ TypeCache[Ty.getAsOpaquePtr()] = Res;
+
+ if (!Res.isForwardDecl())
+ CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;
+
+ return Res;
+}
+
+/// CreateTypeNode - Create a new debug type node.
+llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
+ // Handle qualifiers, which recursively handles what they refer to.
+ if (Ty.hasLocalQualifiers())
+ return CreateQualifiedType(Ty, Unit);
+
+ const char *Diag = 0;
+
+ // Work out details of type.
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Dependent types cannot show up in debug information");
+
+ case Type::ExtVector:
+ case Type::Vector:
+ return CreateType(cast<VectorType>(Ty), Unit);
+ case Type::ObjCObjectPointer:
+ return CreateType(cast<ObjCObjectPointerType>(Ty), Unit);
+ case Type::ObjCObject:
+ return CreateType(cast<ObjCObjectType>(Ty), Unit);
+ case Type::ObjCInterface:
+ return CreateType(cast<ObjCInterfaceType>(Ty), Unit);
+ case Type::Builtin:
+ return CreateType(cast<BuiltinType>(Ty));
+ case Type::Complex:
+ return CreateType(cast<ComplexType>(Ty));
+ case Type::Pointer:
+ return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::BlockPointer:
+ return CreateType(cast<BlockPointerType>(Ty), Unit);
+ case Type::Typedef:
+ return CreateType(cast<TypedefType>(Ty), Unit);
+ case Type::Record:
+ return CreateType(cast<RecordType>(Ty));
+ case Type::Enum:
+ return CreateEnumType(cast<EnumType>(Ty)->getDecl());
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ return CreateType(cast<FunctionType>(Ty), Unit);
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ case Type::IncompleteArray:
+ return CreateType(cast<ArrayType>(Ty), Unit);
+
+ case Type::LValueReference:
+ return CreateType(cast<LValueReferenceType>(Ty), Unit);
+ case Type::RValueReference:
+ return CreateType(cast<RValueReferenceType>(Ty), Unit);
+
+ case Type::MemberPointer:
+ return CreateType(cast<MemberPointerType>(Ty), Unit);
+
+ case Type::Atomic:
+ return CreateType(cast<AtomicType>(Ty), Unit);
+
+ case Type::Attributed:
+ case Type::TemplateSpecialization:
+ case Type::Elaborated:
+ case Type::Paren:
+ case Type::SubstTemplateTypeParm:
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::UnaryTransform:
+ case Type::Auto:
+ llvm_unreachable("type should have been unwrapped!");
+ }
+
+ assert(Diag && "Fall through without a diagnostic?");
+ unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,
+ "debug information for %0 is not yet supported");
+ CGM.getDiags().Report(DiagID)
+ << Diag;
+ return llvm::DIType();
+}
+
+/// getOrCreateLimitedType - Get the type from the cache or create a new
+/// limited type if necessary.
+llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,
+ llvm::DIFile Unit) {
+ if (Ty.isNull())
+ return llvm::DIType();
+
+ // Unwrap the type as needed for debug information.
+ Ty = UnwrapTypeForDebugInfo(Ty);
+
+ llvm::DIType T = getTypeOrNull(Ty);
+
+ // We may have cached a forward decl when we could have created
+ // a non-forward decl. Go ahead and create a non-forward decl
+ // now.
+ if (T.Verify() && !T.isForwardDecl()) return T;
+
+ // Otherwise create the type.
+ llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);
+
+ if (T.Verify() && T.isForwardDecl())
+ ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
+ static_cast<llvm::Value*>(T)));
+
+ // And update the type cache.
+ TypeCache[Ty.getAsOpaquePtr()] = Res;
+ return Res;
+}
+
+// TODO: Currently used for context chains when limiting debug info.
+llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+ RecordDecl *RD = Ty->getDecl();
+
+ // Get overall information about the record type for the debug info.
+ llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
+ unsigned Line = getLineNumber(RD->getLocation());
+ StringRef RDName = getClassName(RD);
+
+ llvm::DIDescriptor RDContext;
+ if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo)
+ RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
+ else
+ RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+
+ // If this is just a forward declaration, construct an appropriately
+ // marked node and just return it.
+ if (!RD->getDefinition())
+ return createRecordFwdDecl(RD, RDContext);
+
+ uint64_t Size = CGM.getContext().getTypeSize(Ty);
+ uint64_t Align = CGM.getContext().getTypeAlign(Ty);
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+ llvm::TrackingVH<llvm::MDNode> RealDecl;
+
+ if (RD->isUnion())
+ RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, llvm::DIArray());
+ else if (RD->isClass()) {
+ // FIXME: This could be a struct type giving a default visibility different
+ // than C++ class type, but needs llvm metadata changes first.
+ RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, 0, llvm::DIType(),
+ llvm::DIArray(), llvm::DIType(),
+ llvm::DIArray());
+ } else
+ RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
+ Size, Align, 0, llvm::DIArray());
+
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = llvm::DIType(RealDecl);
+
+ if (CXXDecl) {
+ // A class's primary base or the class itself contains the vtable.
+ llvm::MDNode *ContainingType = NULL;
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
+ // Seek non virtual primary base root.
+ while (1) {
+ const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
+ const CXXRecordDecl *PBT = BRL.getPrimaryBase();
+ if (PBT && !BRL.isPrimaryBaseVirtual())
+ PBase = PBT;
+ else
+ break;
+ }
+ ContainingType =
+ getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
+ }
+ else if (CXXDecl->isDynamicClass())
+ ContainingType = RealDecl;
+
+ RealDecl->replaceOperandWith(12, ContainingType);
+ }
+ return llvm::DIType(RealDecl);
+}
+
+/// CreateLimitedTypeNode - Create a new debug type node, but only forward
+/// declare composite types that haven't been processed yet.
+llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
+
+ // Work out details of type.
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_TYPE(Class, Base)
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+ #include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Dependent types cannot show up in debug information");
+
+ case Type::Record:
+ return CreateLimitedType(cast<RecordType>(Ty));
+ default:
+ return CreateTypeNode(Ty, Unit);
+ }
+}
+
+/// CreateMemberType - Create new member and increase Offset by FType's size.
+llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
+ StringRef Name,
+ uint64_t *Offset) {
+ llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
+ unsigned FieldAlign = CGM.getContext().getTypeAlign(FType);
+ llvm::DIType Ty = DBuilder.createMemberType(Unit, Name, Unit, 0,
+ FieldSize, FieldAlign,
+ *Offset, 0, FieldTy);
+ *Offset += FieldSize;
+ return Ty;
+}
+
+/// getFunctionDeclaration - Return debug info descriptor to describe method
+/// declaration for the given method definition.
+llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
+ const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) return llvm::DISubprogram();
+
+ // Setup context.
+ getContextDescriptor(cast<Decl>(D->getDeclContext()));
+
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ MI = SPCache.find(FD->getCanonicalDecl());
+ if (MI != SPCache.end()) {
+ llvm::Value *V = MI->second;
+ llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
+ if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ return SP;
+ }
+
+ for (FunctionDecl::redecl_iterator I = FD->redecls_begin(),
+ E = FD->redecls_end(); I != E; ++I) {
+ const FunctionDecl *NextFD = *I;
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ MI = SPCache.find(NextFD->getCanonicalDecl());
+ if (MI != SPCache.end()) {
+ llvm::Value *V = MI->second;
+ llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
+ if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ return SP;
+ }
+ }
+ return llvm::DISubprogram();
+}
+
+// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
+// implicit parameter "this".
+llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
+ QualType FnType,
+ llvm::DIFile F) {
+
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
+ return getOrCreateMethodType(Method, F);
+ if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) {
+ // Add "self" and "_cmd"
+ SmallVector<llvm::Value *, 16> Elts;
+
+ // First element is always return type. For 'void' functions it is NULL.
+ Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
+ // "self" pointer is always first argument.
+ llvm::DIType SelfTy = getOrCreateType(OMethod->getSelfDecl()->getType(), F);
+ Elts.push_back(DBuilder.createObjectPointerType(SelfTy));
+ // "_cmd" pointer is always second argument.
+ llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
+ Elts.push_back(DBuilder.createArtificialType(CmdTy));
+ // Get rest of the arguments.
+ for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
+ PE = OMethod->param_end(); PI != PE; ++PI)
+ Elts.push_back(getOrCreateType((*PI)->getType(), F));
+
+ llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
+ return DBuilder.createSubroutineType(F, EltTypeArray);
+ }
+ return getOrCreateType(FnType, F);
+}
+
+/// EmitFunctionStart - Constructs the debug code for entering a function.
+void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
+ llvm::Function *Fn,
+ CGBuilderTy &Builder) {
+
+ StringRef Name;
+ StringRef LinkageName;
+
+ FnBeginRegionCount.push_back(LexicalBlockStack.size());
+
+ const Decl *D = GD.getDecl();
+ // Function may lack declaration in source code if it is created by Clang
+ // CodeGen (examples: _GLOBAL__I_a, __cxx_global_array_dtor, thunk).
+ bool HasDecl = (D != 0);
+ // Use the location of the declaration.
+ SourceLocation Loc;
+ if (HasDecl)
+ Loc = D->getLocation();
+
+ unsigned Flags = 0;
+ llvm::DIFile Unit = getOrCreateFile(Loc);
+ llvm::DIDescriptor FDContext(Unit);
+ llvm::DIArray TParamsArray;
+ if (!HasDecl) {
+ // Use llvm function name.
+ Name = Fn->getName();
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ // If there is a DISubprogram for this function available then use it.
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
+ FI = SPCache.find(FD->getCanonicalDecl());
+ if (FI != SPCache.end()) {
+ llvm::Value *V = FI->second;
+ llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(V));
+ if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) {
+ llvm::MDNode *SPN = SP;
+ LexicalBlockStack.push_back(SPN);
+ RegionMap[D] = llvm::WeakVH(SP);
+ return;
+ }
+ }
+ Name = getFunctionName(FD);
+ // Use mangled name as linkage name for c/c++ functions.
+ if (FD->hasPrototype()) {
+ LinkageName = CGM.getMangledName(GD);
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ }
+ if (LinkageName == Name ||
+ CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly)
+ LinkageName = StringRef();
+
+ if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+ if (const NamespaceDecl *NSDecl =
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ FDContext = getOrCreateNameSpace(NSDecl);
+ else if (const RecordDecl *RDecl =
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
+ FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
+
+ // Collect template parameters.
+ TParamsArray = CollectFunctionTemplateParams(FD, Unit);
+ }
+ } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
+ Name = getObjCMethodName(OMD);
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ } else {
+ // Use llvm function name.
+ Name = Fn->getName();
+ Flags |= llvm::DIDescriptor::FlagPrototyped;
+ }
+ if (!Name.empty() && Name[0] == '\01')
+ Name = Name.substr(1);
+
+ unsigned LineNo = getLineNumber(Loc);
+ if (!HasDecl || D->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+
+ llvm::DIType DIFnType;
+ llvm::DISubprogram SPDecl;
+ if (HasDecl &&
+ CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+ DIFnType = getOrCreateFunctionType(D, FnType, Unit);
+ SPDecl = getFunctionDeclaration(D);
+ } else {
+ // Create fake but valid subroutine type. Otherwise
+ // llvm::DISubprogram::Verify() would return false, and
+ // subprogram DIE will miss DW_AT_decl_file and
+ // DW_AT_decl_line fields.
+ SmallVector<llvm::Value*, 16> Elts;
+ llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
+ DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);
+ }
+ llvm::DISubprogram SP;
+ SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
+ LineNo, DIFnType,
+ Fn->hasInternalLinkage(), true/*definition*/,
+ getLineNumber(CurLoc), Flags,
+ CGM.getLangOpts().Optimize,
+ Fn, TParamsArray, SPDecl);
+
+ // Push function on region stack.
+ llvm::MDNode *SPN = SP;
+ LexicalBlockStack.push_back(SPN);
+ if (HasDecl)
+ RegionMap[D] = llvm::WeakVH(SP);
+}
+
+/// EmitLocation - Emit metadata to indicate a change in line/column
+/// information in the source file.
+void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
+
+ // Update our current location
+ setLocation(Loc);
+
+ if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
+
+ // Don't bother if things are the same as last time.
+ SourceManager &SM = CGM.getContext().getSourceManager();
+ if (CurLoc == PrevLoc ||
+ SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))
+ // New Builder may not be in sync with CGDebugInfo.
+ if (!Builder.getCurrentDebugLocation().isUnknown())
+ return;
+
+ // Update last state.
+ PrevLoc = CurLoc;
+
+ llvm::MDNode *Scope = LexicalBlockStack.back();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
+ getColumnNumber(CurLoc),
+ Scope));
+}
+
+/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
+/// the stack.
+void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
+ llvm::DIDescriptor D =
+ DBuilder.createLexicalBlock(LexicalBlockStack.empty() ?
+ llvm::DIDescriptor() :
+ llvm::DIDescriptor(LexicalBlockStack.back()),
+ getOrCreateFile(CurLoc),
+ getLineNumber(CurLoc),
+ getColumnNumber(CurLoc));
+ llvm::MDNode *DN = D;
+ LexicalBlockStack.push_back(DN);
+}
+
+/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
+/// region - beginning of a DW_TAG_lexical_block.
+void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {
+ // Set our current location.
+ setLocation(Loc);
+
+ // Create a new lexical block and push it on the stack.
+ CreateLexicalBlock(Loc);
+
+ // Emit a line table change for the current location inside the new scope.
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc),
+ getColumnNumber(Loc),
+ LexicalBlockStack.back()));
+}
+
+/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
+/// region - end of a DW_TAG_lexical_block.
+void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {
+ assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
+
+ // Provide an entry in the line table for the end of the block.
+ EmitLocation(Builder, Loc);
+
+ LexicalBlockStack.pop_back();
+}
+
+/// EmitFunctionEnd - Constructs the debug code for exiting a function.
+void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
+ assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
+ unsigned RCount = FnBeginRegionCount.back();
+ assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");
+
+ // Pop all regions for this function.
+ while (LexicalBlockStack.size() != RCount)
+ EmitLexicalBlockEnd(Builder, CurLoc);
+ FnBeginRegionCount.pop_back();
+}
+
+// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+// See BuildByRefType.
+llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *XOffset) {
+
+ SmallVector<llvm::Value *, 5> EltTys;
+ QualType FType;
+ uint64_t FieldSize, FieldOffset;
+ unsigned FieldAlign;
+
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ QualType Type = VD->getType();
+
+ FieldOffset = 0;
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__isa", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__forwarding", &FieldOffset));
+ FType = CGM.getContext().IntTy;
+ EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
+
+ bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);
+ if (HasCopyAndDispose) {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
+ EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
+ &FieldOffset));
+ EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
+ &FieldOffset));
+ }
+ bool HasByrefExtendedLayout;
+ Qualifiers::ObjCLifetime Lifetime;
+ if (CGM.getContext().getByrefLifetime(Type,
+ Lifetime, HasByrefExtendedLayout)
+ && HasByrefExtendedLayout)
+ EltTys.push_back(CreateMemberType(Unit, FType,
+ "__byref_variable_layout",
+ &FieldOffset));
+
+ CharUnits Align = CGM.getContext().getDeclAlign(VD);
+ if (Align > CGM.getContext().toCharUnitsFromBits(
+ CGM.getContext().getTargetInfo().getPointerAlign(0))) {
+ CharUnits FieldOffsetInBytes
+ = CGM.getContext().toCharUnitsFromBits(FieldOffset);
+ CharUnits AlignedOffsetInBytes
+ = FieldOffsetInBytes.RoundUpToAlignment(Align);
+ CharUnits NumPaddingBytes
+ = AlignedOffsetInBytes - FieldOffsetInBytes;
+
+ if (NumPaddingBytes.isPositive()) {
+ llvm::APInt pad(32, NumPaddingBytes.getQuantity());
+ FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
+ pad, ArrayType::Normal, 0);
+ EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
+ }
+ }
+
+ FType = Type;
+ llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = CGM.getContext().getTypeSize(FType);
+ FieldAlign = CGM.getContext().toBits(Align);
+
+ *XOffset = FieldOffset;
+ FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+
+ unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
+
+ return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
+ Elements);
+}
+
+/// EmitDeclare - Emit local variable declaration debug info.
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
+ llvm::Value *Storage,
+ unsigned ArgNo, CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
+
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIType Ty;
+ uint64_t XOffset = 0;
+ if (VD->hasAttr<BlocksAttr>())
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ else
+ Ty = getOrCreateType(VD->getType(), Unit);
+
+ // If there is no debug info for this type then do not emit debug info
+ // for this variable.
+ if (!Ty)
+ return;
+
+ if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
+ // If Storage is an aggregate returned as 'sret' then let debugger know
+ // about this.
+ if (Arg->hasStructRetAttr())
+ Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
+ else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
+ // If an aggregate variable has non trivial destructor or non trivial copy
+ // constructor than it is pass indirectly. Let debug info know about this
+ // by using reference of the aggregate type as a argument type.
+ if (Record->hasNonTrivialCopyConstructor() ||
+ !Record->hasTrivialDestructor())
+ Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
+ }
+ }
+
+ // Get location information.
+ unsigned Line = getLineNumber(VD->getLocation());
+ unsigned Column = getColumnNumber(VD->getLocation());
+ unsigned Flags = 0;
+ if (VD->isImplicit())
+ Flags |= llvm::DIDescriptor::FlagArtificial;
+ // If this is the first argument and it is implicit then
+ // give it an object pointer flag.
+ // FIXME: There has to be a better way to do this, but for static
+ // functions there won't be an implicit param at arg1 and
+ // otherwise it is 'self' or 'this'.
+ if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
+ Flags |= llvm::DIDescriptor::FlagObjectPointer;
+
+ llvm::MDNode *Scope = LexicalBlockStack.back();
+
+ StringRef Name = VD->getName();
+ if (!Name.empty()) {
+ if (VD->hasAttr<BlocksAttr>()) {
+ CharUnits offset = CharUnits::fromQuantity(32);
+ SmallVector<llvm::Value *, 9> addr;
+ llvm::Type *Int64Ty = CGM.Int64Ty;
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of __forwarding field
+ offset = CGM.getContext().toCharUnitsFromBits(
+ CGM.getContext().getTargetInfo().getPointerWidth(0));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of x field
+ offset = CGM.getContext().toCharUnitsFromBits(XOffset);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.createComplexVariable(Tag,
+ llvm::DIDescriptor(Scope),
+ VD->getName(), Unit, Line, Ty,
+ addr, ArgNo);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ return;
+ } else if (isa<VariableArrayType>(VD->getType())) {
+ // These are "complex" variables in that they need an op_deref.
+ // Create the descriptor for the variable.
+ llvm::Value *Addr = llvm::ConstantInt::get(CGM.Int64Ty,
+ llvm::DIBuilder::OpDeref);
+ llvm::DIVariable D =
+ DBuilder.createComplexVariable(Tag,
+ llvm::DIDescriptor(Scope),
+ Name, Unit, Line, Ty,
+ Addr, ArgNo);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ return;
+ }
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags, ArgNo);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ return;
+ }
+
+ // If VD is an anonymous union then Storage represents value for
+ // all union fields.
+ if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
+ if (RD->isUnion()) {
+ for (RecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end();
+ I != E; ++I) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+ StringRef FieldName = Field->getName();
+
+ // Ignore unnamed fields. Do not ignore unnamed records.
+ if (FieldName.empty() && !isa<RecordType>(Field->getType()))
+ continue;
+
+ // Use VarDecl's Tag, Scope and Line number.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ FieldName, Unit, Line, FieldTy,
+ CGM.getLangOpts().Optimize, Flags,
+ ArgNo);
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
+ }
+ }
+ }
+}
+
+void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
+ llvm::Value *Storage,
+ CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
+}
+
+void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
+ llvm::Value *Storage,
+ CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
+
+ if (Builder.GetInsertBlock() == 0)
+ return;
+
+ bool isByRef = VD->hasAttr<BlocksAttr>();
+
+ uint64_t XOffset = 0;
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ llvm::DIType Ty;
+ if (isByRef)
+ Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
+ else
+ Ty = getOrCreateType(VD->getType(), Unit);
+
+ // Self is passed along as an implicit non-arg variable in a
+ // block. Mark it as the object pointer.
+ if (isa<ImplicitParamDecl>(VD) && VD->getName() == "self")
+ Ty = DBuilder.createObjectPointerType(Ty);
+
+ // Get location information.
+ unsigned Line = getLineNumber(VD->getLocation());
+ unsigned Column = getColumnNumber(VD->getLocation());
+
+ const llvm::DataLayout &target = CGM.getDataLayout();
+
+ CharUnits offset = CharUnits::fromQuantity(
+ target.getStructLayout(blockInfo.StructureType)
+ ->getElementOffset(blockInfo.getCapture(VD).getIndex()));
+
+ SmallVector<llvm::Value *, 9> addr;
+ llvm::Type *Int64Ty = CGM.Int64Ty;
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ if (isByRef) {
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of __forwarding field
+ offset = CGM.getContext()
+ .toCharUnitsFromBits(target.getPointerSizeInBits(0));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
+ // offset of x field
+ offset = CGM.getContext().toCharUnitsFromBits(XOffset);
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
+ }
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
+ llvm::DIDescriptor(LexicalBlockStack.back()),
+ VD->getName(), Unit, Line, Ty, addr);
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *Call =
+ DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());
+ Call->setDebugLoc(llvm::DebugLoc::get(Line, Column,
+ LexicalBlockStack.back()));
+}
+
+/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+/// variable declaration.
+void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
+ unsigned ArgNo,
+ CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
+}
+
+namespace {
+ struct BlockLayoutChunk {
+ uint64_t OffsetInBits;
+ const BlockDecl::Capture *Capture;
+ };
+ bool operator<(const BlockLayoutChunk &l, const BlockLayoutChunk &r) {
+ return l.OffsetInBits < r.OffsetInBits;
+ }
+}
+
+void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ ASTContext &C = CGM.getContext();
+ const BlockDecl *blockDecl = block.getBlockDecl();
+
+ // Collect some general information about the block's location.
+ SourceLocation loc = blockDecl->getCaretLocation();
+ llvm::DIFile tunit = getOrCreateFile(loc);
+ unsigned line = getLineNumber(loc);
+ unsigned column = getColumnNumber(loc);
+
+ // Build the debug-info type for the block literal.
+ getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
+
+ const llvm::StructLayout *blockLayout =
+ CGM.getDataLayout().getStructLayout(block.StructureType);
+
+ SmallVector<llvm::Value*, 16> fields;
+ fields.push_back(createFieldType("__isa", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(0),
+ tunit, tunit));
+ fields.push_back(createFieldType("__flags", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(1),
+ tunit, tunit));
+ fields.push_back(createFieldType("__reserved", C.IntTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(2),
+ tunit, tunit));
+ fields.push_back(createFieldType("__FuncPtr", C.VoidPtrTy, 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(3),
+ tunit, tunit));
+ fields.push_back(createFieldType("__descriptor",
+ C.getPointerType(block.NeedsCopyDispose ?
+ C.getBlockDescriptorExtendedType() :
+ C.getBlockDescriptorType()),
+ 0, loc, AS_public,
+ blockLayout->getElementOffsetInBits(4),
+ tunit, tunit));
+
+ // We want to sort the captures by offset, not because DWARF
+ // requires this, but because we're paranoid about debuggers.
+ SmallVector<BlockLayoutChunk, 8> chunks;
+
+ // 'this' capture.
+ if (blockDecl->capturesCXXThis()) {
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(block.CXXThisIndex);
+ chunk.Capture = 0;
+ chunks.push_back(chunk);
+ }
+
+ // Variable captures.
+ for (BlockDecl::capture_const_iterator
+ i = blockDecl->capture_begin(), e = blockDecl->capture_end();
+ i != e; ++i) {
+ const BlockDecl::Capture &capture = *i;
+ const VarDecl *variable = capture.getVariable();
+ const CGBlockInfo::Capture &captureInfo = block.getCapture(variable);
+
+ // Ignore constant captures.
+ if (captureInfo.isConstant())
+ continue;
+
+ BlockLayoutChunk chunk;
+ chunk.OffsetInBits =
+ blockLayout->getElementOffsetInBits(captureInfo.getIndex());
+ chunk.Capture = &capture;
+ chunks.push_back(chunk);
+ }
+
+ // Sort by offset.
+ llvm::array_pod_sort(chunks.begin(), chunks.end());
+
+ for (SmallVectorImpl<BlockLayoutChunk>::iterator
+ i = chunks.begin(), e = chunks.end(); i != e; ++i) {
+ uint64_t offsetInBits = i->OffsetInBits;
+ const BlockDecl::Capture *capture = i->Capture;
+
+ // If we have a null capture, this must be the C++ 'this' capture.
+ if (!capture) {
+ const CXXMethodDecl *method =
+ cast<CXXMethodDecl>(blockDecl->getNonClosureContext());
+ QualType type = method->getThisType(C);
+
+ fields.push_back(createFieldType("this", type, 0, loc, AS_public,
+ offsetInBits, tunit, tunit));
+ continue;
+ }
+
+ const VarDecl *variable = capture->getVariable();
+ StringRef name = variable->getName();
+
+ llvm::DIType fieldType;
+ if (capture->isByRef()) {
+ std::pair<uint64_t,unsigned> ptrInfo = C.getTypeInfo(C.VoidPtrTy);
+
+ // FIXME: this creates a second copy of this type!
+ uint64_t xoffset;
+ fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
+ fieldType = DBuilder.createPointerType(fieldType, ptrInfo.first);
+ fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
+ ptrInfo.first, ptrInfo.second,
+ offsetInBits, 0, fieldType);
+ } else {
+ fieldType = createFieldType(name, variable->getType(), 0,
+ loc, AS_public, offsetInBits, tunit, tunit);
+ }
+ fields.push_back(fieldType);
+ }
+
+ SmallString<36> typeName;
+ llvm::raw_svector_ostream(typeName)
+ << "__block_literal_" << CGM.getUniqueBlockCount();
+
+ llvm::DIArray fieldsArray = DBuilder.getOrCreateArray(fields);
+
+ llvm::DIType type =
+ DBuilder.createStructType(tunit, typeName.str(), tunit, line,
+ CGM.getContext().toBits(block.BlockSize),
+ CGM.getContext().toBits(block.BlockAlign),
+ 0, fieldsArray);
+ type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
+
+ // Get overall information about the block.
+ unsigned flags = llvm::DIDescriptor::FlagArtificial;
+ llvm::MDNode *scope = LexicalBlockStack.back();
+ StringRef name = ".block_descriptor";
+
+ // Create the descriptor for the parameter.
+ llvm::DIVariable debugVar =
+ DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
+ llvm::DIDescriptor(scope),
+ name, tunit, line, type,
+ CGM.getLangOpts().Optimize, flags,
+ cast<llvm::Argument>(addr)->getArgNo() + 1);
+
+ // Insert an llvm.dbg.value into the current block.
+ llvm::Instruction *declare =
+ DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
+ Builder.GetInsertBlock());
+ declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+}
+
+/// EmitGlobalVariable - Emit information about a global variable.
+void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
+ const VarDecl *D) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ // Create global variable debug descriptor.
+ llvm::DIFile Unit = getOrCreateFile(D->getLocation());
+ unsigned LineNo = getLineNumber(D->getLocation());
+
+ setLocation(D->getLocation());
+
+ QualType T = D->getType();
+ if (T->isIncompleteArrayType()) {
+
+ // CodeGen turns int[] into int[1] so we'll do the same here.
+ llvm::APInt ConstVal(32, 1);
+ QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
+
+ T = CGM.getContext().getConstantArrayType(ET, ConstVal,
+ ArrayType::Normal, 0);
+ }
+ StringRef DeclName = D->getName();
+ StringRef LinkageName;
+ if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())
+ && !isa<ObjCMethodDecl>(D->getDeclContext()))
+ LinkageName = Var->getName();
+ if (LinkageName == DeclName)
+ LinkageName = StringRef();
+ llvm::DIDescriptor DContext =
+ getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
+ DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
+ Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var);
+}
+
+/// EmitGlobalVariable - Emit information about an objective-c interface.
+void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
+ ObjCInterfaceDecl *ID) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ // Create global variable debug descriptor.
+ llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
+ unsigned LineNo = getLineNumber(ID->getLocation());
+
+ StringRef Name = ID->getName();
+
+ QualType T = CGM.getContext().getObjCInterfaceType(ID);
+ if (T->isIncompleteArrayType()) {
+
+ // CodeGen turns int[] into int[1] so we'll do the same here.
+ llvm::APInt ConstVal(32, 1);
+ QualType ET = CGM.getContext().getAsArrayType(T)->getElementType();
+
+ T = CGM.getContext().getConstantArrayType(ET, ConstVal,
+ ArrayType::Normal, 0);
+ }
+
+ DBuilder.createGlobalVariable(Name, Unit, LineNo,
+ getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var);
+}
+
+/// EmitGlobalVariable - Emit global variable's debug info.
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
+ llvm::Constant *Init) {
+ assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ // Create the descriptor for the variable.
+ llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ StringRef Name = VD->getName();
+ llvm::DIType Ty = getOrCreateType(VD->getType(), Unit);
+ if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) {
+ const EnumDecl *ED = cast<EnumDecl>(ECD->getDeclContext());
+ assert(isa<EnumType>(ED->getTypeForDecl()) && "Enum without EnumType?");
+ Ty = getOrCreateType(QualType(ED->getTypeForDecl(), 0), Unit);
+ }
+ // Do not use DIGlobalVariable for enums.
+ if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
+ return;
+ DBuilder.createStaticVariable(Unit, Name, Name, Unit,
+ getLineNumber(VD->getLocation()),
+ Ty, true, Init);
+}
+
+/// getOrCreateNamesSpace - Return namespace descriptor for the given
+/// namespace decl.
+llvm::DINameSpace
+CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
+ NameSpaceCache.find(NSDecl);
+ if (I != NameSpaceCache.end())
+ return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
+
+ unsigned LineNo = getLineNumber(NSDecl->getLocation());
+ llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
+ llvm::DIDescriptor Context =
+ getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
+ llvm::DINameSpace NS =
+ DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
+ NameSpaceCache[NSDecl] = llvm::WeakVH(NS);
+ return NS;
+}
+
+void CGDebugInfo::finalize() {
+ for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI
+ = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) {
+ llvm::DIType Ty, RepTy;
+ // Verify that the debug info still exists.
+ if (llvm::Value *V = VI->second)
+ Ty = llvm::DIType(cast<llvm::MDNode>(V));
+
+ llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
+ TypeCache.find(VI->first);
+ if (it != TypeCache.end()) {
+ // Verify that the debug info still exists.
+ if (llvm::Value *V = it->second)
+ RepTy = llvm::DIType(cast<llvm::MDNode>(V));
+ }
+
+ if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {
+ Ty.replaceAllUsesWith(RepTy);
+ }
+ }
+ DBuilder.finalize();
+}
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Tue Dec 18 08:30:41 2012
@@ -1,330 +1,325 @@
-//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the source level debug info generator for llvm translation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_CODEGEN_CGDEBUGINFO_H
-#define CLANG_CODEGEN_CGDEBUGINFO_H
-
-#include "CGBuilder.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Type.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/DIBuilder.h"
-#include "llvm/DebugInfo.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ValueHandle.h"
-
-namespace llvm {
- class MDNode;
-}
-
-namespace clang {
- class CXXMethodDecl;
- class VarDecl;
- class ObjCInterfaceDecl;
- class ClassTemplateSpecializationDecl;
- class GlobalDecl;
-
-namespace CodeGen {
- class CodeGenModule;
- class CodeGenFunction;
- class CGBlockInfo;
-
-/// CGDebugInfo - This class gathers all debug information during compilation
-/// and is responsible for emitting to llvm globals or pass directly to
-/// the backend.
-class CGDebugInfo {
- CodeGenModule &CGM;
- llvm::DIBuilder DBuilder;
- llvm::DICompileUnit TheCU;
- SourceLocation CurLoc, PrevLoc;
- llvm::DIType VTablePtrType;
- llvm::DIType ClassTy;
- llvm::DIType ObjTy;
- llvm::DIType SelTy;
- llvm::DIType OCLImage1dDITy, OCLImage1dArrayDITy, OCLImage1dBufferDITy;
- llvm::DIType OCLImage2dDITy, OCLImage2dArrayDITy;
- llvm::DIType OCLImage3dDITy;
-
- /// TypeCache - Cache of previously constructed Types.
- llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
-
- /// CompleteTypeCache - Cache of previously constructed complete RecordTypes.
- llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;
-
- /// ReplaceMap - Cache of forward declared types to RAUW at the end of
- /// compilation.
- std::vector<std::pair<void *, llvm::WeakVH> >ReplaceMap;
-
- bool BlockLiteralGenericSet;
- llvm::DIType BlockLiteralGeneric;
-
- // LexicalBlockStack - Keep track of our current nested lexical block.
- std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;
- llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
- // FnBeginRegionCount - Keep track of LexicalBlockStack counter at the
- // beginning of a function. This is used to pop unbalanced regions at
- // the end of a function.
- std::vector<unsigned> FnBeginRegionCount;
-
- /// DebugInfoNames - This is a storage for names that are
- /// constructed on demand. For example, C++ destructors, C++ operators etc..
- llvm::BumpPtrAllocator DebugInfoNames;
- StringRef CWDName;
-
- llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
- llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;
-
- /// Helper functions for getOrCreateType.
- llvm::DIType CreateType(const BuiltinType *Ty);
- llvm::DIType CreateType(const ComplexType *Ty);
- llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);
- llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
- llvm::DIFile F);
- llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const RecordType *Ty);
- llvm::DIType CreateLimitedType(const RecordType *Ty);
- llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);
- llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
- llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
- llvm::DIType CreateEnumType(const EnumDecl *ED);
- llvm::DIType getTypeOrNull(const QualType);
- llvm::DIType getCompletedTypeOrNull(const QualType);
- llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
- llvm::DIFile F);
- llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,
- llvm::DIFile F);
- llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
- llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
- llvm::DIType CreatePointeeType(QualType PointeeTy, llvm::DIFile F);
- llvm::DIType CreatePointerLikeType(unsigned Tag,
- const Type *Ty, QualType PointeeTy,
- llvm::DIFile F);
-
- llvm::DIType getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache);
-
- llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
- llvm::DIFile F,
- llvm::DIType RecordTy);
-
- void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
- llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &E,
- llvm::DIType T);
-
- void CollectCXXFriends(const CXXRecordDecl *Decl,
- llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy);
-
- void CollectCXXBases(const CXXRecordDecl *Decl,
- llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy);
-
- llvm::DIArray
- CollectTemplateParams(const TemplateParameterList *TPList,
- const TemplateArgumentList &TAList,
- llvm::DIFile Unit);
- llvm::DIArray
- CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit);
- llvm::DIArray
- CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,
- llvm::DIFile F);
-
- llvm::DIType createFieldType(StringRef name, QualType type,
- uint64_t sizeInBitsOverride, SourceLocation loc,
- AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile tunit,
- llvm::DIDescriptor scope);
- void CollectRecordStaticVars(const RecordDecl *, llvm::DIType);
- void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &E,
- llvm::DIType RecordTy);
-
- void CollectVTableInfo(const CXXRecordDecl *Decl,
- llvm::DIFile F,
- SmallVectorImpl<llvm::Value *> &EltTys);
-
- // CreateLexicalBlock - Create a new lexical block node and push it on
- // the stack.
- void CreateLexicalBlock(SourceLocation Loc);
-
-public:
- CGDebugInfo(CodeGenModule &CGM);
- ~CGDebugInfo();
-
- void finalize();
-
- /// setLocation - Update the current source location. If \arg loc is
- /// invalid it is ignored.
- void setLocation(SourceLocation Loc);
-
- /// EmitLocation - Emit metadata to indicate a change in line/column
- /// information in the source file.
- void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);
-
- /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
- /// start of a new function.
- void EmitFunctionStart(GlobalDecl GD, QualType FnType,
- llvm::Function *Fn, CGBuilderTy &Builder);
-
- /// EmitFunctionEnd - Constructs the debug code for exiting a function.
- void EmitFunctionEnd(CGBuilderTy &Builder);
-
- /// EmitLexicalBlockStart - Emit metadata to indicate the beginning of a
- /// new lexical block and push the block onto the stack.
- void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc);
-
- /// EmitLexicalBlockEnd - Emit metadata to indicate the end of a new lexical
- /// block and pop the current block.
- void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc);
-
- /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic
- /// variable declaration.
- void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
- CGBuilderTy &Builder);
-
- /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an
- /// imported variable declaration in a block.
- void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
- llvm::Value *storage,
- CGBuilderTy &Builder,
- const CGBlockInfo &blockInfo);
-
- /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
- /// variable declaration.
- void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder);
-
- /// EmitDeclareOfBlockLiteralArgVariable - Emit call to
- /// llvm.dbg.declare for the block-literal argument to a block
- /// invocation function.
- void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
- llvm::Value *addr,
- CGBuilderTy &Builder);
-
- /// EmitGlobalVariable - Emit information about a global variable.
- void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
-
- /// EmitGlobalVariable - Emit information about an objective-c interface.
- void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
-
- /// EmitGlobalVariable - Emit global variable's debug info.
- void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
-
- /// getOrCreateRecordType - Emit record type's standalone debug info.
- llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
-
- /// getOrCreateInterfaceType - Emit an objective c interface type standalone
- /// debug info.
- llvm::DIType getOrCreateInterfaceType(QualType Ty,
- SourceLocation Loc);
-
-private:
- /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
- void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
- unsigned ArgNo, CGBuilderTy &Builder);
-
- // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
- // See BuildByRefType.
- llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
- uint64_t *OffSet);
-
- /// getContextDescriptor - Get context info for the decl.
- llvm::DIDescriptor getContextDescriptor(const Decl *Decl);
-
- /// createRecordFwdDecl - Create a forward decl for a RecordType in a given
- /// context.
- llvm::DIType createRecordFwdDecl(const RecordDecl *, llvm::DIDescriptor);
-
- /// createContextChain - Create a set of decls for the context chain.
- llvm::DIDescriptor createContextChain(const Decl *Decl);
-
- /// getCurrentDirname - Return current directory name.
- StringRef getCurrentDirname();
-
- /// CreateCompileUnit - Create new compile unit.
- void CreateCompileUnit();
-
- /// getOrCreateFile - Get the file debug info descriptor for the input
- /// location.
- llvm::DIFile getOrCreateFile(SourceLocation Loc);
-
- /// getOrCreateMainFile - Get the file info for main compile unit.
- llvm::DIFile getOrCreateMainFile();
-
- /// getOrCreateType - Get the type from the cache or create a new type if
- /// necessary.
- llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
-
- /// getOrCreateLimitedType - Get the type from the cache or create a new
- /// partial type if necessary.
- llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F);
-
- /// CreateTypeNode - Create type metadata for a source language type.
- llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
-
- /// CreateLimitedTypeNode - Create type metadata for a source language
- /// type, but only partial types for records.
- llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F);
-
- /// CreateMemberType - Create new member and increase Offset by FType's size.
- llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
- StringRef Name, uint64_t *Offset);
-
- /// getFunctionDeclaration - Return debug info descriptor to describe method
- /// declaration for the given method definition.
- llvm::DISubprogram getFunctionDeclaration(const Decl *D);
-
- /// getFunctionName - Get function name for the given FunctionDecl. If the
- /// name is constructred on demand (e.g. C++ destructor) then the name
- /// is stored on the side.
- StringRef getFunctionName(const FunctionDecl *FD);
-
- /// getObjCMethodName - Returns the unmangled name of an Objective-C method.
- /// This is the display name for the debugging info.
- StringRef getObjCMethodName(const ObjCMethodDecl *FD);
-
- /// getSelectorName - Return selector name. This is used for debugging
- /// info.
- StringRef getSelectorName(Selector S);
-
- /// getClassName - Get class name including template argument list.
- StringRef getClassName(const RecordDecl *RD);
-
- /// getVTableName - Get vtable name for the given Class.
- StringRef getVTableName(const CXXRecordDecl *Decl);
-
- /// getLineNumber - Get line number for the location. If location is invalid
- /// then use current location.
- unsigned getLineNumber(SourceLocation Loc);
-
- /// getColumnNumber - Get column number for the location. If location is
- /// invalid then use current location.
- unsigned getColumnNumber(SourceLocation Loc);
-};
-} // namespace CodeGen
-} // namespace clang
-
-
-#endif
+//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the source level debug info generator for llvm translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGDEBUGINFO_H
+#define CLANG_CODEGEN_CGDEBUGINFO_H
+
+#include "CGBuilder.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DIBuilder.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/ValueHandle.h"
+
+namespace llvm {
+ class MDNode;
+}
+
+namespace clang {
+ class CXXMethodDecl;
+ class VarDecl;
+ class ObjCInterfaceDecl;
+ class ClassTemplateSpecializationDecl;
+ class GlobalDecl;
+
+namespace CodeGen {
+ class CodeGenModule;
+ class CodeGenFunction;
+ class CGBlockInfo;
+
+/// CGDebugInfo - This class gathers all debug information during compilation
+/// and is responsible for emitting to llvm globals or pass directly to
+/// the backend.
+class CGDebugInfo {
+ CodeGenModule &CGM;
+ llvm::DIBuilder DBuilder;
+ llvm::DICompileUnit TheCU;
+ SourceLocation CurLoc, PrevLoc;
+ llvm::DIType VTablePtrType;
+ llvm::DIType ClassTy;
+ llvm::DIType ObjTy;
+ llvm::DIType SelTy;
+
+ /// TypeCache - Cache of previously constructed Types.
+ llvm::DenseMap<void *, llvm::WeakVH> TypeCache;
+
+ /// CompleteTypeCache - Cache of previously constructed complete RecordTypes.
+ llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;
+
+ /// ReplaceMap - Cache of forward declared types to RAUW at the end of
+ /// compilation.
+ std::vector<std::pair<void *, llvm::WeakVH> >ReplaceMap;
+
+ bool BlockLiteralGenericSet;
+ llvm::DIType BlockLiteralGeneric;
+
+ // LexicalBlockStack - Keep track of our current nested lexical block.
+ std::vector<llvm::TrackingVH<llvm::MDNode> > LexicalBlockStack;
+ llvm::DenseMap<const Decl *, llvm::WeakVH> RegionMap;
+ // FnBeginRegionCount - Keep track of LexicalBlockStack counter at the
+ // beginning of a function. This is used to pop unbalanced regions at
+ // the end of a function.
+ std::vector<unsigned> FnBeginRegionCount;
+
+ /// DebugInfoNames - This is a storage for names that are
+ /// constructed on demand. For example, C++ destructors, C++ operators etc..
+ llvm::BumpPtrAllocator DebugInfoNames;
+ StringRef CWDName;
+
+ llvm::DenseMap<const char *, llvm::WeakVH> DIFileCache;
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH> SPCache;
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH> NameSpaceCache;
+
+ /// Helper functions for getOrCreateType.
+ llvm::DIType CreateType(const BuiltinType *Ty);
+ llvm::DIType CreateType(const ComplexType *Ty);
+ llvm::DIType CreateQualifiedType(QualType Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const TypedefType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ObjCObjectPointerType *Ty,
+ llvm::DIFile F);
+ llvm::DIType CreateType(const PointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const RecordType *Ty);
+ llvm::DIType CreateLimitedType(const RecordType *Ty);
+ llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const ArrayType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const LValueReferenceType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const RValueReferenceType *Ty, llvm::DIFile Unit);
+ llvm::DIType CreateType(const MemberPointerType *Ty, llvm::DIFile F);
+ llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F);
+ llvm::DIType CreateEnumType(const EnumDecl *ED);
+ llvm::DIType getTypeOrNull(const QualType);
+ llvm::DIType getCompletedTypeOrNull(const QualType);
+ llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method,
+ llvm::DIFile F);
+ llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType,
+ llvm::DIFile F);
+ llvm::DIType getOrCreateVTablePtrType(llvm::DIFile F);
+ llvm::DINameSpace getOrCreateNameSpace(const NamespaceDecl *N);
+ llvm::DIType CreatePointeeType(QualType PointeeTy, llvm::DIFile F);
+ llvm::DIType CreatePointerLikeType(unsigned Tag,
+ const Type *Ty, QualType PointeeTy,
+ llvm::DIFile F);
+
+ llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,
+ llvm::DIFile F,
+ llvm::DIType RecordTy);
+
+ void CollectCXXMemberFunctions(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ SmallVectorImpl<llvm::Value *> &E,
+ llvm::DIType T);
+
+ void CollectCXXFriends(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy);
+
+ void CollectCXXBases(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ SmallVectorImpl<llvm::Value *> &EltTys,
+ llvm::DIType RecordTy);
+
+ llvm::DIArray
+ CollectTemplateParams(const TemplateParameterList *TPList,
+ const TemplateArgumentList &TAList,
+ llvm::DIFile Unit);
+ llvm::DIArray
+ CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit);
+ llvm::DIArray
+ CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TS,
+ llvm::DIFile F);
+
+ llvm::DIType createFieldType(StringRef name, QualType type,
+ uint64_t sizeInBitsOverride, SourceLocation loc,
+ AccessSpecifier AS, uint64_t offsetInBits,
+ llvm::DIFile tunit,
+ llvm::DIDescriptor scope);
+ void CollectRecordStaticVars(const RecordDecl *, llvm::DIType);
+ void CollectRecordFields(const RecordDecl *Decl, llvm::DIFile F,
+ SmallVectorImpl<llvm::Value *> &E,
+ llvm::DIType RecordTy);
+
+ void CollectVTableInfo(const CXXRecordDecl *Decl,
+ llvm::DIFile F,
+ SmallVectorImpl<llvm::Value *> &EltTys);
+
+ // CreateLexicalBlock - Create a new lexical block node and push it on
+ // the stack.
+ void CreateLexicalBlock(SourceLocation Loc);
+
+public:
+ CGDebugInfo(CodeGenModule &CGM);
+ ~CGDebugInfo();
+
+ void finalize();
+
+ /// setLocation - Update the current source location. If \arg loc is
+ /// invalid it is ignored.
+ void setLocation(SourceLocation Loc);
+
+ /// EmitLocation - Emit metadata to indicate a change in line/column
+ /// information in the source file.
+ void EmitLocation(CGBuilderTy &Builder, SourceLocation Loc);
+
+ /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
+ /// start of a new function.
+ void EmitFunctionStart(GlobalDecl GD, QualType FnType,
+ llvm::Function *Fn, CGBuilderTy &Builder);
+
+ /// EmitFunctionEnd - Constructs the debug code for exiting a function.
+ void EmitFunctionEnd(CGBuilderTy &Builder);
+
+ /// EmitLexicalBlockStart - Emit metadata to indicate the beginning of a
+ /// new lexical block and push the block onto the stack.
+ void EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc);
+
+ /// EmitLexicalBlockEnd - Emit metadata to indicate the end of a new lexical
+ /// block and pop the current block.
+ void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc);
+
+ /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic
+ /// variable declaration.
+ void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
+ /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an
+ /// imported variable declaration in a block.
+ void EmitDeclareOfBlockDeclRefVariable(const VarDecl *variable,
+ llvm::Value *storage,
+ CGBuilderTy &Builder,
+ const CGBlockInfo &blockInfo);
+
+ /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+ /// variable declaration.
+ void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
+ unsigned ArgNo, CGBuilderTy &Builder);
+
+ /// EmitDeclareOfBlockLiteralArgVariable - Emit call to
+ /// llvm.dbg.declare for the block-literal argument to a block
+ /// invocation function.
+ void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
+ llvm::Value *addr,
+ CGBuilderTy &Builder);
+
+ /// EmitGlobalVariable - Emit information about a global variable.
+ void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
+
+ /// EmitGlobalVariable - Emit information about an objective-c interface.
+ void EmitGlobalVariable(llvm::GlobalVariable *GV, ObjCInterfaceDecl *Decl);
+
+ /// EmitGlobalVariable - Emit global variable's debug info.
+ void EmitGlobalVariable(const ValueDecl *VD, llvm::Constant *Init);
+
+ /// getOrCreateRecordType - Emit record type's standalone debug info.
+ llvm::DIType getOrCreateRecordType(QualType Ty, SourceLocation L);
+
+ /// getOrCreateInterfaceType - Emit an objective c interface type standalone
+ /// debug info.
+ llvm::DIType getOrCreateInterfaceType(QualType Ty,
+ SourceLocation Loc);
+
+private:
+ /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
+ void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
+ unsigned ArgNo, CGBuilderTy &Builder);
+
+ // EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+ // See BuildByRefType.
+ llvm::DIType EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
+ uint64_t *OffSet);
+
+ /// getContextDescriptor - Get context info for the decl.
+ llvm::DIDescriptor getContextDescriptor(const Decl *Decl);
+
+ /// createRecordFwdDecl - Create a forward decl for a RecordType in a given
+ /// context.
+ llvm::DIType createRecordFwdDecl(const RecordDecl *, llvm::DIDescriptor);
+
+ /// createContextChain - Create a set of decls for the context chain.
+ llvm::DIDescriptor createContextChain(const Decl *Decl);
+
+ /// getCurrentDirname - Return current directory name.
+ StringRef getCurrentDirname();
+
+ /// CreateCompileUnit - Create new compile unit.
+ void CreateCompileUnit();
+
+ /// getOrCreateFile - Get the file debug info descriptor for the input
+ /// location.
+ llvm::DIFile getOrCreateFile(SourceLocation Loc);
+
+ /// getOrCreateMainFile - Get the file info for main compile unit.
+ llvm::DIFile getOrCreateMainFile();
+
+ /// getOrCreateType - Get the type from the cache or create a new type if
+ /// necessary.
+ llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F);
+
+ /// getOrCreateLimitedType - Get the type from the cache or create a new
+ /// partial type if necessary.
+ llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F);
+
+ /// CreateTypeNode - Create type metadata for a source language type.
+ llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F);
+
+ /// CreateLimitedTypeNode - Create type metadata for a source language
+ /// type, but only partial types for records.
+ llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F);
+
+ /// CreateMemberType - Create new member and increase Offset by FType's size.
+ llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType,
+ StringRef Name, uint64_t *Offset);
+
+ /// getFunctionDeclaration - Return debug info descriptor to describe method
+ /// declaration for the given method definition.
+ llvm::DISubprogram getFunctionDeclaration(const Decl *D);
+
+ /// getFunctionName - Get function name for the given FunctionDecl. If the
+ /// name is constructred on demand (e.g. C++ destructor) then the name
+ /// is stored on the side.
+ StringRef getFunctionName(const FunctionDecl *FD);
+
+ /// getObjCMethodName - Returns the unmangled name of an Objective-C method.
+ /// This is the display name for the debugging info.
+ StringRef getObjCMethodName(const ObjCMethodDecl *FD);
+
+ /// getSelectorName - Return selector name. This is used for debugging
+ /// info.
+ StringRef getSelectorName(Selector S);
+
+ /// getClassName - Get class name including template argument list.
+ StringRef getClassName(const RecordDecl *RD);
+
+ /// getVTableName - Get vtable name for the given Class.
+ StringRef getVTableName(const CXXRecordDecl *Decl);
+
+ /// getLineNumber - Get line number for the location. If location is invalid
+ /// then use current location.
+ unsigned getLineNumber(SourceLocation Loc);
+
+ /// getColumnNumber - Get column number for the location. If location is
+ /// invalid then use current location.
+ unsigned getColumnNumber(SourceLocation Loc);
+};
+} // namespace CodeGen
+} // namespace clang
+
+
+#endif
Modified: cfe/trunk/lib/CodeGen/CGOpenCLRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenCLRuntime.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenCLRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenCLRuntime.cpp Tue Dec 18 08:30:41 2012
@@ -1,59 +1,28 @@
-//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides an abstract class for OpenCL code generation. Concrete
-// subclasses of this implement code generation for specific OpenCL
-// runtime libraries.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CGOpenCLRuntime.h"
-#include "CodeGenFunction.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/DerivedTypes.h"
-#include <assert.h>
-
-using namespace clang;
-using namespace CodeGen;
-
-CGOpenCLRuntime::~CGOpenCLRuntime() {}
-
-void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
- const VarDecl &D) {
- return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
-}
-
-llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
- assert(T->isOpenCLSpecificType() &&
- "Not an OpenCL specific type!");
-
- switch (cast<BuiltinType>(T)->getKind()) {
- default:
- llvm_unreachable("Unexpected opencl builtin type!");
- return 0;
- case BuiltinType::OCLImage1d:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image1d_t"), 0);
- case BuiltinType::OCLImage1dArray:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image1d_array_t"), 0);
- case BuiltinType::OCLImage1dBuffer:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image1d_buffer_t"), 0);
- case BuiltinType::OCLImage2d:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image2d_t"), 0);
- case BuiltinType::OCLImage2dArray:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image2d_array_t"), 0);
- case BuiltinType::OCLImage3d:
- return llvm::PointerType::get(llvm::StructType::create(
- CGM.getLLVMContext(), "opencl.image3d_t"), 0);
- }
-}
+//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for OpenCL code generation. Concrete
+// subclasses of this implement code generation for specific OpenCL
+// runtime libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CGOpenCLRuntime.h"
+#include "CodeGenFunction.h"
+#include "llvm/GlobalValue.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+CGOpenCLRuntime::~CGOpenCLRuntime() {}
+
+void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
+ const VarDecl &D) {
+ return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
+}
Modified: cfe/trunk/lib/CodeGen/CGOpenCLRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenCLRuntime.h?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenCLRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGOpenCLRuntime.h Tue Dec 18 08:30:41 2012
@@ -1,52 +1,46 @@
-//===----- CGOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides an abstract class for OpenCL code generation. Concrete
-// subclasses of this implement code generation for specific OpenCL
-// runtime libraries.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef CLANG_CODEGEN_OPENCLRUNTIME_H
-#define CLANG_CODEGEN_OPENCLRUNTIME_H
-
-#include "clang/AST/Type.h"
-#include "llvm/Type.h"
-#include "llvm/Value.h"
-
-namespace clang {
-
-class VarDecl;
-
-namespace CodeGen {
-
-class CodeGenFunction;
-class CodeGenModule;
-
-class CGOpenCLRuntime {
-protected:
- CodeGenModule &CGM;
-
-public:
- CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
- virtual ~CGOpenCLRuntime();
-
- /// Emit the IR required for a work-group-local variable declaration, and add
- /// an entry to CGF's LocalDeclMap for D. The base class does this using
- /// CodeGenFunction::EmitStaticVarDecl to emit an internal global for D.
- virtual void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
- const VarDecl &D);
-
- virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
-};
-
-}
-}
-
-#endif
+//===----- CGOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for OpenCL code generation. Concrete
+// subclasses of this implement code generation for specific OpenCL
+// runtime libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_OPENCLRUNTIME_H
+#define CLANG_CODEGEN_OPENCLRUNTIME_H
+
+namespace clang {
+
+class VarDecl;
+
+namespace CodeGen {
+
+class CodeGenFunction;
+class CodeGenModule;
+
+class CGOpenCLRuntime {
+protected:
+ CodeGenModule &CGM;
+
+public:
+ CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
+ virtual ~CGOpenCLRuntime();
+
+ /// Emit the IR required for a work-group-local variable declaration, and add
+ /// an entry to CGF's LocalDeclMap for D. The base class does this using
+ /// CodeGenFunction::EmitStaticVarDecl to emit an internal global for D.
+ virtual void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
+ const VarDecl &D);
+};
+
+}
+}
+
+#endif
Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Tue Dec 18 08:30:41 2012
@@ -1,1017 +1,1011 @@
-//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This contains code dealing with C++ code generation of RTTI descriptors.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CodeGenModule.h"
-#include "CGCXXABI.h"
-#include "CGObjCRuntime.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/Type.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-using namespace clang;
-using namespace CodeGen;
-
-namespace {
-class RTTIBuilder {
- CodeGenModule &CGM; // Per-module state.
- llvm::LLVMContext &VMContext;
-
- /// Fields - The fields of the RTTI descriptor currently being built.
- SmallVector<llvm::Constant *, 16> Fields;
-
- /// GetAddrOfTypeName - Returns the mangled type name of the given type.
- llvm::GlobalVariable *
- GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
-
- /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
- /// descriptor of the given type.
- llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
-
- /// BuildVTablePointer - Build the vtable pointer for the given type.
- void BuildVTablePointer(const Type *Ty);
-
- /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
- /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
- void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
-
- /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
- /// classes with bases that do not satisfy the abi::__si_class_type_info
- /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
- void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
-
- /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
- /// for pointer types.
- void BuildPointerTypeInfo(QualType PointeeTy);
-
- /// BuildObjCObjectTypeInfo - Build the appropriate kind of
- /// type_info for an object type.
- void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
-
- /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
- /// struct, used for member pointer types.
- void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
-
-public:
- RTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
- VMContext(CGM.getModule().getContext()) { }
-
- // Pointer type info flags.
- enum {
- /// PTI_Const - Type has const qualifier.
- PTI_Const = 0x1,
-
- /// PTI_Volatile - Type has volatile qualifier.
- PTI_Volatile = 0x2,
-
- /// PTI_Restrict - Type has restrict qualifier.
- PTI_Restrict = 0x4,
-
- /// PTI_Incomplete - Type is incomplete.
- PTI_Incomplete = 0x8,
-
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.
- /// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10
- };
-
- // VMI type info flags.
- enum {
- /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
- VMI_NonDiamondRepeat = 0x1,
-
- /// VMI_DiamondShaped - Class is diamond shaped.
- VMI_DiamondShaped = 0x2
- };
-
- // Base class type info flags.
- enum {
- /// BCTI_Virtual - Base class is virtual.
- BCTI_Virtual = 0x1,
-
- /// BCTI_Public - Base class is public.
- BCTI_Public = 0x2
- };
-
- /// BuildTypeInfo - Build the RTTI type info struct for the given type.
- ///
- /// \param Force - true to force the creation of this RTTI value
- llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
-};
-}
-
-llvm::GlobalVariable *
-RTTIBuilder::GetAddrOfTypeName(QualType Ty,
- llvm::GlobalVariable::LinkageTypes Linkage) {
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- // We know that the mangled name of the type starts at index 4 of the
- // mangled name of the typename, so we can just index into it in order to
- // get the mangled name of the type.
- llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
- Name.substr(4));
-
- llvm::GlobalVariable *GV =
- CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
-
- GV->setInitializer(Init);
-
- return GV;
-}
-
-llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
- // Mangle the RTTI name.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- // Look for an existing global.
- llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
-
- if (!GV) {
- // Create a new global variable.
- GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
- /*Constant=*/true,
- llvm::GlobalValue::ExternalLinkage, 0, Name);
- }
-
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-}
-
-/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
-/// info for that type is defined in the standard library.
-static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
- // Itanium C++ ABI 2.9.2:
- // Basic type information (e.g. for "int", "bool", etc.) will be kept in
- // the run-time support library. Specifically, the run-time support
- // library should contain type_info objects for the types X, X* and
- // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
- // unsigned char, signed char, short, unsigned short, int, unsigned int,
- // long, unsigned long, long long, unsigned long long, float, double,
- // long double, char16_t, char32_t, and the IEEE 754r decimal and
- // half-precision floating point types.
- switch (Ty->getKind()) {
- case BuiltinType::Void:
- case BuiltinType::NullPtr:
- case BuiltinType::Bool:
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- case BuiltinType::Char_U:
- case BuiltinType::Char_S:
- case BuiltinType::UChar:
- case BuiltinType::SChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- case BuiltinType::Int:
- case BuiltinType::UInt:
- case BuiltinType::Long:
- case BuiltinType::ULong:
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Int128:
- case BuiltinType::UInt128:
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- return true;
-
- case BuiltinType::Dependent:
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- llvm_unreachable("asking for RRTI for a placeholder type!");
-
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- llvm_unreachable("FIXME: Objective-C types are unsupported!");
- }
-
- llvm_unreachable("Invalid BuiltinType Kind!");
-}
-
-static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
- QualType PointeeTy = PointerTy->getPointeeType();
- const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
- if (!BuiltinTy)
- return false;
-
- // Check the qualifiers.
- Qualifiers Quals = PointeeTy.getQualifiers();
- Quals.removeConst();
-
- if (!Quals.empty())
- return false;
-
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-}
-
-/// IsStandardLibraryRTTIDescriptor - Returns whether the type
-/// information for the given type exists in the standard library.
-static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
- // Type info for builtin types is defined in the standard library.
- if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-
- // Type info for some pointer types to builtin types is defined in the
- // standard library.
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return TypeInfoIsInStandardLibrary(PointerTy);
-
- return false;
-}
-
-/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
-/// the given type exists somewhere else, and that we should not emit the type
-/// information in this translation unit. Assumes that it is not a
-/// standard-library type.
-static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
- ASTContext &Context = CGM.getContext();
-
- // If RTTI is disabled, don't consider key functions.
- if (!Context.getLangOpts().RTTI) return false;
-
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (!RD->hasDefinition())
- return false;
-
- if (!RD->isDynamicClass())
- return false;
-
- return !CGM.getVTables().ShouldEmitVTableInThisTU(RD);
- }
-
- return false;
-}
-
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.
-static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getDecl()->isCompleteDefinition();
-}
-
-/// ContainsIncompleteClassType - Returns whether the given type contains an
-/// incomplete class type. This is true if
-///
-/// * The given type is an incomplete class type.
-/// * The given type is a pointer type whose pointee type contains an
-/// incomplete class type.
-/// * The given type is a member pointer type whose class is an incomplete
-/// class type.
-/// * The given type is a member pointer type whoise pointee type contains an
-/// incomplete class type.
-/// is an indirect or direct pointer to an incomplete class type.
-static bool ContainsIncompleteClassType(QualType Ty) {
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- if (IsIncompleteClassType(RecordTy))
- return true;
- }
-
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return ContainsIncompleteClassType(PointerTy->getPointeeType());
-
- if (const MemberPointerType *MemberPointerTy =
- dyn_cast<MemberPointerType>(Ty)) {
- // Check if the class type is incomplete.
- const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
- if (IsIncompleteClassType(ClassType))
- return true;
-
- return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
- }
-
- return false;
-}
-
-/// getTypeInfoLinkage - Return the linkage that the type info and type info
-/// name constants should have for the given type.
-static llvm::GlobalVariable::LinkageTypes
-getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
- // Itanium C++ ABI 2.9.5p7:
- // In addition, it and all of the intermediate abi::__pointer_type_info
- // structs in the chain down to the abi::__class_type_info for the
- // incomplete class type must be prevented from resolving to the
- // corresponding type_info structs for the complete class type, possibly
- // by making them local static objects. Finally, a dummy class RTTI is
- // generated for the incomplete type that will not resolve to the final
- // complete class RTTI (because the latter need not exist), possibly by
- // making it a local static object.
- if (ContainsIncompleteClassType(Ty))
- return llvm::GlobalValue::InternalLinkage;
-
- switch (Ty->getLinkage()) {
- case NoLinkage:
- case InternalLinkage:
- case UniqueExternalLinkage:
- return llvm::GlobalValue::InternalLinkage;
-
- case ExternalLinkage:
- if (!CGM.getLangOpts().RTTI) {
- // RTTI is not enabled, which means that this type info struct is going
- // to be used for exception handling. Give it linkonce_odr linkage.
- return llvm::GlobalValue::LinkOnceODRLinkage;
- }
-
- if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
- if (RD->hasAttr<WeakAttr>())
- return llvm::GlobalValue::WeakODRLinkage;
- if (RD->isDynamicClass())
- return CGM.getVTableLinkage(RD);
- }
-
- return llvm::GlobalValue::LinkOnceODRLinkage;
- }
-
- llvm_unreachable("Invalid linkage!");
-}
-
-// CanUseSingleInheritance - Return whether the given record decl has a "single,
-// public, non-virtual base at offset zero (i.e. the derived class is dynamic
-// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
-static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
- // Check the number of bases.
- if (RD->getNumBases() != 1)
- return false;
-
- // Get the base.
- CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
-
- // Check that the base is not virtual.
- if (Base->isVirtual())
- return false;
-
- // Check that the base is public.
- if (Base->getAccessSpecifier() != AS_public)
- return false;
-
- // Check that the class is dynamic iff the base is.
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- if (!BaseDecl->isEmpty() &&
- BaseDecl->isDynamicClass() != RD->isDynamicClass())
- return false;
-
- return true;
-}
-
-void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
- // abi::__class_type_info.
- static const char * const ClassTypeInfo =
- "_ZTVN10__cxxabiv117__class_type_infoE";
- // abi::__si_class_type_info.
- static const char * const SIClassTypeInfo =
- "_ZTVN10__cxxabiv120__si_class_type_infoE";
- // abi::__vmi_class_type_info.
- static const char * const VMIClassTypeInfo =
- "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
-
- const char *VTableName = 0;
-
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");
-
- case Type::LValueReference:
- case Type::RValueReference:
- llvm_unreachable("References shouldn't get here");
-
- case Type::Builtin:
- // GCC treats vector and complex types as fundamental types.
- case Type::Vector:
- case Type::ExtVector:
- case Type::Complex:
- case Type::Atomic:
- // FIXME: GCC treats block pointers as fundamental types?!
- case Type::BlockPointer:
- // abi::__fundamental_type_info.
- VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
- break;
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- // abi::__array_type_info.
- VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
- break;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- // abi::__function_type_info.
- VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
- break;
-
- case Type::Enum:
- // abi::__enum_type_info.
- VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
- break;
-
- case Type::Record: {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
-
- if (!RD->hasDefinition() || !RD->getNumBases()) {
- VTableName = ClassTypeInfo;
- } else if (CanUseSingleInheritance(RD)) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = VMIClassTypeInfo;
- }
-
- break;
- }
-
- case Type::ObjCObject:
- // Ignore protocol qualifiers.
- Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
-
- // Handle id and Class.
- if (isa<BuiltinType>(Ty)) {
- VTableName = ClassTypeInfo;
- break;
- }
-
- assert(isa<ObjCInterfaceType>(Ty));
- // Fall through.
-
- case Type::ObjCInterface:
- if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = ClassTypeInfo;
- }
- break;
-
- case Type::ObjCObjectPointer:
- case Type::Pointer:
- // abi::__pointer_type_info.
- VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
- break;
-
- case Type::MemberPointer:
- // abi::__pointer_to_member_type_info.
- VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
- break;
- }
-
- llvm::Constant *VTable =
- CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
-
- llvm::Type *PtrDiffTy =
- CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
-
- // The vtable address point is 2.
- llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
- VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
- VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
-
- Fields.push_back(VTable);
-}
-
-// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures
-// from available_externally to the correct linkage if necessary. An example of
-// this is:
-//
-// struct A {
-// virtual void f();
-// };
-//
-// const std::type_info &g() {
-// return typeid(A);
-// }
-//
-// void A::f() { }
-//
-// When we're generating the typeid(A) expression, we do not yet know that
-// A's key function is defined in this translation unit, so we will give the
-// typeinfo and typename structures available_externally linkage. When A::f
-// forces the vtable to be generated, we need to change the linkage of the
-// typeinfo and typename structs, otherwise we'll end up with undefined
-// externals when linking.
-static void
-maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,
- QualType Ty) {
- // We're only interested in globals with available_externally linkage.
- if (!GV->hasAvailableExternallyLinkage())
- return;
-
- // Get the real linkage for the type.
- llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
-
- // If variable is supposed to have available_externally linkage, we don't
- // need to do anything.
- if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
- return;
-
- // Update the typeinfo linkage.
- GV->setLinkage(Linkage);
-
- // Get the typename global.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);
-
- assert(TypeNameGV->hasAvailableExternallyLinkage() &&
- "Type name has different linkage from type info!");
-
- // And update its linkage.
- TypeNameGV->setLinkage(Linkage);
-}
-
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
- // We want to operate on the canonical type.
- Ty = CGM.getContext().getCanonicalType(Ty);
-
- // Check if we've already emitted an RTTI descriptor for this type.
- SmallString<256> OutName;
- llvm::raw_svector_ostream Out(OutName);
- CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
- Out.flush();
- StringRef Name = OutName.str();
-
- llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
- if (OldGV && !OldGV->isDeclaration()) {
- maybeUpdateRTTILinkage(CGM, OldGV, Ty);
-
- return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
- }
-
- // Check if there is already an external RTTI descriptor for this type.
- bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
- if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
- return GetAddrOfExternalRTTIDescriptor(Ty);
-
- // Emit the standard library with external linkage.
- llvm::GlobalVariable::LinkageTypes Linkage;
- if (IsStdLib)
- Linkage = llvm::GlobalValue::ExternalLinkage;
- else
- Linkage = getTypeInfoLinkage(CGM, Ty);
-
- // Add the vtable pointer.
- BuildVTablePointer(cast<Type>(Ty));
-
- // And the name.
- llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
-
- Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy));
-
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.def"
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");
-
- // GCC treats vector types as fundamental types.
- case Type::Builtin:
- case Type::Vector:
- case Type::ExtVector:
- case Type::Complex:
- case Type::BlockPointer:
- // Itanium C++ ABI 2.9.5p4:
- // abi::__fundamental_type_info adds no data members to std::type_info.
- break;
-
- case Type::LValueReference:
- case Type::RValueReference:
- llvm_unreachable("References shouldn't get here");
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__array_type_info adds no data members to std::type_info.
- break;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__function_type_info adds no data members to std::type_info.
- break;
-
- case Type::Enum:
- // Itanium C++ ABI 2.9.5p5:
- // abi::__enum_type_info adds no data members to std::type_info.
- break;
-
- case Type::Record: {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
- if (!RD->hasDefinition() || !RD->getNumBases()) {
- // We don't need to emit any fields.
- break;
- }
-
- if (CanUseSingleInheritance(RD))
- BuildSIClassTypeInfo(RD);
- else
- BuildVMIClassTypeInfo(RD);
-
- break;
- }
-
- case Type::ObjCObject:
- case Type::ObjCInterface:
- BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
- break;
-
- case Type::ObjCObjectPointer:
- BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
- break;
-
- case Type::Pointer:
- BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
- break;
-
- case Type::MemberPointer:
- BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
- break;
-
- case Type::Atomic:
- // No fields, at least for the moment.
- break;
- }
-
- llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
-
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
- /*Constant=*/true, Linkage, Init, Name);
-
- // If there's already an old global variable, replace it with the new one.
- if (OldGV) {
- GV->takeName(OldGV);
- llvm::Constant *NewPtr =
- llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
- OldGV->replaceAllUsesWith(NewPtr);
- OldGV->eraseFromParent();
- }
-
- // GCC only relies on the uniqueness of the type names, not the
- // type_infos themselves, so we can emit these as hidden symbols.
- // But don't do this if we're worried about strict visibility
- // compatibility.
- if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-
- CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI);
- CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName);
- } else {
- Visibility TypeInfoVisibility = DefaultVisibility;
- if (CGM.getCodeGenOpts().HiddenWeakVTables &&
- Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
- TypeInfoVisibility = HiddenVisibility;
-
- // The type name should have the same visibility as the type itself.
- Visibility ExplicitVisibility = Ty->getVisibility();
- TypeName->setVisibility(CodeGenModule::
- GetLLVMVisibility(ExplicitVisibility));
-
- TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility());
- GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility));
- }
-
- GV->setUnnamedAddr(true);
-
- return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
-}
-
-/// ComputeQualifierFlags - Compute the pointer type info flags from the
-/// given qualifier.
-static unsigned ComputeQualifierFlags(Qualifiers Quals) {
- unsigned Flags = 0;
-
- if (Quals.hasConst())
- Flags |= RTTIBuilder::PTI_Const;
- if (Quals.hasVolatile())
- Flags |= RTTIBuilder::PTI_Volatile;
- if (Quals.hasRestrict())
- Flags |= RTTIBuilder::PTI_Restrict;
-
- return Flags;
-}
-
-/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
-/// for the given Objective-C object type.
-void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
- // Drop qualifiers.
- const Type *T = OT->getBaseType().getTypePtr();
- assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
-
- // The builtin types are abi::__class_type_infos and don't require
- // extra fields.
- if (isa<BuiltinType>(T)) return;
-
- ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
- ObjCInterfaceDecl *Super = Class->getSuperClass();
-
- // Root classes are also __class_type_info.
- if (!Super) return;
-
- QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
-
- // Everything else is single inheritance.
- llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
- Fields.push_back(BaseTypeInfo);
-}
-
-/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
-/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
-void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
- // Itanium C++ ABI 2.9.5p6b:
- // It adds to abi::__class_type_info a single member pointing to the
- // type_info structure for the base type,
- llvm::Constant *BaseTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
- Fields.push_back(BaseTypeInfo);
-}
-
-namespace {
- /// SeenBases - Contains virtual and non-virtual bases seen when traversing
- /// a class hierarchy.
- struct SeenBases {
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
- };
-}
-
-/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
-/// abi::__vmi_class_type_info.
-///
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
- SeenBases &Bases) {
-
- unsigned Flags = 0;
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- if (Base->isVirtual()) {
- // Mark the virtual base as seen.
- if (!Bases.VirtualBases.insert(BaseDecl)) {
- // If this virtual base has been seen before, then the class is diamond
- // shaped.
- Flags |= RTTIBuilder::VMI_DiamondShaped;
- } else {
- if (Bases.NonVirtualBases.count(BaseDecl))
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
- }
- } else {
- // Mark the non-virtual base as seen.
- if (!Bases.NonVirtualBases.insert(BaseDecl)) {
- // If this non-virtual base has been seen before, then the class has non-
- // diamond shaped repeated inheritance.
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
- } else {
- if (Bases.VirtualBases.count(BaseDecl))
- Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
- }
- }
-
- // Walk all bases.
- for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(),
- E = BaseDecl->bases_end(); I != E; ++I)
- Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
-
- return Flags;
-}
-
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
- unsigned Flags = 0;
- SeenBases Bases;
-
- // Walk all bases.
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I)
- Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
-
- return Flags;
-}
-
-/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
-/// classes with bases that do not satisfy the abi::__si_class_type_info
-/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
-void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
-
- // Itanium C++ ABI 2.9.5p6c:
- // __flags is a word with flags describing details about the class
- // structure, which may be referenced by using the __flags_masks
- // enumeration. These flags refer to both direct and indirect bases.
- unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p6c:
- // __base_count is a word with the number of direct proper base class
- // descriptions that follow.
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
-
- if (!RD->getNumBases())
- return;
-
- llvm::Type *LongLTy =
- CGM.getTypes().ConvertType(CGM.getContext().LongTy);
-
- // Now add the base class descriptions.
-
- // Itanium C++ ABI 2.9.5p6c:
- // __base_info[] is an array of base class descriptions -- one for every
- // direct proper base. Each description is of the type:
- //
- // struct abi::__base_class_type_info {
- // public:
- // const __class_type_info *__base_type;
- // long __offset_flags;
- //
- // enum __offset_flags_masks {
- // __virtual_mask = 0x1,
- // __public_mask = 0x2,
- // __offset_shift = 8
- // };
- // };
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- const CXXBaseSpecifier *Base = I;
-
- // The __base_type member points to the RTTI for the base type.
- Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType()));
-
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-
- int64_t OffsetFlags = 0;
-
- // All but the lower 8 bits of __offset_flags are a signed offset.
- // For a non-virtual base, this is the offset in the object of the base
- // subobject. For a virtual base, this is the offset in the virtual table of
- // the virtual base offset for the virtual base referenced (negative).
- CharUnits Offset;
- if (Base->isVirtual())
- Offset =
- CGM.getVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
- else {
- const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
- Offset = Layout.getBaseClassOffset(BaseDecl);
- };
-
- OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
-
- // The low-order byte of __offset_flags contains flags, as given by the
- // masks from the enumeration __offset_flags_masks.
- if (Base->isVirtual())
- OffsetFlags |= BCTI_Virtual;
- if (Base->getAccessSpecifier() == AS_public)
- OffsetFlags |= BCTI_Public;
-
- Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
- }
-}
-
-/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
-/// used for pointer types.
-void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // __flags is a flag word describing the cv-qualification and other
- // attributes of the type pointed to
- unsigned Flags = ComputeQualifierFlags(Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
-
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p7:
- // __pointee is a pointer to the std::type_info derivation for the
- // unqualified type being pointed to.
- llvm::Constant *PointeeTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
- Fields.push_back(PointeeTypeInfo);
-}
-
-/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
-/// struct, used for member pointer types.
-void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
- QualType PointeeTy = Ty->getPointeeType();
-
- Qualifiers Quals;
- QualType UnqualifiedPointeeTy =
- CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
-
- // Itanium C++ ABI 2.9.5p7:
- // __flags is a flag word describing the cv-qualification and other
- // attributes of the type pointed to.
- unsigned Flags = ComputeQualifierFlags(Quals);
-
- const RecordType *ClassType = cast<RecordType>(Ty->getClass());
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
- Flags |= PTI_Incomplete;
-
- if (IsIncompleteClassType(ClassType))
- Flags |= PTI_ContainingClassIncomplete;
-
- llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
- Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
-
- // Itanium C++ ABI 2.9.5p7:
- // __pointee is a pointer to the std::type_info derivation for the
- // unqualified type being pointed to.
- llvm::Constant *PointeeTypeInfo =
- RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
- Fields.push_back(PointeeTypeInfo);
-
- // Itanium C++ ABI 2.9.5p9:
- // __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(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
-}
-
-llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
- bool ForEH) {
- // Return a bogus pointer if RTTI is disabled, unless it's for EH.
- // FIXME: should we even be calling this method if RTTI is disabled
- // and it's not for EH?
- if (!ForEH && !getLangOpts().RTTI)
- return llvm::Constant::getNullValue(Int8PtrTy);
-
- if (ForEH && Ty->isObjCObjectPointerType() &&
- LangOpts.ObjCRuntime.isGNUFamily())
- return ObjCRuntime->GetEHType(Ty);
-
- return RTTIBuilder(*this).BuildTypeInfo(Ty);
-}
-
-void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
- QualType PointerType = Context.getPointerType(Type);
- QualType PointerTypeConst = Context.getPointerType(Type.withConst());
- RTTIBuilder(*this).BuildTypeInfo(Type, true);
- RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
- RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
-}
-
-void CodeGenModule::EmitFundamentalRTTIDescriptors() {
- QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,
- Context.BoolTy, Context.WCharTy,
- Context.CharTy, Context.UnsignedCharTy,
- Context.SignedCharTy, Context.ShortTy,
- Context.UnsignedShortTy, Context.IntTy,
- Context.UnsignedIntTy, Context.LongTy,
- Context.UnsignedLongTy, Context.LongLongTy,
- Context.UnsignedLongLongTy, Context.FloatTy,
- Context.DoubleTy, Context.LongDoubleTy,
- Context.Char16Ty, Context.Char32Ty };
- for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)
- EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
-}
+//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of RTTI descriptors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+namespace {
+class RTTIBuilder {
+ CodeGenModule &CGM; // Per-module state.
+ llvm::LLVMContext &VMContext;
+
+ /// Fields - The fields of the RTTI descriptor currently being built.
+ SmallVector<llvm::Constant *, 16> Fields;
+
+ /// GetAddrOfTypeName - Returns the mangled type name of the given type.
+ llvm::GlobalVariable *
+ GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage);
+
+ /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI
+ /// descriptor of the given type.
+ llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty);
+
+ /// BuildVTablePointer - Build the vtable pointer for the given type.
+ void BuildVTablePointer(const Type *Ty);
+
+ /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+ /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b.
+ void BuildSIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+ /// classes with bases that do not satisfy the abi::__si_class_type_info
+ /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+ void BuildVMIClassTypeInfo(const CXXRecordDecl *RD);
+
+ /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used
+ /// for pointer types.
+ void BuildPointerTypeInfo(QualType PointeeTy);
+
+ /// BuildObjCObjectTypeInfo - Build the appropriate kind of
+ /// type_info for an object type.
+ void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty);
+
+ /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+ /// struct, used for member pointer types.
+ void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
+
+public:
+ RTTIBuilder(CodeGenModule &CGM) : CGM(CGM),
+ VMContext(CGM.getModule().getContext()) { }
+
+ // Pointer type info flags.
+ enum {
+ /// PTI_Const - Type has const qualifier.
+ PTI_Const = 0x1,
+
+ /// PTI_Volatile - Type has volatile qualifier.
+ PTI_Volatile = 0x2,
+
+ /// PTI_Restrict - Type has restrict qualifier.
+ PTI_Restrict = 0x4,
+
+ /// PTI_Incomplete - Type is incomplete.
+ PTI_Incomplete = 0x8,
+
+ /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+ /// (in pointer to member).
+ PTI_ContainingClassIncomplete = 0x10
+ };
+
+ // VMI type info flags.
+ enum {
+ /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
+ VMI_NonDiamondRepeat = 0x1,
+
+ /// VMI_DiamondShaped - Class is diamond shaped.
+ VMI_DiamondShaped = 0x2
+ };
+
+ // Base class type info flags.
+ enum {
+ /// BCTI_Virtual - Base class is virtual.
+ BCTI_Virtual = 0x1,
+
+ /// BCTI_Public - Base class is public.
+ BCTI_Public = 0x2
+ };
+
+ /// BuildTypeInfo - Build the RTTI type info struct for the given type.
+ ///
+ /// \param Force - true to force the creation of this RTTI value
+ llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false);
+};
+}
+
+llvm::GlobalVariable *
+RTTIBuilder::GetAddrOfTypeName(QualType Ty,
+ llvm::GlobalVariable::LinkageTypes Linkage) {
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ // We know that the mangled name of the type starts at index 4 of the
+ // mangled name of the typename, so we can just index into it in order to
+ // get the mangled name of the type.
+ llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
+ Name.substr(4));
+
+ llvm::GlobalVariable *GV =
+ CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage);
+
+ GV->setInitializer(Init);
+
+ return GV;
+}
+
+llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
+ // Mangle the RTTI name.
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ // Look for an existing global.
+ llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name);
+
+ if (!GV) {
+ // Create a new global variable.
+ GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
+ /*Constant=*/true,
+ llvm::GlobalValue::ExternalLinkage, 0, Name);
+ }
+
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+}
+
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
+ // Itanium C++ ABI 2.9.2:
+ // Basic type information (e.g. for "int", "bool", etc.) will be kept in
+ // the run-time support library. Specifically, the run-time support
+ // library should contain type_info objects for the types X, X* and
+ // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
+ // unsigned char, signed char, short, unsigned short, int, unsigned int,
+ // long, unsigned long, long long, unsigned long long, float, double,
+ // long double, char16_t, char32_t, and the IEEE 754r decimal and
+ // half-precision floating point types.
+ switch (Ty->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Bool:
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ return true;
+
+ case BuiltinType::Dependent:
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) \
+ case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ llvm_unreachable("asking for RRTI for a placeholder type!");
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ llvm_unreachable("FIXME: Objective-C types are unsupported!");
+ }
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
+
+static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
+ if (!BuiltinTy)
+ return false;
+
+ // Check the qualifiers.
+ Qualifiers Quals = PointeeTy.getQualifiers();
+ Quals.removeConst();
+
+ if (!Quals.empty())
+ return false;
+
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+}
+
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
+ // Type info for builtin types is defined in the standard library.
+ if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+
+ // Type info for some pointer types to builtin types is defined in the
+ // standard library.
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return TypeInfoIsInStandardLibrary(PointerTy);
+
+ return false;
+}
+
+/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
+/// the given type exists somewhere else, and that we should not emit the type
+/// information in this translation unit. Assumes that it is not a
+/// standard-library type.
+static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
+ ASTContext &Context = CGM.getContext();
+
+ // If RTTI is disabled, don't consider key functions.
+ if (!Context.getLangOpts().RTTI) return false;
+
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ if (!RD->hasDefinition())
+ return false;
+
+ if (!RD->isDynamicClass())
+ return false;
+
+ return !CGM.getVTables().ShouldEmitVTableInThisTU(RD);
+ }
+
+ return false;
+}
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+static bool IsIncompleteClassType(const RecordType *RecordTy) {
+ return !RecordTy->getDecl()->isCompleteDefinition();
+}
+
+/// ContainsIncompleteClassType - Returns whether the given type contains an
+/// incomplete class type. This is true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whoise pointee type contains an
+/// incomplete class type.
+/// is an indirect or direct pointer to an incomplete class type.
+static bool ContainsIncompleteClassType(QualType Ty) {
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ if (IsIncompleteClassType(RecordTy))
+ return true;
+ }
+
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return ContainsIncompleteClassType(PointerTy->getPointeeType());
+
+ if (const MemberPointerType *MemberPointerTy =
+ dyn_cast<MemberPointerType>(Ty)) {
+ // Check if the class type is incomplete.
+ const RecordType *ClassType = cast<RecordType>(MemberPointerTy->getClass());
+ if (IsIncompleteClassType(ClassType))
+ return true;
+
+ return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
+ }
+
+ return false;
+}
+
+/// getTypeInfoLinkage - Return the linkage that the type info and type info
+/// name constants should have for the given type.
+static llvm::GlobalVariable::LinkageTypes
+getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
+ // Itanium C++ ABI 2.9.5p7:
+ // In addition, it and all of the intermediate abi::__pointer_type_info
+ // structs in the chain down to the abi::__class_type_info for the
+ // incomplete class type must be prevented from resolving to the
+ // corresponding type_info structs for the complete class type, possibly
+ // by making them local static objects. Finally, a dummy class RTTI is
+ // generated for the incomplete type that will not resolve to the final
+ // complete class RTTI (because the latter need not exist), possibly by
+ // making it a local static object.
+ if (ContainsIncompleteClassType(Ty))
+ return llvm::GlobalValue::InternalLinkage;
+
+ switch (Ty->getLinkage()) {
+ case NoLinkage:
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return llvm::GlobalValue::InternalLinkage;
+
+ case ExternalLinkage:
+ if (!CGM.getLangOpts().RTTI) {
+ // RTTI is not enabled, which means that this type info struct is going
+ // to be used for exception handling. Give it linkonce_odr linkage.
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ if (RD->hasAttr<WeakAttr>())
+ return llvm::GlobalValue::WeakODRLinkage;
+ if (RD->isDynamicClass())
+ return CGM.getVTableLinkage(RD);
+ }
+
+ return llvm::GlobalValue::LinkOnceODRLinkage;
+ }
+
+ llvm_unreachable("Invalid linkage!");
+}
+
+// CanUseSingleInheritance - Return whether the given record decl has a "single,
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
+ // Check the number of bases.
+ if (RD->getNumBases() != 1)
+ return false;
+
+ // Get the base.
+ CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+
+ // Check that the base is not virtual.
+ if (Base->isVirtual())
+ return false;
+
+ // Check that the base is public.
+ if (Base->getAccessSpecifier() != AS_public)
+ return false;
+
+ // Check that the class is dynamic iff the base is.
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+ if (!BaseDecl->isEmpty() &&
+ BaseDecl->isDynamicClass() != RD->isDynamicClass())
+ return false;
+
+ return true;
+}
+
+void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
+ // abi::__class_type_info.
+ static const char * const ClassTypeInfo =
+ "_ZTVN10__cxxabiv117__class_type_infoE";
+ // abi::__si_class_type_info.
+ static const char * const SIClassTypeInfo =
+ "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ // abi::__vmi_class_type_info.
+ static const char * const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+
+ const char *VTableName = 0;
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("References shouldn't get here");
+
+ case Type::Builtin:
+ // GCC treats vector and complex types as fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ case Type::Atomic:
+ // FIXME: GCC treats block pointers as fundamental types?!
+ case Type::BlockPointer:
+ // abi::__fundamental_type_info.
+ VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
+ break;
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // abi::__array_type_info.
+ VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // abi::__function_type_info.
+ VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
+ break;
+
+ case Type::Enum:
+ // abi::__enum_type_info.
+ VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ VTableName = ClassTypeInfo;
+ } else if (CanUseSingleInheritance(RD)) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = VMIClassTypeInfo;
+ }
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ // Ignore protocol qualifiers.
+ Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ VTableName = ClassTypeInfo;
+ break;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ // Fall through.
+
+ case Type::ObjCInterface:
+ if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
+ VTableName = SIClassTypeInfo;
+ } else {
+ VTableName = ClassTypeInfo;
+ }
+ break;
+
+ case Type::ObjCObjectPointer:
+ case Type::Pointer:
+ // abi::__pointer_type_info.
+ VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
+ break;
+
+ case Type::MemberPointer:
+ // abi::__pointer_to_member_type_info.
+ VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
+ break;
+ }
+
+ llvm::Constant *VTable =
+ CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy);
+
+ llvm::Type *PtrDiffTy =
+ CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
+
+ // The vtable address point is 2.
+ llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2);
+ VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two);
+ VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy);
+
+ Fields.push_back(VTable);
+}
+
+// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures
+// from available_externally to the correct linkage if necessary. An example of
+// this is:
+//
+// struct A {
+// virtual void f();
+// };
+//
+// const std::type_info &g() {
+// return typeid(A);
+// }
+//
+// void A::f() { }
+//
+// When we're generating the typeid(A) expression, we do not yet know that
+// A's key function is defined in this translation unit, so we will give the
+// typeinfo and typename structures available_externally linkage. When A::f
+// forces the vtable to be generated, we need to change the linkage of the
+// typeinfo and typename structs, otherwise we'll end up with undefined
+// externals when linking.
+static void
+maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV,
+ QualType Ty) {
+ // We're only interested in globals with available_externally linkage.
+ if (!GV->hasAvailableExternallyLinkage())
+ return;
+
+ // Get the real linkage for the type.
+ llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // If variable is supposed to have available_externally linkage, we don't
+ // need to do anything.
+ if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage)
+ return;
+
+ // Update the typeinfo linkage.
+ GV->setLinkage(Linkage);
+
+ // Get the typename global.
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name);
+
+ assert(TypeNameGV->hasAvailableExternallyLinkage() &&
+ "Type name has different linkage from type info!");
+
+ // And update its linkage.
+ TypeNameGV->setLinkage(Linkage);
+}
+
+llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+ // We want to operate on the canonical type.
+ Ty = CGM.getContext().getCanonicalType(Ty);
+
+ // Check if we've already emitted an RTTI descriptor for this type.
+ SmallString<256> OutName;
+ llvm::raw_svector_ostream Out(OutName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
+ Out.flush();
+ StringRef Name = OutName.str();
+
+ llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name);
+ if (OldGV && !OldGV->isDeclaration()) {
+ maybeUpdateRTTILinkage(CGM, OldGV, Ty);
+
+ return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy);
+ }
+
+ // Check if there is already an external RTTI descriptor for this type.
+ bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty);
+ if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty)))
+ return GetAddrOfExternalRTTIDescriptor(Ty);
+
+ // Emit the standard library with external linkage.
+ llvm::GlobalVariable::LinkageTypes Linkage;
+ if (IsStdLib)
+ Linkage = llvm::GlobalValue::ExternalLinkage;
+ else
+ Linkage = getTypeInfoLinkage(CGM, Ty);
+
+ // Add the vtable pointer.
+ BuildVTablePointer(cast<Type>(Ty));
+
+ // And the name.
+ llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
+
+ Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy));
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
+
+ // GCC treats vector types as fundamental types.
+ case Type::Builtin:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Complex:
+ case Type::BlockPointer:
+ // Itanium C++ ABI 2.9.5p4:
+ // abi::__fundamental_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("References shouldn't get here");
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__array_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__function_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Enum:
+ // Itanium C++ ABI 2.9.5p5:
+ // abi::__enum_type_info adds no data members to std::type_info.
+ break;
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ // We don't need to emit any fields.
+ break;
+ }
+
+ if (CanUseSingleInheritance(RD))
+ BuildSIClassTypeInfo(RD);
+ else
+ BuildVMIClassTypeInfo(RD);
+
+ break;
+ }
+
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ BuildObjCObjectTypeInfo(cast<ObjCObjectType>(Ty));
+ break;
+
+ case Type::ObjCObjectPointer:
+ BuildPointerTypeInfo(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::Pointer:
+ BuildPointerTypeInfo(cast<PointerType>(Ty)->getPointeeType());
+ break;
+
+ case Type::MemberPointer:
+ BuildPointerToMemberTypeInfo(cast<MemberPointerType>(Ty));
+ break;
+
+ case Type::Atomic:
+ // No fields, at least for the moment.
+ break;
+ }
+
+ llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
+ /*Constant=*/true, Linkage, Init, Name);
+
+ // If there's already an old global variable, replace it with the new one.
+ if (OldGV) {
+ GV->takeName(OldGV);
+ llvm::Constant *NewPtr =
+ llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
+ OldGV->replaceAllUsesWith(NewPtr);
+ OldGV->eraseFromParent();
+ }
+
+ // GCC only relies on the uniqueness of the type names, not the
+ // type_infos themselves, so we can emit these as hidden symbols.
+ // But don't do this if we're worried about strict visibility
+ // compatibility.
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty)) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI);
+ CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName);
+ } else {
+ Visibility TypeInfoVisibility = DefaultVisibility;
+ if (CGM.getCodeGenOpts().HiddenWeakVTables &&
+ Linkage == llvm::GlobalValue::LinkOnceODRLinkage)
+ TypeInfoVisibility = HiddenVisibility;
+
+ // The type name should have the same visibility as the type itself.
+ Visibility ExplicitVisibility = Ty->getVisibility();
+ TypeName->setVisibility(CodeGenModule::
+ GetLLVMVisibility(ExplicitVisibility));
+
+ TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility());
+ GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility));
+ }
+
+ GV->setUnnamedAddr(true);
+
+ return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
+}
+
+/// ComputeQualifierFlags - Compute the pointer type info flags from the
+/// given qualifier.
+static unsigned ComputeQualifierFlags(Qualifiers Quals) {
+ unsigned Flags = 0;
+
+ if (Quals.hasConst())
+ Flags |= RTTIBuilder::PTI_Const;
+ if (Quals.hasVolatile())
+ Flags |= RTTIBuilder::PTI_Volatile;
+ if (Quals.hasRestrict())
+ Flags |= RTTIBuilder::PTI_Restrict;
+
+ return Flags;
+}
+
+/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
+/// for the given Objective-C object type.
+void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+ // Drop qualifiers.
+ const Type *T = OT->getBaseType().getTypePtr();
+ assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
+
+ // The builtin types are abi::__class_type_infos and don't require
+ // extra fields.
+ if (isa<BuiltinType>(T)) return;
+
+ ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
+ ObjCInterfaceDecl *Super = Class->getSuperClass();
+
+ // Root classes are also __class_type_info.
+ if (!Super) return;
+
+ QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
+
+ // Everything else is single inheritance.
+ llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
+ Fields.push_back(BaseTypeInfo);
+}
+
+/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
+/// inheritance, according to the Itanium C++ ABI, 2.95p6b.
+void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+ // Itanium C++ ABI 2.9.5p6b:
+ // It adds to abi::__class_type_info a single member pointing to the
+ // type_info structure for the base type,
+ llvm::Constant *BaseTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
+ Fields.push_back(BaseTypeInfo);
+}
+
+namespace {
+ /// SeenBases - Contains virtual and non-virtual bases seen when traversing
+ /// a class hierarchy.
+ struct SeenBases {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+ };
+}
+
+/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
+/// abi::__vmi_class_type_info.
+///
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases) {
+
+ unsigned Flags = 0;
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ if (Base->isVirtual()) {
+ // Mark the virtual base as seen.
+ if (!Bases.VirtualBases.insert(BaseDecl)) {
+ // If this virtual base has been seen before, then the class is diamond
+ // shaped.
+ Flags |= RTTIBuilder::VMI_DiamondShaped;
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl))
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ }
+ } else {
+ // Mark the non-virtual base as seen.
+ if (!Bases.NonVirtualBases.insert(BaseDecl)) {
+ // If this non-virtual base has been seen before, then the class has non-
+ // diamond shaped repeated inheritance.
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ } else {
+ if (Bases.VirtualBases.count(BaseDecl))
+ Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+ }
+ }
+
+ // Walk all bases.
+ for (CXXRecordDecl::base_class_const_iterator I = BaseDecl->bases_begin(),
+ E = BaseDecl->bases_end(); I != E; ++I)
+ Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
+
+ return Flags;
+}
+
+static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
+ unsigned Flags = 0;
+ SeenBases Bases;
+
+ // Walk all bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I)
+ Flags |= ComputeVMIClassTypeInfoFlags(I, Bases);
+
+ return Flags;
+}
+
+/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
+/// classes with bases that do not satisfy the abi::__si_class_type_info
+/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
+void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __flags is a word with flags describing details about the class
+ // structure, which may be referenced by using the __flags_masks
+ // enumeration. These flags refer to both direct and indirect bases.
+ unsigned Flags = ComputeVMIClassTypeInfoFlags(RD);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_count is a word with the number of direct proper base class
+ // descriptions that follow.
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases()));
+
+ if (!RD->getNumBases())
+ return;
+
+ llvm::Type *LongLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().LongTy);
+
+ // Now add the base class descriptions.
+
+ // Itanium C++ ABI 2.9.5p6c:
+ // __base_info[] is an array of base class descriptions -- one for every
+ // direct proper base. Each description is of the type:
+ //
+ // struct abi::__base_class_type_info {
+ // public:
+ // const __class_type_info *__base_type;
+ // long __offset_flags;
+ //
+ // enum __offset_flags_masks {
+ // __virtual_mask = 0x1,
+ // __public_mask = 0x2,
+ // __offset_shift = 8
+ // };
+ // };
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXBaseSpecifier *Base = I;
+
+ // The __base_type member points to the RTTI for the base type.
+ Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base->getType()));
+
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+
+ int64_t OffsetFlags = 0;
+
+ // All but the lower 8 bits of __offset_flags are a signed offset.
+ // For a non-virtual base, this is the offset in the object of the base
+ // subobject. For a virtual base, this is the offset in the virtual table of
+ // the virtual base offset for the virtual base referenced (negative).
+ CharUnits Offset;
+ if (Base->isVirtual())
+ Offset =
+ CGM.getVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
+ else {
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ Offset = Layout.getBaseClassOffset(BaseDecl);
+ };
+
+ OffsetFlags = uint64_t(Offset.getQuantity()) << 8;
+
+ // The low-order byte of __offset_flags contains flags, as given by the
+ // masks from the enumeration __offset_flags_masks.
+ if (Base->isVirtual())
+ OffsetFlags |= BCTI_Virtual;
+ if (Base->getAccessSpecifier() == AS_public)
+ OffsetFlags |= BCTI_Public;
+
+ Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags));
+ }
+}
+
+/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
+/// used for pointer types.
+void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+}
+
+/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
+/// struct, used for member pointer types.
+void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+ QualType PointeeTy = Ty->getPointeeType();
+
+ Qualifiers Quals;
+ QualType UnqualifiedPointeeTy =
+ CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __flags is a flag word describing the cv-qualification and other
+ // attributes of the type pointed to.
+ unsigned Flags = ComputeQualifierFlags(Quals);
+
+ const RecordType *ClassType = cast<RecordType>(Ty->getClass());
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
+ Flags |= PTI_Incomplete;
+
+ if (IsIncompleteClassType(ClassType))
+ Flags |= PTI_ContainingClassIncomplete;
+
+ llvm::Type *UnsignedIntLTy =
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
+
+ // Itanium C++ ABI 2.9.5p7:
+ // __pointee is a pointer to the std::type_info derivation for the
+ // unqualified type being pointed to.
+ llvm::Constant *PointeeTypeInfo =
+ RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+ Fields.push_back(PointeeTypeInfo);
+
+ // Itanium C++ ABI 2.9.5p9:
+ // __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(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
+}
+
+llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
+ bool ForEH) {
+ // Return a bogus pointer if RTTI is disabled, unless it's for EH.
+ // FIXME: should we even be calling this method if RTTI is disabled
+ // and it's not for EH?
+ if (!ForEH && !getLangOpts().RTTI)
+ return llvm::Constant::getNullValue(Int8PtrTy);
+
+ if (ForEH && Ty->isObjCObjectPointerType() &&
+ LangOpts.ObjCRuntime.isGNUFamily())
+ return ObjCRuntime->GetEHType(Ty);
+
+ return RTTIBuilder(*this).BuildTypeInfo(Ty);
+}
+
+void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
+ QualType PointerType = Context.getPointerType(Type);
+ QualType PointerTypeConst = Context.getPointerType(Type.withConst());
+ RTTIBuilder(*this).BuildTypeInfo(Type, true);
+ RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
+ RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+}
+
+void CodeGenModule::EmitFundamentalRTTIDescriptors() {
+ QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy,
+ Context.BoolTy, Context.WCharTy,
+ Context.CharTy, Context.UnsignedCharTy,
+ Context.SignedCharTy, Context.ShortTy,
+ Context.UnsignedShortTy, Context.IntTy,
+ Context.UnsignedIntTy, Context.LongTy,
+ Context.UnsignedLongTy, Context.LongLongTy,
+ Context.UnsignedLongLongTy, Context.FloatTy,
+ Context.DoubleTy, Context.LongDoubleTy,
+ Context.Char16Ty, Context.Char32Ty };
+ for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i)
+ EmitFundamentalRTTIDescriptor(FundamentalTypes[i]);
+}
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Tue Dec 18 08:30:41 2012
@@ -14,7 +14,6 @@
#include "CodeGenTypes.h"
#include "CGCXXABI.h"
#include "CGCall.h"
-#include "CGOpenCLRuntime.h"
#include "CGRecordLayout.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -367,15 +366,6 @@
case BuiltinType::Int128:
ResultType = llvm::IntegerType::get(getLLVMContext(), 128);
break;
-
- case BuiltinType::OCLImage1d:
- case BuiltinType::OCLImage1dArray:
- case BuiltinType::OCLImage1dBuffer:
- case BuiltinType::OCLImage2d:
- case BuiltinType::OCLImage2dArray:
- case BuiltinType::OCLImage3d:
- ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
- break;
case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Dec 18 08:30:41 2012
@@ -2753,30 +2753,6 @@
case tok::kw___pixel:
isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
break;
- case tok::kw_image1d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image1d_buffer_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image1d_buffer_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image2d_array_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image2d_array_t, Loc,
- PrevSpec, DiagID);
- break;
- case tok::kw_image3d_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_image3d_t, Loc,
- PrevSpec, DiagID);
- break;
case tok::kw___unknown_anytype:
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
PrevSpec, DiagID);
@@ -3620,14 +3596,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -3700,14 +3668,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
@@ -3852,14 +3812,6 @@
case tok::kw__Decimal128:
case tok::kw___vector:
- // OpenCL specific types:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t:
-
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=170431&r1=170430&r2=170431&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Dec 18 08:30:41 2012
@@ -1078,13 +1078,7 @@
case tok::kw_void:
case tok::kw_typename:
case tok::kw_typeof:
- case tok::kw___vector:
- case tok::kw_image1d_t:
- case tok::kw_image1d_array_t:
- case tok::kw_image1d_buffer_t:
- case tok::kw_image2d_t:
- case tok::kw_image2d_array_t:
- case tok::kw_image3d_t: {
+ case tok::kw___vector: {
if (!getLangOpts().CPlusPlus) {
Diag(Tok, diag::err_expected_expression);
return ExprError();
More information about the cfe-commits
mailing list